python大規模データ処理テクニックの2:機械学習でよく使われる操作


1、データの前処理
ランダム化操作
機械学習でよく用いられるランダム化操作ではrandomパケットを用いて重複しない乱数生成を行い,生成した乱数をデータセットの下標として対応するデータセットを切り取ることができる.次の単純で効率的なコードは、基本的なすべてのランダム化前処理操作を実現するのに役立ちます.
import random
samp_ids = [i for i in sorted(random.sample(range(nItem), nSample)) ] 
    # nSample        

データのランダムサンプリング:
    import random

    nItem = len(df)
    nSample = 1000
    samp_ids = [i for i in sorted(random.sample(range(nItem), nSample)) ]
         # nSample        
    samp_idList = df.id.isin(samp_ids)
    df_sample = df[samp_idList]

データセットはトレーニングセットとテストセットに切り分けられます.
    import random

    nRatio = 2
    nTest = int(nSample / nRatio)
    nTrain = nSample - nTest
    samp_ix = [rowId[i] for i in sorted(random.sample(range(nSample), nTest)) ]
        #           
    list_testSamp = df.row_id.isin(samp_ix)   
    list_trainSamp = list_testSamp.apply(lambda x: not x)
        #       
    samp_test = df[list_testSamp]
    samp_train = df[list_trainSamp]

