python json

jsonモジュールを使用すると、Json形式のファイルや文字列をパースして、dictなどのオブジェクトとして読み込める。

import json
from collections import OrderedDict 
import pprint 

s = r'{"C": "\u3042", "A": {"i":1, "j":2}, "B":[{"X":1, "Y":10}, {"X":2, "Y": 20}]}'

print(s)

d = json.loads(s)

pprint.pprint(d, width=40)

print(type(d))

[vagrant@localhost python]$ python main.py
{“C”: “\u3042”, “A”: {“i”:1, “j”:2}, “B”:[{“X”:1, “Y”:10}, {“X”:2, “Y”: 20}]}
{‘A’: {‘i’: 1, ‘j’: 2},
‘B’: [{‘X’: 1, ‘Y’: 10},
{‘X’: 2, ‘Y’: 20}],
‘C’: ‘あ’}

Python hashlib

hashlib: セキュアハッシュやメッセージダイジェスト用の様々なアルゴリズムを実装。sha256は有名ですよね。
e.x. sha1, sha224, sha256, sha384, sha512, RSA md5

コンストラクタがあり、ハッシュオブジェクトを返す

import hashlib 
m = hashlib.sha256()
m.update(b"National Security Agency")
print(m.digest())

print(m.digest_size)
print(m.block_size)

[vagrant@localhost python]$ python main.py
b’t\xc6!\xc4\xd2\xd3W&r4\xa2\xe2\xa9\x1f\x15k\xb9\xf1\x08\xa9\x10\xb6\xd2\xb5\xe6\x05|\xe2d\x81\xc8\xe6′
32
64

sha224で実行すると
b’\xe9\xf0\xee\xd4F\xd0;-MM\xa1\xc9\x8cY\x05\x1c\x81H\xde8\x95\x94\x0f\xcb\x13he\x89′

hash.update()でオブジェクトを更新
“b”でエンコード
よく使われるのは、md5とsha256

Blockchain その1

こちらのコードを分解していきます。

import hashlib
import json
import datetime

class Block:
	def __init__(self, index, timestamp, transaction, previous_hash):
		self.index = index 
		self.timestamp = timestamp 
		self.transaction = transaction 
		self.previous_hash = previous_hash 
		self.property_dict = {str(i): j for i, j in self.__dict__.items()}
		self.now_hash = self.calc_hash()

	def calc_hash(self):
		block_string = json.dumps(self.property_dict, sort_keys=True).encode('ascii')
		return hashlib.sha256(block_string).hexdigest()

def new_transaction(sender, recipient, amount):
	transaction = {
		"差出人": sender,
		"宛先": recipient,
		"金額": amount,
	}
	return transaction

block_chain = []
genesis_block = Block(0, 0, 0, "-")
block_chain.append(genesis_block)

transaction = new_transaction("タロウ", "花子", 100)
new_block = Block(1, str(datetime.datetime.now()), transaction, block_chain[0].now_hash)
block_chain.append(new_block)

for key, value in genesis_block.__dict__.items():
	print(key, ':', value)

print("")

for key, value in new_block.__dict__.items():
	print(key, ':', value)

[vagrant@localhost python]$ python app.py
property_dict : {‘transaction’: 0, ‘index’: 0, ‘previous_hash’: ‘-‘, ‘timestamp’: 0}
now_hash : 49f3a23af19229c5a1a12611bdb590f742154a5d11b5018f3f01b740800a5c20
transaction : 0
index : 0
previous_hash : –
timestamp : 0

property_dict : {‘transaction’: {‘宛先’: ‘花子’, ‘差出人’: ‘タロウ’, ‘金額’: 100}, ‘index’: 1, ‘previous_hash’: ’49f3a23af19229c5a1a12611bdb590f742154a5d11b5018f3f01b740800a5c20′, ‘timestamp’: ‘2019-10-18 10:55:22.499513’}
now_hash : b9b57282d7387add7e66d6209f06e4c132ec01cfece9615067bdffeb7b8f4c30
transaction : {‘宛先’: ‘花子’, ‘差出人’: ‘タロウ’, ‘金額’: 100}
index : 1
previous_hash : 49f3a23af19229c5a1a12611bdb590f742154a5d11b5018f3f01b740800a5c20
timestamp : 2019-10-18 10:55:22.499513

誤差逆伝播法

順伝播では、入力値から重みを掛けて、中間層へと計算をして出力を導いた。
逆伝播では、出力値と正解の誤差を出し、最後の層、前の層と計算して重みを調整する

誤差逆伝播法
損失関数を2乗誤差の式として定義し、中間層の活性化関数を標準シグモイド関数として定義する

勾配降下法

二乗誤差を出力層、中間層、入力層に置き換えていくと、
E = 1/2 ||t – y||^2
E = 1/2 ||σ2(a1W2 + b2) – y||^2

E = 1/2 ||σ2(σ1(a0W1 + b1)*W2 + b2) – y||^2
E = 1/2 ||σ2(σ1(x0W1 + b1)*W2 + b2) – y||^2

勾配降下法は、関数のグラフを斜面に見立てて、関数の傾きを調べながら関数の値を小さくするような方向に少しずつ降りていくことで、関数の最小値を近位的に求める方法

df(x)/dx = limΔx→0 Δf(x)/Δx = {limh→0 f(x + Δx) – f(x)} / Δx
Δxが非常に小さい値であれば、
Δf(x) = f(x + Δx) – f(x)

Δx = -η df(x)/dx
xnew = xold -η df(x)/dx

