FC2ブログ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Pythonで機械学習の進捗 §3-5

3.5では「出力層の設計」の説明があります。
私は始め、出力層は自身の値を返す(つまり、恒等関数)のみだと考えていました。

つまるところ、隠れ層(中間層)で行う操作で出したい結果をまとめられると考えていたのです。
ソフトマックス関数を隠れ層として追加する考えです。しかし、これは非効率的でわざわざ中間層を1つ増やしていました。
このことから、わざわざ層を増やすよりも、出力層を使い分けることの方がきれいにまとまっているのです。

恒等関数の紹介は本に書かれている通りで、入ってきた値をそのまま返します。
数学でも恒等的と表現して使うことがあり、その場合も同様の使い方です。

ではソフトマックス関数とはどのようなものなのでしょうか。

式で表すと上のようになります。
良く分からない exp という文字を無視して考えます。
分母にあるMを横に倒した文字はシグマ和(と私は勝手に呼んでます)といって、繰り返される足し算を省略して表す記号です。
つまり、この式の意味は各成分を全ての成分を足した数で割っているということ。

で、結局何してるの? って話ですが・・・

ようは各成分が占める割合を%で表示したいということです。
%で表せたので、分類問題での各比率を出し比べられます。

では無視していた exp について考えましょう。
グラフにするとわかりやすい法則があるので、以下2つをグラフで表します。
・y=exp(x)
・y=x



曲線で上がっているのが y=exp(x) です。この曲線の特徴は2つあります。

・ y=x に比べて急激に増える。
・yの値が0より小さくならない。

この特徴は非常に重要なものです。

1つ目は各成分の違いがより明確になることです。差が広がれば、その分割合も変わってきます。
2つ目は負の値がなくなることです。実は%で表示する時に各成分が全て正の数(負の値ではない)である必要があります。

このような特徴をもつ簡単な関数の1つが exp なんですね。
スポンサーサイト

Pythonで機械学習Extra 1-1

こちらでは機械学習を学ぶ上で私が行っている、本では紹介されていないことを載せてます。

1つ目に行ったことはブラックジャックを機械学習で考えてみようと言うことです。

理由は2つ
・ブラックジャックは数学的に解析されているので、結果の比較がしやすいと考えたこと
・取り扱う情報量が少なく。ランダムを使用することでパターンの収集が楽に行えること

早速、機械学習を行う為にブラックジャックのプログラムを作成してみます。
# -*- coding: utf-8 -*-
#import numpy as np
import random

picture=["heart","spade","diamond","club"]
number=["A",2,3,4,5,6,7,8,9,10,"J","Q","K"]
deck=[True]*52#トランプの残り枚数 こいつはローカル変数
player=[]#「マーク、数」の順に2つでセット
dealer=[]
n=2#枚数

def score(players):
x=0#ループのカウント数
point=0#得点
a=0#エースの枚数
while x < len(players):
if players[x+1]=="A":
a+=1
point+=1
elif players[x+1]=="J":
point+=10
elif players[x+1]=="Q":
point+=10
elif players[x+1]=="K":
point+=10
else:
point+=number.index(players[x+1])+1
x+=2
while a > 0:
if point+10 < 22:#エースの調整
point+=10
a-=1
return point

def shuffle(decks):
decks=[True]*52
x=0
while x < len(dealer):
decks[picture.index(dealer[x])*13+number.index(dealer[x+1])]=False
x+=2
y=0
while y < len(player):
decks[picture.index(player[y])*13+number.index(player[y+1])]=False
y+=2
return decks

def hit(players):
global deck #グローバル変数化させる
x=0#ループのカウント数
while x < 2:
b=deck.count(True)
if b == 0:
deck=shuffle(deck)
R = random.choice(number)#ランダムに数を抽出
r = random.choice(picture)# ランダムにマークを抽出
if deck[picture.index(r)*13+number.index(R)]:#デッキの残りにあればTrue一致で処理する
# print ("drow->",r , R)
deck[picture.index(r)*13+number.index(R)]=False#デッキ情報の更新
players.append(r)
players.append(R)
x+=2

