pandasは遅い!大量データの高速化、最適化のノウハウを公開!

pandas(Pythonのデータ処理用のライブラリ)は、条件を指定してデータを取り出したりするのに便利なライブラリです。

しかし、kaggleのコンペのように1億レコード(行)もある大量データだと、メモリ不足に陥ったり、処理速度が遅くなることがありませんか?

そこで、この記事ではpandasをつかったデータの最適化(メモリ容量の最適化)、高速化について解説します!

\IT未経験者からのサポートあり!転職サービス3選!!/

サービス名
未経験 未経験OK 未経験の転職専用 経験者向け
公開の求人数 ITエンジニア全体で1万件以上
ITエンジニア未経験で600件以上
未公開 5,000件以上
利用対象 全職種 IT特化 IT特化
特徴 ✓誰もが知る転職サービス
✓経歴を登録しておくとオファーが来る
✓企業担当者と条件交渉
✓スキルの身につく企業を紹介
✓IT専門のエージェントが対応
✓転職成功すると年収200万円以上の大幅アップがある
転職サポート内容
  • 求人検索
  • 企業担当者と交渉
  • 求人紹介
  • ライフプランのサポート
  • キャリア相談
  • 求人紹介
  • 提出書類の添削
  • 面接対策
公式サイト リクナビネクスト テックゲート レバテックキャリア

 

メモリ容量の最適化

pandasにread_csvだけでデータを読み込むだけでは、無駄な領域まで使ってしまい、すぐにメモリ不足に陥ります。

ここでは、pandasにおいてできるかぎり少ないメモリ容量で処理できる方法を書きます。

大前提として、使用しないメモリ(変数)が出てきたら、その都度、delで解放していきます。

 

データに対して型を宣言する【メモリ容量最適化】

単純にpandasにread_csvしただけでは、最もデータ領域を使う型が選択されてしまいます。たとえば、int系だとint64が使われてしまいます。

数値の範囲が、127までの場合、int16で足りるのに、int64を使っていたら無駄な領域を使うことになります。

こんなときは、型を定義して、「astype」関数を組み合わせるなどして、メモリ容量を減らすことを検討します。

コードの例は以下の通りです。

 

data_types_dict = {
    'timestamp': 'int64',
    'user_id': 'int32', 
    'content_id': 'int16', 
    'content_type_id':'int8', 
    'task_container_id': 'int16',
    'user_answer': 'int8',
    'answered_correctly': 'int8', 
    'prior_question_elapsed_time': 'float32', 
    'prior_question_had_explanation': 'bool'
}

#データは以下からダウンロードしてください
#https://www.kaggle.com/c/riiid-test-answer-prediction/data
train_df = pd.read_csv('./riiid-test-answer-prediction/train.csv',nrows = 1000000)

#型を宣言しないと、無駄にメモリを使う(例:本来int8で足りるのに、int64で確保される)のでしっかり型宣言しておく
train_df = train_df.astype(data_types_dict)

 

メモリ容量を最適化する処理(関数)を実行する

以下のような関数を使ってメモリ容量を最適化します。

 

'''Function to reduce the DF size'''
# source: https://www.kaggle.com/kernels/scriptcontent/3684066/download

def reduce_mem_usage(df):
    """ iterate through all the columns of a dataframe and modify the data type
        to reduce memory usage.        
    """
    start_mem = df.memory_usage().sum() / 1024**2
    print('Memory usage of dataframe is {:.2f} MB'.format(start_mem))
    
    for col in df.columns:
        col_type = df[col].dtype
        
        if col_type != object:
            c_min = df[col].min()
            c_max = df[col].max()
            if str(col_type)[:3] == 'int':
                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
                    df[col] = df[col].astype(np.int8)
                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
                    df[col] = df[col].astype(np.int16)
                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
                    df[col] = df[col].astype(np.int32)
                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
                    df[col] = df[col].astype(np.int64)  
            else:
                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
                    df[col] = df[col].astype(np.float16)
                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
                    df[col] = df[col].astype(np.float32)
                else:
                    df[col] = df[col].astype(np.float64)
        else:
            df[col] = df[col].astype('category')

    end_mem = df.memory_usage().sum() / 1024**2
    print('Memory usage after optimization is: {:.2f} MB'.format(end_mem))
    print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))
    
    return df


