Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
ハトでもわかるパーセプトロン サンプルコード

【サンプルコード】ハトでもわかるパーセプトロン

slideshareに公開している勉強会資料のサンプルコードです。

http://www.slideshare.net/takosumipasta/ss-71777586

単純パーセプトロンのR言語実装です。

# SlideShare: 用のサンプルソースです
# 
# 単純パーセプトロンのコードですが、わかりやすさ重視のため汎用性は低めです
# クラス化して多少汎用性持たせたものも公開予定

library(magrittr)

#### サンプルデータ ####

data.sample1 <- data.frame(
  "全長" =   c( 90, 80, 85,100, 88, 70, 70, 81, 88, 83),
  "体重" =   c( 39, 50, 48, 57, 44, 35, 45, 41, 29, 37),
  "Label" =  c(  0,  0,  0,  0,  0,  1,  1,  1,  1,  1)
)
plot(data.sample1[,1:2], col = data.sample1[,3] + 1)

#### 必要な関数の定義 ####

# Label = x[1] * w[1] + x[2] * w[2] + x[3] * w[3] %>% output() になればよい

# 重み
W <- c(-1, -1, -1)
# 学習係数
eta <- 0.2
# 線形結合
pred <- function(x){
  (x[1] * W[1] + x[2] * W[2] + x[3] * W[3]) %>% as.numeric
}
# 活性化関数
output <- function(x){
  ifelse(0 < x, 1, 0)
}

# 損失関数、プログラムでは不要
E <- function(x){
  pre <- pred(x) %>% output
  if(pre == x["Label"]){
    return(0)
  }else{
    return(ifelse(x["Label"] == 0, -pred(x), pred(x)))
  }
}

#更新ルール
update.w<-function(x){
  # 現在の判別があってるかどうかはここで見るか呼び出し元で見るか
  # pre <- pred(x) %>% output
  w <- W
  w[1] <- as.numeric(w[1]) + eta * x[1] * ifelse(x["Label"] == 0, -1, 1)
  w[2] <- as.numeric(w[2]) + eta * x[2] * ifelse(x["Label"] == 0, -1, 1)
  w[3] <- as.numeric(w[3]) + eta * x[3] * ifelse(x["Label"] == 0, -1, 1)
  w
}

### ここからメイン処理 ###
data.train <- data.sample1

# スケーリングしてLabelに対する各変数の影響度合いを均一?にしておかないと収束が遅い
data.train[,1] <- data.train[,1] %>% scale
data.train[,2] <- data.train[,2] %>% scale
# バイアス項を追加
data.train <- transform(data.train,"bias" = 1)
# 並び替えだけ
data.train <- data.train[,c("全長","体重","bias","Label")]


# 初期値と学習係数変えて遊ぶ用
W <- c(-1, 1, 1)
eta <- 0.1

# データを描画して線を引いていこう
plot(data.train[,1:2], col = data.train[,4] + 1)
# 終了条件用
w.old <- W + 1

# ここから学習が終了するまでループ
# 線形分離不可の場合、収束しないので、一定回数でbreakする処理を入れた方が安全
while(0.0001 < abs(sum(w.old - W))){
  w.old <- W
  # 全データのループ
  data.train %>% apply(1,function(v){
    pre <- pred(v) %>% output
    if(as.numeric(pre) != as.numeric(v["Label"])){
      W <<- update.w(v)
    }
    W
  })
  abline(-W[3] / W[2], -W[1] / W[2], col = "gray")
  Sys.sleep(0.5)
}
abline(-W[3] / W[2], -W[1] / W[2] , lwd = 3)

#メモ:Animation用ライブラリ使うとアニメーションGIFで出力とかもできるかも
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment