手把手教你開發人工智能微信小程序(1):線性迴歸模型

談到人工智能、機器學習,我們可能會覺得很神祕,其實機器學習背後的理論並不複雜。就如同原子彈這麼尖端的科技,其背後的理論就是一個很簡單的公式:

E = mc²

機器學習的最基礎理論其實也不復雜,本文先嚐試從一個線性迴歸問題出發,探討一下機器學習的一般步驟。通過本文,你將學習到:

  • 定義機器學習模型

  • 定義損失函數

  • 模型訓練

  • 從訓練的模型進行推導

線性迴歸

想必大家應該做過物理實驗,還記得有這樣的實驗嗎?就是觀察一系列根據某個因素變化(比如質量)的實驗數據,然後建立平面座標,在座標系中標記一系列離散的點,然後擬合出曲線或直線。如果結果和因子之間是線性關係,那麼擬合出來就近似於一條直線。一般而言,線性關係可以用如下公式表示:

y = a * x + b

現在我們有一系列的x值以及與之對應的y值,如何得到a和b的值呢?我們以前的方法可能是將這些點描在座標上,然後描一條近似連接所有點的直線(在實際實驗中,可能有一些干擾因素,所有的點連接起來並非一條直線),在座標軸上可以很容易看出a和b的值。

機器學習所要解決的問題也是一樣,就是知道一系列x和y的值(數據集),需要找出它們之間的關係。如果是線性問題,就是求解a和b的值。

機器學習通常採用迴歸解決參數求解問題。

爲了簡單起見,我們以線性迴歸爲例。所謂線性迴歸,就是首先給一個a和b的值(通常給0值),然後計算出y的值,和實際的y值進行比較,如果發現誤差比較大,就調整a和b的值,比如a和b都加上0.0001,然後再計算y的值,和實際的y值比較,依次反覆,只要誤差是在逐步減小,最終選擇的a和b的值,就接近理論的a和b的值。

比如下面幾個x、y的對應值:

x = [1, 2, 3, 4];
y = [1, 3, 5, 7];

你可能立刻就能看出x和y之間的關係是:

y = 2 * x - 1;

這樣理論上 a = 2,b = -1。但對於計算機,它沒有這樣的直覺,我們就先給它a = 0, b = 0,讓它通過遞歸算法,逐步接近這個值,可能最終得到的值是 a = 1.99,b = -0.99。

所以我們需要理解機器學習的結果,最後推算出的結果並非理論上的真實值,而是一個接近真實的值。

至於機器學習如何保證調整a和b的值,誤差能夠越來越小,這背後也有複雜的算法。對於機器學習應用開發者而言,我們並不需要去實現算法,只需要做簡單的瞭解即可,機器學習框架,如tensorflow,幫我們解決了這些問題。

好吧,我們就以實際代碼,來說明如何完成一個機器學習任務。

線性迴歸代碼實例

我們就開門見山,直接放代碼:

    const tf = require('@tensorflow/tfjs');


    //定義一個線性迴歸模型。
    const model = tf.sequential();
    model.add(tf.layers.dense({ units: 1, inputShape: [1] }));


    model.compile({ loss: 'meanSquaredError', optimizer: 'sgd' });


    // 爲訓練生成一些合成數據
    const xs = tf.tensor2d([1, 2, 3, 4], [4, 1]);
    const ys = tf.tensor2d([1, 3, 5, 7], [4, 1]);


    // 使用數據訓練模型
    model.fit(xs, ys, { epochs: 10 }).then(() => {
      // 在該模型從未看到過的數據點上使用模型進行推理
      model.predict(tf.tensor2d([5], [1, 1])).print();
    });

第1行代碼引入 tfjs 模塊,需要注意,在上一篇文章中引入的是 tfjs-core ,這裏爲了方便,直接引入tfjs,它包含了 tfjs-core ,  tfjs-layers 等。所以需要修改 package.json 文件,將其中的 @tensorflow/tfjs-core 替換爲 @tensorflow/tfjs 。

第4、5行代碼定義線性迴歸模型。sequential()返回一個序列模型,dense爲全連接層。一般來說,我們不用自行設計模型,所以一般模型代碼照搬即可。

第7行代碼編譯模型,其中有兩個重要的參數,一個是損失函數,一個是優化器,它們決定着模型是否能夠很快收斂。對於不同的任何以及模型,在損失函數的選擇有考量,不過我們一般也是按照模型設計者的建議使用對應的損失函數。優化器就那幾種選擇,翻翻文檔,這裏選擇最普通的 sgd (隨機梯度下降)優化器。

第10、11行代碼是給出訓練數據,這裏出於演示的目的,直接在代碼中寫定,一般情況需要從文件或網絡讀取。

第14行代碼是進行模型訓練,就是逐步嘗試獲得最優解的過程,我們不能無限訓練下去,所以這裏指定 10 個輪次。

第16行代碼根據訓練的模型,求 x=5 時的 y 值。

怎麼樣?有了機器學習框架,從定義模型、訓練,到最後的推理,是不是很簡單?我們並不需要理解複雜的隨機梯度下降算法,就可以完成機器學習的任務。

如果我們在微信小程序中運行上述代碼,會得出以下結果:

Tensor
     [[6.0889206],]

而且每次的結果還不同,有同學可能會問,正確結果不是應該接近 9 嗎?這個結果也偏差太大了吧!

因爲上述代碼只是出於演示目的,還存在如下問題:

  1. 數據不足,我們只給出了4個樣本數據,樣本太少,很難找出x,y之間的關係。這也是現代機器學習,特別是深度學習,需要大量訓練數據的原因。

  2. 迭代次數太少,在誤差還在減少的中途,我們就退出了計算,這樣得到的參數,就存在比較大的誤差。

  3. 每次推理之前都需要訓練,而在實際的項目中,一般是訓練和推理是兩個分開的過程。

沒關係,這只是一個入門的機器學習程序,後續我們會學習到比較完善的例子。

機器學習應用編寫過程

雖然上面的代碼非常簡短,但也具有機器學習應用的基本框架。機器學習應用的通常過程是:

  1. 準備訓練數據

  2. 定義模型

  3. 編譯模型(定義損失函數、優化器等參數)

  4. 訓練模型

  5. 模型推理

在後面的文章,我們可以看到,不管多複雜的機器學習應用,都不外乎這些步驟,區別就在於複雜程度。就如同雖然有了 E = mc² 這個理論,要造成原子彈,還有很多路需要走。

小結

本章主要講解了建立線性迴歸模型,雖然是一個精簡的程序,但具備了機器學習程序的基本框架。在下一篇文章中,我將說明如何在微信小程序中加載訓練數據。沒有數據,就沒有機器學習。如果你有什麼建議,歡迎留言。

本系列文章的源碼請訪問:

https://github.com/mogotech/wechat-tfjs-examples


發佈了180 篇原創文章 · 獲贊 447 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章