Python scikit-learn - 排他的論理和(XOR)演算を学習する

機械学習で排他的論理和(XOR)を学習します。

排他的論理和(XOR)とは、2つの入力のどちらか片方が真で、もう片方が偽の時には結果が真となり、両方とも真あるいは両方とも偽のときには偽となる演算です。

排他的論理和(XOR)演算を学習する

scikit-learnという機械学習用のライブラリを使います。

[コード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from sklearn import svm

# XORの演算と結果
xor_data = [
[0, 0, 0],
[0, 1, 1],
[1, 0, 1],
[1, 1, 0]
]

# 学習させるためにデータとラベルに分ける
data = []
label = []

for row in xor_data:
data.append([row[0], row[1]])
label.append(row[2])

# データの学習
clf = svm.SVC()
clf.fit(data, label)

# データを予測
pre = clf.predict(data)
print('予測結果:', pre)

# 正解と合っているか結果を確認
cnt_ok = 0
total = 0

for idx, ans in enumerate(label):
if pre[idx] == ans:
cnt_ok += 1
total += 1

print('正解率:{} / {}'.format(cnt_ok, cnt_ok / total))

実行結果は次のようになります。

[実行結果]

予測結果: [0 1 1 0]
正解率:4 / 1.0

4つのデータにおいて4つ正解しており、正解率は100%であることが分かります。

Python Pandas - エクセルファイルの読み込み

Pandasを使ってエクセルファイルの読み込みを行います。

エクセルファイルの書き込み

次のエクセルファイルを読み込みます。

data.xls

読み込み処理は以下の通りです。

read_excel関数を使い、1行でエクセルファイルの読み込みが行えます。

またsort_values関数を使えば特定のキーでソート(並び替え)を行うことができます。

[コード]

1
2
3
4
5
6
7
import pandas as pd

book = pd.read_excel('data.xlsx', sheet_name='Sheet1')
print(book)
print()

print(book.sort_values(by='データ1', ascending=False))

実行結果は次のようになります。

[実行結果]

  都道府県  データ1  データ2
0   東京    10    40
1  北海道    20     5
2   京都    30    60

  都道府県  データ1  データ2
2   京都    30    60
1  北海道    20     5
0   東京    10    40

Python - CSVの読み書き

Ptyhonでcsvファイルの読み書きを行います。

CSVファイルの書き込み

Pythonで標準機能のcsvライブラリを使い、CSVファイルを出力します。

[コード]

1
2
3
4
5
6
7
8
import csv

with open('test.csv', 'w') as f:
writer = csv.writer(f, delimiter=',', quotechar='"',lineterminator='\n')
writer.writerow(['ID', '商品名', '値段'])
writer.writerow(['10', 'SDカード', '500'])
writer.writerow(['20', 'マウス', '300'])
writer.writerow(['30', 'マジック(赤,青)', '150'])

実行すると次のようなCSVファイルが出力されます。

[出力されるCSVファイル]

ID,商品名,値段
10,SDカード,500
20,マウス,300
30,"マジック(赤,青)",150

カンマのあるデータは、quotecharで指定した文字(ダブルクォーテーション)でくくられます。

CSVファイルの読み込み

上記で出力したCSVファイルを読み込んでみます。

[コード]

1
2
3
4
5
6
import csv

with open('test.csv', 'r') as f:
reader = csv.reader(f, delimiter=',', quotechar='"')
for cells in reader:
print(cells)

実行結果は下記の通りです。

[実行結果]

['ID', '商品名', '値段']
['10', 'SDカード', '500']
['20', 'マウス', '300']
['30', 'マジック(赤,青)', '150']

ダブルクォーテーションでくくられた中にカンマがある場合も、問題なく1つの要素として読み込まれていることが分かります。

Python - YAMLの読み書き

PtyhonのデータをYAML形式のデータにしたり、YAML形式のデータをPythonのデータにパースしたりしてみます。

YAMの読み書き

yaml.load()関数でYAML文字列をPythonデータに変換し、yaml.dump()関数でPythonデータをYAML形式で出力します。

[コード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import yaml

data = [
{"name":"Yamada", "age":"33", "gender":"man"},
{"name":"Sato", "age":"58", "gender":"woman"},
{"name":"Kato", "age":"42", "gender":"man"},
{"name":"Nishi", "age":"22", "gender":"man"}
]

# PythonのデータをYAMLに変換
str = yaml.dump(data)
print(str)
print('--- --- ---')

# YAMLをPythonデータに変換
data1 = yaml.load(str)

# Pythonデータを表示
for p in data1:
print(p)

実行結果は下記の通りです。

[実行結果]

- age: '33'
  gender: man
  name: Yamada
- age: '58'
  gender: woman
  name: Sato
- age: '42'
  gender: man
  name: Kato
- age: '22'
  gender: man
  name: Nishi
--- --- ---
{'age': '33', 'gender': 'man', 'name': 'Yamada'}
{'age': '58', 'gender': 'woman', 'name': 'Sato'}
{'age': '42', 'gender': 'man', 'name': 'Kato'}
{'age': '22', 'gender': 'man', 'name': 'Nishi'}

Python - YAMLの解析

YAMLは、インデントを使って階層構造を表現するという特徴をもったデータ形式です。

XMLよりもシンプルなのが特徴です。

PyYAMLをインストール

YAMLを扱うためにPyYAMLというライブラリをインストールします。

1
pip install pyyaml

YAMの解析

果物と値段などの一覧を、文字列にYAML形式で記述しそれをPyYAMLで解析し画面に表示します。

[コード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import yaml

str = '''
Date: 2020-04-15
PriceList:
-
item_id: 1
name: Banana
color: yellow
price: 150
-
item_id: 2
name: Orange
color: orange
price: 300
-
item_id: 3
name: Apple
color: red
price: 200
'''
# YAMLを解析
data = yaml.load(str)

print(data['Date'])
print()

for d1 in data['PriceList']:
print(d1)

実行結果は下記の通りです。

[実行結果]

2020-04-15

{'item_id': 1, 'name': 'Banana', 'color': 'yellow', 'price': 150}
{'item_id': 2, 'name': 'Orange', 'color': 'orange', 'price': 300}
{'item_id': 3, 'name': 'Apple', 'color': 'red', 'price': 200}

Python - JSONの解析(百人一首を読む)

JSONの解析を行っていきます。

JSONの解析

以下のページをJSON解析の対象とします。
http://api.aoikujira.com/hyakunin/get.php?fmt=json

百人一首APIを使って、JSON形式で百人一首をダウンロードしランダムに歌を3首表示します。

[コード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import urllib.request as req
import os.path, random
import json

# JSONをダウンロード
url = 'http://api.aoikujira.com/hyakunin/get.php?fmt=json'
savename = 'hyakunin.json'
if not os.path.exists(savename):
req.urlretrieve(url, savename)

# JSONファイルを解析
data = json.load(open(savename, 'r', encoding='utf-8'))

# ランダムに一首表示
for i in range(3):
r = random.choice(data)
print(r['kami'], r['simo'],)

実行結果は下記の通りです。

[実行結果]

恋すてふ 我が名はまだき 立ちにけり 人しれずこそ 思ひそめしか
田子の浦に うちいでてみれば 白妙の 富士の高嶺に 雪は降りつつ
あはれとも いふべき人は 思ほえで 身のいたづらに なりぬべきかな

Python - XMLの解析(地域防災拠点データを読む)

BeautifulSoupを使ってXMLの解析を行っていきます。

XMLの解析

以下のページをXML解析の対象とします。
http://archive.city.yokohama.lg.jp/somu/org/kikikanri/data/shelter.xml

shelter.xml(一部略)

このページで公開されているXML形式の地域防災拠点データを読み込んで、区ごとに防災拠点の名前一覧を出力します。

[コード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from bs4 import BeautifulSoup
import urllib.request as req
import os.path

# XMLをダウンロード
url = 'http://archive.city.yokohama.lg.jp/somu/org/kikikanri/data/shelter.xml'
savename = 'shelter.xml'
if not os.path.exists(savename):
req.urlretrieve(url, savename)

# BeautifulSoupでXMLを解析
xml = open(savename, 'r', encoding='utf-8').read()
soup = BeautifulSoup(xml, 'html.parser')

# データを各区ごとに確
info = {}
for i in soup.find_all('shelter'):
name = i.find('name').string
ward = i.find('ward').string
addr = i.find('address').string
note = i.find('notes').string
if not (ward in info):
info[ward] = []
info[ward].append(name)

# 区ごとに防災拠点を表示
for ward in info.keys():
print('+', ward)
for name in info[ward]:
print('| - ', name)

実行結果は下記の通りです。

[実行結果]

+ 鶴見区
| -  生麦小学校
| -  豊岡小学校
| -  鶴見小学校
| -  潮田小学校
| -  下野谷小学校
| -  市場小学校
| -  平安小学校
| -  末吉小学校
| -  上末吉小学校
| -  下末吉小学校
| -  旭小学校
| -  東台小学校
| -  岸谷小学校
| -  矢向小学校
| -  入船小学校
| -  寺尾小学校
| -  汐入小学校
| -  馬場小学校
| -  駒岡小学校
| -  獅子ケ谷小学校
| -  上寺尾小学校
| -  新鶴見小学校
| -  市場中学校
| -  矢向中学校
| -  鶴見中学校
| -  末吉中学校
| -  寺尾中学校
| -  生麦中学校
| -  潮田中学校
| -  寛政中学校
| -  上の宮中学校
+ 神奈川区
| -  三ツ沢小学校
| -  青木小学校
| -  二谷小学校
| -  幸ケ谷小学校
| -  浦島小学校
| -  子安小学校
(以下略)

Python BeautifulSoup - 為替データをスクレイピングする

Yahoo!ファイナンスの為替情報を取得してみます。

スクレイピングを行うためにBeautifulSoupというライブラリを使用します。

BeautifulSoupのインストール

まずBeautifulSoupをインストールします。

1
pip install beautifulsoup4

スクレイピング

以下のページをスクレイピング対象とします。
http://stocks.finance.yahoo.co.jp/stocks/detail/?code=usdjpy

為替レートの数字が表示されている部分をソースで見ると次のようになっています。

1
<td class="stoksPrice">108.460000</td>

CSSセレクタで「.stoksPrice」の要素を取得します。

[コード]

1
2
3
4
5
6
7
8
9
10
from bs4 import BeautifulSoup
import urllib.request as req

url = 'http://stocks.finance.yahoo.co.jp/stocks/detail/?code=usdjpy'
res = req.urlopen(url)

soup = BeautifulSoup(res, 'html.parser')

price = soup.select_one('.stoksPrice').string
print('usdjpy=', price)

実行結果は下記の通りです。

[実行結果]

usdjpy= 108.460000

Python - 機械学習③ クラスタリング

機械学習によるクラスタリングを行ってみます。

クラスタリング用のデータ準備

まずはクラスタリング用のデータを準備します。

クラスタリングでは学習データとテストデータという区別はありません。

ただデータを与えれば、データを種類ごとに分けてくれます。

[コード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# matplotlibとnumpyをインポート
import matplotlib.pyplot as plt
import numpy as np

# x軸の範囲を定義
x_max = 1
x_min = -1

# y軸の範囲を定義
y_max = 2
y_min = -1

# スケールを定義(1単位に何点を使うか)
SCALE = 50

# テストデータの割り合い(全データに対してテストデータは30%)
TEST_RATE = 0.3

# データ生成
x = np.arange(x_min, x_max, 1 / float(SCALE)).reshape(-1, 1)
# xの2乗
y = x ** 2
y_noise = y + np.random.randn(len(y), 1) * 0.5 # ノイズを乗せる

クラスタリング

クラスタリングを行います。今回はデータを3つに分けてグラフに表示します。

7行目のn_clustersに分類数を設定します。

[コード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from sklearn import cluster

# xデータとyデータを結合
data = np.c_[x, y_noise]

# 3つのクラスタに分割
model = cluster.KMeans(n_clusters=3)
model.fit(data)

# 分割結果
# 0から2の番号がつけられている
labels = model.labels_

### データの表示
plt.scatter(x[labels == 0], y_noise[labels == 0], c='blue', s=30, marker='^', label='cluster 0')
plt.scatter(x[labels == 1], y_noise[labels == 1], c='black', s=30, marker='x', label='cluster 1')
plt.scatter(x[labels == 2], y_noise[labels == 2], c='red', s=30, marker='*', label='cluster 2')

# 元の線を点線スタイルで表示
plt.plot(x, y, linestyle='-', label='non noise curve')

# x軸とy軸の範囲を設定
plt.xlim(x_min, y_max)
plt.ylim(y_min, y_max)

# 凡例の表示位置を指定
plt.legend()

# グラフを表示
plt.show()

実行結果は下記の通りです。

[実行結果]

結果

データが青の▲マーク、黒の×マーク、赤の★マークの3つに分類されていることが分かります。

Python - 機械学習② 回帰

機械学習による回帰を行ってみます。

回帰問題のデータ準備

まずは回帰問題用のデータを準備します。

[コード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# matplotlibとnumpyをインポート
import matplotlib.pyplot as plt
import numpy as np

# x軸の範囲を定義
x_max = 1
x_min = -1

# y軸の範囲を定義
y_max = 2
y_min = -1

# スケールを定義(1単位に何点を使うか)
SCALE = 50

# テストデータの割り合い(全データに対してテストデータは30%)
TEST_RATE = 0.3

# データ生成
x = np.arange(x_min, x_max, 1 / float(SCALE)).reshape(-1, 1)
# xの2乗
y = x ** 2
y_noise = y + np.random.randn(len(y), 1) * 0.5 # ノイズを乗せる

# 学習データとテストデータに分割(分類問題、回帰問題で使用)
def split_train_test(array):
length = len(array)
n = int(length * (1 - TEST_RATE))

indices = list(range(length))
np.random.shuffle(indices)
idx_train = indices[:n]
idx_test = indices[n:]

return sorted(array[idx_train]), sorted(array[idx_test])

# インデックスリストを分割
indices = np.arange(len(x)) # インデックス値のリスト
idx_train, idx_test = split_train_test(indices)

# 学習データ
x_train = x[idx_train]
y_train = y_noise[idx_train] # ノイズが乗ったデータ

# テストデータ
x_test = x[idx_test]
y_test = y_noise[idx_test] # ノイズが乗ったデータ

回帰

[コード]

1次式(直線)、2次式で回帰させてみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from sklearn import linear_model

### 1次式で回帰

X1_TRAIN = x_train
X1_TEST = x_test

# 学習
model = linear_model.LinearRegression()
model.fit(X1_TRAIN, y_train) # y_trainは学習データ()

# グラフに描画
plt.plot(x_test, model.predict(X1_TEST), linestyle='-.', label='poly deg 1')


### 2次式で回帰

X2_TRAIN = np.c_[x_train**2, x_train]
X2_TEST = np.c_[x_test**2, x_test]

# 学習
model = linear_model.LinearRegression()
model.fit(X2_TRAIN, y_train)

# グラフに描画
plt.plot(x_test, model.predict(X2_TEST), linestyle='--', label='poly deg 2')


### データの表示

plt.scatter(x_train, y_train, c='blue', s=30, marker='*', label='train')
plt.scatter(x_test, y_test, c='red', s=30, marker='x', label='tes')

# 元の線を点線スタイルで表示
plt.plot(x, y, linestyle='-', label='non noise curve')

# x軸とy軸の範囲を設定
plt.xlim(x_min, y_max)
plt.ylim(y_min, y_max)

# 凡例の表示位置を指定
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0)

# グラフを表示
plt.show()

実行結果は下記の通りです。


[実行結果]

結果

1次式は直線、2次式は元の線とかなり近い形になっていることが分かります。