####################################
# Winner-Take-All Groups
# coded by Y.Suganuma
####################################
#############################
# Winnerクラスの定義
# coded by Y.Suganuma
#############################
class Winner
#########################
# コンストラクタ
# max : 最大学習回数
# n : 訓練例の数
# o : 出力セルの数
# p : 入力セルの数
#########################
def initialize(max_i, n_i, o_i, p_i)
# 設定
@_max = max_i
@_n = n_i
@_o = o_i
@_p = p_i
# 領域の確保
@_e = Array.new(@_n) # 訓練例
@_c = Array.new(@_n) # 各訓練例に対する正しい出力
for i1 in 0 ... @_n
@_e[i1] = Array.new(@_p+1)
@_c[i1] = Array.new(@_o)
end
@_w_p = Array.new(@_o) # 重み(ポケット)
@_w = Array.new(@_o) # 重み
for i1 in 0 ... @_o
@_w_p[i1] = Array.new(@_p+1)
@_w[i1] = Array.new(@_p+1)
end
@_ct = Array.new(@_o) # 作業領域
end
#########################################
# 訓練例の分類
# return : 正しく分類した訓練例の数
#########################################
def Bunrui()
mx = 0
mx_v = 0
num = 0
sw = 0
for i1 in 0 ... @_n
cor = 0
for i2 in 0 ... @_o
if @_c[i1][i2] == 1
cor = i2
end
s = 0
for i3 in 0 ... @_p+1
s += @_w[i2][i3] * @_e[i1][i3]
end
if i2 == 0
mx = 0
mx_v = s
else
if s > mx_v
mx = i2
mx_v = s
sw = 0
else
if s == mx_v
sw = 1
end
end
end
end
if sw == 0 and cor == mx
num += 1
end
end
return num
end
#*************************/
# 学習データの読み込み */
# name : ファイル名 */
#*************************/
def Input(name)
f = open(name, "r")
f.gets()
for i1 in 0 ... @_n
@_e[i1][0] = 1
s = f.gets().split(" ")
for i2 in 1 ... @_p+1
@_e[i1][i2] = Integer(s[i2-1])
end
for i2 in 0 ... @_o
@_c[i1][i2] = Integer(s[@_p+i2])
end
end
f.close()
end
#################################
# 学習と結果の出力
# pr : =0 : 画面に出力
# =1 : ファイルに出力
# name : 出力ファイル名
#################################
def Learn(pr, name="")
mx = 0
mx_v = 0
num = Array.new(1)
n_tri = Pocket(num)
if pr == 0
out = $stdout
else
out = open(name, "w")
end
out.print("重み\n")
for i1 in 0 ... @_o
for i2 in 0 ... @_p+1
out.print(" " + String(@_w_p[i1][i2]))
end
out.print("\n")
end
out.print("分類結果\n")
for i1 in 0 ... @_n
sw = 0
for i2 in 0 ... @_o
s = 0
for i3 in 0 ... @_p+1
s += @_w_p[i2][i3] * @_e[i1][i3]
end
if i2 == 0
mx_v = s
mx = 0
else
if s > mx_v
sw = 0
mx_v = s
mx = i2
else
if s == mx_v
sw = 1
end
end
end
end
for i2 in 1 ... @_p+1
out.print(" " + String(@_e[i1][i2]))
end
out.print(" Cor ")
for i2 in 0 ... @_o
out.print(" " + String(@_c[i1][i2]))
end
if sw > 0
mx = -1
end
out.print(" Res " + String(mx+1) + "\n")
end
if @_n == num[0]
print(" !!すべてを分類(試行回数:" + String(n_tri) + ")\n")
else
print(" !!" + String(num[0]) + " 個を分類\n")
end
end
############################################
# Pocket Algorith with Ratcet
# num_p : 正しく分類した訓練例の数
# return : =0 : 最大学習回数
# >0 : すべてを分類(回数)
############################################
def Pocket(num_p)
# 初期設定
count = 0
mx = 0
run = 0
run_p = 0
sw = -1
num_p[0] = 0
for i1 in 0 ... @_o
for i2 in 0 ... @_p+1
@_w[i1][i2] = 0
end
end
# 実行
while sw < 0
# 終了チェック
count += 1
if count > @_max
sw = 0
else
# 訓練例の選択
k = Integer(rand(0) * @_n)
if k >= @_n
k = @_n - 1
end
# 出力の計算
sw1 = 0
cor = -1
for i1 in 0 ... @_o
if @_c[k][i1] == 1
cor = i1
end
s = 0
for i2 in 0 ... @_p+1
s += @_w[i1][i2] * @_e[k][i2]
end
@_ct[i1] = s
if i1 == 0
mx = 0
else
if s > @_ct[mx]
mx = i1
sw1 = 0
else
if s == @_ct[mx]
sw1 = 1
if cor >= 0 and mx == cor
mx = i1
end
end
end
end
end
# 正しい分類
if sw1 == 0 and cor == mx
run += 1
if run > run_p
num = Bunrui()
if num > num_p[0]
num_p[0] = num
run_p = run
for i1 in 0 ... @_o
for i2 in 0 ... @_p+1
@_w_p[i1][i2] = @_w[i1][i2]
end
end
if num == @_n
sw = count
end
end
end
# 誤った分類
else
run = 0
for i1 in 0 ... @_p+1
@_w[cor][i1] += @_e[k][i1]
@_w[mx][i1] -= @_e[k][i1]
end
end
end
end
return sw
end
end
if ARGV[0] != nil
# 基本データの入力
s = gets().split(" ")
max = Integer(s[1])
p = Integer(s[3])
o = Integer(s[5])
n = Integer(s[7])
s = gets().split(" ")
name = s[1]
# ネットワークの定義
srand()
net = Winner.new(max, n, o, p)
net.Input(name)
# 学習と結果の出力
if ARGV[0] == nil
net.Learn(0)
else
net.Learn(1, ARGV[0])
end
else
print("***error 入力ファイル名を指定して下さい\n")
end
=begin
------------------------入力ファイル--------------
最大試行回数 100 入力セルの数 2 出力セルの数 2 訓練例の数 4
入力データファイル or.dat
------------------------or.dat--------------------
OR演算の訓練例.最後の2つのデータが目標出力値
-1 -1 -1 1
-1 1 1 -1
1 -1 1 -1
1 1 1 -1
=end