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

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

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

pandasの高速化について記事化したいと思います!

 

メモリ容量の最適化

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から居なくなってしまった?)を使わせて頂きます。

 

 

本当にすべて必要か検討する

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

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

 

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

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

 

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

 

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

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

 

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

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

 

プログラミング・実務経験がある方も必見!
空いた時間をスキルアップ・収入増に使ってみませんか?

副業で仕事を取る方法を教えてくれる!
プログラミングスクール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]   筆者について 筆者は、AIプログラミングスクールに通っていた経験がある現役エンジニアです。 筆者は、K[…]

 

まとめ

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

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

 

プログラミング・実務経験がある方も必見!
空いた時間をスキルアップ・収入増に使ってみませんか?

副業で仕事を取る方法を教えてくれる!
プログラミングスクール4選の詳細

AI(機械学習)が学べるプログラミングスクール5つを比較!
AIを学び、転職を考えている人にオススメの記事になっています。

【厳選比較】AIプログラミングスクール5選

最新情報をチェックしよう!
>プログラミングスクール検索・比較表サイト

プログラミングスクール検索・比較表サイト

ワンクリック、さらに詳細に条件を指定してプログラミングスクールの検索ができます。さらに比較表により特徴を細かく比較できる!

CTR IMG