関数は、カグラーさんが作ってくれたもの(作成者が、kaggleから居なくなってしまった?)を使わせて頂きます。

上記の方法で、自動的にメモリ容量の最適をします。

私が上記の関数を試したところ、約50%〜70%ほどのメモリ容量を削減できました。

 

本当にすべてのデータ(レコード)が必要か検討する

Kaggleの「Riiid Answer Correctness Prediction」コンペでは、1億レコードもあるデータセットを使います。

データ全てを使用して訓練させる必要はあるのでしょうか?

 

1億レコードの全てを使用する必要があるのかどうかを検討します。

コンペでは、1000万レコードほどで上位に行った人もいるので、全て使用する必要も無いと言えます。

 

分割してデータを渡して機械学習させる

機械学習アルゴリズムによっては、一度にデータを渡す物では無く、分割して渡すことができるものがあります(例:ニューラルネットワーク=NN系)。

そんなときは、ファイルからある程度読み込むことを検討します。

 

以下のようなイメージです。

  1. ファイル全体から1/10(先頭から)ほどのデータをメモリに読み込む
  2. 学習モデルに渡して学習
  3. ファイル全体から次の1/10ほどのデータをメモリに読み込む
  4. 学習モデルに渡して学習

 

実装例あり!pandasの処理の高速化

pandasが、データ容量が多くなると処理遅くなりがちです。

特に、for文でデータの参照をするとものすごく遅くなってしまいます。

そこで、改善した方法を記載します。

 

改善方法は以下の通り

やりたいこと 方法 かかった時間
pandasのデータ参照 for文にてpandasのiterrowsで参照 1分1秒
pandasのデータ参照 for文にてpandasから配列に変換して参照 753ミリ秒
pandasのデータ更新 for文にてpandasのiterrowsで参照
更新は、pandas.atで更新する
1分25秒
pandasのデータ更新 for文にてpandasから配列に変換して参照
更新は、pandas.atで更新する
16秒
pandasのデータ更新 for文にてpandasから配列に変換して参照
更新は、一旦更新元のデータを配列に格納して、for文抜けたあとで更新
979ミリ秒

次に実装例を示します。

 

 

独学で挫折した人向け・AI(機械学習)を短期間で学ぶ方法

独学で挫折してしまった
本買ったり、YoutubeでAIを勉強していたんだけど、結局から何を勉強してよいかわからず挫折してしまったんだ。どうしたら解消できる?

 

独学で挫折してしまった人向けに、PythonとAI(機械学習)について、短期間で効率的に学ぶ方法を紹介します。

それは、プログラミングスクールを利用することです。

プログラミングができる人でも機械学習の習得は、難しいため、プロに教えてもらったほうが遥かに最短経路で身につけることができます。

 

筆者は、ITエンジニアでプログラミングは得意です。

しかし、AIについては、AIの考え方を学ぶところで挫折したためAIスクールに4ヶ月ほど通いました。

だから、現役のエンジニアがAIスクールに行くことは恥ずかしくありません!

関連記事

いますぐにでもAI(機械学習)が学べるプログラミングスクールを検討している方へ! [afTag id=2402] [template id="10277"]   筆者について 筆者は、AIプログラミン[…]

 

まとめ

最近は、データ容量が多いkaggleのコンペが増えてきました。

今後も大量データの処理のスキルも必要になってきますね。

 

\IT未経験者からのサポートあり!転職サービス3選!!/

サービス名
未経験 未経験OK 未経験の転職専用 経験者向け
公開の求人数 ITエンジニア全体で1万件以上
ITエンジニア未経験で600件以上
未公開 5,000件以上
利用対象 全職種 IT特化 IT特化
特徴 ✓誰もが知る転職サービス
✓経歴を登録しておくとオファーが来る
✓企業担当者と条件交渉
✓スキルの身につく企業を紹介
✓IT専門のエージェントが対応
✓転職成功すると年収200万円以上の大幅アップがある
転職サポート内容
  • 求人検索
  • 企業担当者と交渉
  • 求人紹介
  • ライフプランのサポート
  • キャリア相談
  • 求人紹介
  • 提出書類の添削
  • 面接対策
公式サイト リクナビネクスト テックゲート レバテックキャリア
最新情報をチェックしよう!