LoginSignup
0
2

前回の続きです

遺伝的アルゴリズムでナップザック問題を解く

参考文献

「機械学習と深層学習―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()

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2