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