機器學習概述
機器學習(Machine Learning, ML)主要研究計算機系統對于特定任務的性能,逐步進行改善的算法和統計模型。通過輸入海量訓練數據對模型進行訓練,使模型掌握數據所蘊含的潛在規律,進而對新輸入的數據進行準確的分類或預測。
機器學習是一門多領域交叉學科,涉及概率論、統計學、逼近論、凸優化、算法復雜度理論等多門學科。
人工智能、機器學習與深度學習
人工智能(AI)是計算機科學的一個廣泛領域,目標是讓機器具備類人的“智能”,包括自然語言處理(NLP)、計算機視覺、機器人技術、專家系統等等;具體實現手段多種多樣,包括規則系統、符號邏輯、統計方法、機器學習等。
機器學習是AI的一個子領域,核心是通過數據驅動,讓計算機進行學習并改進性能,自動發現規律(模式),并利用這些規律進行預測或決策。
深度學習是機器學習的一個子領域,基于多層神經網絡處理復雜任務。
發展歷史(了解)
早期探索:20世紀50-70年代
人工智能研究處于“推理期”,人們認為只要能賦予機器邏輯推理能力,機器就能具有智能。
圖靈提出“圖靈測試”,定義機器智能的基本標準
弗蘭克·羅森布拉特提出感知機算法,這是最早的人工神經網絡模型之一,用于線性分類問題
亞瑟·李·塞謬爾提出“機器學習”一詞,并設計了一個用于玩跳棋的學習算法
知識驅動與專家系統:20世紀70-80年代
隨著研究推進,人們逐漸認識到,僅具有邏輯推理能力是遠遠實現不了人工智能的。部分人認為,要使機器具有智能,就必須設法使機器擁有知識。計算機硬件逐步發展,人工智能的研究進入以規則為主的“知識驅動”階段。
出現眾多專家系統,如MYCIN(用于醫療診斷)
引入了決策樹(如ID3算法)
統計學習理論開始成形,例如貝葉斯定理在機器學習中的應用
數據驅動與統計學習:20世紀80年代-21世紀
專家系統面臨“知識工程瓶頸”。機器學習成為一個獨立的學科領域,各種機器學習技術百花初綻。基于神經網絡的連接主義逐步發展,但其局限性也開始凸顯。統計學習登場并占據主流,代表技術是支持向量機。互聯網的發展帶來了大量數據,統計學方法逐漸成為機器學習的核心。
決策樹算法得到進一步發展(如C4.5算法)
支持向量機(SVM)被提出,成為一種強大的分類工具
無監督學習方法開始成熟,例如K-means聚類
隨機森林和Boosting方法(如AdaBoost)引入,提升了集成學習的性能
深度學習崛起:21世紀初
隨著計算能力(特別是GPU的發展)和數據規模的快速增長,深度學習技術得以崛起。深度神經網絡主導,突破了圖像、語音和文本領域的性能瓶頸。
深度信念網絡(DBN)被提出,標志著深度學習研究的復興
AlexNet在ImageNet圖像分類競賽中獲勝,證明了卷積神經網絡(CNN)的強大性能
生成對抗網絡(GAN)被提出,用于生成圖像和其他生成任務
Transformer架構在論文《Attention is All You Need》中提出,徹底改變了自然語言處理領域
大模型與通用人工智能:2020年代
深度學習進入規模化應用階段,大語言模型和多模態模型的出現推動了機器學習的新高潮。模型參數規模空前,技術以通用性和泛化能力為目標。
自然語言處理:如OpenAI的GPT系列模型、Google的BERT
多模態模型:如OpenAI的CLIP、DeepMind的Gato
自監督學習成為重要方向,降低了對人工標注數據的依賴
強化學習和深度學習結合,應用于AlphaGo、AlphaFold等項目
機器學習應用領域
今天,在計算機科學的諸多分支學科領域中,無論是多媒體、圖形學,還是網絡通信、軟件工程,乃至體系結構、芯片設計,都能找到機器學習技術的身影,尤其是在計算機視覺、自然語言處理等計算機應用技術領域,機器學習已成為最重要的技術進步源泉之一,并為許多交叉學科提供了重要的技術支撐。
基本術語
數據集(Data Set):多條記錄的集合。
訓練集(Tra條記錄是關于一個事件或對象的描述,稱為一個樣本。
特征(Feature):數據集中一列反映事件或對象在某方面的表現或性質的事項,稱為特征或屬性。
特征向量(Feature Vector):將樣本的所有特征表示為向量的形式,輸入到模型中。
標簽(Label):監督學習中每個樣本的結果信息,也稱作目標值(target)。
模型(Model):一個機器學習算法與訓練后的參數集合,用于進行預測或分類。
參數(Parameter):模型通過訓練學習到的值,例如線性回歸中的權重和偏置。
超參數(Hyper Parameter):由用戶設置的參數,不能通過訓練自動學習,例如學習率、正則化系數等。
機器學習基本理論
機器學習三要素
機器學習的方法一般主要由三部分構成:模型、策略和算法,可以認為:
機器學習方法 = 模型 + 策略 + 算法
模型(model):總結數據的內在規律,用數學語言描述的參數系統
策略(strategy):選取最優模型的評價準則
算法(algorithm):選取最優模型的具體方法
機器學習方法分類
機器學習的方法種類繁多,并不存在一個統一的理論體系能夠涵蓋所有內容。從不同的角度,可以將機器學習的方法進行不同的分類:
通常分類:按照有無監督,機器學習可以分為 有監督學習、無監督學習 和 半監督學習,除此之外還有 強化學習。
按模型分類:根據模型性質,可以分為概率模型/非概率模型,線性/非線性模型等。
按學習技巧分類:根據算法基于的技巧,可以分為貝葉斯學習、核方法等。
各種類型的機器學習方法可以用下圖匯總展示:
建模流程
我們可以以監督學習為例,考察一下機器學習的具體過程。
可以看到,機器學習是由數據驅動的,核心是利用數據來“訓練模型”;模型訓練的結果需要用一定的方法來進行評估、優化,最終得到一個成熟的學習模型;最后就可以用這個模型來進行預測和解決問題了。
總結監督學習建模的整體流程如下:
特征工程
什么是特征工程
特征工程(Feature Engineering)是機器學習過程中非常重要的一步,指的是通過對原始數據的處理、轉換和構造,生成新的特征或選擇有效的特征,從而提高模型的性能。簡單來說,特征工程是將原始數據轉換為可以更好地表示問題的特征形式,幫助模型更好地理解和學習數據中的規律。優秀的特征工程可以顯著提高模型的表現;反之,忽視特征工程可能導致模型性能欠佳。
實際上,特征工程是一個迭代過程。特征工程取決于具體情境。它需要大量的數據分析和領域知識。其中的原因在于,特征的有效編碼可由所用的模型類型、預測變量與輸出之間的關系以及模型要解決的問題來確定。在此基礎上,輔以不同類型的數據集(如文本與圖像)則可能更適合不同的特征工程技術。因此,要具體說明如何在給定的機器學習算法中最好地實施特征工程可能并非易事。
特征工程的內容
特征選擇
從原始特征中挑選出與目標變量關系最密切的特征,剔除冗余、無關或噪聲特征。這樣可以減少模型的復雜度、加速訓練過程、并減少過擬合的風險。
特征選擇不會創建新特征,也不會改變數據結構。
過濾法(Filter Method)
基于統計測試(如卡方檢驗、相關系數、信息增益等)來評估特征與目標變量之間的關系,選擇最相關的特征。
包裹法(Wrapper Method)
使用模型(如遞歸特征消除 RFE)來評估特征的重要性,并根據模型的表現進行特征選擇。
嵌入法(Embedded Method)
使用模型本身的特征選擇機制(如決策樹的特征重要性,L1正則化的特征選擇)來選擇最重要的特征。
特征轉換
對數據進行數學或統計處理,使其變得更加適合模型的輸入要求。
歸一化(Normalization)
將特征縮放到特定的范圍(通常是0到1之間)。適用于對尺度敏感的模型(如KNN、SVM)。
標準化(Standardization)
通過減去均值并除以標準差,使特征的分布具有均值0,標準差1。
對數變換
對于有偏態的分布(如收入、價格等),對數變換可以將其轉化為更接近正態分布的形式。
類別變量的編碼
獨熱編碼(One-Hot Encoding):將類別型變量轉換為二進制列,常用于無序類別特征。
標簽編碼(Label Encoding):將類別型變量映射為整數,常用于有序類別特征。
目標編碼(Target Encoding):將類別變量的每個類別替換為其對應目標變量的平均值或其他統計量。
頻率編碼(Frequency Encoding):將類別變量的每個類別替換為該類別在數據集中的出現頻率。
特征構造
特征構造是基于現有的特征創造出新的、更有代表性的特征。通過組合、轉換、或者聚合現有的特征,形成能夠更好反映數據規律的特征。
交互特征
將兩個特征組合起來,形成新的特征。例如,兩個特征的乘積、和或差等。
例如,將年齡與收入結合創建新的特征,可能能更好地反映某些模式。
統計特征
從原始特征中提取統計值,例如求某個時間窗口的平均值、最大值、最小值、標準差等。
例如,在時間序列數據中,你可以從原始數據中提取每個小時、每日的平均值。
日期和時間特征
從日期時間數據中提取如星期幾、月份、年份、季度等特征。
例如,將“2000-01-01”轉換為“星期幾”、“是否節假日”、“月初或月末”等特征。
特征降維
當數據集的特征數量非常大時,特征降維可以幫助減少計算復雜度并避免過擬合。通過降維方法,可以在保持數據本質的情況下減少特征的數量。
主成分分析(PCA)
通過線性變換將原始特征映射到一個新的空間,使得新的特征(主成分)盡可能地保留數據的方差。
線性判別分析(LDA)
一種監督學習的降維方法,通過最大化類間距離與類內距離的比率來降維。
t-SNE(t-Distributed Stochastic Neighbor Embedding,t分布隨機近鄰嵌入)
一種非線性的降維技術,特別適合可視化高維數據。
自編碼器(Auto Encoder)
一種神經網絡模型,通過壓縮編碼器來實現數據的降維。
常用方法
對于一個模型來說,有些特征可能很關鍵,而有些特征可能用處不大。
例如:
某個特征取值較接近,變化很小,可能與結果無關。
某幾個特征相關性較高,可能包含冗余信息。
因此,特征選擇 在特征工程中是最基本、也最常見的操作。
另外,在訓練模型時有時也會遇到維度災難,即特征數量過多。我們希望能在確保不丟失重要特征的前提下減少維度的數量,來降低訓練模型的難度。所以在特征工程中,也經常會用到 特征降維 方法。
低方差過濾法
對于特征的選擇,可以直接基于方差來判斷,這是最簡單的。低方差的特征意味著該特征的所有樣本值幾乎相同,對預測影響極小,可以將其去掉。
from sklearn.feature_selection import VarianceThreshold
低方差過濾:刪除方差低于 0.01 的特征
var_thresh = VarianceThreshold(threshold=0.01)
X_filtered = var_thresh.fit_transform(X)
相關系數法
通過計算特征與目標變量或特征之間的相關性,篩選出高相關性特征(與目標相關)或剔除冗余特征(特征間高度相關)。
皮爾遜相關系數
皮爾遜相關系數(Pearson Correlation)用于衡量兩個變量的線性相關性,取值范圍[-1,1]。
r=(∑_(i=1)^n?(x_i-x ? )(y_i-y ? ) )/(√(∑_(i=1)^n?(x_i-x ? )^2 ) √(∑_(i=1)^n?(y_i-y ? )^2 ))
正相關:值接近1,說明特征隨目標變量增加而增加。
負相關:值接近-1,說明特征隨目標變量增加而減少。
無關:值接近0,說明特征和目標變量無明顯關系。
例如,現有一數據集包括不同渠道廣告投放金額與銷售額。
使用pandas.DataFrame.corrwith(method=“pearson”)計算各個特征與標簽間的皮爾遜相關系數。
import pandas as pd
advertising = pd.read_csv(“data/advertising.csv”)
advertising.drop(advertising.columns[0], axis=1, inplace=True)
advertising.dropna(inplace=True)
X = advertising.drop(“Sales”, axis=1)
y = advertising[“Sales”]
計算皮爾遜相關系數
print(X.corrwith(y, method=“pearson”))
TV 0.782224
Radio 0.576223
Newspaper 0.228299
dtype: float64
使用pandas.DataFrame.corr(method=“pearson”)計算皮爾遜相關系數矩陣。
import seaborn as sns
import matplotlib.pyplot as plt
計算皮爾遜相關系數矩陣
corr_matrix = advertising.corr(method=“pearson”)
可視化熱力圖
sns.heatmap(corr_matrix, annot=True, cmap=“coolwarm”, fmt=“.2f”)
plt.title(“Feature Correlation Matrix”)
plt.show()
斯皮爾曼相關系數
斯皮爾曼相關系數(Spearman’s Rank Correlation Coefficient)的定義是等級變量之間的皮爾遜相關系數。用于衡量兩個變量之間的單調關系,即當一個變量增加時,另一個變量是否總是增加或減少(不要求是線性關系)。適用于非線性關系或數據不符合正態分布的情況。
r_s=1-(6∑d_i2)/(n(n2-1))
其中:
d_i是兩個變量的等級之差
n是樣本數
斯皮爾曼相關系數的取值范圍為[-1,1]:
ρ=1:完全正相關(一個變量增加,另一個變量也總是增加)。
ρ=-1:完全負相關(一個變量增加,另一個變量總是減少)。
ρ=0:無相關性。
例如,現有一組每周學習時長與數學考試成績的數據:
■(X&y@5&55@8&65@10&70@12&75@15&85@3&50@7&60@9&72@14&80@6&58)
按數值由小到大排出X、y的等級,并計算等級差:
■(X&R_X&y&R_y&d=R_X-R_y&d^2@5&2&55&2&0&0@8&5&65&5&0&0@10&7&70&6&1&1@12&8&75&8&0&0@15&10&85&10&0&0@3&1&50&1&0&0@7&4&60&4&0&0@9&6&72&7&-1&1@14&9&80&9&0&0@6&3&58&3&0&0)
ρ=1-(6∑d_i2)/n(n2-1) =1-(6×2)/10(10^2-1) =1-0.0121=0.9879
使用pandas.DataFrame.corrwith(method=“spearman”)計算斯皮爾曼相關系數。
import pandas as pd
每周學習時長
X = [[5], [8], [10], [12], [15], [3], [7], [9], [14], [6]]
數學考試成績
y = [55, 65, 70, 75, 85, 50, 60, 72, 80, 58]
計算斯皮爾曼相關系數
X = pd.DataFrame(X)
y = pd.Series(y)
print(X.corrwith(y, method=“spearman”))
0.987879
主成分分析(PCA)
主成分分析(Principal Component Analysis,PCA)是一種常用的降維技術,通過線性變換將高維數據投影到低維空間,同時保留數據的主要變化模式。
使用sklearn.decomposition.PCA進行主成分分析。參數n_components若為小數則表示保留多少比例的信息,為整數則表示保留多少個維度。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
n_samples = 1000
第1個主成分方向
component1 = np.random.normal(0, 1, n_samples)
第2個主成分方向
component2 = np.random.normal(0, 0.2, n_samples)
第3個方向(噪聲,方差較小)
noise = np.random.normal(0, 0.1, n_samples)
構造3維數據
X = np.vstack([component1 - component2, component1 + component2, component2 + noise]).T
標準化
scaler = StandardScaler()
X_standardized = scaler.fit_transform(X)
應用PCA,將3維數據降維到2維
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_standardized)
可視化
轉換前的3維數據可視化
fig = plt.figure(figsize=(12, 4))
ax1 = fig.add_subplot(121, projection=“3d”)
ax1.scatter(X[:, 0], X[:, 1], X[:, 2], c=“g”)
ax1.set_title(“Before PCA (3D)”)
ax1.set_xlabel(“Feature 1”)
ax1.set_ylabel(“Feature 2”)
ax1.set_zlabel(“Feature 3”)
轉換后的2維數據可視化
ax2 = fig.add_subplot(122)
ax2.scatter(X_pca[:, 0], X_pca[:, 1], c=“g”)
ax2.set_title(“After PCA (2D)”)
ax2.set_xlabel(“Principal Component 1”)
ax2.set_ylabel(“Principal Component 2”)
plt.show()
模型評估和模型選擇(重點)
損失函數
對于模型一次預測結果的好壞,需要有一個度量標準。
對于監督學習而言,給定一個輸入X,選取的模型就相當于一個“決策函數”f,它可以輸出一個預測結果f(X),而真實的結果(標簽)記為Y。f(X) 和Y之間可能會有偏差,我們就用一個損失函數(loss function)來度量預測偏差的程度,記作 L(Y,f(X))。
損失函數用來衡量模型預測誤差的大小;損失函數值越小,模型就越好;
損失函數是f(X)和Y的非負實值函數;
常見的損失函數有:
0-1損失函數
L(Y,f(X))={█(1,Y≠f(X)@0,Y=f(X))┤
平方損失函數
L(Y,f(X))=〖(Y-f(X))〗^2
絕對損失函數
L(Y,f(X))=|Y-f(X)|
對數似然損失函數
L(Y,P(Y|X))=-logP(Y|X)
經驗誤差
給定一個訓練數據集,數據個數為n:
T={(x_1,y_1 ),(x_2,y_2 ),…,(x_n,y_n )}
根據選取的損失函數,就可以計算出模型f(X)在訓練集上的平均誤差,稱為訓練誤差,也被稱作 經驗誤差(empirical error) 或 經驗風險(empirical risk)。
R_emp (f)=1/n ∑_(i=1)^n?〖L(y_i,f(x_i))〗
類似地,在測試數據集上平均誤差,被稱為測試誤差或者 泛化誤差(generalization error)。
一般情況下對模型評估的策略,就是考察經驗誤差;當經驗風險最小時,就認為取到了最優的模型。這種策略被稱為 經驗風險最小化(empirical risk minimization,ERM)。
欠擬合與過擬合
擬合(Fitting)是指機器學習模型在訓練數據上學習到規律并生成預測結果的過程。理想情況下,模型能夠準確地捕捉訓練數據的模式,并且在未見過的新數據(測試數據)上也有良好的表現;即模型具有良好的 泛化能力。
欠擬合(Underfitting):是指模型在訓練數據上表現不佳,無法很好地捕捉數據中的規律。這樣的模型不僅在訓練集上表現不好,在測試集上也同樣表現差。
過擬合(Overfitting):是指模型在訓練數據上表現得很好,但在測試數據或新數據上表現較差的情況。過擬合的模型對訓練數據中的噪聲或細節過度敏感,把訓練樣本自身的一些特點當作了所有潛在樣本都會具有的一般性質,從而失去了泛化能力。
產生欠擬合和過擬合的根本原因,是模型的復雜度過低或過高,從而導致測試誤差(泛化誤差)偏大。
欠擬合:模型在訓練集和測試集上誤差都比較大。模型過于簡單,高偏差。
過擬合:模型在訓練集上誤差較小,但在測試集上誤差較大。模型過于復雜,高方差。
產生原因與解決辦法
欠擬合
產生原因:
模型復雜度不足:模型過于簡單,無法捕捉數據中的復雜關系。
特征不足:輸入特征不充分,或者特征選擇不恰當,導致模型無法充分學習數據的模式。
訓練不充分:訓練過程中迭代次數太少,模型沒有足夠的時間學習數據的規律。
過強的正則化:正則化項設置過大,強制模型過于簡單,導致模型無法充分擬合數據。
解決辦法:
增加模型復雜度:選擇更復雜的模型。
增加特征或改進特征工程:添加更多的特征或通過特征工程來創造更有信息量的特征。
增加訓練時間:增加訓練的迭代次數,讓模型有更多機會去學習。
減少正則化強度:如果使用了正則化,嘗試減小正則化的權重,以讓模型更靈活。
過擬合
產生原因:
模型復雜度過高:模型過于復雜,參數太多。
訓練數據不足:數據集太小,模型能記住訓練數據的細節,但無法泛化到新數據。
特征過多:特征太多,模型可能會“記住”數據中的噪聲,而不是學到真正的規律。
訓練過長:訓練時間過長,導致模型學習到訓練數據中的噪聲,而非數據的真正規律。
解決辦法:
減少模型復雜度:降低模型的參數數量、使用簡化的模型或降維來減小模型復雜度。
增加訓練數據:收集更多數據,或通過數據增強來增加訓練數據的多樣性。
使用正則化:引入L1、L2正則化,避免過度擬合訓練數據。
交叉驗證:使用交叉驗證技術評估模型在不同數據集上的表現,以減少過擬合的風險。
早停:訓練時,當模型的驗證損失不再下降時,提前停止訓練,避免過度擬合訓練集。
代碼演示
使用多項式在x∈[-3,3]上擬合sin(x):
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
plt.rcParams[“font.sans-serif”] = [“KaiTi”]
plt.rcParams[“axes.unicode_minus”] = False
def polynomial(x, degree):
“”“構成多項式,返回 [x1,x2,x3,…,xn]”“”
return np.hstack([x**i for i in range(1, degree + 1)])
生成隨機數據
X = np.linspace(-3, 3, 300).reshape(-1, 1)
y = np.sin(X) + np.random.uniform(-0.5, 0.5, 300).reshape(-1, 1)
fig, ax = plt.subplots(1, 3, figsize=(15, 4))
ax[0].plot(X, y, “yo”)
ax[1].plot(X, y, “yo”)
ax[2].plot(X, y, “yo”)
劃分訓練集和測試集
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
創建線性回歸模型
model = LinearRegression()
欠擬合
x_train1 = x_train
x_test1 = x_test
model.fit(x_train1, y_train) # 模型訓練
y_pred1 = model.predict(x_test1) # 預測
ax[0].plot(np.array([[-3], [3]]), model.predict(np.array([[-3], [3]])), “c”) # 繪制曲線
ax[0].text(-3, 1, f"測試集均方誤差:{mean_squared_error(y_test, y_pred1):.4f}“)
ax[0].text(-3, 1.3, f"訓練集均方誤差:{mean_squared_error(y_train, model.predict(x_train1)):.4f}”)
恰好擬合
x_train2 = polynomial(x_train, 5)
x_test2 = polynomial(x_test, 5)
model.fit(x_train2, y_train) # 模型訓練
y_pred2 = model.predict(x_test2) # 預測
ax[1].plot(X, model.predict(polynomial(X, 5)), “k”) # 繪制曲線
ax[1].text(-3, 1, f"測試集均方誤差:{mean_squared_error(y_test, y_pred2):.4f}“)
ax[1].text(-3, 1.3, f"訓練集均方誤差:{mean_squared_error(y_train, model.predict(x_train2)):.4f}”)
過擬合
x_train3 = polynomial(x_train, 20)
x_test3 = polynomial(x_test, 20)
model.fit(x_train3, y_train) # 模型訓練
y_pred3 = model.predict(x_test3) # 預測
ax[2].plot(X, model.predict(polynomial(X, 20)), “r”) # 繪制曲線
ax[2].text(-3, 1, f"測試集均方誤差:{mean_squared_error(y_test, y_pred3):.4f}“)
ax[2].text(-3, 1.3, f"訓練集均方誤差:{mean_squared_error(y_train, model.predict(x_train3)):.4f}”)
plt.show()
當多項式次數較低時,模型過于簡單,擬合效果較差。
當多項式次數增加后,模型復雜度適中,擬合效果較好,訓練誤差和測試誤差均較低。
當多項式次數繼續增加,模型變得過于復雜,過度學習了噪聲,導致訓練誤差較低而測試誤差較高。
正則化
正則化(Regularization)是一種在訓練機器學習模型時,在損失函數中添加額外項,來懲罰過大的參數,進而限制模型復雜度、避免過擬合,提高模型泛化能力的技術。
如在平方損失函數中加入正則化項 λ∑_(i=1)k?〖ω_i〗2 :
Loss=1/n (∑_(i=1)n?〖(f(x_i)-y_i)〗2 +λ∑_(i=1)k?〖ω_i〗2 )
原損失函數 ∑_(i=1)n?〖(f(x_i)-y_i)〗2 的目的:更好的擬合數據集。
正則化項 λ∑_(i=1)k?〖〖ω_i〗2 〗的目的:減小參數的大小,從而降低模型的復雜度。
這里的 λ 是 正則化系數,用來表示懲罰項的權重。正則化系數不屬于模型的參數,無法通過訓練學習得到,需要在模型訓練開始之前手動設置,這種參數被稱為“超參數”。
兩者相互平衡,在模型的擬合能力(偏差)和復雜度之間找到最佳折中。
常見的正則化技術有L1正則化和L2正則化。
L1正則化(Lasso回歸)
L1正則化在損失函數中加入參數的絕對值之和:
〖Loss〗L1=原Loss+λ∑(i=1)^k?|ω_i |
L1正則化通過懲罰模型參數的絕對值,使得部分權重趨近0甚至變為0。這會導致特征選擇,即模型會自動“丟棄”一些不重要的特征。L1正則化有助于創建稀疏模型(即許多參數為0)。在解決回歸問題時,使用L1正則化也被稱為“Lasso回歸”。
λ 超參數控制著正則化的強度。較大的 λ 值意味著強烈的正則化,會使模型更簡單,可能導致欠擬合。而較小的 λ 值則會使模型更復雜,可能導致過擬合。
L2正則化(Ridge回歸,嶺回歸)
L2正則化在損失函數中加入參數的平方之和:
〖Loss〗L2=原Loss+λ∑(i=1)k?〖ω_i〗2
L2正則化通過懲罰模型參數的平方,使得所有參數都變得更小,但不會將參數強行壓縮為0。它會使得模型盡量平滑,從而防止過擬合。
在解決回歸問題時,使用L2正則化也被稱為“嶺回歸”。
ElasticNet正則化(彈性網絡回歸)
ElasticNet正則化結合了L1和L2正則化,通過調整兩個正則化項的比例來取得平衡,從而同時具備稀疏性和穩定性的優點。
〖Loss〗ElasticNet=原Loss+λ(α∑(i=1)^n?|ω_i | +(1-α)/2 ∑_(i=1)n?〖ω_i〗2 )
α∈[0,1],決定L1和L2的權重。
正則化案例
同樣以使用多項式在x∈[-3,3]上擬合sin(x)為例,分別不使用正則化、使用L1正則化、使用L2正則化進行擬合。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, Lasso, Ridge
from sklearn.metrics import mean_squared_error
plt.rcParams[“font.sans-serif”] = [“KaiTi”]
plt.rcParams[“axes.unicode_minus”] = False
def polynomial(x, degree):
“”“構成多項式,返回 [x1,x2,x3,…,xn]”“”
return np.hstack([x**i for i in range(1, degree + 1)])
生成隨機數據
X = np.linspace(-3, 3, 300).reshape(-1, 1)
y = np.sin(X) + np.random.uniform(-0.5, 0.5, X.size).reshape(-1, 1)
fig, ax = plt.subplots(2, 3, figsize=(15, 8))
ax[0, 0].plot(X, y, “yo”)
ax[0, 1].plot(X, y, “yo”)
ax[0, 2].plot(X, y, “yo”)
劃分訓練集和測試集
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
x_train1 = polynomial(x_train, 20)
x_test1 = polynomial(x_test, 20)
擬合
model = LinearRegression()
model.fit(x_train1, y_train) # 模型訓練
y_pred3 = model.predict(x_test1) # 預測
ax[0, 0].plot(X, model.predict(polynomial(X, 20)), “r”) # 繪制曲線
ax[0, 0].text(-3, 1, f"測試集均方誤差:{mean_squared_error(y_test, y_pred3):.4f}")
ax[1, 0].bar(np.arange(20), model.coef_.reshape(-1)) # 繪制所有系數
L1正則化-Lasso回歸
lasso = Lasso(alpha=0.01)
lasso.fit(x_train1, y_train) # 模型訓練
y_pred3 = lasso.predict(x_test1) # 預測
ax[0, 1].plot(X, lasso.predict(polynomial(X, 20)), “r”) # 繪制曲線
ax[0, 1].text(-3, 1, f"測試集均方誤差:{mean_squared_error(y_test, y_pred3):.4f}")
ax[0, 1].text(-3, 1.2, “Lasso回歸”)
ax[1, 1].bar(np.arange(20), lasso.coef_) # 繪制所有系數
L2正則化-嶺回歸
ridge = Ridge(alpha=1)
ridge.fit(x_train1, y_train) # 模型訓練
y_pred3 = ridge.predict(x_test1) # 預測
ax[0, 2].plot(X, ridge.predict(polynomial(X, 20)), “r”) # 繪制曲線
ax[0, 2].text(-3, 1, f"測試集均方誤差:{mean_squared_error(y_test, y_pred3):.4f}")
ax[0, 2].text(-3, 1.2, “嶺回歸”)
ax[1, 2].bar(np.arange(20), ridge.coef_) # 繪制所有系數
plt.show()
交叉驗證
交叉驗證(Cross-Validation)是一種評估模型泛化能力的方法,通過將數據集劃分為多個子集,反復進行訓練和驗證,以減少因單次數據劃分帶來的隨機性誤差。通過交叉驗證能更可靠地估計模型在未知數據上的表現。亦能避免因單次數據劃分不合理導致的模型過擬合或欠擬合。
簡單交叉驗證(Hold-Out Validation)
將數據劃分為訓練集和驗證集(如70%訓練,30%驗證)。結果受單次劃分影響較大,可能高估或低估模型性能。
k折交叉驗證(k-Fold Cross-Validation)
將數據均勻分為k個子集(稱為“折”),每次用k?1折訓練,剩余1折驗證,重復k次后取平均性能。充分利用數據,結果更穩定。
留一交叉驗證(Leave-One-Out,LOO)
每次僅留一個樣本作為驗證集,其余全部用于訓練,重復直到所有樣本都被驗證一次。適用于小數據集,計算成本極高。
模型求解算法
正則化可以有效防止過擬合,增強模型的泛化能力。這時模型的評估策略,就是讓結構化的經驗風險最小,即增加了正則化項的損失函數最小,稱為 結構風險最小化(Structural Risk Minimization,SRM)。
min 1/n ∑_(i=1)^n?〖L(y_i,f(x_i))+λJ(θ)〗
這其實就是求解一個 最優化問題。代入訓練集所有數據 (x_i,y_i ),要求最小值的目標函數就是模型中參數 θ的函數。
具體求解的算法,可以利用數學公式直接計算解析解,也可以使用迭代算法。
解析法
如果模型損失函數的最小值可以通過數學公式進行嚴格推導,得到一個解析解,那么就直接得到了最優模型的全部參數。這種方法稱作解析法。
特點
適用條件:目標函數必須可導,且導數方程有解析解。
優點:直接且精確;計算高效;
缺點:適用條件較為苛刻;特征維度較大時,矩陣求逆計算復雜度極高。
應用示例
線性回歸問題:可以采用“最小二乘法”求得解析解。
〖Loss〗_MSE=〖1/n (Xβ-y)〗^T (Xβ-y)
?〖Loss〗_MSE=2/n X^T (Xβ-y)=0
β=〖(X^T X)〗^(-1) X^T y
線性回歸L2正則化(Ridge回歸,嶺回歸)
可以得到解析解如下:
〖Loss〗_L2=1/n (Xβ-y)^T (Xβ-y)+1/n λβ^T β
?〖Loss〗_L2=2/n X^T (Xβ-y)+2/n λβ=0
β=〖(X^T X+λI)〗^(-1) X^T y
由于加入的對角矩陣 λI 就像一條“山嶺”,因此L2正則化也稱作“嶺回歸”。
梯度下降法(重點)
梯度下降法(gradient descent)是一種常用的一階優化方法,是求解無約束優化問題最簡單、最經典的方法之一。梯度下降法是迭代算法,基本思路就是先選取一個適當的初始值θ_0,然后沿著梯度方向或者負梯度方向,不停地更新參數,最終取到極小值。
梯度方向:函數變化增長最快的方向(變量沿此方向變化時函數增長最快)
負梯度方向:函數變化減少最快的方向(變量沿此方向變化時函數減少最快)
因為損失函數是系數的函數,那么如果系數沿著損失函數的負梯度方向變化,此時損失函數減少最快,能夠以最快速度下降到極小值。
θ_(k+1)=θ_k- α·▽L(θ_k)
這里的▽L(θ_k )是參數取值為〖 θ〗_k 時損失函數 L 的梯度; α 是每次迭代的“步長”,被稱為“學習率”。學習率也是一個常見的超參數,需要手動設置,選擇不當會導致收斂失敗。
特點
梯度下降不一定能夠找到全局的最優解,有可能是一個局部最優解。
優點:適用性廣;計算簡單;
缺點:收斂速度慢;可能陷入局部最優。
分類
批量梯度下降(Batch Gradient Descent,BGD)
每次迭代使用全部訓練數據計算梯度。
優點:穩定收斂。
缺點:計算開銷大。
隨機梯度下降(Stochastic Gradient Descent,SGD)
每次迭代隨機選取一個樣本計算梯度。
優點:速度快,適合大規模數據。
缺點:梯度更新方向不穩定,優化過程震蕩較大,可能難以收斂。
小批量梯度下降(Mini-batch Gradient Descent,MBGD)
每次迭代使用一小批樣本(如32、64個)計算梯度。
平衡了BGD的穩定性和SGD的速度,是最常用的方法。
梯度下降法計算步驟
初始化參數:隨機選擇初始參數
計算梯度:在當前參數下,計算損失函數的梯度
更新參數:沿負梯度方向調整參數
重復迭代:直到滿足停止條件(如梯度接近零、達到最大迭代次數等)
代碼實現
我們以一個單變量函數為例,介紹梯度下降法的代碼實現。
設f(x)=x^2,求x為何值時,f(x)=2。
目標函數J(x)=(f(x)-2)2=(x2-2)^2,原問題等價于求x為何值時目標函數取得最小值。
使用梯度下降法求解。
x初始值取1
學習率α取0.1
dJ(x)/dx=2×(x2-2)×2×x=4x3-8x
第1步:x_1=1,J(x_1 )=1,〖J(x_1 )〗^‘=-4,x_2=x_1-α〖J(x_1 )〗^’=1.4
第2步:x_2=1.4,J(x_2 )=0.0016,〖J(x_2 )〗^‘=-0.2240,x_3=x_2-α〖J(x_2 )〗^’=1.4224
?
第n步:x_n=1.414213,J(x_n )=2.53×10^(-12),〖J(x_n )〗'=8.8817×10(-15)
示例代碼:
def J(x):
“”“目標函數”“”
return (x**2 - 2) ** 2
def gradient(x):
“”“梯度”“”
return 4 * x**3 - 8 * x
x = 1 # x的初始值
alpha = 0.1 # 學習率
while (j := J(x)) > 1e-30: # 當目標函數的值小于10的-30次冪時停止計算
print(f"x={x}\tJ={j}")
grad = gradient(x) # 求解梯度
x = x - alpha * grad # 更新參數
應用示例
L1正則化(Lasso回歸)
梯度下降法求解的推導過程如下:
〖Loss〗L1=1/n (∑(i=1)^n?(f(x_i )-y_i )^2 +λ∑_(j=1)^k?|ω_j | )
(?〖Loss〗L1)/(?ω_j )=1/n (2∑(i=1)^n?〖x_ij (f(x_i )-y_i ) 〗+λ?sign(ω_j ))
其中sign(ω_j )={█(1,ω_j>0@0,ω_j=0@-1,ω_j<0)┤
參數更新:ω_j←ω_j-α(2/n ∑_(i=1)^n?〖x_ij (f(x_i)-y_i)〗+λ/n?sign(ω_j))
可見L1正則化項的梯度是一個常數 λ/n,當 ω_j很小時會直接變成0,導致稀疏性。
L2正則化(Ridge回歸,嶺回歸)
梯度下降法求解的推導過程如下:
〖Loss〗L2=1/n (∑(i=1)^n?(f(x_i )-y_i )^2 +λ∑_(j=1)k?〖ω_j〗2 )
(?〖Loss〗L2)/(?ω_j )=1/n (2∑(i=1)^n?〖x_ij (f(x_i)-y_i)〗+2λω_j )
梯度更新:ω_j←ω_j-α(2/n ∑_(i=1)^n?〖x_ij (f(x_i)-y_i)〗+2λ/n ω_j )
可見L2正則化項的梯度是 2λ/n ω_j,相當于在每次更新時都對 ω_j 進行縮小,但不會直接變為0。
牛頓法和擬牛頓法(了解)
牛頓法也是求解無約束最優化問題的常用方法,核心思想是利用目標函數的二階導數信息,通過迭代逐漸逼近極值點。
θ_(k+1)=θ_k- H^(-1) (θ_k)·▽L(θ_k)
這里的〖 H〗^(-1) (θ_k)表示損失函數 L 黑塞矩陣的逆在點 θ_k 的取值。
優點:收斂速度快;精度高;
缺點:計算復雜;可能發散。
由于牛頓法中需要計算黑塞矩陣的逆〖 H〗^(-1) (θ_k),這一步比較復雜;所以可以考慮用一個n階正定矩陣來近似代替它,這種方法稱為“擬牛頓法”。
牛頓法和擬牛頓法一般用于解決中小規模的凸優化問題。
模型評價指標(重點)
對學習的泛化性能進行評估,不僅需要有效可行的實驗估計方法,還需要有衡量模型泛化能力的評價指標,也叫做性能度量(performance measure)。
回歸模型評價指標
模型的評價指標用于衡量模型在訓練集或測試集上的性能,評估結果反映了模型預測的準確性和泛化能力。
對于回歸問題,最常用的性能度量是“均方誤差” (Mean Squared Error,MSE)。
平均絕對誤差(MAE)
MAE=1/n ∑_(i=1)^n?|f(x_i)-y_i |
MAE對異常值不敏感,解釋直觀。適用于數據包含異常值的場景。
均方誤差(MSE)
MSE=1/n ∑_(i=1)n?〖(f(x_i)-y_i)〗2
MSE會放大較大誤差,對異常值敏感。適用于需要懲罰大誤差的場景。
均方根誤差(RMSE)
RMSE=√(1/n ∑_(i=1)n?〖(f(x_i)-y_i)〗2 )
與MSE類似,但量綱與目標變量一致。適用于需要直觀誤差量綱的場景。如果一味地試圖降低RMSE,可能會導致模型對異常值也擬合度也很高,容易過擬合。
R2(決定系數)
R2=1-(∑_(i=1)n?(f(x_i )-y_i )^2 )/(∑_(i=1)^n?(y_i-y ? )^2 )
衡量模型對目標變量的解釋能力,越接近1越好,對異常值敏感。
分類模型評價指標
對于分類問題,最常用的指標就是“準確率”(Accuracy),它定義為分類器對測試集正確分類的樣本數與總樣本數之比。此外還有一系列常用的評價指標。
混淆矩陣
混淆矩陣(Confusion Matrix)是用于評估分類模型性能的工具,展示了模型預測結果與實際標簽的對比情況。
對于二分類問題,混淆矩陣是一個2×2矩陣:
例如,有10個樣本。6個是貓,4個是狗。假設以貓為正例,模型預測對了5個貓,2個狗。
使用sklearn.metrics.confusion_matrix查看混淆矩陣:
import pandas as pd
import seaborn as sns
from sklearn.metrics import confusion_matrix
label = [“貓”, “狗”] # 標簽
y_true = [“貓”, “貓”, “貓”, “貓”, “貓”, “貓”, “狗”, “狗”, “狗”, “狗”] # 真實值
y_pred1 = [“貓”, “貓”, “狗”, “貓”, “貓”, “貓”, “貓”, “貓”, “狗”, “狗”] # 預測值
matrix1 = confusion_matrix(y_true, y_pred1, labels=label) # 混淆矩陣
print(pd.DataFrame(matrix1, columns=label, index=label))
sns.heatmap(matrix1, annot=True, fmt=‘d’, cmap=‘Greens’)
準確率(Accuracy)
正確預測的比例。
Accuracy=(TP+TN)/(TP+TN+FP+FN)
上述案例中,準確率=(5+2)/10=0.7。
from sklearn.metrics import accuracy_score
label = [“貓”, “狗”] # 標簽
y_true = [“貓”, “貓”, “貓”, “貓”, “貓”, “貓”, “狗”, “狗”, “狗”, “狗”] # 真實值
y_pred1 = [“貓”, “貓”, “狗”, “貓”, “貓”, “貓”, “貓”, “貓”, “狗”, “狗”] # 預測值
accuracy = accuracy_score(y_true, y_pred1)
print(accuracy)
精確率(Precision)
預測為正例的樣本中實際為正例的比例,也叫查準率。
Precision=TP/(TP+FP)
上述案例中,精確率=5/(5+2)=0.7143。
from sklearn.metrics import precision_score
label = [“貓”, “狗”] # 標簽
y_true = [“貓”, “貓”, “貓”, “貓”, “貓”, “貓”, “狗”, “狗”, “狗”, “狗”] # 真實值
y_pred1 = [“貓”, “貓”, “狗”, “貓”, “貓”, “貓”, “貓”, “貓”, “狗”, “狗”] # 預測值
precision = precision_score(y_true, y_pred1, pos_label=“貓”) # pos_label指定正例
print(precision)
召回率(Recall)
實際為正類的樣本中預測為正類的比例,也叫查全率。
Recall=TP/(TP+FN)
上述案例中,召回率=5/(5+1)=0.8333。
from sklearn.metrics import recall_score
label = [“貓”, “狗”] # 標簽
y_true = [“貓”, “貓”, “貓”, “貓”, “貓”, “貓”, “狗”, “狗”, “狗”, “狗”] # 真實值
y_pred1 = [“貓”, “貓”, “狗”, “貓”, “貓”, “貓”, “貓”, “貓”, “狗”, “狗”] # 預測值
recall = recall_score(y_true, y_pred1, pos_label=“貓”) # pos_label指定正例
print(recall)
F1分數(F1 Score)
精確率和召回率的調和平均。
F1 Score=(2×Precision×Recall)/(Precision+Recall)
上述案例中,F1分數=(2×5/(5+2)×5/(5+1))/(5/(5+2)+5/(5+1))=0.7692。
from sklearn.metrics import f1_score
label = [“貓”, “狗”] # 標簽
y_true = [“貓”, “貓”, “貓”, “貓”, “貓”, “貓”, “狗”, “狗”, “狗”, “狗”] # 真實值
y_pred1 = [“貓”, “貓”, “狗”, “貓”, “貓”, “貓”, “貓”, “貓”, “狗”, “狗”] # 預測值
f1 = f1_score(y_true, y_pred1, pos_label=“貓”) # pos_label指定正例
print(f1)
在代碼中,我們可通過sklearn.metrics.classification_report生成分類任務的評估報告,包括精確率、召回率、F1分數等。
from sklearn.metrics import classification_report
report = classification_report(y_true, y_pred, labels=[], target_names=None)
y_true:真實標簽
y_pred:預測的標簽
labels:可選,指定需要計算的類別列表(默認計算所有出現過的類別)
target_names:可選,類別名稱(默認使用 labels 指定的類別號)
例如:
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
生成一個二分類數據集
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, random_state=100)
劃分訓練集和測試集
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=100)
訓練一個邏輯回歸模型
model = LogisticRegression()
model.fit(x_train, y_train)
預測
y_pred = model.predict(x_test)
生成分類報告
report = classification_report(y_test, y_pred)
print(report)
ROC曲線
真正例率(TPR):實際為正例,被預測為正例的比例,即召回率。
假正例率(FPR):實際為負例,被預測為正例的比例。
閾值(Threshold):根據閾值將概率轉換為類別標簽。
TPR=TP/實際正例數=TP/(TP+FN)
FPR=FP/實際負例數=FP/(FP+TN)
ROC曲線(Receiver Operating Characteristic Curve,受試者工作特征)是評估二分類模型性能的工具,以假正例率(FPR)為橫軸,以真正例率(TPR)為縱軸,展示不同閾值下模型的表現。繪制ROC曲線時,從高到低調整閾值,計算每個閾值的TPR和FPR并繪制所有閾值的點,形成ROC曲線。
AUC值
AUC值代表ROC曲線下的面積,用于量化模型性能。AUC值越大,模型區分正負類的能力越強,模型性能越好。AUC值=0.5表示模型接近隨機猜測,AUC值=1代表完美模型。
可通過sklearn.metrics.roc_auc_score計算AUC值。
from sklearn.metrics import roc_auc_score
auc_score = roc_auc_score(y_true, y_score)
y_true: 真實標簽(0 或 1)
y_score: 正例的概率值或置信度
例如:
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score
生成一個二分類數據集
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, random_state=100)
劃分訓練集和測試集
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=100)
訓練一個邏輯回歸模型
model = LogisticRegression()
model.fit(x_train, y_train)
預測概率值(取正類的概率)
y_pred_proba = model.predict_proba(x_test)[:, 1]
計算AUC
auc_score = roc_auc_score(y_test, y_pred_proba)
print(auc_score)
案例:繪制ROC曲線
假設一個二分類模型的真實標簽和模型輸出概率如下:
■(樣本&真實標簽&模型輸出概率@1&1&0.9@2&0&0.4@3&1&0.6@4&1&0.8@5&0&0.2@6&0&0.7@7&1&0.3@8&0&0.5)□(→┴按模型輸出概率排序 ) ■(樣本&真實標簽&模型輸出概率@1&1&0.9@4&1&0.8@6&0&0.7@3&1&0.6@8&0&0.5@2&0&0.4@7&1&0.3@5&0&0.2)
調整閾值,計算TPR和FPR:
閾值=0.9:TPR=0/4=0,FPR=0/4=0,點坐標(0,0)
閾值=0.8:TPR=1/4=0.25,FPR=0/4=0,點坐標(0,0.25)
閾值=0.7:TPR=2/4=0.5,FPR=0/4=0,點坐標(0,0.5)
閾值=0.6:TPR=2/4=0.5,FPR=1/4=0.25,點坐標(0.25,0.5)
閾值=0.5:TPR=3/4=0.75,FPR=1/4=0.25,點坐標(0.25,0.75)
閾值=0.4:TPR=3/4=0.75,FPR=2/4=0.5,點坐標(0.5,0.75)
閾值=0.3:TPR=3/4=0.75,FPR=3/4=0.75,點坐標(0.75,0.75)
閾值=0.2:TPR=4/4=1,FPR=3/4=0.75,點坐標(0.75,1)
根據坐標點繪制ROC曲線:
KNN算法
KNN算法介紹
K近鄰算法(K-Nearest Neighbors,KNN)是一種基本的分類與回歸方法,屬于監督學習算法。其核心思想是通過計算給定樣本與數據集中所有樣本的距離,找到距離最近的K個樣本,然后根據這K個樣本的類別或值來預測當前樣本的類別或值。
工作原理
計算距離:計算待分類樣本與訓練集中每個樣本的距離。
選擇K個近鄰:根據計算的距離,選擇距離最近的K個樣本。
投票或平均:
分類任務:統計K個近鄰各類別的數量,將待分類樣本歸為數量最多的類別。
回歸任務:取K個近鄰的平均值作為預測結果。
關鍵參數
距離度量方法:選擇合適的距離度量方法,常見的有歐氏距離、曼哈頓距離、切比雪夫距離、閔可夫斯基距離等。
K值:K值的選擇對結果影響很大。K值過小容易過擬合,K值過大則可能欠擬合。
優缺點
KNN優點:
簡單直觀,易于理解和實現。
無需訓練過程,直接利用訓練數據進行預測。
KNN缺點:
計算量大,尤其是訓練集較大時。
對噪聲數據較敏感。
API使用
分類
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=2) # KNN分類模型,K值為2
X = [[2, 1], [3, 1], [1, 4], [2, 6]] # 特征
y = [0, 0, 1, 1] # 標簽
knn.fit(X, y) # 模型訓練
knn.predict([[4, 9]]) # 預測
回歸
from sklearn.neighbors import KNeighborsRegressor
knn = KNeighborsRegressor(n_neighbors=2) # KNN回歸模型,K值為2
X = [[2, 1], [3, 1], [1, 4], [2, 6]] # 特征
y = [0.5, 0.33, 4, 3] # 標簽
knn.fit(X, y) # 模型訓練
knn.predict([[4, 9]]) # 預測
常見距離度量方法(了解)
歐氏距離
歐幾里得距離(Euclidean Distance)是指連接兩點的線段的長度。
點x(x_1,…,x_n)和y(y_1,…,y_n)之間的歐氏距離d(x,y)=√(∑_(i=1)^n?(x_i-y_i )^2 )。
曼哈頓距離
曼哈頓距離(Manhattan Distance)是兩點在標準坐標系上的絕對軸距之和。
點x(x_1,…,x_n)和y(y_1,…,y_n)之間的曼哈頓距離d(x,y)=∑_(i=1)^n?|x_i-y_i | 。
曼哈頓距離得名于紐約曼哈頓的街道布局。由于曼哈頓的街道多為規則的網格狀,車輛只能沿水平和垂直方向行駛,無法直接斜穿。因此,兩點之間的實際行駛距離是沿街道行走的距離,而非直線距離。
切比雪夫距離
切比雪夫距離(Chebyshev Distance)是兩點各坐標數值差的最大值。
點x(x_1,…,x_n)和y(y_1,…,y_n)之間的切比雪夫距離d(x,y)=max?(|x_i-y_i |)。
在國際象棋中,國王可以橫向、縱向或斜向移動一格。其從起點到終點的最少步數就等于兩點之間的切比雪夫距離。
閔可夫斯基距離
閔可夫斯基距離(Minkowski Distance)是一種用于度量多維空間中兩點間距離的通用方法,點x(x_1,…,x_n)和y(y_1,…,y_n)之間的閔可夫斯基距離d(x,y)=(∑_(i=1)^n?(|x_i-y_i |)^p )^(1/p)。p越小,對多個維度的差異更敏感;p越大,更關注最大維度的差異。
通過調整參數p,閔可夫斯基距離可以退化為以下經典距離:
曼哈頓距離:p=1,d(x,y)=∑_(i=1)^n?|x_i-y_i | 。
歐氏距離:p=2,d(x,y)=√(∑_(i=1)^n?(x_i-y_i )^2 )。
切比雪夫距離:p=∞,d(x,y)=max?(|x_i-y_i |)。
歸一化與標準化
歸一化
定義
將數據按比例縮放到一個固定范圍[x_min,x_max](通常是[0,1]或[-1,1])。
x’=(x-x_min)/(x_max-x_min )
x’=2×(x-x_min)/(x_max-x_min )-1
目的
消除量綱差異:不同特征的單位或量綱可能差異巨大(例如身高以米為單位,體重以千克為單位),歸一化可消除這種差異,避免模型被大范圍特征主導。
加速模型收斂:對于梯度下降等優化算法,歸一化后特征處于相近的尺度,優化路徑更平滑,收斂速度更快。
適配特定模型需求:某些模型(如神經網絡、K近鄰、SVM)對輸入數據的范圍敏感,歸一化能顯著提升其性能。
場景
歸一化不改變原始分布形狀,但對異常值比較敏感。當數據分布有明顯邊界(如圖像像素值、文本詞頻),或模型對輸入范圍敏感時可以優先考慮歸一化。
API使用
from sklearn.preprocessing import MinMaxScaler
X = [[2, 1], [3, 1], [1, 4], [2, 6]]
歸一化,區間設置為(-1,1)
X = MinMaxScaler(feature_range=(-1, 1)).fit_transform(X)
print(X)
標準化
定義
將數據調整為均值為0、標準差為1的標準分布。
x’=(x-μ)/σ
其中μ=∑_(i=1)n?x_i/n是平均值,σ=√(∑_(i=1)n?(x_i-μ) ^2/n)是標準差。
目的
適應數據分布:將數據轉換為均值為0、標準差為1的分布,適合假設數據服從正態分布的模型(如線性回歸、邏輯回歸)。
穩定模型訓練:標準化后的數據對異常值的敏感度較低(相比歸一化),魯棒性更強。
統一特征尺度:與歸一化類似,標準化也能消除量綱差異,但更關注數據的統計分布而非固定范圍。
場景
大多數場景下標準化更通用,尤其是數據分布未知或存在輕微異常值時。
API使用
from sklearn.preprocessing import StandardScaler
X = [[2, 1], [3, 1], [1, 4], [2, 6]]
標準化
X = StandardScaler().fit_transform(X)
print(X)
案例:心臟病預測
數據集說明
Heart Disease數據集https://www.kaggle.com/datasets/johnsmith88/heart-disease-dataset。
年齡:連續值
性別:0-女,1-男
胸痛類型:0-典型心絞痛,1-非典型心絞痛,2-非心絞痛,3-無癥狀
靜息血壓:連續值,單位mmHg
膽固醇:連續值,單位mg/dl
空腹血糖:1-大于120mg/dl,0-小于等于120mg/dl
靜息心電圖結果:0-正常,1-ST-T異常,2-可能左心室肥大
最大心率:連續值
運動性心絞痛:1-有,0-無
運動后的ST下降:連續值
峰值ST段的斜率:0-向上,1-水平,2-向下
主血管數量:0到3
地中海貧血:一種先天性貧血,1-正常,2-固定缺陷,3-可逆缺陷
是否患有心臟病:標簽,0-否,1-是
加載數據集
import pandas as pd
加載數據集
heart_disease = pd.read_csv(“data/heart_disease.csv”)
處理缺失值
heart_disease.dropna()
heart_disease.info()
heart_disease.head()
數據集劃分
from sklearn.model_selection import train_test_split
劃分特征和標簽
X = heart_disease.drop(“是否患有心臟病”, axis=1) # 特征
y = heart_disease[“是否患有心臟病”] # 標簽
將數據集按7:3劃分為訓練數據與測試數據
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=100)
特征工程
特征轉換
數據集中包含多種類型的特征:
類別型特征(需要特殊處理)
胸痛類型:4種分類(名義變量)
靜息心電圖結果:3種分類(名義變量)
峰值ST段的斜率:3種分類(有序變量)
地中海貧血:4種分類(名義變量)
數值型特征(可直接標準化):年齡、靜息血壓、膽固醇、最大心率、運動后的ST下降、主血管數量
二元特征(保持原樣):性別、空腹血糖、運動性心絞痛
對于類別型特征,直接使用整數編碼的類別特征會被算法視為有序數值,導致錯誤的距離計算(例如:會認為 胸痛類型=1 和 胸痛類型=2 之間的差異比 胸痛類型=1和 胸痛類型=3之間差異更小,而實際上它們都是類別)。使用 獨熱編碼(One-Hot Encoding)可將類別特征轉換為二元向量,消除虛假的順序關系。
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
數值型特征
numerical_features = [“年齡”, “靜息血壓”, “膽固醇”, “最大心率”, “運動后的ST下降”, “主血管數量”]
類別型特征
categorical_features = [“胸痛類型”, “靜息心電圖結果”, “峰值ST段的斜率”, “地中海貧血”]
二元特征
binary_features = [“性別”, “空腹血糖”, “運動性心絞痛”]
創建列轉換器
preprocessor = ColumnTransformer(
transformers=[
# 對數值型特征進行標準化
(“num”, StandardScaler(), numerical_features),
# 對類別型特征進行獨熱編碼,使用drop="first"避免多重共線性
(“cat”, OneHotEncoder(drop=“first”), categorical_features),
# 二元特征不進行處理
(“binary”, “passthrough”, binary_features),
]
)
執行特征轉換
x_train = preprocessor.fit_transform(x_train) # 計算訓練集的統計信息并進行轉換
x_test = preprocessor.transform(x_test) # 使用訓練集計算的信息對測試集進行轉換
避免多重共線性
drop="first"是獨熱編碼中的一個參數,它的核心目的是避免多重共線性(Multicollinearity)。
多重共線性是指特征之間存在高度線性相關關系的現象。例如特征胸痛類型包含4個類別(0、1、2、3),若直接進行獨熱編碼會生成4個新列(胸痛類型_0、胸痛類型_1、胸痛類型_2、胸痛類型_3),此時這4列滿足
胸痛類型_0+胸痛類型_1+胸痛類型_2+胸痛類型_3=1
這種完全線性相關關系會導致特征矩陣的列之間存在完美共線性。
當特征矩陣存在多重共線性時,模型參數估計會變得不穩定(矩陣不可逆或接近奇異),導致系數估計值方差增大、模型可解釋性下降、過擬合等問題。
在獨熱編碼時設置drop=“first”,會刪除每個類別特征的第1列,從而打破完全共線性。比如特征胸痛類型會生成3列(胸痛類型_1、胸痛類型_2、胸痛類型_3),此時
胸痛類型_1=0,胸痛類型_2=0,胸痛類型_3=0 隱含代表 胸痛類型_0=1
雖然KNN不直接受多重共線性影響(不像線性模型),但使用drop="first"也能夠減少冗余特征,提升計算效率。
模型訓練與評估
from sklearn.neighbors import KNeighborsClassifier
使用K近鄰分類模型,K=3
knn = KNeighborsClassifier(n_neighbors=3)
模型訓練
knn.fit(x_train, y_train)
模型評估,計算準確率
knn.score(x_test, y_test)
模型的保存
可以使用Python的joblib庫保存訓練好的模型:
import joblib
joblib.dump(knn, “knn_heart_disease”)
加載先前保存的模型:
加載模型
knn_loaded = joblib.load(“knn_heart_disease”)
預測
y_pred = knn_loaded.predict(x_test[10:11])
打印真實值與預測值
print(y_test.iloc[10], y_pred)
模型評估與超參數調優
網格搜索
網格搜索(Grid Search)是一種系統化的超參數調優方法,通過遍歷預定義的超參數組合,找到使模型性能最優的參數配置。通過自動化調參避免手動試錯,提高效率。
網格搜索通常嵌套交叉驗證,與交叉驗證結合以提高調參的可靠性:
外層循環:遍歷參數網格中的每個參數組合。
內層循環:對每個參數組合使用交叉驗證評估模型性能。
對心臟病預測模型進行超參數調優
對模型訓練與評估部分進行修改,使用sklearn.model_selection.GridSearchCV進行交叉驗證和網格搜索:
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
knn = KNeighborsClassifier()
網格搜索參數,K值設置為1到10
param_grid = {“n_neighbors”: list(range(1, 10))}
GridSearchCV(estimator=模型, param_grid=網格搜索參數, cv=k折交叉驗證)
knn = GridSearchCV(estimator=knn, param_grid=param_grid, cv=10)
模型訓練
knn.fit(x_train, y_train)
print(pd.DataFrame(knn.cv_results_)) # 所有交叉驗證結果
print(knn.best_estimator_) # 最佳模型
print(knn.best_score_) # 最佳得分
使用最佳模型進行評估
knn = knn.best_estimator_
print(knn.score(x_test, y_test))
線性回歸
線性回歸簡介
什么是線性回歸
線性回歸(Linear Regression)是一種用于建模兩個或多個變量之間線性關系的統計方法。它通過擬合一條直線(或超平面)來描述自變量(輸入特征)與因變量(輸出目標)之間的關聯,并可用于預測或分析變量間的影響關系。
假設因變量y與自變量x_1,x_2,…,x_n之間的關系可以用如下線性方程表示:
y=β_0+β_1 x_1+β_2 x_2+?+β_n x_n
β_0:截距,模型在自變量全為0時的基準值
β_1,β_2,…,β_n:自變量的系數,表示每個自變量對因變量的影響程度
通過估計這些系數,使模型預測值盡可能接近真實值。
一元線性回歸
僅有一個自變量:y=β_0+β_1 x_1。
多元線性回歸
包含多個自變量:y=β_0+β_1 x_1+β_2 x_2+?+β_n x_n。
線性回歸應用場景
GDP預測:用歷史數據(如投資、消費、出口)建立回歸模型,預測GDP增長趨勢。
廣告效果評估:量化不同渠道廣告投入對銷售額的影響,優化預算分配。
藥物劑量研究:分析藥物劑量與患者生理指標(如血壓、血糖)之間的關系。
產品質量控制:通過生產參數(溫度、壓力、原料配比)預測產品性能(如強度、耐久)。
政策效果評估:分析最低工資政策對就業率的影響,或環保法規對污染排放的抑制作用。
氣候變化建模:用工業排放量、森林覆蓋率等變量預測全球氣溫變化趨勢。
API使用
例如,某中學教師想研究學生每周學習時間(小時)與數學考試成績(0-100分)之間的關系,并預測學生成績。
from sklearn.linear_model import LinearRegression
自變量,每周學習時長
X = [[5], [8], [10], [12], [15], [3], [7], [9], [14], [6]]
因變量,數學考試成績
y = [55, 65, 70, 75, 85, 50, 60, 72, 80, 58]
實例化線性回歸模型
model = LinearRegression()
模型訓練
model.fit(X, y)
系數,每周每學習1小時,成績會增加多少分
print(model.coef_)
截距
print(model.intercept_)
預測,每周學習11小時,成績可能是多少分
print(model.predict([[11]]))
線性回歸求解
損失函數
模型的預測值與真實值之間存在誤差。
損失函數用于衡量模型預測值與真實值之間的誤差,并通過最小化損失函數來優化模型參數。當損失函數最小時,得到的自變量系數就是最優解。
均方誤差(MSE)
MSE=1/n ∑_(i=1)n?〖(f(x_i)-y_i)〗2
n:樣本個數。
y_i:第i個樣本的真實值。
f(x_i):第i個樣本的預測值。
均方誤差是回歸任務中最常用的損失函數。均方誤差對應了歐氏距離。基于均方誤差最小化來進行模型求解的方法稱為“最小二乘法”。在線性回歸中,最小二乘法就是試圖找到一條直線(或超平面),使所有樣本到直線(或超平面)上的歐氏距離之和最小。
均方誤差的特點
均方誤差對大誤差比較敏感,因為平方項會放大較大的誤差(如誤差2→4,誤差10→100)。
均方誤差是凸函數,存在全局的唯一最小值,平方項又使損失函數處處可導,便于求解最優參數。
最小二乘法(最小化MSE)的解析解可通過矩陣運算直接求出(如β=〖(X^T X)〗^(-1) X^T y)。
若誤差服從正態分布,則均方誤差對應極大似然估計,是最優的損失函數。
誤差服從正態分布時,均方誤差與極大似然估計的關系
假設因變量y與自變量x的關系為y_i=β^T x_i+?_i,?_i為誤差項。
當誤差獨立且具有相同分布,并且都服從正態分布時:
p(?_i)=1/√(2πσ^2 ) exp(-〖?_i〗2/(2σ2 ))
將y_i與x_i代入:
p(y_i |x_i;β)=1/√(2πσ^2 ) exp(-(y_i-β^T x_i )2/(2σ2 ))
似然函數:
L(β)=∏_(i=1)^n?〖p(y_i |x_i;β)〗=∏_(i=1)n?〖1/√(2πσ2 ) exp(-(y_i-β^T x_i )2/(2σ2 ))〗
對數似然函數:
ln?L(β)=ln∏_(i=1)n?〖1/√(2πσ2 ) exp?(-(y_i-β^T x_i )2/(2σ2 )) 〗
=-nln√2π σ-1/(2σ^2 ) ∑_(i=1)n?(y_i-βT x_i )^2
為使似然函數最大,需求解1/(2σ^2 ) ∑_(i=1)n?(y_i-βT x_i )^2 =1/(2σ^2 ) ∑_(i=1)n?(y_i-f(x_i))2 的最小值,發現其與均方誤差直接相關。即最大化對數似然函數等價于最小化均方誤差。
平均絕對誤差(MAE)
MAE=1/n ∑_(i=1)^n?|f(x_i)-y_i |
平均絕對誤差受異常值影響較小,但對小誤差的懲罰較弱。適用與數據中存在顯著異常值(如金融風險預測)的場景。
一元線性回歸解析解
對于一元線性回歸,有
f(x_i )=β_0+β_1 x_i
MSE=1/n ∑_(i=1)^n?〖(β_0+β_1 x_i-y_i)〗^2
對β_0求偏導:
?MSE/(?β_0 )=(? 1/n ∑_(i=1)^n?(β_0+β_1 x_i-y_i )^2 )/(?β_0 )
=2/n ∑_(i=1)^n?〖(β_0+β_1 x_i-y_i)〗
令偏導等于0:
2/n ∑_(i=1)^n?(β_0+β_1 x_i-y_i ) =0
β_0=1/n ∑_(i=1)^n?(y_i-β_1 x_i )
=y ?-β_1 x ?
對β_1求偏導:
?MSE/(?β_1 )=(? 1/n ∑_(i=1)^n?(β_0+β_1 x_i-y_i )^2 )/(?β_1 )
=2/n ∑_(i=1)^n?〖(β_0+β_1 x_i-y_i)x_i 〗
將β_0=y ?-β_1 x ?代入:
?MSE/(?β_1 )=2/n ∑_(i=1)^n?(x_i (y ?-β_1 x ? )+β_1 x_i^2-y_i x_i )
=2/n ∑_(i=1)^n?〖(β_1 (x_i^2-x_i x ? )+x_i (y ?-y_i ))〗
令偏導等于0:
2/n ∑_(i=1)^n?(β_1 (x_i^2-x_i x ? )+x_i (y ?-y_i )) =0
β_1 ∑_(i=1)n?(x_i2-x_i x ? ) =∑_(i=1)^n?〖x_i (y_i-y ? ) 〗
解得:
β_1=(∑_(i=1)^n?〖x_i (y_i-y ? ) 〗)/(∑_(i=1)n?(x_i2-x_i x ? ) )
=(∑_(i=1)^n?〖x_i (y_i-y ? ) 〗)/(∑_(i=1)^n?〖x_i (x_i-x ? ) 〗)
=(∑_(i=1)^n?(x_i-x ?+x ? )(y_i-y ? ) )/(∑_(i=1)^n?(x_i-x ?+x ? )(x_i-x ? ) )
=(∑_(i=1)^n?(x_i-x ? )(y_i-y ? ) +x ?∑_(i=1)^n?(y_i-y ? ) )/(∑_(i=1)^n?(x_i-x ? )(x_i-x ? ) +x ?∑_(i=1)^n?(x_i-x ? ) )
其中∑_(i=1)^n?(y_i-y ? ) =∑_(i=1)^n?〖y_i-ny ? 〗=0,∑_(i=1)^n?(x_i-x ? ) =∑_(i=1)^n?〖x_i-nx ? 〗=0
所以
β_1=(∑_(i=1)^n?(x_i-x ? )(y_i-y ? ) )/(∑_(i=1)^n?(x_i-x ? )^2 )
以前述學生每周學習時間(小時)與數學考試成績(0-100分)之間的關系為例:
自變量,每周學習時長
X = [[5], [8], [10], [12], [15], [3], [7], [9], [14], [6]]
因變量,數學考試成績
y = [55, 65, 70, 75, 85, 50, 60, 72, 80, 58]
β_1=(∑_(i=1)^n?(x_i-x ? )(y_i-y ? ) )/(∑_(i=1)^n?(x_i-x ? )^2 )
=((5-8.9)×(55-67)+(8-8.9)×(65-67)+?+(6-8.9)×(58-67))/((5-8.9)2+(8-8.9)2+?+(6-8.9)^2 )
=2.8707
β_0=y ?-β_1 x ?=67-2.8707×8.9=41.4507
解得β=■(41.4507@2.8707)
正規方程法(解析法)
正規方程法介紹
正規方程法(Normal Equation)是一種用于求解線性回歸的解析解的方法。它基于最小二乘法,通過求解矩陣方程來直接獲得參數值。
將損失函數轉換為矩陣形式:
MSE=1/n ∑_(i=1)^n?(f(x_i )-y_i )^2
=1/n ∑_(i=1)^n?((β_0+β_1 x_i1+β_2 x_i2+?+β_m x_im )-y_i )^2
=1/n ∑_(i=1)n?(βT x_i-y_i )^2
=1/n ‖Xβ-y‖_2^2
=〖1/n (Xβ-y)〗^T (Xβ-y)
X:n×(m+1)的矩陣,包含一個全1的列
X=■(1&x_11&x_12&?&x_1m@1&x_21&x_22&?&x_2m@?&?&?&?&?@1&x_n1&x_n2&?&x_nm )
β:(m+1)×1的參數向量(包含截距項β_0)
β=■(β_0@β_1@?@β_m )
y:n×1的因變量向量
對β求偏導
?MSE/?β=?(1/n (Xβ-y)^T (Xβ-y))/?β
=2/n X^T (Xβ-y)
當X^T X為滿秩矩陣或正定矩陣時,令偏導等于0
2/n X^T Xβ-〖2/n X〗^T y=0
X^T Xβ=X^T y
β=〖(X^T X)^(-1) X〗^T y
正規方程法適用于特征數量較少的情況。當特征數量較大時,計算逆矩陣的復雜度會顯著增加,此時梯度下降法更為適用。
API使用
fit_intercept: 是否計算偏置
model = sklearn.linear_model.LinearRegression(fit_intercept=True)
model.fit([[0, 3], [1, 2], [2, 1]], [0, 1, 2])
coef_: 系數
print(model.coef_)
intercept_: 偏置
print(model.intercept_)
梯度下降法
更新公式
梯度下降法(Gradient Descent)是一種用于最小化目標函數的迭代優化算法。核心是沿著目標函數(如損失函數)的負梯度方向逐步調整參數,從而逼近函數的最小值。梯度方向指示了函數增長最快的方向,因此負梯度方向是函數下降最快的方向。
假設目標函數為 J(β),其中β是模型參數。梯度下降的更新公式為:
β_(t+1)=β_t-α??J(β_t)
α:學習率(Learning Rate),用于控制步長
?J(β_t):目標函數在β_t處的梯度(偏導數組成的向量)
計算示例
以前述學生每周學習時間(小時)與數學考試成績(0-100分)之間的關系為例。
自變量(學習時長)x=[■(5&8&10&12&15&3&7&9&14&6)]^T。
因變量(數學考試成績)y=[■(55&65&70&75&85&50&60&72&80&58)]^T 。
求β=[■(β_0&β_1 )]^T 使得損失函數 J(β)=1/n ∑_(i=1)n?〖(f(x_i)-y_i)〗2 最小,為此需要求出損失函數相對β的梯度。
x添加一列1,轉換為X=[■(1&1&1&1&1&1&1&1&1&1@5&8&10&12&15&3&7&9&14&6)]^T。則損失函數J(β)=1/n ‖Xβ-y‖_2^2。
求得損失函數的梯度
?J(β)=2/n X^T (Xβ-y)
使用梯度下降法求解β=[■(β_0&β_1 )]^T。
β初始值取[■(1&1)]^T
學習率α取0.01
?J(β)=2/n X^T (Xβ-y)
β_1=■(1@1),J(β_1 )=3311.3,?J(β_1 )=■(-114.2@-1067.6),β_2=β_1-α?J(β_1 )=■(2.142@11.676)
β_2=■(2.142@11.676),J(β_2 )=2589.9686,?J(β_2 )=■(78.1168@936.3284),β_3=β_2-α?J(β_2 )=■(1.3608@2.3127)
?
β_n=■(41.45069394@2.87070855),J(β_n )=2.98115413,?J(β_n )=■(-2.33768560×10(-12)@1.17950094×10(-13) )
示例代碼:
import numpy as np
def J(beta):
“”“目標函數”“”
return np.sum((X @ beta - y) ** 2, axis=0).reshape(-1, 1) / n
def gradient(beta):
“”“梯度”“”
return X.T @ (X @ beta - y) / n * 2
X = np.array([[5], [8], [10], [12], [15], [3], [7], [9], [14], [6]]) # 自變量,每周學習時長
y = np.array([[55], [65], [70], [75], [85], [50], [60], [72], [80], [58]]) # 因變量,數學考試成績
beta = np.array([[1], [1]]) # 初始化參數
n = X.shape[0] # 樣本數
X = np.hstack([np.ones((n, 1)), X]) # X添加一列1,與偏置項相乘
alpha = 1e-2 # 學習率
epoch = 0 # 迭代次數
while (j := J(beta)) > 1e-10 and (epoch := epoch + 1) <= 10000:
grad = gradient(beta) # 求解梯度
if epoch % 1000 == 0:
print(f"beta={beta.reshape(-1)}\tJ={j.reshape(-1)}")
beta = beta - alpha * grad # 更新參數
學習率的選擇
學習率過大:可能導致跳過最優解,甚至發散。
學習率過小:收斂速度慢,易陷入局部極小。
自適應學習率:高級優化器(如Adam、Adagrad)動態調整學習率以提升性能。
梯度下降法常見問題
特征縮放
通常需要提前對特征進行縮放(如標準化或歸一化),以加快收斂速度。
局部極小值、鞍點問題
可能陷入局部極小值(非全局最優解),或遇到鞍點(梯度為零但非極值點)。
解決方案:使用動量(Momentum)、自適應優化器(如Adam)或二階方法(如牛頓法)。
API使用
model = sklearn.linear_model.SGDRegressor(
loss=“squared_error”, # 損失函數,默認為均方誤差
fit_intercept=True, # 是否計算偏置
learning_rate=“constant”, # 學習率策略
eta0=0.1, # 初始學習率
max_iter=1000, # 最大迭代次數
tol=1e-8, # 損失值小于tol時停止迭代
)
model.fit([[0, 3], [1, 2], [2, 1]], [0, 1, 2])
coef_: 系數
print(model.coef_)
intercept_: 偏置
print(model.intercept_)
案例:廣告投放效果預測
數據集說明
Advertising數據集:https://www.kaggle.com/datasets/tawfikelmetwally/advertising-dataset。
ID:序號
TV:電視廣告投放金額,單位千元
Radio:廣播廣告投放金額,單位千元
Newspaper:報紙廣告投放金額,單位千元
Sales:銷售額,單位百萬元
使用線性回歸預測廣告投放效果
import pandas as pd
from sklearn.preprocessing import StandardScaler # 標準化
from sklearn.model_selection import train_test_split # 劃分數據集
from sklearn.linear_model import LinearRegression, SGDRegressor # 線性回歸-正規方程,線性回歸-隨機梯度下降
from sklearn.metrics import mean_squared_error # 均方誤差
加載數據集
advertising = pd.read_csv(“data/advertising.csv”)
advertising.drop(advertising.columns[0], axis=1, inplace=True)
advertising.dropna(inplace=True)
advertising.info()
print(advertising.head())
劃分訓練集與測試集
X = advertising.drop(“Sales”, axis=1)
y = advertising[“Sales”]
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
標準化
preprocessor = StandardScaler()
x_train = preprocessor.fit_transform(x_train) # 計算訓練集的均值和標準差,并標準化訓練集
x_test = preprocessor.transform(x_test) # 使用訓練集的均值和標準差對測試集標準化
使用正規方程法擬合線性回歸模型
normal_equation = LinearRegression()
normal_equation.fit(x_train, y_train)
print(“正規方程法解得模型系數:”, normal_equation.coef_)
print(“正規方程法解得模型偏置:”, normal_equation.intercept_)
使用隨機梯度下降法擬合線性回歸模型
gradient_descent = SGDRegressor()
gradient_descent.fit(x_train, y_train)
print(“隨機梯度下降法解得模型系數:”, gradient_descent.coef_)
print(“隨機梯度下降法解得模型偏置:”, gradient_descent.intercept_)
使用均方誤差評估模型
print(“正規方程法均方誤差:”, mean_squared_error(y_test, normal_equation.predict(x_test)))
print(“隨機梯度下降法均方誤差:”, mean_squared_error(y_test, gradient_descent.predict(x_test)))
邏輯回歸
邏輯回歸簡介
什么是邏輯回歸
邏輯回歸(Logistic Regression)是一種用于解決分類問題的統計方法,尤其適用于二分類問題。盡管名稱中有“回歸”,但它主要用于分類任務。
邏輯回歸通過將線性回歸的輸出映射到[0,1]區間,來表示某個類別的概率。
常用的映射函數是sigmoid函數:f(x)=1/(1+e^(-x) ),其導數f’(x)=f(x)(1-f(x))。
邏輯回歸結果可表示為:
P(y=1∣x)=1/(1+e^(-(β_0+β_1 x_1+β_2 x_2+?+β_n x_n ) ) )
其中β_0+β_1 x_1+β_2 x_2+?+β_n x_n為線性回歸輸出結果,P(y=1∣x)表示輸出為1類的概率。根據邏輯回歸結果和閾值來確認最終預測結果,若邏輯回歸結果大于閾值則輸出為1類,反之輸出為0類。
■(X@[■(0.5&0&0.7@0.5&0.5&0.9@0.1&1&0.6@0.6&0.1&0)] )■(β@[■(-1@2@0.5)] )=■(線性回歸輸出結果@[■(-0.15@0.95@2.2@-0.4)] )□(→┴sigmoid ) ■(邏輯回歸結果@[■(0.46257015@0.72111518@0.90024951@0.40131234)] )→┴與閾值0.5比較 ■(預測結果@[■(0@1@1@0)] )
邏輯回歸應用場景
信用評分:預測客戶是否會違約(違約/不違約)。
欺詐檢測:預測某筆交易是否是欺詐行為。
垃圾郵件檢測:預測一封郵件是否是垃圾郵件(垃圾郵件/非垃圾郵件)。
廣告點擊預測:預測用戶是否會點擊某個廣告(點擊/不點擊)。
圖像分類:將圖像分類為不同的類別(如貓、狗、鳥等)。
情感分析:將文本分類為正面、負面或中性情感。
產品質量分類:預測產品是否合格。
醫學診斷:預測患者是否患有某種疾病(患病/未患病)。
蛋白質功能預測:基于蛋白質序列和結構特征預測其功能類別。
邏輯回歸損失函數
邏輯回歸的損失函數通常使用對數損失(Log Loss),也稱為二元交叉熵損失(Binary Cross-Entropy Loss),用于衡量模型輸出的概率分布與真實標簽之間的差距。邏輯回歸的損失函數來源于最大似然估計(MLE)。
P(Y│X;β)表示給定輸入特征x和模型參數β時,因變量y發生的概率:
├ █(P(y=1│x;β)=1/(1+e(-(βT x) ) )@P(y=0│x;β)=1-P(y=1│x;β)=1-1/(1+e(-(βT x) ) ))} □(→┴整合 ) P(y│x;β)
P(y│x;β)=〖P(y=1│x;β)〗^y (1-P(y=1│x;β))^(1-y)
=(1/(1+e(-(βT x) ) ))^y (1-1/(1+e(-(βT x) ) ))^(1-y)
似然函數L(β)表示已知y的結果,此時模型參數為β的概率:
對于1個樣本:L(β)=P(y│x;β)=〖P(y=1│x;β)〗^y (1-P(y=1│x;β))^(1-y)
對于n個樣本:L(β)=∏_(i=1)^n?〖P(y_i│x_i;β) 〗=∏_(i=1)n?〖〖P(y_i=1│x_i;β)〗(y_i ) (1-P(y_i=1│x_i;β))^(1-y_i ) 〗
〖取對數似然:log〗?L(β)=∑_(i=1)^n?(y_i logP(y_i=1│x_i;β)+(1-y_i )log(1-P(y_i=1│x_i;β)))
擬合的過程就是求解似然函數的最大值,為了方便優化,令損失函數
Loss=-1/n log?L(β)
=-1/n ∑_(i=1)^n?(y_i logP(y_i=1│x_i;β)+(1-y_i )log(1-P(y_i=1│x_i;β)))
來求解損失函數的最小值。
損失函數的梯度(了解)
Loss=-1/n ∑_(i=1)^n?(y_i logP(y_i=1│x_i;β)+(1-y_i )log(1-P(y_i=1│x_i;β)))
=-1/n (y^T logp+(1-y)^T log(1-p))
其中:
y=[■(y_1&y_2&…&y_n )]^T
p=[■(P(y_1=1│x_1;β)&P(y_2=1│x_2;β)&…&P(y_n=1│x_n;β) )]^T
=[■(1/(1+e(-(βT x_1 ) ) )&1/(1+e(-(βT x_2 ) ) )&…&1/(1+e(-(βT x_n ) ) ))]^T
=1/(1+e^(-(Xβ) ) )
則梯度
?Loss=?Loss/?p??p/?β
=?(-1/n (y^T logp+(1-y)^T log(1-p)))/?p??(1/(1+e^(-(Xβ) ) ))/?β
=-1/n (y/p-(1-y)/(1-p))?(p?(1-p)?X)
=1/n X^T (p-y)
=1/n X^T (1/(1+e^(-(Xβ) ) )-y)
其中?表示Hadamard乘積(逐項乘積)。
API使用
LogisticRegression參數說明
scikit-learn中的LogisticRegression類用于實現邏輯回歸。它支持二分類和多分類任務,并提供了多種優化算法和正則化選項。
solver: 優化算法
lbfgs: 擬牛頓法(默認),僅支持L2正則化
newton-cg: 牛頓法,僅支持L2正則化
liblinear: 坐標下降法,適用于小數據集,支持L1和L2正則化
sag: 隨機平均梯度下降,適用于大規模數據集,僅支持L2正則化
saga: 改進的隨機梯度下降,適用于大規模數據,支持L1、L2和ElasticNet正則化
penalty: 正則化類型,可選l1、l2和elasticnet
C: 正則化強度,C越小,正則化強度越大
class_weight: 類別權重,balanced表示自動平衡類別權重,讓模型在訓練時更關注少數類,從而減少類別不平衡帶來的偏差
model = sklearn.linear_model.LogisticRegression(solver=“lbfgs”, penalty=“l2”, C=1, class_weight=“balanced”)
案例:心臟病預測
Heart Disease數據集https://www.kaggle.com/datasets/johnsmith88/heart-disease-dataset。
年齡:連續值
性別:0-女,1-男
胸痛類型:1-典型心絞痛,2-非典型心絞痛,3-非心絞痛,4-無癥狀
靜息血壓:連續值,單位mmHg
膽固醇:連續值,單位mg/dl
空腹血糖:1-大于120mg/dl,2-小于等于120mg/dl
靜息心電圖結果:0-正常,1-ST-T異常,2-可能左心室肥大
最大心率:連續值
運動性心絞痛:1-有,2-無
運動后的ST下降:連續值
峰值ST段的斜率:1-向上,2-水平,3-向下
主血管數量:0到3
地中海貧血:一種先天性貧血,3-正常,6-固定缺陷,7-可逆缺陷
是否患有心臟病:標簽,0-否,1-是
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.linear_model import LogisticRegression
加載數據集
heart_disease = pd.read_csv(“data/heart_disease.csv”)
heart_disease.dropna()
劃分為訓練集與測試集
X = heart_disease.drop(“是否患有心臟病”, axis=1) # 特征
y = heart_disease[“是否患有心臟病”] # 標簽
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=100)
特征工程
數值型特征
numerical_features = [“年齡”, “靜息血壓”, “膽固醇”, “最大心率”, “運動后的ST下降”, “主血管數量”]
類別型特征
categorical_features = [“胸痛類型”, “靜息心電圖結果”, “峰值ST段的斜率”, “地中海貧血”]
二元特征
binary_features = [“性別”, “空腹血糖”, “運動性心絞痛”]
創建列轉換器
preprocessor = ColumnTransformer(
transformers=[
# 對數值型特征進行標準化
(“num”, StandardScaler(), numerical_features),
# 對類別型特征進行獨熱編碼,使用drop="first"避免多重共線性
(“cat”, OneHotEncoder(drop=“first”), categorical_features),
# 二元特征不進行處理
(“binary”, “passthrough”, binary_features),
]
)
執行特征轉換
x_train = preprocessor.fit_transform(x_train) # 計算訓練集的統計信息并進行轉換
x_test = preprocessor.transform(x_test) # 使用訓練集計算的信息對測試集進行轉換
模型訓練
model = LogisticRegression()
model.fit(x_train, y_train)
模型評估,計算準確率
model.score(x_test, y_test)
多分類任務(了解)
邏輯回歸通常用于二分類問題,但可以通過一對多(One-vs-Rest,OvR)以及Softmax回歸(Multinomial Logistic Regression,多項邏輯回歸)來擴展到多分類任務。
一對多(OVR)
實現方式
若有C個類別,則訓練C個二分類邏輯回歸分類器。
每個分類器將一個類別作為正例、所有其他類別作為反例。
預測時,計算C個分類器的輸出概率,選取概率最高的類別。
對于類別c:
P(y=c│x;β)=1/(1+e(-(βT x) ) )
Loss=-1/n ∑_(i=1)^n?(y_i logP(y_i=c│x_i;β)+(1-y_i )log(1-P(y_i=c│x_i;β)))
優缺點
優點:簡單易于實現,適用于類別數量較少的情況。
缺點:每個類別訓練1個分類器,當類別數量較多時,訓練時間較長。
API
from sklearn.linear_model import LogisticRegression
model = LogisticRegression(multi_class=“ovr”)
或
from sklearn.multiclass import OneVsRestClassifier
model = OneVsRestClassifier(LogisticRegression())
Softmax回歸(多項邏輯回歸)
實現方式
直接擴展邏輯回歸到多分類問題,使用Softmax函數將模型輸出轉化為概率分布。
只需訓練1個邏輯回歸模型。
預測時用1個模型計算所有類別的概率,選擇最大值。
若有C個類別,模型將輸出C個分數。
對于類別c,P(y=c│x)=e(〖β_c〗T x)/(∑_(j=1)C?e(〖β_j〗^T x) )。
損失函數Loss=-1/n ∑_(i=1)n?∑_(c=1)C?〖I(y_i=c)logP(y_i=c│x_i ) 〗
其中I〖(y〗_i=c)為示性函數,當y_i=c時值為1,反之值為0。
優缺點
優點:只訓練1個模型,計算高效,分類一致性更好。
缺點:計算Softmax需要對所有類別求指數,計算量較高。
API
from sklearn.linear_model import LogisticRegression
model = LogisticRegression(multi_class=“multinomial”)
對于多分類問題,LogisticRegression會自動使用multinomial,因此multi_class參數可省略
model = LogisticRegression()
案例:手寫數字識別
數據集說明
Digit Recognizer數據集:https://www.kaggle.com/competitions/digit-recognizer。
文件train.csv中包含手繪數字(從0到9)的灰度圖像,每張圖像為28×28像素,共784像素。每個像素有一個0到255的值表示該像素的亮度。
文件第1列為標簽,之后784列分別為784個像素的亮度值。
第x×28+y個像素表示圖像第x行第y列的像素。
邏輯回歸實現手寫數字識別
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.linear_model import LogisticRegression
加載數據集
digit = pd.read_csv(“data/train.csv”)
plt.imshow(digit.iloc[10, 1:].values.reshape(28, 28), cmap=“gray”)
plt.show()
劃分訓練集和測試集
X = digit.drop(“label”, axis=1) # 特征
y = digit[“label”] # 標簽
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=100)
歸一化
preprocessor = MinMaxScaler()
x_train = preprocessor.fit_transform(x_train)
x_test = preprocessor.transform(x_test)
模型訓練
model = LogisticRegression(max_iter=500)
model.fit(x_train, y_train)
模型評估
model.score(x_test, y_test)
預測
plt.imshow(digit.iloc[123, 1:].values.reshape(28, 28), cmap=“gray”)
plt.show()
print(model.predict(digit.iloc[123, 1:].values.reshape(1, -1)))
感知機
感知機的概念
感知機(Perceptron)是二分類模型,接收多個信號,輸出一個信號。感知機的信號只有0、1兩種取值。下圖是一個接收兩個輸入信號的感知機的例子:
x_1,x_2是輸入信號,y是輸出信號,w_1,w_2是權重,○稱為神經元或節點。輸入信號被送往神經元時,會分別乘以固定的權重。神經元會計算傳送過來的信號的總和,只有當這個總和超過某個界限值時才會輸出1,也稱之為神經元被激活。這里將界限值稱之為閾值θ。
y={■(0 (w_1 x_1+w_2 x_2≤θ)@1 (w_1 x_1+w_2 x_2>θ) )┤
感知機的多個輸入信號都有各自的權重,這些權重發揮著控制各個信號的重要性的作用,權重越大,對應信號的重要性越高。
簡單邏輯電路
與門
嘗試使用感知機解決簡單的問題,如實現邏輯電路中的與門(AND gate)。與門是具有兩個輸入和一個輸出的門電路,僅在兩個輸入均為1時輸出1,其他時候輸出0。這種輸入信號和輸出信號對應表稱為真值表。
使用感知機表示與門需要確定能滿足上述真值表的w_1,w_2,θ的值,滿足條件的參數有無數個,如(w_1,w_2,θ)=(0.5,0.5,0.7)或(1.0,1.0,1.0)。
與非門
再來考慮下與非門(NAND gate),與非門顛倒了與門的輸出,僅當x_1,x_2同時為1時輸出0,其他時候輸出1。
要表示與非門,滿足條件的參數也有無數個,如(w_1,w_2,θ)=(-0.5,-0.5,-0.7)。實際上,只要把實現與門的參數值的符號取反即可。
或門
再來看一下或門(OR gate)。或門只要有一個輸入信號為1,輸出就為1。
(w_1,w_2,θ)=(0.5,0.5,0)。
感知機的實現
簡單實現
先來實現與門,定義一函數AND接受x_1和x_2,在函數內部初始化參數w_1,w_2,θ。當輸入的加權總和超過閾值時返回1,否則返回0。
def AND(x1, x2):
w1, w2, theta = 0.5, 0.5, 0.7
res = x1 * w1 + x2 * w2
if res <= theta:
return 0
elif res > theta:
return 1
print(AND(0, 0)) # 0
print(AND(1, 0)) # 0
print(AND(0, 1)) # 0
print(AND(1, 1)) # 1
可以以同樣的方式實現與非門和或門,不過在此之前先做一些修改。
導入權重和偏置
考慮到以后的事情,我們將其修改為另外一種實現形式。將θ換為-b,表示感知機行為的式子變為如下形式:
y={■(0 (b+w_1 x_1+w_2 x_2≤0)@1 (b+w_1 x_1+w_2 x_2>0) )┤
b為偏置,w_1,w_2為權重。下面我們使用Numpy按上述形式分別實現與門、與非門和或門。
與門:
import numpy as np
def AND(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.7
tmp = np.sum(w * x) + b
if tmp <= 0:
return 0
else:
return 1
print(AND(0, 0)) # 0
print(AND(1, 0)) # 0
print(AND(0, 1)) # 0
print(AND(1, 1)) # 1
偏置b與權重w_1,w_2的作用是不同的,具體地說w_1,w_2是控制輸入信號的重要性的參數,而偏置是調整神經元被激活的容易程度的參數。
接下來實現與非門和或門:
import numpy as np
def NAND(x1, x2):
x = np.array([x1, x2])
w = np.array([-0.5, -0.5])
b = 0.7
tmp = np.sum(w * x) + b
if tmp <= 0:
return 0
else:
return 1
print(NAND(0, 0)) # 1
print(NAND(1, 0)) # 1
print(NAND(0, 1)) # 1
print(NAND(1, 1)) # 0
def OR(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.2
tmp = np.sum(w * x) + b
if tmp <= 0:
return 0
else:
return 1
print(OR(0, 0)) # 0
print(OR(1, 0)) # 1
print(OR(0, 1)) # 1
print(OR(1, 1)) # 1
與門、與非門、或門是具有相同構造的感知機,區別僅在于權重參數的值。因此在與非門和或門的實現中,僅設置權重和偏置的值這一點和與門的實現不同。
感知機的局限
現在來考慮一下異或門(XOR gate)。異或門僅當x_1或x_2中的一方為1時才會輸出1。
之前的感知機是無法實現這個異或門的,具體原因讓我們來分析一下。
感知機表示或門的式子如下:
y={■(0 (-0.5+x_1+x_2≤0)@1 (-0.5+x_1+x_2>0) )┤
上式表示感知機會生成由直線-0.5+x_1+x_2=0劃分的兩個空間,其中一個空間輸出1,另一個空間輸出0,如圖:
如果要實現異或門,是無法使用一條直線將0和1分開的:
但如果將直線這個限制條件去掉就可以了:
感知機的局限性就在于它只能表示由一條直線劃分的空間,而上圖中的曲線無法用感知機表示。由曲線劃分的空間稱為非線性空間,由直線劃分的空間稱為線性空間。
多層感知機
我們先來考慮一下如何使用與門、與非門和或門來組合出異或門。
與門、與非門、或門用下圖的符號表示:
將其組合構成異或門:
使用之前實現的與門、與非門和或門代碼來實現異或門:
import numpy as np
def AND(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.7
tmp = np.sum(w * x) + b
if tmp <= 0:
return 0
else:
return 1
def NAND(x1, x2):
x = np.array([x1, x2])
w = np.array([-0.5, -0.5])
b = 0.7
tmp = np.sum(w * x) + b
if tmp <= 0:
return 0
else:
return 1
def OR(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.2
tmp = np.sum(w * x) + b
if tmp <= 0:
return 0
else:
return 1
def XOR(x1, x2):
s1 = NAND(x1, x2)
s2 = OR(x1, x2)
y = AND(s1, s2)
return y
print(XOR(0, 0)) # 0
print(XOR(1, 0)) # 1
print(XOR(0, 1)) # 1
print(XOR(1, 1)) # 0
試著使用感知機的表示方法來表示這個異或門:
如圖所示,這是一種多層感知機結構。
第0層的兩個神經元接收輸入信號,并將信號發送給第1層的神經元。第1層的神經元將信號發送給第2層的神經元。第2層的神經元輸出結果。
通過疊加層,感知機能進行更加靈活的表示。
感知機是一種非常簡單的算法,也是后續學習神經網絡的基礎。
其他監督學習算法(了解)
樸素貝葉斯法
樸素貝葉斯法簡介
樸素貝葉斯(naive Bayes)法是一種基于概率的機器學習算法。它基于貝葉斯定理,并假設特征之間相互獨立(這就是“樸素”的來源)。樸素貝葉斯法實現簡單,學習與預測的效率都很高,是一種常用方法,在許多場景下表現得非常好,如文本分類(垃圾郵件檢測)、情感分析等。
樸素貝葉斯法的核心是貝葉斯定理:
P(Y|X)=(P(X|Y)P(Y))/(P(X))
P(Y|X):后驗概率,給定特征X時類Y的概率。
P(X|Y):條件概率,類Y包含特征X的概率。
P(Y):先驗概率,類Y的概率。
P(X):特征X的概率。
例如,判斷一封郵件是不是垃圾郵件(Y=垃圾郵件,X=郵件內包含“免費”這個詞):
P(Y|X):郵件包含“免費”時是垃圾郵件的概率。
P(X|Y):垃圾郵件中包含“免費”的概率。
P(Y):郵件是垃圾郵件的概率。
P(X):郵件包含“免費”的概率。
樸素貝葉斯假設所有特征相互獨立,這使得我們無需考慮特征之間復雜的依賴關系,極大簡化了條件概率的計算:
P(X_1,X_2,…,X_n |Y)=P(X_1 |Y)?P(X_2 |Y)?…?P(X_n |Y)=∏_(j=1)^n?P(X_j |Y)
極大似然估計
在樸素貝葉斯法中,學習意味著估計先驗概率和條件概率。可以應用極大似然估計法估計相應的概率。
先驗概率P(Y=C_k )(Y為類C_k)的極大似然估計:
P(Y=C_k )=(∑_(i=1)^N?I(y_i=C_k ) )/N, k=1,2,…,K
條件概率P(X_j=a_jl |Y=C_k )(Y為類C_k時第j個特征X_j為a_jl)的極大似然估計:
P(X_j=a_jl |Y=C_k )=(∑_(i=1)^N?I(x_ji=a_jl,y_i=C_k ) )/(∑_(i=1)^N?I(y_i=C_k ) )
j=1,2,…,n; l=1,2,…,L; k=1,2,…,K
其中I為示性函數,取值為1或0。
貝葉斯估計
使用極大似然估計可能會出現所要估計的概率值為0的情況,這會影響到后驗概率的計算結果,使分類產生偏差。解決方法是改用貝葉斯估計。
先驗概率的貝葉斯估計:
P_λ (Y=C_k )=(∑_(i=1)^N?〖I(y_i=C_k )+λ〗)/(N+Kλ), k=1,2,…,K
條件概率的貝葉斯估計:
P_λ (X_j=a_jl |Y=C_k )=(∑_(i=1)^N?〖I(x_ji=a_jl,y_i=C_k )+λ〗)/(∑_(i=1)^N?I(y_i=C_k ) +Lλ)
j=1,2,…,n; l=1,2,…,L; k=1,2,…,K
式中λ≥0,當λ=0時就是極大似然估計,常取λ=1,這時稱為拉普拉斯平滑。
學習與分類過程
學習時,計算先驗概率:
P(Y=C_k ), k=1,2,…,K
和條件概率:
P(X_j=a_jl |Y=C_k ), j=1,2,…,n; l=1,2,…,L; k=1,2,…,K
分類時,根據給定的實例x=(x_1,x_2,…,x_n )計算后驗概率:
P(Y=C_k ) ∏_(j=1)^n?P(X_j=x_j |Y=C_k ) , k=1,2,…,K
并確定實例x屬于哪一個類別:
y=argmax_(c_k ) P(Y=C_k ) ∏_(j=1)^n?P(X_j=x_j |Y=C_k ) , k=1,2,…,K
決策樹
決策樹簡介
決策樹(Decision Tree)是一種基于樹形結構的算法,根據一系列條件判斷逐步劃分數據,縮小范圍,最終得出預測結果。決策樹由4部分組成:
根節點:樹的節點,包含所有數據。
內部節點:表示特征上的判斷條件。
分支:根據判斷條件分出的路徑。
葉節點:最終分類或回歸的結果。
決策樹適用于需要規則化、可解釋性和快速決策的場景,尤其在數據特征明確、樣本量適中的情況下表現良好。在復雜任務中,它常作為基礎模型,與集成學習結合(如隨機森林、梯度提升樹)以提升性能。
決策樹工作過程
決策樹的學習通常包括3個步驟:特征選擇、決策樹的生成和決策樹的剪枝。
如果特征數量很多,可以在決策樹學習之前對特征進行選擇,只留下對訓練數據有足夠分類能力的特征。
學習時通常是遞歸地選擇最優特征,并根據該特征對訓練數據進行劃分,使得對各個子數據集有一個最好的分類。首先構建根結點,將所有訓練數據都放在根結點。選擇一個最優特征,按照這一特征將訓練數據集劃分成子集,使得各個子集有一個在當前條件下最好的分類。如果這些子集已經能夠被基本正確分類,那么構建葉結點,并將這些子集分到所對應的葉結點中去;如果還有子集不能被基本正確分類,那么就對這些子集選擇新的最優特征,繼續對其進行劃分并構建相應的結點。如此遞歸直至所有訓練數據子集被基本正確分類,或者沒有合適的特征為止。最后每個子集都被分到葉結點上,即都有了明確的類,這就生成了一棵決策樹。決策樹的每次劃分都相當于在特征空間中引入一個超平面將當前空間一分為二。
以上方法生成的決策樹可能對訓練數據有很好的分類能力,但對未知的測試數據卻未必,即可能發生過擬合現象。因此需要對已生成的樹自下而上進行剪枝,將樹變得更簡單,從而使它具有更好的泛化能力。具體地,就是去掉過于細分的葉結點,使其回退到父結點或更高的結點,然后將父結點或更高的結點改為新的葉結點。
決策樹的生成只考慮局部最優,決策樹的剪枝則考慮全局最優。
特征選擇與決策樹生成
特征選擇在于選取對訓練數據具有分類能力的特征,這樣可以提高決策樹學習的效率。如果利用一個特征進行分類的結果與隨機分類的結果沒有很大差別,則稱這個特征是沒有分類能力的,經驗上扔掉這樣的特征對決策樹學習的精度影響不大。通常特征選擇的準則是信息增益或信息增益率。
信息熵
信息熵(Entropy)是表示隨機變量不確定性的度量,設X是一個取有限個值的離散隨機變量,其概率分布為:
P(X=x_i )=p_i, i=1,2,…,n
隨機變量X的熵定義為:
H(X)=-∑_(i=1)^n?〖p_i log?〖p_i 〗 〗
若p_i=0,則定義0 log?0=0。通常式中對數以2或e為底。熵只依賴于X的分布,與X的取值無關。熵越大,隨機變量的不確定性就越大。
設有隨機變量(X,Y),其聯合概率分布為:
P(X=x_i,Y=y_i )=p_ij, i=1,2,…,n; j=1,2,…,m
條件熵H(Y|X)表示在已知隨機變量X的條件下隨機變量Y的不確定性:
H(Y|X)=∑_(i=1)^n?P(X=x_i )H(Y|X=x_i )
信息增益與ID3
決策樹學習應用信息增益(Information Gain)準則選擇特征,給定訓練集數據D和特征A,熵H(D)表示對數據集進行分類的不確定性,條件熵H(D|A)表示在特征A給定條件下對數據集D進行分類的不確定性。兩者之差即信息增益:
g(D,A)=H(D)-H(D|A)
表示由于特征A而使得對數據集D的分類的不確定性減少的程度。對數據集D而言,信息增益依賴于特征,不同的特征具有不同的信息增益,信息增益大的特征具有更強的分類能力。在進行特征選擇時,對訓練數據集D計算每個特征的信息增益,并比較他們的大小,選擇信息增益最大的特征。
假設:
訓練數據集D有|D|個樣本
特征A有n個不同的取值{a_1,a_2,…,a_n},根據特征A將D劃分為n個子集D_1,D_2,…,D_n,D_i的樣本個數為|D_i |
有K個類C_k,每個類有|C_k |個樣本
子集D_i中屬于類C_k的樣本的集合為D_ik (D_ik=D_i∩C_k),D_ik的樣本個數為|D_ik |。
信息增益計算方法如下:
計算數據集D的熵H(D):
H(D)=-∑_(k=1)^K?〖|C_k |/|D| log_2?〖|C_k |/|D| 〗 〗
計算特征A對數據集D的條件熵H(D|A):
H(D|A)=∑_(i=1)^n?|D_i |/|D| H(D_i )=-∑_(i=1)^n?|D_i |/|D| ∑_(k=1)^K?〖|D_ik |/|D_i | log_2?〖|D_ik |/|D_i | 〗 〗
計算信息增益:
g(D,A)=H(D)-H(D|A)
ID3算法在決策樹各個節點上應用信息增益選擇特征,遞歸地構建決策樹。具體方法是:從根節點開始,計算所有可能的信息增益,選擇信息增益最大的特征作為節點特征,由該特征的不同取值建立子節點,再依次對子節點進行上述操作,直到所有特征信息增益均很小或無特征可選為止,最終生成一顆決策樹。
信息增益率與C4.5
使用信息增益劃分訓練數據集的特征,會傾向于選擇取值較多的特征。而使用信息增益率(Information Gain Ratio)可以對這一問題進行校正,這是特征選擇的另一個準則。
特征A對訓練數據集D的信息增益率g_R (D,A)定義為信息增益g(D,A)與訓練數據集D關于特征A的值的熵H_A (D)之比:
g_R (D,A)=(g(D,A))/(H_A (D) )
其中H_A (D)=-∑_(i=1)^n?〖|D_i |/|D| log_2?〖|D_i |/|D| 〗 〗,n是特征A的取值個數。
C4.5算法與ID3算法相似,但對其進行了改進,使用信息增益率來選擇特征。
基尼指數與CART
有K個類,樣本屬于第k類的概率為p_k,則概率分布的基尼指數:
Gini§=∑_(k=1)^K?〖p_k (1-p_k )=1-〗 ∑_(k=1)K?p_k2
對于給定的樣本集合D,其基尼指數:
Gini(D)=1-∑_(k=1)^K?(|C_k |/|D| )^2
這里C_k是D中屬于第k類的樣本子集,K是類的個數。
如果樣本集合D根據特征A是否取某一可能值a被劃分為兩個子集D_1,D_2,則在特征A的條件下,集合D的基尼指數:
Gini(D,A)=|D_1 |/|D| Gini(D_1 )+|D_2 |/|D| Gini(D_2 )
基尼指數Gini(D)表示集合D的不確定性,基尼指數Gini(D,A)表示經A=a劃分后集合D的不確定性。基尼指數越大樣本集合的不確定性也越大,這與信息熵相似。
CART決策樹是一棵二叉樹,根據基尼指數生成決策樹,對訓練數據集D的每個特征A的每一個可能的取值a,計算A=a時的基尼指數,選擇基尼指數最小的特征及其對應的切分點作為最優特征與最優切分點,并生成兩個子節點,將訓練數據集依特征分配到兩個子節點中。重復上述過程,直到節點中樣本數小于閾值、或樣本集的基尼指數小于閾值、或沒有個更多特征。
CART回歸樹
一顆回歸樹對應著輸入空間(特征空間)的劃分,以及在劃分上的輸出值。將輸入空間劃分為M個單元R_1,R_2,…,R_M,并且在每個單元R_m上有一個固定輸出c_m的回歸樹模型可表示為:
f(x)=∑_(m=1)^M?〖c_m I(x∈R_m ) 〗
在訓練數據集所在的空間中,遞歸地將每個區域劃分為兩個子區域并決定每個子區域上的輸出值,構建二叉決策樹。每次劃分的目標是找到一個特征j和該特征的一個切分點s,使得劃分后的誤差最小。在對輸入空間進行劃分時,將特征j和它的取值s(通常是連續特征取值的中間點)作為切分變量和切分點,定義兩個區域:
R_1 (j,s)={x|x_j≤s} 和 R_2 (j,s)={x|x_j>s}
然后尋找最優切分變量j和最優切分點s。具體地,使用平方誤差作為損失函數,求解:
min┬(j,s)?[min┬(c_1 )?∑_(x_i∈R_1 (j,s))?(y_i-c_1 )^2 +min┬(c_2 )?∑_(x_i∈R_2 (j,s))?(y_i-c_2 )^2 ]
解出最優切分變量j和最優切分點s后,使用最優切分變量j和最優切分點s后劃分兩個區域。重復上述過程直到滿足停止條件為止。最終葉節點的輸出值為該區域內所有樣本目標值的均值:
c ?_m=ave(y_i |x_i∈R_m (j,s))
由此生成一顆回歸樹,這樣的回歸樹稱之為最小二乘回歸樹。
決策樹的剪枝
決策樹出現過擬合的原因在于學習時過多的考慮如何提高對訓練數據的正確分類,從而構建出過于復雜的決策樹。為了避免過擬合,可以對已生成的決策樹進行剪枝,從決策樹上裁掉一些子樹或葉節點,并將其根節點或父節點作為新的葉節點,從而簡化模型。決策樹的剪枝通常分為預剪枝(Pre-Pruning)和后剪枝(Post-Pruning)。
預剪枝是在決策樹生成過程中,通過設置一些限制條件提前停止樹的生長,避免過度分裂。常見的停止條件有:限制最大樹深度、限制每個節點最小樣本數、限制最小的誤差減少量、限制最大葉節點數量等。但過于嚴格的停止條件可能導致欠擬合,并且可能難以確定最佳閾值,需要多次嘗試。
后剪枝是在決策樹完全生成之后,基于某種評估準則從底部向上逐步判斷是否移除分支。常見的后剪枝方法有代價復雜度剪枝(Cost-Complexity Pruning,CCP)和減少誤差剪枝(Reduced Error Pruning,REP)等。
代價復雜度剪枝需要首先計算子樹的損失函數:
C_α (T)=C(T)+α|T|
T為任意子樹,|T|為子樹的葉節點個數
C(T)為對訓練數據的預測誤差(如基尼指數)
α≥0為參數,權衡訓練數據的擬合程度和模型的復雜度。α越大越傾向于剪掉子樹,生成更簡單的樹。
C_α (T)為參數是α時子樹T的整體損失
從α=0開始,逐漸增加α。對于每個α,選擇剪掉使C_α (T)最小的子樹。生成一系列剪枝后的樹,使用交叉驗證選擇最優的α和對應的樹。
減少誤差剪枝則是直接基于驗證集的誤差來判斷是否剪枝。剪枝過程遍歷每個內部節點,將該子樹替換為一個葉節點并在驗證集上比較替換前后的誤差,如果替換后誤差沒有增加則剪掉該子樹。
支持向量機
支持向量機簡介
支持向量機(Support Vector Machines,SVM)是一種二分類模型。其核心目標是尋找一個“間隔最大”的超平面將不同類別的數據點分隔開。這個超平面在二維空間中是一條直線,在三維空間中是一個平面,在更高維空間中則是一個超平面。
間隔最大代表該超平面與最近的數據點之間的距離最大,這使得支持向量機有較強的泛化能力。
支持向量機學習方法包括由簡至繁的模型:線性可分支持向量機、線性支持向量機以及非線性支持向量機。
線性可分支持向量機-硬間隔
硬間隔
當訓練樣本線性可分時,此時可以通過最大化硬間隔來學習線性可分支持向量機。硬間隔是指超平面能夠將不同類的樣本完全劃分開。距離超平面最近的幾個樣本點稱為支持向量,它們直接決定超平面的位置和方向,只要支持向量不變,超平面就不會變。
在樣本空間中,超平面可表示為
w^T x+b=0
其中w=(w_1,w_2,…,w_n )為法向量,決定了超平面的方向;b為位移項,決定了超平面與原點之間的距離。將超平面記為(w,b)
相應的分類函數稱為線性可分支持向量機:
f(x)=sign(w^T x+b)
間隔與最大間隔
x’為超平面上一點,w^T x^‘+b=0,樣本空間中任一點x到超平面(w,b)的距離為:
r=|w^T/‖w‖ (x-x’)|=|w^T x+b|/‖w‖
記每個樣本點x_i的類別為y_i,該樣本點的函數間隔γ ?_i=y_i (w^T x+b),表示分類預測的正確性及確信度,若超平面(w,b)能將樣本正確分類,則有
{■(w^T x_i+b>0, y_i=+1@w^T x_i+b<0, y_i=-1)┤
此時有
y_i (w^T x+b)=|w^T x+b|>0
r_i=|w^T x_i+b|/‖w‖ =(y_i (w^T x_i+b))/‖w‖ =γ ?_i/‖w‖
我們注意到對w,b進行縮放變換w→λw,b→λb時,不會改變超平面,也不會改變r的值,但函數間隔γ ?_i=y_i (w^T x_i+b)會隨著縮放w和b而發生變化。也就是說可以通過縮放w和b來任意縮放函數間隔γ ?_i而不改變r_i。
因此令支持向量到超平面的函數間隔γ ?_i=1,此時支持向量到超平面的距離r_i=γ ?_i/‖w‖ =1/‖w‖ 。兩個異類支持向量到超平面的距離之和γ=2/‖w‖ ,γ被稱為“間隔”。
欲找到具有最大間隔的超平面,也就是求在約束y_i (w^T x_i+b)≥1下最大的γ:
█(max┬(w,b)& 2/‖w‖ @s.t.& y_i (w^T x_i+b)≥1)
等價于:
█(min┬(w,b)& ‖w‖^2/2@s.t.& y_i (w^T x_i+b)≥1)
s.t.為Subject to,意為約束。
上式就是支持向量機的基本型。對上式使用拉格朗日乘子法得到其對偶問題,從對偶問題中解出拉格朗日乘子,進而解出w,b,即可得到具有最大間隔的超平面。
線性支持向量機-軟間隔
先前我們假定訓練樣本在樣本空間中線性可分,但現實中很可能并非如此,此時我們無法找出一個合適的超平面將所有樣本點完全正確劃分。通常訓練數據中會有一些特異點,如果將這些特異點去掉,剩下大部分樣本點是線性可分的。這時我們可以放寬條件,允許某些樣本分錯,為此我們引入軟間隔。
線性不可分意味著某些樣本點(x_i,y_i )不能滿足約束條件y_i (w^T x_i+b)≥1。為解決這個問題,可以對每個樣本點引進一個松弛變量ξ_i≥0,使得函數間隔加上松弛變量≥1。這時約束條件變為:
y_i (w^T x_i+b)≥1-ξ_i
同時為了在最大化間隔的時候使不滿足約束的樣本盡可能少,目標函數中引入對誤分類的懲罰:
‖w‖2/2+C∑_(i=1)n?ξ_i
這里C>0為懲罰系數,C值越大對誤分類的懲罰越大。
線性不可分的線性支持向量機的學習問題可表示如下:
█(min┬(w,b,ξ)& ‖w‖2/2+C∑_(i=1)n?ξ_i @s.t.& y_i (w^T x_i+b)≥1-ξ_i )
這就是軟間隔支持向量機。
非線性支持向量機-核函數
非線性分類問題是指通過利用非線性模型才能很好地進行分類的問題,如下圖是無法直接使用超平面對其分類的:
這時我們可以通過核函數將數據從原始空間映射到高維特征空間,使得數據在高維特征空間線性可分,將原本的非線性問題轉換為線性問題。使用核技巧學習非線性支持向量機,等價于隱式地在高維特征空間中學習線性支持向量機。
?(x)表示將x映射后的特征向量,在特征空間中超平面可表示為:
w^T ?(x)+b=0
并且有:
█(min┬(w,b)& ‖w‖^2/2@s.t.& y_i (w^T ?(x_i )+b)≥1)
將其轉化為對偶問題并求解,但其對偶問題涉及到計算?(x_i )^T ?(x_j ),這是樣本x_i和樣本x_j映射到特征空間之后的內積。由于特征空間維度很高,因此直接計算?(x_i )^T ?(x_j )通常非常困難,為了避開這一障礙,設想這樣一個函數:
κ(x_i,x_j )=??(x_i ),?(x_j )?=?(x_i )^T ?(x_j )
κ就是核函數。顯然若已知映射函數?就可寫出核函數,但實際任務中我們通常不知道?的形式,那么如何判斷給定的κ是否是核函數呢?
實際上,只要一個對稱函數所對應的核矩陣半正定,它就能作為核函數使用。這個定義在構造核函數時很有用,但對于一個具體函數κ,檢驗它是否為正定核函數并不容易,因此實際中往往使用已有的核函數。
核函數的選擇也是支持向量機最大的變數,若核函數選擇不合適,意味著將樣本映射到了一個不合適的特征空間,很可能導致性能不佳。下面是幾種常用的核函數:
█(線性核 κ(x_i,x_j )&=x_i^T x_j@多項式核 κ(x_i,x_j )&=(x_i^T x_j )^d@高斯核 κ(x_i,x_j )&=exp?(-‖x_i-x_j ‖2/(2σ2 ))@拉普拉斯核 κ(x_i,x_j )&=exp?(-‖x_i-x_j ‖/σ)@Sigmoid核 κ(x_i,x_j )&=tanh?(βx_i^T x_j+θ) )
集成學習
集成學習(Ensemble Learning)通過某種策略組合多個個體學習器的預測結果來提高整體的預測能力。只包含同種類型的個體學習器的集成稱為同質集成,例如決策樹集成中全是決策樹,同質集成中的個體學習器亦稱基學習器,相應的學習算法稱為基學習算法。包含不同類型的個體學習器的集成稱為異質集成,例如同時包含決策樹和神經網絡。
集成學習有三大經典方法:Boosting、Bagging和Stacking。
Boosting(提升方法)按順序訓練模型,每個模型關注前一個模型的錯誤,通過加權調整來優化整體預測。如AdaBoost通過給錯分的樣本更大的權重,逐步改進;梯度提升樹用梯度下降法優化損失函數;XGBoost和LightGBM是高效的梯度提升樹變種。Boosting主要關注于降低偏差。
Bagging(Bootstrap Aggregating,自助聚合)從原始數據集中通過有放回的對樣本采樣生成多個子數據集,分別訓練多個獨立模型,最后通過投票(分類)或平均(回歸)得到結果。隨機森林則是在Bagging基礎上隨機選擇特征子集訓練每棵樹。Bagging主要關注于降低方差。
Stacking(堆疊)訓練多個不同類型的個體學習器,之后使用一個元模型綜合多個個體學習器的預測。靈活性強,能結合多種模型的優勢。
AdaBoost
在概率近似正確學習的框架中,一個概念如果存在一個多項式的學習算法能夠學習它,并且正確率很高,就稱這個概念是強可學習的;一個概念如果存在一個多項式的學習算法能夠學習它,但正確率僅比隨機猜測略好,就稱這個概念是弱可學習的。后來證明,強可學習與弱可學習是等價的。那么如果已經發現了弱學習算法,能否通過某種方式將其提升為強學習算法?
對于分類問題而言,給定一個訓練樣本集,求比較粗糙的分類規則(弱分類器)要比求精確的分類規則(強分類器)容易的多。Boosting就是從弱學習算法出發,反復學習,得到一系列弱分類器,然后組合這些弱分類器構成一個強分類器。AdaBoost通常使用單層決策樹作為基學習器,單層決策樹也被稱為決策樹樁(Decision Stump)。
大多數Boosting都是改變訓練數據的概率分布(權重分布),針對不同的訓練數據分布調用弱學習算法學習一系列弱分類器。AdaBoost(Adaptive Boosting,自適應提升)的做法是提高被前一輪弱分類器錯誤分類的樣本的權重,降低被正確分類的樣本的權重。這樣一來后一輪弱學習器會更加關注那些沒有被正確分類的數據。同時采用加權多數表決的方法,加大分類誤差率小的弱分類器的權重,減小分類誤差率大的弱分類器的權重。
AdaBoost工作流程如下:
初始化訓練數據權重分布,通常均勻分布:
D_(m=1)=(w_1,1,…w_(1,i),…w_(1,N) ), w_1i=1/N; i=1,2,…,N; m=1,2,…,M
使用具有權重分布D_m的訓練數據集學習,得到基本分類器:
G_m (x):χ→{-1,+1} (G_m (x)將輸入映射到兩個值-1和+1)
計算G_m (x)在訓練數據集上的分類誤差率:
e_m=∑_(i=1)^N?〖w_mi I(G_m (x_i )≠y_i ) 〗
計算弱分類器G_m (x)的權重:
a_m=1/2 ln?〖(1-e_m)/e_m 〗
更新訓練數據集的權重分布:
D_(m+1)=(w_(m+1,1),…w_(m+1,i),…w_(m+1,N) )
其中:w_(m+1,i)=(w_(m,1) exp?(-a_m y_i G_m (x_i )))/(∑_(i=1)^N?〖w_(m,i) exp?(-a_m y_i G_m (x_i )) 〗), i=1,2,…,N
構建基本分類器的線性組合,得到最終分類器:
G(x)=sign(∑_(m=1)^M?〖a_m G_m (x) 〗)
隨機森林
隨機森林是Bagging的一個變體,在以決策樹為基學習器構建Bagging集成的基礎上,進一步在決策樹訓練過程中引入了隨機屬性選擇。
具體來說,傳統決策樹在選擇劃分特征時是在當前節點的特征集合(假定有d個特征)中選擇最優特征。而在隨機森林中,基決策樹的每個節點先從該節點的特征集合中隨機選擇一個包含k個特征的子集,然后再從這個子集中選擇一個最優特征用于劃分。參數k控制著隨機性的引入程度,若k=d,則基決策樹的生成與傳統決策樹相同;若k=1,則隨機選擇一個屬性用于劃分。一般推薦k=log_2?d。
隨機森林簡單易實現,但在很多任務中都展現出了強大性能,被譽為“代表集成學習技術水平的方法”。Bagging中基學習器的多樣性僅來自于樣本擾動,而隨機森林中基學習器的多樣性不僅來自樣本擾動,還來自特征擾動,這就使得最終集成的泛化性能可通過基學習器之間差異度的增加而進一步提升。
無監督學習
聚類
聚類簡介
聚類(Clustering)旨在將數據集中的樣本分成若干個簇,使得同一個簇內的對象彼此相似,不同簇間的對象差異較大。聚類是一種無監督學習算法,不需要預先標記數據的標簽,完全依賴數據本身內在結構和特征來進行分組,最終簇所對應的概念語義需由使用者來把握和命名。
聚類的核心是“物以類聚”,具體通過以下步驟實現:
定義相似性:選擇一個度量標準(如歐氏距離,余弦相似度)來衡量對象之間的相似性或距離。
分組:根據相似性將對象分配到不同的簇中。
優化:通過迭代或直接計算,調整簇的劃分,使簇內相似性最大化,簇間差異最大化。
聚類應用場景:
市場細分:將消費者按購買習慣分組。
圖像分割:將圖像像素按顏色或紋理聚類。
異常檢測:識別不屬于任何主要簇的異常點。
生物信息:對基因表達數據進行分組。
常見聚類算法
K均值聚類
K均值聚類介紹
K均值聚類(K-means)是基于樣本集合劃分的聚類方法,將樣本集合劃分為k個子集構成k個簇,將n個樣本分到k個簇中,每個樣本到其所屬簇的中心的距離最小。每個樣本只能屬于一個簇,所以K均值聚類是硬聚類。
K均值聚類歸結為樣本集合的劃分,通過最小化損失函數來選取最優的劃分C^。
首先使用歐氏距離平方作為樣本之間的距離:
d(x_i,x_j )=‖x_i-x_j ‖^2
定義樣本與其所屬簇的中心之間的距離總和作為損失函數:
W?=∑_(l=1)^k?∑_(C(i)=l)?‖x_i-x ?_l ‖^2
x ?_l:第l個簇的中心。
C(i)=l:第i個樣本是否屬于簇l。
K均值聚類就是求解最優化問題:
C^=〖arg min┬c〗?W?=〖arg min┬c〗?∑_(l=1)^k?∑_(C(i)=l)?‖x_i-x ?_l ‖^2
相似的樣本被聚到同一個簇時損失函數最小。這是一個組合優化問題,n個樣本分到k個簇,所有可能的分法數目S(n,k)=1/k! ∑_(l=1)k?〖(-1)(k-1) (■(k@l)) 〗 k^n,這個數目是指數級的,現實中采用迭代的方法求解。
K均值聚類工作流程
初始化,隨機選擇k個樣本點作為初始簇中心。
對樣本進行聚類,計算每個樣本到各個簇中心的距離,將每個樣本分到與其最近的簇,構成聚類結果。
計算聚類結果中每個簇中所有樣本的均值,作為新的簇中心。
使用新的簇中心重復上述過程,直到收斂或符合停止條件(例如劃分不再改變)。
K均值聚類特點
K均值聚類的初始中心的選擇會直接影響聚類結果,并且不適合非凸形狀簇。
K均值聚類需要事先指定簇個數k,而實際中最優的k值是不知道的,需要嘗試使用不同的k值檢驗聚類結果質量,可以采用二分查找快速找到最優k值。聚類結果的質量可以用簇的平均直徑來衡量,一般地,簇個數變小時平均直徑會增加;簇個數變大超過某個值后平均直徑會不變,而這個值正是最優的k值。
層次聚類
層次聚類(Hierarchical Clustering)假設簇之間存在層次結構,將樣本聚到層次化的簇中。層次聚類有自下而上的聚合方法和自上而下的分裂方法。因為每個樣本只屬于一個簇,所以層次聚類屬于硬聚類。
聚合聚類:開始將每個樣本各自分到一個簇,之后將相距最近的兩個簇合并,如此往復直至滿足停止條件(例如達到預設的簇的個數、每個簇只包含一個樣本、簇內樣本相似性達到某個閾值等)。
分裂聚類:開始將整個數據集視作一個整體,之后根據某種距離或相似性度量,選擇一個現有的簇將其分裂成兩個簇,使分裂后子簇內相似性高,子簇間差異大,如此往復直至滿足停止條件。
密度聚類
密度聚類(Density-Based Clustering)假設聚類結構能通過樣本分布的緊密程度確定。通常情況下,密度聚類算法從樣本密度的角度來考察樣本之間的可連接性,并基于可連接樣本不斷擴展簇以獲得最終聚類效果。
DBSCAN是一種著名的密度聚類算法,基于鄰域參數來刻畫樣本分布的緊密程度。對于給定數據集D={x_1,x_2,…,x_m },定義下列概念:
ε-鄰域:對于x_j∈D,其ε-鄰域包含樣本集D中與x_j的距離不大于ε的樣本。
核心對象:若x_j的ε-鄰域至少包含MinPts個對象,則x_j是一個核心對象。
密度直達:若x_j位于x_i的ε-鄰域中,且x_i是核心對象,則稱x_j由x_i密度直達。
密度可達:對x_i和x_j,若存在樣本序列p_1,p_2,…,p_n,其中p_1=x_i,p_n=x_j,且p_(i+1)由p_i密度直達,則稱x_j由x_i密度可達。
密度相連:對x_i和x_j,存在x_k使得x_i和x_j均由x_k密度可達,則稱x_j由x_i密度相連。
噪聲點:不屬于任何簇的點,既不是核心對象也不在核心對象鄰域內。
基于這些概念,DBSCAN將簇定義為由密度可達關系導出的最大密度相連樣本集合。DBSCAN先根據鄰域參數(ε、MinPts)找出所有核心對象,再以任一核心對象為出發點找出由其密度可達的樣本生成一個簇,直到所有核心對象均被訪問過為止。
密度聚類能識別任意形狀的簇,可以自動識別并排除噪聲點。但ε、MinPts的選擇對密度聚類結果影響較大,且密度聚類難以適應密度變化較大的數據集。
K-means API使用
kmeans = KMeans(n_clusters=3)
n_clusters: 指定 K 的值
kmeans.fit(X) # 訓練
kmeans.predict(X) # 預測
kmeans.fit_predict(X) # 訓練并預測
示例代碼:
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
plt.rcParams[“font.sans-serif”] = [“KaiTi”]
plt.rcParams[“axes.unicode_minus”] = False
使用 make_blobs 生成 3 個簇,每個簇 100 個點
X, y_true = make_blobs(n_samples=300, centers=3, cluster_std=2)
fig, ax = plt.subplots(2, figsize=(8, 8))
ax[0].scatter(X[:, 0], X[:, 1], s=50, c=“gray”, label=“原始數據”)
ax[0].set_title(“原始數據”)
ax[0].legend()
使用 K-Means 聚類
kmeans = KMeans(n_clusters=3)
kmeans.fit(X)
y_kmeans = kmeans.predict(X) # 預測每個點的簇標簽
centers = kmeans.cluster_centers_ # 獲取簇中心
ax[1].scatter(X[:, 0], X[:, 1], s=50, c=y_kmeans)
ax[1].scatter(centers[:, 0], centers[:, 1], s=200, c=“red”, marker=“o”, label=“簇中心”)
ax[1].set_title(“K-means 聚類結果 (K=3)”)
ax[1].legend()
plt.show()
聚類模型評估(了解)
由于聚類任務沒有預定義的標簽(不像監督學習有真實類別可供比較),所以需要依賴聚類結果和原始數據來衡量模型的好壞,主要關注簇內的緊湊性和簇間的分離性。
輪廓系數(Silhouette Coefficient)
計算每個樣本到同簇其他樣本的平均距離(內聚度a_i)和到最近其他簇樣本的平均距離(分離度b_i),綜合評價聚類緊密度和分離度。
s_i=(b_i-a_i)/max?(a_i,b_i ) ∈[-1,1]
s_i的值越接近1,聚類效果越好。總體輪廓系數是所有s_i的平均值。
簇內平方和(Within-Cluster Sum of Squares)
衡量簇內數據點到簇中心的總距離平方和,常用于K-means。
WCSS=∑_(k=1)^K?∑_(i∈C_k)?‖x_i-μ_k ‖^2
其中μ_k是第k個簇的中心。
肘部法
肘部法用于確定最佳簇數K,在使用K-means時非常常見,它通過繪制簇數K和某個聚類質量指標(通常是簇內平方和)的關系曲線,找到一個拐點或“肘部”,即增加簇數帶來的收益顯著減少的點,這個點通常被認為是最佳的K值。
CH指數(Calinski-Harabasz Index)
簇間和簇內分散度的比值,也稱方差比準則:
CH=(BCSS/(K-1))/(WCSS/(N-K))
BCSS=∑_(k=1)^K?〖n_k ‖μ_k-μ‖〗^2
WCSS=∑_(k=1)^K?∑_(i∈C_k)?‖x_i-μ_k ‖^2
BCSS:簇間平方和,n_k是第k個簇的樣本數,μ_k為第k個簇的中心,μ是所有樣本的中心。
WCSS:簇內平方和。
聚類評估API使用
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
from sklearn.metrics import silhouette_score, calinski_harabasz_score
plt.rcParams[“font.sans-serif”] = [“SimHei”]
plt.rcParams[“axes.unicode_minus”] = False
使用 make_blobs 生成 3 個簇,每個簇 100 個點
X, y_true = make_blobs(n_samples=300, centers=3, cluster_std=5)
使用 K-Means 聚類
kmeans = KMeans(n_clusters=3)
kmeans.fit(X)
y_kmeans = kmeans.predict(X) # 預測每個點的簇標簽
centers = kmeans.cluster_centers_ # 獲取簇中心
plt.scatter(X[:, 0], X[:, 1], s=50, c=y_kmeans, cmap=“viridis”)
plt.scatter(centers[:, 0], centers[:, 1], s=200, c=“red”, marker=“*”, label=“簇中心”)
plt.legend()
print(“簇內平方和:”, kmeans.inertia_)
print(“輪廓系數:”, silhouette_score(X, y_kmeans))
print(“CH指數:”, calinski_harabasz_score(X, y_kmeans))
plt.show()
降維(了解)
奇異值分解
奇異值分解簡介
奇異值分解(Singular Value Decompositon,SVD)是一種矩陣因子分解方法,用于將矩陣分解為更簡單的形式,從而揭示數據的內在結構和特性。通過保留最大的幾個奇異值及其對應的奇異向量,可以近似重構原始矩陣,減少數據維度,同時保留主要信息。主成分分析,潛在語義分析等都用到了奇異值分解。
矩陣的奇異值分解是指將一個非零的實矩陣A∈R^(n×p)表示為三個矩陣的乘積(因子分解)的形式:
A=UΣV^T
U是n階正交矩陣:UU^T=I
V是p階正交矩陣:VV^T=I
Σ是由降序排列的非負的對角元素組成的n×p矩形對角陣:
Σ=diag(σ_1,σ_2,…,σ_p ), σ_1≥σ_2≥?≥σ_p≥0, p=min?(n,p)
UΣV^T稱為矩陣A的奇異值分解,σ_i稱為矩陣A的奇異值,U的列向量稱為左奇異向量,V的列向量稱為右奇異向量。任一實矩陣一定存在奇異值分解,且奇異值分解不唯一。
例:
A=[■(1&0&0&0@0&0&0&4@0&3&0&0@0&0&0&0@2&0&0&0)]
它的奇異值分解由UΣVT給出,U、Σ、VT分別為:
U=[■(0&0&√0.2&0&√0.8@1&0&0&0&0@0&1&0&0&0@0&0&0&0&0@0&0&√0.8&0&-√0.2)], Σ=[■(4&0&0&0@0&3&0&0@0&0&√5&0@0&0&0&0@0&0&0&0)], V^T=[■(0&0&0&1@0&1&0&0@1&0&0&0@0&0&1&0)]
奇異值分解算法
矩陣A的奇異值分解可以通過求對稱矩陣A^T A的特征值和特征向量得到。A^T A的單位化特征向量構成正交矩陣V的列;A^T A的特征值的平方根為奇異值σ_i,對其由大到小排列作為對角線元素構成對角矩陣Σ;求正奇異值對應的左奇異向量,再求擴充的A^T的標準正交基,構成正交矩陣U的列。具體過程如下:
首先求A^T A的特征值和特征向量:
(A^T A-λI)x=0
得到特征值并將其由大到小排序:
λ_1≥λ_2≥?≥λ_p≥0
將特征值帶入方程求出對應的特征向量,并將特征向量單位化,得到單位特征向量構成正交矩陣V:
V=[■(v_1&v_2&…&v_p )]
特征值的平方根構成n×p矩形對角陣Σ:
Σ=diag(√(λ_1 ),√(λ_2 ),…,√(λ_p ))
對A的正奇異值計算U的列向量,A的秩為r:
u_j=1/σ_j Av_j, j=1,2,…,r
U_1=[■(u_1&u_2&…&u_r )]
若n>r,則需要補充額外的正交向量使U成為n×n矩陣。求A^T的零空間的一組標準正交基{u_(r+1),u_(r+2),…,u_n }:
U_2=[■(u_(r+1)&u_(r+2)&…&u_n )]
U=[■(U_1&U_2 )]
以求A=[■(1&1@2&2@0&0)]的奇異值分解為例:
A^T A=[■(1&2&0@1&2&0)][■(1&1@2&2@0&0)]=[■(5&5@5&5)]
(A^T A-λI)x=0
得到齊次線性方程組:
{■((5-λ) x_1+5x_2=0@5x_1+(5-λ) x_2=0)┤
該方程組有非零解的充要條件是:
|■(5-λ&5@5&5-λ)|=0
λ^2-10λ=0
解的λ_1=10,λ_2=0,代入線性方程組,得到對應的單位向量:
v_1=[■(1/√2@1/√2)], v_2=[■(1/√2@-1/√2)]
V=[■(1/√2&1/√2@1/√2&-1/√2)]
奇異值σ_1=√(λ_1 )=√10,σ_2=√(λ_2 )=0,構造對角矩陣:
Σ=[■(√10&0@0&0@0&0)]
基于A的正奇異值計算得到列向量u_1:
u_1=1/σ_1 Av_1=1/√10 [■(1&1@2&2@0&0)][■(1/√2@1/√2)]=[■(1/√5@2/√5@0)]
列向量u_2,u_3是AT的零空間N(AT )的一組標準正交基,為此求解下面線性方程組:
A^T x=[■(1&2&0@1&2&0)][■(x_1@x_2@x_3 )]=[■(0@0)]
█(x_1+2x_2+0x_3=&0@x_1=&-2x_2 )
分別取(x_2,x_3 )為(1,0)和(0,1)得到N(A^T )的基:
[■(-2@1@0)], [■(0@0@1)]
正交基為:
u_2=[■(-2/√5@1/√5@0)], u_3=[■(0@0@1)]
構造正交矩陣U:
U=[■(1/√5&-2/√5&0@2/√5&1/√5&0@0&0&1)]
最終得到矩陣A的奇異值分解:
A=UΣV^T=[■(1/√5&-2/√5&0@2/√5&1/√5&0@0&0&1)][■(√10&0@0&0@0&0)][■(1/√2&1/√2@1/√2&-1/√2)]
上述過程只是為了說明計算的過程,實際應用中不會使用此算法。實際應用中雖然也會求解A^T A的特征值,但不直接計算A^T A。
緊湊奇異值分解與截斷奇異值分解
A=UΣV^T又稱矩陣的完全奇異值分解,實際常用的是奇異值分解的緊湊形式和截斷形式。緊湊奇異值分解是與原始矩陣等秩的奇異值分解,截斷奇異值分解是比原始矩陣低秩的奇異值分解。
緊湊奇異值A=U_r Σ_r V_rT,r為矩陣A的秩。U_r∈R(n×r)取U的前r列,Σ_r是r階對角矩陣,V_r∈R^(p×r)取V的前r列。
例如:
A=[■(1&0&0&0@0&0&0&4@0&3&0&0@0&0&0&0@2&0&0&0)], r=3
U_r=[■(0&0&√0.2@1&0&0@0&1&0@0&0&0@0&0&√0.8)], Σ_r=[■(4&0&0@0&3&0@0&0&√5)], V_r^T=[■(0&0&0&1@0&1&0&0@1&0&0&0)]
截斷奇異值A≈U_k Σ_k V_kT只取最大的k個奇異值對應的部分。U_k∈R(n×k)取U的前k列,Σ_k取Σ的前k個對角線元素,V_k∈R^(p×k)取V的前k列。
例如:
A=[■(1&0&0&0@0&0&0&4@0&3&0&0@0&0&0&0@2&0&0&0)], r=2
U_2=[■(0&0@1&0@0&1@0&0@0&0)], Σ_2=[■(4&0@0&3)], V_2^T=[■(0&0&0&1@0&1&0&0)]
A_2=U_2 Σ_2 V_2^T=[■(0&0&0&0@0&0&0&4@0&3&0&0@0&0&0&0@0&0&0&0)]
主成分分析
主成分分析簡介
主成分分析(Principal Component Analysis,PCA)是一種常用的無監督學習方法,旨在找到數據中“最重要的方向”,即方差最大的方向,并用這些方向重新表達數據。
在主成分分析過程中,首先將數據的每個特征規范化為平均值為0方差為1,以消除不同特征之間量綱的差異,再使用正交變換把線性相關的原始數據轉換為線性無關的新數據(主成分)。主成分彼此正交并且能夠最大化地保留原始數據的方差信息。主成分分析主要用于降維和發現數據的基本結構。
主成分分析可直觀解釋為對數據所在的原始坐標系進行旋轉變換,將數據投影到新坐標系的坐標軸上,新坐標系的第一坐標軸、第二坐標軸等分別表示第一主成分、第二主成分等。數據在每一軸上的坐標值的平方表示相應變量的方差,并且這個坐標系是所有可能的新坐標系中,坐標軸上的方差的和最大的。
在數據總體上進行的主成分分析稱為總體主成分分析,在有限樣本上進行的主成分分析稱為樣本主成分分析。在實際問題中,通常需要在觀測數據上進行主成分分析,也就是樣本主成分分析。
傳統的主成分分析通過協方差矩陣或相關矩陣的特征值分解進行。
協方差矩陣描述變量之間的方差和協方差,適用于未標準化的數據;
相關矩陣描述變量之間的標準化相關性,適用于標準化的數據。
特征值分解的結果給出了主成分的方向(特征向量)和每個主成分的方差(特征值)。
現在常用的方法是通過奇異值分解進行主成分分析。
相關矩陣特征值分解實現主成分分析
給定的樣本數據每行為一個樣本,每列為一個特征,對其進行規范化使其每列均值為0方差為1,得到X。對于標準化后的數據,其相關矩陣等于協方差矩陣。X的相關矩陣:
R=1/(n-1) X^T X∈R^(p×p)
求解特征方程|R-λI|=0,得到p個特征值λ_1,λ_2,…,λ_p,降序排列作為主成分的方差。
將解得的特征值代入特征方程求出對應的單位特征向量v_1,v_2,…,v_p,作為主成分方向。
根據特征值計算每個主成分的方差貢獻率
方差貢獻率=λ_i/(∑_(i=1)^p?λ_i ), 累計方差貢獻率=(∑_(j=1)^k?λ_j )/(∑_(i=1)^p?λ_i )
根據累計方差貢獻率選擇前k個主成分(如選擇累計方差貢獻率大于90%的前k個主成分),取V的前k列構成V_k。
將數據投影到主成分方向,得到主成分Y=XV_k。
下面是一個主成分分析的例子:
給定樣本數據X。當使用樣本均值替代總體均值時,偏差平方和會系統性低估總體方差,因此使用樣本標準差√((∑_(i=1)^n?(x_i-x ? )^2 )/(n-1))代替總體標準差,n-1提供無偏估計:
X=[■(2&3&5@4&6&10@1&2&3@5&7&11@3&4&6)] □(→┴規范化 ) X=[■(-0.6325&-0.6751&-0.5898@0.6325&0.7716&0.8847@-1.2649&-1.1574&-1.1795@-1.2649&1.2538&1.1795@0.0&-0.1929&-0.2949)]
計算相關矩陣,對于標準化后的數據,其相關矩陣等于協方差矩陣:
R=(X^T X)/(n-1)=[■(1.0&0.9912&0.9791@0.9912&1.0&0.9954@0.9791&0.9954&1.0)]
對R進行特征值分解,得到特征值和特征向量:
λ_1=2.9772,λ_2=0.0021,λ_3=0.0002
v_1=[■(-0.5760@-0.5792@-0.5768)],v_2=[■(-0.7530@0.1013@0.6502)],v_3=[■(0.3182@-0.8089@0.4945)]
選擇前兩個作為主成分方向進行投影,得到第一、第二主成分:
█(Y=&XV@=&[■(-0.6325&-0.6751&-0.5898@0.6325&0.7716&0.8847@-1.2649&-1.1574&-1.1795@-1.2649&1.2538&1.1795@0.0&-0.1929&-0.2949)][■(-0.5760&-0.7530@-0.5792&0.1013@-0.5768&0.6502)]@=&[■(1.0955&0.0244@-1.3215&0.1771@2.0794&0.0683@-2.1352&-0.0585@0.2818&-0.2113)] )
奇異值分解實現主成分分析
通過奇異值分解實現主成分分析可以避免計算協方差矩陣或相關矩陣,可以提高計算效率。
計算過程如下:
對規范化后的樣本矩陣X進行奇異值分解X=UΣVT,V的列向量就是X的主成分的方向,主成分矩陣Y=XV。Σ則與協方差矩陣的特征值相關。每個主成分的方差貢獻率為(σ_i2)/(∑_(i=1)p?σ_i2 ),用于決定保留多少主成分。
數學驗證如下:
給定的樣本矩陣每行為一個樣本,每列為一個特征,對其進行規范化使其每列均值為0方差為1,得到X。X的協方差矩陣為:
S_X=(X^T X)/(n-1)
代入奇異值分解X=UΣVT,因為U是正交矩陣,UT U=I:
█(S_X=&(X^T X)/(n-1)@=&((UΣV^T )^T (UΣV^T ))/(n-1)@=&(VΣ^T U^T UΣV^T)/(n-1)@=&V (Σ^T Σ)/(n-1) VT@=&VΛVT )
這正是協方差矩陣的特征值分解形式,其中V是特征向量,λ_i=(σ_i^2)/(n-1)是特征值。