分割してCSVに書く、分割されたCSVを読む
1年前のプログラムの一部改良。
複数ファイルを連続して読むプログラム - Cucco’s Compute Hack
ディレクトリのパスと、ファイル名(拡張子ナシ、連番ナシ)を与えて、
決まった行数を書いたファイルを保存する、それらのファイルを開いて読む、というプログラム。
読む場合は以前から継続で、イテレータを利用できるようにした。
読むファイルをすべてリストで指定していたが、pathlibで一覧を取得している。
プログラム
import csv from pathlib import Path import os from faker import Faker import random class split_csv_writer: ''' 渡された値をファイルに書き落としていく max_linesを超えたら、別のファイルに変更する。 ''' def __init__(self, dirctory_path, filename_wo_extension, header_data=None, max_lines=100000): self.max_lines = max_lines if header_data == None: self.max_lines = max_lines-1 self.currnet_lines = self.max_lines+1 # 初回にOpenを実行してもらうため。 self.currnet_file_post_index = 0 self.filename = filename_wo_extension self.f = None self.dirctory_path = dirctory_path self.header_data = header_data self.delete_existing_files() def close(self): # デストラクタでも呼んでいる self.currnet_file_post_index = self.currnet_file_post_index+1 if self.f != None: self.f.flush() # 実際には、ファイルに書き込みしてくれないことがあったので追加。 self.f.close() self.f = None def delete_existing_files(self): p = Path(self.dirctory_path) r = self.filename+"*.csv" for existing_file_path in p.glob(r): print("削除します ", existing_file_path) os.remove(existing_file_path) def __del__(self): self.close() def open(self): if self.f == None: pass else: self.close() real_filename = self.dirctory_path + self.filename + \ "_{0:08d}.csv".format(self.currnet_file_post_index) os.makedirs(self.dirctory_path, exist_ok=True) self.f = open(real_filename, 'w', encoding='utf-8') self.csv_writer = csv.writer( self.f, delimiter=',', quotechar='"', lineterminator='\n') self.currnet_lines = 0 print("新規作成 ", real_filename) def writerow(self, input_data): ''' input_dataには、リストかタプルでデータを与える。 ''' if self.currnet_lines > self.max_lines: self.open() if self.header_data != None: self.writerow(self.header_data) self.csv_writer.writerow(input_data) self.currnet_lines = self.currnet_lines+1 class split_csv_reader: def __init__(self, dirctory_path, readfilename_wo_extention, skipHeader=False): self.filename = readfilename_wo_extention self.currentFileIndex = -1 self.fp = None self.csv_reader = None self.skipHeader = skipHeader self.dirctory_path = dirctory_path self.set_readFileNames() def set_readFileNames(self): self.readFileNames = [] p = Path(self.dirctory_path) r = self.filename+"*.csv" for existing_file_path in p.glob(r): self.readFileNames.append(existing_file_path) # ⃣print(self.readFileNames) def __iter__(self): # next()はselfが実装してるのでそのままselfを返す return self def __next__(self): if self.csv_reader is None: # 1個目のファイルを開く self.nextfile() try: value = next(self.csv_reader) return value except StopIteration: # 終端まで来たら、このStopIterationが投げられる。 try: self.nextfile() value = next(self.csv_reader) return value except StopIteration: # 次のファイルがなかったので、例外を投げてイテレータを終わる。 # ファイルがロックされている場合もここに来るので、問題になる可能性あり。 raise (StopIteration) except: # ここには来ない。 raise (StopIteration) def nextfile(self): self.currentFileIndex = self.currentFileIndex + 1 if self.fp is not None: self.fp.close() if self.currentFileIndex > len(self.readFileNames)-1: # 次のファイルはないので例外を投げる raise(StopIteration) else: self.fp = open( self.readFileNames[self.currentFileIndex], mode='r', newline='\n') self.csv_reader = csv.reader(self.fp, delimiter=',', quotechar='"') if self.skipHeader is True: next(self.csv_reader) # ⃣print(value) # 動作確認用プログラム if __name__ == "__main__": dirname = r"C:/lib_split_test/" # 最後はos.sepで終わるように指定する filename = r"lib_split_test" print("#書き込みのテスト") headerdata = ("#", "Name", "score") writer = split_csv_writer( dirname, filename, header_data=headerdata, max_lines=3) fake = Faker() for i in range(1, 10+1): # 最後の値は実行されないrange(1,10+1)で、1~10 data = [i, fake.name(), random.random()] writer.writerow(data) print(data) writer.close() print("#読み込みのテスト") reader = split_csv_reader(dirname, filename, skipHeader=True) for item in reader: print(item)
実行結果
(base) C:\dev\ > python C:\dev\lib_sprit_csv_reader_writer.py #書き込みのテスト 削除します C:\lib_split_test\lib_split_test_00000000.csv 削除します C:\lib_split_test\lib_split_test_00000001.csv 削除します C:\lib_split_test\lib_split_test_00000002.csv 削除します C:\lib_split_test\lib_split_test_00000003.csv 新規作成 C:/lib_split_test/lib_split_test_00000000.csv [1, 'Carol Martinez', 0.2993282973465532] [2, 'Monica Skinner', 0.47771227744058886] [3, 'Stephanie Zimmerman', 0.30639552562401595] 新規作成 C:/lib_split_test/lib_split_test_00000001.csv [4, 'Terry Williams', 0.2800113471343493] [5, 'Scott Grant', 0.8271274374443526] [6, 'Jose Daniels', 0.4170927481515181] 新規作成 C:/lib_split_test/lib_split_test_00000002.csv [7, 'Adam Austin', 0.2850528257749132] [8, 'Krista Williams', 0.9258438865231986] [9, 'Jared Adkins', 0.6205699038539508] 新規作成 C:/lib_split_test/lib_split_test_00000003.csv [10, 'Ryan Morales', 0.9635161039757013] #読み込みのテスト ['1', 'Carol Martinez', '0.2993282973465532'] ['2', 'Monica Skinner', '0.47771227744058886'] ['3', 'Stephanie Zimmerman', '0.30639552562401595'] ['4', 'Terry Williams', '0.2800113471343493'] ['5', 'Scott Grant', '0.8271274374443526'] ['6', 'Jose Daniels', '0.4170927481515181'] ['7', 'Adam Austin', '0.2850528257749132'] ['8', 'Krista Williams', '0.9258438865231986'] ['9', 'Jared Adkins', '0.6205699038539508'] ['10', 'Ryan Morales', '0.9635161039757013']
pythonの引数ライブラリargparse
argparseのサンプルコード。-から始まる名前にしてOptional引数にして、
action="store_true"をつけておけば、フラグとして利用できそう。
プログラム
import argparse if __name__ == "__main__": parser = argparse.ArgumentParser() # 必須引数(=位置引数)を追加 # type=intがない場合は文字列 parser.add_argument( "square", help="display a square of a given number", type=int) parser.add_argument( "base", help="display a square of a given number", type=int) # Optional引数 # 引数に -v があれば、args.verbosityはTrueになる parser.add_argument("-v", "--verbosity", help="increase output verbosity", action="store_true") # Optional引数 # とれる値の指定のある引数 parser.add_argument("-c", "--choices", type=int, choices=[0, 1, 2], help="increase output verbosity") args = parser.parse_args() # 引数の参照方法/値確認 print(args.square**2) print(args.base) if args.verbosity: print("verbosity turned on ", args.verbosity) else: print("verbosity turned off ", args.verbosity) print("choices:", args.choices)
-h の結果
(base) c:\dev>python a00_main.py -h usage: a00_main.py [-h] [-v] [-c {0,1,2}] square base positional arguments: square display a square of a given number base display a square of a given number optional arguments: -h, --help show this help message and exit -v, --verbosity increase output verbosity -c {0,1,2}, --choices {0,1,2} increase output verbosity
実行結果
(base) c:\dev>python a00_main.py -v -c 2 5 6 25 6 verbosity turned on True choices: 2
pythonの.formatに辞書を渡すときの書き方
pythonの.formatに辞書を渡すときの書き方。
dic={"key": "value"} "value: {key}".format(**dic)
複数の2クラス分類の一括学習
タイトルでは、わけがわからないと思うが、
1種類のデータに対して、2クラス分類問題が複数ある場合の学習。
整数dに対して、2の倍数かどうかと、3の倍数かどうか、・・・を例に学習してみた。
訓練データ形式
x : 8桁のビット整数。アンダーバー2つは、xベクトルの中での次元の番号。
y0:2の倍数かどうか。
y1:3の倍数かどうか。以降5,7,11の倍数かどうか。
x__0,x__1,x__2,x__3,x__4,x__5,x__6,x__7,y0,y1,y2,y3,y4 0,0,0,0,0,0,0,0,0,0,0,0,0 0,0,0,0,0,0,0,0,0,0,0,0,0 0,0,0,0,0,0,0,0,0,0,0,0,0 0,0,0,0,0,0,0,1,0,0,0,0,0 0,0,0,0,0,0,1,0,1,0,0,0,0 0,0,0,0,0,0,1,1,0,1,0,0,0 0,0,0,0,0,1,0,0,1,0,0,0,0 0,0,0,0,0,1,0,1,0,0,1,0,0 0,0,0,0,0,1,1,0,1,1,0,0,0 0,0,0,0,0,1,1,1,0,0,0,1,0 0,0,0,0,1,0,0,0,1,0,0,0,0 0,0,0,0,1,0,0,1,0,1,0,0,0 0,0,0,0,1,0,1,0,1,0,1,0,0 0,0,0,0,1,0,1,1,0,0,0,0,1
所見
- BatchNormalization はあったほうが収束が早い。
- ReLUは収束早い。(Sigmoidに比べて)
- ノード数を減らして、段数を増やすより、ノード数を増やしたほうが精度が高い(今回はノイズなしだから??)
- 分岐前のノード数は、分岐数の2倍以上あったほうが良い(?)
LEFT OUTER JOINの評価
LEFT OUTER JOINの評価
一瞬で終わる。メモリも食わない。
UNIQUE属性付けておくとさらに早い。
実施内容
データのテーブルと、クラス分け結果のテーブルのJoin。
クラス分け結果は適当に%演算で作った。
ソースコード
import sqlite3 from faker import Faker import random from datetime import datetime tic0 = datetime.now() con = sqlite3.connect(":memory:") con.isolation_level = None # None で自動コミットモード cur = con.cursor() cur.execute('PRAGMA temp_store=MEMORY;') cur.execute('PRAGMA journal_mode=MEMORY;') #cur.execute('PRAGMA rock_mode=OFF;') listsize = 100000 classsize= 128 sql_create_data = "CREATE TABLE data(number INTEGER UNIQUE, name TEXT, score REAL)" sql_create_class = "CREATE TABLE class(number INTEGER UNIQUE, label INTEGER)" sql_instert_data = "INSERT INTO data VALUES(?,?,?)" sql_instert_class = "INSERT INTO class VALUES(?,?)" sql_select_join = "SELECT data.number, data.name, data.score, class.label FROM data LEFT OUTER JOIN class ON data.number = class.number" sql_select_join_cl1 = "SELECT data.number, data.name, data.score, class.label FROM data LEFT OUTER JOIN class ON data.number = class.number WHERE class.label = 1 " #list_data = [[None] for i in range(listsize)] list_data = [None] * listsize list_class = [None] * listsize fake = Faker() print("データ準備 開始") for i in range(listsize): list_data[i] = [i, fake.name(), random.random()] list_class[i] = [i, i%classsize] print("データ準備 完了") cur.execute(sql_create_data) cur.execute(sql_create_class) print("テーブルの定義を表示") table_defs = cur.execute("SELECT * FROM sqlite_master WHERE type='table'") for item in table_defs: print(item) print("データの挿入") cur.executemany(sql_instert_data, list_data) cur.executemany(sql_instert_class, list_class) # ここからjoin時間計測 tic = datetime.now() cur.execute(sql_select_join) toc = datetime.now() print("テーブルの中身を表示") print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print("classが1のテーブルの中身を表示") cur.execute(sql_select_join_cl1) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print("join {0}件 処理時間 {1}".format(listsize, toc-tic)) print("全体処理時間 {0}件 処理時間 {1}".format(listsize, datetime.now()-tic0)) con.close()
結果
(base) C:\dev\SampleCodes\hello_sqlite>python outerjoin.py データ準備 開始 データ準備 完了 テーブルの定義を表示 ('table', 'data', 'data', 2, 'CREATE TABLE data(number INTEGER UNIQUE, name TEXT, score REAL)') ('table', 'class', 'class', 4, 'CREATE TABLE class(number INTEGER UNIQUE, label INTEGER)') データの挿入 テーブルの中身を表示 (0, 'Troy Wagner', 0.44436625795068907, 0) (1, 'Lee Robertson', 0.8527352596455694, 1) (2, 'Mark Franco', 0.9942993187450221, 2) (3, 'Joel Sandoval', 0.9462360044917911, 3) (4, 'Katherine Ho', 0.6177953257612685, 4) (5, 'Shannon Adams', 0.6044842942129696, 5) (6, 'Jacob Wong', 0.4513990366427033, 6) (7, 'Howard Bennett', 0.6643356684420646, 7) (8, 'Scott Mitchell', 0.5792325135939987, 8) (9, 'Joshua Tyler', 0.4882390253804837, 9) (10, 'Steven Day', 0.03463822764171387, 10) (11, 'Heather Hughes', 0.888992343863056, 11) (12, 'Margaret Thomas DDS', 0.402020535579534, 12) (13, 'David Rosario', 0.8354810420435498, 13) classが1のテーブルの中身を表示 (1, 'Lee Robertson', 0.8527352596455694, 1) (129, 'April Pittman', 0.48442848761646606, 1) (257, 'Mercedes Gallagher', 0.9811398290695581, 1) (385, 'Xavier Harvey', 0.39333389385880146, 1) (513, 'Laura Powell', 0.11691465694144565, 1) (641, 'Mrs. Lori Gibbs MD', 0.13424141037411286, 1) (769, 'Christina Jacobson', 0.7144345369983663, 1) (897, 'Gregory Lowe', 0.2939644032693347, 1) (1025, 'Michael Santos', 0.9319930754332403, 1) (1153, 'Olivia Montgomery', 0.3756360549631732, 1) (1281, 'Joseph Eaton', 0.7451317465818261, 1) (1409, 'Julia Adams', 0.5858535015316725, 1) (1537, 'George Kelley', 0.12250922691704258, 1) (1665, 'Patricia Johnson DVM', 0.09949616494939173, 1) join 100000件 処理時間 0:00:00 全体処理時間 100000件 処理時間 0:00:14.371519
Neural Network ConsoleのCrossEntropy損失関数(ロス関数)の使い方
Neural Network Consoleの損失関数(ロス関数)の使い方の記録。
画像処理系はSquareErrorでもいいが、カテゴリ系はそんなわけにもいかないので。
入力データ次第で、ある程度決まった形になるので、記録として残しておく。
CategoricalCrossEntropyを使う場合
ラベルは、複数値のカテゴリインデックス。1列。
affineで適当な列数に変換した後、softmax -> CategoricalCrossEntropy
BinaryCrossEntropyを使う場合
ラベルは1か0の2値。
OneHot形式の2列の場合、affineで2列に変換した後、softmax -> BinaryCrossEntropy
1列の0/1の場合、affineで1列に変換した後、sigmoid(softmaxからsigmoidに訂正) -> BinaryCrossEntropy
補足
参考資料。softmaxではなくsigmoidの例。
レイヤーの層を単純に深くしても、精度は向上しないことを確認する/Neural Network Consoleの使い方 - "BOKU"のITな日常
sqlite3のexecutemanyの動作確認
1回で10万件を挿入するのに、0.35秒。
別実行した1件ソートの繰り返しでは0.42秒。大した差ではないが、ループを組まなくていいメリットあり。
値を埋めたいところは、"INSERT INTO users VALUES(?,?,?)" のようにハテナにしておく。
リストのリストや、タプルのリストにしておけば、全件Insertしてくれるようす。
プログラム
import sqlite3 from faker import Faker import random from datetime import datetime con = sqlite3.connect(":memory:") con.isolation_level = None # None で自動コミットモード cur = con.cursor() cur.execute('PRAGMA temp_store=MEMORY;') cur.execute('PRAGMA journal_mode=MEMORY;') listsize = 100000 sql_create = "CREATE TABLE users(number INTEGER, name TEXT, score REAL)" sql_instert = "INSERT INTO users VALUES(?,?,?)" sql_select = "SELECT number,name,score FROM users ORDER BY number LIMIT 3" sql_select_last = "SELECT number,name,score FROM users ORDER BY number LIMIT 3 OFFSET {0}".format(listsize-3) list1 = [None] * listsize fake = Faker() print("データ準備 開始") for i in range(listsize): list1[i] = [i, fake.name(), random.random()] print("データ準備 完了") cur.execute(sql_create) print("テーブルの定義を表示") tmp = cur.execute("SELECT * FROM sqlite_master WHERE type='table'").fetchall() print(tmp) # ここからexecutemany時間計測 tic = datetime.now() print("データの挿入") cur.executemany(sql_instert, list1) # executemany時間計測終わり toc = datetime.now() cur.execute(sql_select) print("テーブルの中身を表示") print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print() cur.execute(sql_select_last) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print() print("executemany {0}件 処理時間 {1}".format(listsize, toc-tic)) con.close()
実行結果
(base) C:\dev\SampleCodes\hello_sqlite>python execmeny.py データ準備 開始 データ準備 完了 テーブルの定義を表示 [('table', 'users', 'users', 2, 'CREATE TABLE users(number INTEGER, name TEXT, score REAL)')] データの挿入 テーブルの中身を表示 (0, 'Dawn West', 0.5244752623689407) (1, 'Marvin Chambers', 0.8354440852719125) (2, 'Clinton Lowe', 0.4116042084368037) (99997, 'Aaron Conley', 0.795391969430207) (99998, 'Alyssa Brooks', 0.17316654138026266) (99999, 'Marisa Peterson', 0.018786705346994004) executemany 100000件 処理時間 0:00:00.350097