nprogram’s blog

気ままに、プログラミングのトピックについて書いていきます

matplotlib基礎

はじめに

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'>

f:id:nprogram:20190424045507p:plain

複数の図を描いてみる

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)

f:id:nprogram:20190424055536p:plain

matplotlib.pyplot.subplot

グリッド上に規則正しくグラフを配置する場合はsubplotメソッドを使います。

フォーマット

subplot(行数, 列数, プロット番号)

行数 × 列数 のグリッドに figure が分割され、プロット番号の位置に座標軸が作成されます。

np.linspace

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関数の実装)

はじめに

C++で、関数型プログラミングでいうfilter関数(抽出の処理を行う関数のこと)を使う場合は、以下のテンプレート関数を使うといいです。

  • copy_if
  • remove_copy_if

コード例

以下のコード例では、ラムダ式と挿入イテレータが使用されています。

挿入イテレータ(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関数の実装

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

リンク

Keras学習入門

はじめに

公式ドキュメントを読みましょう。

Home - Keras Documentation

サンプルもあります。

https://github.com/keras-team/keras/tree/master/examples

参考にした記事

無から始めるKeras - Qiita

作りたいもの

適当な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個のニュートラルネットワークを作成します。

f:id:nprogram:20190414190509p:plain

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で画像データをFlickerで取得する

はじめに

Pythonで画像データを取得してみたいと思います。 flickr の画像取得は、flickr API を使用します。

flickrのAPIは以下に記載されています

https://www.flickr.com/services/api/

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)

mnist手書き数字画像データ学習モデル活用でjpeg画像を予測します [Python]

はじめに

手書き文字の認識を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 – 環境・生物・情報処理 -