【C++】範囲for文の変数宣言autoは省略できた
たまたま出会った下記の範囲for文について、きちんとコンパイルされ動作されているのを見て、軽く調べたメモ。
std::vector<int> x{1,2,3}; for(i : x){ // iの変数宣言部に型指定が無い std::cout << i << std::endl; }
結論
昔はサポートされており、コンパイラのほうでよしなにしてくれた。
C++17より未サポートとなり、以降はコンパイル時に怒られる。
使わないほうが安全。
詳細
検索すると下記のstackoverflowのページが引っ掛かった。 stackoverflow.com どうやら、C++17より未サポートになったようだ。
gccのバージョンを変えながらwandboxで実際に動かしてみたがどうやらそのようだ。
gcc6からC++17をサポートしており、stackoverflowの内容とも一致している。 gcc.gnu.org
【読書ノート】やさしく学ぶ機械学習を理解するための数学のきほん
機械学習に興味を持っているが、きちんと学習した経験がなかったため、
機械学習の入門書の1つとして紹介されていた、本書を手に取りました。
『やさしく学ぶ 機械学習を理解するための数学のきほん アヤノ&ミオと一緒に少しずつ学ぶ 機械学習の理論と数学、実装まで』
やさしく学ぶ 機械学習を理解するための数学のきほん | マイナビブックス
先日一通り読み終えたため、記録として本書の感想と自分のメモを記しておこうと思います。
本書の構成
全5章構成
1章は導入として、機械学習の基本的な紹介
2章では回帰問題、3章では分類問題を題材として、具体的なアルゴリズムの紹介
4章はモデルの評価について
5章で、2~4章の内容を実際にpythonを用いて実装する
という内容になっています。
読了時間
およそ10時間(4日かけて読みました)
1~4章までは、2日間で一気に読み終えました。
軽くメモを取りながら6時間程度だったと思います。
5章では、ソースコードを見ながら、実際に自分も実装・動作させながら2日かけて読みました。
5章だけで4時間かからない程度だったと思います。
Anacondaにデフォルトで入っているライブラリのみで動かせたので、このために環境を構築する必要はありませんでした。
感想
とても読みやすかったというのが一番の感想です。
2人の会話形式になっていて、文章量が多くないのですらすら読めました。
内容も、今まで機械学習にあまり触れたことがない人向けで、理解に苦労したところはあまりありませんでした。
理系として高校数学を学んでいた人であれば、数学面でも特に理解に苦しむことはないと思います。
(私も微分の計算から離れて久しいですが、思い出しながら読み進められました)
いきなり機械学習の分厚い本を読むのに抵抗がある人が、初めの一歩を踏むのにちょうどよいと思います。
読書メモ
私が本書を読みながらメモした内容です。
あくまで私のメモで、本書からコピペしたものではないので、間違っている点などがあるかもしれませんので、
内容の参考程度としてください。
2章 回帰
手順は、予測のための関数f(x)を定義して、そのパラメータθを学習データから求める
・用語
パラメータθ:未知数、推定数、求めていく値
目的関数:出力を最大/最小にしたい関数 これを果たすのを最適化問題という
学習率η:最急降下法の場合は、次のxの更新度合が決まる
ミニバッチ法:100個の学習データから一部抜き出した集合作ってパラメータの更新を繰り返すやり方
・最小二乗法
各学習データごとの誤差の和
・最急降下法、勾配降下法
パラメータに対して微分を用いて更新式を求める。傾きを見てどちらに近づけるかを判断する
欠点として、全学習データで計算するため計算量が多くて遅い、局所解につかまる
・多項式回帰
回帰関数の次数を増やすとよりフィットする、が過学習が発生するリスクも上がる
結局パラメータごとに更新式を求めるだけ
・重回帰
入力(変数)xをn個に->xをベクトルに
・確率的勾配降下法
勾配降下法でパラメータ更新式ですべての誤差でやってたのを
1つor数個を毎回ランダムに選んで更新する
3章 分類
分類の目的は境界線(決定境界)を見つけること
実際は重みベクトルを学習によって見つけて、その法線ベクトル(重みベクトルに垂直な線)が境界線となる
そのほかの分類アルゴリズム:SVMサポートベクタマシン
二値分類だけでなく多値分類も
・用語
識別関数:入力からラベルを出力する関数
ラベルの定義:更新式が単純になるようにきめてよい
・パーセプトロン (単層パーセプトロン)
複数の入力に対し重みをかけて総和を出力するモデル->ベクトル(入力と重み)同士の内積になる
重みベクトルの更新式がでる。ただのベクトル加算
欠点として、線形分離可能な問題しかとけない
・ロジスティック回帰
識別関数として、シグモイド関数を使用
シグモイド関数によって分類結果を確率として考えて決定
境界を定めるアルゴリズム
目的関数は、尤度関数L これを最大にするパラメータを探す
線形分離不可能な時の場合は、入力xの次数を増やしたθxを用いる
・対数尤度関数
尤度関数のままだと、数が小さくなりプログラム上の精度に課題、掛け算が計算しずらいなどのため、対数をとる
4章 評価
・交差検証
学習用とテスト用に分割するやり方。K分割交差検証はK分割してK-1が学習用、テスト用1を変えて繰り返す
回帰の場合は、テストデータに対して、平均二乗誤差(MSE)が少なければいい
分類の場合は、精度:Accuracyだけではだめ。
適合率:Precision 決定境界の片方の領域だけ注目して評価
再現率:Recall 片方のデータだけ注目して評価
これらの総合評価としてF値:Fmeasure どちらかが極端に低いと極端に低く出るような値 重みをつけないのがF1値で数学的には調和平均
・正則化
過学習の対策の1つ
目的関数に正則化項を加える方法、パラメータが大きくなりすぎないようにする働き
目的関数に加えるので、そこから微分して求める更新式も変わる
・学習曲線
データの個数と精度の関係をプロットしたグラフ
未学習状態:ハイバイアス データ個数を増やすと学習用データでの精度が下がっていき上がらないテスト用データの精度に近づく状態
過学習状態:ハイバリアンス データ個数を増やしても学習用データの精度が高いまま、テスト用データの精度が上がらない状態
"クロスワード辞典"の検索結果をスクレイピング
Webサイト"クロスワード辞典"の検索結果のスクレイピングを行った。
クロスワード辞典
言語&ライブラリ : python , requests , BeautifulSoup
ソースコード
requestsを使用して、検索結果のhtmlを取得
import requests def search(search_word): """クロスワード辞典 検索の検索結果のhtmlを返す関数 Args: serch_word (str) :検索キーワード returns: html (str) :検索結果のhtml """ url = 'http://cross.matrix.jp/search.cgi' print(search_word) req = requests.post(url, {'key':search_word.encode('euc-jp')}) return req.text
取得したhtmlに対してBeautifulSoupでスクレイピング。
ここでは、検索結果を引数で返すようにした。
from bs4 import BeautifulSoup def get_search_result(html): """検索結果のヒット数を返す Args: html (str) :クロスワード辞典の検索結果ページのhtml returns: num (int) :ヒット件数 words_list :検索で出てきた単語 ['カタカナ',['漢字']] """ try: soup = BeautifulSoup(html, "html.parser") words_list=[] str = soup.find("div", class_="search-result") print(str) if str == None: return 0 ,words_list text = str.get_text() i = -1 for line in text.splitlines(): i+=1 if i == 0: continue data = line.split("\xa0") words=[] words.append(data[0]) words.append(data[2].split("、")) print(words) words_list.append(words) return i ,words_list except urllib.error.URLError as e: print(e) return 0
実行例
■検索語 ねこ ■検索結果 <div class="search-result"> ネコ : 猫 <a class="edit" href="entry.cgi?rm=edit&keyword=%A5%CD%A5%B3&search=%A4%CD%A4%B3">(編集)</a><br/> </div> ■返り値 ['ネコ', ['猫']]
一枚謎の自動生成をやってみる
謎解きゲームの序盤で出てくるイラスト系の一枚謎を自動生成するスクリプトを作成してみた。
技術的な内容としては、webサイトのスクレイピングの初歩を学ぶことができた。
言語&ライブラリ : python , requests , BeautifulSoup , OpenCV
1. 一枚謎とは?
リアル脱出ゲーム( (株)SCRAPの商標 )を筆頭に、謎解きゲームがここ数年で広がりを見せている。
私も2年ほど前に友人に誘われて公演に参加したのをきっかけに、今では月2回ほどのペースで参加するようになった。
その中で、公演の序盤によく出てくる、紙1枚で問題が完結しているものを一枚謎と言ったりする。
パズル系の問題を除けば、基本的には閃けば数秒で回答できるものがほとんどである。
( TwitterなどWebで公開されている解き直しまくる系一枚謎は例外 )
たとえばこんな感じ(※自動生成ではありません。クオリティはお察しください)
例1
引用
https://www.ac-illust.com/main/detail.php?id=92571
例2
引用
※回答はページ最後に
言ってしまえば親父ギャグのような謎。
今回作成したのは、例2のような複数の画像をつなげる解き方の謎を自動生成するもの。
単語をインプットすると、それが回答となるような親父ギャグ謎を自動生成するスクリプト。
2. 手順
処理手順は3step
- インプットされた単語を、"意味の通じる"単語に分割
- 分割された単語に適合する画像を検索し取得
- 取得した画像を合わせて一枚の謎に
step1,step2はスクレイピング、step3は画像処理を活用。
3. step1 単語の分割
機械的に単語を分割するだけなら特に工夫は必要ないが、今回は、"意味の通じる"単語に分割する必要がある。
ここでのポイントは、ある文字列が"意味の通じる"単語であるかをどう判定するかということ。
ここでは"意味が通じる"を具体的に以下のように定義した。
- 世の中に存在する単語である
- 人によって言い回しが変化することがない
- 万人が知っている単語である
1つ目は当然のごとく、存在しない単語はただの文字列である。
2つ目、人や地域によって言い方が異なるような単語は、その地域でしか通じないため避ける。
(例:絆創膏 = サビオ、カットバン、バンドエイド、リバテープ ...)
3つ目、難しい単語や専門用語など、一部の人しか知らないような単語は避ける。
小中学生でもわかるような義務教育レベルの単語が理想。
ただし、3つ目の判断方法が難しい。
試して見た結果、普段使用しないような単語や、単語でない文字列も補完されて近い単語がサジェストされてしまった。
そこで今回利用したのは、以下のページ。
謎解きや謎製作で単語の検索で活用させてもらっているページ。
wikipediaやgoogleと比べ、マニアックな単語が少なく、補完もされない。
otoge-programing.hatenablog.jp
例
■imput
"いんすうぶんかい"
■output
['いん', 'すう', 'ぶん', 'かい']
['イン', '数', '文', '貝']
クロスワード辞典では、複数の漢字が出てくることがあるため、とりあえず先頭の漢字を使用
例 : ['カイ', ['貝', '下位']] →"貝"
これにより、ひとつの単語を複数の単語に切り分けることができた。
4. step2 画像検索
次に、それぞれの単語に対し、対応する画像を取得する。
例: ['イン', '数', '文', '貝']
当初は、例2と同じくみんな大好き"いらすとや"さんを使用するつもりでいたが、上のような単語単体で検索しても、思ったような画像が探せずに断念。
"いらすとや"の画像を用いた一枚謎をSNS等で拝見していたが、画像選びにも人間の手(センス)が求められることを学んだ。
そのため、多少カオスになることを覚悟しつつ、今回はみんな大好き?google画像検索を利用することに。
<具体的なスクレイピング方法は別記事にて記載予定>
例: ['イン', '数', '文', '貝']
<img alt="「イン」の画像検索結果" height="84" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-Ei0NWjEI5Qnd4MiAzw8X2FLQSo5OkLPLfyObM60ZFZt1ZLzQYnI7gWxm" width="150"/>
https://www.google.co.jp/search?q=%E6%95%B0&tbm=isch
<img alt="「数」の画像検索結果" height="123" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTpxoKtVPiUuxGiiw-9OwLnuDcBVTv-XvgOsftRueD11XGkIba__bOK1A" width="124"/>
https://www.google.co.jp/search?q=%E6%96%87&tbm=isch
<img alt="「文」の画像検索結果" height="123" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS6rAO4WBOF8CXimIF8DC83zOScFiIL8Z-SMfsCRP3Ovcr7ok3YzQBU0w" width="124"/>
https://www.google.co.jp/search?q=%E8%B2%9D&tbm=isch
<img alt="「貝」の画像検索結果" height="114" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSnEhxGlUaj-_3lW54d4FJ_XeQDZv6F-6hdFYcnbGkaYvf7ahZycGywEw" width="114"/>
5. step3 一枚謎に合成
※未実装
ひとまずstep2で取得した画像を手動で並べるとこちら。
例
- "イン"で検索すると東横インの画像が真っ先に出てくるのか
- 数の画像で、答えがそのまま出てきてしまっている
等つっこみどころは多々あるが、ひとまず形にはなった。
まとめ
所感
思いつきで作ったこともあり、とても一枚謎のクオリティに達しているとは言いがたいが、google画像検索のおかげで、いい感じにカオスなものが生成されて、適当な単語を生成するだけで面白い感じになるので、個人的には満足。ただ、step1,2どちらも改良の余地あり。
スクレイピングについて、手を動かして学ぶことができた。
わかっていたことだが、謎製作はクリエイティブな作業である。
おまけ
上記スクリプトで自動生成した謎をいくつか。
分かるか!といいたくなるようなもの多数なので、ネタとして見てください。
おまけ1
一言:まだまともな問題
おまけ2
一言:"けん"で3番目の画像がでてきてしまうのか...
おまけ3
一言:四字熟語。人物が写ってしまっている部分は別途隠しています。
おまけ4
一言:ライトノベル作品。入力単語を前から機械的に単語を分割するだけのやり方だと、長い単語はうまくいかない。
おまけ5
一言:音ゲーマーなら知っている(かもしれない)単語。現状のやり方だと、カタカナ(英語)が入ってもあまりうまくいかない。
お付き合いいただき、ありがとうございました。
回答一覧
例とおまけの回答となります。
例1 ひよこ
(ひ が横になっている)
例2 ネットワーク
(網、仕事の画像。それぞれ英語でネット、ワーク)
おまけ1 水泳
(水、エイの画像)
おまけ2 埼玉県
(差異、玉、県の画像)
おまけ3 意気投合
(息、塔、業の画像。人の写真も遠慮なくサジェストしてくるgoogle先生)
おまけ4 ノーゲームノーライフ
(NO,ゲーム,らい の画像。"らい"で単語として認識され、ライ麦パンが画像検索された様子)
おまけ5 猫叉マスター
(猫、股、鱒の画像。魚の種類で単語認識されると、魚の種類当てクイズに変化してしまう課題)