言語処理100本ノック #073
# 73. 学習
72で抽出した素性を用いて,ロジスティック回帰モデルを学習せよ.
準備:scikit-learn をインストール
参考 👉 Installing scikit-learn — scikit-learn 0.22.1 documentation
$ pip install -U scikit-learn ... Successfully installed joblib-0.14.1 scikit-learn-0.22.2
どうやって使うのかなと調べていたら、どうやらベクトルを食わせないといけないっぽい???(他の人の書いた答えの丸写しはしたくないなあと思って、他の人の書いた答えは見ていない)
たしか、お魚の本にベクトルの作り方が載っていたような気がするので、見てみよう。
お魚の本 (ゼロから作る Deep Learning ② 自然言語処理編)
2.3 カウントベースの手法 (2.3.1 コーパスの下準備):正規表現が分からない
p.64 によれば、 re.split(r'(\W+)?', text)
というように正規表現を使えば、単語単位の分割がスッキリできるはずが……
words = re.split(r'(\W+)?', text) ↓ ['', None, 'y', None, 'o', None, 'u', ' ', '', None, 's', None, 'a', None, 'y', ' ', '', None, 'g', None, 'o', None, 'o', None, 'd', None, 'b', None, 'y', None, 'e', ' ', '', None, 'a', None, 'n', None, 'd', ' ', '', None, 'i', ' ', '', None, 's', None, 'a', None, 'y', ' ', '', None, 'h', None, 'e', None, 'l', None, 'l', None, 'o', '.', '', None, '']
なんか1文字ごとのぶつ切りにされてしまい、うまくいかない。 re — 正規表現操作 — Python 3.8.2 ドキュメント によると
\w
Unicode 単語文字にマッチします。これはあらゆる言語で単語の一部になりうるほとんどの文字、数字、およびアンダースコアを含みます。
\W
単語文字ではない任意の文字にマッチします。これは \w の反対です。
とのことで、\w
を使ったら良いのか?
words = re.split(r'(\w+)?', text) # ↓ #['', 'you', '', None, ' ', 'say', '', None, ' ', 'goodbye', '', None, ' ', 'and', '', None, ' ', 'i', '', None, ' ', 'say', '', None, ' ', 'hello', '', None, '.', None, '']
さらに、
(…)
丸括弧で囲まれた正規表現にマッチするとともに、グループの開始と終了を表します。+
直前の正規表現を 1 回以上繰り返したものにマッチさせる結果の正規表現にします。例えば ab+ は ‘a’ に 1 つ以上の ‘b’ が続いたものにマッチし、単なる ‘a’ にはマッチしません。?
直前の正規表現を 0 回か 1 回繰り返したものにマッチさせる結果の正規表現にします。例えば ab? は ‘a’ あるいは ‘ab’ にマッチします。
なんかよく分からない。
re.split(r'(\W+)?', text)
は、「『単語文字ではない文字を1回以上繰り返したグループを0回か1回繰り返す』を区切り文字とする」???
?
を抜いて、re.split(r'(\W+)', text)
は、「『単語文字ではない文字を1回以上繰り返したグループ』を区切り文字とする」なら、
words = re.split(r’(\W+)’, text) # ↓ #[‘you’, ‘ ‘, ‘say’, ‘ ‘, ‘goodbye’, ‘ ‘, ‘and’, ‘ ‘, ‘i’, ‘ ‘, ‘say’, ‘ ‘, ‘hello’, ‘.’, ‘’]
となり、無 ''
と 空白 ' '
を除けば目当てのものが手に入りそう。ちなみに、逆の \w
を使って、re.split(r'(\w+)', text)
は、「『単語を1回以上繰り返したグループ』を区切り文字とする」なら、
words = re.split(*r*’(\w+)’, text) # ↓ #[‘’, ‘you’, ‘ ‘, ‘say’, ‘ ‘, ‘goodbye’, ‘ ‘, ‘and’, ‘ ‘, ‘i’, ‘ ‘, ‘say’, ‘ ‘, ‘hello’, ‘.’]
無 ''
が切られる位置が違うけど、だいたい同じ結果になる。
なんかもう困ったので、このリストから無 ''
と 空白 ' '
を除くでいいか。
words = [w for w in re.split(r'(\w+)', text) if w not in ['', ' ']] # ↓ #['you', 'say', 'goodbye', 'and', 'i', 'say', 'hello', '.']
とりあえず目当てのものは手に入った。
それから、
corpus = np.array([word_to_id[w] for w in words])
このリストの内包表記ってやつ、便利だなあ!(早速、リストから無 ''
と 空白 ' '
を除くのに使った)