2014-11-08 218 views
-1

我來尋找我正在寫的程序的一般提示。神經網絡[ocr]

目標是: 使用神經網絡程序識別3個字母[D,O,M](或者如果我輸入除3之外的任何內容則顯示「什麼都不識別」)。

這是我到目前爲止有:

一類爲我的單神經元

public class neuron 
{ 
    double[] weights; 
    public neuron() 
    { 
     weights = null; 
    } 
    public neuron(int size) 
    { 
     weights = new double[size + 1]; 
     Random r = new Random(); 
     for (int i = 0; i <= size; i++) 
     { 
      weights[i] = r.NextDouble()/5 - 0.1; 
     } 
    } 
    public double output(double[] wej) 
    { 
     double s = 0.0; 
     for (int i = 0; i < weights.Length; i++) s += weights[i] * wej[i]; 
     s = 1/(1 + Math.Exp(s)); 
     return s; 
    } 
} 

一種用於層類:

public class layer 
{ 
    neuron[] tab; 
    public layer() 
    { 
     tab = null; 
    } 
    public layer(int numNeurons, int numInputs) 
    { 
     tab = new neuron[numNeurons]; 
     for (int i = 0; i < numNeurons; i++) 
     { 
      tab[i] = new neuron(numInputs); 
     } 
    } 
    public double[] compute(double[] wejscia) 
    { 
     double[] output = new double[tab.Length + 1]; 
     output[0] = 1; 
     for (int i = 1; i <= tab.Length; i++) 
     { 
      output[i] = tab[i - 1].output(wejscia); 
     } 
     return output; 
    } 
} 

最後一類的網絡

public class network 
{ 
    layer[] layers = null; 
    public network(int numLayers, int numInputs, int[] npl) 
    { 
     layers = new layer[numLayers]; 
     for (int i = 0; i < numLayers; i++) 
     { 
      layers[i] = new layer(npl[i], (i == 0) ? numInputs : (npl[i - 1])); 
     } 

    } 
    double[] compute(double[] inputs) 
    { 
     double[] output = layers[0].compute(inputs); 
     for (int i = 1; i < layers.Length; i++) 
     { 
      output = layers[i].compute(output); 

     } 
     return output; 
    } 
} 

現在爲algorythm我選擇了:

我有一個圖片框,大小200x200,您可以在其中繪製一個字母(或從jpg文件中讀取一個字母)。

我然後將其轉換爲我的第一個陣列(讓整個畫面)和2一(切周圍的非相關背景),像這樣:

Bitmap bmp2 = new Bitmap(this.pictureBox1.Image); 
     int[,] binaryfrom = new int[bmp2.Width, bmp2.Height]; 

     int minrow=0, maxrow=0, mincol=0, maxcol=0; 
     for (int i = 0; i < bmp2.Height; i++) 
     { 
      for (int j = 0; j < bmp2.Width; j++) 
      { 
       if (bmp2.GetPixel(j, i).R == 0) 
       { 
        binaryfrom[i, j] = 1; 
        if (minrow == 0) minrow = i; 
        if (maxrow < i) maxrow = i; 
        if (mincol == 0) mincol = j; 
        else if (mincol > j) mincol = j; 
        if (maxcol < j) maxcol = j; 
       } 
       else 
       { 
        binaryfrom[i, j] = 0; 
       } 
      } 
     } 


     int[,] boundaries = new int[binaryfrom.GetLength(0)-minrow-(binaryfrom.GetLength(0)-(maxrow+1)),binaryfrom.GetLength(1)-mincol-(binaryfrom.GetLength(1)-(maxcol+1))]; 

     for(int i = 0; i < boundaries.GetLength(0); i++) 
     { 
      for(int j = 0; j < boundaries.GetLength(1); j++) 
      { 
       boundaries[i, j] = binaryfrom[i + minrow, j + mincol]; 

      } 
     } 

並將其轉換爲12X8像我的最後一個數組所以(我知道我可以這樣縮短公平一點,但希望在不同循環的每一步,所以我可以看到哪裏出了問題更容易[如果有的話確實]):

