Learning Programming【プログラミング基礎勉強会2018】
概要
- Unix環境でのプログラミング方法,研究室の実験環境を学ぶ
- 自然言語処理で頻繁に使われる処理を題材としてプログラミング演習を行うことで,スムースに研究に取り組める力を養います
内容
- 言語処理100本ノック 2015
- 自然言語処理に関するプログラムを実際に作ってもらい,互いにコードレビューを行います。
- 問題に対する答えは一つではありません。どんな方法でも,無理矢理でも解いてみてください。
- ほか「研究に伴うプログラミング/実装」の周辺知識
2018年度
- 日時
- TBA
- 参加者
- 大竹、今野、佐藤(志)、佐藤(拓)、藤井、北山
- 書いたコード
- https://github.com/cl-tohoku/100knock-2018
このページの記録
- やったことだけ書く
- 以前の記録と同じことを書いても良い
- 何度も書かれているということは,それだけ重要だということを意味する
予定・記録
- 10/16(火)
- (57-59)
- 57
- グラフ化する際は表層形の重複を防ぐ工夫が必要
- 依存構造は係り元から係り先への向きにする流儀と逆にする流儀がある
- 59
- 再帰構造は停止/再帰部分をコメント書くなどして明示しておくと見やすい
- S式のParserもある
- https://www.nltk.org/_modules/nltk/tokenize/sexpr.html(NLTK)
- http://inforno.net/articles/2008/09/19/sexp-library-for-python
- 10/09(火)
- (54-56)
- ElementTree
- Elementオブジェクトのchildにアクセスする場合、elem[i]とするよりもelem.find(‘word’)のようにした方が可読性が良い
- findallはリストに一度格納するので(メモリ消費量が)怖い
- XPathで .//tag で指定する場合、すべての子要素から選択されるため、想定外のタグの重複に注意
- POS-taggingなどの前処理の方法は記録して統一したほうがいい(複数人で共同で作業する場合は特に)
- POS taggingに関しては、Standard Core NLPとspaCyで nlp.txt の解析結果が異なる箇所が15%位あった
- (55) 固有表現抽出の注意点
- NERが連続してた場合につなげる
- 1)Alan / Turing → Alan Turing
- 2)Joseph / Weizenbaum → Joseph Weizenbaum
- (56) 共参照解析の注意点
- 参照の入れ子に注意
- ある参照表現の中に別の代表参照表現があるケースがある
- 例)sentence 41 代表参照表現 -> the advantage
- sentence 25 参照表現 -> advantage of existing multilingual textual…
- sentence 25 代表参照表現 -> existing multilingual textual…
- sentence 36 参照表現 -> “ corpora ”
- 10/02(火)
- (50-53)
- wget
- オプション -nc / –no-clobber で上書きしない設定にできる
- 正規表現
- 文区切りのスペースは一つとは限らないケースがあるので、\s よりも \s+ としておいた方が良い
- 正規表現のパターンはキャッシュされる。パターン数が少なければ re.compile(pattern) をした場合とre.match(pattern, string) で速度差はほとんどない
- ルールベースで文区切りをすると、以下の場合にe.g.と人名で区切られてしまったりするので気を付ける
- 例) e.g. 人名(大文字スタート)
- 文区切りするなら、NLTKやspaCyを使ったほうがいい
- stripは区切り文字を文字集合として捉える
- hohogege.rstrip(‘ge’) の結果は hoho
- assertで自分の想定通りの動作になっているか確認
- if文
- できるだけ、not表現よりも==表現を使う
- if x != y vs. if not x == y であれば前者推奨(https://stackoverflow.com/questions/31026754/python-if-not-vs-if/)
- readlinesはメモリ消費が激しい
- ElementTreeのiterparse
- Standard Core NLPのオプション
- ssplit.eolonly:行末のみを文区切りと見なす
- もともと各行に1文が書かれているようなファイルに便利
- RISE
- JupyterでプレゼンができるCoolなTool
- http://codecrafthouse.jp/p/2017/05/jupyter-rise-live-presentation/
- 命名に悩んだとき
- メソッド名の参考ページ(https://qiita.com/KeithYokoma/items/2193cf79ba76563e3db6)
- クラス名の参考ページ(https://qiita.com/KeithYokoma/items/ee21fec6a3ebb5d1e9a8)
- 07/24(火)
- (49)
- itertoolsのpermutations, combinations, product
- 真偽値を返す関数の名前はis_〜、has_〜等、わかりやすいものにする
- 関数のデフォルト引数はimutableにすべし
- デフォルト引数をリストにしたいときは、一度Noneとしてから関数内でリストを作る
- 研究室の実験サーバの使い方
- 07/17(火)
- (46-48)
- Broke pipe error
- 標準出力をパイプでheadに渡すと、Broke pipeのエラーが出る
- エラーを消したいようであれば、sort 2>/dev/null | head 等とすることで、標準エラー出力を破棄できる
- あるインデックスの値でソートをしたい場合、以下のどちらでもできる
- sorted(hoge, key=lambda x: x[n])
- sorted(hoge, key=operator.itemgetter(n))
- list.sort()は破壊的、sorted(list)は非破壊的
- 関数化は重要。可読性に大きな影響が出る
- 文字列の初期化はNoneよりも空文字
- メモ化
- @lru_cache(maxsize=int, typed=Boolean)
- 上のデコレータを付けるだけで、関数のメモ化してくれる https://docs.python.jp/3/library/functools.html
- 同じ引数で関数が何回か呼び出されるようなケースの計算時間を減らすことができる
- LRU (least recently used) キャッシュ:最も使われていないデータから捨てられる。Memory Leak を防げる
- 07/10(火)
- (44-45)
- 依存構造木の矢印の向き
- 係り元から係り先への向き(係り受け構造と同じ方向)にする流儀と逆にする流儀がある
- pydot
- 表層系の重複を防ぐ工夫が必要
- 独自にユニークな番号を割り振る、Cabochaが文節に振るIDを使うなど
- 関数の引数やtuple定義などの括弧 (){}[]の内側では改行や空白は許容される
- 文字列の結合
- listにappendか内包表記してjoinする方が良いらしい (strはimmutable)
- pythonからの外部プロセス起動
- 外部プロセスを起動するときはsubprocessを使う
- 3.5以降は subprocess.run が追加されている
- 引数 check=True にするとエラー時に例外が発生する
- 引数 shell=True は非推奨(外部入力をそのまま指定した場合にコマンドインジェクションされる危険性があるため)
- X in Y の判定をする場合、Yにsetを使うと高速
- 辞書順
- 文字列のリストをソートすると文字コードに基づく辞書式順序になる
- 国語辞書の見出し順とは必ずしも一致しないことに注意
- 07/3(火)
- (41-43)
- groupby()が返すgroupのcopy
- わかりやすい命名
- なるべくメソッド化
- メンバ変数の取得・変更等
- for文・if文が深くなるのを回避
- re.split()
- 関数のキーワード引数
- strとrepr
- if 条件式:
- “”, [], 0, None
- A and BとA or Bの評価戦略
- Spacy
- 06/26(火)
- (40)
- クラスについて
- なぜ使うのか
- クラス変数、インスタンス変数、初期化、インスタンスメソッド
- メソッドの定義が不要なときはcollections.namedtupleを使っても良い
- has-a関係には「包含」を利用
- slots
- インスタンス変数を予め列挙して外から追加不能にする。メモリの節約になる。
- インスタンス変数が少量・固定で何度もインスタンス化をする時は利用して良いかも
- @classmethod
- strとrepr
- _strはユーザ向け、reprは開発者向けの文字列を返すようにする
- strはprint()等、reprはrepr()等で呼び出される
- print([instance1, instance2])等とするとreprが呼び出されてしまう
- “プライベート”変数
- __spam (先頭に二個以上の下線文字、末尾に一個以下の下線文字) という形式で定義
- @propertyをつけてspamという名前のgetterを定義すると、self.spamは外から変更不能のままアクセス可能になる
- cytoolz.nth
- cytoolz.nth(3, iterable)
- itertools.islice(iterable, 3, 4)
- more_itertools.nth(iterable, 3)
- PEP8を守ろう
- キーワード引数や、デフォルトパラメータであることを示すために使う = の両側にスペースを入れてはいけません
- argparseは重要
- stringクラスには便利な文字列定数が定義されている
- Docstring
- fstring
- str.format()より簡単
- Python3.6の新機能なので、後方互換性注意
- 06/12(火)
- (35-39)
- 数え上げ方いろいろ
- Counter, defaultdict, setdefaultなどなど
- Counter()を呼び出しまくると遅い
- %%timeitで時間測ると楽しい
- AppleGothicはダメ。ゼッタイ。
- 別にmatplotlibはオワコンではない
- pandas使えるようになりたい
- カーネル密度推定
- xkcd()で心にゆとりを
- 06/8(火)
- (29)
- Requests, urllibを用いてGETリクエストを送る
- エンドポイント・クエリパラメータ
- (30-34)
- 形態素解析はなぜ必要なのか
- 様々な形態素解析器
- Mecab, JUMAN, JUMAN++, knp※, KyTea, sudachi…
- ※knpは格解析器
- Python wrapperがある解析器:Mecab, JUMAN, knp
- 基本的には形態素解析後の出力をpythonで処理
- wgetコマンド
-O
output_documentの名前を指定
- 元データはdataディレクトリへ
itertools.groupby(iterable, key)
- key(lambda式など)のTrue/Falseに従いiterableをグルーピング
itertools.islice()
(復習)- リストじゃないけどiterableをスライスしたいな〜
- そこでislice
- 正規表現は遅い
- generatorの定義
- コードの可読性と速さの両立を意識して内包表記を使おう
- (%%heatでIPythonのスクリプト中において時間がかかる箇所を表示できる)
- ‘’組み込みの名前を上書きしない’’(復習)
tqdm(.notebook)
モジュール- 処理時間・進捗をいい感じに可視化してくれる
- toolz.itertoolz.sliding_window(復習)
- ★try_except(例外処理)
- 組み込み例外
- 自分で例外を定義することも可能
- 05/22(火)
- (22)-(25)
- 正規表現の後読みアサーション(と先読みアサーション)とは
- 否定もあるよ
- 後方参照で前側でマッチした内容を参照できるよ
- グループに名前を付けられるよ(付けなかった場合が
1
とか2
)
- グループに名前を付けられるよ(付けなかった場合が
- takewhile, dropwhile でイテレータの前部分をスキップしたり、後ろ部分を読まずに終わったりすることができる
- 05/15(火)
- (19)-(21)
pprint.pprint
: オブジェクトを整形して出力する- sort コマンド
-r
: 降順にソート-n
: 数値としてソート
collections.Counter(iterable)
:iterable
をイテレートして値をカウントした dictionary を生成する- 安定ソートとは
- 正規表現テスター https://regex101.com
- 正規表現の可視化 https://regexper.com
- JSON とは
gzip
モジュールjson
モジュールjson.load()
とjson.loads()
の違い
- wget コマンド
- gunzip コマンド
- zcat コマンド
- コマンドラインで完結する作業では Python を使わなくてもよい
re.MULTILINE
flag- 正規表現の特殊文字
- 貪欲マッチ
str.startswith()
- 05/08(火)
- (16)-(18)
- for x in iterable 内で list.append(f(x)) を繰り返すよりも内包表記 [f(x) for x in iterable] の方が(一般に)高速 & Pythonic
deque.popleft()
は $O(1)$$[^1]
≒expr 算術式
- split コマンド: ファイル分割
split -n l/N
: 行を分断せずに N 個のファイルに分割
diff -s
: 比較するファイルが同じであることを出力- iterator に対して
itertools.islice()
を繰り返すと中身を次々消費する math.floor(N / M)
=N // M
divmod()
more_itertools.divide()
sort | uniq
: ソートして重複行をつぶすsort -u
でも同じ
- 集合内包表記
{f(x) for x in iterable}
set(f(x) for x in iterable)
も結果は同じ.これはジェネレータ式(iterable)をset()
コンストラクタに代入したもの
set()
コンストラクタは引数をイテレートして集合を作るset('abc')
->{'a', 'b', 'c'}
sort(iterable, key)
:key
関数でiterable
をソートoperator.itemgetter
,operator.attrgetter
- sort コマンド
-s
安定ソート
- ソートの安定性
var = !command
: シェルコマンドの実行結果を Python の変数に代入 (Jupyter)!... $var ...
: Python の変数をシェルコマンドの引数として利用 (Jupyter)
- 04/24(火)
- (12)-(15)
cut
コマンド-f
で切り出すフィールド指定- デリミタはデフォルトでタブ文字
- コマンドによってデリミタとされる文字が異なるので注意
*
でイテラブルをバラすprint(*'abc')
はprint('a', 'b', 'c')
と等価
*変数
に「残りの値」を代入する (extended iterable unpacking)x, y = 'ab' # x == 'a', y == 'b'
x, *rest = 'abc' # x == 'a', rest == ['b', 'c']
- 以上詳細: https://qiita.com/eumesy/items/dda85b70d28da61663cb
file.seek()
paste
コマンドcat
コマンドzip()
は引数にイテラブルをとる- Python スクリプトファイルの作り方
chmod
コマンド- shebang
- スクリプトファイルとしてコマンドラインから呼び出されたときだけ実行したい部分は
if __name__ == '__main__':
ブロックに書く sys.argv
argparse
モジュール
- ★
itertools
モジュール- イテレータを便利に扱うためのモジュール
- レシピ集を含め必読
- さらなる追加関数群:
more_itertools
モジュール
file.readlines()
には気を付けましょうcollections.deque([iterable, maxlen])
- 双方向キュー / double ended queue
- 04/17(火)
- (08)-(11)
- map, filter, lambda
- filter + map より内包表記が好まれる
- ★iterable (list, str など) の要素を for で iterate したい場合は range() で index を iterate するのでは なく, 要素を直接 iterate する
- 変数名を capitalize するとクラス名に見える
- random.random(population, k) seq or set からの非復元抽出
- random.shuffle(list) list を破壊的に shuffle
- ★ipython: [tab] による補完(e.g., クラスメンバ名)
- ★ipython:
?
による docstring 閲覧 - ipython:
??
による(より詳しい) docstring(?)閲覧 - file から line を iterate する場合はとりあえず rstrip()
- UNIX コマンドの使い方を確認するオプション:
--help
wc -l
- ショートオプション (e.g.,
-l
) とロングオプション (e.g.,--lines
)- 頻繁に入力するコマンドはショートオプションを覚える
- 稀にしか入力しないコマンドはロングオプションで書くと可読性が高い
- 改行の数をカウントするアプローチ
- ファイル末尾に改行を
file.read()
,file.readlines()
の使い方に注意- ファイルサイズが非常に大きいとメモリに載り切らない
- tldr http://tldr.sh
- man ページの簡易版
- 新しいデータを処理する前にやること:ファイルの中身を確認する:
head
,less
with
文:file.close()
を自動的にやってくれる- 使わないことを明示したい場合,変数名に
_
を使うことが多いfor i, _ in enumerate(file):
diff
コマンド- 標準入出力
- IPython でセルの中身をファイルに書き出す:
%%file filename
tr
,sed
,expand
sed
の典型的な使い方:sed 's/old/new/g' file
- Python でのファイル処理では行を処理する前に
str.strip()
で改行を消すことが多い itertools.islice()
: スライスのイテレータ版
- 04/04(水) 14:40-16:10
- (03)-(07)
- ★スライス
x in s
は set が速い (O(1))- 時間計算量
- set の要素や dict の key はハッシュ化される
- 三項演算子 (的な表記):
true_value if cond else false_value
- 命名規則: PEP 8
- 組み込みの名前を上書きしない
- フォーマット文字列
- % (printf 形式の文字列書式化)
- ★str.format() (推奨), 仮引数に名前をつけられる
- f” (フォーマット済み文字列リテラル) (Python 3.6-)
- toolz.itertoolz.sliding_window
%timeit
on Jupyter で時間計測できる- 高度な話題
- escape sequence for shell
- 03/30(金) 10:30-12:00
- (00)-(03)
- ★スライス
- 文字列の連結
reversed()
str.join()
list.reverse()
enumerate()
- 0以外の数値は True になる
- リスト内包表記
- 高度な話題
- ジェネレータ
- イテレータ
- 遅延評価
- ★
zip()
- 短いほうに合わせる
- ★関数名に ? を付けると仕様を表示できる
min()
- ★
str.format()
- ★
str.replace()
- ★
str.split()
- ★
str.strip()
- ファイルを読み込むときによく使う
str.lstrip()
str.rstrip()
- lambda 式
map()
- 03/26(月)
- (準備)
- 100本ノック初回(esa)
- jupyterlab インストール: conda install -c conda-forge jupyterlab
- git 周りの設定: ~/.ssh/config に ssh 公開鍵 path, git config –global 系
- GitHub 当該ディレクトリに個人用ブランチ&ディレクトリ作成
- 03/??
- (課題図書)
- Python
- Shell
- 『新しいLinuxの教科書』
TA
研究室の実験環境など
- 内部資料 (2016年版)
Pythonプログラミングのチュートリアル
100本ノックコーチ割り当て
場所 | 担当者 |
---|---|
第1章: 準備運動 | 清野 |
第2章: UNIXコマンドの基礎 | 横井 |
第3章: 正規表現 | 阿部,白井 |
第4章: 形態素解析 | 伊藤,田上 |
第5章: 係り受け解析 | 浅野,高橋 |
第6章: 英語テキストの処理 | 栗林 |
第7章: データベース | 佐々木 |
第8章: 機械学習 | 鈴木,赤間 |
第9章: ベクトル空間法 (I) | 塙 |
第10章: ベクトル空間法 (II) | 吉成,中村 |
代打 | 水本,横井,松林,O |
参考書
- TBA
過去の記録
Last-modified: 2023-02-14 (Tue) 22:57:03 (732d)