最近在嗶哩嗶哩刷到一位up主,僅用了10行代碼就實現了機器學習,真讓我歎爲觀止。看視頻戳這裏python
如下是個人學習總結。bash
小強會去看電影嗎?網絡
如花,小倩,小明和小強,他們是好基友,常常相約去看電影。但小強不是每次都去,如下是他們前四次相約去看電影的狀況:(1 表示去看電影,0 表示沒去看電影)dom
如花 | 小倩 | 小明 | 小強 |
---|---|---|---|
1 | 0 | 1 | 1 |
1 | 1 | 0 | 1 |
0 | 0 | 1 | 0 |
0 | 1 | 0 | 0 |
假如第五次相約看電影,如花不去,小倩和小明要去,那麼小強會去嗎?機器學習
如花 | 小倩 | 小明 | 小強 |
---|---|---|---|
1 | 0 | 1 | 1 |
1 | 1 | 0 | 1 |
0 | 0 | 1 | 0 |
0 | 1 | 0 | 0 |
0 | 1 | 1 | ? |
咱們人腦對以上數據進行分析,很容易看出,如花去,小強就去,如花不去,小強就不去,很明顯小強對如花有意思,因此得出結論,小強不去。ide
人腦思考分析的過程,怎麼轉換成讓計算機思考呢?函數
from numpy import array, exp, random, dot
X = array([[1,0,1],[1,1,0],[0,0,1],[0,1,0]])
y = array([[1,1,0,0]]).T
random.seed(1)
weights = 2 * random.random((3,1)) - 1
for _ in range(10000):
output = 1/(1+exp(-dot(X, weights)))
error = y - output
delta = error * output * (1-output)
weights += dot(X.T, delta)
p = 1/(1+exp(-dot([[1,0,0]], weights)))[0][0]
print("小強去不去:", "不去" if p > 0.5 else "去")
複製代碼
不算用於打印的代碼,恰好10行。若是不多用Python進行科學計算的同窗可能會有點矇蔽,不要着急,下面我對每行代碼進行解釋。學習
from numpy import array, exp, random, dot
複製代碼
numpy 能夠說是 Python 科學計算的基石,用起來很是方便。 對於數學計算方便,咱們主要導入了 array、exp、random、dot優化
X = array([
[1,0,1],[1,1,0],[0,0,1],[0,1,0]
])
y = array([[1,1,0,0]]).T
複製代碼
將上表四人相約看電影的數據生成代碼,注意第二行有個 .T
是轉置的意思,將行向量轉成列向量,以下:spa
[ [
[1,0,1], [1],
[1,1,0], [1],
[0,0,1], [0],
[0,1,0], [0],
] ]
複製代碼
# 設置隨機因子,讓每次生成的隨機數都同樣,方便代碼調試。
random.seed(1)
# 生成一個範圍爲 -1 ~ 1,3列的行向量。
weights = 2 * random.random((3,1))-1
複製代碼
爲何要設置權重?
以第一次看電影爲例,[1,0,1] 對應 [1],他們之間存在某種關聯,以下:
1*w1 + 0*w2 + 1*w3 = 1
複製代碼
w1
,w2
,w3
,表示的就是權重。
若是咱們能求出w1
,w2
,w3
,是否是就能夠把第五次([0,1,1])的代入,獲得小強去不去看電影。
0*w1 + 1*w2 + 1*w3 = 小強去嗎?
複製代碼
怎麼求出權重?
咱們把第一條數據求出的權重,很難代入後面三條數據。
因此咱們隨機一組權重,代入每一組數據,獲得偏差,再修改權重,獲得新的偏差,如此反覆,直至偏差最小化,咱們就把這個過程叫作機器學習
for _ in range(10000):
# 用 sigmoid函數將計算結果進行轉換
output = 1/(1+exp(-dot(X, weights)))
# 用真實值減去計算結果求出偏差
error = y - output
# 計算增量
delta = error * output*(1-output)
# 獲得新的權重
weights += dot(X.T, delta)
複製代碼
循環往復 10000 次,讓偏差不斷變小,最終獲得最優的權重,將權重代入第五次的數據就能夠推算出小強去不去看電影了。
爲何要用 sigmoid 函數?
因爲計算結果的範圍是正無窮到負無窮,用 sigmoid 函數轉換成 0~1,方便進行分類,好比大於0.5 去看電影,小於0.5 不去看電影。
怎麼計算增量?
delta = error * output*(1-output)
複製代碼
將上面這句分拆成兩句代碼好理解一些:
# 計算斜率,也就是對計算結果進行求導
slope = output*(1-output)
# 基於 error 計算出 delta,用於更新權重
delta = error * slope
複製代碼
斜率是什麼?
因爲計算結果被 sigmoid 函數轉換後爲0~1的平滑曲線。 要想 error 越小,計算結果就要無線趨近於0或1,越趨近於0或者1斜率越小
爲何要用讓 error 乘以斜率?
在梯度降低法中,越靠近最優勢,斜率越小,因此在斜率最小的地方,咱們要減少 delta 的變化,以避免錯過最優勢。
p = 1/(1+exp(-dot([[1,0,0]], weights)))[0][0]
print("小強去不去:", "不去" if p > 0.5 else "去")
// => 不去
複製代碼
將通過10000次優化後的權重代入[1,0,0],計算出 p
爲 0.9999253713868242
,大於 0.5 且無限接近於1,因此小明會去看電影。
以上是這10行代碼所有解讀。
這10行代碼爲了最小化所需專業知識,沒有考慮局部最優,沒有考慮計算結果收斂等問題,因此代碼不夠嚴謹,但足夠體現機器學習的整個運行機制。
經過這10行代碼,能夠體會到機器是如何模擬人類學習的——即經過不斷試錯,不斷改正,最終獲得正解。
最後很是感謝視頻做者,視頻作的真好,讓晦澀的內容變得如此通俗易懂。強烈推薦各位看一看。大話神經網絡,10行代碼不調包,聽不懂你打我!