Machine Learning in Python (Scikit-learn)-(No.1)
作者?:范淼?(人人網(wǎng))
1. 閑話篇
機(jī)器學(xué)習(xí)(ML),自然語言處理(NLP)惠窄,神馬的巷波,最近太火了碗殷。哥童。。不知道再過幾年哼凯,大家都玩兒ML欲间,還會不會繼續(xù)火下去。断部。括改。需要有人繼續(xù)再添點(diǎn)柴火才行。本人僅僅是一個迷途小書童家坎,知識有限嘱能,還望各位ML大神多多指點(diǎn):)。
最近想系統(tǒng)地收拾一下ML的現(xiàn)有工具虱疏,發(fā)現(xiàn)比較好的應(yīng)該是這個http://scikit-learn.org/stable/index.html惹骂。
對于初學(xué)和進(jìn)階階段的ML研究者們是個不錯的選擇。不過美中不足的是少了Large-scale ML的一些做瞪,畢竟這是單機(jī)的对粪。后面琢磨琢磨右冻,寫個ADMM(今年ICML劇多相關(guān)的論文)的吧,這個之前在MSRA的Learning Group做過一個Turtorial.
尤其是他的參考手冊著拭,更是沒有太多廢話纱扭,都能一針見血地講明重點(diǎn):http://scikit-learn.org/stable/user_guide.html
其實不要指望這個工具包能有啥新的東西,不過就是這些經(jīng)典的東西儡遮,要是你真掌握了乳蛾,也基本God Like!了鄙币。:)肃叶,特別是你用ML創(chuàng)業(yè)的時候,可能真能用上一兩個思路十嘿,也就是被訓(xùn)練出來的思想估計是大學(xué)能留下來的因惭,剩下的都在狗肚子里。
我們來大致瀏覽一下這個系統(tǒng)的ML工具的功能绩衷,整體內(nèi)容較多蹦魔,我們逐步更新,想具體了解哪個部分的童鞋可以留言咳燕,我一下子還真很難都詳細(xì)介紹(我會基本上保證一周更新一個小章節(jié)勿决,逐步學(xué)習(xí)。首先弄懂模型原理迟郎,講出來,然后使用對應(yīng)數(shù)據(jù)實戰(zhàn)一下聪蘸,貼出代碼宪肖,作圖,最后利用測試結(jié)果適當(dāng)比較一下模型之間的差異)健爬,所有的代碼控乾,我都會后續(xù)貼到CSDN或者Github上面。
---------------------------------------------------華麗麗的分割線---------------------------------------------------------
2. 配置篇
推薦學(xué)習(xí)配置:python 2.7, pycharm IDE (這個Python的IDE不錯娜遵,推薦大家用下蜕衡,如果用過Eclipse寫Java,這個上手會很快)设拟, numpy, scipy慨仿。其他還有一些需要下載的包,大家可以邊配置邊有問題留言纳胧,建議在windows下面弄弄就行镰吆,我基本不用Linux。
有些小伙伴建議我也詳細(xì)講講在windows下的配置跑慕。的確万皿,這一系列的配置還真心沒有那么簡單摧找,我特地找了一臺windows7 Ultimiate SP1 x64 的裸機(jī)來重現(xiàn)一下整體配置過程。
首先是Python 2.7 (切記Python 3.x 和2.x的版本完全不是一路貨牢硅,不存在3.x向下兼容的問題蹬耘,所以,如果哪位小伙伴為了追求軟件版本高而不小心安裝了python 3.x减余,我只能說综苔。。好吧佳励。休里。你被坑了。最簡單的理解赃承,你可以認(rèn)為這兩個Python版本壓根就不是一門相同的編程語言妙黍,就連print的語法都不同)
1. Python 2.7.x ?在 x64 windows平臺下的解釋器。具體下載地址:https://www.python.org/download/releases/2.7.8/注意64位的是這個Windows X86-64 MSI Installer(2.7.8)
測試這個Python是否在你的環(huán)境里配置好瞧剖,你可以在命令行里直接輸入python拭嫁,如果報錯,那么你需要手動配置一下環(huán)境抓于,這個大家上網(wǎng)搜就可以解決(簡單說做粤,在環(huán)境變量PATH里把你的Python的安裝文件夾路徑寫進(jìn)去)。
2. 然后安裝Pycharm捉撮,這個是我在Hulu實習(xí)的時候用到過的IDE怕品,還是濤哥推薦的,還不錯巾遭。因為有正版收費(fèi)的問題肉康,推薦大家下載它的(community)版http://www.jetbrains.com/pycharm/download/。安裝好后灼舍,它應(yīng)該會讓你選擇剛才安裝好的Python的解釋器吼和,這樣你就可以做一些簡單的python編程了,用過eclipse的人骑素,這個上手非踌排遥快。
3. 接著就需要配置跟sklearn有關(guān)的一系列Python的擴(kuò)展包了献丑。這個美國加州一個學(xué)校的一個非官方網(wǎng)站張貼了所有windows直接安裝的版本http://www.lfd.uci.edu/~gohlke/pythonlibs/末捣,特別實用,大家到里面去下載跟python 2.7 amd64有關(guān)的安裝包创橄。然后直接下載運(yùn)行即可塔粒。需要下載的一系列擴(kuò)展包的列表(按照依賴順序):Numpy-MKL, SciPy, Scikit-learn。有了這些就可以學(xué)習(xí)Scikit-learn這個工具包了筐摘。
4. 此外卒茬,如果想像我一樣船老,同時可以畫圖,那么就需要matplotlib圃酵,這個也有一個網(wǎng)站手冊http://matplotlib.org/contents.html柳畔,同樣也需要一系列擴(kuò)展包的支持。使用matplotlib 需要如下必備的庫郭赐,numpy,dateutil,pytz,pyparsing,six薪韩。都能從剛才我推薦的下載網(wǎng)站上獲取到。
上面的一系列都搞定了捌锭,大家可以使用我第一個線性回歸的代碼(加粗的代碼)測試一下俘陷,直接輸出圖像,最后還能保存成為png格式的圖片观谦。
------------------------------華麗麗的分割線------------------------------------------
3. 數(shù)據(jù)篇
用工具之前先介紹幾個我會用到的數(shù)據(jù)
這里大部分的數(shù)據(jù)都是從這個經(jīng)典的機(jī)器學(xué)習(xí)網(wǎng)站提供的:
https://archive.ics.uci.edu/ml/
sklearn.datasets里面集成了這個網(wǎng)站里的部分?jǐn)?shù)據(jù)(剛接觸Python的童鞋天吓,需要一點(diǎn)點(diǎn)Python的知識性含,和Java類似硼讽,使用現(xiàn)成工具模塊的時候鸳君,需要import一下,我們這個基于Python的機(jī)器學(xué)習(xí)工具包的全名是sklearn泻红,這里介紹數(shù)據(jù)夭禽,所以下一個目錄是datasets)。具體的Python代碼:
import sklearn.datasets
數(shù)據(jù)一:波士頓房價(適合做回歸)谊路,以后直接用boston標(biāo)記
這行代碼就讀進(jìn)來了
boston = sklearn.datasets.load_boston()
查詢具體數(shù)據(jù)說明讹躯,用這個代碼:
print boston.DESCR
輸出如下:
Data Set Characteristics:
:Number of Instances: 506
:Number of Attributes: 13 numeric/categorical predictive
:Median Value (attribute 14) is usually the target
:Attribute Information (in order):
- CRIM per capita crime rate by town
- ZN proportion of residential land zoned for lots over 25,000 sq.ft.
- INDUS proportion of non-retail business acres per town
- CHAS Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)
- NOX nitric oxides concentration (parts per 10 million)
- RM average number of rooms per dwelling
- AGE proportion of owner-occupied units built prior to 1940
- DIS weighted distances to five Boston employment centres
- RAD index of accessibility to radial highways
- TAX full-value property-tax rate per $10,000
- PTRATIO pupil-teacher ratio by town
- B 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town
- LSTAT % lower status of the population
- MEDV Median value of owner-occupied homes in $1000's
一共506組數(shù)據(jù),13維特征缠劝,
比如第一個維度的特征是犯罪率潮梯,第六個是每個房子平均多少房間等等。
boston.data 獲取這506 * 13的特征數(shù)據(jù)
boston.target 獲取對應(yīng)的506 * 1的對應(yīng)價格
數(shù)據(jù)二:牽攀1颍花(適合做簡單分類)酷麦,標(biāo)記為Iris
import sklearn.datasets
iris = sklearn.datasets.load_iris()
iris.data 獲取特征
iris.target 獲取對應(yīng)的類別
Data Set Characteristics:
:Number of Instances: 150 (50 in each of three classes)
:Number of Attributes: 4 numeric, predictive attributes and the class
:Attribute Information:
- sepal length in cm
- sepal width in cm
- petal length in cm
- petal width in cm
- class:
- Iris-Setosa
- Iris-Versicolour
- Iris-Virginica
這個數(shù)據(jù)基本是個ML的入門選手都知道矿卑,一共三類牽藕砹担花,獲取特征和對應(yīng)的類別標(biāo)簽也是同上
一共150樣本母廷,3類轻黑,特征維度為4
數(shù)據(jù)三: 糖尿病(回歸問題)琴昆,diabetes
這個數(shù)據(jù)包很奇怪氓鄙,沒有描述。我也到原本的UCI的網(wǎng)站上查了一下业舍,也是沒有太好的描述抖拦。
import sklearn.datasets
diabetes = sklearn.datasets.load_diabetes()
print diabetes.keys()
這樣的輸出只有data, targets升酣。
我也觀察了一下數(shù)據(jù),感覺是經(jīng)過額外的歸一化處理的态罪,原始的數(shù)據(jù)樣貌已經(jīng)看不出來了噩茄。。
下面這個圖是我從網(wǎng)站上Copy下來的有限的描述复颈,樣本量為442绩聘,特征維度為10,每個特征元素的值都是連續(xù)的實數(shù)耗啦,在正負(fù)0.2之間凿菩。。目標(biāo)這個整數(shù)值有可能是血糖帜讲。
Samples total442
Dimensionality10
Featuresreal, -.2 < x < .2
Targetsinteger 25 - 346
數(shù)據(jù)四:手寫數(shù)字識別(多類分類衅谷,10個類別,從0-9)digits
import sklearn.datasets
digits = sklearn.datasets.load_digits()
總體樣本量:1797舒帮,每個類別大約180個樣本会喝,每個手寫數(shù)字是一個8*8的圖片,每個像素是0-16的整數(shù)值玩郊。
綜上肢执,大家可以加載相應(yīng)的數(shù)據(jù)來玩,這幾個數(shù)據(jù)算是比較有代表性的译红。后面會介紹如何利用SKLEARN工具下載更大規(guī)模的數(shù)據(jù)预茄,比如MINIST的大規(guī)模的手寫數(shù)字識別庫等等。
總之侦厚,如果你想獲取特征耻陕,就在*.data里,對應(yīng)的類別或者回歸值在*.target里面
光說不練不行刨沦,我對每個介紹的方法都會選用上面的Dataset實際測試一下诗宣,并且會酌情給出結(jié)果和圖像。
------------------------------華麗麗的分割線------------------------------------------
4.實戰(zhàn)篇
這個監(jiān)督學(xué)習(xí)最常用想诅,分類啊召庞,預(yù)測回歸(預(yù)測個股票啥的,雖然在我大天朝不太適合)啊来破。
1.1. Generalized Linear Models
最通用的線性模型
把你的特征x和對應(yīng)的權(quán)重w相加篮灼,最后爭取接近你的目標(biāo)y,機(jī)器學(xué)的就是w徘禁。
這個模型應(yīng)用最廣诅诱,其實就是大家會權(quán)衡各種各樣的因素,最后給一個總評送朱。
1.1.1. Ordinary Least Squares最小二乘約束
目標(biāo)函數(shù)是這個
要總體的平方和最小干旁。
具體代碼大家import sklearn.linear_model,然后sklearn.linear_model.LinearRegression()就是這個模塊了炮沐。做個簡單的什么房價估計還行(別說預(yù)測疤孕,那個不準(zhǔn),只能說估計一下租房的價格央拖,隨便在搜房網(wǎng)上弄點(diǎn)兒數(shù)據(jù)祭阀,他那里有現(xiàn)成的特征,什么地理位置啊鲜戒,面積啊专控,朝向啊等等,最后你回歸一個大致房價玩玩)遏餐。
我們就使用波士頓的房價來預(yù)測一下(后面的所有python代碼注意縮進(jìn)伦腐!我是沒工夫一行一行調(diào)整了。失都。柏蘑。多包涵):
'''
Author: Miao Fan
Affiliation: Department of Computer Science and Technology, Tsinghua University, P.R.China.
Email: fanmiao.cslt.thu@gmail.com
'''
import sklearn.datasets
import sklearn.linear_model
import numpy.random
import numpy.linalg
import matplotlib.pyplot
if __name__ == "__main__":
# Load boston dataset
boston = sklearn.datasets.load_boston()
# Split the dataset with sampleRatio
sampleRatio = 0.5
n_samples = len(boston.target)
sampleBoundary = int(n_samples * sampleRatio)
# Shuffle the whole data
shuffleIdx = range(n_samples)
numpy.random.shuffle(shuffleIdx)
# Make the training data
train_features = boston.data[shuffleIdx[:sampleBoundary]]
train_targets = boston.target[shuffleIdx [:sampleBoundary]]
# Make the testing data
test_features = boston.data[shuffleIdx[sampleBoundary:]]
test_targets = boston.target[shuffleIdx[sampleBoundary:]]
# Train
linearRegression = sklearn.linear_model.LinearRegression()
linearRegression.fit(train_features, train_targets)
# Predict
predict_targets = linearRegression.predict(test_features)
# Evaluation
n_test_samples = len(test_targets)
X = range(n_test_samples)
error = numpy.linalg.norm(predict_targets - test_targets, ord = 1) / n_test_samples
print "Ordinary Least Squares (Boston) Error: %.2f" %(error)
# Draw
matplotlib.pyplot.plot(X, predict_targets, 'r--', label = 'Predict Price')
matplotlib.pyplot.plot(X, test_targets, 'g:', label='True Price')
legend = matplotlib.pyplot.legend()
matplotlib.pyplot.title("Ordinary Least Squares (Boston)")
matplotlib.pyplot.ylabel("Price")
matplotlib.pyplot.savefig("Ordinary Least Squares (Boston).png", format='png')
matplotlib.pyplot.show()
結(jié)果:
Ordinary Least Squares (Boston) Error:3.35〈馀樱基本上咳焚,平均每筆預(yù)測,都會距離真實的價格差3350美金庞溜,這個數(shù)值的單位是1000 U.S.D. (見數(shù)據(jù)描述)
下面這個圖就是預(yù)測和實際價格的對比圖線革半,這里是隨機(jī)采樣了50%作為訓(xùn)練,50%做預(yù)測流码,效果還行又官,看來這個線性模型還可以接受。
1.1.2. Ridge Regression
這個中文一般叫嶺回歸漫试,就是在上面的目標(biāo)函數(shù)上加個正則項六敬,嶺回歸用二范數(shù)(L2 norm)。
這個范數(shù)的目的在于對整體學(xué)習(xí)到的權(quán)重都控制得比較均衡驾荣,因為我們的數(shù)據(jù)不能保證非常正常外构,有的時候,接近線性相關(guān)的那些噪聲樣本會加劇權(quán)重系數(shù)的非均衡學(xué)習(xí)秘车,最后就是這個樣子
一旦某個特征噪音比較大典勇,剛好那個權(quán)重也不小劫哼,那回歸結(jié)果就慘了叮趴。
好,我們再用波士頓的房價試試嶺回歸权烧。
'''
Author: Miao Fan
Affiliation: Department of Computer Science and Technology, Tsinghua University, P.R.China.
Email: fanmiao.cslt.thu@gmail.com
'''
import sklearn.datasets
import sklearn.linear_model
import numpy.random
import numpy.linalg
import matplotlib.pyplot
if __name__ == "__main__":
# Load boston dataset
boston = sklearn.datasets.load_boston()
# Split the dataset with sampleRatio
sampleRatio = 0.5
n_samples = len(boston.target)
sampleBoundary = int(n_samples * sampleRatio)
# Shuffle the whole data
shuffleIdx = range(n_samples)
numpy.random.shuffle(shuffleIdx)
# Make the training data
train_features = boston.data[shuffleIdx[:sampleBoundary]]
train_targets = boston.target[shuffleIdx [:sampleBoundary]]
# Make the testing data
test_features = boston.data[shuffleIdx[sampleBoundary:]]
test_targets = boston.target[shuffleIdx[sampleBoundary:]]
# Train with Cross Validation
ridgeRegression = sklearn.linear_model.RidgeCV(alphas=[0.01, 0.05, 0.1, 0.5, 1.0, 10.0])
這個地方使用RidgeCV 直接交叉驗證出我需要試驗的幾個懲罰因子眯亦,它會幫我選擇這些里面在集內(nèi)測試表現(xiàn)最優(yōu)的一個參數(shù)伤溉。后面的輸出選擇了0.1。
ridgeRegression.fit(train_features, train_targets)
print "Alpha = ", ridgeRegression.alpha_
# Predict
predict_targets = ridgeRegression.predict(test_features)
# Evaluation
n_test_samples = len(test_targets)
X = range(n_test_samples)
error = numpy.linalg.norm(predict_targets - test_targets, ord = 1) / n_test_samples
print "Ridge Regression (Boston) Error: %.2f" %(error)
# Draw
matplotlib.pyplot.plot(X, predict_targets, 'r--', label = 'Predict Price')
matplotlib.pyplot.plot(X, test_targets, 'g:', label='True Price')
legend = matplotlib.pyplot.legend()
matplotlib.pyplot.title("Ridge Regression (Boston)")
matplotlib.pyplot.ylabel("Price (1000 U.S.D)")
matplotlib.pyplot.savefig("Ridge Regression (Boston).png", format='png')
matplotlib.pyplot.show()
輸出:
Alpha = 0.1
Ridge Regression (Boston) Error: 3.21
基本上妻率,這樣的結(jié)果乱顾,誤差在3210美金左右,比之前的最一般的線性模型好一點(diǎn)宫静。而且走净,這種情況下,基本上預(yù)測出來的圖線的方差比較小孤里,振幅略小伏伯,因為有Ridge的懲罰項的約束,保證每個特征的變化不會對整體預(yù)測有過大的影響
1.1.3. Lasso
老是聽MSRA的師兄說這個捌袜,貌似還挺火的一個研究说搅,這里面就是把二范數(shù)(L2)換成一范數(shù)(L1)。
絕對值的這個約束虏等,更想讓學(xué)習(xí)到的權(quán)重稀疏一些弄唧,壓縮感知啥的跟這個有關(guān)。
這個估計不會有太大的性能提升霍衫,對于Boston數(shù)據(jù)候引,因為本來特征就不稀疏,后面可以試試newsgroup20敦跌。那個夠稀疏背伴。
'''
Author: Miao Fan
Affiliation: Department of Computer Science and Technology, Tsinghua University, P.R.China.
Email: fanmiao.cslt.thu@gmail.com
'''
import sklearn.datasets
import sklearn.linear_model
import numpy.random
import numpy.linalg
import matplotlib.pyplot
if __name__ == "__main__":
# Load boston dataset
boston = sklearn.datasets.load_boston()
# Split the dataset with sampleRatio
sampleRatio = 0.5
n_samples = len(boston.target)
sampleBoundary = int(n_samples * sampleRatio)
# Shuffle the whole data
shuffleIdx = range(n_samples)
numpy.random.shuffle(shuffleIdx)
# Make the training data
train_features = boston.data[shuffleIdx[:sampleBoundary]]
train_targets = boston.target[shuffleIdx [:sampleBoundary]]
# Make the testing data
test_features = boston.data[shuffleIdx[sampleBoundary:]]
test_targets = boston.target[shuffleIdx[sampleBoundary:]]
# Train
lasso = sklearn.linear_model.LassoCV(alphas=[0.01, 0.05, 0.1, 0.5, 1.0, 10.0])
lasso.fit(train_features, train_targets)
print "Alpha = ", lasso.alpha_
# Predict
predict_targets = lasso.predict(test_features)
# Evaluation
n_test_samples = len(test_targets)
X = range(n_test_samples)
error = numpy.linalg.norm(predict_targets - test_targets, ord = 1) / n_test_samples
print "Lasso (Boston) Error: %.2f" %(error)
# Draw
matplotlib.pyplot.plot(X, predict_targets, 'r--', label = 'Predict Price')
matplotlib.pyplot.plot(X, test_targets, 'g:', label='True Price')
legend = matplotlib.pyplot.legend()
matplotlib.pyplot.title("Lasso (Boston)")
matplotlib.pyplot.ylabel("Price (1000 U.S.D)")
matplotlib.pyplot.savefig("Lasso (Boston).png", format='png')
matplotlib.pyplot.show()
輸出:
Alpha = 0.01
Lasso (Boston) Error: 3.39
這個結(jié)果的振幅還是比較大的。特別是對于低價位的振幅峰髓。
1.1.4. Elastic Net
這個不知道中文怎么說合適傻寂,其實就是兼顧了上面兩個正則項(L1和L2兩個先驗(Prior)),既保證能夠訓(xùn)練出一組比較稀疏的模型(Lasso的貢獻(xiàn))携兵,同時還能兼具嶺回歸L2的好處疾掰。這個我沒試過,不知道啥樣的數(shù)據(jù)這么做最合適徐紧,回頭我試幾個數(shù)據(jù)集静檬,比較一下普通的線性回歸和這個模型的性能。
很自然地并级,要用一個額外的參數(shù)來平衡這兩個先驗約束拂檩,一個是懲罰因子alpha,這個之前也有嘲碧,另一個就是
'''
Author: Miao Fan
Affiliation: Department of Computer Science and Technology, Tsinghua University, P.R.China.
Email: fanmiao.cslt.thu@gmail.com
'''
import sklearn.datasets
import sklearn.linear_model
import numpy.random
import numpy.linalg
import matplotlib.pyplot
if __name__ == "__main__":
# Load boston dataset
boston = sklearn.datasets.load_boston()
# Split the dataset with sampleRatio
sampleRatio = 0.5
n_samples = len(boston.target)
sampleBoundary = int(n_samples * sampleRatio)
# Shuffle the whole data
shuffleIdx = range(n_samples)
numpy.random.shuffle(shuffleIdx)
# Make the training data
train_features = boston.data[shuffleIdx[:sampleBoundary]]
train_targets = boston.target[shuffleIdx [:sampleBoundary]]
# Make the testing data
test_features = boston.data[shuffleIdx[sampleBoundary:]]
test_targets = boston.target[shuffleIdx[sampleBoundary:]]
# Train
elasticNet = sklearn.linear_model.ElasticNetCV(alphas=[0.01, 0.05, 0.1, 0.5, 1.0, 10.0], l1_ratio=[0.1,0.3,0.5,0.7,0.9])
elasticNet.fit(train_features, train_targets)
print "Alpha = ", elasticNet.alpha_
print "L1 Ratio = ", elasticNet.l1_ratio_
# Predict
predict_targets = elasticNet.predict(test_features)
# Evaluation
n_test_samples = len(test_targets)
X = range(n_test_samples)
error = numpy.linalg.norm(predict_targets - test_targets, ord = 1) / n_test_samples
print "Elastic Net (Boston) Error: %.2f" %(error)
# Draw
matplotlib.pyplot.plot(X, predict_targets, 'r--', label = 'Predict Price')
matplotlib.pyplot.plot(X, test_targets, 'g:', label='True Price')
legend = matplotlib.pyplot.legend()
matplotlib.pyplot.title("Elastic Net (Boston)")
matplotlib.pyplot.ylabel("Price (1000 U.S.D)")
matplotlib.pyplot.savefig("Elastic Net (Boston).png", format='png')
matplotlib.pyplot.show()
輸出:
Alpha = 0.01
L1 Ratio = 0.9
Elastic Net (Boston) Error: 3.14
貌似還是混合所有制比較牛逼鸠窗!知道這年頭審論文最怕遇到題目里面有啥么味悄?Hybird...,這尼瑪性能不提升都對不起這個單詞塌鸯。侍瑟。。
1.1.10. Logistic regression
這里補(bǔ)充一個比較實用的邏輯斯蒂回歸丙猬,雖然名字叫這個涨颜,但是一般用在分類上。
采用這個函數(shù)來表達(dá)具體樣本的特征加權(quán)組合能夠分到哪個類別上(注:下面的圖片來自博客http://blog.csdn.net/marvin521/article/details/9263483)
下面的這個sigmod函數(shù)對于z值特別敏感茧球,但是他的優(yōu)點(diǎn)在于他是連續(xù)可導(dǎo)的庭瑰,這個非常重要,便于我們用梯度法計算W抢埋。
事實證明弹灭,Logistic Regression做分類非常好用也很易用,據(jù)說Goolge對點(diǎn)擊率CTR的預(yù)測也會用到這個模型揪垄,這個我沒有考證過穷吮,只是聽說,不過下面的代碼對Iris的分類結(jié)果倒是也能說明這個做分類也是挺好用的(這里強(qiáng)調(diào)饥努,我們經(jīng)臣裼悖看到Logistic Regression用來做二分類,事實上它可以拓展到對多類分類上酷愧,我這里不過多介紹驾诈,大家可以查Softmax Regression做參考)。
我們使用Iris的數(shù)據(jù)來測試一下:
大致回顧一下Iris(牽湃茉。花(數(shù)據(jù)篇有詳細(xì)介紹))的數(shù)據(jù)特點(diǎn):150個樣本乍迄,3類,每類基本50條數(shù)據(jù)士败,每個數(shù)據(jù)條目4中特征闯两,都是連續(xù)數(shù)值類型。我們的目標(biāo)就是把隨機(jī)抽取的50%(切記要隨機(jī)打亂數(shù)據(jù),這個數(shù)據(jù)原始的順序不是打亂的生蚁,前50條都是一個類別,別弄錯了戏自。)的數(shù)據(jù)做個類別0,1,2的預(yù)測邦投。
'''
Author: Miao Fan
Affiliation: Department of Computer Science and Technology, Tsinghua University, P.R.China.
Email: fanmiao.cslt.thu@gmail.com
'''
import sklearn.datasets
import sklearn.linear_model
import numpy.random
import matplotlib.pyplot
if __name__ == "__main__":
# Load iris dataset
iris = sklearn.datasets.load_iris()
# Split the dataset with sampleRatio
sampleRatio = 0.5
n_samples = len(iris.target)
sampleBoundary = int(n_samples * sampleRatio)
# Shuffle the whole data
shuffleIdx = range(n_samples)
numpy.random.shuffle(shuffleIdx)
# Make the training data
train_features = iris.data[shuffleIdx[:sampleBoundary]]
train_targets = iris.target[shuffleIdx [:sampleBoundary]]
# Make the testing data
test_features = iris.data[shuffleIdx[sampleBoundary:]]
test_targets = iris.target[shuffleIdx[sampleBoundary:]]
# Train
logisticRegression = sklearn.linear_model.LogisticRegression()
logisticRegression.fit(train_features, train_targets)
# Predict
predict_targets = logisticRegression.predict(test_features)
# Evaluation
n_test_samples = len(test_targets)
X = range(n_test_samples)
correctNum = 0
for i in X:
if predict_targets[i] == test_targets[i]:
correctNum += 1
accuracy = correctNum * 1.0 / n_test_samples
print "Logistic Regression (Iris) Accuracy: %.2f" %(accuracy)
# Draw
matplotlib.pyplot.subplot(2, 1, 1)
matplotlib.pyplot.title("Logistic Regression (Iris)")
matplotlib.pyplot.plot(X, predict_targets, 'ro-', label = 'Predict Labels')
matplotlib.pyplot.ylabel("Predict Class")
legend = matplotlib.pyplot.legend()
matplotlib.pyplot.subplot(2, 1, 2)
matplotlib.pyplot.plot(X, test_targets, 'g+-', label='True Labels')
legend = matplotlib.pyplot.legend()
matplotlib.pyplot.ylabel("True Class")
matplotlib.pyplot.savefig("Logistic Regression (Iris).png", format='png')
matplotlib.pyplot.show()
輸出:
Logistic Regression (Iris) Accuracy: 0.95
使用50%作訓(xùn)練,50%做測試擅笔,分類精度可以達(dá)到95%志衣。
下面這個圖算是一個直觀的輔助,因為分類精度比較高猛们,所以預(yù)測類別和真實類別對應(yīng)的走勢幾乎相同:
http://blog.renren.com/blog/bp/Q7Vlj0xW7D
接著之前No.1绿店,我們繼續(xù)。
之前的易懂的線性模型基本走了一遭庐橙,我們再看看假勿,如果數(shù)據(jù)的特征因素是復(fù)合的,平方的态鳖,立方的(也就是多項式回歸會怎么樣转培?)。我覺得這種東西沒有定論浆竭,誰也不能確定特征組合會不會有道理浸须,再說的直白點(diǎn),到底特征是不是幫助我們機(jī)器學(xué)習(xí)的有效利器邦泄,也沒有定論删窒,但是至少目前看還是有效的。
1.1.15. Polynomial regression: extending linear models with basis functions
我們之前都是關(guān)注顺囊,怎么找到特征的線性組合易稠,但是事實上,不可能都是線性組合包蓝,房價也許從某個特征(比如有一個特征是房子的平均面積驶社,這個和價格有可能是線性關(guān)系;但是如果是這個地區(qū)的房子的數(shù)量测萎,這個很難講亡电,有可能就不是線性的,有可能是平方的硅瞧,也有可能是其他復(fù)雜的關(guān)系份乒,比如邏輯斯蒂關(guān)系,因為環(huán)境飽和有可能造成房價持平甚至下跌)。我們這里考慮這種多項式組合的特征關(guān)系或辖。
這是原來的特征線性組合
這個就是特征的二項式組合瘾英,
我們來看看代碼上,怎么來處理颂暇,還是用房價的數(shù)據(jù)缺谴。
'''
Author: Miao Fan
Affiliation: Department of Computer Science and Technology, Tsinghua University, P.R.China.
Email: fanmiao.cslt.thu@gmail.com
'''
import sklearn.datasets
import sklearn.linear_model
import numpy.random
import numpy.linalg
import matplotlib.pyplot
import sklearn.preprocessing
if __name__ == "__main__":
# Load boston dataset
boston = sklearn.datasets.load_boston()
# Data tranform
polynominalData = sklearn.preprocessing.PolynomialFeatures(degree=2).fit_transform(boston.data)
# Split the dataset with sampleRatio
sampleRatio = 0.5
n_samples = len(boston.target)
sampleBoundary = int(n_samples * sampleRatio)
# Shuffle the whole data
shuffleIdx = range(n_samples)
numpy.random.shuffle(shuffleIdx)
# Make the training data
train_features = polynominalData[shuffleIdx[:sampleBoundary]]
train_targets = boston.target[shuffleIdx [:sampleBoundary]]
# Make the testing data
test_features = polynominalData[shuffleIdx[sampleBoundary:]]
test_targets = boston.target[shuffleIdx[sampleBoundary:]]
# Train
linearRegression = sklearn.linear_model.LinearRegression()
linearRegression.fit(train_features, train_targets)
# Predict
predict_targets = linearRegression.predict(test_features)
# Evaluation
n_test_samples = len(test_targets)
X = range(n_test_samples)
error = numpy.linalg.norm(predict_targets - test_targets, ord = 1) / n_test_samples
print "Polynomial Regression (Degree = 2) (Boston) Error: %.2f" %(error)
# Draw
matplotlib.pyplot.plot(X, predict_targets, 'r--', label = 'Predict Price')
matplotlib.pyplot.plot(X, test_targets, 'g:', label='True Price')
legend = matplotlib.pyplot.legend()
matplotlib.pyplot.title("Polynomial Regression (Degree = 2) (Boston)")
matplotlib.pyplot.ylabel("Price (1000 U.S.D)")
matplotlib.pyplot.savefig("Polynomial Regression (Degree = 2) (Boston).png", format='png')
matplotlib.pyplot.show()
這份代碼里,我使用的是二項式特征轉(zhuǎn)換耳鸯,最高階次是2湿蛔。然后使用普通的線性擬合,
輸出:
Polynomial Regression (Degree = 2) (Boston) Error: 3.26
誤差在3260美金上下县爬,我記得之前的普通的線性回歸是3350阳啥。略好一點(diǎn)點(diǎn)。
有些喜歡質(zhì)疑的同學(xué)也許會問财喳,我這代碼會不會有問題察迟?沒關(guān)系,我們繼續(xù)延伸一個小話題耳高,如果我們只修改一個地方:
# Data tranform
polynominalData = sklearn.preprocessing.PolynomialFeatures(degree=4).fit_transform(boston.data)卷拘,改成4階的,會怎么樣呢祝高?后果不堪設(shè)想栗弟。。工闺。
輸出:
Polynomial Regression (Degree = 4) (Boston) Error: 30.19
誤差達(dá)到3W美金乍赫,這模型完全不能用了。
大家可以看到陆蟆,預(yù)測價格(紅色虛線)的震動非常強(qiáng)烈雷厂,而真實價格基本在30左右徘徊(綠色的虛線)。這說明你的模型在對測試數(shù)據(jù)的泛化能力上非常差叠殷。但是有人一定會問:“我設(shè)計的4階模型應(yīng)該比2階的考慮的特征組合要多得多啊改鲫,怎么會測試的時候這么差?” 是啊林束,考慮全面了像棘,還這么差,我只能說“您想多了”壶冒。事實上缕题,沒有那么多數(shù)據(jù)夠你合理地調(diào)整參數(shù),因為你的模型過于復(fù)雜胖腾。這種情況叫做過擬合(overfitting)烟零。上面的圖片顯示的就是典型的過擬合瘪松。那么如果你的模型本身就是二次的,你用線性回歸锨阿,那么效果也會略差宵睦,這種情況叫做欠擬合(underfitting)
在大數(shù)據(jù)時代,深度學(xué)習(xí)的模型參數(shù)非常多墅诡,但是數(shù)據(jù)也多壳嚎,這樣復(fù)雜模型本身的強(qiáng)大的表達(dá)能力得以展現(xiàn),這是我覺得為什么在圖像书斜,語音這些領(lǐng)域 诬辈,深度學(xué)習(xí)這么有效的簡單原因酵使。
---------------------------------------------------------------------------------------------------------------------------------
支持向量機(jī)的歷史命運(yùn)特別像諾基亞荐吉,曾經(jīng)輝煌很長一段時間,盡管現(xiàn)在已經(jīng)成為歷史口渔,但是終究不能磨滅期偉大貢獻(xiàn)样屠。應(yīng)該是上個世紀(jì)90年代,幾乎在學(xué)術(shù)界充斥了大量的關(guān)于SVM的話題論文缺脉。要是那個時候誰不知道SVM痪欲,就跟現(xiàn)在不知道深度學(xué)習(xí)似的,不知道要遭到多少鄙視:)攻礼。其實我也不懂深度學(xué)習(xí)业踢。。礁扮。被鄙視習(xí)慣了知举,也就見慣不慣了。
我們的這個sklearn系列的討論帖不在于介紹數(shù)學(xué)細(xì)節(jié)太伊,更關(guān)注怎么用雇锡,什么情況下使用什么模型更適合。因此我同意下面的四條關(guān)于SVM的優(yōu)勢的總結(jié)僚焦,這些總結(jié)從側(cè)面告訴你什么時候用SVM:
a. 高維度特征數(shù)據(jù)有效
b. 訓(xùn)練樣本數(shù)量小于特征維數(shù)的數(shù)據(jù)有效(這個特別霸氣)
c. 節(jié)約模型的存儲內(nèi)存(就那么幾個支持向量有用)
d. 還可以根據(jù)需要對特征進(jìn)行高維變化(核函數(shù)的方法)
1.2.1. Classification
SVM用來做Classification锰提,縮寫就是SVC(Support Vector Classification)(SVM不僅僅能做分類,這個一定要說明)的基本思想非常直觀芳悲,也是要找一個超平面(2類分類)立肘,但是要找最好的那個。下圖來自博文:http://blog.csdn.net/marvin521/article/details/9286099名扛。我們可以看到赛不,類似B,C的分隔線可以有無數(shù)個,都能分離藍(lán)色和紅色的兩個類別罢洲,但是貌似D的分類方式更讓人接受踢故,好像如果有一個新的數(shù)據(jù)文黎,大體上像D這樣劃分更容易對,是吧殿较。這里D的方式就是找到了已知數(shù)據(jù)分布的最大間隔耸峭,有充足的泛化空間讓給那些沒有看到的數(shù)據(jù),這樣模型的泛化能力達(dá)到了最大(機(jī)器學(xué)習(xí)的關(guān)鍵問題不在于模型在訓(xùn)練樣本上的契合程度淋纲,在于泛化能力如何劳闹,雖然這是很難評估的),這是為什么SVM在90年代的時候風(fēng)靡一時的原因洽瞬,它也的確好使本涕。
再來看,其實像D這樣的分隔線的確定貌似不太依賴那些遠(yuǎn)離分隔線的數(shù)據(jù)點(diǎn)伙窃,只有那些距離分割線(如果是更多維度的特征菩颖,那就是分隔超平面)最近的一些點(diǎn)能夠支持分割線確定位置,因此叫支持向量機(jī)为障。而那些用來確定分割線的有效數(shù)據(jù)點(diǎn)(特征向量)晦闰,叫做支持向量。
來鳍怨,我們用代碼找找感覺:
這里需要說明一下:如果我們繼續(xù)使用Iris的數(shù)據(jù)呻右,這是一個多類別(3個類別)的分類問題,我覺得大家需要大致了解一下SVC這套工具是怎么處理多類分類的問題的(畢竟鞋喇,我們給出的例子是2類分類的)声滥。
大體上有兩種,將兩類分類器擴(kuò)展到多類分類問題侦香,我這里強(qiáng)調(diào)落塑,不是只有兩種,而是鄙皇,將兩類分類問題進(jìn)行擴(kuò)展芜赌,達(dá)到多(假設(shè)有n個類別) 分類的目的,這個思路有兩種:一種是訓(xùn)練n*(n-1)/ 2個二類分類器伴逸,兩兩類別之間訓(xùn)練一個分類器缠沈,用于專門處理;另外一種就是把其中一個類別拿出來作為正類別错蝴,其他的所有類別統(tǒng)一歸為負(fù)類洲愤,這樣會訓(xùn)練n個訓(xùn)練樣本。
用Iris的數(shù)據(jù)我們都來試試顷锰。
'''
Author: Miao Fan
Affiliation: Department of Computer Science and Technology, Tsinghua University, P.R.China.
Email: fanmiao.cslt.thu@gmail.com
'''
import sklearn.datasets
import sklearn.svm
import numpy.random
import matplotlib.pyplot
import matplotlib.colors
if __name__ == "__main__":
# Load iris dataset
iris = sklearn.datasets.load_iris()
# Split the dataset with sampleRatio
sampleRatio = 0.5
n_samples = len(iris.target)
sampleBoundary = int(n_samples * sampleRatio)
# Shuffle the whole data
shuffleIdx = range(n_samples)
numpy.random.shuffle(shuffleIdx)
# Make the training data
train_features = iris.data[shuffleIdx[:sampleBoundary]]
train_targets = iris.target[shuffleIdx [:sampleBoundary]]
# Make the testing data
test_features = iris.data[shuffleIdx[sampleBoundary:]]
test_targets = iris.target[shuffleIdx[sampleBoundary:]]
# Train
svc = sklearn.svm.SVC()
nusvc = sklearn.svm.NuSVC()
linearsvc = sklearn.svm.LinearSVC()
svc.fit(train_features, train_targets)
nusvc.fit(train_features, train_targets)
linearsvc.fit(train_features, train_targets)
predict_targets = svc.predict(test_features)
#SVC Evaluation
n_test_samples = len(test_targets)
X = range(n_test_samples)
correctNum = 0
for i in X:
if predict_targets[i] == test_targets[i]:
correctNum += 1
accuracy = correctNum * 1.0 / n_test_samples
print "SVC Accuracy: %.2f" %(accuracy)
predict_targets = nusvc.predict(test_features)
#NuSVC Evaluation
n_test_samples = len(test_targets)
X = range(n_test_samples)
correctNum = 0
for i in X:
if predict_targets[i] == test_targets[i]:
correctNum += 1
accuracy = correctNum * 1.0 / n_test_samples
print "NuSVC Accuracy: %.2f" %(accuracy)
predict_targets = linearsvc.predict(test_features)
#LinearSVC Evaluation
n_test_samples = len(test_targets)
X = range(n_test_samples)
correctNum = 0
for i in X:
if predict_targets[i] == test_targets[i]:
correctNum += 1
accuracy = correctNum * 1.0 / n_test_samples
print "LinearSVC Accuracy: %.2f" %(accuracy)
1.3. Stochastic Gradient Descent
1.4. Nearest Neighbors
1.4.2. Nearest Neighbors Classification
借著剛剛更新過的Logistic Regression 對 Iris做分類的余興柬赐,我們來看看使用近鄰法是怎么做分類(近鄰法不僅能做分類,還能回歸官紫,我先介紹分類肛宋,這個比較好懂)的州藕。這個算是基于實例的分類方法,和前面介紹的回歸啊酝陈,分類啊這些方法都不同床玻,之前都是要訓(xùn)練出一個具體的數(shù)學(xué)函數(shù),對吧沉帮。這種近鄰法不需要預(yù)先訓(xùn)練出什么公式锈死。近鄰法的思想很簡單,“物以類聚穆壕,人以群分”待牵,特征相似的,類別最相近喇勋。KNN(K Nearest Neighbor)的意思就是在某個待分類的樣本周圍找K個根據(jù)特征度量距離最近的K個已知類別的樣本缨该,這K個樣本里面,如果某個類別個數(shù)最多茄蚯,那么這個待分類的樣本就從屬于那個類別压彭。意思就是睦优,找特性最相近的朋黨渗常,然后少數(shù)服從多數(shù)。
當(dāng)然汗盘,這個工具包也沒有那么簡單皱碘,除了KNN(KNeighborsClassifier)還有RNN(RadiusNeighborsClassifier),說白了隐孽,KNN不在乎那K個最近的點(diǎn)到底離你有多遠(yuǎn)癌椿,反正總有相對最近的K個。但是RNN要考慮半徑Radius菱阵,在待測樣本以Radius為半徑畫個球(如果是二維特征就是圓踢俄,三維特征以上,你可以理解為一個超球面)晴及,這個球里面的都算進(jìn)來都办,這樣就不能保證每個待測樣本都能考慮相同數(shù)量的最近樣本。
同時虑稼,我們也可以根據(jù)距離的遠(yuǎn)近來對這些已知類別的樣本的投票進(jìn)行加權(quán)琳钉,這個想法當(dāng)然很自然。后面的代碼都會體現(xiàn)蛛倦。
我們還是用Iris來測試一下歌懒,這次采樣比例弄得狠了點(diǎn),20%訓(xùn)練溯壶,80%用來預(yù)測測試及皂,就是為了區(qū)別一下兩種距離加權(quán)方式[unifrom, distance]甫男。
'''
Author: Miao Fan
Affiliation: Department of Computer Science and Technology, Tsinghua University, P.R.China.
Email: fanmiao.cslt.thu@gmail.com
'''
import sklearn.datasets
import sklearn.neighbors
import numpy.random
import matplotlib.pyplot
import matplotlib.colors
if __name__ == "__main__":
# Load iris dataset
iris = sklearn.datasets.load_iris()
# Split the dataset with sampleRatio
sampleRatio = 0.2
n_samples = len(iris.target)
sampleBoundary = int(n_samples * sampleRatio)
# Shuffle the whole data
shuffleIdx = range(n_samples)
numpy.random.shuffle(shuffleIdx)
# Make the training data
train_features = iris.data[shuffleIdx[:sampleBoundary]]
train_targets = iris.target[shuffleIdx [:sampleBoundary]]
# Make the testing data
test_features = iris.data[shuffleIdx[sampleBoundary:]]
test_targets = iris.target[shuffleIdx[sampleBoundary:]]
# Train
n_neighbors = 5 #選5個最近鄰
for weights in ['uniform', 'distance']: #這個地方采用兩種加權(quán)方式
kNeighborsClassifier = sklearn.neighbors.KNeighborsClassifier(n_neighbors, weights=weights)
kNeighborsClassifier.fit(train_features, train_targets)
# Test
predict_targets = kNeighborsClassifier.predict(test_features)
#Evaluation
n_test_samples = len(test_targets)
X = range(n_test_samples)
correctNum = 0
for i in X:
if predict_targets[i] == test_targets[i]:
correctNum += 1
accuracy = correctNum * 1.0 / n_test_samples
print "K Neighbors Classifier (Iris) Accuracy [weight = '%s']: %.2f" %(weights, accuracy)
# Draw
cmap_bold = matplotlib.colors.ListedColormap(['red', 'blue', 'green'])
X_test = test_features[:, 2:4]
X_train = train_features[:, 2:4]
matplotlib.pyplot.scatter(X_train[:, 0], X_train[:, 1], label = 'train samples', marker='o', c = train_targets, cmap=cmap_bold,)
matplotlib.pyplot.scatter(X_test[:,0], X_test[:, 1], label = 'test samples', marker='+', c = predict_targets, cmap=cmap_bold)
legend = matplotlib.pyplot.legend()
matplotlib.pyplot.title("K Neighbors Classifier (Iris) [weight = %s]" %(weights))
matplotlib.pyplot.savefig("K Neighbors Classifier (Iris) [weight = %s].png" %(weights), format='png')
matplotlib.pyplot.show()
輸出:
K Neighbors Classifier (Iris) Accuracy [weight = 'uniform']: 0.91
K Neighbors Classifier (Iris) Accuracy [weight = 'distance']: 0.93
加權(quán)方法略好一點(diǎn),大約提升2%的精度(注意這兩個圖验烧,我只是采用了其中的兩個維度特征進(jìn)行的重建查剖,事實上應(yīng)該有4個維度):
1.5. Gaussian Processes
1.6. Cross decomposition
1.7. Naive Bayes
1.8. Decision Trees
1.10. Multiclass and multilabel algorithms
1.13. Linear and quadratic discriminant analysis
然后讓我們開始無監(jiān)督學(xué)習(xí):(聚類啊,概率密度估計(離群點(diǎn)檢測)啊噪窘,數(shù)據(jù)降維八褡)等等。相對而言倔监,這個部分的工具還是比起許多其他ML包要豐富地多直砂!什么流形學(xué)習(xí)啊都有。
2.5. Decomposing signals in components (matrix factorization problems)
2.7. Novelty and Outlier Detection
2.9. Neural network models (unsupervised)
3. Model selection and evaluation
模型選擇有的時候,特別是在使用ML創(chuàng)業(yè)的時候更需要把握。其實好多問題不同模型都差不多到80%精度痴鳄,后面怎么提升才是重點(diǎn)乒裆。不止一個小伙伴想要用Deep Learning 這個話題作為噱頭準(zhǔn)備9月份的博士或者碩士開題,那玩意兒想做好王污,你還真得有耐心調(diào)參數(shù),回想起MSRA我那同一排的大嬸(神)們,都是NIPS敖脊!=础驮审!丫的,1%的提升都要尖叫了:)吉执,其實我想說疯淫,妹的,參數(shù)不一樣唄戳玫。熙掺。。這就是Black Magic(黑魔法)咕宿。玩深度學(xué)習(xí)的多了币绩,估計以后不是模型值錢,是參數(shù)值錢了荠列。
另外就是特征選擇类浪,這個玩意兒也有講究,如果真正用ML創(chuàng)業(yè)肌似,其實模型還是那些模型费就,特征和參數(shù)的選擇往往更能看出這個人的水平,別瞎試川队,千萬別力细。睬澡。。
3.1. Cross-validation: evaluating estimator performance
3.2. Grid Search: Searching for estimator parameters
3.3. Pipeline: chaining estimators
3.4. FeatureUnion: Combining feature extractors
3.5. Model evaluation: quantifying the quality of predictions
3.7. Validation curves: plotting scores to evaluate models
4.5. Pairwise metrics, Affinities and Kernels
5.5. Datasets in svmlight / libsvm format
5.6. The Olivetti faces dataset
5.7. The 20 newsgroups text dataset
5.8. Downloading datasets from the mldata.org repository
5.9. The Labeled Faces in the Wild face recognition dataset