2016-09-26 32 views
7

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:

+1

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

+0

@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. –

cevap

2

Orijinal kodunuzu çalıştırdığımda bazen tüm sıfırları tahmin ediyorum ve bazen mükemmel performans elde ediyorum. Bu, orijinal modelinizin parametre değerlerinin başlatılmasında çok hassas olduğunu gösterir.

torch.manualSeed(0) numaralı bir tohum değeri kullanırsam (bu nedenle her zaman aynı başlatma işlemine sahibiz) her seferinde mükemmel performans elde ederim. Ama bu gerçekten genel bir çözüm değil.

  1. gizli birim sayısı azaltılmış:

    aşağıdaki değişiklikler yaptık daha genel bir iyileşme almak için. Orijinal kodda, 2000 biriminde tek gizli katmanı vardır. Ancak sadece 34 girişiniz ve 1 çıkışınız var. Çoğu zaman, giriş ve çıkışların sayısı arasında sadece olmak üzere gizli birimlerin sayısına ihtiyacınız var. 50'a indirdim.
  2. Etiketler asimetriktir, etiketlerin yalnızca 5/27'si (% 19) bir tanesidir, bu nedenle tren | test kümelerini gerçekten sıfır olanlara oranını koruyacak şekilde bölmelisiniz. Şimdilik test seti boyutunu% 50'ye çıkardım.
  3. Ben de, '0,01' öğrenme oranı arttı üzerine MOMENTUM döndü ve ben bu modeli (seri başı olmayan) 20 kez çalıştırdığınızda ben Excellent performansı 19 kez got 200

için ITERATIONS artmıştır. Daha da geliştirmek için hiper parametrelerini daha fazla ayarlayabilirsin. Ayrıca, "en iyi" modeli seçmek için ayrı bir doğrulama seti ile birden fazla başlatmaya da bakmalıdır (bu, zaten çok küçük veri kümenizi daha da alt bölecek olsa da). Aşağıda Yapıştırılan

-- 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_ALPHA = 0.5 
MAX_MSE = 4 

-- CHANGE: increased learn_rate to 0.01, reduced hidden units to 50, turned momentum on, increased iterations to 200 
LEARN_RATE = 0.01 
local hidden_units = 50 
MOMENTUM = true 
ITERATIONS = 200 
------------------------------------- 

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 

-- Seed random number generator 
-- torch.manualSeed(0) 

local indexVect = {}; 
for i=1, #table_rows_vett do indexVect[i] = i; end 
permutedIndexVect = permute(indexVect, #indexVect, #indexVect); 

-- CHANGE: increase test_set to 50% 
TEST_SET_PERC = 50 
--------------------------- 

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 
end 

20 ishal 1 çıktısı:

Correct predictions = 100% 
TOTAL: 
FN = 0/4 (truth == 1) & (prediction < threshold)  
TP = 4/4 (truth == 1) & (prediction >= threshold) 

FP = 0/9 (truth == 0) & (prediction >= threshold) 
TN = 9/9 (truth == 0) & (prediction < threshold) 

signedMCC = 1 

:::: Matthews correlation coefficient = 1 :::: 

accuracy = 1 = (tp + tn)/(tp + tn +fn + fp)  [worst = -1, best = +1] 
f1_score = 1 = (2*tp)/(2*tp+fp+fn)  [worst = 0, best = 1] 
total rate = 3 in [-1, +3] that is 100% of possible correctness 
numberOfPredictedOnes = (TP + FP) = 4 = 30.77% 

Diagnosis: Excellent ! ! ! 
+0

Teşekkürler Khalid, gerçekten işe yaradı! Sorular: Gizli birim numarasının '50'ye indirilmesi gerektiğini nasıl bildiniz? Öğrenme oranının 0.01'e yükseltilmesi gerektiğini nasıl bildiniz? Yineleme sayısının 200'e yükseltilmesi gerektiğini nasıl anladınız? –

+0

Hiper-parametreli ayarlamayla ilgili tavsiye ile birlikte iyi bir makale [burada] (https://arxiv.org/pdf/1206.5533v2.pdf) var, ancak itiraf etmeliyim ki, henüz bunu okuma şansım olmadı. Düşünce sürecim, ağın sadece ihtiyaç duyulduğu kadar geniş olmasını sağlamaktı (söz konusu soruda belirtildiği gibi, bir ağın giriş/çıkış katmanlarının büyüklüğünün iki katından (genişlik) olması gerektiği nadirdir) . Bundan sonra diğer parametrelerle deneme yapmak daha hızlıdır (model daha hızlı ilerler). – kabdulla

0

Şansı NN çok yavaş öğrenme ve dolayısıyla hiçbir şey öğrenme değildir vardır Senaryomun kullandıkları, onun normalize sürümü ile orijinal veri kümesi yerini aldı. Deeplearning4j, troubleshooting neural net training'da, çeşitli hiperparametrelerin sahip olduğu etki hakkında biraz ışık tutabilecek harika bir makaleye sahiptir.

Kodunuza bir bakış vardı, ben öncelikle aşağıdaki şeyler denemek istiyorum: LEARN_RATE = 0.001: Sen öğrenmek oranını sabit
:

  • öğrenme hızını ayarlayın. 1e-1 ve 1e-8 arasındaki değerleri deneyin.
  • Gizli katmanınızı ikiye katlayın:
    Gizli katmanınızı çimdiklemeniz gerekebilir: hiddenUnitVect = {2000, 4000, 6000, 8000, 10000}. Bu eldeki görev için biraz büyük görünüyor. Önce daha küçük bir ağ deneyin ve iyi genelleme yapmazsa boyutu artırın.
İlgili konular