int[,] finalnet = new int[12, 8]; 

     int k = 1; 
     int l = 1; 

     for (int i = 0; i < finalnet.GetLength(0); i++) 
     { 
      for (int j = 0; j < finalnet.GetLength(1); j++) 
      { 
       finalnet[i, j] = 0; 
      } 
     } 

     while (k <= finalnet.GetLength(0)) 
      { 
       while (l <= finalnet.GetLength(1)) 
       { 
        for (int i = (int)(boundaries.GetLength(0)/finalnet.GetLength(0)) * (k - 1); i < (int)(boundaries.GetLength(0)/finalnet.GetLength(0)) * k; i++) 
        { 
         for (int j = (int)(boundaries.GetLength(1)/finalnet.GetLength(1)) * (l - 1); j < (int)(boundaries.GetLength(1)/finalnet.GetLength(1)) * l; j++) 
         { 
          if (boundaries[i, j] == 1) finalnet[k-1, l-1] = 1; 
         } 
        } 
        l++; 
       } 
       l = 1; 
       k++; 
      } 
     int a = boundaries.GetLength(0); 
     int b = finalnet.GetLength(1); 
     if((a%b) != 0){ 

      k = 1; 

      while (k <= finalnet.GetLength(1)) 
      { 
       for (int i = (int)(boundaries.GetLength(0)/finalnet.GetLength(0)) * finalnet.GetLength(0); i < boundaries.GetLength(0); i++) 
       { 
        for (int j = (int)(boundaries.GetLength(1)/finalnet.GetLength(1)) * (k - 1); j < (int)(boundaries.GetLength(1)/finalnet.GetLength(1)) * k; j++) 
        { 
         if (boundaries[i, j] == 1) finalnet[finalnet.GetLength(0) - 1, k - 1] = 1; 
        } 

       } 
       k++; 
      } 
     } 

     if (boundaries.GetLength(1) % finalnet.GetLength(1) != 0) 
     { 
      k = 1; 

      while (k <= finalnet.GetLength(0)) 
      { 
       for (int i = (int)(boundaries.GetLength(0)/finalnet.GetLength(0)) * (k - 1); i < (int)(boundaries.GetLength(0)/finalnet.GetLength(0)) * k; i++) 
       { 
        for (int j = (int)(boundaries.GetLength(1)/finalnet.GetLength(1)) * finalnet.GetLength(1); j < boundaries.GetLength(1); j++) 
        { 
         if (boundaries[i, j] == 1) finalnet[k - 1, finalnet.GetLength(1) - 1] = 1; 
        } 
       } 
       k++; 
      } 

      for (int i = (int)(boundaries.GetLength(0)/finalnet.GetLength(0)) * finalnet.GetLength(0); i < boundaries.GetLength(0); i++) 
      { 
       for (int j = (int)(boundaries.GetLength(1)/finalnet.GetLength(1)) * finalnet.GetLength(1); j < boundaries.GetLength(1); j++) 
       { 
        if (boundaries[i, j] == 1) finalnet[finalnet.GetLength(0) - 1, finalnet.GetLength(1) - 1] = 1; 
       } 
      } 
     } 

結果是12X8(我可以在代碼中更改它以從一些窗體控件中獲取它)0和1的數組,其中1構成粗糙的shap e你畫的一封信。

現在我的問題是: 這是一個正確的algorythm? 是我的功能

1/(1+Math.Exp(x)) 

好一個在這裏使用? 什麼應該是拓撲結構? 2或3層,如果3,隱藏層中有多少個神經元?我有96個輸入(finalnet數組的每個字段),所以我應該在第一層還需要96個神經元?我應該在最後一層還是4層有3個神經元(考慮到「不承認」的情況),還是沒有必要?

謝謝你的幫助。

編輯:哦,我忘了補充,我要訓練我的網絡使用Backpropagation algorythm。

回答

1

後來我創建了一個neural net to recognize digits 0-9(python,抱歉),所以根據我的(短)經驗,3層都可以,96/50/3拓撲可能會很好。至於輸出層,這是您的選擇;如果輸入圖像不是D,O或M,或者使用第四個輸出神經元指示該字母未被識別,則可以反向傳播全0。我認爲第一種選擇是最好的選擇,因爲它更簡單(縮短培訓時間,減少調試網絡的問題......),您只需要應用一個閾值,將圖像歸類爲「不被識別」。
我還使用了S形的激活功能,我沒有嘗試別人,但它的工作:)

+0

那麼,在我的演講中,沒有說明是使用雙極性還是單極性功能更好,所以我在網上進行了搜索,但我仍然不確定這一點。 3個輸出神經元看起來更容易是的,但是閾值讓我感到困惑,所以我們假設所有的神經元都返回接近0的值,如0,1; 0,2; 0,15是否可以安全地假設它不識別? – NagashTDN 2014-11-08 10:46:35

+1

@NagashTDN yes – BlackBear 2014-11-08 10:47:08

+0

alrgiht,thank you :) – NagashTDN 2014-11-08 10:53:14

2
  1. 您可能需要4層至少使用反向傳播方法獲得準確的結果。 1個輸入,2箇中間層和一個輸出層。 12 * 8矩陣太小(並且最終會導致數據丟失,從而導致完全失敗) - 嘗試一些16 * 16的東西。如果您想縮小大小,則必須剝離進一步的黑色像素的外層。

  2. 想想用你的參考字符訓練網絡。

  3. 請記住,您必須將輸出再次反饋回輸入層,並重復多次。

+0

1.您能否很快向我解釋爲什麼我需要4層? 2.我開始使用7x5矩陣,然後發現如果我不想要一個超級準確的結果(這是我的實驗室uni的程序),12x8是優先考慮的大小。您認爲16x16的AxA矩陣比AxB更好還是更大一些? 3.我有一組訓練圖像,由5個不同的人寫成,每個字母10個。 4.我認爲我的英語不夠好理解這一點,對不起:) 此外,爲什麼我會陷入低谷,我盡我所能解釋我的情況。 – NagashTDN 2014-11-08 10:47:04

+0

中間(隱藏)圖層在學習樣本中發揮着至關重要的作用。因此,多一層可以提高學習能力。如果精度不是問題,你可以使用3層。然而,在工業強度代碼中,人們使用動態可配置網絡來提高準確性和更好的測試。 16X16是我的經驗優化的。 – Raj 2014-11-08 12:03:28