2017-10-14 2 views
1

私は、PythonとSciKitLearnスタックを使用してブラジルの都市間の気候データを一致させるためのスクリプトを作成しました。現時点では、私はMongoDBを使って60M +のエントリを持つ気候コレクションを、Pandasはこれらのテーブルを照会して参加しています。PandasとSciKitLearn Stackを使用してPythonスクリプトのパフォーマンスを向上させるには?

各ブラジルの都市の気候データを簡単なアルゴリズムで比較して、都市の各ペアの最終得点を生成します。

問題は、時間がかかりすぎるということです(ペアあたり11秒)。 12M +の可能なすべての組み合わせのスコアを取得したいので、これは実際には遅いです。どうすれば速くすることができますか?ここに関連するコードは次のとおりです。MongoDBの(ほとんど瞬時)との接続

client = MongoClient('localhost', 27017) 
db = client.agricredit_datafetcher_development 

(速いが、インスタントではない)気候データのフェッチ:

base_weather_data = list(db.meteo_data_weather_data.find({'weather_station_id': ObjectId(base_weather_station['_id'])})) 
target_weather_data = list(db.meteo_data_weather_data.find({'weather_station_id': ObjectId(target_weather_station['_id'])})) 


return {'base_dataframe': pd.DataFrame(base_weather_data), 
     'target_dataframe': pd.DataFrame(target_weather_data)} 

埋め込まれた(ネスト)からデータを取得しますMongoコレクション(遅い):

base_dataframe = dataframes['base_dataframe'].set_index('analysis_date')['weather_forecast'].apply(pd.Series) 
target_dataframe = dataframes['target_dataframe'].set_index('analysis_date')['weather_forecast'].apply(pd.Series) 

空の値を削除してDに参加するクエリataFrames(速いが、インスタントではない):

available_forecast_data = base_dataframe[base_dataframe['weather_forecast'] > 0][['weather_forecast']] 
to_be_compared_data = target_dataframe[target_dataframe['weather_forecast'] > 0][['weather_forecast']] 

join_dataframe = available_forecast_data.join(to_be_compared_data, how='inner', lsuffix='_base', rsuffix='_target') 

は、その後、私は(ちょうど合計値や平均値はかなり速いです)スコアリングアルゴリズムを適用し、その後、私のモンゴデータベースに挿入します。

コードを改善するにはどうすればよいですか?ここで

は、いくつかのポイントです:

  • 私はそれは私が新しいデータフレームにpd.Series方法を作成、使用せずにできるハンドル埋め込まれたMongoDBのデータ(第3ステップ)をしていた場合にかなり確信しています。私は既にjson.normalize私のMongoコレクションを試みて、それをDataframeに変換しましたが、それも遅く、これを行うといくつかのデータが駄目になります。

  • ボトルネックは上記の手順に従います。他のすべてのステップ(スコアリングアルゴリズムなど)は即座に実行されます。

  • 私は、質問、グループ化、およびデータフレームの作成を行うためにパンダに依存しています。それは大丈夫ですか?私はMongo Aggregation Frameworkを試して、何か改善があるかどうか試してみたいと思っています。その価値はありますか?

  • これを改善する方法はHadoop/Sparkですか?データサイエンスプロジェクトでの役割を理解するのに苦労しています。

EDIT:第3ポイントが解決!代わりに、データフレームにpd.Series方法を適用した使用済みモンゴ集計:

pipeline = [ 
    {"$match" : {"weather_station_id": ObjectId(weather_station_id)}}, 
    {"$project": { 
     'analysis_date': "$analysis_date", 
     'rainfall': "$rainfall.rainfall", 
     'agricultural_drought': "$rainfall.agricultural_drought", 
     'weather_forecast': "$weather_forecast.med_temp" 
     } 
    } 
] 

今では都市の各ペアのために〜1.2秒かかります。しかし、私はまだこれを改善できると思っています...今、ボトルネックはweather_dataのクエリです。しかし、索引付けされているので、それを速くする方法はありますか?私は2を持っている

+0

60M +エントリデータベースである 'meteo_data_weather_data'は' weather_station_id 'によって索引付けされるので、2番目のステップでパフォーマンスを向上させる方法はないと思います。 –

答えて

0

ものの、

Parallel(n_jobs=4)(delayed(insert_or_read_scores_on_db)(city['name']) for city in cities) 

それでも改善を探して:

EDIT 2:JobLibhttps://pythonhosted.org/joblib/parallel.html)で自分のタスクを並列化は3〜4倍:)で私のスクリプト仮想速度をスケールあなたに役立つ提案。

1)2番目のステップでは、列の各セルに適用されるデータフレーム適用関数を使用しています。もし何とかあなたは、それを行うためのforループを書くことができますが、並行して行うことで有名なPython Numbaライブラリを使うことができます。 forループを使って関数を作成することができます。その関数では、マルチコアCPUで並行して動作するデコレータ@jitを与えることができます。あなたはnumbaインポートjitから行う必要があります

2)私はワシントン大学の教授のビデオを見てきました。コースラでコースをやっているところで、地図を減らすアルゴリズムを使って2つのテーブルのJOINを実行する方法を教えています。平行。あなたが並行して実行される場合は、あなたが参加することもできます。

+0

あなたの最初の声明は、私が第3のポイントを改善するのに役立ちました。私は、 'apply'関数が各セルで同時に働いたことを知らなかった。私は代わりにMongoDB集計を使用して解決しました。 TY、上記の私の編集を参照してください! –

関連する問題