前回の続きです
参考文献
「機械学習と深層学習―C言語によるシミュレーション―」2016/05/21
(著)小高 知宏
文献元
準備
console
pip install numpy
ソースコード
sample.py
# -*- coding: utf-8 -*-
#/*********************************************************/
#/* 自己符号化器 */
#/* 誤差の推移や,学習結果となる結合係数などを出力します */
#/*********************************************************/
import numpy as np
#/*******************/
#/* main()関数 */
#/*******************/
def main():
#/*記号定数の定義*/
INPUTNO=9 #/*入力層のセル数*/
HIDDENNO=4 #/*中間層のセル数*/
OUTPUTNO=9 #/*出力層のセル数*/
ALPHA=10 #/*学習係数*/
MAXINPUTNO=100 #/*学習データの最大個数*/
BIGNUM=100 #/*誤差の初期値*/
LIMIT=1e-5 #/*誤差の上限値*/
wh=np.full((HIDDENNO,INPUTNO+1),0.)#/*中間層の重み*/
wo=np.full((OUTPUTNO,HIDDENNO+1),0.)#/*出力層の重み*/
e=np.full((MAXINPUTNO,INPUTNO+OUTPUTNO),0.)#/*学習データセット*/
hi=np.full((HIDDENNO+1,),0.)#/*中間層の出力*/
o=np.full((OUTPUTNO,),0.)#/*出力*/
err=np.double(BIGNUM)#/*誤差の評価*/
i=j=k=0#/*繰り返しの制御*/
n_of_e=0#/*学習データの個数*/
count_=0#/*繰り返し回数のカウンタ*/
#/*乱数の初期化*/
np.random.seed(None)
#/*重みの初期化*/
wh=initwh(wh,HIDDENNO,INPUTNO)#/*中間層の重みの初期化*/
wo=initwo(wo,OUTPUTNO,HIDDENNO)#/*出力層の重みの初期化*/
print(wh,wo)#/*結果の出力*/
#/*学習データの読み込み*/
n_of_e,e=getdata(e,MAXINPUTNO,INPUTNO,OUTPUTNO)
print("学習データの個数:",n_of_e)
#/*学習*/
for _ in range(50000):
#/*複数の出力層に対応*/
err=0.
err_=0.
for k in range(OUTPUTNO):
err=0.
for j in range(n_of_e):
#/*順方向の計算*/
o[k]=forward(wh,wo[k],hi,e[j],HIDDENNO,INPUTNO)
#/*出力層の重みの調整*/
wo[k]=olearn(wo[k],hi,e[j],o[k],k,ALPHA,HIDDENNO,INPUTNO)
#/*中間層の重みの調整*/
wh=hlearn(wh,wo[k],hi,e[j],o[k],k,ALPHA,HIDDENNO,INPUTNO)
#/*誤差の積算*/
err+=(o[k]-e[j][INPUTNO+k])*(o[k]-e[j][INPUTNO+k])
err_+=(o[k]-e[j][INPUTNO+k])*(o[k]-e[j][INPUTNO+k])
count_+=1
#/*誤差の出力*/
print("count_",count_,"err_",err_)
#/*複数の出力層対応部分終了*/
if LIMIT>err_:
break
#/*学習終了*/
#/*結合荷重の出力*/
print_(wh,wo)
#/*学習データに対する出力*/
for i in range(n_of_e):
out_=[]
for j in range(OUTPUTNO):
out_=np.append(out_,forward(wh,wo[j],hi,e[i],HIDDENNO,INPUTNO))
print("e",e[i],"out_",out_)
#/**********************/
#/* hlearn()関数 */
#/* 中間層の重み学習 */
#/**********************/
def hlearn(wh,wo,hi,e,o,k,ALPHA,HIDDENNO,INPUTNO):
i=j=0#/*繰り返しの制御*/
dj=0.#/*中間層の重み計算に利用*/
for j in range(HIDDENNO):#/*中間層の各セルjを対象*/
dj=hi[j]*(1-hi[j])*wo[j]*(e[INPUTNO+k]-o)*o*(1-o)
i=np.arange(INPUTNO)#/*i番目の重みを処理*/
wh[j][i]+=ALPHA*e[i]*dj
wh[j][i[-1]+1]+=ALPHA*(-1.0)*dj#/*しきい値の学習*/
return wh
#/**********************/
#/* getdata()関数 */
#/*学習データの読み込み*/
#/**********************/
def getdata(e,MAXINPUTNO,INPUTNO,OUTPUTNO):
n_of_e=0#/*データセットの個数*/
e=np.array([[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1],
[0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0],
[1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0]])
#/*データの入力*/
#e=(np.random.sample((MAXINPUTNO,INPUTNO+OUTPUTNO))*2)-1
n_of_e=e.shape[0]
return n_of_e,e
#/**********************/
#/* olearn()関数 */
#/* 出力層の重み学習 */
#/**********************/
def olearn(wo,hi,e,o,k,ALPHA,HIDDENNO,INPUTNO):
i=0#/*繰り返しの制御*/
d=0.#/*重み計算に利用*/
d=(e[INPUTNO+k]-o)*o*(1-o)#/*誤差の計算*/
i=np.arange(HIDDENNO)
wo[i]+=ALPHA*hi[i]*d#/*重みの学習*/
wo[i[-1]+1]+=ALPHA*(-1.0)*d#/*しきい値の学習*/
return wo
#/**********************/
#/* forward()関数 */
#/* 順方向の計算 */
#/**********************/
def forward(wh,wo,hi,e,HIDDENNO,INPUTNO):
i=j=0#/*繰り返しの制御*/
u=0.#/*重み付き和の計算*/
o=0.#/*出力の計算*/
#/*hiの計算*/
for i in range(HIDDENNO):
u=0 #/*重み付き和を求める*/
j=np.arange(INPUTNO)
u=(e[j]*wh[i][j]).sum()
u-=wh[i][j[-1]+1]#/*しきい値の処理*/
hi[i]=f(u)
#/*出力oの計算*/
o=0
i=np.arange(HIDDENNO)
o=(hi[i]*wo[i]).sum()
o-=wo[i[-1]+1]#/*しきい値の処理*/
return f(o)
#/**********************/
#/* print()関数 */
#/* 結果の出力 */
#/**********************/
def print_(wh,wo):
print("wh",wh)
print("wo",wo)
#/**********************/
#/* initwh()関数 */
#/*中間層の重みの初期化*/
#/**********************/
def initwh(wh,HIDDENNO,INPUTNO):
#/*乱数による重みの決定*/
for i in range(HIDDENNO):
for j in range(INPUTNO+1):
wh[i][j]=drnd()
return wh
#/**********************/
#/* initwo()関数 */
#/*出力層の重みの初期化*/
#/**********************/
def initwo(wo,OUTPUTNO,HIDDENNO):
#/*繰り返しの制御*/
#/*乱数による重みの決定*/
for i in range(OUTPUTNO):
for j in range(HIDDENNO+1):
wo[i][j]=drnd()
return wo
#/*******************/
#/* drnd()関数 */
#/* 乱数の生成 */
#/*******************/
def drnd():
rndno=(np.random.sample(1)*2)-1#/*-1から1の間の乱数を生成*/
return rndno
#/*******************/
#/* f()関数 */
#/* 伝達関数 */
#/*(シグモイド関数) */
#/*******************/
def f(u):
return 1.0/(1.0+np.exp(-u))
main()