Scikitでの特徴選択,Xboostでの回帰予測,モデル最適化の実戦


一昨日偶然あるサイトでデータ分析の試合(sofasofa)を見て、自分は機械について勉強したが、試合で実践したことがないので、好奇心を持って今回の試合に参加した.
試合問題:サッカー選手の身代見積り
試合の概要
本試合は個人練習試合で、主にデータ新人に対して自己練習、自己向上を行い、みんなと切磋琢磨します.
練習試合時間:2018-03-05から2020-03-05
タスク・タイプ:回帰
背景紹介:サッカー選手一人一人が移籍市場でそれぞれの価格コードを持っている.今回のデータ練習の目的は、選手の各情報と能力値に基づいて、その選手の市場価値を予測することである.
以上の説明から,回帰予測クラスの問題であると容易に判断できる.もちろん、予測を行うには、まずデータのフォーマットと内容を見てみましょう(パラメータが多すぎるので、一つ一つ挙げません.直接ネットで見てもいいです.以下、簡単に図を貼ります):
データのフォーマットとサイズを簡単に理解した後、実践経験がないので、私は自分の感覚で、単純にいくつかのフィールドが最も重要かもしれないと思っています.
フィールド
意味
club
この選手が所属するクラブ.この情報は既に符号化されている.
league
この選手が所属するリーグ戦.エンコードされています.
potential
選手の底力.数値変数.
international_reputation
国際的知名度.数値変数.
偶然にもこれらのフィールドに値が欠けていないので、XGBoostモデルを直接利用して予測できると思います.具体的なXGBoostの使い方は、XGBoostおよび公式ドキュメントXGBoost Parametersを参照してください.そういえば、codingの仕事を始めました.次は私の第1版のコードを貼ります.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : soccer_value.py
# @Author: Huangqinjian
# @Date  : 2018/3/22
# @Desc  :

import pandas as pd
import matplotlib.pyplot as plt
import xgboost as xgb
import numpy as np
from xgboost import plot_importance
from sklearn.preprocessing import Imputer


def loadDataset(filePath):
    df = pd.read_csv(filepath_or_buffer=filePath)
    return df


def featureSet(data):
    data_num = len(data)
    XList = []
    for row in range(0, data_num):
        tmp_list = []
        tmp_list.append(data.iloc[row]['club'])
        tmp_list.append(data.iloc[row]['league'])
        tmp_list.append(data.iloc[row]['potential'])
        tmp_list.append(data.iloc[row]['international_reputation'])
        XList.append(tmp_list)
    yList = data.y.values
    return XList, yList


def loadTestData(filePath):
    data = pd.read_csv(filepath_or_buffer=filePath)
    data_num = len(data)
    XList = []
    for row in range(0, data_num):
        tmp_list = []
        tmp_list.append(data.iloc[row]['club'])
        tmp_list.append(data.iloc[row]['league'])
        tmp_list.append(data.iloc[row]['potential'])
        tmp_list.append(data.iloc[row]['international_reputation'])
        XList.append(tmp_list)
    return XList


def trainandTest(X_train, y_train, X_test):
    # XGBoost    
    model = xgb.XGBRegressor(max_depth=5, learning_rate=0.1, n_estimators=160, silent=False, objective='reg:gamma')
    model.fit(X_train, y_train)

    #         
    ans = model.predict(X_test)

    ans_len = len(ans)
    id_list = np.arange(10441, 17441)
    data_arr = []
    for row in range(0, ans_len):
        data_arr.append([int(id_list[row]), ans[row]])
    np_data = np.array(data_arr)

    #     
    pd_data = pd.DataFrame(np_data, columns=['id', 'y'])
    # print(pd_data)
    pd_data.to_csv('submit.csv', index=None)

    #       
    # plot_importance(model)
    # plt.show()

if __name__ == '__main__':
    trainFilePath = 'dataset/soccer/train.csv'
    testFilePath = 'dataset/soccer/test.csv'
    data = loadDataset(trainFilePath)
    X_train, y_train = featureSet(data)
    X_test = loadTestData(testFilePath)
    trainandTest(X_train, y_train, X_test)

