《Python語言基礎及應用》 課件 第9章 機器學習_第1頁
《Python語言基礎及應用》 課件 第9章 機器學習_第2頁
《Python語言基礎及應用》 課件 第9章 機器學習_第3頁
《Python語言基礎及應用》 課件 第9章 機器學習_第4頁
《Python語言基礎及應用》 課件 第9章 機器學習_第5頁
已閱讀5頁,還剩82頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第9章機器學習目錄contents基于數據的學習實例:手寫數字識別實例:交通車流量預測實例:電影推薦系統Scikit-learn近年來,從計算機科學開始,到物理、生物、能源、醫療等領域,人工智能都實現了許多優秀的實際應用。如計算機視覺模型可以協助醫生開展日常工作,自然語言模型在對話翻譯中大放異彩,基于大數據的推薦系統能夠針對性地為用戶推薦所需信息。在這其中,機器學習算法是實現相關應用的核心,是使計算機具有智能的根本途徑。在之前的章節中已經介紹了NumPy對高維數組數據的高效處理,Matplotlib對數據的可視化分析,Scipy提供的豐富科學計算資源,這些以足夠作為開發基礎機器學習應用的工具。本章將介紹Python中最普遍與流行的機器學習庫Scikit-Learn(簡稱Sklearn),該庫建立在NumPy、SciPy以及Matplotlib的基礎之上,因此也擁有幾乎等效于C語言的運算速度。由于該庫API設計的易用性,通過修改幾行代碼即可實現各類機器學習算法并進行實驗,其在學術研究與工業應用領域都很流行。Scikit-learn可以通過conda或者pip安裝,由于該庫內容龐大,在進行實驗和開發時通常只導入項目需要的模塊,而不像NumPy和Matplotlib一樣將整個庫導入。基于數據的學習01機器學習簡述早在1959年,機器學習的先驅ArthurSamuel首次對機器學習進行了定義:“機器學習是使計算機無需明確編程即可學習的研究領域。”除此之外,他還開發了一個機器學習的跳棋程序,其通過與用戶進行跳棋游戲,在一段時間后,程序可以學習到什么是好的布局,什么是不好的布局,并且學會跳棋的基本玩法。通過長期的學習后,該程序甚至可以打敗ArthurSamuel。在那個沒有高級編程語言甚至也沒有顯示器的年代,該機器學習系統的開發與驗證是具有劃時代的開創意義的。到了1998年,卡內基梅隆大學教授TomM.Mitchell對機器學習作出了更嚴謹的定義“一個計算機程序利用經驗E來學習任務T,性能是P,如果針對任務T的性能P隨著經驗E不斷增長,則稱為機器學習”。圖9-1展示了該機器學習算法的定義。機器學習簡述例如,對于一個傳統的垃圾電子郵件過濾系統,設計者首先需要收集垃圾郵件中可能包含的文本信息、發件人姓名、郵件的格式等,對每種異常的模式編寫檢測算法,對于檢測到異常的郵件標記為垃圾郵件。但這種方法在實施時會極度困難,因為程序中會包含大量復雜的規則而變得難以維護。而在基于機器學習的垃圾郵件過濾系統中,可以使用垃圾郵件(如通過人工標記)和普通郵件作為訓練數據(經驗E),對垃圾郵件分類任務自動學習(任務T),分類的正確率(性能P)會隨著訓練數據的增加不斷地增長。這意味系統會自動學習垃圾郵件中的特征,這類方法不僅更易維護,其分類準確率通常也更高。上述的案例使用機器學習算法判斷郵件是否為垃圾郵件,是典型的分類任務。按任務的不同,機器學習大體可分為分類、回歸、聚類、降維四種任務。分類任務和回歸任務都是基于數據作出預測,區別在于分類任務是對離散值進行預測,而回歸任務是對連續值進行預測。如預測會不會下雨是一個分類任務,預測氣溫是一個回歸任務。聚類任務是按照某種特定的標準把相似的數據聚合在一起,與分類任務不同的是聚類任務對無標記訓練樣本學習數據的內在性質。降維任務是針對高緯度、大規模、高復雜數據,挖掘其中有意義的內容,去除特征的冗余,用更加少的維度表示信息,從而更好地認識和理解數據。機器學習簡述按是否有標簽數據,機器學習又可分為監督學習、無監督學習和強化學習。監督學習的每個訓練實例都包含輸入和期望輸出的標簽,如分類和回歸任務都屬于監督學習。無監督學習輸入的數據并沒有期望輸出的標簽,其利用算法探索數據中隱藏的模式,如聚類任務屬于無監督學習。與監督學習和無監督學習不同,強化學習關注的是如何基于環境而行動,以取得最大化的預期利益,其不需要帶標簽的輸入輸出對,同時也無需對非最優解的精確地糾正。強化學習注重于對未知領域的探索和對已有知識利的利用之間的平衡,如知名的AlphaGo圍棋就是基于強化學習算法構建的。如圖9-2所示,這三種類型并不是完全孤立的,在實際的設計與開發中,通常會對其中的一種或多種算法進行結合構建出適合任務特點的機器學習模型。機器學習數據準備對于機器學習算法來說,數據是及其重要的,如果沒有數據就無法進行模型的訓練,而數據質量過低也會導致模型性能降低。之前的章節介紹了基于NumPy進行數據的導入與處理工作,在面對復雜的數據集時,由于NumPy矩陣對數據格式的要求,會加大數據讀取工作的復雜度。事實上,在大量機器學習任務的數據準備環節中,開發者往往會選用Pandas庫對數據進行預處理。Pandas的出現不僅簡化了Python進行數據準備和分析的流程,更降低了其上手難度。對于機器學習算法來說,數據是及其重要的,如果沒有數據就無法進行模型的訓練,而數據質量過低也會導致模型性能降低。之前的章節介紹了基于NumPy進行數據的導入與處理工作,在面對復雜的數據集時,由于NumPy矩陣對數據格式的要求,會加大數據讀取工作的復雜度。事實上,在大量機器學習任務的數據準備環節中,開發者往往會選用Pandas庫對數據進行預處理。Pandas的出現不僅簡化了Python進行數據準備和分析的流程,更降低了其上手難度。通常以如下方式進行引用:>>>importpandasaspdPandas常用的數據讀取函數函數名描述read_csv()讀取CSV文件并轉換為DataFrame對象read_excel()讀取Excel文件并轉換為DataFrame對象read_json()讀取JSON文件并轉換為Pandas對象read_html()讀取HTML表格并轉換為DataFrame對象的列表read_pickle()讀取文件中PickledPandas對象DataFrame對象下列代碼使用read_csv()函數讀取“student.csv”文件,由于該文件中包含中文,需在讀取文件時確定編碼格式為“GB18030”,以避免亂碼現象的出現。隨后,使head(5)函數觀察數據的前五行內容。>>>df=pd.read_csv('student.csv',encoding='GB18030')>>>df.head(5)缺失值檢測數據為NaN,代表數據缺失。在實際中,常常會由于數據收集、數據整理、數據挖掘等過程中的不完善或限制因素,造成數據缺失的問題。Pandas提供了isnull()和notnull()兩種方法對缺失值進行檢測,下列代碼對數據對象各列的缺失值進行統計并打印。>>>print(df.isnull().sum())學號0姓名1年齡1性別0評分2dtype:int64缺失值填充不完整的數據會給機器學習模型帶來極大挑戰。對于缺失數據,在Pandas中常用的有使用fillna()函數進行值替換或使用dropna()函數刪除數據段兩種處理方法。下列代碼分辨展示替換缺失值0和刪除含缺失值行的方法。#將缺失值替換為0>>>print(df.fillna(value=0))

