自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

前端人工智能:通過機(jī)器學(xué)習(xí)推導(dǎo)函數(shù)方程式--鉑金Ⅲ

開發(fā) 前端 機(jī)器學(xué)習(xí)
本文要講解的項(xiàng)目代碼,就是要根據(jù)一些規(guī)則模擬數(shù)據(jù),然后通過機(jī)器學(xué)習(xí)和訓(xùn)練,根據(jù)這些數(shù)據(jù)去反向推測出生成這些數(shù)據(jù)的公式函數(shù)。

 [[259734]]

什么是tensorflow.js

tensorflow.js是一個(gè)能運(yùn)行在瀏覽器和nodejs的一個(gè)機(jī)器學(xué)習(xí)、機(jī)器訓(xùn)練的javascript庫,眾所周知在瀏覽器上用javascript進(jìn)行計(jì)算是很慢的,而tensorflow.js會(huì)基于WebGL通過gpu進(jìn)行運(yùn)算加速來對(duì)高性能的機(jī)器學(xué)習(xí)模塊進(jìn)行加速運(yùn)算,從而能讓我們前端開發(fā)人員能在瀏覽器中進(jìn)行機(jī)器學(xué)習(xí)和訓(xùn)練神經(jīng)網(wǎng)絡(luò)。本文要講解的項(xiàng)目代碼,就是要根據(jù)一些規(guī)則模擬數(shù)據(jù),然后通過機(jī)器學(xué)習(xí)和訓(xùn)練,根據(jù)這些數(shù)據(jù)去反向推測出生成這些數(shù)據(jù)的公式函數(shù)。

基本概念

接下來我們用五分鐘過一下tensorflow的基本概念,這一部分主要介紹一些概念,筆者會(huì)用一些類比方式簡單的講述一些概念,旨在幫助大家快速理解,但是限于精力和篇幅,概念的具體詳細(xì)定義讀者們還是多去參照官方文檔。

張量(tensors)

張量其實(shí)就是一個(gè)數(shù)組,可以一維或多維數(shù)組。張量在tensorflow.js里就是一個(gè)數(shù)據(jù)單元。 

  1. const tensors = tf.tensor([[1.0, 2.0, 3.0], [10.0, 20.0, 30.0]]);  
  2. tensors.print(); 

在瀏覽器里將會(huì)輸出:

tensorflow還提供了語義化的張量創(chuàng)建函數(shù):tf.scalar(創(chuàng)建零維度的張量), tf.tensor1d(創(chuàng)建一維度的張量), tf.tensor2d(創(chuàng)建二維度的張量), tf.tensor3d(創(chuàng)建三維度的張量)、tf.tensor4d(創(chuàng)建四維度的張量)以及 tf.ones(張量里的值全是1)或者tf.zeros(張量里的值全是0)。

變量(variable)

張量tensor是不可變的,而變量variable是可變的,變量是通過張量初始化而來,代碼如下: 

  1. const initialValues = tf.zeros([5]);//[0, 0, 0, 0, 0]  
  2. const biases = tf.variable(initialValues); //通過張量初始化變量  
  3. biases.print(); //輸出[0, 0, 0, 0, 0] 

操作(operations)

張量可以通過操作符進(jìn)行運(yùn)算,比如add(加法)、sub(減法)、mul(乘法)、square(求平方)、mean(求平均值) 。 

  1. const e = tf.tensor2d([[1.0, 2.0], [3.0, 4.0]]);  
  2. const f = tf.tensor2d([[5.0, 6.0], [7.0, 8.0]]);  
  3. const ee_plus_f = e.add(f);  
  4. e_plus_f.print(); 

上面的例子輸出:

內(nèi)存管理(dispose和tf.tidy)

dispose和tf.tidy都是用來清空GPU緩存的,就相當(dāng)于咱們?cè)诰帉慾s代碼的時(shí)候,通過給這個(gè)變量賦值null來清空緩存的意思。 

  1. var a = {num: 1};  
  2. a = null;//清除緩存 

dispose