そして結果ファイルをcsvはウェブサイトに提出して、結果を見て、MAEは106.6977で、24/28位で、とても理想的ではありません.しかし、これも予想されています.私はほとんど特徴処理をしていないからです.
もちろん満足していませんが、どうやって精度を高めることができるのかずっと考えていました.あとでscikitというライブラリを利用できると思いました!scikitには特徴選択モジュールsklearnが含まれている.feature_selectionですが、このモジュールの下には以下の方法があります.
  • Removing features with low variance(低分散の特徴を除く)
  • Univariate feature selection(単一変数フィーチャー選択)
  • Recursive feature elimination(再帰機能消去)
  • Feature selection using SelectFromModel(SelectFromModelを使用したフィーチャー選択)
  • まず,単一変数特徴選択法を用いて予測結果に最も関連するいくつかの特徴を選択することを考えた.公式ドキュメントに基づいて、変数間の依存度を検証するスコア関数は次のとおりです.
  • 回帰問題について:f_regression, mutual_info_regression
  • 分類問題:chi 2,f_classif, mutual_info_classif

  • この試合は回帰予測の問題だったので、f_を選びました.regressionという得点関数(最初は気づかなかったのですが、間違って分類問題の得点関数chi 2を使ってしまい、プログラムがずっと間違っていました!心が疲れました~)
    f_regressionのパラメータ: sklearn.feature_selection.f_regression(X, y, center=True) X:多次元配列、サイズ(n_samples,n_features)、すなわち行数がトレーニングサンプルのサイズ、列数が特徴の個数y:1次元配列、長さがトレーニングサンプルのサイズreturn:戻り値が特徴のF値およびp値
    しかし、この操作を行う前に、空の値の処理という重大なタスクがあります.幸いなことにscikitにもこの問題を処理できる専門モジュールがあります:Imputation of missing values
    sklearn.preprocessing.Imputerのパラメータ:sklearn.preprocessing.Imputer(missing_values=’NaN’, strategy=’mean’, axis=0, verbose=0, copy=True)
    ここでstrategyは、空の値に対する入力ポリシーを表します(デフォルトはmeanです.つまり、カラムの平均数を入力します).
  • strategy='median'は、その列の中位数を表す
  • を充填する.
  • strategy='most_frequent',代表取所在列的衆数进行填充
  • axisのデフォルト値は0です.
  • axis=0は、
  • を列ごとに充填することを表す.
  • axis=1は、行単位で充填する
  • を表す.
    その他の具体的なパラメータは、sklearn.preprocessing.Imputer
    以上、データについていくつかの処理を行いました.
    from sklearn.feature_selection import f_regression
    from sklearn.preprocessing import Imputer
    
    imputer = Imputer(missing_values='NaN', strategy='mean', axis=0)
    imputer.fit(data.loc[:, 'rw':'lb'])
    x_new = imputer.transform(data.loc[:, 'rw':'lb'])
    data_num = len(x_new)
    XList = []
    yList = []
    for row in range(0, data_num):
        tmp_list = []
        tmp_list.append(x_new[row][0])
        tmp_list.append(x_new[row][1])
        tmp_list.append(x_new[row][2])
        tmp_list.append(x_new[row][3])
        tmp_list.append(x_new[row][4])
        tmp_list.append(x_new[row][5])
        tmp_list.append(x_new[row][6])
        tmp_list.append(x_new[row][7])
        tmp_list.append(x_new[row][8])
        tmp_list.append(x_new[row][9])
        XList.append(tmp_list)
        yList.append(data.iloc[row]['y'])
    
    F = f_regression(XList, yList)
    print(len(F))
    print(F)
    

    テスト結果:
    2
    (array([2531.07587725, 1166.63303449, 2891.97789543, 2531.07587725,
           2786.75491791, 2891.62686404, 3682.42649607, 1394.46743196,
            531.08672792, 1166.63303449]), array([0.00000000e+000, 1.74675421e-242, 0.00000000e+000, 0.00000000e+000,
           0.00000000e+000, 0.00000000e+000, 0.00000000e+000, 1.37584507e-286,
           1.15614152e-114, 1.74675421e-242]))

    以上の結果から,rw,st,lw,cf,cam,cm(F値が比較的大きい)のいくつかの特徴をモデルに加えた.以下は私が改善したコードです.
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @File  : soccer_value.py
    # @Author: Huangqinjian
    # @Date  : 2018/3/22
    # @Desc  :
    
    import pandas as pd
    import matplotlib.pyplot as plt
    import xgboost as xgb
    import numpy as np
    from xgboost import plot_importance
    from sklearn.preprocessing import Imputer
    
    
    def loadDataset(filePath):
        df = pd.read_csv(filepath_or_buffer=filePath)
        return df
    
    
    def featureSet(data):
        imputer = Imputer(missing_values='NaN', strategy='mean', axis=0)
        imputer.fit(data.loc[:, ['rw', 'st', 'lw', 'cf', 'cam', 'cm']])
        x_new = imputer.transform(data.loc[:, ['rw', 'st', 'lw', 'cf', 'cam', 'cm']])
        data_num = len(data)
        XList = []
        for row in range(0, data_num):
            tmp_list = []
            tmp_list.append(data.iloc[row]['club'])
            tmp_list.append(data.iloc[row]['league'])
            tmp_list.append(data.iloc[row]['potential'])
            tmp_list.append(data.iloc[row]['international_reputation'])
            tmp_list.append(data.iloc[row]['pac'])
            tmp_list.append(data.iloc[row]['sho'])
            tmp_list.append(data.iloc[row]['pas'])
            tmp_list.append(data.iloc[row]['dri'])
            tmp_list.append(data.iloc[row]['def'])
            tmp_list.append(data.iloc[row]['phy'])
            tmp_list.append(data.iloc[row]['skill_moves'])
            tmp_list.append(x_new[row][0])
            tmp_list.append(x_new[row][1])
            tmp_list.append(x_new[row][2])
            tmp_list.append(x_new[row][3])
            tmp_list.append(x_new[row][4])
            tmp_list.append(x_new[row][5])
            XList.append(tmp_list)
        yList = data.y.values
        return XList, yList
    
    
    def loadTestData(filePath):
        data = pd.read_csv(filepath_or_buffer=filePath)
        imputer = Imputer(missing_values='NaN', strategy='mean', axis=0)
        imputer.fit(data.loc[:, ['rw', 'st', 'lw', 'cf', 'cam', 'cm']])
        x_new = imputer.transform(data.loc[:, ['rw', 'st', 'lw', 'cf', 'cam', 'cm']])
        data_num = len(data)
        XList = []
        for row in range(0, data_num):
            tmp_list = []
            tmp_list.append(data.iloc[row]['club'])
            tmp_list.append(data.iloc[row]['league'])
            tmp_list.append(data.iloc[row]['potential'])
            tmp_list.append(data.iloc[row]['international_reputation'])
            tmp_list.append(data.iloc[row]['pac'])
            tmp_list.append(data.iloc[row]['sho'])
            tmp_list.append(data.iloc[row]['pas'])
            tmp_list.append(data.iloc[row]['dri'])
            tmp_list.append(data.iloc[row]['def'])
            tmp_list.append(data.iloc[row]['phy'])
            tmp_list.append(data.iloc[row]['skill_moves'])
            tmp_list.append(x_new[row][0])
            tmp_list.append(x_new[row][1])
            tmp_list.append(x_new[row][2])
            tmp_list.append(x_new[row][3])
            tmp_list.append(x_new[row][4])
            tmp_list.append(x_new[row][5])
            XList.append(tmp_list)
        return XList
    
    
    def trainandTest(X_train, y_train, X_test):
        # XGBoost    
        model = xgb.XGBRegressor(max_depth=5, learning_rate=0.1, n_estimators=160, silent=False, objective='reg:gamma')
        model.fit(X_train, y_train)
    
        #         
        ans = model.predict(X_test)
    
        ans_len = len(ans)
        id_list = np.arange(10441, 17441)
        data_arr = []
        for row in range(0, ans_len):
            data_arr.append([int(id_list[row]), ans[row]])
        np_data = np.array(data_arr)
    
        #     
        pd_data = pd.DataFrame(np_data, columns=['id', 'y'])
        # print(pd_data)
        pd_data.to_csv('submit.csv', index=None)
    
        #       
        # plot_importance(model)
        # plt.show()
    
    if __name__ == '__main__':
        trainFilePath = 'dataset/soccer/train.csv'
        testFilePath = 'dataset/soccer/test.csv'
        data = loadDataset(trainFilePath)
        X_train, y_train = featureSet(data)
        X_test = loadTestData(testFilePath)
        trainandTest(X_train, y_train, X_test)
    

    再度提出し、今回のMAEは42.1227で、16/28位だった.かなりアップしましたが、1位まではまだまだ差があり、頑張ります.
    次に、次のフィールドを処理します.
    この2つのフィールドはラベルであるため、モデルでは処理後(ラベルの標準化)に使用する必要があります.私たちが使う関数はsklearnです.preprocessing.LabelEncoder:
        le = preprocessing.LabelEncoder()
        le.fit(['Low', 'Medium', 'High'])
        att_label = le.transform(data.work_rate_att.values)
        # print(att_label)
        def_label = le.transform(data.work_rate_def.values)
        # print(def_label)

    もちろんpandasを使用して離散型特徴変数を直接処理することもできます.具体的な内容は、pandasがgetを使用することを参照してください.dummiesはone-hot符号化を行う.ちなみにscikitにも処理できる方法があります.参考:sklearn.preprocessing.OneHotEncoder.
    調整後のコード:
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @File  : soccer_value.py
    # @Author: Huangqinjian
    # @Date  : 2018/3/22
    # @Desc  :
    
    import pandas as pd
    import matplotlib.pyplot as plt
    import xgboost as xgb
    from sklearn import preprocessing
    import numpy as np
    from xgboost import plot_importance
    from sklearn.preprocessing import Imputer
    from sklearn.cross_validation import train_test_split
    
    
    def featureSet(data):
        imputer = Imputer(missing_values='NaN', strategy='mean', axis=0)
        imputer.fit(data.loc[:, ['rw', 'st', 'lw', 'cf', 'cam', 'cm']])
        x_new = imputer.transform(data.loc[:, ['rw', 'st', 'lw', 'cf', 'cam', 'cm']])
    
        le = preprocessing.LabelEncoder()
        le.fit(['Low', 'Medium', 'High'])
        att_label = le.transform(data.work_rate_att.values)
        # print(att_label)
        def_label = le.transform(data.work_rate_def.values)
        # print(def_label)
    
        data_num = len(data)
        XList = []
        for row in range(0, data_num):
            tmp_list = []
            tmp_list.append(data.iloc[row]['club'])
            tmp_list.append(data.iloc[row]['league'])
            tmp_list.append(data.iloc[row]['potential'])
            tmp_list.append(data.iloc[row]['international_reputation'])
            tmp_list.append(data.iloc[row]['pac'])
            tmp_list.append(data.iloc[row]['sho'])
            tmp_list.append(data.iloc[row]['pas'])
            tmp_list.append(data.iloc[row]['dri'])
            tmp_list.append(data.iloc[row]['def'])
            tmp_list.append(data.iloc[row]['phy'])
            tmp_list.append(data.iloc[row]['skill_moves'])
            tmp_list.append(x_new[row][0])
            tmp_list.append(x_new[row][1])
            tmp_list.append(x_new[row][2])
            tmp_list.append(x_new[row][3])
            tmp_list.append(x_new[row][4])
            tmp_list.append(x_new[row][5])
            tmp_list.append(att_label[row])
            tmp_list.append(def_label[row])
            XList.append(tmp_list)
        yList = data.y.values
        return XList, yList
    
    
    def loadTestData(filePath):
        data = pd.read_csv(filepath_or_buffer=filePath)
        imputer = Imputer(missing_values='NaN', strategy='mean', axis=0)
        imputer.fit(data.loc[:, ['rw', 'st', 'lw', 'cf', 'cam', 'cm']])
        x_new = imputer.transform(data.loc[:, ['rw', 'st', 'lw', 'cf', 'cam', 'cm']])
    
        le = preprocessing.LabelEncoder()
        le.fit(['Low', 'Medium', 'High'])
        att_label = le.transform(data.work_rate_att.values)
        # print(att_label)
        def_label = le.transform(data.work_rate_def.values)
        # print(def_label)
    
        data_num = len(data)
        XList = []
        for row in range(0, data_num):
            tmp_list = []
            tmp_list.append(data.iloc[row]['club'])
            tmp_list.append(data.iloc[row]['league'])
            tmp_list.append(data.iloc[row]['potential'])
            tmp_list.append(data.iloc[row]['international_reputation'])
            tmp_list.append(data.iloc[row]['pac'])
            tmp_list.append(data.iloc[row]['sho'])
            tmp_list.append(data.iloc[row]['pas'])
            tmp_list.append(data.iloc[row]['dri'])
            tmp_list.append(data.iloc[row]['def'])
            tmp_list.append(data.iloc[row]['phy'])
            tmp_list.append(data.iloc[row]['skill_moves'])
            tmp_list.append(x_new[row][0])
            tmp_list.append(x_new[row][1])
            tmp_list.append(x_new[row][2])
            tmp_list.append(x_new[row][3])
            tmp_list.append(x_new[row][4])
            tmp_list.append(x_new[row][5])
            tmp_list.append(att_label[row])
            tmp_list.append(def_label[row])
            XList.append(tmp_list)
        return XList
    
    
    def trainandTest(X_train, y_train, X_test):
        # XGBoost    
        model = xgb.XGBRegressor(max_depth=6, learning_rate=0.05, n_estimators=500, silent=False, objective='reg:gamma')
        model.fit(X_train, y_train)
    
        #         
        ans = model.predict(X_test)
    
        ans_len = len(ans)
        id_list = np.arange(10441, 17441)
        data_arr = []
        for row in range(0, ans_len):
            data_arr.append([int(id_list[row]), ans[row]])
        np_data = np.array(data_arr)
    
        #     
        pd_data = pd.DataFrame(np_data, columns=['id', 'y'])
        # print(pd_data)
        pd_data.to_csv('submit.csv', index=None)
    
        #       
        # plot_importance(model)
        # plt.show()
    
    if __name__ == '__main__':
        trainFilePath = 'dataset/soccer/train.csv'
        testFilePath = 'dataset/soccer/test.csv'
        data = pd.read_csv(trainFilePath)
        X_train, y_train = featureSet(data)
        X_test = loadTestData(testFilePath)
        trainandTest(X_train, y_train, X_test)

    今回は40.8686にしか上げられませんでした.しばらくは上達の仕方が思いつかないので、大神様によろしくお願いします!
    詳細は私の個人公衆番号に注目してください.