學號姓名年齡性別評分010001小明22.0男75.0110002大飛27.0男86.0210003小王22.0男0.0310004丁丁24.0女95.0410005小張20.0女79.0510006小麗22.0女81.0610007大壯21.0男0.0710008小飛22.0女83.0810009小強20.0男65.0910010021.0女76.01010011小華0.0男83.0#將包含缺失值的行刪除>>>print(df.dropna())

學號姓名年齡性別評分010001小明22.0男75.0110002大飛27.0男86.0310004丁丁24.0女95.0410005小張20.0女79.0510006小麗22.0女81.0710008小飛22.0女83.0810009小強20.0男65.0Pandas索引方法方法描述[]切片索引.loc()基于標簽的索引.iloc()基于整數的索引#使用切片索引>>>print(df[['姓名','評分']][:3])

姓名評分0小明75.01大飛86.02小王NaN#基于標簽的索引>>>print(df.loc[:2,['姓名','評分']])

姓名評分0小明75.01大飛86.02小王NaN#基于整數的索引>>>print(df.iloc[:3,[1,4]])

姓名評分0小明75.01大飛86.02小王NaNDataFrame與ndarray與NumPy相比,Pandas更適合處理包含不同數據格式的表格類數據,并提供了對數據進行去重、排序、合并、統計、采樣等便捷的功能函數。但是,Pandas的DataFrame的內存消耗也要高于NumPy的ndarray,在實際進行數據準備時,需根據開發和效率需求使用正確的工具。對Pandas其他功能感興趣的讀者可以根據Pandas官方網站提供的用戶手冊進一步學習。機器學習流程在機器學習模型與算法的開發與實施通常會遵循一套適用的流程和步驟1.獲得數據2.數據預處理3.模型建立與訓練4.模型預測和評估獲得數據機器學習中的經驗E本質上是數據,在開發模型前,首先需要明確需要的訓練數據類型。數據需要對擬問題具有顯著的代表性,如對于“中文—英文”翻譯模型,諸如德語、法語等數據在一般情況下是對模型沒有明顯幫助的。隨后需要確定數據的數量,這往往取決于擬解決的問題與模型的復雜度。通常來說,越復雜的模型需要越多的數據進行訓練。這之后最重要的步驟就是對所需的數據開展收集工作,如查閱公開的數據集、使用爬蟲程序從互聯網收集數據、使用傳感器收集實測數據等。如表9-3所示,Scikit-learn在sklearn.datasets中提供了一系列用于機器學習的數據集。除此之外,sklearn.datasets還提供了從中下載數據集的接口。出于時間和成本的考慮,在收集數據時應首先考慮公開的數據集Scikit-learn中常用的內置數據集方法描述任務load_iris()鳶尾花數據集分類load_digits()數字數據集分類load_wine()葡萄酒數據集分類load_breast_cancer()威斯康星乳腺癌數據集分類load_diabetes()糖尿病數據集回歸load_linnerud()林納魯德體能訓練數據集(多輸出)回歸數據預處理在機器學習的訓練數據中,通常包含著大量的特征,每個特征的性質、量綱、數量級、可用性等都可能存在一定的差異。若特征之間差異較大時,直接使用原始數據分析會造成特征的不平衡。如在考慮不同時期的物價指數時,若將較低價格的食品和較高價格的汽車的價格漲幅一并納入特征,會導致汽車在綜合指數中的作用被放大。因此,在訓練機器學習模型前,通常需要對數據進行預處理工作。對于數字數據,為了保持其數量級上的統一,最常用的預處理方式是數據標準化。其做法是對數據集中的數據首先減去平均值,再除以標準差,將數據映射至平均值為0且有相同階數的方差。數據標準化處理>>>importsklearn>>>importnumpyasnp>>>importmatplotlib.pyplotasplt#設置中文顯示>>>pltrcParams['font.sans-serif']=['SimHei']>>>plt.rcParams['axes.unicode_minus']=False#生成正態分布的測試數據>>>x=np.random.normal(-10,10,1000)>>>y=np.random.normal(-5,2,1000)>>>data=np.stack([x,y],axis=-1)#對數據進行標準化處理>>>scaler=sklearn.preprocessing.StandardScaler()>>>scaler.fit(data)>>>trans_data=scaler.transform(data)#可視化對比>>>fig,ax=plt.subplots(1,2,figsize=(9,4),dpi=300)>>>ax[0].scatter(data[:,0],data[:,1])>>>ax[0].grid()>>>ax[0].axis([-40,40,-40,40])>>>ax[0].set(xlabel='x軸',ylabel='y軸',title='原始數據')>>>ax[1].scatter(trans_data[:,0],trans_data[:,1],color='red')>>>ax[1].axis([-40,40,-40,40])>>>ax[1].grid()>>>ax[1].set(xlabel='x軸',ylabel='y軸',title='標準化處理后的數據')>>>plt.show()數據集劃分機器學習算法最終的目的是將訓練好的模型部署至真實環境中,并希望模型能夠在未知的數據上得到較好的預測效果。因此,模型在訓練數據集上的表現并不能完全代表模型的泛化能力。為此,在訓練機器學習模型時需要將數據分割為訓練集(Train)和測試集(Test)兩個部分。在模型訓練時只使用訓練集數據,然后用測試集數據上的誤差作為模型應對真實場景中的泛化誤差。劃分數據集必須在開始構建之前模型完成,防止數據窺探偏誤。通常來說,應該將數據集的大部分(80%以上)劃撥為訓練集,以保證模型能夠從足夠的樣本中學習到數據的模式。當涉及到根據預測結果調整模型參數時(通常稱為模型的超參數),為了保證無偏估計不可以直接在測試集數據上進行模型調整。為此,可以將訓練集數據進一步劃分為訓練集與驗證集(Validation),通過驗證集評估模型,再通過測試集觀察模型的泛化能力。train_test_split()sklearn.model_selection.train_test_split(*arrays,**options)下列代碼使用該函數將使用NumPy生成模擬數據集并劃分為80%的訓練集和20%的測試集>>>fromsklearn.model_selectionimporttrain_test_split>>>importnumpyasnp>>>X,y=np.arange(10).reshape((5,2)),range(5)>>>X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2)模型建立與訓練在完成數據預處理后,需要選擇合適的算法開展訓練。表9-4列出了Scikit-learn庫針對分類、回歸、聚類、降維等機器學習任務提供的常用算法。在實際應用中,需要考慮算法的應用場景和可用的數據形式。若數據帶有標簽,則根據輸出的數據是否連續選擇回歸或分類算法。若數據沒有標簽,如需將數據劃分為離散的組,則使用聚類算法;若僅需要對數據的維度進行約簡,則使用降維算法。確定好任務類型后,需對算法進行合適的選擇。當數據的特征數較少時,簡單的模型就可以保證足夠的學習和泛化能力。當特征數較大時,往往應選擇諸如集成學習的較復雜的模型。隨著數據量的增大,對模型復雜度要求也會增加,使其能夠充分學習大量數據提供的信息。Scikit-learn中常用的機器學習算法任務類型算法名稱Scikit-learn中類名稱回歸線性回歸linear_model.LinearRegression()嶺回歸linear_model.Ridge()LASSO回歸linear_model.Lasso()貝葉斯嶺回歸linear_model.BayesianRidge()核函數嶺回歸kernel_ridge.KernelRidge()線性支持向量回歸svm.LinearSVR()決策樹回歸tree.DecisionTreeRegressor()隨機森林回歸ensemble.RandomForestRegressor()梯度提升回歸ensemble.GradientBoostingRegressor()分類邏輯回歸linear_model.LogisticRegression()嶺回歸分類linear_model.RidgeClassifier()線性感知器分類linear_model.Perceptron()線性支持向量分類svm.LinearSVC()決策樹分類tree.DecisionTreeClassifier(隨機森林分類ensemble.RandomForestClassifier()梯度提升分類ensemble.GradientBoostingClassifier()聚類K-Means聚類cluster.KMeans()DBSCAN聚類cluster.DBSCAN()均值偏移聚類cluster.MeanShift()譜聚類cluster.SpectralClustering()降維主成成分分析降維decomposition.PCA()截斷SVD降維decomposition.TruncatedSVD()非負矩陣分解decomposition.NMF()fit()函數在確定模型使用的機器學習算法后,即可利用訓練數據對模型進行訓練。由于Scikit-learn在設計時統一了API,因此模型的訓練與數據預處理中一樣,只需在選擇的對象上使用fit()方法既可以展開訓練。下列代碼首先使用NumPy生成模擬數據作為數據集,劃分80%為訓練集。構建線性回歸算法的模型,利用訓練數據訓練該模型,并將訓練好的模型賦值給reg。>>>fromsklearn.linear_modelimportLinearRegression>>>X,y=np.arange(10).reshape((5,2)),range(5)>>>X_train,X_test,y_train,y_test=train_test_split(X,y,train_size=0.8)>>>reg=LinearRegression().fit(X_train,y_train)模型預測和評估獲得訓練好的模型后,即可調用predict()方法對數據進行輸出預測。然而僅僅觀察預測輸出并不能直觀地反映模型的性能。sklearn.metrics針對不同機器學習任務的實現了各類指標函數,以科學地評估模型性能。任務類型指標名稱方法名稱描述分類準確率accuracy_score()正確分類樣本的比例召回率recall_score()正樣本中預測正確的百分比F1分數f1_score()準確率和召回率的調和平均值AUCroc_auc_score()ROC曲線下方的面積回歸平均絕對誤差mean_absolute_error()絕對誤差均方誤差mean_squared_error()二次誤差R2分數r2_score()決定系數最大誤差max_error()誤差的最大值聚類蘭德指數rand_score()聚類的相似性度量調整蘭德指數adjusted_rand_score()改進的蘭德系數完整性completeness_score()類的所有成員都在同個集群同質性homogeneity_score()每個集群只包含單個類的成員模型預測和評估通常來說,對模型的評價是在驗證集上進行的。若模型在訓練集上表現很好,但在驗證集上表現較差,則很可能發生了“過擬合”現象,即模型學習能力過強,以至于將訓練數據中單個樣本的噪聲、不均勻分布等都進行了學習,這導致了模型的泛化能力下降,以至于其在未知數據上的表現下降。若判斷出現“過擬合”現象,可以考慮給減少數據的特征數量、給模型增加正則化等手段調節模型。若模型無論在測試集還是驗證集上都有較大的誤差,則很可能發生了“欠擬合”現象,即模型過于簡單,無法充分學習數據的模式。若判斷出現“欠擬合”現象,可以選擇增加模型的復雜度或添加新的域特有特征和更多特征笛卡爾積,并更改特征處理所用的類型。模型預測和評估下列代碼首先使用NumPy生成模擬數據作為數據集,劃分80%為訓練集。構建線性回歸算法的模型,調用fit()方法使用訓練數據訓練該模型。調用predict()方法在測試集上預測數據。最后使用r2_score()計算預測數據和實際數據的R-squared分數。由結果可知,在測試集上模型的R-squared分數為0.89802,較為接近1,表示預測情況和真實情況的吻合度較高。>>>fromsklearn.metricsimportr2_score>>>X,y=np.arange(30).reshape((15,2)),range(15)>>>y+=np.random.randn(15)>>>X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.20)>>>reg=LinearRegression().fit(X_train,y_train)>>>y_predict=reg.predict(X_test)>>>print('在測試集上的R-squared分數為{:.5f}'.format(r2_score(y_predict,y_test)))在測試集上的R-squared分數為0.89802實例:手寫數字識別01問題分析手寫數字識別是機器學習領域中的一個經典應用,其地位在某種程度上可以相當于入門編程語言時的“HelloWorld”。該任務的目的是計算機能正確從紙質文檔、照片或其他接收來源接受和理解并識別可讀的手寫數字的的能力。若計算機能達到較高的識別正確率,便可應用于信件的郵政編碼自動識別等領域之中。然而,利用傳統的圖像處理手段在該問題上并不能達到較滿意的結果,雖然只是針對0至9之間的十個數字的識別,但手寫字體的多樣性、數字之間的混淆性(如4和9)等因素都造成了識別的困難。在本節中,將建立數據驅動的機器學習算法識別手寫數字的模式特征,從而達到正確的分類結果。模塊導入與設置本案例中將使用到如下的庫與模塊,首先將其進行導入同時,本案例的可視化分析涉及到中文的使用,需要進行設置>>>importnumpyasnp>>>importmatplotlib.pyplotasplt>>>fromsklearnimportdatasets,metrics>>>fromsklearn.model_selectionimporttrain_test_split>>>fromsklearn.datasetsimportfetch_openml>>>fromsklearn.utilsimportcheck_random_state>>>fromsklearn.preprocessingimportStandardScaler>>>fromsklearn.linear_modelimportLogisticRegression>>>plt.rcParams['font.sans-serif']=['SimHei']>>>plt.rcParams['axes.unicode_minus']=FalseMNIST數據集手寫數字識別的研究歷史可追溯至上世紀,在1988年,著名的MNIST數據集(MixedNationalInstituteofStandardsandTechnologyDatabase)問世。該數據集由來自高中學生與人口普查局雇員的手寫數字構成,包括訓練與測試在內一共有70000張圖像。每張圖像都是單通道的灰度圖像。該數據集數據量適中,數據質量較高,直至今日仍被廣泛用于驗證機器學習算法的有效性。MNIST數據集可以在網站中獲取,作為經典的數據集,sklearn.datasets中也封裝了自動下載該數據集的方法。下列代碼使用fetch_openml方法從機器學習數據和實驗的公共存儲庫OpenML中下載MNIST數據集,并將圖像與標簽數據賦值給對應的變量X和y,并打印出數據集的基本情況。>>>X,y=fetch_openml("mnist_784",version=1,return_X_y=True,as_frame=False)>>>print("數據集共包含{}個樣本\n每個輸入數據的形狀為{},每個標簽的形狀為{}".format(X.shape[0],X.shape[1],1))數據集共包含70000個樣本每個輸入數據的形狀為784,每個標簽的形狀為1MNIST數據集中各個數字的數據量>>>digits,counts=np.unique(y,return_counts=True)#數字類型及其數據量>>>plt.figure(figsize=(12,8))>>>b=plt.bar(digits,counts,alpha=0.5)>>>plt.bar_label(b,padding=5)#為每個柱狀圖添加標簽>>>plt.xlabel('數字')>>>plt.ylabel('數據量')>>>plt.grid(axis='y')>>>plt.title('MNIST數據集各個數字的數據量')>>>plt.show()MNIST數據集可視化>>>defplot_digits(data,label,title):...plt.figure(figsize=(12,12))...foriinrange(16):...plt.subplot(4,4,i+1)...plt.imshow(data[i].reshape(28,28),cmap='gray',interpolation='none')...plt.title("數字:{}".format(label[i]))...plt.xticks([])...plt.yticks([])...plt.suptitle(title)...plt.tight_layout()...plt.show()>>>plot_digits(X,y,'MNIST數據集')MNIST數據集標準化>>>defscaler_input(data):...scaler=StandardScaler()...data=scaler.fit_transform(data)...returndata>>>X_scaler=scaler_input(X)>>>print('原始輸入數據的均值為{:.2f},標準差為{:.2f}\n經過標準化處理后數據的均值為{:.2f},標準差為{:.2f}'.format(X.mean(),X.std(),X_scaler.mean(),X_scaler.std()))原始輸入數據的均值為33.39,標準差為78.65經過標準化處理后數據的均值為0.00,標準差為0.96>>>plot_digits(X_scaler,y,'MNIST數據集(標準化處理后)')MNIST數據集劃分>>>deftrain_validation_split(X,y,train_size):...random_state=check_random_state(0)...permutation=random_state.permutation(X.shape[0])...X=X[permutation]...y=y[permutation]...X=X.reshape((X.shape[0],-1))...X_train,X_val,y_train,y_val=train_test_split(...X,y,train_size=train_size)...returnX_train,X_val,y_train,y_val>>>X_train,X_val,y_train,y_val=train_validation_split(X_scaler,y,0.9)>>>print('劃分后,訓練集中有{}個樣本,驗證集中有{}個樣本。'.format(X_train.shape[0],X_val.shape[0]))劃分后,訓練集中有63000個樣本,驗證集中有7000個樣本.Sigmoid函數如上小節介紹,MNIST數據集包含了圖像數據與其對應的數字類別標簽。由于數字類別是一種離散數據,手寫數字問題的識別本質上是監督學習中的分類問題,即輸入圖片,判斷其屬于數字0至9之間的哪一類別。在本案例中,將使用機器學習分類任務中的邏輯回歸算法(LogisticRegression),配合正則化技術,實現手寫數字的分類識別。邏輯回歸盡管以回歸命名算法,但其實際上是分類模型而不是線性模型,在一些文獻資料中,其也被稱為logit回歸、最大熵分類、對數線性分類器等。對于二分類的邏輯回歸算法,其首先將權重矩陣與輸入特征向量相乘,得到再將其輸入至Sigmoid映射函數進行非線性變換得到輸出預測。Sigmoid函數的公式如下Sigmoid函數#定義Sigmoid函數>>>sigmoid=lambdax:1./(1.+np.exp(-x))>>>x=np.linspace(-5,5,100)>>>plt.figure(figsize=(10,6))#繪制Sigmoid函數>>>plt.plot(x,sigmoid(x))#以紅色點劃線繪制水平輔助線>>>plt.plot(x,0.5*np.ones_like(x),'r-.')>>>plt.xlim([-5,5])>>>plt.title('Sigmoid函數')>>>plt.grid()>>>plt.show()多分類領域當分類問題由二分類推廣至多分類領域時,有一種直觀地解決方案稱之為one-versus-rest。其本質思想是將一個多分類問題轉化為多個二分類問題,即選擇其中一項為正類,其余所有類別為負類。如在手寫數字識別中,建立10個數字分類器,每個分類器將對應的數字字符定義為正類,其他字符定義為負類。在預測時,將利用這10個二分類器進行分類,得到數據屬于當前類的概率,選擇其中最大的一個類別作為最終結果。但該方法在訓練樣本分布不均且類別較多的情況下,容易出現正類的數量遠不及負類的數量,從而造成分類器的偏向性。one-versus-rest中手寫數字識別的二分類器方法正類負類二分類器0數字0數字1至數字9二分類器1數字1數字0、數字2至數字9二分類器2數字2數字0至數值1,數字3至數字9……二分類器9數字9數字0至數字8Softmax函數除此之外,還可以將二分類邏輯回歸通過映射函數的方式直接變更為多分類邏輯回歸。其將Sigmoid映射函數更換為Softmax函數,該函數將特征的加權求和結果映射至多個0-1之間的數值,從而得到概率分布。對于擁有個類別的多分類模型,每個類別的Softmax值為與Sigmoid函數相似,Softmax同樣是非線性指數函數且嚴格遞增,有較好的求導性質,且該函數計算每個類別的和為1,對概率分布達到了歸一化。損失函數邏輯回歸算法通過計算預測值與真實值之間的交叉熵(Cross-Entropy)作為損失函數,其衡量概率分布之間的相似度,當交叉熵損失函數值較大時,代表模型效果較差。因此使用數據持續最小化交叉熵損失函數能夠提升模型的性能。正則化MNIST數據集中的每幅圖像的尺寸為(28,28),即共有784個特征。如在9.1.3中所介紹的,機器學習中當特征數量較多時,可能會出導致對訓練數據的過度擬合,導致高方差,使得模型雖然在訓練數據集上有較好的表現,但在未知樣本的預測上卻表現較差。為此,可采取在損失函數中增加正則項的方法,減小高階次項對模型整體的影響,降低模型的復雜度,以此提升模型的泛化能力。常用的正則化手段有L1正則化與L2正則化。L1正則化在損失函數上增加正則系數乘以所有權重絕對值之和。當權重更新時,若權重值過大,則無法有效降低損失函數值,從而避免某些維度上權重過大而過分依賴對應維度的線性。由于L1正則化采取了絕對值的方式,能進一步加強權重的稀疏性。與之相比,L2正則化在損失函數上在損失函數上加上正則系數乘以所有權重的平方和,其同樣可以防止權重過大,從而降低網絡復雜度。但是由于L2正則化平方和的形式,在權重較小時其平方進一步減小,因此無法像采用絕對值和的L1正則化一樣加強權重的稀疏性。在一些機器學習算法的設計中,有時也會采用L1正則化與L2正則化相結合的手段。正則化在sklearn.linear_model的LogisticRegression中已經完整地封裝了邏輯回歸的算法,可直接通過關鍵字參數定義多分類方法、正則化手段、優化器等模型設置。在本案例中將訓練兩個多分類邏輯回歸模型,分別采用L1和L2正則化手段,設定相同的正則化系數。選擇SAGA算法作為求解器,該算法是SAG(StochasticAverageGradient)算法的加速版本。當樣本數量遠大于特征數量時,該求解器的速度很快,并且能夠優化如L1正則項這樣非光滑目標函數。上述這些在模型開始訓練學習前設置的相關參數也被稱作“超參數”,其不是通過訓練學習得到而是通過人工或網格搜索等技術得到。在機器學習實戰中常提及的“調參”實質上就是對超參數選取的調整。帶正則化的分類器#構建帶有L1正則化的邏輯回歸模型>>>clf_L1=LogisticRegression(C=0.0001,...penalty="l1",...multi_class="multinomial",...solver="saga")#訓練帶有L1正則化的邏輯回歸模型>>>clf_L1.fit(X_train,y_train)#構建帶有L2正則化的邏輯回歸模型>>>clf_L1=LogisticRegression(C=0.0001,...penalty="l2",...multi_class="multinomial",...solver="saga")#訓練帶有L2正則化的邏輯回歸模型>>>clf_L1.fit(X_train,y_train)結果分析在完成模型訓練后,可以通過測試數據對模型的預測結果開展分析。在此案例中,重點關注模型的稀疏性與其在驗證集上分類的正確性。下列代碼接受訓練好的模型為輸入,統計模型中權重為0的權重個數,通過百分比計算其稀疏性,使用score()方法對計算驗證集上模型預測與實際標簽的平均準確度進行打印。>>>defscore_print(model,penalty_name):...sparsity=np.mean(model.coef_==0)*100...score=model.score(X_val,y_val)...print("帶%s懲罰項邏輯回歸的稀疏性:%.2f%%"%(penalty_name,sparsity))...print("帶%s懲罰項邏輯回歸的驗證集分數:%.4f"%(penalty_name,score))>>>score_print(clf_L1,'L1')帶L1懲罰項邏輯回歸的稀疏性:85.83%帶L1懲罰項邏輯回歸的驗證集分數:0.9087>>>score_print(clf_L2,'L2')帶L2懲罰項邏輯回歸的稀疏性:8.29%帶L2懲罰項邏輯回歸的驗證集分數:0.9204L1邏輯回歸權重可視化通過可視化分類向量的權重可以進一步探究模型的稀疏性。由于該問題有10個類別,因此權重對應為(10,784),每一項代表一個對應的分類。下列代碼定義了繪制各個類別權重的函數。其使用coef方法獲得模型的權重,構建包含2行5列10張子圖的畫布,對每個類別繪制其對應的權重圖像,>>>defplot_classification_vector(model,title):...coef=model.coef_.copy()...plt.figure(figsize=(12,4))...scale=np.abs(coef).max()...foriinrange(10):...sub_plot=plt.subplot(2,5,i+1)...sub_plot.imshow(coef[i].reshape(28,28),...interpolation="nearest",...cmap=plt.cm.RdGy,...vmin=-scale,vmax=scale)...sub_plot.set_xticks([])...sub_plot.set_yticks([])...sub_plot.set_xlabel("數字%i"%i)...plt.suptitle(title)...plt.show()e)>>>plot_classification_vector(clf_L1,'L1邏輯回歸的分類向量')L2邏輯回歸權重可視化>>>plot_classification_vector(clf_L2,'L2邏輯回歸的分類向量')混淆矩陣在監督學習中,可以通過混淆矩陣(也稱誤差矩陣)的方式可視化評價分類的精度。其縱軸為真實值的類別,橫軸為預測值的類別,可以直觀地展示多個類別是否有混淆(即其中一個類別被預測為其他類別),從而明確了解分類模型的表現。在矩陣中,對角線上的位置表示正確分類的類別數量,對角線以外的位置為模型對該樣本預測錯誤。在sklearn.metrics中封裝了根據預測數據與真實標簽顯示混淆矩陣的方法,下列函數對其進行了封裝。>>>defplot_confusion_matrix(predict,label,title):...disp=metrics.ConfusionMatrixDisplay.from_predictions(label,predict)...disp.figure_.suptitle(title)...plt.show()混淆矩陣>>>predict_l1=clf_L1.predict(X_val)>>>plot_confusion_matrix(predict_l1,y_val,'L1邏輯回歸混淆矩陣')>>>predict_l2=clf_L2.predict(X_val)>>>plot_confusion_matrix(predict_l2,y_val,'L2邏輯回歸混淆矩陣')結果可視化除此之外,還可以通過定性地可視化分析來直觀感受模型在哪些樣本上出現了錯誤分類。下列代碼定義了可視化模型在數據集上錯誤分類樣本圖像的函數。其首先利用NumPy的高級索引計算模型在驗證集上的預測值與標簽值不相等樣本的索引。再繪制包含4行4列16個子圖的畫布,可視化驗證集中分類錯誤的前16個樣本,并以每個樣本的真實值與預測值為對應子圖的標題。>>>defplot_wrong_digits(clf,data,label,title):...#計算預測錯誤樣本的索引...index=np.arange(0,label.shape[0])...target=clf.predict(data)...wrong_index=index[target!=label]...#可視化圖像...plt.figure(figsize=(12,12))...foriinrange(16):...plt.subplot(4,4,i+1)...plt.imshow(data[wrong_index[i]].reshape(28,28),cmap='gray',interpolation='none')...plt.title("真實值:{}\n預測值:{}".format(label[wrong_index[i]],target[wrong_index[i]]))...plt.xticks([])...plt.yticks([])...plt.suptitle(title)...plt.tight_layout()...plt.show()結果可視化>>>plot_wrong_digits(clf_L1,X_val,y_val,'L1邏輯回歸驗證集中預測錯誤的樣本')>>>plot_wrong_digits(clf_L2,X_val,y_val,'L2邏輯回歸驗證集中預測錯誤的樣本')實例:交通車流量預測01問題分析城市化的推進顯著提高了城市居民出行的機動化率,但交通擁堵、交通安全、環境污染、能源消耗等現象與問題也日益突出。準確可靠的交通流量預測可以為政府的工作與車主的出行規劃提供極大的幫助,并有效預防一系列交通問題。交通流量實際上是一種具有周期性、時空性的數據,在擁有足夠數據樣本時,可以通過機器學習的方法對交通流量的數據模式進行分析與識別,從而達到預測該路段未來車流量的目的。在本節案例中,將基于某路段的交通車流量數據集,建立能夠預測車流量的機器學習回歸模型。模塊導入與設置本案例中將使用到如下的庫與模塊,首先將其進行導入同時,本案例的可視化分析涉及到中文的使用,需要進行設置>>>importnumpyasnp>>>importpandasaspd>>>importmatplotlib.pyplotasplt>>>fromsklearnimportmetrics>>>fromsklearn.kernel_ridgeimportKernelRidge>>>fromsklearn.preprocessingimportMinMaxScale>>>plt.rcParams['font.sans-serif']=['SimHei']>>>plt.rcParams['axes.unicode_minus']=False車流量數據讀取本案例中使用到的交通車流量數據保存在“Traffic_flow.csv”文件中,首先使用如下代碼將該csv文件通過pandas讀取為DataFrame對象,以便對數據進行分析與預處理。由于文件中有中文,在讀取時選擇編碼方式為“GB18030”可防止亂碼。>>>df=pd.read_csv('Traffic_flow.csv',encoding='GB18030')>>>df#此語句為在交互環境的顯示方法,在非交互環境中,需輸入print(df)車流量數據分析該數據集一共由五個特征組成,分別是:一天中的第幾個小時:由[0,23]之間的整數構成,指代該條車流量信息所屬于哪一小時;一周中的第幾天:由[0,6]之間的整數構成,其中數字0表示星期天,指代該條車流量信息屬于星期幾;一年中的第幾天:由[0,365]之間的整數構成,指代該條車流量信息屬于哪一天;一年中的幾周:由[0.53]之間的整數構成,指代車該條車流量信息屬于哪一軸;車流量:該小時內路段上經過車輛的數量。>>>df.describe()車流量數據分析僅觀察數字仍無法直觀了解數據集中數據的分布,下列代碼提取車流量特征,將其按照在數據集中的順序,繪制數據集中所有小時車流量的數據>>>data=np.array(df)>>>fig=plt.figure(figsize=(16,6))>>>plt.plot(data[:,4],linewidth=.3)>>>plt.xlim([0,data.shape[0]])>>>plt.xlabel('小時ID')>>>plt.ylabel('車流量')>>>plt.title('交通車流量數據')>>>plt.show()全年周內每小時平均車流量>>>average_week_flow=df.groupby(["一周中的第幾天","一天中的第幾個小時"]).mean()['車流量']>>>fig,ax=plt.subplots(figsize=(12,4))>>>average_week_flow.plot(ax=ax)>>>ax.grid()>>>ax.set(...title='全年周內每小時平均車流量',...xticks=[i*24foriinrange(7)],...xticklabels=["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],...xlabel="星期",...ylabel="平均車流量")>>>plt.show()每小時車流量與最大車流量比例直方圖>>>fig,ax=plt.subplots(figsize=(12,4))>>>fraction=df["車流量"]/df["車流量"].max()>>>fraction.hist(bins=50,ax=ax,alpha=0.5)>>>ax.set(...title='每小時車流量與最大車流量比例直方圖',...xlabel="車流量與最大車流量的比例",...ylabel="小時數")>>>plt.show()數據集預處理在完成數據集的基礎分析后,通過下列代碼構建用于機器學習模型的訓練集與驗證集。其中輸入數據為數據集中除去車流量的剩余四個特征,由于四個特征的數據尺度不一,首先使用sklearn.preprocessing中的MinMaxScaler將其統一縮放至[0,1]區間內,輸出的預測數據采用當前小時車流量與數據集中最大車流量的比值,其取值亦屬于[0,1]之間的區間。在劃分時需要注意該數據集是一種時間序列,即交通流量與時間先后存在關系,因此本案例中不對數據集進行打亂重組。這里設置訓練集與驗證集的比例為9:1。>>>X=df.drop('車流量',axis='columns')>>>y=fraction#將特征數值縮放至[0,1]區間>>>scaler=MinMaxScaler()>>>X_scaler=scaler.fit_transform(X)#劃分數據集函數>>>deftrain_validation_split(X,y,train_size):...data_size=len(y)...idx=int(data_size*train_size)...X_train,X_val=X[:idx,],X[idx:,]...y_train,y_val=y[:idx],y[idx:]...returnX_train,X_val,y_train,y_val#劃分數據集>>>X_train,X_val,y_train,y_val=train_validation_split(X_scaler,y,0.9)交通流量數據集的劃分>>>fig=plt.figure(figsize=(16,6))>>>plt.plot(y_train,'k-',linewidth=.2)>>>plt.plot(y_val,'k-',linewidth=.3)>>>plt.axvspan(y_val.index[0],y_val.index[-1],alpha=0.2,color='red')>>>plt.xlim([0,data.shape[0]])>>>plt.xlabel('小時ID')>>>plt.ylabel('車流量')>>>plt.title('數據集劃分')>>>plt.show()回歸模型的建立本案例中交通車流量預測模型的任務是根據輸入的具體時間段(幾月幾號星期幾第幾個小時),預測此時間段內道路中車流量的情況。不同于9.2節的分類任務,該模型的輸出是連續的數值。在本節中,將在使用機器學習回歸任務中的嶺回歸算法(RidgeRegression)的基礎上,進一步探究核函數對預測結果的影響,實現交通車流量的預測。Scikit-learn內封裝的常用核函數核名稱表達式描述linear線性核函數,等同于多項式核函數階數取1poly多項式核函數,超參數