張量和變量都可以通過dispose來清空GPU緩存: 

  1. const x = tf.tensor2d([[0.0, 2.0], [4.0, 6.0]]);  
  2. const xx_squared = x.square();  
  3. x.dispose();  
  4. x_squared.dispose();  
  5. tf.tidy 

當(dāng)有多個(gè)張量和變量的時(shí)候,如果挨個(gè)調(diào)用dispose就太麻煩了,所以有了tf.tidy,將張量或者變量操作放在tf.tidy函數(shù)中,就會(huì)自動(dòng)給我們優(yōu)化和清除緩存。 

  1. const average = tf.tidy(() => {  
  2.   const y = tf.tensor1d([4.0, 3.0, 2.0, 1.0]);  
  3.   const z = tf.ones([1]);  
  4.   return y.sub(z);  
  5. });  
  6. average.print()  

以上例子輸出:

模擬數(shù)據(jù)

首先,我們要模擬一組數(shù)據(jù),根據(jù) 這個(gè)三次方程,以參數(shù)a=-0.8, b=-0.2, c=0.9, d=0.5生成[-1, 1]這個(gè)區(qū)間內(nèi)一些有誤差的數(shù)據(jù),數(shù)據(jù)可視化后如下:

假設(shè)我們并不知道a、b、c、d這四個(gè)參數(shù)的值,我們要通過這一堆數(shù)據(jù),用機(jī)器學(xué)習(xí)和機(jī)器訓(xùn)練去反向推導(dǎo)出這個(gè)多項(xiàng)式函數(shù)方程的和它的a、b、c、d這四個(gè)參數(shù)值。

設(shè)置變量(Set up variables)

因?yàn)槲覀円聪蛲茖?dǎo)出多項(xiàng)式方程的a、b、c、d這四個(gè)參數(shù)值,所以首先我們要先定義這四個(gè)變量,并給他們賦上一些隨機(jī)數(shù)當(dāng)做初始值。 

  1. const a = tf.variable(tf.scalar(Math.random()));  
  2. const b = tf.variable(tf.scalar(Math.random()));  
  3. const c = tf.variable(tf.scalar(Math.random()));  
  4. const d = tf.variable(tf.scalar(Math.random())); 

上面這四行代碼,tf.scalar就是創(chuàng)建了一個(gè)零維度的張量,tf.variable就是將我們的張量轉(zhuǎn)化并初始化成一個(gè)變量variable,如果通俗的用我們平時(shí)編寫javascript去理解,上面四行代碼就相當(dāng)于: 

  1. let a = Math.random();  
  2. let b = Math.random();  
  3. let c = Math.random();  
  4. let d = Math.random(); 

當(dāng)我們給a、b、c、d這四個(gè)參數(shù)值賦上了初始隨機(jī)值以后,a=0.513, b=0.261, c=0.259, d=0.504,我們將這些參數(shù)放入方程式后得到的曲線圖如下:

我們可以看到,根據(jù)隨機(jī)生成的a、b、c、d這四個(gè)參數(shù)并入到多項(xiàng)式后生成的數(shù)據(jù)跟真正的數(shù)據(jù)模擬的曲線差別很大,這就是我們接下來要做的,通過機(jī)器學(xué)習(xí)和訓(xùn)練,不斷的調(diào)整a、b、c、d這四個(gè)參數(shù)來將這根曲線盡可能的接近實(shí)際的數(shù)據(jù)曲線。

創(chuàng)建優(yōu)化器(Create an optimizer) 

  1. const learningRate = 0.5;  
  2. const optimizer = tf.train.sgd(learningRate); 

learningRate這個(gè)變量是定義學(xué)習(xí)率,在進(jìn)行每一次機(jī)器訓(xùn)練的時(shí)候,會(huì)根據(jù)學(xué)習(xí)率的大小去進(jìn)行計(jì)算的偏移量調(diào)整幅度,學(xué)習(xí)率越低,后面預(yù)測到的值就會(huì)越精準(zhǔn),但是響應(yīng)的會(huì)增加程序的運(yùn)行時(shí)間和計(jì)算量。高學(xué)習(xí)率會(huì)加快學(xué)習(xí)過程,但是由于偏移量幅度太大,容易造成在正確值的周邊上下擺動(dòng)導(dǎo)致運(yùn)算出的結(jié)果沒有那么準(zhǔn)確。

