読者です 読者をやめる 読者になる 読者になる

liblinear-ruby-swigを使って手書き数字を判別する2

今回も、前回に引き続きliblinear-ruby-swigを使って手書き数字を判別する機械学習のプログラムを組んでいきたいと思います。
【サンプルコードの改良】
サンプルコードには今回は関係ないものとかが多いので簡単に整理します。
libsvm.rb----------

require "linear"

# types = [ 'L2R_LR', 'L2R_L2LOSS_SVC_DUAL', 'L2R_L2LOSS_SVC', 'L2R_L1LOSS_SVC_DUAL', 'MCSVM_CS', 'L1R_L2LOSS_SVC', 'L1R_LR' ] SVMの種類
# 0:L2_LR , 1:L2LOSS_SVM_DUAL , 2:L2LOSS_SVM , 3: L1L1LOSS_SVM_DUAL, 4: MCSVM_CS, ... 定義されている変数名

pa = LParameter.new
pa.solver_type = MCSVM_CS
pa.eps = 0.1
bias = 1
labels, samples = read_file("training_file")
sp = LProblem.new(labels,samples,bias)
model = LModel.new(sp,pa)

x = {1=>1,2=>0.1,3=>0.2,4=>0,5=>0} # テストしてみるデータ
puts model.predict(x)
                                      • -

簡単ですけどこんな感じに整理しておきます。
みたらなんとなくわかると思いますが、
sp = LProblem.new(labels,samples,bias)
この部分に必要なデータを与えることがポイントになっています。

csvファイルの読み込み】
機械学習において重要なのがデータをいかにプログラムに組み込むかという点である。
今回の最終目標は
sp = LProblem.new(labels,samples,bias)
この部分に
label:正解の配列
samples:ピクセルデータの配列
を渡すことである。
そのためにそれにあった配列を作成する。
整理しておいてなんですが、先ほどのコードを全部コメントアウトします。
面倒な方は一旦消してもいいです。
そして以下のようなコードを書いていきます。
libsvm.rb----------

require "linear"
require "csv"

label = []
data = []
load_data = []
cnt = 0;
CSV.foreach("train.csv") do |row|
load_data.push(row)
cnt = cnt + 1
if cnt == 5
break
end

end
load_data.shift #先頭の一行を削除

load_data.each do |load|
label.push(load.shift.to_i)
data.push(load.map(&:to_i))
end
p label
p data
                                      • -

これで、csvファイルからlabel(正解の数字)とそれに関するデータ(ピクセル)をそれぞれ配列に入れることができます。
無理やりbreakさせてるのは、すべてやると4万個ロードしてなかなか動かないし、結果も見づらいからです。
to_iやmap(&:to_i)などは、もともとのcsvファイルの情報は全部文字列なので数値に変換する必要があるため行っています。

【実際のコーディング】
libsvm.rb----------

require "linear"
require "csv"
# types = [ 'L2R_LR', 'L2R_L2LOSS_SVC_DUAL', 'L2R_L2LOSS_SVC', 'L2R_L1LOSS_SVC_DUAL', 'MCSVM_CS', 'L1R_L2LOSS_SVC', 'L1R_LR' ] SVMの種類
# 0:L2_LR , 1:L2LOSS_SVM_DUAL , 2:L2LOSS_SVM , 3: L1L1LOSS_SVM_DUAL, 4: MCSVM_CS, ... 定義されている変数名
# 
def train_loop(limit)
label = []
data = []
load_data = []
cnt = 0;
CSV.foreach("train.csv") do |row|
load_data.push(row)
cnt = cnt + 1
if cnt == limit
break
end

end
load_data.shift #先頭の一行を削除

load_data.each do |load|
label.push(load.shift.to_i)
data.push(load.map(&:to_i))
end
test_method(label,data)
end

def test_method(label,data)
load_test_data = []
label_test = []
data_test = []
CSV.foreach("mini_test.csv") do |row|
load_test_data.push(row)
end
load_test_data.shift #先頭の一行を削除

load_test_data.each do |load|
label_test.push(load.shift.to_i)
data_test.push(load.map(&:to_i))
end

pa = LParameter.new
pa.solver_type = MCSVM_CS
pa.eps = 0.1
bias = 1
sp = LProblem.new(label,data,bias)
model = LModel.new(sp,pa)

index = 0.0
success = 0.0
data_test.each do |test|
# puts "#{model.predict(test)}:#{label_test[index]}"
if model.predict(test) == label_test[index]
success = success + 1
end
index = index + 1
end
puts "トータル#{index}正解#{success}正答率#{success/index*100}%"
end

num = [100,200,500,1000,5000]
5.times{|i|
puts "学習数#{num[i]}"
train_loop(num[i])
}
                                      • -