DeepLearningでは、勾配降下法の確率的勾配降下法(SGD)などを利用する
訓練データからデータをN個抜き出し、N枚を学習させて計算された損失関数から、勾配降下法を用いてN枚ごとに重みを更新する。この枚数をバッチサイズという
訓練データを使いまわす回数をエポック数と呼ぶ

損失関数

重みやバイアスは損失関数が最小になるように調整される

損失関数の例: 二乗誤差
E = 1/2*|t – y|^2
※t=正解ラベル、y=NN出力
→ 二乗誤差を最小化するため、微分計算する

損失関数の例: クロスエントロピー
E = -Σt*log[e]y
※t=正解ラベル、y=NN出力
正解ラベルが0か1の値のみ持つ場合、正解ラベル1に対応する出力の自然対数を計算する
y=1, E=0

順伝播

入力値(0層目): x01 x02 x03 ※α:層の数、β:ノードの数
出力値(出力層):a21 a22 a23
wαβγ ※α:次の層の数、β:α層のノードの数(β番目)、γ:α-1層のノードの数(バイアスbの場合は記載なし)

中間層の計算
x11 = w111*a01 + w112a02 + w13a03 + b11
x12 = w121*a01 + w122a02 + w23a03 + b12
バイアスはパラメータとして入る
計算は行列を用いると
x1(中間層) = W1a0(入力層) + b1(バイアス) に置き換えられる

中間層の出力 a11, a12
a11 = σ1(x11)
a12 = σ1(x12)
σに活性化関数を選択し、x11 = 0 だった場合は、中間層の出力はa11 = σ1(0) = 0.5となる。シグモイド関数を挟むことで、出力は0 or 1 ではなくなる。

x2, w2, a1, b1を行列として出力層を表現すると
x2 = W2a1 + b2

最後の出力層では、softmax関数で非線形変換される。
softmax関数で確率に変換される。
yi = exp(xi)/ (exp(x1) + exp(x2) + … exp(xn)) (1≦i≦n)

DNN

入力値: x
重み: w
バイアス: b
活性化: σ

wx + b -> σ(wx + b) = 出力α

MNISTの場合、入力層は784ノード
つまり、画像認識の場合、入力層がピクセル数というイメージだ。
出力層では確率を表しており、確率の高い出力結果をoutputする
例えば、MNISTのように数字が0~9だと10通りだが、自動運転のように外景全てを認識させるとなると、無数に広がる
-> ということは1000万画素の画像認識の場合はノードは1000万?
-> 信号、人、建物、のように出力を絞れば可能か?
-> 人間の顔の場合は、目、鼻など特徴抽出ができるが、ルールがない場合は、頻度の問題が常に生じる??

活性化関数σにはシグモイド関数ReLu関数がよく用いられる
シグモイド関数: 1/(1+exp(-x))
ReLu関数: max(0,x)
-> 線形分離不可能なデータを分離するのに有効

教師あり、教師なし

教師あり学習: 正解ラベルの付いたデータセット
教師なし学習: 正解ラベルの付いていないデータセット
-> 人間の解釈が必要な場合が多い

import numpy as np 
import matplotlib.pyplot as plt 
%matplotlib inline

from sklearn import datasets 
iris = datasets.load_iris()

print(iris.DESCR)
import numpy as np 
import numpy.random as random 
import scipy as sp 
import pandas as pd 
from pandas import Series, DataFrame 

from sklearn.model_selection import train_test_split 
from sklearn.datasets import load_iris 

iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df["target"] = iris.target_names[iris.target]

df.head()

X = df.drop('target', axis=1)
Y = df['target']

X_train, X_test, y_train, y_test = train_test_split(X,Y,random_state=0)

# K-NN
from sklearn.neighbors import KNeighborsClassifier 
model = KNeighborsClassifier(n_neighbors=3)
model.fit(X_train, y_train)

print("train score:",model.score(X_train,y_train))
print("test score:",model.score(X_test,y_test))

# decision tree
from sklearn.tree import DecisionTreeClassifier 
model = DecisionTreeClassifier(max_depth=3)
model.fit(X_train, y_train)

print("train score:",model.score(X_train,y_train))
print("test score:",model.score(X_test,y_test))

# SVM
from sklearn.svm import LinearSVC
model = LinearSVC()
model.fit(X_train, y_train)

print("train score:",model.score(X_train,y_train))
print("test score:",model.score(X_test,y_test))

# Linear Regression
from sklearn.linear_model import LogisticRegression

model = LogisticRegression()
model.fit(X_train, y_train)

print("train score:",model.score(X_train,y_train))
print("test score:",model.score(X_test,y_test))

MNIST

MNISTとは?
Mixed National Institute of Standards and Technology database
手書き60000枚とテスト画像10000枚の画像データセット

MNISTのデータDL
http://yann.lecun.com/exdb/mnist/

import keras 
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, InputLayer
from keras.optimizers import RMSprop

(x_train, y_train),(x_test,y_test) = mnist.load_data()

x_train = x_train.reshape(60000, 748)
x_test = x_test.reshape(10000, 784)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
y_train = keras.utils.to_categorical(y_train, 10)
y_test = keras.utils.to_categorical(y_test, 10)

model = Sequential()
model.add(InputLayer(input_shape=(784,)))
model.add(Dense(10, activation='softmax'))
model.compile(loss='categorical_crossentropy',optimizer='rmsprop', metrics=['accuracy'])

epochs = 20
batch_size = 128
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_test, y_test))

score = model.evaluate(x_test, y_test, verbose=1)
print()
print('Test loss:', score[0])
print('Test accuracy:', score[1])

MNISTのデータは縦28ピクセル x 横28ピクセル = 計748ピクセル
各ピクセルRGBは 0 – 255 の256種類の整数値