在手撕機器學習系列文章的上一篇刽辙,我們詳細講解了線性回歸的問題玛追,并且最后通過梯度下降算法擬合了一條直線,從而使得這條直線盡可能的切合數據樣本集俱萍,已到達模型損失值最小的目的端壳。
在本篇文章中,我們主要是手撕Logistic回歸鼠次,這個在李航老師的《統(tǒng)計學習方法》一書中也叫做為邏輯斯諦回歸更哄。聽到回歸一詞芋齿,有的讀者可能會想,上一篇線性回歸求解的是擬合問題成翩,這篇文章手撕的是Logistic回歸觅捆,會不會也是一個擬合問題?只不過使用到的算法原理不同而已麻敌,而求解的問題是一致的栅炒??术羔?
其實不然赢赊,Logistic回歸模型是一種廣義的線性回歸模型,主要是針對的是分類問題级历。只不過這個分類模型與上一章中的擬合模型有一些相似之處释移,或者我們可以這樣說,如果你明白了上篇文章中所講解的線性回歸寥殖,那么這篇文章中所涉及到的Logistic回歸的內容玩讳,你將會學的很輕松。這也是為什么Taoye首先肝線性回歸的原因嚼贡。
手撕機器學習系列目前已經更新了八篇熏纯,讀者可自行根據需要“充電”(持續(xù)更新中):
- 《Machine Learning in Action》—— 剖析支持向量機,單手狂撕線性SVM: https://www.zybuluo.com/tianxingjian/note/1755051
- 《Machine Learning in Action》—— 剖析支持向量機粤策,優(yōu)化SMO: https://www.zybuluo.com/tianxingjian/note/1756832
- 《Machine Learning in Action》—— 懂的都懂樟澜,不懂的也能懂。非線性支持向量機: https://www.zybuluo.com/tianxingjian/note/1758624
- 《Machine Learning in Action》—— Taoye給你講講決策樹到底是支什么“鬼”: https://www.zybuluo.com/tianxingjian/note/1757662
- 《Machine Learning in Action》—— 小朋友叮盘,快來玩啊秩贰,決策樹呦: https://www.zybuluo.com/tianxingjian/note/1758236
- 《Machine Learning in Action》—— 女同學問Taoye,KNN應該怎么玩才能通關: https://www.zybuluo.com/tianxingjian/note/1759263
- 《Machine Learning in Action》—— 白話貝葉斯熊户,“恰瓜群眾”應該恰好瓜還是恰壞瓜: https://www.zybuluo.com/tianxingjian/note/1758540
- 《Machine Learning in Action》—— 淺談線性回歸的那些事: https://www.zybuluo.com/tianxingjian/note/1761762
- 《Machine Learning in Action》—— Taoye給你講講Logistic回歸是咋回事: https://www.zybuluo.com/tianxingjian/note/1761888
本文主要包括以下兩個部分的內容:
- 和Logistic回歸交個朋友萍膛,互相認識一下吧(原理剖析,公式推導)
- 基于Logistic回歸手撕解決二分類問題
一嚷堡、和Logistic回歸交個朋友蝗罗,互相認識一下吧(原理剖析)
關于機器學習中的分類算法,我們前面已經肝了不少蝌戒。而Logistic回歸是同樣也是分類算法中的一員串塑,一般用于二分類問題,比如患者是否患有胃癌北苟、明天是否會下雨等等桩匪。當然了,對于多分類問題友鼻,Logistic回歸也是有應對之法的傻昙,畢竟你有張良計闺骚,我也有過墻體嘛。本文主要是以二分類問題為例妆档,來剖析Logistic回歸中的那些小秘密僻爽。
假設現在有一些樣本數據點,每個樣本包括兩個屬性贾惦,我們可以利用一條直線來對其進行擬合胸梆,這個擬合的過程就叫做回歸,擬合效果如下所示:
這個也是我們在上一篇文章中所詳細講到的內容须板,具體可見:《Machine Learning in Action》—— 淺談線性回歸的那些事: https://www.zybuluo.com/tianxingjian/note/1761762
而Logistic回歸是一種分類算法碰镜,它分類的核心思想是建立在線性回歸基礎之上的,并且對其進行了拓展习瑰,主要利用到了Sigmoid函數閾值在[0,1]這么一個特性绪颖,而這個特性則正好符合概率所在區(qū)間。所以說杰刽,Logistic回歸的本質就是一個基于條件概率的判別模型(在已知樣本屬性特征的前提下菠发,判斷其屬于哪一類別)王滤。
現在就讓我們來和Logistic回歸互相認識一下吧贺嫂,看看能不能挖出它的一些小秘密,一睹廬山真面目雁乡。
不知道各位看官還記不記得之前在講解SVM的時候第喳,我們是通過一種間隔最大化的形式來找出最佳的決策面,以此來對數據集進行分類踱稍。
而在Logistic回歸看來曲饱,每一個樣本的類別標簽都對應著一個概率,哪個類別標簽的概率大珠月,那么我就將樣本歸于哪一類扩淀。我們不妨假設單個樣本有個屬性特征,我們可以把它看做一個向量形式啤挎,且每個樣本對應的標簽情況只可能有兩類驻谆,即:
也就是說,我們現在的目的就是找到一個超平面庆聘,在超平面的一側為一個類別樣本胜臊,在另一側為另一類樣本。且每個樣本只可能存在兩種情況伙判,非0即1象对。對此,我們不妨假設在已知樣本屬性特征和模型參數的前提下宴抚,令該樣本標簽類別為1的概率為
勒魔,因為只可能存在兩個類別甫煞,所以樣本標簽為0的概率為
,即:
對于上式冠绢,它表示的意思是在已知樣本屬性特征x和模型參數的前提下危虱,該樣本標簽為1和0的概率分別為
和
。根據我們自己意愿唐全,我們當然是希望這兩者相差越大越好咯埃跷,這樣得到的分類結果才更具有說服力。
比如說對于一個樣本來講邮利,該樣本標簽為0的概率為0.9弥雹,為1的概率則等于0.1,我們當然是更加情愿將這個樣本歸于0那一類別延届,而且這樣的分類結果比較容易服眾剪勿。那假設該樣本標簽為0的概率為0.51,為1的概率為0.49方庭,那么這個時候你愿意將這個樣本歸于哪一類呢厕吉??械念?是不是很難做出抉擇头朱??龄减?是不是相當的糾結项钮??希停?因為這樣得出的分類概率結果和我們盲猜的概率也相差不多烁巫,完全達不到一個服眾的目的。
對此宠能,我們更加希望是這樣的:標簽的分類概率相差越大越好亚隙,這樣我們對樣本的分類結果更加具有說服力。
上述兩個概率其實就是兩種情況违崇,且其樣本標簽為非0即1阿弃,根據這個特性,為了方便我們表示分類的概率情況亦歉,可以將上述兩個概率值合二為一恤浪,得到如下:
上述這種將二者合二為一的處理方式,曾經在SVM那篇文章中也是有謀面過的肴楷,如有遺忘水由,讀者可暫且跳轉進行復習:《Machine Learning in Action》—— 剖析支持向量機,單手狂撕線性SVM: https://www.zybuluo.com/tianxingjian/note/1755051
合并出來的上式赛蔫,當y等于1時砂客,(1-y)項(第二項)為0泥张;當y等于0時,y項(第一項)為0鞠值。也就是說媚创,我們現在的目的就是根據訓練樣本集,使得上式的值最大化彤恶,這樣我們對樣本集分類的準確性就越高钞钙。
此外,上述單個樣本所表示的概率值声离,而我們知道芒炼,樣本集是由大量的單個樣本所組成的一個集合,所以此時我們的極大似然法就該出場了术徊,假設樣本與樣本之間是相互獨立的本刽,那么其似然函數為(假定有n個樣本):
此時,我們的目的就是要根據數據樣本集赠涮,來求解上述似然函數的最大值子寓。求最值問題,我們自然會使用到求解導函數笋除,而對于上述的乘積形式斜友,我們直接求導并不簡單,而且還會大大提高求解的效率和復雜度株憾。對此我們需要對其進行對數化蝙寨,從而將乘積的形式轉化成求和的形似,這樣一來對于求導來講就比較的友好了嗤瞎。
假設我們對上述式子對數化之后,命名為听系,則其為我們最終的損失函數贝奇,或者說是待優(yōu)化的目標函數,具體形式如下:
寫到這里靠胜,我們算是得到了最終所需要求解的目標函數了掉瞳,現在就是需要將上述的損失函數值最大化,這樣才能使得最終分類的結果集的準確性更高浪漠。
注意一點:對于上述的損失函數陕习,讀者可能在這里有個疑問,按道理將應該是使得損失值最小化才對址愿,為什么會需要使得上式最大化呢该镣??响谓?其實是這樣的损合,上述的式子說是說損失函數省艳,其實它真正代表的意思是使得整個樣本集的分類正確率盡可能的提高暇咆。這一點若讀者還有疑問星著,可返回仔細想想該式子的推導過程,及其背后隱藏的真正含義茵肃。
這樣一來律适,對于上述的損失函數還有一個我們是不知道的辐烂。通過前面分析,我們也可以知道
表示的是一個概率捂贿,其值為0-1棉圈。然而,我們通過計算
眷蜓,可以發(fā)現該值的具體范圍是不確定的分瘾。為此,我們需要對該計算得到的值進行一定的處理吁系,將其轉化到0-1范圍之間德召,如此一來,才能符合概率的范圍特性汽纤。
那么上岗,該如何處理呢?蕴坪?肴掷?
聰明的研究人員就發(fā)現,有這么一個函數背传,無論該值的有多大呆瞻,或者有多小,都能將其映射到0-1之間径玖。這個函數就是大名鼎鼎的Sigmoid函數痴脾,其具體形式和圖像如下所示:
通過Sigmoid函數的表達式和具體圖像,我們也可以發(fā)現梳星,其正好滿足我們的實際需求赞赖。另外,Sigmoid函數在今后的學習過程中還會經常見到的冤灾,比如在卷積神經網絡中前域,就經常會使用Sigmoid函數來作為我們的激活函數,以解決非線性問題韵吨。
如此一來匿垄,我們通過Sigmoid函數來處理樣本,得到如下結果:
了解了具體表達之后,我們就能對損失函數進行進一步的處理變換年堆,處理過程如下:
將損失函數處理成如上式子之后吞杭,我們可以發(fā)現在整個訓練數據樣本集中,都是已知的变丧,唯一不確定的就是
芽狗,其是一個與單個樣本屬性特征相對應的向量形式。我們對
進行求導之后可以得到如下結果:
由此痒蓬,我們計算得到損失函數關于的梯度之后童擎,就可以通過梯度上升算法來不斷更新迭代
參數,從而使得損失函數的值最大化攻晒,即使得訓練樣本集分類的正確性盡可能高顾复。
另外,我們知道參數其實是一個向量的形式鲁捏,其與
的屬性特征是相對應的芯砸,對此我們對
進行更新的時候,是對其內部的每一個元素同時更新给梅。根據上述的求導結果假丧,我們得到每個元素的具體更新如下:
注意,在這里我們是假設每個元素有個屬性特征的动羽,即
包帚,這一點在前面也是有提到。其中
表示的是更新迭代之前的
值运吓,而
表示的是更新迭代之后的
值渴邦,而
表示的是一個學習率,也代表著學習的快慢拘哨,這個在之前講解線性回歸的時候也是有詳細講到的谋梭。
二、基于Logistic回歸手撕解決二分類問題
得到Logistic回歸模型之后宅静,我們就能根據來不斷更新迭代得到
章蚣,最終使得損失函數值最大化。
接下來姨夹,我們嘗試著通過Python代碼來實現Logistic回歸分類,本次主要針對于二分類矾策。數據集依然通過NumPy隨機生成磷账,定義一個establish_data
方法隨機生成數據集的代碼如下:
"""
Author: Taoye
微信公眾號: 玩世不恭的Coder
Explain: 通過NumPy準備數據集
Return:
x_data:樣本的屬性特征
y_label:樣本屬性特征所對應的標簽
"""
def establish_data():
# np.random.seed(1) # 可根據需要是否選擇隨機種子
x_data = np.concatenate((np.add(np.random.randn(50, 2), [1.5, 1.5]),
np.subtract(np.random.randn(50, 2), [1.5, 1.5])),
axis = 0) # random隨機生成數據,+ -1.5達到不同類別數據分隔的目的
y_label = np.concatenate((np.zeros([50]), np.ones([50])), axis = 0) # concatenate合并數據集
return x_data. y_label
可視化數據之后的分布如下:
從上圖我們可以看出數據的大致分布情況贾虽,并且能夠通過一條直線將兩類數據分割開來逃糟。在這里,我們假設Sigmoid函數的輸入記為,那么
绰咽,即可將數據分割開菇肃。其中,為了體現出直線的截距取募,我們將
當作是數值為1的固定值琐谤,
為數據集的第一個屬性特征,
為數據集的第二個屬性特征玩敏。另z=0斗忌,則得到該直線的一般表達式
。
對于這個方程旺聚,我們已知的是樣本數據织阳,也就是橫坐標為,縱坐標為
砰粹,表示樣本的兩個屬性唧躲。而未知的參數為
弄痹,也就是我們需要求的回歸系數(最優(yōu)參數),也正是需要通過梯度上升算法訓練的模型參數厘贼。
在開始訓練模型參數之前界酒,我們把迭代更新的式子再次搬出來看看:
即:
我們知道,對于求和的式子我們可以將其轉換成矩陣或向量 的形式來表示嘴秸,這也是矢量化的一種操作毁欣,比如可以轉化成
。因此岳掐,對于上式凭疮,我們同樣可以對其進行矢量化,得到如下結果:
這里對上式再解釋一下串述,比如說我們有100個數據樣本执解,每個樣本含有2個屬性,那么此時的x代表整個樣本集纲酗,其衰腌,所以
,而
觅赊,所以兩者相乘之后得到的shape是
右蕊,正好與所需要的
向量的維數一致。
根據上述矢量化之后的結果吮螺,我們定義一個gradient_ascent
方法來通過代碼實現這個功能饶囚。
"""
Author: Taoye
微信公眾號: 玩世不恭的Coder
Explain: Sigmoid函數
Parameters:
in_data: sigmoid處理的輸入數據
Return:
sigmoid_result:sigmoid函數處理之后的結果
"""
def sigmoid(in_data):
return 1 / (1 + np.exp(-in_data))
"""
Author: Taoye
微信公眾號: 玩世不恭的Coder
Explain: Logistic回歸的核心方法帕翻,主要使用到了梯度上升算法
Parameters:
x_data:樣本集的屬性特征
y_label:樣本集的標簽
Return:
weights: 模型訓練完成之后的w參數
"""
def gradient_ascent(x_data, y_label):
x_data, y_label = np.mat(x_data), np.mat(y_label).T # 轉換成矩陣形式,方便操作
data_number, attr_number = x_data.shape # 獲取樣本數量以及屬性特征的數量
learning_rate, max_iters, weights = 0.001, 500, np.ones([attr_number, 1]) # 一些超參數和參數的初始化
loss_list = list()
for each_iter in range(max_iters): # 更新迭代max_iters次
sigmoid_result = sigmoid(np.matmul(x_data, weights)) # sigmoid處理 x*w
difference = y_label - sigmoid_result # 計算損失值
weights = weights + learning_rate * np.matmul(x_data.T, difference) # 更新權重w向量
loss = np.matmul(y_label.T, np.log(sigmoid_result)) + np.matmul((1 - y_label).T, np.log(1 - sigmoid_result))
loss_list.append(loss.tolist()[0][0])
return weights.getA(), loss_list
獲取到了模型的最終訓練的參數之后萝风,就可以對結果進行可視化了嘀掸,以便直觀感受下Logistic回歸的分類結果。為此规惰,定義一個show_result
方法來實現結果的可視化:
"""
Author: Taoye
微信公眾號: 玩世不恭的Coder
Explain: 可視化分類結果睬塌,也就是Logistic回歸的可視化
Parameters:
x_data:樣本集的屬性特征
y_label:樣本集的標簽
weights:模型所需要的參數,也就是權重
"""
def show_result(x_data, y_label, weights):
from matplotlib import pyplot as plt
w_1, w_2, w_3 = weights[0][0], weights[1][0], weights[2][0] # 獲取權重參數
min_x_1, min_x_2 = np.min(x_data, axis = 0)[:-1] # 獲取屬性特征的最小值
max_x_1, max_x_2 = np.max(x_data, axis = 0)[:-1] # 獲取屬性特征的最大值
line_x_1 = np.linspace(min_x_1 - 0.2, max_x_1 + 0.2, 1000) # 決策直線的橫坐標
line_x_2 = (-w_3 - w_1 * line_x_1) / w_2 # 決策直線的縱坐標
plt.scatter(x_data[:, 0], x_data[:, 1], c = y_label) # 繪制數據的散點圖
plt.plot(line_x_1, line_x_2) # 繪制分類的決策直線
可視化分類結果如下所示:
上圖主要包括倆個部分卿拴,一個是通過Logistic回歸分類的結果衫仑,另一個是每次迭代之后損失值的變換情況。
從可視化的結果來看堕花,這個分類效果相當不錯文狱,基本上所有的數據點都能夠被正確分類,讀者可根據需要來決定是否使用隨機種子缘挽,從而觀察不同數據集的分類效果瞄崇。
從第二張圖中,我們可以看出通過Logistic回歸進行訓練的過程中壕曼,損失函數的值是不斷增大苏研。而且我們還可以發(fā)現,其增大的斜率逐漸減小腮郊,尤其是在前面幾次迭代過程中摹蘑,這種現象尤為明顯。當損失函數值提高到一定程度之后轧飞,這個時候基本屬于飽和了衅鹿,也就是說分類的過程基本結束了。
上圖是損失函數的值的可視化結果过咬,我們也可以從其每次迭代之后的具體值來觀察這一變化趨勢:
總共500次迭代大渤,共輸出500次損失值,起初的損失值為300多掸绞,每次迭代之后的損失值逐漸增大泵三,且增大的速度在不斷減小,最終的損失值停留在3左右達到飽和衔掸。這就是梯度上升算法所體現出來的效果烫幕,也就是說我們的損失函數值越小,我們梯度上升法優(yōu)化的效果也就越明顯敞映。
完整代碼:
import numpy as np
"""
Author: Taoye
微信公眾號: 玩世不恭的Coder
Explain: 通過NumPy準備數據集
Return:
x_data:樣本的屬性特征
y_label:樣本屬性特征所對應的標簽
"""
def establish_data():
# np.random.seed(1)
x_data = np.concatenate((np.add(np.random.randn(50, 2), [1.5, 1.5]),
np.subtract(np.random.randn(50, 2), [1.5, 1.5])),
axis = 0) # random隨機生成數據纬霞,+ -1.5達到不同類別數據分隔的目的
x_data = np.concatenate((x_data, np.ones([100, 1])), axis = 1)
y_label = np.concatenate((np.zeros([50]), np.ones([50])), axis = 0) # concatenate合并數據集
return x_data, y_label
"""
Author: Taoye
微信公眾號: 玩世不恭的Coder
Explain: Sigmoid函數
Parameters:
in_data: sigmoid處理的輸入數據
Return:
sigmoid_result:sigmoid函數處理之后的結果
"""
def sigmoid(in_data):
return 1 / (1 + np.exp(-in_data))
"""
Author: Taoye
微信公眾號: 玩世不恭的Coder
Explain: Logistic回歸的核心方法,主要使用到了梯度上升算法
Parameters:
x_data:樣本集的屬性特征
y_label:樣本集的標簽
Return:
weights: 模型訓練完成之后的w參數
"""
def gradient_ascent(x_data, y_label):
x_data, y_label = np.mat(x_data), np.mat(y_label).T # 轉換成矩陣形式驱显,方便操作
data_number, attr_number = x_data.shape # 獲取樣本數量以及屬性特征的數量
learning_rate, max_iters, weights = 0.001, 500, np.ones([attr_number, 1]) # 一些超參數和參數的初始化
loss_list = list()
for each_iter in range(max_iters): # 更新迭代max_iters次
sigmoid_result = sigmoid(np.matmul(x_data, weights)) # sigmoid處理 x*w
difference = y_label - sigmoid_result # 計算損失值
weights = weights + learning_rate * np.matmul(x_data.T, difference) # 更新權重w向量
loss = np.matmul(y_label.T, np.log(sigmoid_result)) + np.matmul((1 - y_label).T, np.log(1 - sigmoid_result))
loss_list.append(loss.tolist()[0][0])
return weights.getA(), loss_list
"""
Author: Taoye
微信公眾號: 玩世不恭的Coder
Explain: 可視化分類結果,也就是Logistic回歸的可視化
Parameters:
x_data:樣本集的屬性特征
y_label:樣本集的標簽
weights:模型所需要的參數,也就是權重
"""
def show_result(x_data, y_label, weights):
from matplotlib import pyplot as plt
w_1, w_2, w_3 = weights[0][0], weights[1][0], weights[2][0] # 獲取權重參數
min_x_1, min_x_2 = np.min(x_data, axis = 0)[:-1] # 獲取屬性特征的最小值
max_x_1, max_x_2 = np.max(x_data, axis = 0)[:-1] # 獲取屬性特征的最大值
line_x_1 = np.linspace(min_x_1 - 0.2, max_x_1 + 0.2, 1000) # 決策直線的橫坐標
line_x_2 = (-w_3 - w_1 * line_x_1) / w_2 # 決策直線的縱坐標
plt.scatter(x_data[:, 0], x_data[:, 1], c = y_label) # 繪制數據的散點圖
plt.plot(line_x_1, line_x_2) # 繪制分類的決策直線
if __name__ == "__main__":
x_data, y_label = establish_data()
weights, loss_list = gradient_ascent(x_data, y_label)
show_result(x_data, y_label, weights)
# from matplotlib import pyplot as plt
# plt.plot(np.arange(len(loss_result)), loss_list)
以上就是本篇文章中Logistic回歸的全部內容了埃疫,我們在來總結一下Logistic回歸實現的過程:
首先是通過分析推導伏恐,得到Logistic回歸的損失函數(使用到了極大似然法):
其次,為了將和
內積之后的結果映射到0-1范圍之內栓霜,以體現出概率的特性翠桦,我們引入了Sigmoid函數對內積結果進行處理:
引入了Sigmoid函數之后,將損失函數化簡得到:
最后胳蛮,因為我們需要不斷地對參數通過梯度上升算法進行更新迭代销凑,所以我們需要對
進行求導,求導結果如下:
如此一來仅炊,我們就能通過該梯度值對參數一步步的優(yōu)化斗幼,優(yōu)化方法主要是通過梯度上升算法:
即對向量內部的每個元素進行更新:
當迭代次數達到一定程度時,最終更新迭代得到的向量就是我們得到的參數結果抚垄,根據該參數就能構造一個模型將數據集分割開來蜕窿,從而實現了數據的分類。
Logistic回歸主要運用的是梯度上升算法呆馁,在上面案例實戰(zhàn)的過程中桐经,我們的隨機生成的樣本數據集不是特別的多,所以訓練的速度還挺快浙滤。但是假定我們的訓練樣本數量比較多阴挣,這個時候的訓練效率就比較的低下了。這個時候可能就需要對梯度上升算法進行一定的優(yōu)化了纺腊,而該部分優(yōu)化常用的方式是使用隨機梯度上升算法畔咧,限于篇幅和時間原因,我們后面有機會再來肝摹菠。
這是手撕機器學習系列文章的第九篇了盒卸,也差不多接近尾聲了,初步計劃這周完成吧次氨,因為后面還有很多任務到現在還沒有開始蔽介,想到這,Taoye的眼角有不知覺地煮寡。虹蓄。。
當然了幸撕,吾生也有涯薇组,而知也無涯,以有涯隨無涯坐儿,殆已律胀。學習本身就是一個無止境的過程宋光,目前所講到的機器學習算法以及所涉及到的知識也只是該領域的冰山一角,我們最重要的是要保持一顆不斷積極進取的心炭菌。
我是Taoye罪佳,愛專研,愛分享黑低,熱衷于各種技術赘艳,學習之余喜歡下象棋、聽音樂克握、聊動漫蕾管,希望借此一畝三分地記錄自己的成長過程以及生活點滴,也希望能結實更多志同道合的圈內朋友菩暗,更多內容歡迎來訪微信公主號:玩世不恭的Coder掰曾。
我們下期再見,拜拜~~~
參考資料:
<font style="font-size:13px;opacity:0.7">[1] 《機器學習實戰(zhàn)》:Peter Harrington 人民郵電出版社</font>
<font style="font-size:13px;opacity:0.7">[2] 《統(tǒng)計學習方法》:李航 第二版 清華大學出版社</font>
推薦閱讀
《Machine Learning in Action》—— 淺談線性回歸的那些事
《Machine Learning in Action》—— 白話貝葉斯勋眯,“恰瓜群眾”應該恰好瓜還是恰壞瓜
《Machine Learning in Action》—— 女同學問Taoye婴梧,KNN應該怎么玩才能通關
《Machine Learning in Action》—— 懂的都懂,不懂的也能懂客蹋。非線性支持向量機
《Machine Learning in Action》—— hao朋友塞蹭,快來玩啊,決策樹呦
《Machine Learning in Action》—— Taoye給你講講決策樹到底是支什么“鬼”
《Machine Learning in Action》—— 剖析支持向量機讶坯,優(yōu)化SMO
《Machine Learning in Action》—— 剖析支持向量機番电,單手狂撕線性SVM
print( "Hello,NumPy辆琅!" )
干啥啥不行漱办,吃飯第一名
Taoye滲透到一家黑平臺總部,背后的真相細思極恐
《大話數據庫》-SQL語句執(zhí)行時婉烟,底層究竟做了什么小動作娩井?