TensorFlow.NET機器學習入門【3】採用神經網路實現非線性迴歸

seabluescn發表於2021-12-24

 上一篇文章我們介紹的線性模型的求解,但有很多模型是非線性的,比如:

 

 這裡表示有兩個輸入,一個輸出。

現在我們已經不能採用y=ax+b的形式去定義一個函式了,我們只能知道輸入變數的數量,但不知道某個變數存在幾次方的分量,所以我們採用一個神經網路去定義一個函式。

 

   我們假設只有一個輸入、一個輸出,神經網路模型結構類似上圖,其中藍色的路徑仍為線性模型,紅色路徑為階躍函式,是非線性模型。

 以上模型只有三個神經元,設輸入為x,隱藏層為h,啟用函式輸出為a,最終輸出為y,整個資料計算流情況如下:

   

  以上共有6+3+1個變數,整個訓練的過程就是要解出這些變數。官方教程內有自定義神經網路模型的求解程式碼,和解線性模型的流程一致,大致以下幾個步驟:

1、預設所有k=1,b=0;

2、將x代入模型,求得pred_y,通過pred_y和y計算損失函式,在通過損失函式來計算梯度;

3、通過梯度調整k、b的值

4、重複上述2、3過程,直到損失函式足夠小。

具體程式碼請參看官方示例程式碼。

我們這篇文章將採用Keras封裝好的方法來進行神經網路的訓練和應用。

整個程式包括:建立模型、訓練模型和應用模型三個過程。

主執行緒程式碼:

        public void Run()
        {  
            //1、建立模型
            Model model = BuildModel();  
            model.compile(loss: keras.losses.MeanSquaredError(),
                optimizer: keras.optimizers.SGD(0.02f),
                metrics: new[] { "mae" }); 
            model.summary();       

            //2、訓練模型
            (NDArray train_x, NDArray train_y) = PrepareData(1000);
            model.fit(train_x, train_y, batch_size: 64, epochs: 100);

            //3、應用模型(消費)
            test(model);
        }

 

1、建立模型

BuildModel方法定義如下:
        /// <summary>
        /// 構建網路模型
        /// </summary>     
        private Model BuildModel()
        {
            // 網路引數
            int num_features = 1; // data features 
            int n_hidden_1 = 16; // 1st layer number of neurons.     
            int num_out = 1; // total output .

            var model = keras.Sequential();
            model.add(keras.Input(num_features));
            model.add(keras.layers.Dense(n_hidden_1));
            model.add(keras.layers.LeakyReLU(0.2f));
            model.add(keras.layers.Dense(num_out));

            return model;
        }

以上:Input為輸入層,Dense為全連線層,啟用函式可選包括:Sigmod、ReLu、LeakyReLu、tanh

model.compile方法定義該模型的訓練方式:

loss: keras.losses.MeanSquaredError()表示損失函式採用均方差公式(MSE),這個公式上一篇文章介紹過
optimizer: keras.optimizers.SGD(0.02f)表示引數更新採用隨機梯度下降法(SGD),學習率為0.02
metrics: new[] { "mae" }表示要顯示的模型評價方法為平均絕對誤差(Mean absolute Error),另外此處還有一個選項為acc,表示準確性( accuracy),後面在進行分類學習時將採用這種評價方法。

 model.summary()方法將列印出該模型的摘要資訊。

 

  

2、訓練模型

 (NDArray train_x, NDArray train_y) = PrepareData(1000);

model.fit(train_x, train_y, batch_size: 64, epochs: 100);

首先要載入學習資料,然後將學習資料提供給fit方法進行學習,batch_size 表示每次運算取的資料量,epochs表示迴圈迭代的次數。所有學習資料用完一次就表示一個epoch,1000除以64等於15.625,所以每計算16次就表示一個epoch。

整個訓練過程中將列印出下列資訊:

 

  PrepareData方法:

TensorFlow.NET機器學習入門【3】採用神經網路實現非線性迴歸
        /// <summary>
        /// 載入訓練資料
        /// </summary>
        /// <param name="total_size"></param>    
        private (NDArray, NDArray) PrepareData(int total_size)
        {
            float[,] arrx = new float[total_size, 1];
            float[] arry = new float[total_size];

            for (int i = 0; i < total_size; i++)
            {
                float x = (float)random.Next(-400, 400) / 100;
                float y = x * x;

                arrx[i, 0] = x;
                arry[i] = y;
            }

            NDArray train_X = np.array(arrx);
            NDArray train_Y = np.array(arry);

            return (train_X, train_Y);
        }
View Code

該方法生成1000個符合y=x*x的標準資料。

 

3、應用模型

 學習完成以後,該模型就可以用於實際應用了。我們隨機生成一下資料,將模型計算的結果和理論實際的數值進行比較,可以判斷模型是否有效。

        /// <summary>
        /// 消費模型
        /// </summary>      
        private void test(Model model)
        {
            int test_size = 10;

            for (int i = 0; i < test_size; i++)
            {
                float x = (float)random.Next(-300, 300) / 100;
                float y = x * x;

                var test_x = np.array(new float[1, 1] { { x } });
                var pred_y = model.Apply(test_x);

                Console.WriteLine($"{i}:x={(float)test_x:0.00}\ty={y:0.0000} Pred:{(float)pred_y[0].numpy():0.0000}");
            }
        }

執行結果如下:

 看結果情況,基本像那麼一回事。

 

【相關資源】

 原始碼:Git: https://gitee.com/seabluescn/tf_not.git

專案名稱:NonlinearRegressionWithKeras

目錄:檢視TensorFlow.NET機器學習入門系列目錄

相關文章