tf.train.sgd是我們選用了tensorflow.js里幫我們封裝好的SGD優(yōu)化器,即隨機(jī)梯度下降法。在機(jī)器學(xué)習(xí)算法的時(shí)候,通常采用梯度下降法來對(duì)我們的算法進(jìn)行機(jī)器訓(xùn)練,梯度下降法常用有三種形式BGD、SGD以及MBGD。

我們使用的是SGD這個(gè)批梯度下降法,因?yàn)槊慨?dāng)梯度下降而要更新一個(gè)訓(xùn)練參數(shù)的時(shí)候,機(jī)器訓(xùn)練的速度會(huì)隨著樣本的數(shù)量增加而變得非常緩慢。隨機(jī)梯度下降正是為了解決這個(gè)辦法而提出的。假設(shè)一般線性回歸函數(shù)的函數(shù)為:

SGD它是利用每個(gè)樣本的損失函數(shù)對(duì)θ求偏導(dǎo)得到對(duì)應(yīng)的梯度,來更新θ:

隨機(jī)梯度下降是通過每個(gè)樣本來迭代更新一次,對(duì)比上面的批量梯度下降,迭代一次需要用到所有訓(xùn)練樣本,SGD迭代的次數(shù)較多,在解空間的搜索過程看起來很盲目。但是大體上是往著更優(yōu)值方向移動(dòng)。隨機(jī)梯度下降收斂圖如下:

預(yù)期函數(shù)模型(training process functions)

編寫預(yù)期函數(shù)模型,其實(shí)就是用一些列的operations操作去描述我們的函數(shù)模型 

  1. function predict(x) {  
  2.   // y = a * x ^ 3 + b * x ^ 2 + c * x + d  
  3.   return tf.tidy(() => {  
  4.     return a.mul(x.pow(tf.scalar(3, 'int32')))  
  5.       .add(b.mul(x.square()))  
  6.       .add(c.mul(x))  
  7.       .add(d);  
  8.   });  

a.mul(x.pow(tf.scalar(3, 'int32')))就是描述了ax^3(a乘以x的三次方),b.mul(x.square()))描述了b x ^ 2(b乘以x的平方),c.mul(x)這些同理。注意,在predict函數(shù)return的時(shí)候,用tf.tidy包了起來,這是為了方便內(nèi)存管理和優(yōu)化機(jī)器訓(xùn)練過程的內(nèi)存。

定義損失函數(shù)(loss)

接下來我們要定義一個(gè)損失函數(shù),使用的是MSE(均方誤差,mean squared error)。數(shù)理統(tǒng)計(jì)中均方誤差是指參數(shù)估計(jì)值與參數(shù)真值之差平方的期望值,記為MSE。MSE是衡量“平均誤差”的一種較方便的方法,MSE可以評(píng)價(jià)數(shù)據(jù)的變化程度,MSE的值越小,說明預(yù)測模型描述實(shí)驗(yàn)數(shù)據(jù)具有更好的精確度。MSE的計(jì)算非常簡單,就是先根據(jù)給定的x得到實(shí)際的y值與預(yù)測得到的y值之差 的平方,然后在對(duì)這些差的平方求平均數(shù)即可。 