ランダム化データセットサンプルの順序:
  • 推奨:一文出力下付き:sorted(random.sample(range(nSample), nSample))このデータセットをランダム下付き順で巡る
  • sklearnパッケージを使用した内蔵操作:マシン学習アルゴリズムのtrainメソッドはrandom_stateパラメータデータのランダム初期化を設定するための
  • ただし、上記の方法で実現しなければ、サンプルごとに2つの値a,bを設定する方法を用いることができる.前者はランダム値、後者は下付き値である
  • ランダム値aを並べ替え基準として各サンプルの2つの値を並べ替え(昇降順ともに可)
  • 並べ替え後のサンプル値bでそのままの本セットのサンプルをアドレスし、順番に並べ替え順に操作すればよい
  •  def randomlizeSample(X_row, y_row):
         nSample, nFeat = np.shape(X_row)
         inx1 = DataFrame(np.random.randn(nSample), columns = ['randVal'])
         inx2 = DataFrame(range(nSample), columns = ['inxVal'])
         inx = pd.concat([inx1, inx2], axis = 1)
         inx = inx.sort_index(by = 'randVal', ascending = False)
         cnt = 0;
         X = np.zeros((nSample, nFeat))
         y = np.zeros((nSample))
             # you should not set X and y to []
         for line in inx['inxVal']:
             X[cnt] = X_row[line]
             y[cnt] = y_row[line]
             cnt += 1
         return X, y

    アンバランス分類抽出:
  • 希少類サンプル数を保持し、多数類のサンプルを比例してランダムに抽出する
  • 比較的効率的なコード:
    def sampleBalance(df, lableColumn, th):
        label_counts = df[lableColumn].value_counts()
            #           
        mask = (label_counts[df[lableColumn].values] >= th).values
        df = df.loc[mask]
            #             
        label_counts = df[lableColumn].value_counts()
            #            
        labels = label_counts.order(ascending = False).index
        nLabel = len(labels)
        nSampPerLabel = label_counts[labels[-1]]
    
        balancedSamples = pd.DataFrame()
        for n in range(nLabel):
            df_label =  df[lableColumn == labels[n]]
            nItem = len(df_label)
            df_label.reindex(range(nItem))
                #     
            samp_index = [i for i in sorted(random.sample(range(nItem),
                                                             nSampPerLabel))]
            samp_list = df_label[lableColumn].isin(samp_index) 
            df_label = df_label[samp_list]
            balancedSamples = pd.concat([balancedSamples, df_label], axis = 1)
    
        return balancedSamples, [label for lable in labels] 

    書いた拙劣なコード(推奨しない書き方):pythonの特性を運用せず、純粋にc/c++の思想でコードを書き、コード実行効率が悪い.
    - def sampleBalance(X_row, y_row):
    -     rate_np = 1
    -         # radio of negative sample and positive sample
    -     nSample, nFeat = np.shape(X_row)
    -     nSample_pos = np.sum(y_row == 1)
    -     nSample_neg = np.sum(y_row == 0)
    -     nSample_negOnRate = np.floor(nSample_pos * rate_np)
    -     print(nSample, nSample_pos, nSample_neg)
    
    -     X = np.zeros((nSample_pos + nSample_negOnRate, nFeat))
    -     y = np.zeros((nSample_pos + nSample_negOnRate))
    -     # get pos sample
    -     id_pos = 0
    -     id_neg = 0
    -     X_neg = np.zeros((nSample_neg, nFeat))
    -     for i in range(nSample):
    -         if y_row[i] == 1:
    -             X[id_pos] = X_row[i]
    -             y[id_pos] = 1
    -             id_pos += 1
    -         else:
    -             X_neg[id_neg] = X_row[i]
    -             id_neg += 1
    
    -     inx1 = DataFrame(np.random.randn(nSample_neg), columns = ['randVal'])
    -     inx2 = DataFrame(range(nSample_neg), columns = ['inxVal'])
    -     inx = pd.concat([inx1, inx2], axis = 1)
    -     inx = inx.sort_index(by = 'randVal', ascending = False)
    
    -     cnt = 0
    -     for line in inx['inxVal']:
    -         if cnt >= nSample_negOnRate:
    -             break
    -         X[nSample_pos + cnt] = X_neg[line]
    -         y[nSample_pos + cnt] = 0
    -         cnt += 1
    
    -     X_rand, y_rand = randomlizeSample(X, y)
    
    -     return X_rand, y_rand

    2、データセット変換
    異なるパケット間のフォーマット変換
  • 内蔵データ構造、numpyとpandasのデータ構造の使い道の簡単な説明:(データ格納形式はまとめていない)
  • list、dict、set、tupleなどの内蔵データ構造は最も汎用的なデータ構造であり、使い勝手がよい.
  • numpyのデータ構造はmatlabと非常に類似しており、マトリクス演算などの算術計算に適している.機械学習パッケージscikit-learnがサポートするデータ構造でもある.
  • dataframeの機能はデータベースと若干似ており、データの大規模な処理と分析に適している.


  • numpyとlist間の変換:
  • リストをnumpyに変換:
  •     data = [[6, 7.5, 8, 0, 1], [6, 7.5, 8, 0, 1]]
        arr = np.array(data)
  • numpy変換リスト
  •     ##   numpy  :
        data = [[6, 7.5, 8, 0, 1], [6, 7.5, 8, 0, 1]]
        arr = np.array(data)
        data = arr.tolist()
        ##     :
        data = [[elem for elem in line] for line in arr]

    Dataframeとnumpyの変換:
  • dataframe回転numpy
  •     X_train = df.values.astype(int) # df   numpy ndarray,     int
  • numpy転dataframe
  •     columns = ['c0', 'c1', 'c2', 'c3', 'c4']
        df = pd.DataFrame(X_train, columns = columns)

    Dataframe,seriesとlist間の変換:
  • list変換dataframeとseries
  •     data = [[6, 7.5, 8, 0, 1], [6, 7.5, 8, 0, 1]]
        columns = ['c0', 'c1', 'c2', 'c3', 'c4']
        df = pd.DataFrame(data, columns = columns)
        data = [6, 7.5, 8, 0, 1]
        ser = pd.series(data)
  • dataframeとseriesをlistに変換
  •     ## dataframe   list
        df['c0'].values.tolist() #        list
        df.values.tolist() #    dataframe   list
        ## series   list
        ser.values.tolist() #  series    list