def display():
print ("dealer hands->",dealer[0],dealer[1])
print ("your hands->",player)
print ("your score->",score(player))
print ("deck->",deck.count(True))

def choose(player):
x=0#ループのカウント数
while x < 2:
if score(player) > 21:
break
print ("if you pull is your input [hit].")
print ("if you stop is your input [stand].")
input_line = input(">>> ")#入力
if input_line == 'hit':
hit(player)
display()
elif input_line == 'stand':
break
elif input_line == 'deck':
print (deck)
else:
print ("code error. select again your choose")

def setup(Dealer,players):#始まりの処理
while len(Dealer) < n*2:
hit(Dealer)
while len(players) < n*2:
hit(players)
display()

def finish():#終わりの処理
x=0#ループのカウント数
player_score = score(player)#確定してるのでループ外で変数化
while x < 2:
dealer_score = score(dealer)#更新が必要なのでループ内で変数化
print ("dealer hands->",dealer)
print ("dealer score->",score(dealer))
print ("your hands->",player)
print ("your score->",score(player))
print ("deck->",deck.count(True))
if dealer_score > 21:#ディーラーがバスト
print ("dealer is bust!")
print ("you win!")
x+=2
elif dealer_score > player_score:#ディーラーの勝利
print ("dealer choose")
print (">>> stand")
print ("you lose")
x+=2
elif dealer_score == player_score:#引き分け判定
print ("dealer choose")
print (">>> stand")
print ("draw")
x+=2
elif dealer_score > 16:#ディーラーの投了
print ("dealer choose")
print (">>> stand")
print ("you win!")
x+=2
else:
print ("dealer choose")
print(">>> hit")
hit(dealer)

#処理開始
setup(dealer,player)
choose(player)
print("finish")
if score(player) > 21:
print ("you are bust!")
print ("you lose")
else:
finish()
z=0
while z < 2:
print ("continue? y/n")
input_line = input(">>> ")#入力
if input_line == 'y':
del player[:]
del dealer[:]
print ("<>")
setup(dealer,player)
choose(player)
print("finish")
if score(player) > 21:
print ("you are bust!")
print ("you lose")
else:
finish()
elif input_line == 'n':
break
else:
print ("code error. select again your choose")

print("end")

覚え立てのptyhonで四苦八苦しながら組んだプログラムなので、細かい粗には目をつぶって頂いて・・・
困った箇所はいっぱいありますが、しいていくつか挙げるなら、
・勝敗条件の決定
・デッキのリシャッフル
・ブラックジャックの判定

プレイヤーの行動がhit/standの2つしかありませんが、これでブラックジャックの仕組みを再現できました。
今現在ではdouble down , surrender , insuranceも実装できましたがsplitはまだできていません。

これを使って簡単な機械学習を行いたいと思います。
細かい内容は次回に回します。
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。

Pythonで機械学習の進捗 §3-4

前回の記事§3-1でさらっと流したシグモイド関数について触れていました。紹介の順番があべこべになってしまいましたが気にせずいきます。

3.4では「ニューラルネットワークの実装」を紹介しています。
本では一番隠れ層が少ない3層の場合を取り上げています。

一番単純な機構という前提で考えると、私はこの”ニューラルネットワークの仕組み”を”行列をたくさん掛けるもの”だと思いました。
そりゃ行列を使うと言っているのだから当たり前のことなのですが。
言葉のイメージとして、

ベクトル →  行列  → … → ベクトル
(入力値) × (重み) ×   = (出力値)

このようなことを考えました。
ここには簡略化のためにバイアスを含めていないです。

本では計算を効率的に行う為に行列で実装しています。
ですが、私はむしろニューラルネットワークの仕組みが行列でも表せることを示したことが素晴らしいと思います。
それはなぜか。機械学習を数学的に解析することができるかもしれないからです。
機械学習を解析? と思われるかもしれません。なので、機械学習について考えてみます。