根據(jù)如上所述,我們的損失函數(shù)代碼如下: 

  1. function loss(prediction, labels) {  
  2.   const error = prediction.sub(labels).square().mean();  
  3.   return error;  

預(yù)期值prediction減去實(shí)際值labels,然后平方后求平均數(shù)即可。

機(jī)器訓(xùn)練(training)

好了,上面說了這么多,做了這么多的鋪墊和準(zhǔn)備,終于到了最關(guān)鍵的步驟,下面這段代碼和函數(shù)就是真正的根據(jù)數(shù)據(jù)然后通過機(jī)器學(xué)習(xí)和訓(xùn)練計(jì)算出我們想要的結(jié)果最重要的步驟。我們已經(jīng)定義好了基于SGD隨機(jī)梯度下降的優(yōu)化器optimizer,然后也定義了基于MSE均方誤差的損失函數(shù),我們應(yīng)該怎么結(jié)合他們兩個(gè)裝備去進(jìn)行機(jī)器訓(xùn)練和機(jī)器學(xué)習(xí)呢,看下面的代碼。 

  1. const numIterations = 75 
  2. async function train(xs, ys, numIterations) {  
  3.   for (let iter = 0; iter < numIterations; iter++) {  
  4.     //優(yōu)化器:SGD隨機(jī)梯度下降  
  5.     optimizer.minimize(() => {  
  6.       const pred = predict(xs);  
  7.       //損失函數(shù):MSE均方誤差  
  8.       return loss(pred, ys);  
  9.     });  
  10.     //防止阻塞瀏覽器  
  11.     await tf.nextFrame();  
  12.   }  

我們?cè)谕鈱佣x了一個(gè)numIterations = 75,意思是我們要進(jìn)行75次機(jī)器訓(xùn)練。在每一次循環(huán)中我們都調(diào)用了optimizer.minimize這個(gè)函數(shù),它會(huì)不斷地調(diào)用SGD隨機(jī)梯度下降法來不斷地更新和修正我們的a、b、c、d這四個(gè)參數(shù),并且每一次return的時(shí)候都會(huì)調(diào)用我們的基于MSE均方誤差loss損失函數(shù)來減小損失。經(jīng)過這75次的機(jī)器訓(xùn)練和機(jī)器學(xué)習(xí),加上SGD隨機(jī)梯度下降優(yōu)化器和loss損失函數(shù)進(jìn)行校準(zhǔn),然后就會(huì)得到非常接近正確數(shù)值的a、b、c、d四個(gè)參數(shù)。

我們注意到這個(gè)函數(shù)末尾有一行tf.nextFrame(),這個(gè)函數(shù)是為了解決在機(jī)器訓(xùn)練和機(jī)器學(xué)習(xí)的過程中會(huì)進(jìn)行大量的機(jī)器運(yùn)算,會(huì)阻塞瀏覽器,導(dǎo)致ui沒法更新的問題。

我們調(diào)用這個(gè)機(jī)器訓(xùn)練的函數(shù)train: 

  1. import {generateData} from './data';//這個(gè)文件在git倉庫里  
  2. const trainingData = generateData(100, {a: -.8, b: -.2, c: .9, d: .5});  
  3. await train(trainingData.xs, trainingData.ys, 75); 

調(diào)用了train函數(shù)后,我們就可以拿到a、b、c、d四個(gè)參數(shù)了。 

  1. console.log('a', a.dataSync()[0]);  
  2.  console.log('b', b.dataSync()[0]);  
  3.  console.log('c', c.dataSync()[0]);  
  4.  console.log('d', d.dataSync()[0]); 

得到的值是a=-0.564, b=-0.207, c=0.824, d=0.590,和原先我們定義的實(shí)際值a=-0.8, b=-0.2, c=0.9, d=0.5非常的接近了,對(duì)比圖如下:

項(xiàng)目運(yùn)行和安裝

本文涉及到的代碼安裝和運(yùn)行步驟如下: 

  1. git clone https://github.com/tensorflow/tfjs-examples  
  2. cd tfjs-examples/polynomial-regression-core  
  3. yarn  
  4. yarn watch 

tensorflow.js的官方example里有很多個(gè)項(xiàng)目,其中polynomial-regression-core(多項(xiàng)式方程回歸復(fù)原)這個(gè)例子就是我們本文重點(diǎn)講解的代碼,我在安裝的過程中并不太順利,每一次運(yùn)行都會(huì)報(bào)缺少模塊的error,讀者只需要根據(jù)報(bào)錯(cuò),把缺少的模塊挨個(gè)安裝上,然后根據(jù)error提示信息上google去搜索相應(yīng)的解決方法,都能運(yùn)行起來。

結(jié)語

說了這么多,本來不想寫結(jié)語的,但是想想,還是想表達(dá)一下本人內(nèi)心的一個(gè)搞笑荒謬的想法。我為什么會(huì)對(duì)這個(gè)人工智能的例子感興趣呢,是因?yàn)?,在我廣西老家(一個(gè)偏遠(yuǎn)的山村),那邊比較封建迷信,經(jīng)常拿一個(gè)人的生辰八字就去計(jì)算并說出這個(gè)人一生的命運(yùn),balabala說一堆,本人對(duì)這些風(fēng)氣一貫都是嗤之以鼻。但是,但是,但是。。。?;闹嚨臇|西來了,我老丈人十早年前因?yàn)檐嚨湺鴶嗔艘粭l腿,幾年前帶媳婦和老丈人回老家見親戚,老丈人覺得南方人這些封建迷信很好玩,就拿他自己的生辰八字去給鄉(xiāng)下的老者算了一下,結(jié)果那個(gè)老人說了很多,并說出了我老丈人出車禍的那一天的準(zhǔn)確的日期,精確到那一天的下午大致時(shí)間。。。。。這。。。。這就好玩了。。。當(dāng)年整個(gè)空氣突然安靜的場景至今歷歷在目,這件事一直記在心里,畢竟我從來不相信這些鬼鬼乖乖的東西,一直信奉科學(xué)是至高無上帶我們飛的真理。

