はじめに
リカレントニューラルネットワーク学習を学習します。
リンク
https://www.infiniteloop.co.jp/blog/2018/02/learning-keras-07/
matplotlibでグラフを書きます。
import matplotlib.pyplot as plt plt.style.use('seaborn-whitegrid') import numpy as np %matplotlib inline # numpy.linspace(start, stop, num = 50, endpoint = True, retstep = False, dtype = None) # num: 生成する配列(ndarray)の要素数を指定。 # endpoint: 生成する数列において、stopを要素に含むかどうかを指定。Trueなら含み、Falseなら含まない。 # retstep: 生成された配列(ndarray)の後に公差を表示するかどうかを指定。Trueなら表示し、Falseなら非表示。 # dtype: 出力された配列(ndarray)のデータ型を指定。指定がない場合、データ型はfloat。 x = np.linspace(0, 10, 1000) print(x) print(type(x)) # figureの縦横の大きさ fig = plt.figure() # figure内の枠の大きさとどこに配置している。subplot(行の数,列の数,何番目に配置しているか) ax = plt.axes() plt.plot(x, np.sin(x)) plt.plot(x, np.cos(x))
[ 0. 0.01001001 0.02002002 0.03003003 0.04004004 0.05005005 0.06006006 0.07007007 0.08008008 0.09009009 0.1001001 0.11011011 ・・・ 9.90990991 9.91991992 9.92992993 9.93993994 9.94994995 9.95995996 9.96996997 9.97997998 9.98998999 10. ] <class 'numpy.ndarray'>
matplotlib.pyplot.subplotを使って規則正しくグラフを書きます。
2×2で4枚のグラフを描きます。
プロット番号は、左上が 1 で、右方向、下方向へいくにしたがい値が大きくなります。 たとえば、2 × 2 のグリッドの場合は
1 2
3 4
となります。
%matplotlib inline import matplotlib.pyplot as plt plt.style.use('seaborn-whitegrid') import numpy as np x = np.linspace(-3, 3, 20) y1 = x y2 = x ** 2 y3 = x ** 3 y4 = x ** 4 fig = plt.figure() # 左上 plt.subplot(2,2,1) plt.plot(x,y1) # 右上 plt.subplot(2,2,2) plt.plot(x, y2) # 左下 plt.subplot(2,2,3) plt.plot(x,y3) # 右下 plt.subplot(2,2,4) plt.plot(x,y4)
グリッド上に規則正しくグラフを配置する場合はsubplotメソッドを使います。
subplot(行数, 列数, プロット番号)
行数 × 列数 のグリッドに figure が分割され、プロット番号の位置に座標軸が作成されます。
NumPyのnp.linspaceは、線形に等間隔な数列を生成する関数です。
同様の数列をnp.arangeで生成することもできますが、np.linspaceを使用したほうがコード量を減らすことができます。
numpy.linspace(start, stop, num = 50, endpoint = True, retstep = False, dtype = None)
params:
パラメータ名 | 型 | 概要 |
---|---|---|
start | intまたはfloat | 数列の始点を指定します。 |
stop | intまたはfloat | 数列の終点を指定します。 |
num | int | (省略可能)初期値50 生成する配列(ndarray)の要素数を指定します。 |
endpoint | bool値 | (省略可能)初期値True 生成する数列において、stopを要素に含むかどうか指定します。Trueなら含み、Falseなら含みません。 |
retstep | boo値 | (省略可能)初期値False 生成された配列(ndarray)の後に公差を表示するかどうか指定します。Trueなら表示し、Falseなら非表示です。 |
dtype | dtype | (省略可能)初期値None 出力された配列(ndarray)のデータ型を指定します。dtypeが指定されない場合、データ型は基本的にはfloatになっている。 |
returns:
num等分された等差数列を要素とするndarrayが返されます。
C++で、関数型プログラミングでいうfilter関数(抽出の処理を行う関数のこと)を使う場合は、以下のテンプレート関数を使うといいです。
以下のコード例では、ラムダ式と挿入イテレータが使用されています。
挿入イテレータ(insert iterator)は、イテレータに対する代入処理を挿入処理に置き換える特殊な出力イテレータです。
#include <iostream> #include <vector> #include <numeric> #include <algorithm> using namespace std; void getCharVector(std::vector<char> &someVector, const std::string someString) { // 1文字つずつ取り出してvector<char>に格納する for (auto var : someString) { someVector.push_back(var); } } int main(void) { std::vector<char> temp; getCharVector(temp, "a1a2a3a4a5a6a7a8a9a10"); std::vector<char> filtered; // copy_ifテンプレート関数は、条件を満たした要素のみをコピーする機能 std::copy_if(temp.begin(), temp.end(), std::back_inserter(filtered), [](char c) { return c == 'a'; }); std::for_each(filtered.begin(), filtered.end(), [](char c) {std::cout << c << std::endl; }); // std::count_if とは、第3引数で与えられる単項関数(Unary function)の条件を満たす要素が配列やコンテナにいくつ含まれているか返すテンプレート関数 int sum = std::count_if(temp.begin(), temp.end(), [](char c) { return c == 'a'; }); std::cout << "total : " << sum << std::endl; }
a a a a a a a a a a total : 10
template関数を使えば、数列で文字列でも、同じfilter関数で処理できます。
#include <iostream> #include <algorithm> #include <vector> #include <cassert> template<class Container, class Predicate> Container filter(const Container& c, Predicate f) { Container r; std::copy_if(begin(c), end(c), std::back_inserter(r), f); return r; } int main(void) { // 配列をfileter template関数に渡す auto target = filter(std::vector<int>{2, 3, 4}, [](int i) { return i < 4; }); for (auto var : target) { std::cout << var << std::endl; } // std::vector::back関数は末尾要素への参照を取得する関数 assert(3 == target.back()); // 文字列をfileter template関数に渡す auto targetString = filter(std::string("a::b_c()"), isalpha); // 変数の方を調べます(std::string型で返ってきます) std::cout << typeid(targetString).name() << std::endl; for (auto var : targetString) { std::cout << var << std::endl; } assert("abc" == targetString); }
2 3 NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE a b c
公式ドキュメントを読みましょう。
サンプルもあります。
https://github.com/keras-team/keras/tree/master/examples
適当な5次元のデータ配列を入力すると、その和が2.5より大きい場合に、1と教えてくれるニュートラルネットワークを作成します。
適当なデータセットを作ります。以下は1000行、5列の2次元のデータを作成する。
random.randの1つ目の引数に行数、2つ目の引数に列数を指定します。
ここで、1つの行について考えると、列は5つあるため、1000個の5次元のデータを作成したと考えることもできます。
data = np.randam.rand(1000, 5)
array([[0.3940429 , 0.79998594, 0.58371434, 0.4746385 , 0.57960131], [0.48199409, 0.29579691, 0.6393789 , 0.79172043, 0.35938036], [0.32953348, 0.44838049, 0.60369065, 0.96091877, 0.61703259], ..., [0.40231469, 0.69186734, 0.09979942, 0.57616445, 0.99702868], [0.41718706, 0.92310164, 0.66852297, 0.69960452, 0.15955488], [0.25724677, 0.94933856, 0.18957415, 0.22025431, 0.52682667]])
import numpy as np from keras.utils import np_utils # dataは5次元のデータ data = np.random.rand(1000, 5) # sum_dataは1次元のデータ sum_data = (np.sum(data, axis=1) > 2.5) * 1
one-hotなラベルを作成します。
one-hot(ワン・ホット)は1つだけHigh(1)であり、他はLow(0)であるようなデータのことです。
from keras.utils import np_utils sum_data = (np.sum(data, axis=1) > 2.5) * 1 labels = np_utils.to_categorical(sum_data)
array([[0., 1.], [1., 0.], [1., 0.], ..., [0., 1.], [1., 0.], [0., 1.]], dtype=float32)
Sequentialは層を積み上げるだけのモデル。
今回は中間層(入力層・隠れ層・出力層)とする
入力5個、出力2個のニュートラルネットワークを作成します。
from keras.models import Sequential from keras.layers import Dense, Activation model = Sequential()
Denseというレイヤー(通常の全結合ニューラルネットワークレイヤー)を使用する。
5個のノートから、それぞれ10本矢印が出てきて、次の層のノードが10個であることを示す。 ノード数は入力データの次元数と一致する必要がある。
model.add(Dense(10, input_dim=5))
出力に活性化関数を適用します。'relu'はランプ関数です。
活性化関数は、入力信号の総和がどのように活性化するかを決定する役割を持ちます。
これは、次の層に渡す値を整えるような役割をします。
model.add(Activation('relu'))
次は隠れ層―出力層。10個のノードから(活性化関数が適用されたあと)それぞれ値がやってくる。出力は2次元で、ノードにやってきた10個の値に対して重み付き和とソフトマックス関数を使用します。
ソフトマックス関数は、活性化関数の1つで、出力層で使われる関数です。
model.add(Dense(2, activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
学習の前にコンパイルを行います。
1つめは最適化関数、2つめは損失関数、3つめは評価指標のリスト。
model.compile('rmsprop', 'categorical_crossentropy', metrics=['accuracy'])
nb_epoch は回数。validation_split は検証に使うデータの割合(全体のデータを学習に使わず、8割のみを学習に使って、残りの2割を評価に使う)。
model.fit(data, labels, nb_epoch=300, validation_split=0.2)
予測精度を判別します。
test = np.random.rand(1000, 5) ## 予測配列 predict = np.argmax(model.predict(test), axis=1) ## 正解配列 real = (np.sum(test, axis=1) > 2.5) * 1 sum(predict == real) / 1000.0
from keras.utils import np_utils from keras.models import Sequential from keras.layers import Dense, Activation import numpy as np data = np.random.rand(1000,5) data_sum = (np.sum(data, axis=1) > 2.5) * 1 labels = np_utils.to_categorical(data_sum) model = Sequential([Dense(10, input_dim=5), Activation('relu'), Dense(2, activation='softmax')]) model.compile('rmsprop', 'categorical_crossentropy', metrics=['accuracy']) model.fit(data, labels, nb_epoch=100, validation_split=0.2) test = np.random.rand(1000, 5) predict = np.argmax(model.predict(test), axis=1) real = (np.sum(test, axis=1) > 2.5) * 1 print(sum(predict == real) / 1000.0)
0.979
Pythonで画像データを取得してみたいと思います。 flickr の画像取得は、flickr API を使用します。
https://www.flickr.com/services/api/
flickrのAPIを使用して画像の情報を取得します。
コマンドプロンプト上から python [コードのファイル名] monkey と打つと画像情報を取得できます。
import flickrapi from urllib.request import urlretrieve from pprint import pprint import os, time, sys # APIキーの情報 key = "d21bac140e0245aed437c6c812f27d44" secret = "b5e79704c13a3d15" wait_time = 1 # コマンドライン引数の 1 番目の値を取得 animalname = sys.argv[1] # 画像を保存するディレクトリを指定 savedir = "./" + animalname flickr = flickrapi.FlickrAPI(key, secret, format='parsed-json') result = flickr.photos.search( # 検索キーワード text = animalname, # 取得するデータ件数 per_page = 2, # 検索するデータの種類(ここでは、写真) media = 'photos', # データの並び順(関連順) sort = 'relevance', # UI コンテンツを表示しない safe_search = 1, # 取得したいオプションの値(url_q->画像のアドレスが入っている情報、licence -> ライセンス情報) extras = 'url_q, licence' ) photos = result['photos'] # 戻り値を表示する # pprint(photos)
{'page': 1, 'pages': 498092, 'perpage': 2, 'photo': [{'farm': 4, 'height_q': '150', 'id': '15557905405', 'isfamily': 0, 'isfriend': 0, 'ispublic': 1, 'owner': '101295317@N06', 'secret': '05357b440d', 'server': '3928', 'title': 'monkey', 'url_q': 'https://live.staticflickr.com/3928/15557905405_05357b440d_q.jpg', 'width_q': '150'}, {'farm': 1, 'height_q': '150', 'id': '297887549', 'isfamily': 0, 'isfriend': 0, 'ispublic': 1, 'owner': '12345287@N00', 'secret': '2dc0ee273f', 'server': '110', 'title': 'monkey', 'url_q': 'https://live.staticflickr.com/110/297887549_2dc0ee273f_q.jpg', 'width_q': '150'}], 'total': '996183'}
次に、画像を実際にダウンロードします。
コマンドプロンプト上から python [コードのファイル名] monkey と打つと画像データがダウンロードされます。
import flickrapi from urllib.request import urlretrieve from pprint import pprint import os, time, sys # APIキーの情報 key = "d21bac140e0245aed437c6c812f27d44" secret = "b5e79704c13a3d15" wait_time = 1 # コマンドライン引数の 1 番目の値を取得 animalname = sys.argv[1] # 画像を保存するディレクトリを指定 savedir = "./" + animalname flickr = flickrapi.FlickrAPI(key, secret, format='parsed-json') result = flickr.photos.search( # 検索キーワード text = animalname, # 取得するデータ件数 per_page = 400, # 検索するデータの種類(ここでは、写真) media = 'photos', # データの並び順(関連順) sort = 'relevance', # UI コンテンツを表示しない safe_search = 1, # 取得したいオプションの値(url_q->画像のアドレスが入っている情報、licence -> ライセンス情報) extras = 'url_q, licence' ) photos = result['photos'] for i, photo in enumerate(photos['photo']): url_q = photo['url_q'] filepath = savedir + '/' + photo['id'] + '.jpg' # ファイルが重複していたらスキップする if os.path.exists(filepath): continue # データをダウンロードする urlretrieve(url_q, filepath) time.sleep(wait_time)
手書き文字の認識をNeuralnetworkを用いて行います。 Kerasから手書き文字のデータをダウンロードして、そのデータを用いて、NeuralnetworkのTrainingを行い、その後に下記のnumber_fileをTest dataとして数字の認識を実施します。
from keras import backend as K from keras.datasets import mnist from keras.layers import Activation, Dense, Dropout from keras.layers.normalization import BatchNormalization from keras.models import Sequential from keras.utils.np_utils import to_categorical import numpy as np from sklearn.metrics import classification_report, confusion_matrix # Kerasに付属の手書き数字画像データをダウンロード np.random.seed(0) (X_train, labels_train), (X_test, labels_test) = mnist.load_data() # Traning setのラベルを確認 labels_train # Training setの概要確認 print(X_train.shape, labels_train.shape, sep='\n') # Test setの概要確認 print(X_test.shape, labels_test.shape, sep='\n') # Training setの画像を表示 import matplotlib.pyplot as plt %matplotlib inline label_images = {label: [] for label in set(labels_train.tolist())} for x, label in zip(X_train, labels_train): if all(len(images) >= 10 for images in label_images.values()): break if len(label_images[label]) >= 10: continue label_images[label].append(x) for j, (label, images) in enumerate(label_images.items()): plt.subplot(10, 11, j * 11 + 1) plt.text(0.5, 0.5, label, ha='center', va='center') plt.axis('off') for i, image in enumerate(images): if i >= 10: continue plt.subplot(10, 11, j * 11 + i + 2) plt.imshow(image, cmap='Greys_r') plt.axis('off') plt.show() del label_images # Test dataの画像表示 label_images = {label: [] for label in set(labels_test.tolist())} for x, label in zip(X_test, labels_test): if all(len(images) >= 10 for images in label_images.values()): break if len(label_images[label]) >= 10: continue label_images[label].append(x) for j, (label, images) in enumerate(label_images.items()): plt.subplot(10, 11, j * 11 + 1) plt.text(0.5, 0.5, label, ha='center', va='center') plt.axis('off') for i, image in enumerate(images): if i >= 10: continue plt.subplot(10, 11, j * 11 + i + 2) plt.imshow(image, cmap='Greys_r') plt.axis('off') plt.show() del label_images ## 画像データを特微ベクトルに変換します # 各画像は行列なのでベクトルに変換→X_trainとX_testを作成 X_train = X_train.reshape(len(X_train), -1) X_test = X_test.reshape(len(X_test), -1) print(X_train.shape) print(X_train[:5]) # ラベルをone-hotベクトル(値がひとつだけ1で他が0のベクトル)に変換→Y_trainとY_testを作成 Y_train = to_categorical(labels_train) Y_test = to_categorical(labels_test) print(Y_train) print(Y_test) ## Deep learningの実施 # モデルの準備 model = Sequential() model.add(Dense(10, input_shape=(784,))) model.add(Activation('softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # Trainingの実施 model.fit(X_train, Y_train, batch_size=128, nb_epoch=10, verbose=1) # Test dataを用いてモデルを評価(accuracyを算出) _, acc = model.evaluate(X_test, Y_test, verbose=0) print('accuracy: {}'.format(acc)) # Classification_report関数で評価結果を表示 labels_pred = model.predict_classes(X_test, verbose=0) print(confusion_matrix(labels_test, labels_pred)) print(classification_report(labels_test, labels_pred)) # Training後のモデルを用いてnumber_file中の画像の数字を予測 # 必要なモジュールの読み込み import glob import os from PIL import Image (x_train, y_train), (x_test, y_test) = mnist.load_data() print(x_train.shape) print(y_train.shape) print(x_test.shape) print(y_test.shape) img_dir = 'number_file' os.makedirs(img_dir, exist_ok=True) # 全画像分を保存するようにする for data, label in zip(x_test[:1000], y_test[:1000]): img = Image.fromarray(data) # グレースケール形式で保存する。 img.save(os.path.join(img_dir, 'gray_{}.png'.format(label))) # RGB 形式で保存する。 img = img.convert('RGB') img.save(os.path.join(img_dir, 'color_{}.png'.format(label))) # フォルダ内の画像を読み込み、予測する。 for img_path in glob.glob(os.path.join(img_dir, '*.png')): # 画像を読み込む。 img = Image.open(img_path) # 画像が RGB ならグレースケールに変換する。(28, 28, 3) -> (28, 28) if img.mode == 'RGB': img = img.convert("L") # 行列を1次元に変換する(28, 28) -> (1, 784) にする。 data = np.array(img).reshape(1, -1) # データをモデルに入れて予測 pred_y = model.predict_classes(data, verbose=0) print(img_path, pred_y)
accuracy: 0.9061 [[ 961 0 2 3 0 3 8 1 2 0] [ 0 1091 25 3 1 1 3 2 9 0] [ 3 0 967 5 16 3 7 9 19 3] [ 4 0 56 870 4 37 1 8 21 9] [ 2 1 8 0 933 0 9 2 8 19] [ 11 1 15 23 24 762 10 6 36 4] [ 14 1 28 0 12 25 867 1 10 0] [ 2 5 33 4 15 0 0 943 4 22] [ 5 3 36 12 20 19 3 16 856 4] [ 9 4 2 9 109 15 1 33 16 811]] precision recall f1-score support 0 0.95 0.98 0.97 980 1 0.99 0.96 0.97 1135 2 0.83 0.94 0.88 1032 3 0.94 0.86 0.90 1010 4 0.82 0.95 0.88 982 5 0.88 0.85 0.87 892 6 0.95 0.91 0.93 958 7 0.92 0.92 0.92 1028 8 0.87 0.88 0.88 974 9 0.93 0.80 0.86 1009 micro avg 0.91 0.91 0.91 10000 macro avg 0.91 0.90 0.91 10000 weighted avg 0.91 0.91 0.91 10000 number_file\color_0.png [0] number_file\color_1.png [1] number_file\color_2.png [2] number_file\color_3.png [3] number_file\color_4.png [4] number_file\color_5.png [5] number_file\color_6.png [6] number_file\color_7.png [7] number_file\color_8.png [8] number_file\color_9.png [9] number_file\gray_0.png [0] number_file\gray_1.png [1] number_file\gray_2.png [2] number_file\gray_3.png [3] number_file\gray_4.png [4] number_file\gray_5.png [5] number_file\gray_6.png [6] number_file\gray_7.png [7] number_file\gray_8.png [8] number_file\gray_9.png [9]
Python - mnist手書き数字画像データ学習モデル活用でjpeg画像の予測ができません。|teratail
深層学習 TensorFlow を MNIST で試す(2) | ecobioinfo.com – 環境・生物・情報処理 -