#概要
VSCodeでPython3で機械学習とかデータマイニング的なことをする時に得られた知見をメモしていく。
読み辛いのは重々承知。
随時更新。
Python3オンリーな場合の開発環境構築の個人的ベストプラクティス
Python3 + venv + VSCode + macOS な開発環境の構築 - Qiita
作図ライブラリ比較
Jupyter-notebook の作図ライブラリ比較 - Qiita
インタラクティブな可視化
ipywidgetsとBokeh使ってインタラクティブな可視化をする - Qiita
VSCodeのjupyter extensionでipywidgetsをしようとすると、スクリプト周りが読めないようなので使えない。
support for ipython/jupyter widgets · Issue #21 · DonJayamanne/vscodeJupyter
大人しくブラウザのJupyterでやろう
サンプル
numpy使ってたらpylintがhas no ~のエラーが出る時はVSCodeのsettings.jsonに
"python.linting.pylintArgs": [
"--extension-pkg-whitelist=numpy"
]
Pylint で no-member エラーを出なくする - Qiita
k-meansした時に ValueError: n_samples=1 should be >= n_clusters=3
なエラーが出る理由
必要となるデータは2次元である必要があるので、このブログではappendしていて非効率なので、sample_data.iloc[:, 0:1]
のようにするといい。
これで抽出できるのは1列目であり、sample_data.iloc[:, 0]とした時と変わらないが、0:1とすることで2次元で表されることになるようで、上記のエラーは出なくなる
機械学習・クラスタリングを理解するまで6日目 - ITの隊長のブログ
df = pd.DataFrame()
で df.append(df2)
しても dfには追加されない。
df = df.append(df2)
とすべし
python - Appending to an empty data frame in Pandas? - Stack Overflow
:の後ろに型名を書くおくと(Type Hints)、IntelliSenseしてくれるようになる
ただしType Hintsは単なるコメントと同義なようなので、合ってない型のオブジェクトを渡してもlinterは怒らないし、実行するまで型チェックはされない
クラスメンバのスコープ
pandasのデータをいい感じに取り出したい時
Python pandas データのイテレーションと関数適用、pipe - StatsFragments
listをforeachするときにindexも欲しい時
リストのインデックス (enumerate) - Python入門から応用までの学習サイト
dataframeの中身の型を変換したい時
Pandas: Converting to numeric, creating NaNs when necessary
pip-compileとpip-syncの組み合わせ良さげ
pip関連ツールでPythonのパッケージ管理を楽にする - Qiita
DataFrameの連結や結合した時の図解
シンプルに縦に結合したい時はappend、横に結合したい時はjoin
Python pandas 図でみる データ連結 / 結合処理 - StatsFragments
pandasのdataFrameをprintした時に量が多かったら省略されてしまうが、任意に設定すれば全表示とかできる
pd.set_option("display.max_rows", 10)
pandasで表示が省略されるのを防ぐ - 仕事中の問題と解決メモ。
多次元のlistをソートする場合にはsortのkeyをlambda
データ構造別のソートの仕方
Python sortのまとめ (リスト、辞書型、Series、DataFrame) - Qiita
isortを使えばimportをいい感じにreformatしてくれます
code-python-isort - Visual Studio Marketplace
%sql select * from hoge
とか書くだけていい感じにDataFrameとかにも突っ込めるjupyterのextention
ipython-sql
VSCodeでJupyterなpyをipynbに変換するツール作った - Qiita
VSCodeでJupyterなpyをipynbに変換するツール作った - Qiita
前者のappendはIntelliSenseが働いてappendって出てくるが、後者のは出てこない
tttt = pd.DataFrame()
tttt.append(None)
tttt = df[["label"]]
tttt.append(None)
これは引数の型が分からないからなので、assert isinstance
とかを使ってdf[[“label”]]
の後に型を明示してあげれば、appendはIntelliSenseで出てくる
IntelliSense に仕事してもらう Python の書き方 - アジョブジ星通信
grouperとても便利
Python pandas アクセサ / Grouperで少し高度なグルーピング/集計 - StatsFragments
時系列データを1sec毎とか1日毎とかでグルーピングしたりもできる
.replace("hoge", "toHoge")
で置換できるのは対象の文字列に対してだけだが、
.replace(".*", "+1", regex=True)
みたいに正規表現でもいける
機械学習の超初心者が、みんなが良いと言う記事を読んでまとめてみた - Qiita
機械学習の超初心者が、みんなが良いと言う記事を読んでまとめてみた - Qiita
confusion matrixを出したくなったらこんな感じですぐできる
from sklearn.metrics import confusion_matrix
test_label_lb = [] # 正解ラベル
p_label = [] # 推定ラベル
cmx_data = confusion_matrix(y_true=test_label_lb, y_pred=p_label)
labels = ["A", "B", "C"]
df_cmx = pd.DataFrame(cmx_data, index=labels, columns=labels)
開発者がビッグデータ分析にPythonを使う時によくやる間違い | プログラミング | POSTD
jupyterで地下はともかく地図表示できる
import folium
m = folium.Map(location=[33.763, -84.392], zoom_start=17)
folium.Marker(
location=[33.763006, -84.392912],
popup='World of Coca-Cola'
).add_to(m)
m
やはりラムダ使う方がスマートか
Python3におけるmap/filterの使い方 - どこかに向かうらしい話
いい感じのplot例
Python pandas プロット機能を使いこなす - StatsFragments
mapやfilterで返してくるのはiteratorなので
list()などで中身出しちゃうとiteratorが進んでしまう
num_map = map(lambda n: n + 1, np.random.random(1000))
print(list(num_map)) # ここでは値でる
num_filter = filter(lambda n: n > 0.5, np.random.random(1000))
print(list(num_filter)) # ここでは値でる
print(list(num_map)) # ここではもうでない
print(list(num_filter)) # ここではもうでない
dictのvalueがmaxなもののkeyを見つけたいなら1行でいける
max(dic, key=lambda i: dic[i])
パスの操作はpathlibが簡単
Python3.4以降ならos.pathはさっさと捨ててpathlibを使うべき
from pathlib import Path
LOG_DIR = "/Users/your_name/log"
Path(LOG_DIR).joinpath("log.json") #それか Path(LOG_DIR) / "log.json"
# PosixPath('/Users/your_name/log/log.json') となる
Path(LOG_DIR).joinpath("log.json").exists()
# False
multiprocessing使ってマルチプロセスで処理
rangeで適当に渡せばいいので簡単
いろいろあるグラフ描画ツールのラッパーHoloViews
Pythonの可視化ツールはHoloViewsが標準になるかもしれない
HoloViewsの基本的なグラフをワンライナーで
進捗バーの表示
iterableのオブジェクトを渡せば秒速何iterate?で進捗しているのかも分かったりするのでいい目安になる
matplotlibでsavefigしたらラベルがはみ出る時がある
フォントデカくしたりしたり、横長とか縦長グラフを作るとsavefigでラベルがはみ出ることがあるので.savefig("test.png", bbox_inches="tight")
とすると綺麗に出る
実行時間を測りたい
Jupyter Notebook > %timeit range(100) > 処理時間の計測 > %%timeit > 複数文の処理時間の計測
IPythonでコードの実行時間を測る話
Jupyterでなら%time func()
でfuncの実行時間が取れるが、割とブレる
%timeit func()
にすると何回か実行して測ってくれる
VSCodeのjupyter extensionでは%%timeit
を認識しないので複数行を評価する場合はVSCodeのJupyterでは無理っぽい(まぁ関数にすればいい)
そのDataFrameにNaNあるのか
pandas DataFrame内にNaNありますか?
df.isnull().values.any()
が覚えやすいし早いので良さげだが、型によっても変わってくるのでお試しあれ
Pandasで高速に処理するためのtips
Python pandas パフォーマンス維持のための 3 つの TIPS
pythonVSCodeでautocomplete遅い問題
Slow auto complete speed for custom modules python #903
Slow autocompletion/formatting #581
VSCodeのsettings.jsonに以下のように追記するとpreloadしてくれる。
"python.autoComplete.preloadModules": [
"pandas",
"numpy",
"matplotlib"
]
これにより、pandas.DataFrame()
とかのsuggestは早くなってる気がするけど、型推論が必要な場面では変わらない気がする。
assert isinstance
で明示してあげると早くなるけど、一々やってられん...
df = func_something()
df.sum() #ここではsumが出るの遅い
assert isinstance(df, pd.DataFrame)
df.sum() #ここではsumはすぐ出る
JupyterでPoolでマルチプロセスな処理したらゾンビ大量発生問題
IPythonでmultiprocessingを使ってたらゾンビ化するとき
#p = Pool()
p.terminate()
明示的に殺すか、
with Pool() as p:
results = p.map(func, range(0, 100))
withを使う
filterやmapを2重にしてlambdaの変数を参照するとpylintがE0602で怒る
list_prefix
にあるprefixと一致するものをlist_ab
から見つける場合(この例はあまりうまい例じゃないけど...)
list_ab = ["aa_a", "aa_b", "ab_a", "ab_b", "ba_a", "ba_b"]
list_prefix = ["aa", "ab"]
print(list(
filter(lambda a: True in map(lambda b: a.startswith(b), list_prefix),
list_ab)
)) # ['aa_a', 'aa_b', 'ab_a', 'ab_b']
これだとa
がE0602で怒られる(が、pylintが怒るだけなので実行はできるし結果も期待通りに得られる)
from itertools import compress
print(list(
compress(list_ab,
[True in [a.startswith(b) for b in list_prefix] for a in list_ab]
)
)) # ['aa_a', 'aa_b', 'ab_a', 'ab_b']
compressを使ってリスト内包表記で書くと良い。
【python】pythonでメモリ不足になったときにすること
要約すると
- multiprocessingをやめよう
- GCを上手く使おう
- numpy配列にしよう
- 32bitにしよう
- forで破壊的代入をしよう(遅いならcython)
- データ圧縮しよう(実用性微妙?)
- 物理的にメモリ増やそう
pickleの代わりにjoblibを使って永続化する
データ的に圧縮があんまり効かないので効果は薄いが、小さくはなってる
圧縮してるので書き出しまでの速度はpickeよりも当然遅い
compless=0にすると無圧縮なのでpickleで出した時とほぼ同じサイズになるが、dumpとloadにwith openとか書く必要ないのでjoblibの方が楽
import os
import pickle
import joblib
import numpy as np
import pandas as pd
dump_data = np.random.randn(10000000)
with open("dump_data.pkl", "wb") as f:
pickle.dump(dump_data, f)
print(os.path.getsize("dump_data.pkl") / 1024 / 1024, "MB")
# 76.29409885406494 MB
joblib.dump(dump_data, "dump_data", compress=3)
print(os.path.getsize("dump_data") / 1024 / 1024, "MB")
# 73.5648946762085 MB
# joblib.load("dump_data") #読み込み
seabornの作図例あれこれ
Seabornの全メソッドを解説(その1:グラフ一覧)
Python でデータ可視化 - カッコいいヒートマップを描こう
pythonで美しいグラフ描画 -seabornを使えばデータ分析と可視化が捗る その1
pip-compileするときにegg_infoのエラーが出たら
matplotlibやseaborn関連で起きる場合が多い気がするが、egg_info云々とエラーが出てpip-compileができない場合がある。
その場合は pip-compile --rebuild
するとうまくいくと思う
参考: https://github.com/jazzband/pip-tools/issues/586
別のディレクトリからimportしたい時
__init__.py
を作って読むのがベストか
Visual Studio CodeのJupyter extensionからPlotlyを使う
めちゃめちゃ便利
HTML(html_code)
とinit_notebook_mode()
を同じCellで一気に実行すると表示されない。
なので、まずHTML(html_code)
だけを実行してから、init_notebook_mode()
を実行するとうまくいく(一旦表示できれば同じCellで一気に実行しても大丈夫)
JSのロードが非同期だから?