Linux CentOS 7 makinede Torch7 ile çalışıyorum. ikili sınıflandırma problemini çözmek için yapay sinir ağı (ANN) veri kümemi uygulamaya çalışıyorum. Basit bir çok katmanlı perceptron kullanıyorum.Torch, yapay sinir ağım neden her zaman sıfırdır?
Şu Torch paketlerini kullanıyorum: optim, torch.
konu benim algılayıcı hep sıfır değerlerini (sıfır olarak sınıflandırılan elemanları) tahmin olduğunu ve
İşte benim veri kümesi ("dataset_file.csv") neden ... anlayamıyorum. 34 özellikleri ve 1 etiket hedefi vardır (son sütun, o 0 olabilir veya 1):0.55,1,0,1,0,0.29,1,0,1,0.46,1,1,0,0.67,1,0.37,0.41,1,0.08,0.47,0.23,0.13,0.82,0.46,0.25,0.04,0,0,0.52,1,0,0,0,0.33,0
0.65,1,0,1,0,0.64,1,0,0,0.02,1,1,1,1,0,0.52,0.32,0,0.18,0.67,0.47,0.2,0.64,0.38,0.23,1,0.24,0.18,0.04,1,1,1,1,0.41,0
0.34,1,0.13,1,0,0.33,0,0.5,0,0.02,0,0,0,0.67,1,0.25,0.55,1,0.06,0.23,0.18,0.15,0.82,0.51,0.22,0.06,0,0,0.6,1,0,0,0,0.42,1
0.46,1,0,1,0,0.14,1,0,0,0.06,0,1,1,0,1,0.37,0.64,1,0.14,0.22,0.17,0.1,0.94,0.65,0.22,0.06,0.75,0.64,0.3,1,1,0,0,0.2,0
0.55,1,0,1,0,0.14,1,0.5,1,0.03,1,1,0,1,1,0.42,0.18,0,0.16,0.55,0.16,0.12,0.73,0.55,0.2,0.03,0.54,0.44,0.35,1,1,0,0,0.11,0
0.67,1,0,1,0,0.71,0,0.5,0,0.46,1,0,1,1,1,0.74,0.41,0,0.1,0.6,0.15,0.15,0.69,0.42,0.27,0.04,0.61,0.48,0.54,1,1,0,0,0.22,1
0.52,1,0,1,0,0.21,1,0.5,0,0.01,1,1,1,0.67,0,0.27,0.64,0,0.08,0.34,0.14,0.21,0.85,0.51,0.2,0.05,0.51,0.36,0.36,1,1,0,0,0.23,0
0.58,1,0.38,1,0,0.36,1,0.5,1,0.02,0,1,0,1,1,0.38,0.55,1,0.13,0.57,0.21,0.23,0.73,0.52,0.19,0.03,0,0,0.6,1,0,0,0,0.42,0
0.66,1,0,1,0,0.07,1,0,0,0.06,1,0,0,1,1,0.24,0.32,1,0.06,0.45,0.16,0.13,0.92,0.57,0.27,0.06,0,0,0.55,1,0,0,0,0.33,0
0.39,1,0.5,1,0,0.29,1,0,1,0.06,0,0,0,1,1,0.34,0.45,1,0.1,0.31,0.12,0.16,0.81,0.54,0.21,0.02,0.51,0.27,0.5,1,1,0,0,0.32,0
0.26,0,0,1,0,0.21,1,0,0,0.02,1,1,1,0,1,0.17,0.36,0,0.19,0.41,0.24,0.26,0.73,0.55,0.22,0.41,0.46,0.43,0.42,1,1,0,0,0.52,0
0.96,0,0.63,1,0,0.86,1,0,1,0.06,1,1,1,0,0,0.41,0.5,1,0.08,0.64,0.23,0.19,0.69,0.45,0.23,0.06,0.72,0.43,0.45,1,1,0,0,0.53,0
0.58,0,0.25,1,0,0.29,1,0,1,0.04,1,0,0,0,1,0.4,0.27,1,0.09,0.65,0.21,0.16,0.8,0.57,0.24,0.02,0.51,0.28,0.5,1,1,1,0,0.63,0
0.6,1,0.5,1,0,0.73,1,0.5,1,0.04,1,0,1,0,1,0.85,0.64,1,0.16,0.71,0.24,0.21,0.72,0.45,0.23,0.1,0.63,0.57,0.13,1,1,1,1,0.65,0
0.72,1,0.25,1,0,0.29,1,0,0,0.06,1,0,0,1,1,0.31,0.41,1,0.17,0.78,0.24,0.16,0.75,0.54,0.27,0.09,0.78,0.68,0.19,1,1,1,1,0.75,0
0.56,0,0.13,1,0,0.4,1,0,0,0.23,1,0,0,1,1,0.42,1,0,0.03,0.14,0.15,0.13,0.85,0.52,0.24,0.06,0,0,0.56,1,0,0,0,0.33,0
0.67,0,0,1,0,0.57,1,0,1,0.02,0,0,0,1,1,0.38,0.36,0,0.08,0.12,0.11,0.14,0.8,0.49,0.22,0.05,0,0,0.6,1,0,0,0,0.22,0
0.67,0,0,1,0,0.36,1,0,0,0.23,0,1,0,0,0,0.32,0.73,0,0.25,0.86,0.26,0.16,0.62,0.35,0.25,0.02,0.46,0.43,0.45,1,1,1,0,0.76,0
0.55,1,0.5,1,0,0.57,0,0.5,1,0.12,1,1,1,0.67,1,1,0.45,0,0.19,0.94,0.19,0.22,0.88,0.41,0.35,0.15,0.47,0.4,0.05,1,1,1,0,0.56,1
0.61,0,0,1,0,0.43,1,0.5,1,0.04,1,0,1,0,0,0.68,0.23,1,0.12,0.68,0.25,0.29,0.68,0.45,0.29,0.13,0.58,0.41,0.11,1,1,1,1,0.74,0
0.59,1,0.25,1,0,0.23,1,0.5,0,0.02,1,1,1,0,1,0.57,0.41,1,0.08,0.05,0.16,0.15,0.87,0.61,0.25,0.04,0.67,0.61,0.45,1,1,0,0,0.65,0
0.74,1,0.5,1,0,0.26,1,0,1,0.01,1,1,1,1,0,0.76,0.36,0,0.14,0.72,0.12,0.13,0.68,0.54,0.54,0.17,0.93,0.82,0.12,1,1,0,0,0.18,0
0.64,0,0,1,0,0.29,0,0,1,0.15,0,0,1,0,1,0.33,0.45,0,0.11,0.55,0.25,0.15,0.75,0.54,0.27,0.05,0.61,0.64,0.43,1,1,0,0,0.23,1
0.36,0,0.38,1,0,0.14,0,0.5,0,0.02,1,1,1,0.33,1,0.18,0.36,0,0.17,0.79,0.21,0.12,0.75,0.54,0.24,0.05,0,0,0.52,1,0,0,0,0.44,1
0.52,0,0.75,1,0,0.14,1,0.5,0,0.04,1,1,1,0,1,0.36,0.68,1,0.08,0.34,0.12,0.13,0.79,0.59,0.22,0.02,0,0,0.5,1,0,0,0,0.23,0
0.59,0,0.75,1,0,0.29,1,0,0,0.06,1,1,0,0,1,0.24,0.27,0,0.12,0.7,0.2,0.16,0.74,0.45,0.26,0.02,0.46,0.32,0.52,1,0,0,0,0.33,0
0.72,1,0.38,1,0,0.43,0,0.5,0,0.06,1,0,1,0.67,1,0.53,0.32,0,0.2,0.68,0.16,0.13,0.79,0.45,0.25,0.09,0.61,0.57,0.15,1,1,0,0,0.22,1
Ve işte benim Torch Lua kod:
-- add comma to separate thousands
function comma_value(amount)
local formatted = amount
while true do
formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
if (k==0) then
break
end
end
return formatted
end
-- function that computes the confusion matrix
function confusion_matrix(predictionTestVect, truthVect, threshold, printValues)
local tp = 0
local tn = 0
local fp = 0
local fn = 0
local MatthewsCC = -2
local accuracy = -2
local arrayFPindices = {}
local arrayFPvalues = {}
local arrayTPvalues = {}
local areaRoc = 0
local fpRateVett = {}
local tpRateVett = {}
local precisionVett = {}
local recallVett = {}
for i=1,#predictionTestVect do
if printValues == true then
io.write("predictionTestVect["..i.."] = ".. round(predictionTestVect[i],4).."\ttruthVect["..i.."] = "..truthVect[i].." ");
io.flush();
end
if predictionTestVect[i] >= threshold and truthVect[i] >= threshold then
tp = tp + 1
arrayTPvalues[#arrayTPvalues+1] = predictionTestVect[i]
if printValues == true then print(" TP ") end
elseif predictionTestVect[i] < threshold and truthVect[i] >= threshold then
fn = fn + 1
if printValues == true then print(" FN ") end
elseif predictionTestVect[i] >= threshold and truthVect[i] < threshold then
fp = fp + 1
if printValues == true then print(" FP ") end
arrayFPindices[#arrayFPindices+1] = i;
arrayFPvalues[#arrayFPvalues+1] = predictionTestVect[i]
elseif predictionTestVect[i] < threshold and truthVect[i] < threshold then
tn = tn + 1
if printValues == true then print(" TN ") end
end
end
print("TOTAL:")
print(" FN = "..comma_value(fn).."/"..comma_value(tonumber(fn+tp)).."\t (truth == 1) & (prediction < threshold)");
print(" TP = "..comma_value(tp).."/"..comma_value(tonumber(fn+tp)).."\t (truth == 1) & (prediction >= threshold)\n");
print(" FP = "..comma_value(fp).."/"..comma_value(tonumber(fp+tn)).."\t (truth == 0) & (prediction >= threshold)");
print(" TN = "..comma_value(tn).."/"..comma_value(tonumber(fp+tn)).."\t (truth == 0) & (prediction < threshold)\n");
local continueLabel = true
if continueLabel then
upperMCC = (tp*tn) - (fp*fn)
innerSquare = (tp+fp)*(tp+fn)*(tn+fp)*(tn+fn)
lowerMCC = math.sqrt(innerSquare)
MatthewsCC = -2
if lowerMCC>0 then MatthewsCC = upperMCC/lowerMCC end
local signedMCC = MatthewsCC
print("signedMCC = "..signedMCC)
if MatthewsCC > -2 then print("\n::::\tMatthews correlation coefficient = "..signedMCC.."\t::::\n");
else print("Matthews correlation coefficient = NOT computable"); end
accuracy = (tp + tn)/(tp + tn +fn + fp)
print("accuracy = "..round(accuracy,2).. " = (tp + tn)/(tp + tn +fn + fp) \t \t [worst = -1, best = +1]");
local f1_score = -2
if (tp+fp+fn)>0 then
f1_score = (2*tp)/(2*tp+fp+fn)
print("f1_score = "..round(f1_score,2).." = (2*tp)/(2*tp+fp+fn) \t [worst = 0, best = 1]");
else
print("f1_score CANNOT be computed because (tp+fp+fn)==0")
end
local totalRate = 0
if MatthewsCC > -2 and f1_score > -2 then
totalRate = MatthewsCC + accuracy + f1_score
print("total rate = "..round(totalRate,2).." in [-1, +3] that is "..round((totalRate+1)*100/4,2).."% of possible correctness");
end
local numberOfPredictedOnes = tp + fp;
print("numberOfPredictedOnes = (TP + FP) = "..comma_value(numberOfPredictedOnes).." = "..round(numberOfPredictedOnes*100/(tp + tn + fn + fp),2).."%");
io.write("\nDiagnosis: ");
if (fn >= tp and (fn+tp)>0) then print("too many FN false negatives"); end
if (fp >= tn and (fp+tn)>0) then print("too many FP false positives"); end
if (tn > (10*fp) and tp > (10*fn)) then print("Excellent ! ! !");
elseif (tn > (5*fp) and tp > (5*fn)) then print("Very good ! !");
elseif (tn > (2*fp) and tp > (2*fn)) then print("Good !");
elseif (tn >= fp and tp >= fn) then print("Alright");
else print("Baaaad"); end
end
return {accuracy, arrayFPindices, arrayFPvalues, MatthewsCC};
end
-- Permutations
-- tab = {1,2,3,4,5,6,7,8,9,10}
-- permute(tab, 10, 10)
function permute(tab, n, count)
n = n or #tab
for i = 1, count or n do
local j = math.random(i, n)
tab[i], tab[j] = tab[j], tab[i]
end
return tab
end
-- round a real value
function round(num, idp)
local mult = 10^(idp or 0)
return math.floor(num * mult + 0.5)/mult
end
-- ##############################3
local profile_vett = {}
local csv = require("csv")
local fileName = "dataset_file.csv"
print("Readin' "..tostring(fileName))
local f = csv.open(fileName)
local column_names = {}
local j = 0
for fields in f:lines() do
if j>0 then
profile_vett[j] = {}
for i, v in ipairs(fields) do
profile_vett[j][i] = tonumber(v);
end
j = j + 1
else
for i, v in ipairs(fields) do
column_names[i] = v
end
j = j + 1
end
end
OPTIM_PACKAGE = true
local output_number = 1
THRESHOLD = 0.5 -- ORIGINAL
DROPOUT_FLAG = false
MOMENTUM = false
MOMENTUM_ALPHA = 0.5
MAX_MSE = 4
LEARN_RATE = 0.001
ITERATIONS = 100
local hidden_units = 2000
local hidden_layers = 1
local hiddenUnitVect = {2000, 4000, 6000, 8000, 10000}
-- local hiddenLayerVect = {1,2,3,4,5}
local hiddenLayerVect = {1}
local profile_vett_data = {}
local label_vett = {}
for i=1,#profile_vett do
profile_vett_data[i] = {}
for j=1,#(profile_vett[1]) do
if j<#(profile_vett[1]) then
profile_vett_data[i][j] = profile_vett[i][j]
else
label_vett[i] = profile_vett[i][j]
end
end
end
print("Number of value profiles (rows) = "..#profile_vett_data);
print("Number features (columns) = "..#(profile_vett_data[1]));
print("Number of targets (rows) = "..#label_vett);
local table_row_outcome = label_vett
local table_rows_vett = profile_vett
-- ########################################################
-- START
local indexVect = {};
for i=1, #table_rows_vett do indexVect[i] = i; end
permutedIndexVect = permute(indexVect, #indexVect, #indexVect);
TEST_SET_PERC = 20
local test_set_size = round((TEST_SET_PERC*#table_rows_vett)/100)
print("training_set_size = "..(#table_rows_vett-test_set_size).." elements");
print("test_set_size = "..test_set_size.." elements\n");
local train_table_row_profile = {}
local test_table_row_profile = {}
local original_test_indexes = {}
for i=1,#table_rows_vett do
if i<=(tonumber(#table_rows_vett)-test_set_size) then
train_table_row_profile[#train_table_row_profile+1] = {torch.Tensor(table_rows_vett[permutedIndexVect[i]]), torch.Tensor{table_row_outcome[permutedIndexVect[i]]}}
else
original_test_indexes[#original_test_indexes+1] = permutedIndexVect[i];
test_table_row_profile[#test_table_row_profile+1] = {torch.Tensor(table_rows_vett[permutedIndexVect[i]]), torch.Tensor{table_row_outcome[permutedIndexVect[i]]}}
end
end
require 'nn'
perceptron = nn.Sequential()
input_number = #table_rows_vett[1]
perceptron:add(nn.Linear(input_number, hidden_units))
perceptron:add(nn.Sigmoid())
if DROPOUT_FLAG==true then perceptron:add(nn.Dropout()) end
for w=1,hidden_layers do
perceptron:add(nn.Linear(hidden_units, hidden_units))
perceptron:add(nn.Sigmoid())
if DROPOUT_FLAG==true then perceptron:add(nn.Dropout()) end
end
perceptron:add(nn.Linear(hidden_units, output_number))
function train_table_row_profile:size() return #train_table_row_profile end
function test_table_row_profile:size() return #test_table_row_profile end
-- OPTIMIZATION LOOPS
local MCC_vect = {}
for a=1,#hiddenUnitVect do
for b=1,#hiddenLayerVect do
local hidden_units = hiddenUnitVect[a]
local hidden_layers = hiddenLayerVect[b]
print("hidden_units = "..hidden_units.."\t output_number = "..output_number.." hidden_layers = "..hidden_layers)
local criterion = nn.MSECriterion()
local lossSum = 0
local error_progress = 0
require 'optim'
local params, gradParams = perceptron:getParameters()
local optimState = nil
if MOMENTUM==true then
optimState = {learningRate = LEARN_RATE}
else
optimState = {learningRate = LEARN_RATE,
momentum = MOMENTUM_ALPHA }
end
local total_runs = ITERATIONS*#train_table_row_profile
local loopIterations = 1
for epoch=1,ITERATIONS do
for k=1,#train_table_row_profile do
-- Function feval
local function feval(params)
gradParams:zero()
local thisProfile = train_table_row_profile[k][1]
local thisLabel = train_table_row_profile[k][2]
local thisPrediction = perceptron:forward(thisProfile)
local loss = criterion:forward(thisPrediction, thisLabel)
-- print("thisPrediction = "..round(thisPrediction[1],2).." thisLabel = "..thisLabel[1])
lossSum = lossSum + loss
error_progress = lossSum*100/(loopIterations*MAX_MSE)
if ((loopIterations*100/total_runs)*10)%10==0 then
io.write("completion: ", round((loopIterations*100/total_runs),2).."%")
io.write(" (epoch="..epoch..")(element="..k..") loss = "..round(loss,2).." ")
io.write("\terror progress = "..round(error_progress,5).."%\n")
end
local dloss_doutput = criterion:backward(thisPrediction, thisLabel)
perceptron:backward(thisProfile, dloss_doutput)
return loss,gradParams
end
optim.sgd(feval, params, optimState)
loopIterations = loopIterations+1
end
end
local correctPredictions = 0
local atleastOneTrue = false
local atleastOneFalse = false
local predictionTestVect = {}
local truthVect = {}
for i=1,#test_table_row_profile do
local current_label = test_table_row_profile[i][2][1]
local prediction = perceptron:forward(test_table_row_profile[i][1])[1]
predictionTestVect[i] = prediction
truthVect[i] = current_label
local labelResult = false
if current_label >= THRESHOLD and prediction >= THRESHOLD then
labelResult = true
elseif current_label < THRESHOLD and prediction < THRESHOLD then
labelResult = true
end
if labelResult==true then correctPredictions = correctPredictions + 1; end
print("\nCorrect predictions = "..round(correctPredictions*100/#test_table_row_profile,2).."%")
local printValues = false
local output_confusion_matrix = confusion_matrix(predictionTestVect, truthVect, THRESHOLD, printValues)
end
end
kimse neden hakkında fikir var mı benim betik sadece sıfır elementi mi tahmin ediyor?
DÜZENLEME:
Ben meşale/lua aşina değilim ama Kodunuzdaki herhangi bir veri-normalleştirme adımı bulamıyorum. Bunu yapıyor musun? Bu çok önemlidir (özellikle de diğerlerine göre çok büyük değerlere sahip bir sütununuz olduğu için)! Bazı yakınsama sayılarını da göstermek isteyebilirsiniz. Eğitim hatası azaldı mı? – sascha
@sascha Teşekkürler, normalleştirilmiş veri kümesini kullanıyorum, ancak orijinal veri kümesini kazara ekledim. Şimdi orijinal veri kümesini normalleştirilmiş olanla değiştirdim. Fark ettiğin için teşekkürler. Ve evet, eğitim hatası genellikle ~ 15'den ~ 6'ya düşer. –