- はじめに
- for文が正しく終了したときに、処理を実行する。(for...else) [1]
- コマンドライン引数を処理する。(argparser, click) [2]、[3]
- ファイル名に時間を埋め込む 。(datetime)[4]
- ファイルを開く。(with open... as f)
- プログラムの進行状況などをprintするときに改行せず上書きする。 (sys.stdout.write)
- ファイル名で検索してリストを取得する。(glob)
- 文字中に含まれる数字でソート。[5]
- 別のディレクトリのファイルをインポートする。(sys.path.append)
- ある条件を満たす数列を生成する。(リスト内包表記、ジェネレータ)
- 学習データからランダムなミニバッチを作る。( np.random.permutation(N) ) [6]、[7]
- KFold Cross Validation(sklearn.cross_validation.KFold) [8]
- 特徴ベクトル(の一部)を正規化する。(sklearn.preprocessing.MinMaxScaler) [9]
- bool型の掛け算順
- クラスタリングなどの結果をscatterでプロットする(plt.scatter)
- csvファイルからデータを読み込む。(pandas)
- リストで重複した要素を削除する。(pandas)
- 特定の文字を含むものを取り出す(pandas)
- おわりに
- 参考
はじめに
コードを書いていると、「あ、これ前もググって実装したやつだ」ということがよくある。 しかもどうやったか全く覚えていない。悲しい。 あげく検索ワードすらわからないときが頻繁にある。悲しい。
これ以上、そのような悲しいことを起こさないために、たまに使う細かい処理について書いていく。 間違っている部分や黒魔術的な部分もあるかもしれないので注意。 随時追加するつもり。 番号は参考サイトを示している。サンプルコードについて非常に参考にした。
for文が正しく終了したときに、処理を実行する。(for...else) [1]
正常終了するとelseというのが、なんとなく慣れない。いちいちフラグとかたてなくてもいい。
for i in range(10): print i else: print "hoge"
0
1
2
3
4
5
6
7
8
9
hoge
for i in range(10): print i break else: print "hoge"
0
コマンドライン引数を処理する。(argparser, click) [2]、[3]
コマンドライン引数を処理するモジュールとして、argparserとclickがある。まずはargpaeser。
import argparse parser = argparse.ArgumentParser() parser.add_argument('-n', '--n_iter', default=1000, type=int, help="num_iteration") parser.add_argument('-g', '--gpu', action='store_true') args = parser.parse_args() print args print args.n_iter print args.gpu
$ python temp.py -n 10 --gpu
Namespace(gpu=True, n_iter=10)
10
True
続いてclick。最近知ったので、使い方がまだ良くわかっていないが、こちらのほうがコンパクトに書けて便利な気がする。
import click @click.command() @click.argument("name") @click.option("-n", "--num_iter", type=int, help="num iteration") def main(name, num_iter): for i in range(num_iter): msg = "hello %s %d" % (name, i) print msg if __name__ == '__main__': main()
$ python temp2.py world -n 10
hello world 0
hello world 1
hello world 2
hello world 3
hello world 4
hello world 5
hello world 6
hello world 7
hello world 8
hello world 9
ファイル名に時間を埋め込む 。(datetime)[4]
結果の出力など、うっかり上書きしないようにするときによく使う。
from datetime import datetime filename = "results/" + datetime.now().strftime("%Y%m%d_%H%M%S") + ".csv" print filename
results/20151130_225340.csv
ファイルを開く。(with open... as f)
普通にopenだけで開くと後でcloseしないといけない。忘れるので、withを使う。 自作のクラスもこういうものに対応させておくと後で便利かも。
with open("temp.csv") as f: for i in f: print i
プログラムの進行状況などをprintするときに改行せず上書きする。 (sys.stdout.write)
ループの中で、print i などと書くと、いちいち改行されて鬱陶しい。 以下のコードでいい感じに進行状況を表示できる。
import sys import time for i in range(100): sys.stdout.write("\riter=%d" % i) sys.stdout.flush() time.sleep(0.1)
iter=99
ファイル名で検索してリストを取得する。(glob)
paramsディレクトリ内に存在する全てのパラメータファイルを読んでいって、順番に実行するとか、resultsディレクトリ以下の全てのファイルの平均値をとるとか、やりたいときに使う。
import glob print glob.glob("./*") print glob.glob("./*.py")
['./tips.org', './temp.csv', './Untitled.ipynb', './temp1.py', './temp2.py', './temp10.py']
['./temp1.py', './temp2.py', './temp10.py']
文字中に含まれる数字でソート。[5]
ファイル名などに数字が付いている時、普通にsortメソッドを使うと、2の前に10が来たりしてしまう。はじめから%05dとかで書いておけば不要。
import re files = glob.glob("./*.py") temp = [(re.search("[0-9]+", x).group(), x) for x in files] temp.sort(cmp = lambda x, y: cmp(int(x[0]), int(y[0]))) print [x[1] for x in temp]
['./temp1.py', './temp2.py', './temp10.py']
別のディレクトリのファイルをインポートする。(sys.path.append)
昔作ったコードを再利用したいとき、コピーしてきてもいいけど、これでもOK。
import sys sys.path.append("../kaggle/mnist/") import nn net = nn.Perceptron(10,2)
ある条件を満たす数列を生成する。(リスト内包表記、ジェネレータ)
リスト内包表記をごちゃごちゃすると色々できる。 あまり使いすぎるとわかりにくいので、ほどほどに使う。
x = [i**2 for i in range(10) if i%2==0] print x
[0, 4, 16, 36, 64]
ジェネレータでもいける。yieldは遅延評価なので、1つ値を生成するコストが大きいかつ、いくつ必要かわからないときとかいいかもしれない。
def generator(): counter = 0 while(True): yield counter**2 counter += 2 for i in generator(): print i if i>=64: break
0
4
16
36
64
学習データからランダムなミニバッチを作る。( np.random.permutation(N) ) [6]、[7]
SGDとかやるときに使う。
def train(self, inputs, labels, tests): N = len(inputs) inputs = np.array(inputs).astype(np.float32) labels = np.array(labels).astype(np.int32) tests = np.array(tests).astype(np.float32) for epoch in range(self.num_epoch): print "epoch: %d" % epoch perm = np.random.permutation(N) for i in range(0, N, self.batchsize): x_batch = cuda.to_gpu(inputs[perm[i:i + self.batchsize]]) y_batch = cuda.to_gpu(labels[perm[i:i + self.batchsize]])
KFold Cross Validation(sklearn.cross_validation.KFold) [8]
一瞬自分でつくろうかと思ったけど、探してみたらやっぱりあったscikit_learn。 自分で書くコードは最小限にする方針からこれを使う。
kf = cross_validation.KFold(len(all_vec), n_folds=10, shuffle=True) for train_index, test_index in kf: test_vec = all_vec[test_index] test_label = labels[test_index] train_vec = all_vec[train_index] train_label = labels[train_index]
特徴ベクトル(の一部)を正規化する。(sklearn.preprocessing.MinMaxScaler) [9]
sklearnに正規化の関数があるので、それを使う。1ofKの変数とかは正規化しなくてもいいと思うので、一部だけやる例。
min_max_scaler = sklearn.preprocessing.MinMaxScaler()
no_normalize_index = 8
min_max_scaler.fit(train_vec[:, no_normalize_index:])
test_vec[:, no_normalize_index:] = min_max_scaler.transform(test_vec[:, no_normalize_index:])
train_vec[:, no_normalize_index:] = min_max_scaler.transform(train_vec[:, no_normalize_index:])
bool型の掛け算順
以前、一度バグを産んだ原因コード。演算子の優先度は、(符号としての) - > * > (引き算としての)- なので、こういうことをすると、一見引き算の順序を変えただけなのに、結果がかわる。これからはおとなしくastypeでキャストしようと心に誓った。
import numpy as np bool_list = np.array([True, False]) print [0,0] - bool_list * 0.5 print -bool_list * (0.5) + [0,0] print - bool_list.astype(int) * 0.5 + [0,0]
[-0.5 0. ]
[ 0. 0.5]
[-0.5 0. ]
クラスタリングなどの結果をscatterでプロットする(plt.scatter)
だいたい特徴量的にx, yを管理しているので、特徴ベクトル行列のrow, colを入れ替えてプロットする。 colorの変数に適当に突っ込むとよしなにやってくれる。 ついでにPCAもする。
from sklearn.decomposition import PCA pca = PCA(n_components=2) pcaed_data = pca.fit_transform(data[:,1:]/255.0) pcaed_data = zip(*pcaed_data) plt.scatter(pcaed_data[0], pcaed_data[1], marker=".",c=data[:,0], linewidths=0, alpha=0.7)
csvファイルからデータを読み込む。(pandas)
普通にopenでファイルを開いてもいいけど、pandasでやると欠損値とかの扱いがかなり楽。
import pandas as pd data = pd.read_csv("train.csv") data = data[~data.Cabin.isnull()] #"Cabin"がNanでないものだけを抽出する。 print data
PassengerId Survived Pclass \
1 2 1 1
3 4 1 1
6 7 0 1
10 11 1 3
.. ... ... ...
879 880 1 1
887 888 1 1
889 890 1 1
Name Sex Age SibSp \
1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1
3 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1
6 McCarthy, Mr. Timothy J male 54.0 0
10 Sandstrom, Miss. Marguerite Rut female 4.0 1
.. ... ... ... ...
879 Potter, Mrs. Thomas Jr (Lily Alexenia Wilson) female 56.0 0
887 Graham, Miss. Margaret Edith female 19.0 0
889 Behr, Mr. Karl Howell male 26.0 0
Parch Ticket Fare Cabin Embarked
1 0 PC 17599 71.2833 C85 C
3 0 113803 53.1000 C123 S
6 0 17463 51.8625 E46 S
10 1 PP 9549 16.7000 G6 S
.. ... ... ... ... ...
879 1 11767 83.1583 C50 C
887 0 112053 30.0000 B42 S
889 0 111369 30.0000 C148 C
[204 rows x 12 columns]
リストで重複した要素を削除する。(pandas)
例えばIDが重複していて、どちらかの要素がいらないとき、これを見つけて削除する。 オプションで上にあるものを残すか、下にあるものを残すかを選べる。
print data[~data.Cabin.duplicated()]
PassengerId Survived Pclass \
1 2 1 1
3 4 1 1
6 7 0 1
10 11 1 3
.. ... ... ...
879 880 1 1
887 888 1 1
889 890 1 1
Name Sex Age SibSp \
1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1
3 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1
6 McCarthy, Mr. Timothy J male 54.0 0
10 Sandstrom, Miss. Marguerite Rut female 4.0 1
.. ... ... ... ...
879 Potter, Mrs. Thomas Jr (Lily Alexenia Wilson) female 56.0 0
887 Graham, Miss. Margaret Edith female 19.0 0
889 Behr, Mr. Karl Howell male 26.0 0
Parch Ticket Fare Cabin Embarked
1 0 PC 17599 71.2833 C85 C
3 0 113803 53.1000 C123 S
6 0 17463 51.8625 E46 S
10 1 PP 9549 16.7000 G6 S
.. ... ... ... ... ...
879 1 11767 83.1583 C50 C
887 0 112053 30.0000 B42 S
889 0 111369 30.0000 C148 C
[147 rows x 12 columns]
特定の文字を含むものを取り出す(pandas)
数字は簡単だけど、文字の一部に含まれているというのがよくわからなかった。これもpandasを使えば簡単。
print data[data.Cabin.str.contains("A")]
PassengerId Survived Pclass \
23 24 1 1
96 97 0 1
174 175 0 1
185 186 0 1
209 210 1 1
284 285 0 1
445 446 1 1
475 476 0 1
556 557 1 1
583 584 0 1
599 600 1 1
630 631 1 1
647 648 1 1
806 807 0 1
867 868 0 1
Name Sex Age SibSp \
23 Sloper, Mr. William Thompson male 28 0
96 Goldschmidt, Mr. George B male 71 0
174 Smith, Mr. James Clinch male 56 0
185 Rood, Mr. Hugh Roscoe male NaN 0
209 Blank, Mr. Henry male 40 0
284 Smith, Mr. Richard William male NaN 0
445 Dodge, Master. Washington male 4 0
475 Clifford, Mr. George Quincy male NaN 0
556 Duff Gordon, Lady. (Lucille Christiana Sutherl... female 48 1
583 Ross, Mr. John Hugo male 36 0
599 Duff Gordon, Sir. Cosmo Edmund ("Mr Morgan") male 49 1
630 Barkworth, Mr. Algernon Henry Wilson male 80 0
647 Simonius-Blumer, Col. Oberst Alfons male 56 0
806 Andrews, Mr. Thomas Jr male 39 0
867 Roebling, Mr. Washington Augustus II male 31 0
Parch Ticket Fare Cabin Embarked
23 0 113788 35.5000 A6 S
96 0 PC 17754 34.6542 A5 C
174 0 17764 30.6958 A7 C
185 0 113767 50.0000 A32 S
209 0 112277 31.0000 A31 C
284 0 113056 26.0000 A19 S
445 2 33638 81.8583 A34 S
475 0 110465 52.0000 A14 S
556 0 11755 39.6000 A16 C
583 0 13049 40.1250 A10 C
599 0 PC 17485 56.9292 A20 C
630 0 27042 30.0000 A23 S
647 0 13213 35.5000 A26 C
806 0 112050 0.0000 A36 S
867 0 PC 17590 50.4958 A24 S
おわりに
書いたら覚えるだろう、そう思っていた。
参考
- for文の終了時の処理(for...else) - 繰り返し - Python入門
- argparseを使ってみた - そこはかとなく書くよ。
- Python: コマンドラインパーサの Click が便利すぎた - CUBE SUGAR CONTAINER
- 現在時刻を取得・ファイル名用に整形 - 週末京都
- スーパーIT戦士になりたい!: Python: ファイル名の番号でソートする
- Chainerによる多層パーセプトロンの実装 - 人工知能に関する断創録
- numpy.random.permutation — NumPy v1.10 Manual
- sklearn.cross_validation.KFold — scikit-learn 0.17 documentation
- API Reference — scikit-learn 0.17 documentation