機械学習はここ数年で飛躍的な技術の向上があり、何かと話題になりますが、先行研究は1900年代に既に存在していたそうです。その頃のCPUの性能は現在に比べて著しく低いものでした。なので、機械学習の仕組みそのものを手計算で簡単に再現でき、その良し悪しを解析できました。
しかし、ここ数年の技術向上により機械学習がブラックボックス化してしまい、使えばうまくいくがなぜなのか分からなくなってしまいました。なので、当然解析もできなくなっているのです。
ブラックボックスとは過程が見えない・分からないことです。

このブラックボックス化してしまった機械学習の仕組みを解析することは数学者の中で当面の課題にもなっています。

私は行列の部分に注目することで多少の解析を行えるのではないかと考えています。
個人的な課題としては、行列が時々刻々と更新されて変化していく部分があります。決まってしまえば観察のしようがあるのですが、変わっていく様子となると複雑な計算が増えそうな気がします。

Pythonで機械学習の進捗 §3-3

3.2では活性化関数の紹介がされています。
そして「シグモイド関数」の節タイトルと共に物々しい式が紹介されています。



高校生の時に数学が苦手だった方は、この数式を見て諦めようと思ったのではないでしょうか?

数学好きな私から言わせてもらえば、この式はe(ネイピア数、オイラー数)が持つ魅力の1つの側面だと感じられます。
数学が好きな人にとってはこのように感じ取っているのだという一例と考えてください。

数式の解説より先にグラフでイメージすると理解し易いので、図示したものを載せます。



少しは式のことが理解できたのではないでしょうか?
式の意味を翻訳すると次の主張となります。
・-6から6までの範囲で徐々に0から1に上昇していく関数である。

式の意味を理解すると、次にこのような疑問が浮かぶと思います。
「y=xのような斜めの直線ではダメなのだろうか?」
本のなかではこの疑問にしっかりと触れて、回答を載せています。ですが、比喩表現が多く出てきており、私自身も一読した限りでは分かった気になる程度でした。

数学的な回答だとどうなるのか。それは、
「始めの数式は”非線形”であり、y=xは”線型”という違いがある」
実は善し悪しの問題では無かったのですね。

明確なダメな理由。それは、
「機械学習では非線形関数を重ねることが大切なこと」
なので、y=xのような斜めの直線ではダメ。

数学的な問題と機械学習などの技術的な問題をしっかり区別して考えないと本質は見えてきません。

シグモイド関数の紹介はここで切り上げますが、機械学習を行う上で必要な認識は「シグモイド関数は便利だから使う」ことです。
もし機械学習を進めていき、関数の部分を変更したいと考えたとき、この場所に立ち戻って非線形関数とは何ぞやと勉強すると良いと思われます。

Pythonで機械学習の進捗 §3-2

3.3では「多次元配列の計算」が紹介されています。
行列を知っている人からすれば、多次元配列=行列と紹介できます。
高校数学を覚えている人に紹介するなら、ベクトルの要素にベクトルをもつ形です。
ベクトルも何なのか覚えてない、知らない人はぜひ行列を知るところから始めてみてください。

これもそのうち、行列を知らない人向けに紹介の記事をまとめたいですね。

ここで行列をざっくり紹介すると、複数のデータをまとめて計算できるすごい手法のことです。
他のプログラミング言語だと行列を直接計算できるものがいくつかあって代表的なものは、mathmaticaやscilabなどがあります。
逆に行列計算が標準で含まれていないプログラミング言語はjavaやC言語があり、これらはfor文を使って繰り返し処理で行列の計算をしなければいけないので面倒ですね。

ではpythonはどちらなのでしょうか。答えは後者であり前者です。
まぁ、思い出してみれば第1章のnumpyの紹介の部分で行列を計算していました。
つまり、python単体には行列計算する機構はないですが、numpyに含まれているということですね。
このおかげで行列計算を知らなくても機械学習を学ぶことができるのですね。
プロフィール

yamoto.tvp

Author:yamoto.tvp
FC2ブログへようこそ!
大学の数学科に通うほど、数学が好きな私です。
趣味で勉強している”機械学習”などの進捗を載せています。

最新記事
最新コメント
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。