■目次
PythonWindows上に開発環境を構築Linux上に開発環境を構築matplotlib(グラフ描画)数式の表現数学の復習数学とグラフ回帰による予測Pandas(データ解析支援)OpenCV(画像処理)skimage(画像処理)MeCab(形態素解析)Janome(形態素解析)機械学習scikit-learn(機械学習)scikit-learn(機械学習)でアヤメの分類scikit-learn(機械学習)でワインの品質判定scikit-learn(機械学習)で気象データを解析scikit-learn(機械学習)での最適なアルゴリズムやパラメータを探すscikit-learn(機械学習)で言語を判定scikit-learn(機械学習)で数字を判定scikit-learn(機械学習)でスパムメールを判定TensorFlow(ディープラーニング)TensorFlow+Keras(ディープラーニング)TensorFlow+Keras(ディープラーニング)で手書き数字の判定TensorFlow+Keras(ディープラーニング)で写真に映った物体を認識TensorFlow+Keras(ディープラーニング)でカタカナを判定TensorFlow+Keras(ディープラーニング)で画像を判定TensorFlow+Keras(ディープラーニング)で文章を分類機械学習メモWindowsアプリケーション2017年2月時点のメモ
■Python
■入門 以下が詳細で解りやすい Python入門 - @IT https://www.atmarkit.co.jp/ait/series/12963/ Pythonプログラミング入門 - Pythonプログラミング入門 documentation https://utokyo-ipp.github.io/ ■応用 Pythonのアンダースコア( _ )を使いこなそう! - LSC PSD - Medium https://medium.com/lsc-psd/pythonic%E8%89%B2%E3%80%85-python%E3%81%AE%E3%82%A2%E3%83%B3%E3%83%80%E3%... AIエンジニアが気をつけたいPython実装のノウハウ・コツまとめ - Qiita https://qiita.com/sugulu/items/c0e8a5e6b177bfe05e99 【Python】いい書き方と悪い書き方を知って中級者を目指す - Qiita https://qiita.com/_masa_u/items/b21c493a82e8aba8993f Pythonのオブジェクト指向プログラミングを完全理解 - Qiita https://qiita.com/kaitolucifer/items/926ed9bc08426ad8e835 【2020年新人研修資料】ナウでヤングなPython開発入門 - Speaker Deck https://speakerdeck.com/stakaya/2020nian-xin-ren-yan-xiu-zi-liao-nauteyankunapythonkai-fa-ru-men 朝飯前に学べる!便利なPythonのヒント100選【前編】 - Qiita https://qiita.com/baby-degu/items/05cf809d4d992923020d 朝飯前に学べる!便利なPythonのヒント100選【後編】 - Qiita https://qiita.com/baby-degu/items/532bea7be058c35f61a8 全てがTypeScriptで動く「クラウド郵便 atena」を支える技術スタック https://zenn.dev/n1nc/articles/atena-system-architecture ■数値を文字列と結合して表示 a = 10 print('a = ' + str(a)) ■配列 targets の内容をすべて表示 map_result = map(str, targets) result = ', '.join(map_result) print('[' + result + ']') ■配列 targets の要素数を表示 print(len(targets)) ■map 【Pythonステップアップ!】高階関数mapの便利な使い方 | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト https://www.sejuku.net/blog/24759 ■lambda Pythonのlambdaって分かりやすい - Qiita https://qiita.com/nagataaaas/items/531b1fc5ce42a791c7df ■画像 PythonでPowerPointの各ページを画像ファイルにする - Qiita https://qiita.com/natsutan/items/2487e24fe3f31569b40d ■クロスプラットフォームアプリ Pythonだけでクロスプラットフォームなアプリを作れるFletについて - Qiita https://qiita.com/NasuPanda/items/48849d7f925784d6b6a0 ■ゲーム 「ゲーム制作するなら、これだけは覚えておいたほうがいい」 プログラミングする上で重要な「対数」の考え方 - ログミーTech https://logmi.jp/tech/articles/326705 Pythonなら3Dゲームも作れる!まずは空間にモノを置いてみよう | 日経クロステック(xTECH) https://xtech.nikkei.com/atcl/nxt/column/18/02075/052400001/ ■数学 数学×Pythonプログラミング入門 - @IT https://atmarkit.itmedia.co.jp/ait/series/24243/ 統計・機械学習の理論を学ぶ手順 - Qiita https://qiita.com/kueda_cs/items/28008db6491c71ac5659 数学を楽しみながら独学できる本、究極の5冊 | 独学大全 | ダイヤモンド・オンライン https://diamond.jp/articles/-/301387 ■機械学習 Pythonでニューラルネットワークを書いてみよう:ニューラルネットワーク入門 - @IT https://atmarkit.itmedia.co.jp/ait/articles/2202/09/news027.html みんな、とにかくオセロAIを作るんだ - Qiita https://qiita.com/Nyanyan_Cube/items/1839732d7bdf74caff21 機械学習が独学できる日本語Youtube難易度別まとめ - Qiita https://qiita.com/fujimr_19xx/items/f85d08a260ef7e0df655 モナリザがトランプ大統領のように動き出すFirst Order Motion Modelを試してみる - Qiita https://qiita.com/jun40vn/items/722bd4675246eb7eac46 第1回 初めてのニューラルネットワーク実装、まずは準備をしよう ― 仕組み理解×初実装(前編):TensorFlow 2+Keras(tf.keras)入門 - @IT https://atmarkit.itmedia.co.jp/ait/articles/1909/19/news026.html Pythonで作る人工生命 | 日経クロステック(xTECH) https://xtech.nikkei.com/atcl/nxt/column/18/01996/
■Windows上に開発環境を構築
■XAMPPでPythonを動作させるメモ Python | Pythonのダウンロードとインストール https://www.javadrive.jp/python/install/index1.html 今回はAnacondaを使ってインストールした Anacondaのインストール | Python入門 https://www.javadrive.jp/python/install/index5.html Anaconda で Python 環境をインストールする - Qiita https://qiita.com/t2y/items/2a3eb58103e85d8064b6 【Python】非エンジニアWindowユーザー向けのAnacondaインストールの手順 https://tonari-it.com/python-anaconda-install/ ■コマンプロンプトで動作確認 コマンドプロンプトから、以下を実行してインストールを確認 >C:\Users\refirio\Anaconda3\python --version Python 3.7.3 以下のようにして直接命令を実行できる >C:\Users\refirio\Anaconda3\python >>> print('Hello Python') Hello Python >>> quit() hello.py を作成して以下の内容を記述
print("Hello! Python.")
以下のようにしてプログラムを実行 >C:\Users\refirio\Anaconda3\python hello.py Hello! Python. ■CGIで動作確認 あらかじめ、XAMPPをインストールしておく C:\xampp\apache\conf\httpd.conf を編集し、Apacheを再起動する
AddHandler cgi-script .cgi .pl .asp ↓ AddHandler cgi-script .cgi .pl .asp .py
test.py を作成して以下の内容を記述
#!C:\Users\refirio\Anaconda3\python # -*- coding: utf-8 -*- print("Content-Type: text/html\n") print("Hello World")
以下のようにしてプログラムを実行 http://localhost/test/test.py ■文字化け対策 Python 3.x - Pythonにて文字化けが発生します|teratail https://teratail.com/questions/130659 PythonのCGIで日本語が文字化けしたときの対処法 - Qiita https://qiita.com/eleven-junichi2/items/f3fcb6abe7fe21a4d89a
#!/Users/refirio/Anaconda3/python # coding: utf-8 # -*- coding: utf-8 -*- import sys,io sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') print("Content-Type: text/html; charset=UTF-8\n") print("<!DOCTYPE html>") print("<html>") print("<head>") print("<meta charset=\"utf-8\">") print("<title>Python</title>") print("</head>") print("<body>") print("<h1>Python</h1>") print("<p>これはPythonの実行結果です。</p>") print("</body>") print("</html>")
■pip(Pythonのパッケージ管理システム) pipとpipenvとpoetryの技術的・歴史的背景とその展望 - Stimulator https://vaaaaaanquish.hatenablog.com/entry/2021/03/29/221715 Python - Pythonの「pip」と「pip3」は何が違う?|teratail https://teratail.com/questions/46066 PythonでOpenCVをはじめる(Windows10、Anaconda 2018.12、Python3.7.1、OpenCV4.0.0) - Qiita https://qiita.com/SatoshiGachiFujimoto/items/94da93f88578b87f6a89 Windowsの検索機能などから「Anaconda Prompt」を開く 以下のようにして、Pythonとpipのバージョンを確認できる >python --version Python 3.7.3 >python -m pip -V pip 19.1.1 from C:\Users\refirio\Anaconda3\lib\site-packages\pip (python 3.7) pipでライブラリをインストールした場合、以下のようにすればPythonプログラムの簡易な動作確認が >python Python 3.7.3 (default, Apr 24 2019, 15:29:51) [MSC v.1915 64 bit (AMD64)] :: Anaconda, Inc. on win32 Type "help", "copyright", "credits" or "license" for more information. >>> print('Hello!') Hello! >>> quit Use quit() or Ctrl-Z plus Return to exit >>> exit() ■Excelを操作 ※未検証 ゼロからはじめるPython(65) PythonでExcelを操作する二大手法を比較しよう | マイナビニュース https://news.mynavi.jp/article/zeropython-65/ PythonによるExcel自動化は何がスゴい?インストールからコードサンプルまで実践詳解 |ビジネス+IT https://www.sbbit.jp/article/cont1/46162 ■OpenCV PythonでOpenCVをはじめる(Windows10、Anaconda 2018.12、Python3.7.1、OpenCV4.0.0) - Qiita https://qiita.com/SatoshiGachiFujimoto/items/94da93f88578b87f6a89 Pythonを用いた画像処理(openCV,skimage) - Qiita https://qiita.com/taka_baya/items/453e429b466ffaa702c9 >pip install opencv-python Successfully installed opencv-python-4.1.1.26 >pip install opencv-contrib-python Successfully installed opencv-contrib-python-4.1.1.26 >python Python 3.7.3 (default, Apr 24 2019, 15:29:51) [MSC v.1915 64 bit (AMD64)] :: Anaconda, Inc. on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import cv2 >>> cv2.__version__ '4.1.1' >>> exit() インストールできたが、CGIからサンプルプログラムを実行するとエラーになった エラーの内容は以下のとおり
[Sun Sep 22 14:11:11.801745 2019] [cgi:error] [pid 13672:tid 1960] [client ::1:52117] End of script output before headers: test.py, referer: http://localhost/~raspberrypi/cgi/opencv/ [Sun Sep 22 14:11:11.801745 2019] [cgi:error] [pid 13672:tid 1960] [client ::1:52117] AH01215: ImportError: numpy.core.multiarray failed to import\r: C:/localhost/home/raspberrypi/public_html/cgi/opencv/test.py, referer: http://localhost/~raspberrypi/cgi/opencv/ [Sun Sep 22 14:11:11.802745 2019] [cgi:error] [pid 13672:tid 1960] [client ::1:52117] AH01215: Traceback (most recent call last):\r: C:/localhost/home/raspberrypi/public_html/cgi/opencv/test.py, referer: http://localhost/~raspberrypi/cgi/opencv/ [Sun Sep 22 14:11:11.802745 2019] [cgi:error] [pid 13672:tid 1960] [client ::1:52117] AH01215: File "C:/localhost/home/raspberrypi/public_html/cgi/opencv/test.py", line 5, in <module>\r: C:/localhost/home/raspberrypi/public_html/cgi/opencv/test.py, referer: http://localhost/~raspberrypi/cgi/opencv/ [Sun Sep 22 14:11:11.802745 2019] [cgi:error] [pid 13672:tid 1960] [client ::1:52117] AH01215: import cv2\r: C:/localhost/home/raspberrypi/public_html/cgi/opencv/test.py, referer: http://localhost/~raspberrypi/cgi/opencv/ [Sun Sep 22 14:11:11.803737 2019] [cgi:error] [pid 13672:tid 1960] [client ::1:52117] AH01215: File "C:\\Users\\refirio\\Anaconda3\\lib\\site-packages\\cv2\\__init__.py", line 3, in <module>\r: C:/localhost/home/raspberrypi/public_html/cgi/opencv/test.py, referer: http://localhost/~raspberrypi/cgi/opencv/ [Sun Sep 22 14:11:11.803737 2019] [cgi:error] [pid 13672:tid 1960] [client ::1:52117] AH01215: from .cv2 import *\r: C:/localhost/home/raspberrypi/public_html/cgi/opencv/test.py, referer: http://localhost/~raspberrypi/cgi/opencv/ [Sun Sep 22 14:11:11.803737 2019] [cgi:error] [pid 13672:tid 1960] [client ::1:52117] AH01215: ImportError: numpy.core.multiarray failed to import\r: C:/localhost/home/raspberrypi/public_html/cgi/opencv/test.py, referer: http://localhost/~raspberrypi/cgi/opencv/
エラーメッセージによると、numpy.core.multiarray を使えないらしい 以下を参考に numpy をアップデートすると大丈夫だった 【Pythonエラー対策】ImportError: numpy.core.multiarray failed to import | 西住工房 https://algorithm.joho.info/programming/python/numpy-core-multiarray-failed-to-import/ >pip install numpy --upgrade なお、プログラム実行ディレクトリに、numpy.py を自身で作成していると、そちらが読み込まれる 結果的に正しいファイルを読み込めずにエラーになるので注意 ■OpenCV(バージョン3をインストール) 上記「OpenCV」の手順でインストールすると、4.1.1 がインストールされた 今回は本番環境に合わせて 3.4.3 にバージョンダウンするものとする 【Jupyter Notebook】OpenCVのインポートエラー解決メモ - Qiita https://qiita.com/yut-nagase/items/27b0a17e9e3074a95c6c 以下のようにしてアンインストール&インストールできた >pip uninstall opencv-python >pip install opencv-python==3.4.3.18 なお、以下のバージョン指定だと「バージョンの指定が不十分」となる エラーメッセージをもとに、マイナーバージョンを指定する >pip install opencv-python==3.4.3 Collecting opencv-python==3.4.3 ERROR: Could not find a version that satisfies the requirement opencv-python==3.4.3 (from versions: 3.4.2.16, 3.4.2.17, 3.4.3.18, 3.4.4.19, 3.4.5.20, 3.4.6.27, 3.4.7.28, 4.0.0.21, 4.0.1.23, 4.0.1.24, 4.1.0.25, 4.1.1.26) ERROR: No matching distribution found for opencv-python==3.4.3 ■その他メモ 2020年5月におけるPython開発環境の選択肢 - Qiita https://qiita.com/nicco_mirai/items/80ba4b4bf9db11ac54c6 2020 年の Python パッケージ管理ベストプラクティス - Qiita https://qiita.com/sk217/items/43c994640f4843a18dbe
■Linux上に開発環境を構築
基本的に、Pythonは初めからインストールされている ■Raspberry Pi Raspberry Pi 上で開発するために諸々のツールを追加インストールした際のメモは RaspberryPi.txt を参照 ■CentOS CentOS7の場合、初めからPython2がインストールされている ただしPython3を使用したい場合、別途インストールする必要がある # python --version Python 2.7.5 ■CentOS7.7以降の場合 以下でインストールできる # yum -y install python3 # python3 --version Python 3.6.8 # pip3 --version pip 9.0.3 from /usr/lib/python3.6/site-packages (python 3.6) CentOS7.7でPython3.6をインストールしてみよう - DENET 技術ブログ https://blog.denet.co.jp/centos77python36/ ■CentOS7.7より以前の場合 以下でインストールできる # yum install -y https://repo.ius.io/ius-release-el7.rpm # yum search python36 # yum install -y python36u python36u-libs python36u-devel python36u-pip ※https://centos7.iuscommunity.org/ius-release.rpm は使えなくなっているので https://repo.ius.io/ius-release-el7.rpm を指定する Python 3 を CentOS 7 に yum でインストールする手順 | https://weblabo.oscasierra.net/python3-centos7-yum-install/ iusの最新リンクが変更になったので注意 - Qiita https://qiita.com/seal_qiita/items/981a9284ecd44e54af96 ■CentOS7でPython3.7を使う場合 現状Python3.7は提供されておらず、どうしても使いたければソースコードからインストールする必要があるみたい Python3.7とDjango3.0をインストールする(CentOS) - Qiita https://qiita.com/shiranon/items/889b9d32bea0df4b89dc ■その他メモ 【Python入門】subprocessを使ってコマンドを実行しよう! | 侍エンジニア塾ブログ(Samurai Blog) https://www.sejuku.net/blog/51090 subprocessの使い方(Python3.6) - Qiita https://qiita.com/caprest/items/0245a16825789b0263ad
■matplotlib(グラフ描画)
プログラミング言語Pythonおよびその科学計算用ライブラリである「NumPy」のためのグラフ描画ライブラリ matplotlibのめっちゃまとめ - Qiita https://qiita.com/nkay/items/d1eb91e33b9d6469ef51 以下はグラフを画像に出力する例
import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt x = [1, 2, 3, 4, 5] y = [10, 11, 23, 45, 21] plt.figure(figsize=(4, 4), dpi=72) plt.plot(x, y) #plt.bar(x, y) plt.savefig('output/graph.png')
以下のようにして実行すると、outputフォルダ内にグラフの画像が出力される > python graph.py CLIでプログラムを実行すると画面に画像を表示できずにエラーとなる 「matplotlib.use('Agg')」と指定することで、画面ではなく画像に保存できるようになる なお「Agg」は「Anti-Grain Geometry engine」のことで、データを画像に描画するライブラリ 「plt.figure(figsize=(4, 4), dpi=72)」 は 「横4インチ×縦4インチ、解像度72」 の意味 これらを変更することで、画像の縦横比率や解像度が変わる matplotlibで作成したプロットを画像ファイルに保存する方法 - Qiita https://qiita.com/koichifukushima/items/e63e642431db92178188 matplotlib.use('Agg')するときの注意点 - みんなのふぃじー(はてなブログ版) http://fijixfiji.hatenablog.com/entry/2016/12/17/001226 Matplotlib - Linux のCLIでmatplotlibを動かしたい|teratail https://teratail.com/questions/166605 matplotlibで出力される画像のサイズを変更する https://www.solima.net/python/archives/179
■数式の表現
※Pythonとは直接関係しないが、数式を表現するためにMathJaxを使用する MathJax | Beautiful math in all browsers. https://www.mathjax.org/ mathjax.pdf http://www.eng.niigata-u.ac.jp/~nomoto/download/mathjax.pdf MathJax<Javascript<木暮 http://www.kogures.com/hitoshi/javascript/mathjax/index.html Github Pages で数式を 〜 MathJax v3 設定のポイント - Qiita https://qiita.com/memakura/items/e4d2de379f98ad7be498 お勧めのMathJax設定方法(構成や日本語表示など) - いっしきまさひこBLOG https://blog.masahiko.info/entry/2020/03/09/203814 以下は数式の例 \[x = -\frac{b}{a} \] \[x = \frac{-b\pm\sqrt{b^{2}-4ac}}{2a} \] \[\sum_{k=1}^{n} a_{k} = a_{1} + a_{2} + \dots + a_{n} \] \[\int_{-\infty}^{\infty} e^{-x^{2}} \, dx = \sqrt{\pi} \] \[f'(x) = \lim_{\varDelta x \to 0} \frac{ f(x+\varDelta x) - f(x) }{\varDelta x} \] \[\left\{ \begin{array}{l} x+y&=8\\ 2x+4y&=26 \end{array} \right. \] \[\begin{pmatrix} 1 & 2 \\ 11 & 12 \end{pmatrix} \] \[\frac{df}{dx} = \lim_{\Delta x \to 0} \frac{f(x+ \Delta x)-f(x)}{\Delta x} \]
■数学の復習
以下の書籍の勉強メモ やさしく学ぶ 機械学習を理解するための数学のきほん アヤノ&ミオと一緒に学ぶ 機械学習の理論と数学、実装まで https://www.amazon.co.jp/gp/product/B075GSMZDS ■総和 以下のような、1から100までの足し算があるとする \[1 + 2 + 3 + 4 + … + 99 + 100 \] 総和の記号を使うと、以下のように表現できる \[\sum_{i=1}^{100} i \] 何個足せばいいのかわからない場合、「n」を使って以下のように表現できる \[\sum_{i=1}^{n} i \] 同様に、以下のような式があるとする (式中の「(1)」や「(2)」は「1乗」「2乗」ではなく、「1番目」「2番目」の意味) \[E(\theta) = \frac{1}{2}((y^{(1)} - f_{\theta}(x^{(1)}))^{2} + (y^{(2)} - f_{\theta}(x^{(2)}))^{2} + … + (y^{(n)} - f_{\theta}(x^{(n)}))^{2}) \] これは以下のように表現できる \[E(\theta) = \frac{1}{2} \sum_{i=1}^{n} (y^{(i)} - f_{\theta}(x^{(i)}))^{2} \] ■微分 微分とは、関数のある点における傾きを調べたり、瞬間の変化を捉えることができるものとされる 例えば「40秒で120m走行した車の速度」を求める場合、通常以下のように求める \[\frac{120m}{40s} = 3m/s \] ただしこれは平均速度であって、常に秒速3mの速度が出ていたわけではない ある時点における瞬間の速度は、それぞれで異なる値を取る 瞬間の変化量を求めるために、関数を「f(x)」、微小な数を「h」と置くと、 関数「f(x)」の点「x」での傾きは以下のような式で表すことができる(左辺は「f(x)の微分」の意味を表す) \[\frac{d}{dx}f(x) = \lim_{h \to 0} \frac{ f(x + h) - f(x) }{h} \] 文字になると難しく感じるが、具体的な数字を代入してみるとイメージが付きやすい 例えば「10.0秒と10.1秒という0.1秒の間に、40.0mから40.6mに移動した」の場合、「x = 10」「h = 0.1」なので、 \[\frac{ f(10 + 0.1) - f(10) }{0.1} = \frac{ 40.6 - 40}{ 0.1 } = 6 \] となり、「傾き6」が速度となる なお「h = 0.1」はあくまでも例なので、実際は「限りなく0に近い数」となる 以下に微分の性質を3つ示す。覚えておくと式の整理を効率よく行える 1つめ \[f(x) = x^{n} \] という式があるとき、これを微分すると以下のようになる \[\frac{d}{dx}f(x) = nx^{n-1} \] 2つめ 複数の関数や定数は以下のように扱える \[\frac{d}{dx}(f(x) + g(x)) = \frac{d}{dx}f(x) + \frac{d}{dx}g(x) \] \[\frac{d}{dx}(af(x)) = a\frac{d}{dx}f(x) \] 3つめ 「x」に関係のない定数aの微分は0になる \[\frac{d}{dx}a = 0 \] 以下計算例 \[\frac{d}{dx}5 = 0 \] \[\frac{d}{dx}x = \frac{d}{dx}x^{1} = 1\cdot x^{0} = 1 \] \[\frac{d}{dx}x^{3} = 3x^{2} \] \[\frac{d}{dx}x^{-2} = -2x^{-3} \] \[\frac{d}{dx}10x^{4} = 10\frac{d}{dx}x^{4} = 10\cdot 4x^{3} = 40x^{3} \] \[\frac{d}{dx}(x^{5} + x^{6}) = \frac{d}{dx}x^{5} + \frac{d}{dx}x^{6} = 5x^{4} + 6x^{5} \] ■偏微分 上で紹介した関数「f(x)」は変数が「x」しかない1変数関数だが、変数が2つ以上ある多変数関数も存在する 機械学習の最適化問題はパラメータの数だけ変数があるので、目的関数が多変数関数となる \[g(x_{1}, x_{2}, … , x_{n}) = x_{1} + x_{2}^{2} … + x_{n}^{n} \] 多変数関数を微分する場合、微分する変数だけに注目し、他の変数はすべて定数として扱うことにして微分する このような微分方法を偏微分という 例えば \[h(x_{1}, x_{2}) = x_{1}^{2} + x_{2}^{3} \] このように変数が2つある場合、3次元空間へのプロットとなる これを例えば「x2 = 1」に固定してみると、以下のように「h」は「x1」だけの関数になる \[h(x_{1}, x_{2}) = x_{1}^{2} + 1^{3} \] これで単純な二次関数となる 定数を微分するとすべて0になるので、「h」を「x1」で偏微分すると以下の結果になる(左辺は「h(x1, x2)の偏微分」の意味を表す) \[\frac{\partial}{\partial x_{1}}h(x_{1}, x_{2}) = 2x_{1} \] 同じ要領で「x1 = 1」に固定してみると、以下のように「h」は「x2」だけの関数になる \[h(x_{1}, x_{2}) = 1^{2} + x_{2}^{3} \] 「h」を「x2」で偏微分すると以下のようになる \[\frac{\partial}{\partial x_{2}}h(x_{1}, x_{2}) = 3x_{2}^{2} \] このように、微分したい変数のみに注目して、他の変数をすべて定数として扱うことで、その変数での関数の傾きを知ることができる 今回は2つの変数を持つ関数での例を挙げたが、変数がどれだけ増えたとしても同じ考え方が適用できる ■合成関数 例えば、以下のような2つの関数「f(x)」と「g(x)」があるとする \[f(x) = 10 + x^{2} \] \[g(x) = 3 + x \] このとき、「x」に適当な値を代入すると、それに対応する値が出力される \[f(1) = 10 + 1^{2} = 11 \] \[f(2) = 10 + 2^{2} = 14 \] \[g(1) = 3 + 1 = 4 \] \[g(2) = 3 + 2 = 5 \] 「x」には関数を代入することもできる \[f(g(x)) = 10 + g(x)^{2} = 10 + (3 + x)^{2} \] \[g(f(x)) = 3 + f(x) = 3 + (10 + x^{2}) \] 「f(x)」の中に「g(x)」が、もしくは「g(x)」の中に「f(x)」が使われているが、このように関数が複数組み合わさったものを合成関数と呼ぶ 例えば合成関数「f(g(x))」を「x」で微分することを考えてみる 解りやすくするために、いったん以下のように変数に置き換えてみる \[u = g(x) \] \[y = f(u) \] こうすると、以下のように段階的に微分できる \[\frac{dy}{dx} = \frac{dy}{du} \cdot \frac{du}{dx} \] つまり「y」を「u」で微分し、「u」を「x」で微分したものを掛けることで計算できる 実際に微分をすると以下のようになる \[\frac{dy}{du} = \frac{d}{du} f(u) \] \[\frac{dy}{du} = \frac{d}{du} (10 + u^{2}) = 2u \] \[\frac{du}{dx} = \frac{d}{dx} g(x) \] \[\frac{du}{dx} = \frac{d}{dx} (3 + x) = 1 \] それぞれの結果を掛けると、微分結果を得ることができる \[\frac{dy}{dx} = \frac{dy}{du} \cdot \frac{du}{dx} \] \[\frac{dy}{dx} = 2u \cdot 1 \] \[\frac{dy}{dx} = 2g(x) \] \[\frac{dy}{dx} = 2(3 + x) \] ■ベクトルと行列 ベクトルとは数を縦に並べたもの、行列とは数を縦と横に並べたもので、それぞれ以下のような形をしている \[a = \begin{bmatrix} 3 \\ 9 \end{bmatrix} , A = \begin{bmatrix} 6 & 3 \\ 8 & 10 \end{bmatrix} \] 慣習的にベクトルは小文字、行列は大文字のアルファベットを用いる(加えて、太文字で表すことが多い) ここでベクトルaは縦に2つの数が並んでおり、これは3次元ベクトルとなる 行列Aは縦横に2つの数が並んでおり、2×2(2行2列)のサイズの行列となる ベクトルを「列が1つしかない行列」と考えると、aは「2×1の行列」とみなすことができる \[A = \begin{bmatrix} 6 & 3 \\ 8 & 10 \end{bmatrix} , B = \begin{bmatrix} 2 & 1 \\ 5 & -3 \end{bmatrix} \] 行列は、それぞれ和差積の演算を定義することができる 和と差は単純に各要素ごとに足し算と引き算をすればいい \[A + B = \begin{bmatrix} 6 + 2 & 3 + 1 \\ 8 + 5 & 10 - 3 \end{bmatrix} = \begin{bmatrix} 8 & 4 \\ 13 & 7 \end{bmatrix} \] \[A - B = \begin{bmatrix} 6 - 2 & 3 - 1 \\ 8 - 5 & 10 + 3 \end{bmatrix} = \begin{bmatrix} 4 & 2 \\ 3 & 13 \end{bmatrix} \] 積は少し特殊で、左側の行列の「行」と右側の行列の「列」の要素を順番に掛けてから、それらを足し合わせる 行列同士の掛け算をする場合、左側にある行列の列数と、右側にある行列の行数が一致している必要がある \[AB = \begin{bmatrix} 6 * 2 + 3 * 5 & 6 * 1 + 3 * -3 \\ 8 * 2 + 10 * 5 & 8 * 1 + 10 * -3 \end{bmatrix} = \begin{bmatrix} 27 & -3 \\ 66 & -22 \end{bmatrix} \] また、以下のように行と列を入れ替える操作を転置と呼ぶ \[a = \begin{bmatrix} 2 \\ 5 \\ 2 \end{bmatrix} , a^{T} = \begin{bmatrix} 2 & 5 & 2 \end{bmatrix} \] 例えばベクトル同士を掛ける場合、以下のように片方を転地してから積を計算することがある これはベクトル同士の内積を求めることと同じ \[a = \begin{bmatrix} 2 \\ 5 \\ 2 \end{bmatrix} , a^{T} = \begin{bmatrix} 1 \\ 2 \\ 3 \end{bmatrix} \] \[a^{T}b = \begin{bmatrix} 2 & 5 & 2 \end{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \end{bmatrix} \] \[a^{T}b = [ 2 * 1 + 5 * 2 + 2 * 3 ] \] \[a^{T}b = [ 18 ] \] ■法線ベクトル 法線ベクトルとは、ある直接に垂直なベクトルのこと 例えば \[ax + by + c = 0 \] という直線があるとき、その法線ベクトルpは \[p = (a, b) \] となる ■指数・対数 指数とは、数の右上に記載して「その数を何乗するか」を表すもの 例えば以下のようなもの \[x^{3} = x \cdot x \cdot x \] \[x^{-4} = \frac{1}{x^{4}} = \frac{1}{x \cdot x \cdot x \cdot x} \] 指数は以下のような性質を持っており、これらは指数法則と呼ばれている \[a^{b} \cdot a^{c} = a^{b + c} \] \[\frac{a^{b}}{a^{c}} = a^{b - c} \] \[(a^{b})^{c} = a^{b + c} \] 上のように、指数は通常普通の数が使われるが、指数部が変数になっているものがある こようなものは指数関数と呼ばれ、以下のような関数の形をしている(「a > 1」の場合) \[y = a^{x} \] このような指数関数の逆関数として対数関数というものがあり、それを log を使って以下のように表す \[y = {log_{a}}x \] 逆関数とは、ある関数の「x」と「y」を入れ替えた関数のこと 逆関数のグラフの形は、もとの関数のグラフを時計回りに90度回転させて、左右方向に反転させた形になっている これは「a を y 乗すると x になる」と考えることができる また「a」の部分を「底」と呼ぶが、特にネイピア数(「e」という記号で表される 2.7182… という定数)を底としたものを自然対数と言い、 自然対数の場合は底を省略して単純に log または ln を使って以下のように表すことが多くある \[y = {log_{e}}x = log \ x = ln \ x \] この対数関数は以下のような性質を持っている \[log \ e = 1 \] \[log \ ab = log a + log b \] \[log \frac{a}{b} = log \ a - log \ b \] \[log \ a^{b} = b \ log \ a \] また、対数関数の微分もよく使われる 底を「a」とする対数関数の微分は以下のようになる \[\frac{d}{dx}log_{a}x = \frac{1}{x \ log \ a} \] 特に底が「e」の自然対数については、「log e = 1」という性質から、微分結果も以下のように簡潔なものになる \[\frac{d}{dx}log_{e}x = \frac{1}{x} \] ■標準偏差 標準偏差の意味と求め方 | AVILEN AI Trend https://ai-trend.jp/basic-study/basic/standard-deviation/ 統計学における分散とは?不偏分散との違いも! 例題でわかりやすく解説 | AVILEN AI Trend https://ai-trend.jp/basic-study/basic/variance/ 以下のデータがあるとする 名前: 得点 Aさん: 90点 Bさん: 80点 Cさん: 40点 Dさん: 60点 Eさん: 90点 平均は以下のように求められる \[(90 + 80 + 40 + 60 + 90) / 5 \\ = 72 \] 分散(データのばらつき具合)は以下のように求められる \[((90 - 72)^2 + (80 - 72)^2 + (40 - 72)^2 + (60 - 72)^2 + (90 - 72)^2) / 5 \\ = ((18)^2 + (8)^2 + (-32)^2 + (-12)^2 + (18)^2) / 5 \\ = (324 + 64 + 1024 + 144 + 324) / 5 \\ = 376 \] 平方根で本来のデータと単位を揃える これを標準偏差と呼ぶ \[√376 \\ =19.3907194297 \] これで「平均点±19.39点の中に大体の人がいる」ということを求めらえる 正規分布(平均値と最頻値・中央値が一致し、それを軸として左右対称となっている確率分布)の場合、平均値±標準偏差中に観測データが含まれる確率は68.3%になる これが±標準偏差の2倍、3倍になるとさらに確率は上がる - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 範囲 範囲内に指定の数値が現れる確率 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 平均値±標準偏差 68.3% 平均値±(標準偏差×2) 95.4% 平均値±(標準偏差×3) 99.7% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - また、偏差値は以下のように求める ((得点 - 平均点) / 標準偏差) * 10 + 50 例えば80点の場合、偏差値は以下のようになる \[((80 - 72) / 19.39) * 10 + 50 \\ = 54.1258380609 \] 例えば90点の場合、偏差値は以下のようになる \[((90 - 72) / 19.39) * 10 + 50 \\ = 59.2831356369 \] ■標準偏差(実際の得点に近いデータで確認) 疑似偏差値計算 https://shade-search.com/sts/fsw/hensachi/test.cgi 作成された、以下の得点データで試す
0 0 6 8 10 10 11 13 15 17 18 18 18 20 21 21 21 22 22 22 23 23 23 24 24 24 25 25 25 25 26 26 26 26 26 27 27 27 27 27 28 28 28 29 30 31 31 31 31 32 32 32 32 32 32 33 33 33 34 34 34 34 34 34 35 35 35 35 36 36 36 36 36 36 37 37 37 38 38 38 38 38 39 39 39 39 40 40 40 41 41 41 41 41 41 41 41 41 42 42 42 42 42 42 43 43 43 43 43 43 43 43 44 44 44 44 44 44 45 45 46 46 46 46 46 46 46 46 46 46 47 47 47 47 47 47 47 47 47 47 47 47 48 48 48 49 49 49 49 49 50 50 50 50 50 50 50 50 51 51 51 51 51 51 51 52 52 52 52 52 52 53 53 53 53 53 54 54 54 54 54 54 54 55 55 55 55 55 55 55 55 56 56 56 56 56 56 57 57 58 58 58 58 59 59 59 59 59 59 59 60 60 60 61 61 62 62 62 62 62 63 63 63 63 63 63 63 64 64 64 64 64 65 66 66 66 66 66 67 67 67 67 67 67 67 68 68 68 69 69 69 69 69 69 70 70 70 70 70 71 71 71 72 72 73 73 74 74 74 75 75 77 77 77 77 77 78 79 79 79 79 79 79 79 80 80 81 82 82 82 83 83 84 85 87 87 90 91 96 96
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 得点エリア 人数 得点エリアの平均点 得点エリアの合計点 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0〜9 4 4.5 18.0 10〜19 9 14.5 130.5 20〜29 31 24.5 759.5 30〜39 42 34.5 1449.0 40〜49 64 44.5 2848.0 50〜59 60 54.5 3270.0 60〜69 44 64.5 2838.0 70〜79 30 74.5 2235.0 80〜89 12 84.5 1014.0 90〜100 4 95.0 380.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 参考までに、得点エリアごとの人数をグラフにプロットするには以下のようになる
import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt x = [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90] y = [ 4, 9, 31, 42, 64, 60, 44, 30, 12, 4] plt.figure(figsize=(4, 4), dpi=72) plt.plot(x, y) plt.savefig('output/graph.png')
偏差値は以下のようになる 得点合計 ... 14938 得点の平均 ... 49.7933333333333 標準偏差 ... 18.5568663542337 0点の偏差値 = (( 0 - 49.79) / 18.56) * 10 + 50 = 23.1734913793 24点の偏差値 = (( 24 - 49.79) / 18.56) * 10 + 50 = 36.1045258621 70点の偏差値 = (( 70 - 49.79) / 18.56) * 10 + 50 = 60.8890086207 96点の偏差値 = (( 96 - 49.79) / 18.56) * 10 + 50 = 74.8976293103 100点の偏差値 = ((100 - 49.79) / 18.56) * 10 + 50 = 77.0528017241 以下はサンプリングしたデータから標準偏差と偏差値を計算した場合 得点合計 = 14942 得点の平均=49.8066666666667 標準偏差 = 18.4979986905491 (疑似平均使用) 24点の偏差値 = 36.0489412404101 (疑似平均使用) 以下は全体の平均値のみ、オリジナルデータから得た場合 標準偏差 = 18.4980034958731 (オリジナルの平均使用) 24点の偏差値 = 36.0561528496371 (オリジナルの平均使用) 標準偏差の誤差 abs(18.4979986905491 - 18.5568663542337) = 0.0588676636845697 偏差値の誤差 abs(36.0489412404101 - 36.1003830921869) = 0.0514418517768078 ■最急降下法 ※整理中。以下を参考にメモを残しておきたい やる夫で学ぶ機械学習 - 単回帰問題 - - けんごのお屋敷 http://tkengo.github.io/blog/2016/01/04/yaruo-machine-learning2/ 最急降下法の概要 - Qiita https://qiita.com/Takayoshi_Makabe/items/ee467313c38b1879c097 \[g(x) = (x - 1)^{2} \] という二次関数のグラフがあるとき、最小値は x = 1 のときの g(1) = 0 である この式は単純なので簡単に求められるが、複雑な式の場合には以下のように求める方法がある まず、二次関数の増減表を求める 増減表を求めるためには関数を微分する \[\frac{d}{dx}g(x) = 2x - 2 \] 増減表は以下のようになる
x の範囲 … x<1 x=1 x>1 g(x) を微分したときの符号 … - 0 + g(x) の増減 … 減少 増加
例えば x = 3 からスタートして g(x) の値を小さくするためには、x を少しずつ左にずらしていけばいい(増減表から x > 1 の時は、グラフが左下がりになっているのがわかるため) x = -3 からだと、逆に右にずらしていけばいい つまり導関数の符号によって x をずらす方向が変わる(マイナスなら減少だから右にずらし、プラスなら増加だから左にずらす) このように微分して導関数を求めて、その符号によって x の位置をずらす、別の言い方をすると x を更新していくことで、最小値を求める x の更新を式にすると以下のようになる \[x := x - \eta \frac{d}{dx} g(x) \] これは「x を新しい x で定義していく」ということになり、つまりは計算で求めた x を次の計算に使うことになる この手法を最急降下法という 微分式の前に付いている記号は「イータ」と読み、学習率と呼ばれる正の定数 学習率が小さければ、g(x) の最小値にたどり着くまでに何度も x を更新する必要があって時間がかかってしまう 逆に学習率を大きくすれば、速く g(x) の最小値にたどり着ける可能性があるが、x が定まらず発散してしまう可能性もある 具体的には g(x) の微分は 2x - 2 だから、x を更新する式は \[x := x - \eta (2x - 2) \] となる イータを1として x = 3 から始めて計算すると x := 3 - 1(2 * 3 - 2) = 3 - 4 = -1 x := -1 - 1(2 * -1 - 2) = -1 + 4 = 3 x := 3 - 1(2 * 3 - 2) = 3 - 4 = -1 となり、ループして求めることができない (1つ目の式で求められた「-1」を2つ目の式で使う。以降も同じように計算している) これが発散している状態 イータを0.1として計算すると x: = 3 - 0.1(2 * 3 - 2) = 3 - 0.4 = 2.6 x: = 2.6 - 0.1(2 * 2.6 - 2) = 2.6 - 0.3 = 2.3 x: = 2.3 - 0.1(2 * 2.3 - 2) = 2.3 - 0.2 = 2.1 x: = 2.1 - 0.1(2 * 2.1 - 2) = 2.1 - 0.2 = 1.9 となり、時間はかかるが正解には近づくことができている (1つ目の式で求められた「2.6」を2つ目の式で使う。以降も同じように計算している)
■数学とグラフ
[python]算数・数学?~関数と方程式~ - Qiita https://qiita.com/hiroyuki_mrp/items/d4194a6de594c2e0f56f ■基本のグラフ \[y = x \]
import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt x = [0, 1, 2, 3, 4, 5, 6, 7, 8] # Xの範囲 y = x # Yの範囲 plt.figure(figsize=(8, 8), dpi=72) plt.axis('equal') # 縦横のメモリの大きさを揃える plt.xlim(-10, 10) # X軸は-10〜10の範囲を表示する plt.ylim(-10, 10) # Y軸は-10〜10の範囲を表示する plt.xticks(np.arange(-10, 10, 1)) # X軸のグリッド間隔を-10〜10の範囲で1刻みに設定する plt.yticks(np.arange(-10, 10, 1)) # Y軸のグリッド間隔を-10〜10の範囲で1刻みに設定する plt.grid(color='0.8') # 薄いグレーでグリッドを表示する plt.plot(x, y) plt.savefig('graph.png')
■1次関数 \[y = 2x + 3 \]
import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt x = np.arange(-100, 100) y = 2 * x + 3 # 1次関数「y = 2x + 3」のグラフを描画 plt.figure(figsize=(8, 8), dpi=72) plt.axis('equal') plt.xlim(-10, 10) plt.ylim(-10, 10) plt.xticks(np.arange(-10, 10, 1)) plt.yticks(np.arange(-10, 10, 1)) plt.grid(color='0.8') plt.plot(x, y) plt.savefig('graph.png')
■2次関数 \[y = x^{2} + 1 \]
import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt x = np.arange(-100, 100, 0.1) # 0.1刻みにしてグラフをなめらかにする y = x ** 2 + 1 # 2次関数「y = x^2 + 1」のグラフを描画 plt.figure(figsize=(8, 8), dpi=72) plt.axis('equal') plt.xlim(-10, 10) plt.ylim(-10, 10) plt.xticks(np.arange(-10, 10, 1)) plt.yticks(np.arange(-10, 10, 1)) plt.grid(color='0.8') plt.plot(x, y) plt.savefig('graph.png')
■3次関数 \[y = x^{3} + 4 \]
import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt x = np.arange(-100, 100, 0.1) # 0.1刻みにしてグラフをなめらかにする y = x ** 3 + 4 # 3次関数「y = x^3 + 4」のグラフを描画 plt.figure(figsize=(8, 8), dpi=72) plt.axis('equal') plt.xlim(-10, 10) plt.ylim(-10, 10) plt.xticks(np.arange(-10, 10, 1)) plt.yticks(np.arange(-10, 10, 1)) plt.grid(color='0.8') plt.plot(x, y) plt.savefig('graph.png')
■連立方程式 2点 (3, 6) と (4, 12) を通る直線を求める ・「x = 3」のときに「y = 6」となる ・「x = 4」のときに「y = 12」となる なので、1次関数「y = ax + b」に当てはめて 6 = 3a + b 12 = 4a + b となる この連立方程式を解けばいい 以下はプログラムを使わずに解く例 b = 6 - 3a 12 = 4a + 6 - 3a a = 6 6 = 3 * 6 + b b = -12 y = 6x - 12 以下はプログラムを使って解く例 実行して 「ModuleNotFoundError: No module named 'sympy'」 のエラーになる場合、sympyをインストールする必要がある $ pip3.7 install sympy
from sympy import Symbol, solve a = Symbol('a') # 変数を定義(「a」を記号として扱う。通常int型とstr型は一緒に計算できない) b = Symbol('b') # 変数を定義(「b」を記号として扱う。通常int型とstr型は一緒に計算できない) exp1 = 3 * a + b - 6 exp2 = 4 * a + b - 12 ans = solve((exp1, exp2)) # 方程式の解を取得 print(ans) # 解を表示
以下は実行結果 $ python3.7 math.py {a: 6, b: -12}
■回帰による予測
以下の書籍の勉強メモ 最小二乗法を使って一次関数の式を求める やさしく学ぶ 機械学習を理解するための数学のきほん アヤノ&ミオと一緒に学ぶ 機械学習の理論と数学、実装まで https://www.amazon.co.jp/gp/product/B075GSMZDS この書籍のもとになったページが以下にある やる夫で学ぶ機械学習シリーズ - けんごのお屋敷 http://tkengo.github.io/blog/2016/06/06/yaruo-machine-learning0/ ■データの確認 click.csv
x,y 235,591 216,539 148,413 35,310 85,308 204,519 49,325 25,332 173,498 191,498 134,392 99,334 117,385 112,387 162,425 272,659 159,400 159,427 59,319 198,522
以下でグラフに配置して確認できる
import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt # 学習データを読み込む train = np.loadtxt('click.csv', delimiter=',', dtype='int', skiprows=1) train_x = train[:,0] train_y = train[:,1] # プロット plt.plot(train_x, train_y, 'o') plt.savefig('graph.png')
以下で一次関数の学習データをプロットできる
import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt # 学習データを読み込む train = np.loadtxt('click.csv', delimiter=',', dtype='int', skiprows=1) train_x = train[:,0] train_y = train[:,1] # 標準化 mu = train_x.mean() sigma = train_x.std() def standardize(x): return (x - mu) / sigma train_z = standardize(train_x) # パラメータを初期化 theta0 = np.random.rand() theta1 = np.random.rand() # 予測関数 def f(x): return theta0 + theta1 * x # 目的関数 def E(x, y): return 0.5 * np.sum((y - f(x)) ** 2) # 学習率 ETA = 1e-3 # 誤差の差分 diff = 1 # 更新回数 count = 0 # 誤差の差分が0.01以下になるまでパラメータ更新を繰り返す error = E(train_z, train_y) while diff > 1e-2: # 更新結果を一時変数に保存 tmp_theta0 = theta0 - ETA * np.sum((f(train_z) - train_y)) tmp_theta1 = theta1 - ETA * np.sum((f(train_z) - train_y) * train_z) # パラメータを更新 theta0 = tmp_theta0 theta1 = tmp_theta1 # 前回の誤差との差分を計算 current_error = E(train_z, train_y) diff = error - current_error error = current_error # ログの出力 count += 1 log = '{}回目: theta0 = {:.3f}, theta1 = {:.3f}, 差分 = {:.4f}' print(log.format(count, theta0, theta1, diff)) # プロットして確認 x = np.linspace(-3, 3, 100) plt.plot(train_z, train_y, 'o') plt.plot(x, f(x)) plt.savefig('graph.png')
実行の際、以下のようなログが出力される $ python3.7 regression1_linear.py 1回目: theta0 = 9.411, theta1 = 2.790, 差分 = 76035.5263 2回目: theta0 = 17.806, theta1 = 4.604, 差分 = 73024.5195 3回目: theta0 = 26.033, theta1 = 6.381, 差分 = 70132.7485 4回目: theta0 = 34.095, theta1 = 8.123, 差分 = 67355.4917 5回目: theta0 = 41.996, theta1 = 9.830, 差分 = 64688.2142 6回目: theta0 = 49.739, theta1 = 11.503, 差分 = 62126.5609 〜中略〜 389回目: theta0 = 428.985, theta1 = 93.443, 差分 = 0.0118 390回目: theta0 = 428.988, theta1 = 93.444, 差分 = 0.0113 391回目: theta0 = 428.991, theta1 = 93.444, 差分 = 0.0109 392回目: theta0 = 428.994, theta1 = 93.445, 差分 = 0.0105 393回目: theta0 = 428.997, theta1 = 93.446, 差分 = 0.0101 394回目: theta0 = 429.000, theta1 = 93.446, 差分 = 0.0097 プログラムの最後に以下を追加すると
print(f(standardize(100))) print(f(standardize(200))) print(f(standardize(300)))
実行時に以下も表示される つまり、個別に予測を表示できる
370.9672809730788 510.4700574222163 649.9728338713539
以下メモ …だが、まだまだ理解を超えているので要勉強 予測データを関数として表すことができれば、与えられたデータをもとに予測を立てることができる シンプルな例として、今回の学習データは一次関数であると推測して実装する 一次関数の学習データは以下のように表すことができる \[y = ax + b \] この式を以下のように表すものとする \[f_{\theta}(x) = \theta_{0} + \theta_{1}x \] これが予測関数の元になっており、このシータ1とシータ2の値を求めることができれば正しい予測ができることになる そしてこれらの式において、 \[y = f_{\theta}(x) \] と一致するときが誤差のない状態となる これを変形すると \[y - f_{\theta}(x) = 0 \] と表すことができる 学習データが「n」個あるとして、学習データごとの誤差の和は以下のように表すことができる(この誤差の和が小さければ小さいほど正確な予測と言える) 左辺の E は、誤差を英語で表したときの「Error」の頭文字から取ったもの これが目的関数の元になっている なお、全体を2で割っているのは微分の計算を簡単にするため、2乗しているのは誤差が負の値になっても正確に算出するため \[E(\theta) = \frac{1}{2} \sum_{i=1}^{n} (y^{(i)} - f_{\theta}(x^{(i)}))^{2} \] 標準化(学習データの平均を0、分散を1とする)は以下で行う 必須の処理ではないが、行っておくとパラメータの収束が早くなる \[z^{(i)} = \frac{x^{i} - \mu}{\sigma} \] 標準化については、まだ理解の範囲を超えている 以下などで引き続き確認したい 機械学習でなぜ正規化が必要なのか - Qiita https://qiita.com/yShig/items/dbeb98598abcc98e1a57 【統計・機械学習】標準化(Standardization)と正規化(Normalization)とは?初心者向けにわかりやすく解説 | AI Academy Media https://aiacademy.jp/media/?p=1147 正規化・標準化を徹底解説 (Python 前処理 サンプルコード付き) https://www.codexa.net/normalization-python/ 【機械学習入門】正規化と標準化の特徴量のスケーリングの使い分け方法 https://www.hobby-happymylife.com/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0/no... 目的関数で E を小さくしていけば誤差が小さくなる ただし、適当に値を代入して求めるのは大変。このようなときは微分を使って求めていく この目的関数は \[f_{\theta}(x^{(i)}) \] を含んでいて、この値はシータ0とシータ1の2つのパラメーターを持っている つまりこの目的関数は、シータ0とシータ1の2つの変数を持つ2次関数になる よって普通の微分ではなく偏微分となり、更新式は以下のようになる \[\theta_{0} := \theta_{0} - \eta \frac{\partial E}{\partial \theta_{0}} \] \[\theta_{1} := \theta_{1} - \eta \frac{\partial E}{\partial \theta_{1}} \] これは最急降下法や勾配降下法と呼ばれるもの 分数の前に付いている記号は「イータ」で、学習率と呼ばれる正の定数 学習率の大小によって、最小値にたどり着くまでの更新回数が変わってくる 偏微分の計算を行うが、正攻法の微分は大変。よって合成関数の微分を使う。今回は以下のように定義する \[u = E(\theta) \] \[\nu = f_{\theta}(x) \] すると、以下のように段階的に微分できる \[\frac{\partial u}{\partial \theta_{0}} = \frac{\partial u}{\partial \nu} \cdot \frac{\partial \nu}{\partial \theta_{0}} \] これを計算すると、 \[\frac{\partial u}{\partial \nu} = \frac{\partial}{\partial \nu}(\frac{1}{2} \sum_{i=1}^{n} (y^{(i)} - \nu)^{2}) \] \[\frac{\partial u}{\partial \nu} = \frac{1}{2} \sum_{i=1}^{n} (\frac{\partial}{\partial \nu}(y^{(i)} - \nu)^{2}) \] \[\frac{\partial u}{\partial \nu} = \frac{1}{2} \sum_{i=1}^{n} (\frac{\partial}{\partial \nu}(y^{(i)2} - 2y^{(i)}\nu - \nu^{2})) \] \[\frac{\partial u}{\partial \nu} = \frac{1}{2} \sum_{i=1}^{n} (-2y^{(i)} + 2\nu) \] \[\frac{\partial u}{\partial \nu} = \sum_{i=1}^{n} (\nu - y^{(i)}) \] と \[\frac{\partial \nu}{\partial \theta_{0}} = \frac{\partial}{\partial \theta_{0}}(\theta_{0} + \theta_{1}x) \] \[\frac{\partial \nu}{\partial \theta_{0}} = 1 \] になる これをかけ合わせると \[\frac{\partial u}{\partial \theta_{0}} = \frac{\partial u}{\partial \nu} \cdot \frac{\partial \nu}{\partial \theta_{0}} \] \[\frac{\partial u}{\partial \theta_{0}} = \sum_{i=1}^{n} (\nu - y^{(i)}) \cdot 1 \] \[\frac{\partial u}{\partial \theta_{0}} = \sum_{i=1}^{n} (f_{\theta}(x^{(i)}) - y^{(i)}) \] 引き続きシータ1についても微分してみる \[\frac{\partial u}{\partial \theta_{1}} = \frac{\partial u}{\partial \nu} \cdot \frac{\partial \nu}{\partial \theta_{1}} \] \[\frac{\partial u}{\partial \theta_{1}} = \frac{\partial \nu}{\partial \theta_{1}}(\theta_{0} + \theta_{1}x) \] \[\frac{\partial u}{\partial \theta_{1}} = x \] 微分する \[\frac{\partial u}{\partial \theta_{1}} = \frac{\partial u}{\partial \nu} \cdot \frac{\partial \nu}{\partial \theta_{1}} \] \[\frac{\partial u}{\partial \theta_{1}} = \sum_{i=1}^{n} (\nu - y^{(i)}) \cdot x^{(i)} \] \[\frac{\partial u}{\partial \theta_{1}} = \sum_{i=1}^{n} (f_{\theta}(x^{(i)}) - y^{(i)}) x^{(i)} \] 最終的に以下2つのパラメータの更新式を得ることができる これが更新式の元になっている \[\theta_{0} := \theta_{0} - \mu \sum_{i=1}^{n} (f_{\theta}(x^{(i)}) - y^{(i)}) \] \[\theta_{1} := \theta_{1} - \mu \sum_{i=1}^{n} (f_{\theta}(x^{(i)}) - y^{(i)})x^{(i)} \] 試行回数は一概には言えないが、今回は 10^-3 にしておく これらの内容をもとにプログラムを作成したものが先の内容となる 結果として \[\theta_{0} = 429.000 \] \[\theta_{1} = 93.446 \] という値を求められているが、つまりは求めたい1次関数は \[f_{\theta}(x) = \theta_{0} + \theta_{1}x \] \[f_{\theta}(x) = 429.000 + 93.446x \] \[y = 93.446x + 429.000 \] となる。具体的には xが100のときyは、93.446 * 100 + 429 = 9773.6 xが200のときyは、93.446 * 200 + 429 = 19118.2 xが300のときyは、93.446 * 300 + 429 = 28462.8 …だとおかしな値だが、もとのプログラムと同じく標準化の処理を加えると以下のようになる xが100のときyは370.9671010284257 xが200のときyは510.46967317686426 xが300のときyは649.9722453253028 標準化を含むと大丈夫そうだが、 もとのプログラムから標準化の処理を無くすと、意図したグラフを描けないのは不明 要勉強 ■メモ 以下なども参考になりそう 機械学習のパラメータチューニングを「これでもか!」というくらい丁寧に解説 - Qiita https://qiita.com/c60evaporator/items/ca7eb70e1508d2ba5359
■Pandas(データ解析支援)
データ解析を支援する機能を提供するライブラリ 以下でインストールできる $ sudo pip3 install pandas データ分析で頻出のPandas基本操作 - Qiita https://qiita.com/ysdyt/items/9ccca82fc5b504e7913a pandas の loc、iloc、ix の違い - python | コード7区 http://ailaby.com/lox_iloc_ix/ ■1次元のデータ構造
import pandas as pd label = ['a', 'b', 'c', 'd', 'e'] data = [1, 2, 3, 4, 5] s = pd.Series(data, index=label) # 行ラベル付きの1次元データ構造 # 内容をすべて表示 print(s)
$ python3 test.py a 1 b 2 c 3 d 4 e 5 dtype: int64 ■2次元のデータ構造
import pandas as pd data = { 'col1': [1, 2, 3, 4, 5], 'col2': [2, 3, 4, 5, 6], 'col3': [3, 4, 5, 6, 7], } index_name = ['zero', 'one', 'two', 'three', 'four'] df = pd.DataFrame(data, index=index_name) # 行ラベル・列ラベル付きの2次元データ構造 # 内容をすべて表示 print(df) # ラベルによるデータ選択 print(df.loc['one', 'col2']) # 「one」行、「col2」列のデータを選択 print(df.loc['one':'three', :]) # 「one」から「three」行のすべての列のデータを選択 print(df.loc[['one', 'four'], ['col1', 'col3']]) # 「one」と「four」行の「col1」と「col3」列のデータを選択 # 位置番号によるデータ選択(一番号は0始まり / 結果は上と同じ) print(df.iloc[1, 1]) print(df.iloc[1:4, :]) print(df.iloc[[1, 4], [0, 2]])
$ python3 2.py col1 col2 col3 zero 1 2 3 one 2 3 4 two 3 4 5 three 4 5 6 four 5 6 7 3 col1 col2 col3 one 2 3 4 two 3 4 5 three 4 5 6 col1 col3 one 2 4 four 5 7 3 col1 col2 col3 one 2 3 4 two 3 4 5 three 4 5 6 col1 col3 one 2 4 four 5 7 ■CSVファイルを読み込み
import pandas as pd # CSVファイルを読み込み df = pd.read_csv('sample.csv', index_col=0, encoding='shift-jis') # 次元をタプルに格納して返す print(df.shape) # 簡素な情報を出力する print(df.info()) # 最初の5行を表示 print(df.head()) # 最後の5行を表示 print(df.tail())
■Excelファイルを読み込み
import pandas as pd # Excelファイルを読み込み #excel = pd.read_excel('sample.xlsx', index_col=0) excel = pd.read_excel('sample.xlsx', index_col=0, engine='openpyxl') # 次元をタプルに格納して返す print(excel.shape) # 簡素な情報を出力する print(excel.info()) # 最初の5行を表示 print(excel.head()) # 最後の5行を表示 print(excel.tail())
「ImportError: Missing optional dependency 'xlrd'. Install xlrd >= 1.0.0 for Excel support Use pip or conda to install xlrd.」 のエラーになる場合、xlrdをインストールする必要がある $ sudo pip3 install xlrd インストールしても 「ValueError: Your version of xlrd is 2.0.1. In xlrd >= 2.0, only the xls format is supported. Install openpyxl instead.」 のエラーが表示される xlrd 2.0.0 からxlsxがサポートされなくなったらしい 対策に、openpyxlをインストールする $ sudo pip3 install openpyxl これでExcelファイルの読み込み時、「engine='openpyxl'」を指定すると読み込める
■OpenCV(画像処理)
OpenCV(Open Source Computer Vision Library) 画像や動画を処理するのに必要な様々な機能を提供するライブラリ Pythonを用いた画像処理(openCV,skimage) - Qiita https://qiita.com/taka_baya/items/453e429b466ffaa702c9 Pythonで画像処理: Pillow, NumPy, OpenCVの違いと使い分け | note.nkmk.me https://note.nkmk.me/python-image-processing-pillow-numpy-opencv/ ■開発環境を構築 Windowsの場合は、このファイル内の「Windows上に開発環境を構築」を参照 Linuxの場合は、RaspberryPi.txt の「OpenCV」を参照 ■画像の読み込みと表示 保存の際に拡張子を「.png」にすればPNG形式で保存される 「.jpg」ならJpeg形式で保存される
import cv2 img = cv2.imread("sample.jpg") cv2.imwrite("output.png", img)
■画像のグレースケール変換
import cv2 img = cv2.imread("sample.png", 0) cv2.imwrite('gray.png', img)
import cv2 img = cv2.imread("sample.png") img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) cv2.imwrite("gray.png", img)
■画像の指定範囲の色を抽出
import cv2 import numpy as np img = cv2.imread("sample.png", 1) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 取得する色の範囲を指定する lower_color = np.array([20, 50, 50]) upper_color = np.array([255, 255, 255]) # 指定した色に基づいたマスク画像の生成 img_mask = cv2.inRange(hsv, lower_color, upper_color) # フレーム画像とマスク画像の共通の領域を抽出する。 img_color = cv2.bitwise_and(img, img, mask=img_mask) cv2.imwrite("hsv.png", img_color)
■画像のエッジ部分を抽出
import cv2 import numpy as np # 白黒画像で画像を読み込み img = cv2.imread("sample.png", 0) # エッジ検出 canny_img = cv2.Canny(img, 50, 110) cv2.imwrite("canny.png", canny_img)
■画像のネガポジ変換
import cv2 img = cv2.imread("face.png") #img = 256 - img img = 0 - img cv2.imwrite("invert.png", img)
■画像のリサイズ
import cv2 # 画像を読み込み img = cv2.imread("sample.png") # リサイズ img = cv2.resize(img, (80, 80)) cv2.imwrite("resize.png", img)
■画像のトリミング
import cv2 # 画像を読み込み img = cv2.imread("sample.png") # トリミング x, y = 180, 240 w, h = 200, 60 img = img[y:y+h, x:x+w] cv2.imwrite("trimming.png", img)
■画像の特異点を抽出
import cv2 import numpy as np # 画像を読み込み img = cv2.imread("sample.png", 1) # 特異点を抽出 detector = cv2.ORB_create() keypoints = detector.detect(img) # 画像に特徴点を書き込み img_orb = cv2.drawKeypoints(img, keypoints, None) cv2.imwrite("orb.png", img_orb)
■画像のヒストグラムを可視化
import cv2 import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt # 画像を読み込み img = cv2.imread('sample.png') # ヒストグラムを可視化 color = ('b','g','r') for i,col in enumerate(color): histr = cv2.calcHist([img],[i],None,[256],[0,256]) plt.plot(histr,color = col) plt.xlim([0,256]) plt.savefig('histogram.png')
■輪郭抽出
import cv2 import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt # 画像を読み込んでリサイズ img = cv2.imread("face.jpg") img = cv2.resize(img, (200, 300)) # 色空間を二値化 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # グレースケールに変換 gray = cv2.GaussianBlur(gray, (7, 7), 0) # 平滑化 im2 = cv2.threshold(gray, 140, 240, cv2.THRESH_BINARY_INV)[1] # 二極化 # 画面左側に二値化した画像を描画 plt.subplot(1, 2, 1) plt.imshow(im2, cmap="gray") # 輪郭を抽出 cnts = cv2.findContours(im2, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[0] # 抽出した枠を描画 for pt in cnts: x, y, w, h = cv2.boundingRect(pt) # 大きすぎたり小さすぎたり領域を除去 if w < 30 or w > 200: continue print(x,y,w,h) # 結果を出力 cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) # 画面右側に抽出結果を描画 plt.subplot(1, 2, 2) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.savefig("found.png", dpi=200)
実行時に 「npoints = 0 && (depth == cv_32f depth == cv_32s) in function 'pointsetboundingrect'」 のようなエラーになった場合、findContoursの「[1]」を「[0]」にすれば動作した Opencv 3.2から仕様が変わり、関数の戻り値の数が変わったとのこと Python - 輪郭抽出プログラムが実行されません|teratail https://teratail.com/questions/175238 ■顔認識
#!/Users/refirio/Anaconda3/python # coding: utf-8 # -*- coding: utf-8 -*- import sys import io import cv2 # 使用ファイルと入出力ディレクトリ IMAGE_FILE = "daughter.png" INPUT_PATH = "./inputs/" + IMAGE_FILE OUTPUT_PATH = "./outputs/" + IMAGE_FILE # ラインの色 COLOR_WHITE = (255, 255, 255) COLOR_RED = (0, 0, 255) # 画像ファイル読み込み image = cv2.imread(INPUT_PATH) # 画像をグレースケール変換 image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # カスケード分類器の特徴量を取得 face_cascade = cv2.CascadeClassifier("./haarcascades/haarcascade_frontalface_alt.xml") eye_cascade = cv2.CascadeClassifier("./haarcascades/haarcascade_eye.xml") # 画像の中から顔を検出 faces = face_cascade.detectMultiScale(image_gray, scaleFactor=1.1, minNeighbors=2, minSize=(50, 50)) if len(faces) > 0: # 検出した顔の座標を取得 for (face_x,face_y,face_w,face_h) in faces: # 検出した顔を囲む矩形の作成 cv2.rectangle(image, (face_x,face_y),(face_x + face_w,face_y + face_h), COLOR_WHITE, 2) # 検出した顔画像を取得 face_image = image[face_y : face_y + face_h, face_x : face_x + face_w] # 検出した顔画像をグレースケール変換 face_image_gray = image_gray[face_y : face_y + face_h, face_x : face_x + face_w] # 顔画像の中から目を検出 eyes = eye_cascade.detectMultiScale(face_image_gray, scaleFactor=1.1, minNeighbors=2, minSize=(20, 20)) if len(faces) > 0: # 検出した目の座標を取得 for (eye_x,eye_y,eye_w,eye_h) in eyes: # 検出した目を囲む矩形の作成 cv2.rectangle(face_image,(eye_x, eye_y),(eye_x + eye_w,eye_y + eye_h), COLOR_RED, 2) # 認識結果の保存 cv2.imwrite(OUTPUT_PATH, image) # 結果画面を表示 sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') print("Content-Type: text/html; charset=UTF-8\n") print("<!DOCTYPE html>") print("<html>") print("<head>") print("<meta charset=\"utf-8\">") print("<title>Python</title>") print("</head>") print("<body>") print("<h1>Python</h1>") print("<img src=\"" + OUTPUT_PATH + "\" style=\"max-width: 500px; max-height: 500px;\">") print("</body>") print("</html>")
■skimage(画像処理)
skimageとは、画像処理に関するアルゴリズムを集めたライブラリ Pythonを用いた画像処理(openCV,skimage) - Qiita https://qiita.com/taka_baya/items/453e429b466ffaa702c9 ■画像の色の違いの部分を切り分け
import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import cv2 from skimage import data, segmentation, color from skimage.future import graph # 画像を読み込み img = cv2.imread('sample.png', 1) #画像の色の違いの部分を切り分け labels = segmentation.slic(img, compactness=30, n_segments=400, start_label=0) out = color.label2rgb(labels, img, kind='avg', bg_label=0) plt.plot() plt.imshow(out) plt.savefig('rag.png')
■MeCab(形態素解析)
形態素解析とは、文章を意味を持つ最小単位(形態素)に分割し、各形態素に品詞情報などを付加する 英単語は単語の区切りが明確だが、日本語の形態素解析は容易ではない 代表的な形態素解析ライブラリとしてMeCabがある ■MeCabをインストール Raspberry Piでpythonからmecabを使う初期設定 - Qiita https://qiita.com/fujit33/items/fd1d09f3332c626c9379 $ sudo apt-get install mecab libmecab-dev mecab-ipadic-utf8 python-mecab $ sudo apt-get install swig $ sudo pip3 install mecab-python3 $ python3 Python 3.8.7 (default, Feb 7 2021, 00:21:33) [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import MeCab >>> mecab = MeCab.Tagger() >>> print(mecab.parse("すもももももももものうち")) すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ も 助詞,係助詞,*,*,*,*,も,モ,モ もも 名詞,一般,*,*,*,*,もも,モモ,モモ も 助詞,係助詞,*,*,*,*,も,モ,モ もも 名詞,一般,*,*,*,*,もも,モモ,モモ の 助詞,連体化,*,*,*,*,の,ノ,ノ うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ EOS >>> exit() ■mecab-ipadic-NEologd を導入 MeCabは形態素解析を行うに当たり単語辞書を用いており、IPADICという単語辞書がよく用いられる mecab-ipadic-NEologd は、新しい語や固有表現を追加することで IPADICを拡張したMeCab用のシステム辞書 GitHub - neologd/mecab-ipadic-neologd: Neologism dictionary based on the language resources on the Web for mecab-ipadic https://github.com/neologd/mecab-ipadic-neologd $ git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git $ cd mecab-ipadic-neologd $ ./bin/install-mecab-ipadic-neologd -n -p /var/lib/mecab/dic/mecab-ipadic-neologd Raspberry Pi 4 4B-32GB の環境ではインストールできた インストールに成功したら、以下のようにして辞書を指定できる $ python3 Python 3.8.7 (default, Feb 7 2021, 00:21:33) [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import MeCab >>> mecab = MeCab.Tagger("-d /var/lib/mecab/dic/mecab-ipadic-neologd") >>> print(mecab.parse("メイが恋ダンスを踊っている。")) メイ 名詞,固有名詞,人名,一般,*,*,M.A.Y,メイ,メイ が 助詞,格助詞,一般,*,*,*,が,ガ,ガ 恋ダンス 名詞,固有名詞,一般,*,*,*,恋ダンス,コイダンス,コイダンス を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ 踊っ 動詞,自立,*,*,五段・ラ行,連用タ接続,踊る,オドッ,オドッ て 助詞,接続助詞,*,*,*,*,て,テ,テ いる 動詞,非自立,*,*,一段,基本形,いる,イル,イル 。 記号,句点,*,*,*,*,。,。,。 EOS >>> exit() Raspberry Pi 3 Model b+ の環境では以下のエラーになった メモリ不足のためインストールできないみたい 公式の解説によると4GBほどのメモリ空き容量が必要らしいが、今回の環境は1GB程度しかない terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc /home/pi/mecab-ipadic-neologd/bin/../libexec/make-mecab-ipadic-neologd.sh: 525 行: 23592 中止 ${MECAB_LIBEXEC_DIR}/mecab-dict-index -f UTF8 -t UTF8 mecab-ipadic-neologd/README.ja.md at master - neologd/mecab-ipadic-neologd - GitHub https://github.com/neologd/mecab-ipadic-neologd/blob/master/README.ja.md Vagrant上のVMへのmecab-ipadic-neologdのインストールが失敗する時 - Qiita https://qiita.com/comocc/items/bfa5c4fe3c84d31e8ae7 以下のようにすると、300MBほどサイズを削減できるとのこと 今回の環境ではこれでもインストールできなかった $ ./bin/install-mecab-ipadic-neologd -n -y --ignore_adverb --ignore_interject --ignore_noun_ortho --ignore_noun_sahen_conn_ortho --ignore_adjective_std --ignore_adjective_verb --ignore_ill_formed_words -p /var/lib/mecab/dic/mecab-ipadic-neologd 以下のようにすると512MBほどのメモリ空き容量があればインストールできるとのこと ただしオススメしないとされている 今回の環境ではこれでもインストールできなかった $ ./bin/install-mecab-ipadic-neologd -n -y --eliminate-redundant-entry -p /var/lib/mecab/dic/mecab-ipadic-neologd 今回はメモリ不足のため mecab-ipadic-NEologd を使えないようなので、標準の辞書を使う
■Janome(形態素解析)
Pythonで書かれた形態素解析ライブラリ pipでインストール可能なので、MeCabよりも手軽に扱うことができる ただし処理速度はMeCabに敵わない 内包辞書として mecab-ipadic-2.7.0-20070801 が使われている ■Janomeをインストール $ pip3 install janome $ python3 Python 3.8.7 (default, Feb 7 2021, 00:21:33) [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from janome.tokenizer import Tokenizer >>> t = Tokenizer() >>> for token in t.tokenize("すもももももももものうち"): ... print(token) ... すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ も 助詞,係助詞,*,*,*,*,も,モ,モ もも 名詞,一般,*,*,*,*,もも,モモ,モモ も 助詞,係助詞,*,*,*,*,も,モ,モ もも 名詞,一般,*,*,*,*,もも,モモ,モモ の 助詞,連体化,*,*,*,*,の,ノ,ノ うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ >>> exit() Welcome to janome's documentation! (Japanese) - Janome v0.4 documentation (ja) https://mocobeta.github.io/janome/ Python, Janomeで日本語の形態素解析、分かち書き(単語分割) | note.nkmk.me https://note.nkmk.me/python-janome-tutorial/ Janomeを使ってPythonで形態素解析 - Qiita https://qiita.com/charon/items/661d9a25b2233a9f8da4 ■最新の mecab-ipadic-NEologd を導入 $ git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git $ xz -dkv seed/*.csv.xz $ cat seed/*.csv > neologd.csv 作成された neologd.csv を作業フォルダに配置する 今回は janome ディレクトリで作業するものとする janome/neologd.csv 以下のプログラムで辞書をビルドする
from janome.dic import UserDictionary from janome import sysdic user_dict = UserDictionary('neologd.csv', 'utf8', 'ipadic', sysdic.connections) user_dict.save('neologd')
…が、Raspberry Pi 4 4B-32GB の環境では「MemoryError」となって処理が止まった JanomeでNEologd辞書を使う - Qiita https://qiita.com/_likr/items/0fc845f59b4ad685cc06
■機械学習
■機械学習とは 機械学習とは、人間の学習能力と同様の機能をコンピューター上で実現しようとする技術 人工知能における研究課題の一つ 一般的な識別プログラムを作る場合、画像データの画素を調べて 「赤色の要素が多ければリンゴ、黄色の要素が多ければレモン」 のように判定する。判定のルールは人間が決める 機械学習で判定する場合、人間が明確なルールを決めることは無い たくさんのリンゴとレモンの画像データを用意しておいて、それを識別器というプログラムに与える そうすることで、識別器が自動的に 「リンゴには赤色の要素が多く、レモンには黄色の要素が多い」 ということを学習する ■ニューラルネットワークとは ニューラルネットワークとは、人の神経を模したネットワーク構造のこと コンピュータに学習能力をもたせることにより、様々な問題を解決するためのアプローチ 人間の脳の中には、多数の神経細胞(ニューロン)が存在している 一つのニューロンは他の複数のニューロンから信号を受け取り、他のニューロンに対して信号を渡す 脳はこのような信号の流れによって、様々な情報を伝達している この仕組をコンピュータで再現したのがニューラルネットワーク ■ディープラーニング(深層学習)とは ニューラルネットワークを3層以上重ねたものを、一般に「ディープ・ニューラル・ネットワーク(DNN)」と呼ぶ このDNNを使った機械学習がディープラーニング(深層学習) ディープラーニングでは、大量のデータを学習することで、各ニューロン間の接続の重み付けのパラメーターを繰り返し調整する ■パーセプトロンとは 比較的単純な仕組みでありながら、現在の機械学習の基礎となっている人工ニューロン 入力層と出力層のみの2層からなる、単純パーセプトロンについて考える 3つの入力x1、x2、x3と1つの出力yがあるとする そして各入力値には、0または1の値を与えることにし、出力する値も0または1になるとする ここでは例えば、「新しいパソコンを買うかどうか」について考える 新しいパソコンを買う場合に出力yは1となり、買わない場合は0になる そして入力には、パソコンを購入してもいいかどうかを判断する要因を与えるものとする ・今が買い替えどきか(x1) ・手元に資金が十分にあるか(x2) ・現在セールをしているか(x3) これらの要素を考慮し、多数決で決めることになる ただしこの多数決は、平等に一票ずつが与えられるわけではない もしその人tの手元に資金がたくさんあるなら、x2の条件はそれほど重要ではない また、今使っているパソコンが故障した場合はx1の条件は重要になる つまり単純な多数決で判断できないため、パーセプトロンでも各入力に対する重み(W)というパラメーターを導入している x1、x2、x3に対する重みをW1、W2、W3としたとき、資金が多い人なら(W1=5、W2=2、W3=3)と重みを設定すると考えられるし、 すでにパソコンが壊れている人なら(W1=7、W2=2、W3=1)と重みを設定すると考えられる そして、パソコンを購入するかどうかを検討するプログラムは、閾値をbとしたとき、以下のように表現できる
if (x1 * W1) + (x2 * W2) + (x3 * W3) > b: # 買う else: # 買わない
このように重みや閾値を変化させることで、意思決定を明確化させることができる このパーセプトロンを複雑に組み合わせることで、より複雑な判断ができるようにする ■AI(人工知能)、機械学習、ディープラーニング(深層学習)の違い AI(人工知能): マシンによって再現される人間の知能 人間と同様の知能を実現させようという取り組みやその技術 機械学習: 人工知能を実現するためのアプローチ 特定のタスクをトレーニングにより実行できるようになるAI。人が特徴を定義する ディープラーニング(深層学習): 機械学習を実装するための手法 マシンが特徴を自動定義する 人工知能、機械学習、ディープラーニングの違いとは | NVIDIA https://blogs.nvidia.co.jp/2016/08/09/whats-difference-artificial-intelligence-machine-learning-deep... AI、機械学習、ディープラーニングの違いを説明できますか?機械学習と統計の違いは? (1/3):MarkeZine(マーケジン) https://markezine.jp/article/detail/29471
■scikit-learn(機械学習)
scikit-learn(サイキット・ラーン)は、Python向けの機械学習フレームワーク 様々なアルゴリズムに対応しており、すぐに機械学習を試せるようにサンプルデータも含まれている 機械学習でよく使われる他のライブラリ(PandasやNumPyなど)との親和性が高い BSDライセンスのオープンソースのため、無償で商用利用が可能 ■インストール $ sudo pip3 install sklearn $ python3 Python 3.7.3 (default, Apr 3 2019, 05:39:12) [GCC 8.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from sklearn.svm import LinearSVC >>> from sklearn.metrics import accuracy_score >>> exit() 機械学習のライブラリ!scikit-learnとは【初心者向け】 | TechAcademyマガジン https://techacademy.jp/magazine/17375 使用すべきアルゴリズムについても、上記ページで紹介されている 以下のプログラムでは、中小規模のクラス分類手法である Linear SVC を使用している
from sklearn.svm import LinearSVC from sklearn.metrics import accuracy_score # 学習用データと結果の準備 learn_data = [[0, 0], [1, 0], [0, 1], [1, 1]] learn_label = [0, 0, 0, 1] # アルゴリズムの指定(LinearSVC) clf = LinearSVC() # 学習用データと結果の学習 clf.fit(learn_data, learn_label) # テストデータによる予測 test_data = [[0, 0], [1, 0], [0, 1], [1, 1]] test_label = clf.predict(test_data) # 予測結果の評価 print(test_data, " の予測結果: ", test_label) print("正解率: ", accuracy_score([0, 0, 0, 1], test_label))
■インストール時にエラー インストール時に以下のようなエラーになることがあった $ sudo pip3 install sklearn ERROR: Command errored out with exit status 1: /usr/local/bin/python3.8 /usr/local/lib/python3.8/site-packages/pip install Python - pythonでscikit-learnがインストールできない|teratail https://teratail.com/questions/223561 Pythonの新しいバージョンに対応できていない可能性があるので、バージョンを下げて試す このときはPython3.8で上記エラーになったが、Python3.7だとインストールできた ■AnacondaのCGI環境で動作しないので試行錯誤中 Anaconda Prompt では動作するが、コマンドプロンプトやCGIだとscikitを認識できない? 以下の解説に習って「Add Anaconda to the system PATH environment variable」のチェックを外したが、それが問題になっているかも 【Python】非エンジニアWindowユーザー向けのAnacondaインストールの手順 https://tonari-it.com/python-anaconda-install/ 以下の記事では、チェックを入れるように案内されている Windows10でpythonを使う環境を作る?:AnacondaとPycharm - プロクラシスト https://www.procrasist.com/entry/2016/10/04/200000 チェックを入れて再インストールすると、コマンドプロンプトからは sklearn を呼び出せた …と思ったが、C:\Users\refirio\Anaconda3 の場所で実行するか否かによって違う? コマンドプロンプトでもアナコンダプロンプトでも同じ? ただしCGI経由だと以下のエラーになる Pythonのパスは #!/Users/refirio/Anaconda3/python から変える必要はないか [Tue Sep 24 00:19:40.842477 2019] [cgi:error] [pid 11380:tid 1900] [client ::1:50053] End of script output before headers: sklearn.py [Tue Sep 24 00:19:40.842477 2019] [cgi:error] [pid 11380:tid 1900] [client ::1:50053] AH01215: Traceback (most recent call last):\r: C:/localhost/home/raspberrypi/public_html/cgi/sklearn.py [Tue Sep 24 00:19:40.842477 2019] [cgi:error] [pid 11380:tid 1900] [client ::1:50053] AH01215: File "C:/localhost/home/raspberrypi/public_html/cgi/sklearn.py", line 9, in <module>\r: C:/localhost/home/raspberrypi/public_html/cgi/sklearn.py [Tue Sep 24 00:19:40.843483 2019] [cgi:error] [pid 11380:tid 1900] [client ::1:50053] AH01215: from sklearn.svm import LinearSVC\r: C:/localhost/home/raspberrypi/public_html/cgi/sklearn.py [Tue Sep 24 00:19:40.843483 2019] [cgi:error] [pid 11380:tid 1900] [client ::1:50053] AH01215: File "C:\\localhost\\home\\raspberrypi\\public_html\\cgi\\sklearn.py", line 9, in <module>\r: C:/localhost/home/raspberrypi/public_html/cgi/sklearn.py [Tue Sep 24 00:19:40.843483 2019] [cgi:error] [pid 11380:tid 1900] [client ::1:50053] AH01215: from sklearn.svm import LinearSVC\r: C:/localhost/home/raspberrypi/public_html/cgi/sklearn.py [Tue Sep 24 00:19:40.843483 2019] [cgi:error] [pid 11380:tid 1900] [client ::1:50053] AH01215: ModuleNotFoundError: No module named 'sklearn.svm'; 'sklearn' is not a package\r: C:/localhost/home/raspberrypi/public_html/cgi/sklearn.py 以下、試行錯誤 pip list pip install sklearn pip install sklearn.svm pip install scikit-learn 【Python】アナコンダプロンプトだけでなくコマンドプロンプトでもPythonを使えるようにする|ぷんたむの悟りの書 https://punhundon-lifeshift.com/python_command_prompt anaconda 環境を設定しscikit-learnを実行する - Qiita https://qiita.com/KENOSIN/items/f9fef4da20cdd4489950 Pythonおよび機械学習勉強用のRaspberryPiの構築 - Qiita https://qiita.com/rhene/items/71b92c253d5ac2a4cc52 いったん諦めて、常に Raspberry Pi 環境で実行することにした ■Raspberry PiのCGI環境で動作しないので試行錯誤中 $ sudo pip3 install sklearn $ python3 Python 3.7.3 (default, Apr 3 2019, 05:39:12) [GCC 8.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from sklearn.svm import LinearSVC >>> from sklearn.metrics import accuracy_score >>> exit() $ python3 test.py この環境でも、コマンドラインからは呼び出せるが、CGI経由だと以下のエラーになる CGI経由の場合は環境変数がセットされないので、何らかの対策が必要? [Wed Sep 25 00:03:37.128014 2019] [cgi:error] [pid 19171:tid 1952445472] [client 192.168.1.110:50839] AH01215: Traceback (most recent call last):: /var/www/cgi-bin/test/sklearn.py [Wed Sep 25 00:03:37.128256 2019] [cgi:error] [pid 19171:tid 1952445472] [client 192.168.1.110:50839] AH01215: File "/var/www/cgi-bin/test/sklearn.py", line 5, in <module>: /var/www/cgi-bin/test/sklearn.py [Wed Sep 25 00:03:37.128320 2019] [cgi:error] [pid 19171:tid 1952445472] [client 192.168.1.110:50839] AH01215: from sklearn.svm import LinearSVC: /var/www/cgi-bin/test/sklearn.py [Wed Sep 25 00:03:37.128409 2019] [cgi:error] [pid 19171:tid 1952445472] [client 192.168.1.110:50839] AH01215: File "/var/www/cgi-bin/test/sklearn.py", line 5, in <module>: /var/www/cgi-bin/test/sklearn.py [Wed Sep 25 00:03:37.128469 2019] [cgi:error] [pid 19171:tid 1952445472] [client 192.168.1.110:50839] AH01215: from sklearn.svm import LinearSVC: /var/www/cgi-bin/test/sklearn.py [Wed Sep 25 00:03:37.128578 2019] [cgi:error] [pid 19171:tid 1952445472] [client 192.168.1.110:50839] AH01215: ModuleNotFoundError: No module named 'sklearn.svm'; 'sklearn' is not a package: /var/www/cgi-bin/test/sklearn.py [Wed Sep 25 00:03:37.143283 2019] [cgi:error] [pid 19171:tid 1952445472] [client 192.168.1.110:50839] End of script output before headers: sklearn.py
■scikit-learn(機械学習)でアヤメの分類
■アヤメの分類 pandas/iris.csv at master - pandas-dev/pandas - GitHub https://github.com/pandas-dev/pandas/blob/master/pandas/tests/data/iris.csv GitHub - kujirahand/book-mlearn-gyomu: Book sample (AI Machine-learning Deep-learning) https://github.com/kujirahand/book-mlearn-gyomu
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.svm import SVC from sklearn.metrics import accuracy_score # アヤメデータの読み込み iris_data = pd.read_csv("iris.csv", encoding="utf-8") # アヤメデータをラベルと入力データに分離する y = iris_data.loc[:,"Name"] x = iris_data.loc[:,["SepalLength","SepalWidth","PetalLength","PetalWidth"]] # 学習用とテスト用に分離する x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, train_size = 0.8, shuffle = True) # 学習する clf = SVC() clf.fit(x_train, y_train) # 評価する y_pred = clf.predict(x_test) print("正解率 = " , accuracy_score(y_test, y_pred))
以下、勉強メモ train_test_split関数でデータ分割 - PyQ 1.0 ドキュメント https://docs.pyq.jp/python/machine_learning/tips/train_test_split.html $ vi iris.csv
SepalLength,SepalWidth,PetalLength,PetalWidth,Name 5.1,3.5,1.4,0.2,Iris-setosa 4.9,3.0,1.4,0.2,Iris-setosa 7.0,3.2,4.7,1.4,Iris-versicolor 6.4,3.2,4.5,1.5,Iris-versicolor 6.3,3.3,6.0,2.5,Iris-virginica 5.8,2.7,5.1,1.9,Iris-virginica
$ vi iris.py
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.svm import SVC from sklearn.metrics import accuracy_score # アヤメデータの読み込み iris_data = pd.read_csv("iris.csv", encoding="utf-8") print("iris_test.csv") print(iris_data) # アヤメデータをラベルと入力データに分離する y = iris_data.loc[:,"Name"] x = iris_data.loc[:,["SepalLength","SepalWidth","PetalLength","PetalWidth"]] print("y") print(y) print("x") print(x) # 学習用とテスト用に分離する x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, train_size = 0.8, shuffle = True) print("x_train") print(x_train) print("x_test") print(x_test) print("y_train") print(y_train) print("y_test") print(y_test)
$ python3 iris_test.py iris_test.csv SepalLength SepalWidth PetalLength PetalWidth Name 0 5.1 3.5 1.4 0.2 Iris-setosa 1 4.9 3.0 1.4 0.2 Iris-setosa 2 7.0 3.2 4.7 1.4 Iris-versicolor 3 6.4 3.2 4.5 1.5 Iris-versicolor 4 6.3 3.3 6.0 2.5 Iris-virginica 5 5.8 2.7 5.1 1.9 Iris-virginica y 0 Iris-setosa 1 Iris-setosa 2 Iris-versicolor 3 Iris-versicolor 4 Iris-virginica 5 Iris-virginica Name: Name, dtype: object x SepalLength SepalWidth PetalLength PetalWidth 0 5.1 3.5 1.4 0.2 1 4.9 3.0 1.4 0.2 2 7.0 3.2 4.7 1.4 3 6.4 3.2 4.5 1.5 4 6.3 3.3 6.0 2.5 5 5.8 2.7 5.1 1.9 x_train SepalLength SepalWidth PetalLength PetalWidth 5 5.8 2.7 5.1 1.9 2 7.0 3.2 4.7 1.4 0 5.1 3.5 1.4 0.2 3 6.4 3.2 4.5 1.5 x_test SepalLength SepalWidth PetalLength PetalWidth 1 4.9 3.0 1.4 0.2 4 6.3 3.3 6.0 2.5 y_train 5 Iris-virginica 2 Iris-versicolor 0 Iris-setosa 3 Iris-versicolor Name: Name, dtype: object y_test 1 Iris-setosa 4 Iris-virginica Name: Name, dtype: object
■scikit-learn(機械学習)でワインの品質判定
Index of /ml/machine-learning-databases/wine-quality https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/ GitHub - kujirahand/book-mlearn-gyomu: Book sample (AI Machine-learning Deep-learning) https://github.com/kujirahand/book-mlearn-gyomu 以下のプログラムで学習&評価できるが、正解率は6〜7割程度と低い
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score from sklearn.metrics import classification_report # データを読み込む wine = pd.read_csv("winequality-white.csv", sep=";", encoding="utf-8") # データをラベルとデータに分離 y = wine["quality"] x = wine.drop("quality", axis=1) # 学習用とテスト用に分割する x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2) # 学習する model = RandomForestClassifier() model.fit(x_train, y_train) # 評価する y_pred = model.predict(x_test) print(classification_report(y_test, y_pred)) print("正解率=", accuracy_score(y_test, y_pred))
以下のプログラムで確認すると、品質データの数には大きく偏りがあることが判る (品質の大半は5〜7で、2以下と10は存在すらしていない) なお結果のグラフは wine-count-plt.png に出力されるが、出力できるようにあらかじめパーミッションを調整しておく
import matplotlib.pyplot as plt import pandas as pd # ワインデータの読み込み wine = pd.read_csv("winequality-white.csv", sep=";", encoding="utf-8") # 品質データごとにグループ分けして、その数を数える count_data = wine.groupby('quality')["quality"].count() print(count_data) # 数えたデータをグラフに描画 count_data.plot() plt.savefig("wine-count-plt.png") plt.show()
以下のように、品質を3段階に再分類する これにより、正解率は9割以上になる 1, 2, 3, 4 → 0(悪い) 5, 6, 7 → 1(普通) 8, 9, 10 → 2(良い)
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score from sklearn.metrics import classification_report # データを読み込む wine = pd.read_csv("winequality-white.csv", sep=";", encoding="utf-8") # データをラベルとデータに分離 y = wine["quality"] x = wine.drop("quality", axis=1) # yのラベルを付け直す newlist = [] for v in list(y): if v <= 4: newlist += [0] elif v <= 7: newlist += [1] else: newlist += [2] y = newlist # 学習用とテスト用に分割する x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2) # 学習する model = RandomForestClassifier() model.fit(x_train, y_train) # 評価する y_pred = model.predict(x_test) print(classification_report(y_test, y_pred)) print("正解率=", accuracy_score(y_test, y_pred))
■scikit-learn(機械学習)で気象データを解析
気象庁|過去の気象データ・ダウンロード https://www.data.jma.go.jp/gmd/risk/obsdl/ 東京の10年分の平均気温を取得する 地点を選ぶ ... 東京 → 東京 項目を選ぶ ... 日別値 → 日平均気温 期間を選ぶ ... 2006年1月1日〜2016年12月31日 として「CSVファイルダウンロード」をクリック 余計な項目も含まれているので、以下のプログラムでデータを整形する
in_file = "data.csv" out_file = "temperature.csv" # CSVファイルを一行ずつ読み込み with open(in_file, "rt", encoding="Shift_JIS") as fr: lines = fr.readlines() # ヘッダをそぎ落として、新たなヘッダをつける lines = ["年,月,日,気温,品質,均質\n"] + lines[5:] lines = map(lambda v: v.replace('/', ','), lines) result = "".join(lines).strip() print(result) # 結果をファイルへ出力 with open(out_file, "wt", encoding="utf-8") as fw: fw.write(result) print("saved.")
以下のプログラムで平均を表示できる
import pandas as pd # PandasでCSVを読み込む df = pd.read_csv("temperature.csv", encoding="utf-8") # 日付ごとに気温をリストにまとめる md = {} for i, row in df.iterrows(): m, d, v = (int(row['月']), int(row['日']), float(row['気温'])) key = str(m) + "/" + str(d) if not(key in md): md[key] = [] md[key] += [v] # 日付ごとに平均を求める avs = {} for key in md: v = avs[key] = sum(md[key]) / len(md[key]) print("{0} : {1}".format(key, v)) # 11月3日の平均気温を表示 print(avs["11/3"])
以下のようにすれば、よりかんたんに平均を求めることができる
import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import pandas as pd # CSVを読み込む df = pd.read_csv("temperature.csv", encoding="utf-8") # 月ごとに平均を求める g = df.groupby(['月'])["気温"] gg = g.sum() / g.count() # 結果を出力 print(gg) gg.plot() plt.savefig("average.png") plt.show()
以下のようにすれば、年ごとに30度超えの日数を表示できる
import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import pandas as pd # CSVを読み込む df = pd.read_csv("temperature.csv", encoding="utf-8") # 気温が30度超えのデータを調べる bool_30 = (df["気温"] > 30) # データを抜き出す over_30 = df[bool_30] # 年ごとにカウント count = over_30.groupby(["年"])["年"].count() # 結果を出力 print(count) count.plot() plt.savefig("over30.png") plt.show()
以下のようにすれば、過去6日の気温から翌日の気温を予測できる
from sklearn.linear_model import LinearRegression import pandas as pd import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt # 気温データ10年分の読み込み df = pd.read_csv('temperature.csv', encoding="utf-8") # データを学習用とテスト用に分割する train_year = (df["年"] <= 2015) test_year = (df["年"] >= 2016) interval = 6 # 過去6日分を学習するデータを作成 def make_data(data): x = [] # 学習データ(過去6日分の気温) y = [] # 結果(翌日の気温) temps = list(data["気温"]) for i in range(len(temps)): if i < interval: continue y.append(temps[i]) xa = [] for p in range(interval): d = i + p - interval xa.append(temps[d]) x.append(xa) return (x, y) train_x, train_y = make_data(df[train_year]) test_x, test_y = make_data(df[test_year]) # 直線回帰分析を行う lr = LinearRegression(normalize=True) lr.fit(train_x, train_y) # 学習 pre_y = lr.predict(test_x) # 予測 # 結果を図にプロット plt.figure(figsize=(10, 6), dpi=100) plt.plot(test_y, c='r') plt.plot(pre_y, c='b') plt.savefig('predict.png') plt.show()
■scikit-learn(機械学習)での最適なアルゴリズムやパラメータを探す
$ sudo pip3 install pytest $ sudo pip3 install cython 各アルゴリズムの正解率を比較 ただし2021年2月現在、実行すると以下のエラーになる $ python3 algorithm.py Traceback (most recent call last): File "algorithm.py", line 5, in <module> from sklearn.utils.testing import all_estimators ModuleNotFoundError: No module named 'sklearn.utils.testing' 以下をインストールしても変化なし $ sudo pip3 install sklearn.utils
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score import warnings from sklearn.utils.testing import all_estimators import warnings warnings.filterwarnings('ignore') # アヤメデータの読み込み iris_data = pd.read_csv("iris.csv", encoding="utf-8") # アヤメデータをラベルと入力データに分離する y = iris_data.loc[:,"Name"] x = iris_data.loc[:,["SepalLength","SepalWidth","PetalLength","PetalWidth"]] # 学習用とテスト用に分離する warnings.filterwarnings('ignore') x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, train_size = 0.8, shuffle = True) # classifierのアルゴリズム全てを取得する warnings.filterwarnings("ignore") allAlgorithms = all_estimators(type_filter="classifier") for (name, algorithm) in allAlgorithms: # 一部のアルゴリズムでエラーになるので除外(要調査) if name == "CheckingClassifier" or name == "ClassifierChain" or name == "MultiOutputClassifier" or name == "OneVsOneClassifier" or name == "OneVsRestClassifier" or name == "OutputCodeClassifier" or name == "VotingClassifier": continue # 各アリゴリズムのオブジェクトを作成 clf = algorithm() # 学習して、評価する clf.fit(x_train, y_train) y_pred = clf.predict(x_test) print(name, "の正解率 = " , accuracy_score(y_test, y_pred))
クロスバリデーション
import pandas as pd from sklearn.model_selection import KFold from sklearn.model_selection import cross_val_score import warnings from sklearn.utils.testing import all_estimators # アヤメデータの読み込み iris_data = pd.read_csv("iris.csv", encoding="utf-8") # アヤメデータをラベルと入力データに分離する y = iris_data.loc[:,"Name"] x = iris_data.loc[:,["SepalLength","SepalWidth","PetalLength","PetalWidth"]] # classifierのアルゴリズム全てを取得する warnings.filterwarnings("ignore") allAlgorithms = all_estimators(type_filter="classifier") # K分割クロスバリデーション用オブジェクト kfold_cv = KFold(n_splits=5, shuffle=True) for (name, algorithm) in allAlgorithms: # 一部のアルゴリズムでエラーになるので除外(要調査) if name == "CheckingClassifier" or name == "ClassifierChain" or name == "MultiOutputClassifier" or name == "OneVsOneClassifier" or name == "OneVsRestClassifier" or name == "OutputCodeClassifier" or name == "VotingClassifier": continue # 各アリゴリズムのオブジェクトを作成 clf = algorithm() # scoreメソッドをもつクラスを対象とする if hasattr(clf,"score"): # クロスバリデーションを行う scores = cross_val_score(clf, x, y, cv=kfold_cv) print(name,"の正解率=") print(scores)
最適なパラメータを探す
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.svm import SVC from sklearn.metrics import accuracy_score from sklearn.model_selection import KFold from sklearn.model_selection import GridSearchCV # アヤメデータの読み込み iris_data = pd.read_csv("iris.csv", encoding="utf-8") # アヤメデータをラベルと入力データに分離する y = iris_data.loc[:,"Name"] x = iris_data.loc[:,["SepalLength","SepalWidth","PetalLength","PetalWidth"]] # 学習用とテスト用に分離する x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, train_size = 0.8, shuffle = True) # グリッドサーチで利用するパラメータを指定 parameters = [ {"C": [1, 10, 100, 1000], "kernel":["linear"]}, {"C": [1, 10, 100, 1000], "kernel":["rbf"], "gamma":[0.001, 0.0001]}, {"C": [1, 10, 100, 1000], "kernel":["sigmoid"], "gamma": [0.001, 0.0001]} ] # グリッドサーチを行う kfold_cv = KFold(n_splits=5, shuffle=True) clf = GridSearchCV( SVC(), parameters, cv=kfold_cv) clf.fit(x_train, y_train) print("最適なパラメータ = ", clf.best_estimator_) # 最適なパラメータで評価 y_pred = clf.predict(x_test) print("評価時の正解率 = " , accuracy_score(y_test, y_pred))
■scikit-learn(機械学習)で言語を判定
利用されている文字コードが異なる言語を判定
import numpy as np from sklearn.naive_bayes import GaussianNB from sklearn.metrics import accuracy_score # Unicodeのコードポイント頻度測定 def count_codePoint(str): # Unicodeのコードポイントをアドレスとする配列を用意 counter = np.zeros(65535) for i in range(len(str)): # 各文字をUnicodeのコードポイントに変換 code_point = ord(str[i]) if code_point > 65535 : continue # 対応するアドレスの出現回数をインクリメント counter[code_point] += 1 # 各要素を文字数で割って正規化 counter = counter/len(str) return counter # 学習用データの準備 ja_str = 'これは日本語の文章です。' en_str = 'This is English Sentences.' th_str = '(タイ語の文章)' x_train = [count_codePoint(ja_str),count_codePoint(en_str),count_codePoint(th_str)] y_train = ['ja','en','th'] # 学習する clf = GaussianNB() clf.fit(x_train, y_train) # 評価用データの準備 ja_test_str = 'こんにちは' en_test_str = 'Hello' th_test_str = '(タイ語の文章)' x_test = [count_codePoint(en_test_str),count_codePoint(th_test_str),count_codePoint(ja_test_str)] y_test = ['en', 'th', 'ja'] # 評価する y_pred = clf.predict(x_test) print(y_pred) print("正解率 = " , accuracy_score(y_test, y_pred))
利用されている文字コードが同じ言語を判定 あらかじめ以下のファイルを用意しておく de, en , es からはじまるファイルの内容は、それぞれドイツ語、英語、スペイン語の内容にしておく train/de_cat.txt train/de_dog.txt train/de_elephant.txt train/en_cat.txt train/en_dog.txt train/en_elephant.txt train/es_cat.txt train/es_dog.txt train/es_elephant.txt test/de_lion.txt test/en_lion.txt test/es_lion.txt
import numpy as np from sklearn.naive_bayes import GaussianNB from sklearn.metrics import accuracy_score import glob # Unicodeのコードポイント頻度測定 def count_codePoint(str): # Unicodeのコードポイントをアドレスとする配列を用意 counter = np.zeros(65535) for i in range(len(str)): # 各文字をUnicodeのコードポイントに変換 code_point = ord(str[i]) if code_point > 65535 : continue # 対応するアドレスの出現回数をインクリメント counter[code_point] += 1 # 各要素を文字数で割って正規化 counter = counter/len(str) return counter # 学習データの準備 index = 0 x_train = [] y_train = [] for file in glob.glob('./train/*.txt'): # 言語情報の取得し、ラベルに設定 y_train.append(file[8:10]) # ファイル内の文字列を連結後、Unicodeのコードポイント頻度測定し、入力データに設定 file_str = '' for line in open(file, 'r'): file_str = file_str + line x_train.append(count_codePoint(file_str)) # 学習する clf = GaussianNB() clf.fit(x_train, y_train) # 評価データの準備 index = 0 x_test = [] y_test = [] for file in glob.glob('./test/*.txt'): # 言語情報の取得し、ラベルに設定 y_test.append(file[7:9]) # ファイル内の文字列を連結後、Unicodeのコードポイント頻度測定し、入力データに設定 file_str = '' for line in open(file, 'r'): file_str = file_str + line x_test.append(count_codePoint(file_str)) # 評価する y_pred = clf.predict(x_test) print(y_pred) print("正解率 = " , accuracy_score(y_test, y_pred))
■scikit-learn(機械学習)で数字を判定
■手書きの数字画像を表示 datasets.load_digits() で手書き数字のデータを参照できる digits.images ... 画像データの配列 digits.target ... データがどの数字を表すかのラベル
import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt # 手書きデータを読み込む from sklearn import datasets digits = datasets.load_digits() # 15個連続で出力する for i in range(15): plt.subplot(3, 5, i+1) # 3行×5列の枠組みを用意し、i+1番目に表示する plt.axis("off") # 軸線を表示しない plt.title(str(digits.target[i])) # 見出し文字 plt.imshow(digits.images[i], cmap="gray") # 画像をグレースケールで表示する # 画像に保存する plt.savefig("output.png")
■手書きの数字を学習&判定 以下で学習させる
from sklearn.model_selection import train_test_split from sklearn import datasets, svm, metrics from sklearn.metrics import accuracy_score #from sklearn.externals import joblib import joblib # データを読み込む digits = datasets.load_digits() x = digits.images y = digits.target x = x.reshape((-1, 64)) # 二次元配列を一次元配列に変換 # データを学習用とテスト用に分割する x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2) # データを学習 clf = svm.LinearSVC() clf.fit(x_train, y_train) # 予測して精度を確認する y_pred = clf.predict(x_test) print(accuracy_score(y_test, y_pred)) # 学習済みデータを保存 joblib.dump(clf, "digits.pkl")
以下で判定させる 手書きの画像を number フォルダ内に 0.png 〜 9.png の名前で保存しておく ただし自分の手書き文字で試すと正解率は50%程度 ディープラーニングを用いた方法の方が制度が高くなるらしいので、引き続き要勉強
import cv2 #from sklearn.externals import joblib import joblib def predict_digit(filename): # 学習済みデータを読み込む clf = joblib.load("digits.pkl") # 自分で用意した手書きの画像ファイルを読み込む my_img = cv2.imread(filename) # 画像データを学習済みデータに合わせる my_img = cv2.cvtColor(my_img, cv2.COLOR_BGR2GRAY) my_img = cv2.resize(my_img, (8, 8)) my_img = 15 - my_img // 16 # 白黒反転する # 二次元を一次元に変換 my_img = my_img.reshape((-1, 64)) # データ予測する res = clf.predict(my_img) return res[0] # 画像ファイルを指定して実行 for i in range(10): n = predict_digit("number/" + str(i) + ".png") print("my" + str(i) + ".png = " + str(n))
■scikit-learn(機械学習)でスパムメールを判定
以下からスパムメールと通常メールを取得 GitHub - kujirahand/spam-database-ja: Spam database for Japanese https://github.com/kujirahand/spam-database-ja not-spam-sjis をもとに、以下の手順で文字コード変換をして not-spam-utf8 を作成する 複数ファイルのエンコードの変換 - EmEditor (テキストエディタ) https://jp.emeditor.com/text-editor-features/versatility/multiple-file-encoding-conversions/ 上記手順で作成した、「spam-utf8」「not-spam-utf8」以下を使用して進める 「spam-utf8」を「spam」として配置し、「not-spam-utf8」を「ok」として配置する また、以下のプログラムを作成する makedb_spamcheck.py
import os, glob import MeCab import numpy as np import pickle # ファイル名を定義 data_file = "./spamcheck-data.pickle" # 変数の準備 word_dic = {"__id": 0} # 単語辞書 files = [] # 読み込んだ単語データを追加する # MeCabの準備 tagger = MeCab.Tagger() # 指定したディレクトリ内のファイル一覧を読み込む def read_files(dir, label): # テキストファイルの一覧を得る files = glob.glob(dir + "/*.txt") for f in files: read_file(f, label) # ファイルを読み込む def read_file(filename, label): words = [] # ファイルの内容を読み込む with open(filename, "rt", encoding="utf-8") as f: text = f.read() files.append({ "label": label, "words": text_to_ids(text) }) # テキストを単語IDのリストに変換 def text_to_ids(text): # 形態素解析 word_s = tagger.parse(text) # 以下のような解析内容を得られるので、これを一行ずつ処理していく # # 友達 名詞,一般,*,*,*,*,友達,トモダチ,トモダチ # が 助詞,格助詞,一般,*,*,*,が,ガ,ガ # 遊び 名詞,一般,*,*,*,*,遊び,アソビ,アソビ # に 助詞,格助詞,一般,*,*,*,に,ニ,ニ # 来る 動詞,自立,*,*,カ変・来ル,基本形,来る,クル,クル words = [] # 単語を辞書に登録 for line in word_s.split("\n"): if line == "EOS" or line == "": continue word = line.split("\t")[0] params = line.split("\t")[1].split(",") hinsi = params[0] # 品詞 bunrui = params[1] # 品詞の分類 org = params[6] # 単語の原型 # 助詞・助動詞・記号・数字は処理しない if not (hinsi in ["名詞", "動詞", "形容詞"]): continue if hinsi == "名詞" and bunrui == "数詞": continue # 単語をidに変換 id = word_to_id(org) words.append(id) return words # 単語をidに変換 def word_to_id(word): # 単語が辞書に登録されているか if not (word in word_dic): # 登録されていないので新たにIDを割り振る id = word_dic["__id"] word_dic["__id"] += 1 word_dic[word] = id else: # 既存の単語IDを返す id = word_dic[word] return id # 単語の頻出頻度のデータを作る def make_freq_data_allfiles(): y = [] x = [] for f in files: y.append(f["label"]) x.append(make_freq_data(f["words"])) return y, x # 単語の出現頻度を取得 def make_freq_data(words): # 単語の出現回数を調べる cnt = 0 dat = np.zeros(word_dic["__id"], "float") for w in words: dat[w] += 1 cnt += 1 # 出現回数を出現頻度に直す dat = dat / cnt return dat # ファイルの一覧から学習用の単語頻出データベースを作る if __name__ == "__main__": read_files("ok", 0) read_files("spam", 1) y, x = make_freq_data_allfiles() # ファイルにデータを保存 pickle.dump([y, x, word_dic], open(data_file, "wb")) print("単語頻出データベース作成完了")
train_spamcheck.py
import pickle from sklearn.naive_bayes import GaussianNB from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score # ファイル名を定義 data_file = "./spamcheck-data.pickle" model_file = "./spamcheck-model.pickle" # データファイルの読込 data = pickle.load(open(data_file, "rb")) y = data[0] # ラベル x = data[1] # 単語の出現頻度 # 学習とテストを100回繰り返す count = 100 rate = 0 for i in range(count): # データを学習用とテスト用に分割 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2) # 学習する model = GaussianNB() model.fit(x_train, y_train) # 評価する y_pred = model.predict(x_test) acc = accuracy_score(y_test, y_pred) # 評価結果が良ければモデルを保存 if acc > 0.94: pickle.dump(model, open(model_file, "wb")) print(acc) rate += acc # 平均値を表示 print("----") print("平均=", rate / count)
test_spamcheck.py
import pickle import MeCab import numpy as np from sklearn.naive_bayes import GaussianNB # テストするテキスト test_text1 = """ 会社から支給されているiPhoneの調子が悪いのです。 修理に出すので、しばらくはアプリのテストができません。 """ test_text2 = """ 億万長者になる方法を教えます。 すぐに以下のアドレスに返信して。 """ # ファイル名を定義 data_file = "./spamcheck-data.pickle" model_file = "./spamcheck-model.pickle" label_names = ["OK", "SPAM"] # 単語辞書の読み込む data = pickle.load(open(data_file, "rb")) word_dic = data[2] # 学習済みモデルの読み込む model = pickle.load(open(model_file, "rb")) # MeCabの準備 tagger = MeCab.Tagger() # テキストがスパムかどうか判定する def check_spam(text): # テキストを単語IDのリストに変換し単語の頻出頻度を調べる zw = np.zeros(word_dic["__id"]) count = 0 s = tagger.parse(text) # 単語毎の回数を加算 for line in s.split("\n"): if line == "EOS": break params = line.split("\t")[1].split(",") org = params[6] # 単語の原型 if org in word_dic: id = word_dic[org] zw[id] += 1 count += 1 zw = zw / count # 予測 pre = model.predict([zw])[0] print("結果=", label_names[pre]) if __name__ == "__main__": print("テキスト1") check_spam(test_text1) print("テキスト2") check_spam(test_text2)
以下で単語頻出データ(spamcheck.pickle)を作成する $ python3.7 makedb_spamcheck.py 単語頻出データ作成完了 以下で学習済みモデル(spamcheck-model.pickle)を作成する 評価結果が良いものをモデルとして保存する $ python3.7 train_spamcheck.py 1.0 0.9777777777777777 1.0 〜中略〜 1.0 0.9777777777777777 0.9555555555555556 ---- 平均= 0.9911111111111102 以下でスパムか否かをテスト $ python3.7 test_spamcheck.py テキスト1 結果= OK テキスト2 結果= SPAM プログラム実行時に以下のようなエラーになる場合、サンプルデータが0件もしくは読み込みに失敗している可能性がある データファイルが正しく配置されているか確認する $ python3.7 train_spamcheck.py Traceback (most recent call last): File "train_spamcheck.py", line 21, in <module> x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2) File "/usr/local/lib64/python3.7/site-packages/sklearn/model_selection/_split.py", line 2176, in train_test_split default_test_size=0.25) File "/usr/local/lib64/python3.7/site-packages/sklearn/model_selection/_split.py", line 1861, in _validate_shuffle_split train_size) ValueError: With n_samples=0, test_size=0.2 and train_size=None, the resulting train set will be empty. Adjust any of the aforementioned parameters.
■TensorFlow(ディープラーニング)
TensorFlow(テンソルフロー)は物体認識の分野で圧倒的な性能を示すようになり、 今は画像・音声・自然言語処理など、さまざまな分野で活用されている TensorFlow https://www.tensorflow.org/ Googleがオープンソースで公開している機械学習ライブラリで、機械学習やディープラーニングを実践できる Gmailでの迷惑メール除去にも使われているらしい スパムはいらない ―― TensorFlow を使って Gmail から新たに 1 億以上のスパム メッセージを除去 | Google Cloud Blog https://cloud.google.com/blog/ja/products/gcp/ridding-gmail-of-100-million-more-spam-messages-with-t... ■テンソル ディープラーニングの数学「スカラー・ベクトル・行列・テンソル」とは? | あぱーブログ https://blog.apar.jp/deep-learning/12121/ 「テンソル」「ベクトル」「行列」とは?ディープラーニングの情報整理のカラクリ 連載:図でわかる3分間AIキソ講座|ビジネス+IT https://www.sbbit.jp/article/cont1/63580 ディープラーニングでは、複雑なニューラルネットワーク上で膨大な数の数値がやりとりされる コンピュータではこれらの数値を扱うことができるが、数値の羅列だと人間には理解しづらく、技術の応用や発展も難しい そこで使われるようになったのが「テンソル(Tensor)」という数学的概念 基本的には「たくさんの数値を集めて、1つの情報として表現する」のがテンソル スカラーは単なる数値 スカラーを縦もしくは横に並べたものをベクトルという スカラーを縦横に並べたものを行列という 上記も含めて、スカラーを縦横斜めなど複数に並べたものをまとめて「テンソル」と呼ぶ これはプログラムの配列をイメージすると解りやすい 0次元テンソル … 0次元の配列(スカラー) 1次元テンソル … 1次元の配列(ベクトル) 2次元テンソル … 2次元の配列(行列) 3次元テンソル … 3次元の配列 4次元テンソル … 4次元の配列 X次元テンソル … X次元の配列 例えば2次元の配列なら「行列」という呼び方があるが、3次元以上になると決まった呼び方がない よって「3次元のテンソル」や「3階のテンソル」などと呼ぶ TensorFlowでは、グラフを構成するすべてのものをテンソルとして扱う ■TensorFlowのインストール $ sudo apt install libatlas-base-dev $ sudo pip3 install tensorflow Raspberry Pi 4 4B-32GB の環境ではインストールできた Raspberry Pi 3 Model b+ の環境では以下のエラーになったが、「sudo pip3 install tensorflow」を3回目でインストールに成功した Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple Collecting tensorflow Downloading https://www.piwheels.org/simple/tensorflow/tensorflow-1.13.1-cp37-none-linux_armv7l.whl (93.2MB) 85% |■■■■■■■■■■■■■■ | 79.8MB 2.3MB/s eta 0:00:06 THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the package versions, please update the hashes. Otherwise, examine the package contents carefully; someone may have tampered with them. tensorflow from https://www.piwheels.org/simple/tensorflow/tensorflow-1.13.1-cp37-none-linux_armv7l.whl#sha256=25f4f... Expected sha256 25f4ff027beec1e568baf8e90a07bad59d354560533d6b37318b9efeb70beeb1 Got 4d215130b13d9606e91a2327383cf98e603e9e53294c2d68c59e8b5224e8a923 以下で動作確認 $ python3 Python 3.7.3 (default, Apr 3 2019, 05:39:12) [GCC 8.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import tensorflow as tf >>> sess = tf.Session() >>> hello = tf.constant('Hello.') >>> print(sess.run(hello)) b'Hello.' >>> exit() Raspberry Pi 4 4B-32GB の環境では「import tensorflow as tf」を実行したときに以下の警告が表示されたが動作した 2021-02-06 14:47:10.086584: E tensorflow/core/platform/hadoop/hadoop_file_system.cc:132] HadoopFileSystem load error: libhdfs.so: cannot open shared object file: No such file or directory Raspberry Pi 3 Model b+ の環境では「import tensorflow as tf」を実行したときに以下の警告が表示されたが動作した Pythonのバージョン次第で表示されないらしいが、いったんこのまま進める WARNING:tensorflow:From /usr/local/lib/python3.7/dist-packages/tensorflow/__init__.py:98: The name tf.AUTO_REUSE is deprecated. Please use tf.compat.v1.AUTO_REUSE instead. WARNING:tensorflow:From /usr/local/lib/python3.7/dist-packages/tensorflow/__init__.py:98: The name tf.AttrValue is deprecated. Please use tf.compat.v1.AttrValue instead. WARNING:tensorflow:From /usr/local/lib/python3.7/dist-packages/tensorflow/__init__.py:98: The name tf.COMPILER_VERSION is deprecated. Please use tf.version.COMPILER_VERSION instead. WARNING:tensorflow:From /usr/local/lib/python3.7/dist-packages/tensorflow/__init__.py:98: The name tf.CXX11_ABI_FLAG is deprecated. Please use tf.sysconfig.CXX11_ABI_FLAG instead. WARNING:tensorflow:From /usr/local/lib/python3.7/dist-packages/tensorflow/__init__.py:98: The name tf.ConditionalAccumulator is deprecated. Please use tf.compat.v1.ConditionalAccumulator instead. Raspberry PiにTensorFlowをインストールして基本的な分類サンプル実行まで試した - Qiita https://qiita.com/hidakanoko/items/5292ca79e3ff53867e40 RaspberryPiで機械学習TensorFlowセットアップ - Qiita https://qiita.com/totoshi/items/7eb690926eebafdb49ff Raspbian に公式対応した TensorFlow を入れてみたら警告が出たのでどうにかしてみたって話 - Qiita https://qiita.com/ktooi/items/48a8d18839cae7246c0b ■TensorFlowのインストール(CentOS7) 以下などを試したがインストールできず # pip3 install tensorflow # pip3 install --upgrade https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-1.8.0-py3-none-any.whl # pip3 install tensorflow-gpu==2.4 # pip3 install tensorflow-gpu==1.14.0 # yum -y groupinstall "Base" "Development tools" # pip3 install tensorflow # yum -y install python3-devel # pip3 install tensorflow # pip3 install tensorflow-gpu==1.14.0 # pip3 install tensorflow==2.0.0b1 TensorFlow のインストール https://docs.vmware.com/jp/VMware-vSphere-Bitfusion/3.0/Example-Guide/GUID-1C053853-4D83-4D94-A6F3-D... 以下のエラーメッセージによると、「-std=gnu99」のオプションが問題になっているようだが対応方法が判らず # pip3 install tensorflow==2.0.0b1 gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -D_WIN32_WINNT=1536 -DGPR_BACKWARDS_COMPATIBILITY_MODE=1 -DHAVE_CONFIG_H=1 -DGRPC_ENABLE_FORK_SUPPORT=1 -DPyMODINIT_FUNC=extern "C" __attribute__((visibility ("default"))) PyObject* -DGRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK=1 -Isrc/python/grpcio -Iinclude -I. -Ithird_party/abseil-cpp -Ithird_party/address_sorting/include -Ithird_party/cares -Ithird_party/cares/cares -Ithird_party/cares/config_linux -Ithird_party/re2 -Ithird_party/boringssl-with-bazel/src/include -Ithird_party/upb -Isrc/core/ext/upb-generated -Isrc/core/ext/upbdefs-generated -Ithird_party/xxhash -Ithird_party/zlib -I/usr/include/python3.6m -c src/python/grpcio/grpc/_cython/cygrpc.cpp -o python_build/temp.linux-x86_64-3.6/src/python/grpcio/grpc/_cython/cygrpc.o -std=c++11 -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions -pthread cc1plus: warning: command line option ‘-std=gnu99’ is valid for C/ObjC but not for C++ [enabled by default] 〜中略〜 Traceback (most recent call last): File "/tmp/pip-build-nppnb9ij/grpcio/src/python/grpcio/commands.py", line 286, in build_extensions build_ext.build_ext.build_extensions(self) File "/usr/lib64/python3.6/distutils/command/build_ext.py", line 448, in build_extensions self._build_extensions_serial() File "/usr/lib64/python3.6/distutils/command/build_ext.py", line 473, in _build_extensions_serial self.build_extension(ext) File "/usr/local/lib/python3.6/site-packages/setuptools/command/build_ext.py", line 202, in build_extension _build_ext.build_extension(self, ext) File "/usr/lib64/python3.6/distutils/command/build_ext.py", line 533, in build_extension depends=ext.depends) File "/usr/lib64/python3.6/distutils/ccompiler.py", line 574, in compile self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) File "/usr/lib64/python3.6/distutils/unixccompiler.py", line 129, in _compile raise CompileError(msg) distutils.errors.CompileError: command 'gcc' failed with exit status 1 ---------------------------------------- Command "/usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-nppnb9ij/grpcio/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-dqgchcji-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-build-nppnb9ij/grpcio/ -std=c99と-std=gnu99は同じ? - bugfix https://pneumaster.hatenadiary.org/entry/20081224/p1 ■足し算を行う
import tensorflow as tf # 定数を定義 a = tf.constant(100) b = tf.constant(30) # 演算を定義 add_op = a + b # セッションを開始する sess = tf.Session() # 式を評価する res = sess.run(add_op) print(res)
■データフローログ $ sudo mkdir logs $ sudo chown smbuser. logs $ sudo chmod 0777 logs
import tensorflow as tf # 定数を定義 a = tf.constant(10, name='10') b = tf.constant(20, name='20') c = tf.constant(30, name='30') # 演算を定義 add_op = tf.add(a, b, name='add') mul_op = tf.multiply(add_op, c, name='mul') # セッションを開始する sess = tf.Session() # 式を評価する res = sess.run(mul_op) print(res) # TensorBoardのためにグラフを出力 tf.summary.FileWriter('./logs', sess.graph)
プログラム実行後、tensorboard コマンドでデータフローグラフを表示できる $ python3 test_mul_tb.py $ tensorboard --logdir=./logs 2021-02-06 15:06:32.558996: E tensorflow/core/platform/hadoop/hadoop_file_system.cc:132] HadoopFileSystem load error: libhdfs.so: cannot open shared object file: No such file or directory Serving TensorBoard on localhost; to expose to the network, use a proxy or pass --bind_all TensorBoard 2.0.2 at http://localhost:6006/ (Press CTRL+C to quit) Raspberry Pi にGUIでアクセスし、ブラウザを起動して以下にアクセスすると「TensorBoard」が表示された http://localhost:6006/ Raspberry Pi 3 Model b+ の環境では以下のエラーになって動作しなかった $ tensorboard --logdir=./logs WARNING:tensorflow:From /usr/local/lib/python3.7/dist-packages/tensorflow/__init__.py:98: The name tf.AUTO_REUSE is deprecated. Please use tf.compat.v1.AUTO_REUSE instead. WARNING:tensorflow:From /usr/local/lib/python3.7/dist-packages/tensorflow/__init__.py:98: The name tf.AttrValue is deprecated. Please use tf.compat.v1.AttrValue instead. WARNING:tensorflow:From /usr/local/lib/python3.7/dist-packages/tensorflow/__init__.py:98: The name tf.COMPILER_VERSION is deprecated. Please use tf.version.COMPILER_VERSION instead. WARNING:tensorflow:From /usr/local/lib/python3.7/dist-packages/tensorflow/__init__.py:98: The name tf.CXX11_ABI_FLAG is deprecated. Please use tf.sysconfig.CXX11_ABI_FLAG instead. WARNING:tensorflow:From /usr/local/lib/python3.7/dist-packages/tensorflow/__init__.py:98: The name tf.ConditionalAccumulator is deprecated. Please use tf.compat.v1.ConditionalAccumulator instead. Traceback (most recent call last): File "/usr/local/bin/tensorboard", line 6, in <module> from tensorboard.main import run_main File "/usr/local/lib/python3.7/dist-packages/tensorboard/main.py", line 44, in <module> from tensorboard import default File "/usr/local/lib/python3.7/dist-packages/tensorboard/default.py", line 44, in <module> from tensorboard.plugins.interactive_inference import interactive_inference_plugin File "/usr/local/lib/python3.7/dist-packages/tensorboard/plugins/interactive_inference/interactive_inference_plugin.py", line 27, in <module> from grpc.framework.interfaces.face.face import AbortionError File "/usr/local/lib/python3.7/dist-packages/grpc/__init__.py", line 23, in <module> from grpc._cython import cygrpc as _cygrpc ImportError: /usr/local/lib/python3.7/dist-packages/grpc/_cython/cygrpc.cpython-37m-arm-linux-gnueabihf.so: undefined symbol: __atomic_exchange_8 ■TensorFlowでアヤメの分類 TensorFlowでは、ラベルデータを「One-Hotベクトル」という形式で表す必要がある これは「1つだけHight(1)の状態で、他はLow(0)の状態であるようなビット列のことを指す」 iris.csv は「Pandas(データ解析支援)でアヤメの分類」で使用したものと同じ
import tensorflow as tf import pandas as pd from sklearn.model_selection import train_test_split # アヤメデータの読み込み iris_data = pd.read_csv("iris.csv", encoding="utf-8") # アヤメデータをラベルと入力データに分離する y_labels = iris_data.loc[:,"Name"] x_data = iris_data.loc[:,["SepalLength","SepalWidth","PetalLength","PetalWidth"]] # ラベルデータをone-hotベクトルに直す labels = { 'Iris-setosa': [1, 0, 0], 'Iris-versicolor': [0, 1, 0], 'Iris-virginica': [0, 0, 1] } y_nums = list(map(lambda v : labels[v] , y_labels)) # 学習用とテスト用に分離する x_train, x_test, y_train, y_test = train_test_split( x_data, y_nums, train_size=0.8) # アヤメデータの入力値(4次元)と出力値(3次元)を入れる場所を定義 x = tf.placeholder(tf.float32, [None, 4]) y_ = tf.placeholder(tf.float32, [None, 3]) # 重みとバイアスのための変数を定義 w = tf.Variable(tf.zeros([4, 3])) # 重み b = tf.Variable(tf.zeros([3])) # バイアス # ソフトマックス回帰を定義 y = tf.nn.softmax(tf.matmul(x, w) + b) # モデルを訓練する cross_entropy = -tf.reduce_sum(y_ * tf.log(y)) optimizer = tf.train.AdamOptimizer(0.05) train = optimizer.minimize(cross_entropy) # 正解率を求める predict = tf.equal(tf.argmax(y, 1), tf.argmax(y_,1)) accuracy = tf.reduce_mean(tf.cast(predict, tf.float32)) # 変数を初期化 init = tf.global_variables_initializer() sess = tf.Session() sess.run(init) # 変数を初期化 init = tf.global_variables_initializer() sess = tf.Session() sess.run(init) # 学習を行う train_feed_dict = {x: x_train, y_: y_train} for step in range(300): sess.run(train, feed_dict=train_feed_dict) # テストデータで最終的な正解率を求める acc = sess.run(accuracy, feed_dict={x: x_test, y_: y_test}) print("正解率=", acc)
$ python3.7 iris.py 2021-02-20 12:43:47.841792: E tensorflow/core/platform/hadoop/hadoop_file_system.cc:132] HadoopFileSystem load error: libhdfs.so: cannot open shared object file: No such file or directory WARNING:tensorflow:From iris.py:25: The name tf.placeholder is deprecated. Please use tf.compat.v1.placeholder instead. WARNING:tensorflow:From iris.py:36: The name tf.log is deprecated. Please use tf.math.log instead. WARNING:tensorflow:From iris.py:37: The name tf.train.AdamOptimizer is deprecated. Please use tf.compat.v1.train.AdamOptimizer instead. WARNING:tensorflow:From iris.py:45: The name tf.global_variables_initializer is deprecated. Please use tf.compat.v1.global_variables_initializer instead. WARNING:tensorflow:From iris.py:46: The name tf.Session is deprecated. Please use tf.compat.v1.Session instead. 正解率= 0.96666664 「E tensorflow/core/platform/hadoop/hadoop_file_system.cc:132」のエラーが表示されているが、実行に問題は無いようなのでいったん無視しておく Pythonおよび機械学習勉強用のRaspberryPiの構築 (RaspberryPi4 & Buster版 (RaspberryPi3も可)) - Qiita https://qiita.com/rhene/items/d370a3b3f05a7248bd79 Raspberry Pi 4 で機械学習系のパッケージを入れる(numpy, scipy, pandas, sklearn, matplotlib, tensorflow, keras) - 工作と競馬2 https://dekuo-03.hatenablog.jp/entry/2020/02/01/000000_1
■TensorFlow+Keras(ディープラーニング)
KerasはTensorFlowを簡単に使えるようにするためのライブラリだったが、使いやすかったのでTensorFlowに取り込まれた ■Kerasでアヤメの分類 モデル定義部分にある「Dense」というのは、全結合ニューラルネットワーク つまり「keras.layers.Dense」だけで1つのニューラルネットワークを表している 次の「keras.models.Sequential()」は、シーケンシャル(順番)にニューラルネットワークを追加するモデルを定義している 「Dense(10)」では、ユニット数が10個あるネットワークを作成している またこのモデルで最終的な出力は3次元なので、「Dense(3)」によって出力ユニット数を3次元にしている iris.csv は「Pandas(データ解析支援)でアヤメの分類」で使用したものと同じ
import tensorflow as tf #import tensorflow.contrib.keras as keras import tensorflow.keras as keras from sklearn.model_selection import train_test_split import pandas as pd import numpy as np # アヤメデータの読み込み iris_data = pd.read_csv("iris.csv", encoding="utf-8") # アヤメデータをラベルと入力データに分離する y_labels = iris_data.loc[:,"Name"] x_data = iris_data.loc[:,["SepalLength","SepalWidth","PetalLength","PetalWidth"]] # ラベルデータをone-hotベクトルに直す labels = { 'Iris-setosa': [1, 0, 0], 'Iris-versicolor': [0, 1, 0], 'Iris-virginica': [0, 0, 1] } y_nums = np.array(list(map(lambda v : labels[v] , y_labels))) x_data = np.array(x_data) # 学習用とテスト用に分割する x_train, x_test, y_train, y_test = train_test_split( x_data, y_nums, train_size=0.8) # モデル構造を定義 Dense = keras.layers.Dense model = keras.models.Sequential() model.add(Dense(10, activation='relu', input_shape=(4,))) model.add(Dense(3, activation='softmax')) # モデルを構築 model.compile( loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # 学習を実行 model.fit(x_train, y_train, batch_size=20, epochs=300) # モデルを評価 score = model.evaluate(x_test, y_test, verbose=1) print('正解率=', score[1], 'loss=', score[0])
実行するとエラーになるようになっていたが、 $ python3 keras-iris.py 2021-02-06 15:24:33.126208: E tensorflow/core/platform/hadoop/hadoop_file_system.cc:132] HadoopFileSystem load error: libhdfs.so: cannot open shared object file: No such file or directory Traceback (most recent call last): File "keras-iris.py", line 2, in <module> import tensorflow.contrib.keras as keras ModuleNotFoundError: No module named 'tensorflow.contrib' kerasの読み込み部分を以下のようにすれば実行できた バージョンアップによって読み込み方法が変わったのかもしれない
#import tensorflow.contrib.keras as keras import tensorflow.keras as keras
以下で実行できた $ python3.7 keras-iris.py 2021-02-20 12:48:40.802940: E tensorflow/core/platform/hadoop/hadoop_file_system.cc:132] HadoopFileSystem load error: libhdfs.so: cannot open shared object file: No such file or directory WARNING:tensorflow:From /usr/local/lib/python3.7/dist-packages/tensorflow_core/python/ops/resource_variable_ops.py:1630: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version. Instructions for updating: If using Keras pass *_constraint arguments to layers. Train on 120 samples Epoch 1/300 120/120 [==============================] - 0s 1ms/sample - loss: 2.6795 - acc: 0.3583 Epoch 2/300 120/120 [==============================] - 0s 131us/sample - loss: 2.4687 - acc: 0.3583 Epoch 3/300 120/120 [==============================] - 0s 132us/sample - loss: 2.2803 - acc: 0.3583 〜中略〜 Epoch 298/300 120/120 [==============================] - 0s 143us/sample - loss: 0.1543 - acc: 0.9833 Epoch 299/300 120/120 [==============================] - 0s 142us/sample - loss: 0.1536 - acc: 0.9833 Epoch 300/300 120/120 [==============================] - 0s 143us/sample - loss: 0.1531 - acc: 0.9833 30/30 [==============================] - 0s 2ms/sample - loss: 0.1132 - acc: 0.9667 正解率= 0.96666664 loss= 0.11321666091680527 ■学習メモ book-mlearn-gyomu/tf-iris.py at master - kujirahand/book-mlearn-gyomu - GitHub https://github.com/kujirahand/book-mlearn-gyomu/blob/master/src/ch5/iris/tf-iris.py book-mlearn-gyomu/keras-iris.py at master - kujirahand/book-mlearn-gyomu - GitHub https://github.com/kujirahand/book-mlearn-gyomu/blob/master/src/ch5/iris/keras-iris.py 【Pythonステップアップ!】高階関数mapの便利な使い方 | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト https://www.sejuku.net/blog/24759 Pythonのlambdaって分かりやすい - Qiita https://qiita.com/nagataaaas/items/531b1fc5ce42a791c7df
■TensorFlow+Keras(ディープラーニング)で手書き数字の判定
■MNISTデータの利用 MNISTのデータは、白黒画像の手書き数字のデータセット 学習用の画像に6万枚、テスト用の画像に1万枚もの画像が用意されている sklearnのデータセットに比べると、質も量も大きなデータセット $ sudo pip3 install keras
#import keras #from keras.datasets import mnist from tensorflow.keras.datasets import mnist from matplotlib import pyplot # MNISTのデータを読み込む (x_train, y_train), (x_test, y_test) = mnist.load_data() # データを 4x8 に出力 for i in range(0, 32): pyplot.subplot(4, 8, i + 1) pyplot.imshow(x_train[i], cmap='gray') # 画像に保存する pyplot.savefig("output.png")
初回実行時は、以下からMNISTデータのダウンロードが行われる メモリ不足になるとダウンロードに失敗することがあるらしいので注意する https://s3.amazonaws.com/img-datasets/mnist.npz ■多層パーセプトロン(Multilayer perceptron)で画像認識
# MLPでMNISTの分類問題に挑戦 #import keras #from keras.models import Sequential #from keras.layers import Dense, Dropout #from keras.optimizers import RMSprop #from keras.datasets import mnist import tensorflow.keras as keras from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout from tensorflow.keras.optimizers import RMSprop from tensorflow.keras.datasets import mnist import matplotlib.pyplot as plt # 入力と出力を指定 in_size = 28 * 28 out_size = 10 # MNISTのデータを読み込み (X_train, y_train), (X_test, y_test) = mnist.load_data() X_train = X_train[0:in_size * 20] y_train = y_train[0:in_size * 20] X_test = X_test[0:in_size * 20] y_test = y_test[0:in_size * 20] # データを28*28=784の一次元配列に変換 X_train = X_train.reshape(-1, 784).astype('float32') / 255 X_test = X_test.reshape(-1, 784).astype('float32') / 255 # ラベルデータをone-hotベクトルに直す #y_train = keras.utils.np_utils.to_categorical(y_train.astype('int32'),10) #y_test = keras.utils.np_utils.to_categorical(y_test.astype('int32'),10) y_train = keras.utils.to_categorical(y_train.astype('int32'),10) y_test = keras.utils.to_categorical(y_test.astype('int32'),10) # MLPモデル構造を定義 model = Sequential() model.add(Dense(512, activation='relu', input_shape=(in_size,))) model.add(Dropout(0.2)) model.add(Dense(512, activation='relu')) model.add(Dropout(0.2)) model.add(Dense(out_size, activation='softmax')) # モデルをコンパイル model.compile( loss='categorical_crossentropy', optimizer=RMSprop(), metrics=['accuracy']) # 学習を実行 hist = model.fit(X_train, y_train, batch_size=64, epochs=30, verbose=1, validation_data=(X_test, y_test)) # モデルを評価 score = model.evaluate(X_test, y_test, verbose=1) print('正解率=', score[1], 'loss=', score[0]) # # 学習の様子をグラフへ描画 # # 正解率の推移をプロット # plt.plot(hist.history['acc']) # plt.plot(hist.history['val_acc']) # plt.title('Accuracy') # plt.legend(['train', 'test'], loc='upper left') # plt.show() # # # ロスの推移をプロット # plt.plot(hist.history['loss']) # plt.plot(hist.history['val_loss']) # plt.title('Loss') # plt.legend(['train', 'test'], loc='upper left') # plt.show()
Raspberry Pi 3 Model b+ 環境では15分以上かかった Raspberry Pi 4 4B-32GB 環境では10分程度かかった また X_train = X_train[0:in_size * 20] y_train = y_train[0:in_size * 20] X_test = X_test[0:in_size * 20] y_test = y_test[0:in_size * 20] の処理を入れないと X_train = X_train.reshape(-1, 784).astype('float32') / 255 部分で MemoryError のエラーになって処理が止まった ■学習結果の保存と読み込み 「学習を実行」の直後に以下の処理を記述すると、学習結果をファイルに保存できる
# 学習結果を保存 model.save_weights('mnist-mlp.h5')
またその後、「学習を実行」の処理の代わりに以下を記述すると、学習結果を読み込んで使用できる 学習には非常に時間がかかることがあるので、これにより処理時間を大幅に短縮できる
# 学習結果を読み込み model.load_weights('mnist-mlp.h5')
ただし、Raspberry Pi 4 4B-32GB 環境では以下のエラーになった AttributeError: 'str' object has no attribute 'decode' 【Keras】エラー 'str' object has no attribute 'decode'について - Qiita https://qiita.com/Hiroki-Fujimoto/items/b078bfb680fb710c38c1 Python 3.x - 【機械学習】学習済みkerasモデルのロードが出来ない|teratail https://teratail.com/questions/306240 以下でh5pyをバージョン指定でインストールしてみる なお sudo でroot権限で実行しようとすると、「sudo: pip3.7: コマンドが見つかりません」のエラーになった $ pip3.7 install h5py==2.10.0 $ pip3.7 show h5py Name: h5py Version: 2.10.0 Summary: Read and write HDF5 files from Python Home-page: http://www.h5py.org Author: Andrew Collette Author-email: andrew.collette@gmail.com License: BSD Location: /home/pi/.local/lib/python3.7/site-packages Requires: six, numpy Required-by: Keras, Keras-Applications これで、以下で実行できるようになった $ python3.7 keras-perceptron.py 2021-02-20 13:07:23.519644: E tensorflow/core/platform/hadoop/hadoop_file_system.cc:132] HadoopFileSystem load error: libhdfs.so: cannot open shared object file: No such file or directory Unable to init server: Could not connect: Connection refused Unable to init server: Could not connect: Connection refused (keras-perceptron.py:17547): Gdk-CRITICAL **: 13:07:28.524: gdk_cursor_new_for_display: assertion 'GDK_IS_DISPLAY (display)' failed (keras-perceptron.py:17547): Gdk-CRITICAL **: 13:07:28.527: gdk_cursor_new_for_display: assertion 'GDK_IS_DISPLAY (display)' failed WARNING:tensorflow:From /usr/local/lib/python3.7/dist-packages/tensorflow_core/python/ops/resource_variable_ops.py:1630: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version. Instructions for updating: If using Keras pass *_constraint arguments to layers. 10000/10000 [==============================] - 4s 438us/sample - loss: 0.4175 - acc: 0.9662 正解率= 0.9662 loss= 0.4175194102861721 最初以下でインストールしようとしたが、pip3.7 には影響しなかった(pip3 にのみ影響した) 一つの環境に複数のPythonのバージョンを同居させているための問題だと思われる $ sudo pip3 install h5py==2.10.0 $ pip3 show h5py ■畳み込みニューラルネットワーク(Convolutional Neural Network)で画像認識 深層学習(ディープラーニング)の原理、CNN、RNN、LSTM,GANを図解で解説 | TickTack World http://gagbot.net/machine-learning/ml4 Convolutional Neural Network(CNN)は画像認識で実績のあるニューラルネットワーク
# CNNでMNISTの分類問題に挑戦 #import keras #from keras.models import Sequential #from keras.layers import Dense, Dropout, Flatten #from keras.layers import Conv2D, MaxPooling2D #from keras.optimizers import RMSprop #from keras.datasets import mnist import tensorflow.keras as keras from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout, Flatten from tensorflow.keras.layers import Conv2D, MaxPooling2D from tensorflow.keras.optimizers import RMSprop from tensorflow.keras.datasets import mnist import matplotlib.pyplot as plt # 入力と出力を指定 im_rows = 28 # 画像の縦ピクセルサイズ im_cols = 28 # 画像の横ピクセルサイズ im_color = 1 # 画像の色空間/グレイスケール in_shape = (im_rows, im_cols, im_color) in_size = 28 * 28 out_size = 10 # MNISTのデータを読み込み (X_train, y_train), (X_test, y_test) = mnist.load_data() X_train = X_train[0:in_size * 2] y_train = y_train[0:in_size * 2] X_test = X_test[0:in_size * 2] y_test = y_test[0:in_size * 2] # 読み込んだデータをの三次元配列に変換 X_train = X_train.reshape(-1, im_rows, im_cols, im_color) X_train = X_train.astype('float32') / 255 X_test = X_test.reshape(-1, im_rows, im_cols, im_color) X_test = X_test.astype('float32') / 255 # ラベルデータをone-hotベクトルに直す #y_train = keras.utils.np_utils.to_categorical(y_train.astype('int32'),10) #y_test = keras.utils.np_utils.to_categorical(y_test.astype('int32'),10) y_train = keras.utils.to_categorical(y_train.astype('int32'),10) y_test = keras.utils.to_categorical(y_test.astype('int32'),10) # CNNモデル構造を定義 model = Sequential() model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=in_shape)) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(out_size, activation='softmax')) # モデルをコンパイル model.compile( loss='categorical_crossentropy', optimizer=RMSprop(), metrics=['accuracy']) # 学習を実行 hist = model.fit(X_train, y_train, batch_size=128, epochs=12, verbose=1, validation_data=(X_test, y_test)) # 学習結果を保存 #model.save_weights('mnist-cnn.h5') # 学習結果を読み込み #model.load_weights('mnist-cnn.h5') # モデルを評価 score = model.evaluate(X_test, y_test, verbose=1) print('正解率=', score[1], 'loss=', score[0])
$ python3.7 keras-cnn.py 2021-02-20 13:17:35.353177: E tensorflow/core/platform/hadoop/hadoop_file_system.cc:132] HadoopFileSystem load error: libhdfs.so: cannot open shared object file: No such file or directory Unable to init server: Could not connect: Connection refused Unable to init server: Could not connect: Connection refused (keras-cnn.py:17621): Gdk-CRITICAL **: 13:17:40.334: gdk_cursor_new_for_display: assertion 'GDK_IS_DISPLAY (display)' failed (keras-cnn.py:17621): Gdk-CRITICAL **: 13:17:40.337: gdk_cursor_new_for_display: assertion 'GDK_IS_DISPLAY (display)' failed WARNING:tensorflow:From /usr/local/lib/python3.7/dist-packages/tensorflow_core/python/ops/resource_variable_ops.py:1630: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version. Instructions for updating: If using Keras pass *_constraint arguments to layers. Train on 1568 samples, validate on 1568 samples Epoch 1/12 1568/1568 [==============================] - 17s 11ms/sample - loss: 1.5820 - acc: 0.4847 - val_loss: 1.0910 - val_acc: 0.6429 Epoch 2/12 1568/1568 [==============================] - 17s 11ms/sample - loss: 0.6963 - acc: 0.7953 - val_loss: 0.5761 - val_acc: 0.8240 Epoch 3/12 1568/1568 [==============================] - 17s 11ms/sample - loss: 0.4347 - acc: 0.8731 - val_loss: 0.4242 - val_acc: 0.8788 Epoch 4/12 1568/1568 [==============================] - 17s 11ms/sample - loss: 0.3382 - acc: 0.9062 - val_loss: 0.3544 - val_acc: 0.8992 Epoch 5/12 1568/1568 [==============================] - 17s 11ms/sample - loss: 0.2708 - acc: 0.9311 - val_loss: 0.3081 - val_acc: 0.9062 Epoch 6/12 1568/1568 [==============================] - 17s 11ms/sample - loss: 0.2152 - acc: 0.9362 - val_loss: 0.2688 - val_acc: 0.9216 Epoch 7/12 1568/1568 [==============================] - 17s 11ms/sample - loss: 0.1852 - acc: 0.9420 - val_loss: 0.2591 - val_acc: 0.9196 Epoch 8/12 1568/1568 [==============================] - 17s 11ms/sample - loss: 0.1411 - acc: 0.9547 - val_loss: 0.2451 - val_acc: 0.9203 Epoch 9/12 1568/1568 [==============================] - 17s 11ms/sample - loss: 0.1150 - acc: 0.9656 - val_loss: 0.2703 - val_acc: 0.9235 Epoch 10/12 1568/1568 [==============================] - 17s 11ms/sample - loss: 0.0993 - acc: 0.9739 - val_loss: 0.2994 - val_acc: 0.9082 Epoch 11/12 1568/1568 [==============================] - 17s 11ms/sample - loss: 0.0870 - acc: 0.9732 - val_loss: 0.2334 - val_acc: 0.9369 Epoch 12/12 1568/1568 [==============================] - 17s 11ms/sample - loss: 0.0682 - acc: 0.9777 - val_loss: 0.2361 - val_acc: 0.9324 1568/1568 [==============================] - 3s 2ms/sample - loss: 0.2361 - acc: 0.9324 正解率= 0.93239796 loss= 0.23608304721740436 Python - Kerasのto_categoricalを使おうとすると、no attributeのエラーが出てしまう。|teratail https://teratail.com/questions/277434 「学習結果を保存」の処理を有効にして学習結果を保存したあと、 「学習を実行」を「学習を実行」に変更すると、以下のように学習結果から処理を実行できる $ python3.7 keras-cnn.py 2021-02-20 13:38:18.336257: E tensorflow/core/platform/hadoop/hadoop_file_system.cc:132] HadoopFileSystem load error: libhdfs.so: cannot open shared object file: No such file or directory Unable to init server: Could not connect: Connection refused Unable to init server: Could not connect: Connection refused (keras-cnn.py:17756): Gdk-CRITICAL **: 13:38:23.309: gdk_cursor_new_for_display: assertion 'GDK_IS_DISPLAY (display)' failed (keras-cnn.py:17756): Gdk-CRITICAL **: 13:38:23.312: gdk_cursor_new_for_display: assertion 'GDK_IS_DISPLAY (display)' failed WARNING:tensorflow:From /usr/local/lib/python3.7/dist-packages/tensorflow_core/python/ops/resource_variable_ops.py:1630: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version. Instructions for updating: If using Keras pass *_constraint arguments to layers. 1568/1568 [==============================] - 4s 2ms/sample - loss: 0.2332 - acc: 0.9381 正解率= 0.93813777 loss= 0.23319860234172368 ★2021年2月にここまで再検証した
■TensorFlow+Keras(ディープラーニング)で写真に映った物体を認識
■CIFAR-10 CIFAR-10 and CIFAR-100 datasets https://www.cs.toronto.edu/~kriz/cifar.html 6万枚の画像にラベルを付けて公開しているサイト フルカラーだが、32px×32pxと小さなサイズの画像となっている ■CIFAR-10の画像を表示
from keras.datasets import cifar10 import matplotlib.pyplot as plt from PIL import Image # 画像データを読み込む (X_train, y_train), (X_test, y_test) = cifar10.load_data() plt.figure(figsize = (10, 10)) labels = ["airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck"] # 40個連続で出力する for i in range(0, 40) : im = Image.fromarray(X_train[i]) plt.subplot(5, 8, i + 1) plt.title(labels[y_train[i][0]]) plt.tick_params(labelbottom="off", bottom="off") plt.tick_params(labelleft="off", left="off") plt.imshow(im) plt.show() # 画像に保存する plt.savefig("output.png")
プログラムをはじめて実行したとき、以下のように画像のダウンロードが行われる Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz 170500096/170498071 [==============================] - 107s 1us/step ■多層パーセプトロン(Multilayer perceptron)で画像認識
import matplotlib.pyplot as plt import keras from keras.datasets import cifar10 from keras.models import Sequential from keras.layers import Dense, Dropout num_classes = 10 im_rows = 32 im_cols = 32 im_size = im_rows * im_cols * 3 # データを読み込む (X_train, y_train), (X_test, y_test) = cifar10.load_data() X_train = X_train[0:im_size * 5] y_train = y_train[0:im_size * 5] X_test = X_test[0:im_size * 5] y_test = y_test[0:im_size * 5] # データを一次元配列に変換 X_train = X_train.reshape(-1, im_size).astype('float32') / 255 X_test = X_test.reshape(-1, im_size).astype('float32') / 255 # ラベルデータをOne-Hot形式に変換 y_train = keras.utils.to_categorical(y_train, num_classes) y_test = keras.utils.to_categorical(y_test, num_classes) # モデルを定義 model = Sequential() model.add(Dense(512, activation='relu', input_shape=(im_size,))) model.add(Dense(num_classes, activation='softmax')) # モデルをコンパイル model.compile( loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) ## 学習を実行 #hist = model.fit(X_train, y_train, # batch_size=32, epochs=50, # verbose=1, # validation_data=(X_test, y_test)) # ## 学習結果を保存 #model.save_weights('cifar10-mlp.h5') # 学習結果を読み込み model.load_weights('cifar10-mlp.h5') # モデルを評価 score = model.evaluate(X_test, y_test, verbose=1) print('正解率=', score[1], 'loss=', score[0])
■畳み込みニューラルネットワーク(Convolutional Neural Network)で画像認識
import matplotlib.pyplot as plt import keras from keras.datasets import cifar10 from keras.models import Sequential from keras.models import load_model from keras.layers import Dense, Dropout, Activation, Flatten from keras.layers import Conv2D, MaxPooling2D num_classes = 10 im_rows = 32 im_cols = 32 in_shape = (im_rows, im_cols, 3) in_size = 32 * 32 # データを読み込む (X_train, y_train), (X_test, y_test) = cifar10.load_data() X_train = X_train[0:in_size * 5] y_train = y_train[0:in_size * 5] X_test = X_test[0:in_size * 5] y_test = y_test[0:in_size * 5] # データを正規化 X_train = X_train.astype('float32') / 255 X_test = X_test.astype('float32') / 255 # ラベルデータをOne-Hot形式に変換 y_train = keras.utils.to_categorical(y_train, num_classes) y_test = keras.utils.to_categorical(y_test, num_classes) ## モデルを定義 #model = Sequential() #model.add(Conv2D(32, (3, 3), padding='same', input_shape=in_shape)) #model.add(Activation('relu')) #model.add(Conv2D(32, (3, 3))) #model.add(Activation('relu')) #model.add(MaxPooling2D(pool_size=(2, 2))) #model.add(Dropout(0.25)) # #model.add(Conv2D(64, (3, 3), padding='same')) #model.add(Activation('relu')) #model.add(Conv2D(64, (3, 3))) #model.add(Activation('relu')) #model.add(MaxPooling2D(pool_size=(2, 2))) #model.add(Dropout(0.25)) # #model.add(Flatten()) #model.add(Dense(512)) #model.add(Activation('relu')) #model.add(Dropout(0.5)) #model.add(Dense(num_classes)) #model.add(Activation('softmax')) # ## モデルをコンパイル #model.compile( # loss='categorical_crossentropy', # optimizer='adam', # metrics=['accuracy']) # ## モデルを保存 #model.save('cifar10-cnn-model.h5') # モデルを読み込み model = load_model('cifar10-cnn-model.h5') ## 学習を実行 #hist = model.fit(X_train, y_train, # batch_size=32, epochs=50, # verbose=1, # validation_data=(X_test, y_test)) # ## 学習結果を保存 #model.save_weights('cifar10-cnn-weight.h5') # 学習結果を読み込み model.load_weights('cifar10-cnn-weight.h5') # モデルを評価 score = model.evaluate(X_test, y_test, verbose=1) print('正解率=', score[1], 'loss=', score[0])
■多層パーセプトロン(Multilayer perceptron)の学習結果から画像を判定
import cv2 import numpy as np import matplotlib.pyplot as plt from keras.models import Sequential from keras.layers import Dense, Dropout num_classes = 10 labels = ["airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck"] im_size = 32 * 32 * 3 # モデルを定義 model = Sequential() model.add(Dense(512, activation='relu', input_shape=(im_size,))) model.add(Dense(num_classes, activation='softmax')) # 学習結果を読み込み model.load_weights('cifar10-mlp.h5') # OpenCVを使って画像を読み込む im = cv2.imread('test-car.jpg') # 色空間を変換してリサイズ im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB) im = cv2.resize(im, (32, 32)) plt.imshow(im) # 画像を出力 plt.show() # MLPで学習した画像データに合わせる im = im.reshape(im_size).astype('float32') / 255 # 予測する r = model.predict(np.array([im]), batch_size=32, verbose=1) res = r[0] # 結果を表示する for i, acc in enumerate(res): print(labels[i], "=", int(acc * 100)) print("---") print('予測した結果=', labels[res.argmax()])
以下の結果になる $ python3 cifar10-mlp-judge.py 1/1 [==============================] - 0s 67ms/step airplane = 7 automobile = 89 bird = 0 cat = 0 deer = 0 dog = 0 frog = 0 horse = 0 ship = 0 truck = 2 --- 予測した結果= automobile ■畳み込みニューラルネットワーク(Convolutional Neural Network)の学習結果から画像を判定
import cv2 import numpy as np import matplotlib.pyplot as plt from keras.models import Sequential from keras.models import load_model from keras.layers import Dense, Dropout, Activation, Flatten from keras.layers import Conv2D, MaxPooling2D num_classes = 10 im_rows = 32 im_cols = 32 in_shape = (im_rows, im_cols, 3) in_size = 32 * 32 labels = ["airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck"] im_size = 32 * 32 * 3 # モデルを読み込み model = load_model('cifar10-cnn-model.h5') # 学習結果を読み込み model.load_weights('cifar10-cnn-weight.h5') # OpenCVを使って画像を読み込む im = cv2.imread('test-car.jpg') # 色空間を変換してリサイズ im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB) im = cv2.resize(im, (32, 32)) plt.imshow(im) # 画像を出力 plt.show() # CNNで学習した画像データに合わせる im = im.astype('float32') / 255 # 予測する r = model.predict(np.array([im]), batch_size=32, verbose=1) res = r[0] # 結果を表示する for i, acc in enumerate(res): print(labels[i], "=", int(acc * 100)) print("---") print('予測した結果=', labels[res.argmax()])
$ python3 cifar10-cnn-judge.py 1/1 [==============================] - 0s 250ms/step airplane = 0 automobile = 99 bird = 0 cat = 0 deer = 0 dog = 0 frog = 0 horse = 0 ship = 0 truck = 0 --- 予測した結果= automobile
■TensorFlow+Keras(ディープラーニング)でカタカナを判定
■文字データベースのダウンロード etlcdb http://etlcdb.db.aist.go.jp/?lang=ja 画面上部の「DOWNLOAD」から利用申請できる 申請すると、すぐにメールアドレスにダウンロードリンクとパスワードが送られてくる 今回はダウンロードページから「ETL-1」をダウンロードする ダウンロードしたファイルを展開すると、「ETL-1」というフォルダの中に14個のファイルが作成される ■データベースを画像に変換
# ETL1Cのファイルを読み込む import struct from PIL import Image, ImageEnhance import glob, os # 出力ディレクトリ outdir = "png-etl1/" if not os.path.exists(outdir): os.mkdir(outdir) # ETL1ディレクトリ以下のファイルを処理する files = glob.glob("ETL1/*") for fname in files: if fname == "ETL1/ETL1INFO": continue # 情報ファイルは飛ばす print(fname) # ETL1のデータファイルを開く f = open(fname, 'rb') f.seek(0) while True: # メタデータ+画像データの組を一つずつ読む s = f.read(2052) if not s: break # バイナリデータなのでPythonが理解できるように抽出 r = struct.unpack('>H2sH6BI4H4B4x2016s4x', s) code_ascii = r[1] code_jis = r[3] # 画像データとして取り出す iF = Image.frombytes('F', (64, 63), r[18], 'bit', 4) iP = iF.convert('L') # 画像を鮮明にして保存 dir = outdir + "/" + str(code_jis) if not os.path.exists(dir): os.mkdir(dir) fn = "{0:02x}-{1:02x}{2:04x}.png".format(code_jis, r[0], r[2]) fullpath = dir + "/" + fn #if os.path.exists(fullpath): continue enhancer = ImageEnhance.Brightness(iP) iE = enhancer.enhance(16) iE.save(fullpath, 'PNG') print("ok")
■画像をリサイズしてバイナリにまとめる
import glob import numpy as np import cv2 import matplotlib.pyplot as plt import pickle # 保存先や画像サイズの指定 out_dir = "./png-etl1" # 画像データがあるディレクトリ im_size = 25 # 画像サイズ save_file = out_dir + "/katakana.pickle" # 保存先 plt.figure(figsize=(9, 17)) # 出力画像を大きくする # カタカナの画像が入っているディレクトリから画像を取得 kanadir = list(range(177, 220+1)) kanadir.append(166) # ヲ kanadir.append(221) # ン result = [] for i, code in enumerate(kanadir): img_dir = out_dir + "/" + str(code) fs = glob.glob(img_dir + "/*") print("dir=", img_dir) # 画像を読み込んでグレイスケールに変換しリサイズする for j, f in enumerate(fs): img = cv2.imread(f) img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img = cv2.resize(img_gray, (im_size, im_size)) result.append([i, img]) # Jupyter Notebookで画像を出力 if j == 3: plt.subplot(11, 5, i + 1) plt.axis("off") plt.title(str(i)) plt.imshow(img, cmap='gray') # メモリ消費対策に読み込む数を制限 #print(str(j) + ' / ' + f) if j >= 99: break # ラベルと画像のデータを保存 pickle.dump(result, open(save_file, "wb")) plt.show() # 画像に保存する plt.savefig("output.png") print("ok")
■多層パーセプトロン(Multilayer perceptron)で学習
import numpy as np import cv2, pickle from sklearn.model_selection import train_test_split import keras # データファイルと画像サイズの指定 data_file = "./png-etl1/katakana.pickle" im_size = 25 in_size = im_size * im_size out_size = 46 # ア-ンまでの文字の数 # 保存した画像データ一覧を読み込む data = pickle.load(open(data_file, "rb")) # 画像データを0-1の範囲に直す y = [] x = [] for d in data: (num, img) = d img = img.reshape(-1).astype('float') / 255 y.append(keras.utils.np_utils.to_categorical(num, out_size)) x.append(img) x = np.array(x) y = np.array(y) # 学習用とテスト用に分離する x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, train_size = 0.8, shuffle = True) # モデル構造を定義 Dense = keras.layers.Dense model = keras.models.Sequential() model.add(Dense(512, activation='relu', input_shape=(in_size,))) model.add(Dense(out_size, activation='softmax')) # モデルをコンパイルして学習を実行 model.compile( loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) model.fit(x_train, y_train, batch_size=20, epochs=50, verbose=1, validation_data=(x_test, y_test)) # モデルを評価 score = model.evaluate(x_test, y_test, verbose=1) print('正解率=', score[1], 'loss=', score[0])
正解率= 0.6391304135322571 loss= 1.788340950012207 ※読み込む画像を100に制限しているので、正解率は低い ■畳み込みニューラルネットワーク(Convolutional Neural Network)で学習
import numpy as np import cv2, pickle from sklearn.model_selection import train_test_split import keras from keras.models import Sequential from keras.models import load_model from keras.layers import Dense, Dropout, Flatten from keras.layers import Conv2D, MaxPooling2D from keras.optimizers import RMSprop from keras.datasets import mnist import matplotlib.pyplot as plt # データファイルと画像サイズの指定 data_file = "./png-etl1/katakana.pickle" im_size = 25 out_size = 46 # ア-ンまでの文字の数 im_color = 1 # 画像の色空間/グレイスケール in_shape = (im_size, im_size, im_color) # カタカナ画像のデータセットを読み込む data = pickle.load(open(data_file, "rb")) # 画像データを変形して0-1の範囲に直す y = [] x = [] for d in data: (num, img) = d img = img.astype('float').reshape(im_size, im_size, im_color) / 255 y.append(keras.utils.np_utils.to_categorical(num, out_size)) x.append(img) x = np.array(x) y = np.array(y) # 学習用とテスト用に分離する x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, train_size = 0.8, shuffle = True) ## CNNモデル構造を定義 #model = Sequential() #model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=in_shape)) #model.add(Conv2D(64, (3, 3), activation='relu')) #model.add(MaxPooling2D(pool_size=(2, 2))) #model.add(Dropout(0.25)) # #model.add(Flatten()) #model.add(Dense(128, activation='relu')) #model.add(Dropout(0.5)) # #model.add(Dense(out_size, activation='softmax')) #model.compile( # loss='categorical_crossentropy', # optimizer=RMSprop(), # metrics=['accuracy']) # ## モデルを保存 #model.save('katakana_cnn-model.h5') # モデルを読み込み model = load_model('katakana_cnn-model.h5') ## 学習を実行して評価 #hist = model.fit(x_train, y_train, # batch_size=128, # epochs=12, # verbose=1, # validation_data=(x_test, y_test)) # ## 学習結果を保存 #model.save_weights('katakana_cnn-weight.h5') # 学習結果を読み込み model.load_weights('katakana_cnn-weight.h5') # モデルを評価 score = model.evaluate(x_test, y_test, verbose=1) print('正解率=', score[1], 'loss=', score[0])
正解率= 0.7630434632301331 loss= 0.9600743656573089 ※読み込む画像を100に制限しているので、正解率は低い それでも多層パーセプトロンよりは向上している ※読み込む画像は800まで耐えられた 800の画像をもとに判定すると、正解率は以下になった 正解率= 0.9686141014099121 loss= 0.12908870187871482 ■畳み込みニューラルネットワーク(Convolutional Neural Network)の学習結果から画像を判定
import numpy as np import cv2, pickle from sklearn.model_selection import train_test_split import keras from keras.models import Sequential from keras.models import load_model from keras.optimizers import RMSprop from keras.datasets import mnist import matplotlib.pyplot as plt # データファイルと画像サイズの指定 data_file = "./png-etl1/katakana.pickle" im_size = 25 out_size = 46 # ア-ンまでの文字の数 im_color = 1 # 画像の色空間/グレイスケール in_shape = (im_size, im_size, im_color) # カタカナ画像のデータセットを読み込む data = pickle.load(open(data_file, "rb")) # 画像データを変形して0-1の範囲に直す y = [] x = [] for d in data: (num, img) = d img = img.astype('float').reshape(im_size, im_size, im_color) / 255 y.append(keras.utils.np_utils.to_categorical(num, out_size)) x.append(img) x = np.array(x) y = np.array(y) # 学習用とテスト用に分離する x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, train_size = 0.8, shuffle = True) # モデルを読み込み model = load_model('katakana_cnn-model.h5') # 学習結果を読み込み model.load_weights('katakana_cnn-weight.h5') # モデルを評価 score = model.evaluate(x_test, y_test, verbose=1) print('正解率=', score[1], 'loss=', score[0])
■TensorFlow+Keras(ディープラーニング)で画像を判定
■FlickrのAPIを使う $ sudo pip3 install flickrapi ■Flickrから学習用の画像を取得する
# Flickrで写真を検索して、ダウンロードする from flickrapi import FlickrAPI from urllib.request import urlretrieve from pprint import pprint import os, time, sys # APIキーとシークレットの指定 key = '取得したAPIキー' secret = '取得したシークレットキー' wait_time = 1 # 待機秒数(1以上を推奨) # キーワードとディレクトリ名を指定してダウンロード def main(): go_download('ショートケーキ', 'cake') go_download('サラダ', 'salad') go_download('麻婆豆腐', 'tofu') # Flickr APIで写真を検索 def go_download(keyword, dir): # 画像の保存パスを決定 savedir = './images/' + dir if not os.path.exists(savedir): os.mkdir(savedir) # APIを使ってダウンロード flickr = FlickrAPI(key, secret, format='parsed-json') res = flickr.photos.search( text = keyword, # 検索語 per_page = 300, # 取得件数 media = 'photos', # 写真を検索 sort = 'relevance', # 検索語の関連順に並べる safe_search = 1, # セーフサーチ extras = 'url_q, license') # 検索結果を確認 photos = res['photos'] pprint(photos) try: # 1枚ずつ画像をダウンロード for i, photo in enumerate(photos['photo']): url_q = photo['url_q'] filepath = savedir + '/' + photo['id'] + '.jpg' if os.path.exists(filepath): continue print(str(i + 1) + ':download=', url_q) urlretrieve(url_q, filepath) time.sleep(wait_time) except: import traceback traceback.print_exc() if __name__ == '__main__': main()
実行すると images 内に画像が300個ずつ保存される ただし関係ない画像も保存されるので、手動で100個まで絞り込む 絞り込んだ画像は cleaned_images に保存するものとする ■画像Numpy形式に変換する
# 画像ファイルを読んでNumpy形式に変換 import numpy as np from PIL import Image import os, glob, random outfile = "photos.npz" # 保存ファイル名 max_photo = 100 # 利用する写真の枚数 photo_size = 32 # 画像サイズ x = [] # 画像データ y = [] # ラベルデータ def main(): # 各画像のフォルダを読む glob_files("./cleaned_images/cake", 0) glob_files("./cleaned_images/salad", 1) glob_files("./cleaned_images/tofu", 2) # ファイルへ保存 np.savez(outfile, x=x, y=y) print("保存しました:" + outfile, len(x)) # path以下の画像を読み込む def glob_files(path, label): files = glob.glob(path + "/*.jpg") random.shuffle(files) # 各ファイルを処理 num = 0 for f in files: if num >= max_photo: break num += 1 # 画像ファイルを読む img = Image.open(f) img = img.convert("RGB") # 色空間をRGBに img = img.resize((photo_size, photo_size)) # サイズ変更 img = np.asarray(img) x.append(img) y.append(label) if __name__ == '__main__': main()
実行すると cleaned_images 内の画像をもとに photos.npz に保存される
import numpy as np import matplotlib.pyplot as plt # 写真データを読み込み photos = np.load('photos.npz'); x = photos['x'] y = photos['y'] # 開始インデックス idx = 0 #idx = 100 #idx = 200 # pyplotで出力 plt.figure(figsize=(10, 10)) for i in range(25) : plt.subplot(5, 5, i + 1) plt.title(y[i + idx]) plt.imshow(x[i + idx]) plt.show() # 画像に保存する plt.savefig("output.png")
実行すると photos.npz の内容をもとに output.png に画像が表示される idx が 0 ならショートケーキの画像、100 にするとサラダの画像、200 にすると麻婆豆腐の画像が表示される ■画像をもとに学習する
import cnn_model import keras import matplotlib.pyplot as plt import numpy as np from sklearn.model_selection import train_test_split # 入力と出力を指定 im_rows = 32 # 画像の縦ピクセルサイズ im_cols = 32 # 画像の横ピクセルサイズ im_color = 3 # 画像の色空間 in_shape = (im_rows, im_cols, im_color) nb_classes = 3 # 写真データを読み込み photos = np.load('photos.npz') x = photos['x'] y = photos['y'] # 読み込んだデータをの三次元配列に変換 x = x.reshape(-1, im_rows, im_cols, im_color) x = x.astype('float32') / 255 # ラベルデータをone-hotベクトルに直す y = keras.utils.np_utils.to_categorical(y.astype('int32'), nb_classes) # 学習用とテスト用に分ける x_train, x_test, y_train, y_test = train_test_split( x, y, train_size=0.8) # CNNモデルを取得 model = cnn_model.get_model(in_shape, nb_classes) # 学習を実行 hist = model.fit(x_train, y_train, batch_size=32, epochs=20, verbose=1, validation_data=(x_test, y_test)) # モデルを評価 score = model.evaluate(x_test, y_test, verbose=1) print('正解率=', score[1], 'loss=', score[0]) # 学習結果を保存 model.save_weights('photos.h5')
正解率= 0.800000011920929 loss= 0.5151064833005269 正解率を上げるため、回転と反転を行って水増し学習する 300枚での学習だったが5760枚での学習となる ただし学習にかかる時間は何倍にもなる
# CNNでMNISTの分類問題に挑戦 import cnn_model import keras import matplotlib.pyplot as plt import numpy as np from sklearn.model_selection import train_test_split import cv2 # 入力と出力を指定 im_rows = 32 # 画像の縦ピクセルサイズ im_cols = 32 # 画像の横ピクセルサイズ im_color = 3 # 画像の色空間 in_shape = (im_rows, im_cols, im_color) nb_classes = 3 # 写真データを読み込み photos = np.load('photos.npz') x = photos['x'] y = photos['y'] # 読み込んだデータをの三次元配列に変換 x = x.reshape(-1, im_rows, im_cols, im_color) x = x.astype('float32') / 255 # ラベルデータをone-hotベクトルに直す y = keras.utils.np_utils.to_categorical(y.astype('int32'), nb_classes) # 学習用とテスト用に分ける x_train, x_test, y_train, y_test = train_test_split( x, y, train_size=0.8) # 学習用データを水増しする x_new = [] y_new = [] for i, xi in enumerate(x_train): yi = y_train[i] for ang in range(-30, 30, 5): # 回転させる center = (16, 16) # 回転の中心点 mtx = cv2.getRotationMatrix2D(center, ang, 1.0) xi2 = cv2.warpAffine(xi, mtx, (32, 32)) x_new.append(xi2) y_new.append(yi) # さらに左右反転させる xi3 = cv2.flip(xi2, 1) x_new.append(xi3) y_new.append(yi) # 水増しした画像を学習用に置き換える print('水増し前=', len(y_train)) x_train = np.array(x_new) y_train = np.array(y_new) print('水増し後=', len(y_train)) # CNNモデルを取得 model = cnn_model.get_model(in_shape, nb_classes) # 学習を実行 hist = model.fit(x_train, y_train, batch_size=64, epochs=20, verbose=1, validation_data=(x_test, y_test)) # モデルを評価 score = model.evaluate(x_test, y_test, verbose=1) print('正解率=', score[1], 'loss=', score[0]) # 学習結果を保存 model.save_weights('photos2.h5')
正解率= 0.9666666388511658 loss= 0.4047759254773458 ■オリジナル画像をもとに判定する
import cnn_model import keras import matplotlib.pyplot as plt import numpy as np from PIL import Image import matplotlib.pyplot as plt im_rows = 32 # 画像の縦ピクセルサイズ im_cols = 32 # 画像の横ピクセルサイズ im_color = 3 # 画像の色空間 in_shape = (im_rows, im_cols, im_color) nb_classes = 3 LABELS = ["ショートケーキ", "サラダ", "麻婆豆腐"] CALORIES = [344, 81, 256] # 保存したCNNモデルを読み込む model = cnn_model.get_model(in_shape, nb_classes) model.load_weights('photos2.h5') def check_photo(path): # 画像を読み込む img = Image.open(path) img = img.convert("RGB") # 色空間をRGBに img = img.resize((im_cols, im_rows)) # サイズ変更 #plt.imshow(img) #plt.show() # データに変換 x = np.asarray(img) x = x.reshape(-1, im_rows, im_cols, im_color) x = x / 255 # 予測 pre = model.predict([x])[0] idx = pre.argmax() per = int(pre[idx] * 100) return (idx, per) def check_photo_str(path): idx, per = check_photo(path) # 答えを表示 print(path, "は", LABELS[idx], "で、カロリーは", CALORIES[idx],"kcalです。") print("可能性は", per, "%です。") if __name__ == '__main__': check_photo_str('test_cake.jpg') check_photo_str('test_salad.jpg') check_photo_str('test_tofu.jpg')
test_cake.jpg は ショートケーキ で、カロリーは 344 kcalです。 可能性は 100 %です。 test_salad.jpg は サラダ で、カロリーは 81 kcalです。 可能性は 100 %です。 test_tofu.jpg は 麻婆豆腐 で、カロリーは 256 kcalです。 可能性は 97 %です。
■TensorFlow+Keras(ディープラーニング)で文章を分類
※未検証 以下で文章の分類を行っている まずはリンク先にある英語文章の分類から試したい Janomeも含めて試したい 日本語文章の分類ができるようになったら、実際のメールを元に「重要」「通常」「迷惑」などの分類を試したい Keras MLPの文章カテゴリー分類を日本語のデータセットでやってみる | cedro-blog http://cedro3.com/ai/keras-mlp-livedoor/ 数字画像の判定プログラムをベースに、バイナリデータを文章に差し替えれば文章認識に応用できるか …と思って以下をメモしたが、いったん上の方法を試す ただし「Kerasの使い方まとめ【入門者向け】」などは、試す内容に関わらず目を通しておきたい 【気温を予測してみよう!】機械学習の第一歩 | 底辺動物の雑記ブログ https://ashikapengin.com/2019/08/14/yosoku-kion/ Kerasのサンプルソースが何をやっているか読んでみる - It’s now or never https://inon29.hateblo.jp/entry/2017/06/23/183749 Kerasの使い方まとめ【入門者向け】 https://sinyblog.com/deaplearning/keras_how_to/ TensorFlowを使ってテキスト分類をしてみる。 - どん底から這い上がるまでの記録 https://www.pytry3g.com/entry/tensorflow_basic_text_classification 挑戦! word2vecで自然言語処理(Keras+TensorFlow使用):ディープラーニング習得、次の一歩(1/2 ページ) - @IT https://www.atmarkit.co.jp/ait/articles/1801/30/news139.html PythonライブラリKerasを用いたAI(ディープラーニング)による文書分類とモデルの評価 | 知のマイニング https://software-data-mining.com/python%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AAkeras%E3%82%92%E...
■機械学習メモ
■日本語処理 機械学習のための日本語前処理 - Qiita https://qiita.com/Qazma/items/0daf927e34d22617ddcd ■ディープラーニングで「娘が写っている」「娘が写っていない」「暗くて不明」を判定 定点撮影で撮りためたものから学習用データを作成する 2019年10月1日時点から、「娘が写っている」「娘が写っていない」「暗くて不明」を仕分けていく それぞれ100枚ずつ画像を用意する 10月16日くらいまででデータが揃った …が、実際に試すと正解率は6〜7割程度 チューニングでどの程度改善できるかは不明
■Windowsアプリケーション
※未検証 【Python】PythonでGUI(デスクトップ)アプリを作ってみる@Windows - SEワンタンの独学備忘録 https://www.wantanblog.com/entry/2020/07/14/224611 Pythonでデスクトップアプリを作成する時に使えるライブラリ4選【アプリの配布方法も解説】 https://sync-g.co.jp/sjobs/python-desktop/ 【超入門】Pythonによるデスクトップアプリの作り方と配布方法|エンジニアブログ https://engineer-life.dev/python-desktop-app/ ゼロからはじめるPython(46) Pythonでデスクトップアプリ作成入門 - Tkinterで肥満判定ツールを作ろう | TECH+(テックプラス) https://news.mynavi.jp/techplus/article/zeropython-46/
■2017年2月時点のメモ
■インストール http://refirio.org/view/358 2017年2月の時点で、この方法でPython+MySQLを動作させることができた(Bottleフレームワークは未検証) ただし今ならVer3でいいかも。 2018年なら、以下も参考にできそう 2018年のPythonプロジェクトのはじめかた - Qiita https://qiita.com/sl2/items/1e503952b9506a0539ea ■「import urllib」でエラー 「import urllib.request」となっている箇所を「import urllib」にして、 「urllib.request.urlretrieve」となっている箇所を「urllib.urlretrieve」にしたら何故か動いた。 Ver3から命令が整理されているらしい。 ■pip(Pythonのパッケージ管理システム) >python -m pip -V … pipのインストールを確認 pip 8.1.1 from C:\Python27\lib\site-packages (python 2.7) ■Beautiful Soup インストール >python -m pip install beautifulsoup4 HTMLの解析
# coding: UTF-8 # ライブラリの取り込み from bs4 import BeautifulSoup # 解析したいHTML html = """ <html> <body> <h1>スクレイピングとは</h1> <p>Webページを解析すること。</p> <p>任意の箇所を抽出すること。</p> </body> </html> """ # HTMLを解析する soup = BeautifulSoup(html, 'html.parser') # 任意の部分を抽出する h1 = soup.html.body.h1 p1 = soup.html.body.p p2 = p1.next_sibling.next_sibling # 要素のテキストを表示する print "h1 = " + h1.string print "p = " + p1.string print "p = " + p2.string # 完了 print "OK"
簡単なクロール
# coding: UTF-8 # ライブラリの取り込み from bs4 import BeautifulSoup import urllib # ダウンロード res = urllib.urlopen("http://stocks.finance.yahoo.co.jp/stocks/detail/?code=usdjpy") # HTMLを解析する soup = BeautifulSoup(res, 'html.parser') # 任意の部分を抽出する price = soup.select_one(".stoksPrice").string # 要素のテキストを表示する print "usd/jpy = " + price # 完了 print "OK"