神经网络基础原理(三)-----分类问题实弹演练及一些小干货
現(xiàn)在基本的概念已經(jīng)介紹得差不多了,是時候?qū)崙?zhàn)演示一下如何利用神經(jīng)網(wǎng)絡來處理分類問題的。按照一直的做法,自己出題自己解決。這次拿一個現(xiàn)實生活中的一個小問題來練練手:根據(jù)人的身高,體重,把人劃分成輕,正常,偏胖,肥胖這四種情況。按照現(xiàn)在流行的觀點認為,人正常的BMI指數(shù)范圍在20-25之間,低于20就是過輕,高于25低于28是偏胖,高于28就是肥胖了。
按照前面介紹的方法,解決問題的第一步是建模和打標簽。根據(jù)問題的描述,可以把訓練樣本定義成一個2維向量,其中第1維表示身高(以米為計算單位),第2維是體重(以千克為單位)。訓練樣本有了之后就是打標。有點編程經(jīng)驗的人一眼就可以看出來這里可以用機器打標。標簽數(shù)據(jù)是一個4維布爾值向量,第1維表示過輕,第2維表示正常,第3維表示偏胖,第4維表示肥胖。
第二步是建立模型,對于分類問題而言,最好的是先根據(jù)問題的規(guī)模來確定結(jié)點的數(shù)量,從上面的問題描述中大概可以猜出至少需要3個結(jié)點,才能劃分出四個分類。因此不妨就將隱層結(jié)點數(shù)定義成3或4。這里建議大家訓練模型的時候,根據(jù)先簡單后復雜的原則來調(diào)整網(wǎng)絡。因為一開始就訓練很復雜的網(wǎng)絡,不僅不一定得到很好的結(jié)果,而且訓練的時間太長,也不利于檢驗模型的質(zhì)量。
第三步就是訓練模型,不停改進模型,直至得到較滿意的精度。
下面給出訓練代碼:
import tensorflow as tf
import numpy as np
?
#設置訓練集大小
train_set_size=1000
#隨機生成身高數(shù)據(jù),以男性1.7m為平均身高,上下浮動0.2m
height=tf.Variable(tf.random.truncated_normal([train_set_size,1],mean=1.7,dtype=tf.double,stddev=0.1))
#隨機生成體重數(shù)據(jù),以體重60kg為平均值,上下浮動20kg
weight=tf.Variable(tf.random.truncated_normal([train_set_size,1],mean=60,dtype=tf.double,stddev=20))
#歸并數(shù)據(jù)
x=tf.concat([height,weight],1)
?
# 計算BMI指數(shù)
def getBMI(x):
return x[1] / (x[0] ** 2)
?
# 根據(jù)BMI指數(shù)自動生成標簽
def getLable(x):
label = np.zeros(shape=[train_set_size,4],dtype=float)
for i in range(len(x)):
bmi = getBMI(x[i])
if bmi < 20:
label[i][0] = 1
elif bmi >=?20 and bmi < 25:
label[i][1] = 1
elif bmi >=?25 and bmi < 28:
label[i][2] = 1
else:
label[i][3] = 1
?
return label
?
# 將標簽數(shù)據(jù)轉(zhuǎn)換成tensorflow框架能處理的張量
y_=tf.convert_to_tensor(getLable(x))
?
# ?設計兩層神經(jīng)網(wǎng)絡,第一層隱含層共4個結(jié)點,激活函數(shù)為RELU;第二層為輸出層也包含4個結(jié)點,對應4個分類,激活函數(shù)為softmax
model = tf.keras.models.Sequential([
??tf.keras.layers.Dense(4, activation='relu',input_shape=[2]),
??tf.keras.layers.Dense(4,activation='softmax')
])
?
# ?定義優(yōu)化器,用于優(yōu)化學習率等超參數(shù)指標
optimizer = tf.keras.optimizers.Adadelta(lr=1.0, rho=0.95, epsilon=1e-06)
?
# ?編譯模型,loss='categorical_crossentropy'指定損失函數(shù)為交叉熵,Metrics標注網(wǎng)絡評價指標accuracy為準確率
model.compile(loss='categorical_crossentropy',
????????????????optimizer=optimizer,
????????????????metrics=['accuracy'])
?
# ?打印網(wǎng)絡參數(shù)模型,僅用于自檢
model.summary()
?
# ?重復訓練3000次
for i in range(3000):
# ?輸入樣本x和標簽y, batch_size=1,每輸入1條數(shù)據(jù),就運行反向傳播算法,更新網(wǎng)絡參數(shù)。
model.fit(x=x,y=y_,batch_size=1)
?
# ?準備測試集
test_size=3
h_t=tf.Variable(tf.random.truncated_normal([test_size,1],mean=1.7,dtype=tf.double,stddev=0.1))
w_t=tf.Variable(tf.random.truncated_normal([test_size,1],mean=60,dtype=tf.double,stddev=20))
x_t=tf.concat([h_t,w_t],1)
?
# ?打印測試集內(nèi)容和模型預測的結(jié)果
print(x_t)
print(model.predict(x_t))
?
下面是訓練結(jié)果:
1000/1000 [==============================] - 0s 455us/step - loss: 0.1065 - accuracy: 0.9580
1000/1000 [==============================] - 0s 449us/step - loss: 0.0986 - accuracy: 0.9550
1000/1000 [==============================] - 0s 447us/step - loss: 0.1108 - accuracy: 0.9560
1000/1000 [==============================] - 0s 449us/step - loss: 0.1104 - accuracy: 0.9570
1000/1000 [==============================] - 0s 452us/step - loss: 0.0977 - accuracy: 0.9570
tf.Tensor(
[[ 1.87404843 51.79656559]
?[ 1.69247713 54.36136267]
?[ 1.80369327 53.8165295 ]], shape=(3, 2), dtype=float64)
[[1.0000000e+00 7.5280788e-35 0.0000000e+00 0.0000000e+00]
?[9.9999952e-01 5.1134185e-07 7.3078410e-31 0.0000000e+00]
?[1.0000000e+00 3.5876334e-22 0.0000000e+00 0.0000000e+00]]
?
連續(xù)訓練3000次以上,準確率穩(wěn)定在95%以上,證明算法是有效可靠的。而且從預測方面的能力看,效果還是挺不錯的。從結(jié)果來看,一切都挺有趣的。但這個模型沒有什么實際意義。正如前文所言,如果可以用普通的邏輯判斷語句就可以實現(xiàn)分類,那根本就沒有神經(jīng)網(wǎng)絡什么事。神經(jīng)網(wǎng)絡的分類能力主要還是用于數(shù)據(jù)挖掘上面,在海量數(shù)據(jù)中挖掘出人們還沒或者不可能發(fā)現(xiàn)潛在的聯(lián)系。
小結(jié)(內(nèi)含干貨,請認真閱讀)
對于一些普通的業(yè)務需求而言,用神經(jīng)網(wǎng)絡來分類真的是脫褲子放屁---多此一舉嗎?在我看來,并不一定!!!
首先,從宏觀的角度來看,用神經(jīng)網(wǎng)絡進行分類,起碼是一種思維定式上的轉(zhuǎn)變。過去我們認為,只有給電腦制定特定的運行邏輯(這個過程就是所謂的編程),電腦才能按照我們的想法工作。有了神經(jīng)網(wǎng)絡后,這個定式就打破了。實際上我們并不需要給電腦這么多條條框框,制定那么多那么細的規(guī)則。只要我們告訴電腦什么是對的,什么是錯的?電腦自己就會去學習?這時候電腦是不是越來越有點人類的味道?沒錯,很多時候,我們作為成人,作為家長,對于小孩的教育,往往都是先從告訴他什么是對的,什么是錯的開始。如果我們把一大段復雜冗長的邏輯,壓縮成足夠多的事例,是不是就等于把邏輯內(nèi)嵌到神經(jīng)網(wǎng)絡的模型參數(shù)里面呢?上面的例子,就是一個很好的示范案例。它把求BMI,然后根據(jù)BMI指數(shù)來劃分人的體重情況這一大段邏輯,壓縮成了 (2 * 4 + 4)+ (4 * 4 + 4)=32 個參數(shù),按每個參數(shù)以64位浮點型來存儲,一共才浪費了32 * (64 / 8)= 256個字節(jié)。比原來的代碼(凈代碼不含注釋約占354個字節(jié))節(jié)省了98個字節(jié)。
壓縮代碼容量好像沒有什么了不起的。而且還以犧牲準確率為代價(準確率下降了4%)。神經(jīng)網(wǎng)絡看起來好像還是個廢物點心呀!但請記住,“神經(jīng)網(wǎng)絡在某些分類問題上沒用”這句話,是針對有編程基礎的人而言。而且就算是有足夠編程基礎的大神,也不能保證所寫的代碼完全沒有bug。一旦代碼有bug,準確率就是一個未知之數(shù)了。所以再牛X的大牛,也還要寫單元測試,要借助測試用例來檢驗自己的代碼有沒有bug。但問題是,有時候,大牛自己寫的單元測試和生成的測試用例也是可能有bug的。。。。。從上面的分析可以看出,bug這種東西從人們學會編程的那一刻就已經(jīng)是根深蒂固的存在了。那用神經(jīng)網(wǎng)絡訓練的邏輯就沒Bug了嗎?有,肯定有。但就算有,也有解決辦法讓bug的出現(xiàn)概率限制在特定的誤差范圍內(nèi)。
其次,神經(jīng)網(wǎng)絡將人工智能輔助編程變成一種可能。前面已經(jīng)介紹過,一個多分支邏輯判斷語句可以等價為一個n分類神經(jīng)網(wǎng)絡。其中一個條件分支就對應著一個分類。因此,可以將用一般的高級程序語言寫的邏輯判斷語句,直接轉(zhuǎn)化成一個(或一組)神經(jīng)網(wǎng)絡。眾所周知,神經(jīng)網(wǎng)絡有較好的魯棒性(Robust),它僅與問題規(guī)模有關(guān),而與問題所涉及具體的業(yè)務場景無關(guān)。因此用神經(jīng)網(wǎng)絡構(gòu)建人工智能編程環(huán)境,能適應所有現(xiàn)階段已知的業(yè)務類型。之前的示例很好的說明了這一點,不管我們是建立體重的BMI測量模型,還是建立工資收入與消費支出的統(tǒng)計學模型,神經(jīng)網(wǎng)絡都能輕松駕馭。
第三,人工智能輔助編程將極大地提升軟件有效生產(chǎn)率。估計看到這里,不少碼農(nóng)朋友可能又要聽到“狼來了”的聲音。如果計算機自己都會編程了,那碼農(nóng)們是不是要集體失業(yè)了。不!正好相反,神經(jīng)網(wǎng)絡只是”輔助”人類編程,而不是去搶奪我們的主動權(quán)。首先,計算機沒有自主意識,它不知道在什么時候干什么才是有意義的。其次,計算機能控制的范圍都盡在人類的掌控之中。現(xiàn)今的所有計算機理論都是建立在嚴密的數(shù)學理論上面,也就是說,所有未來可能出現(xiàn)的情況,都可以在那一堆復雜的數(shù)學公式中找到答案。
人工智能輔助編程其實是廣大碼農(nóng)的福音!自此之后,大家不用再花時間去996,寫那枯燥乏味的業(yè)務代碼。人們只需要按照業(yè)務需求場景,搭建好網(wǎng)絡模型,然后把業(yè)務數(shù)據(jù)準備好,輸入到神經(jīng)網(wǎng)絡中,最后就可以靜待神經(jīng)網(wǎng)絡返回正確的結(jié)果。相信不久的將來,碼農(nóng)們已經(jīng)可以擺脫代碼的束縛,不再僅將關(guān)注點放在如何實現(xiàn)這件事上面,而更多的會從如何做好這件事去思考(這已經(jīng)是產(chǎn)品思維了)
最后,人工智能輔助編程將進一步降低人們學習計算機編程的門檻。以后所有現(xiàn)在所謂的高級程序語言(如Java,C++,Ruby)可能都將成為歷史。未來的編程語言隨著NLP (自然語言理解)和人工智能輔助編程的持續(xù)發(fā)展,將會逐步演化為一門更貼近人類母語語法,更簡練直觀的語言。將來編程將不再是一門只有少數(shù)人掌握的技能,而是一項像喝水吃飯一樣簡單的本能。
總結(jié)
以上是生活随笔為你收集整理的神经网络基础原理(三)-----分类问题实弹演练及一些小干货的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: element-ui表格表头内容 限制不
- 下一篇: Heiro试用失败记