咦?這跟人工智能有什么關(guān)系?我只是在思考,是不是我們每個(gè)人的生辰八字,就是笛卡爾平面坐標(biāo)系上的維度,或者說生辰八字就是多項(xiàng)式函數(shù)的a、b、c、d、e系數(shù),是不是真的有一個(gè)多項(xiàng)式函數(shù)方程能把這些生辰八字系數(shù)串聯(lián)起來得到一個(gè)公式,這個(gè)公式可以描述你的一生,記錄你的過去,并預(yù)測你的將來。。。。。。我們能不能找到自己對(duì)應(yīng)的維度和發(fā)生過的事情聯(lián)系起來,然后用人工智能去機(jī)器學(xué)習(xí)并訓(xùn)練出一個(gè)屬于我們自己一生命運(yùn)軌跡的函數(shù)。。。。行 不說了 ,各位讀者能看到這里我也是覺得對(duì)不起你們,好好讀書并忘掉我說的話。

上述觀點(diǎn)純屬個(gè)人見解。!^_^!

 

責(zé)任編輯:龐桂玉 來源: senmentfault
相關(guān)推薦

2015-10-10 09:32:24

機(jī)器學(xué)習(xí)人工智能

2021-03-30 13:45:00

人工智能

2016-09-19 08:57:48

2017-04-18 15:49:24

人工智能機(jī)器學(xué)習(xí)數(shù)據(jù)

2021-04-16 09:53:45

人工智能機(jī)器學(xué)習(xí)深度學(xué)習(xí)

2011-09-21 17:26:54

2017-05-12 13:58:30

2020-09-07 11:28:09

人工智能機(jī)器學(xué)習(xí)AI

2021-02-26 10:02:13

人工智能深度學(xué)習(xí)機(jī)器學(xué)習(xí)

2017-03-18 16:28:40

人工智能機(jī)器學(xué)習(xí)深度學(xué)習(xí)

2021-02-22 10:59:43

人工智能機(jī)器學(xué)習(xí)深度學(xué)習(xí)

2015-02-06 10:41:43

云許可軟件即服務(wù)IaaS

2019-03-06 09:00:00

機(jī)器學(xué)習(xí)人工智能

2020-10-16 10:19:10

智能

2017-07-19 13:08:27

人工智能機(jī)器學(xué)習(xí)深度學(xué)習(xí)

2017-05-04 20:45:07

人工智能數(shù)據(jù)科學(xué)機(jī)器學(xué)習(xí)

2023-03-01 11:18:59

人工智能機(jī)器學(xué)習(xí)

2022-06-01 14:33:59

人工智能交通運(yùn)輸機(jī)器學(xué)習(xí)

2020-06-12 10:57:08

人工智能機(jī)器學(xué)習(xí)RPA

2017-07-21 12:52:32

人工智能機(jī)器學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)