為多項式的階數rbf徑向基核函數(高斯核函數),超參數

控制徑向作用范圍laplacian拉普拉斯核函數,為徑向基核的變種。計算輸入向量間的曼哈頓距離,超參數

控制徑向作用范圍回歸模型的建立在本案例中,將比較線性核函數、三階多項式核函數、五階多項式核函數、徑向基核函數與拉普拉斯核函數嶺回歸在交通車流量預測上的表現效果>>>defbuild_train_model():...#保存模型的字典...models={}...forkernelin('linear','poly-3','poly-5','rbf','laplacian'):...#多項式核函數需根據名稱中的階數創建模型...if'poly'inkernel:...clf=KernelRidge(kernel='poly',...gamma=2,...degree=int(kernel[-1]))...#其他核函數創建模型...else:...clf=KernelRidge(kernel=kernel,...gamma=2)...#使用訓練集數據訓練模型...clf.fit(X_train,y_train)...#將訓練完畢的模型添加至字典中...models[kernel]=clf...returnmodels#調用構建并生成模型的函數>>>models=build_train_model()>>>print(models){'linear':KernelRidge(gamma=2),'poly-3':KernelRidge(gamma=2,kernel='poly'),'poly-5':KernelRidge(degree=5,gamma=2,kernel='poly'),'rbf':KernelRidge(gamma=2,kernel='rbf'),'laplacian':KernelRidge(gamma=2,kernel='laplacian')}回歸模型的預測分析在Scikit-learn中,在訓練好的模型上使用predict()方法可使模型根據輸入數據做出預測。下列代碼將驗證集的數據作為輸入,在每個模型上進行預測,并將預測結果存儲與字典中,并賦值給result變量。>>>defmaek_predict(models,data):...result={}...forname,modelinmodels.items():...result[name]=model.predict(data)...returnresult#調用定義的函數預測模型在驗證集上的車流量(與最大車流量的比值)>>>result=maek_predict(models,X_val)>>>print(result){'linear':array([0.18524845,0.19716828,0.20908811,...,0.4514431,0.46336293,0.47528275]),'poly-3':array([0.08701442,0.1137189,0.1462421,...,0.32175255,0.23544349,0.12949224]),'poly-5':array([0.08485934,0.09647624,0.12591843,...,0.4118781,0.359178,0.30602133]),'rbf':array([0.0819029,0.09476369,0.12099408,...,0.33193726,0.27503546,0.21360745]),'laplacian':array([0.11717616,0.11492388,0.12071438,...,0.05438403,0.03031455,0.01775509])}定量分析>>>defmodels_score(label,predicts):...models_score={}...defcalculate_score(label,predicted):...score={}...score['r2']=metrics.r2_score(label,predicted)...score['mae']=metrics.mean_absolute_error(label,predicted)...score['mse']=metrics.mean_squared_error(label,predicted)...score['max']=metrics.max_error(label,predicted)...returnscore...forname,predictinpredicts.items():...models_score[name]=calculate_score(label,predict)...returnmodels_score#調用定義的函數計算模型的指標參數>>>models_score=models_score(y_val,result)#打印參數數據>>>print(models_score){'linear':{'r2':-19.436096247431077,'mae':0.3346218294413336,'mse':0.6618504152595966,'max':3.57772707239244},'poly-3':{'r2':-56.60262397328022,'mae':0.3885366260368387,'mse':1.8655383168666728,'max':8.888473221178035},'poly-5':{'r2':-40.6707308598833,'mae':0.32196263633066846,'mse':1.3495625676186356,'max':7.959323333043722},'rbf':{'r2':0.38350252495691983,'mae':0.09019113777631395,'mse':0.01996609846242267,'max':0.7053440761732674},'laplacian':{'r2':0.49158932589217763,'mae':0.08529234896469771,'mse':0.01646556229265031,'max':0.5391318333405098}}五種核函數嶺回歸模型在驗證集上的指標表現>>>colors=['grey','gold','darkviolet','turquoise','salmon']>>>x_label=['線性','三階多項式','五階多項式','徑向基','拉普拉斯']#構建畫布>>>fig,ax=plt.subplots(2,2,figsize=(12,12))#構建平均絕對誤差MAE>>>bar_mae=ax[0,0].bar(models_score.keys(),[i['mae']foriinmodels_score.values()],color=colors,alpha=0.7)>>>ax[0,0].bar_label(bar_mae,padding=2,fmt="%.3f")>>>ax[0,0].set(title='驗證集平均絕對誤差',...xticklabels=x_label)>>>ax[0,0].grid(axis='y',linestyle='-.',linewidth=0.5)#均方誤差MSE>>>bar_mse=ax[0,1].bar(models_score.keys(),[i['mse']foriinmodels_score.values()],color=colors,alpha=0.7)>>>ax[0,1].bar_label(bar_mse,padding=2,fmt="%.3f")>>>ax[0,1].set(title='驗證集均方誤差',...xticklabels=x_label)>>>ax[0,1].grid(axis='y',linestyle='-.',linewidth=0.5)#最大誤差Max_error>>>bar_max=ax[1,0].bar(models_score.keys(),[i['max']foriinmodels_score.values()],color=colors,alpha=0.7)>>>ax[1,0].bar_label(bar_max,padding=2,fmt="%.3f")>>>ax[1,0].set(title='驗證集最大誤差',...xticklabels=x_label)>>>ax[1,0].grid(axis='y',linestyle='-.',linewidth=0.5)#R2分數>>>

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論