文章目錄
1. 迴歸分析概述
迴歸分析是處理多變量間相關關係的一種數學方法。相關關係不同於函數關係,函數關係反應變量間嚴格依存性,簡單說就是一個自變量對應一個因變量。而相關分析中,對自變量的每一個取值,因變量可以有多個數值與之對應。在統計上,研究相關關係可以運用 迴歸分析 和 相關分析。
當自變量爲非隨機變量而因變量爲隨機變量時,它們的關係分析成爲 迴歸分析。當自變量和因變量都是隨機變量時,它們的關係分析稱爲 相關分析。迴歸分析和相關分析往往不加區分。廣義上說,相關分析包括迴歸分析,但是嚴格說兩者是有區別的。
具有相關關係的兩個變量 ξ 和 η(ξ:克西、η :伊塔 ),它們之間雖然存在着密切的關係,但不能由一個變量精確地求出另一個變量的值。通常選用 ξ = x 時 η 的數學期望作爲對應 ξ = x 時 η 的代表值,因此它反映 ξ = x 條件下 η 取值的平均水平。這樣的對應關係稱爲 迴歸關係。根據迴歸分析可以建立變量間的數學表達式,稱爲 迴歸方程。迴歸方程反映自變量在固定條件下因變量的平均狀態變化情況。
具有相關關係的變量之間雖然具有某種不確定性,但是通過對現象的不斷觀察可以探索出它們之間的統計規律,這類統計規律稱爲 迴歸關係。有關回歸關係理論、計算和分析稱爲 迴歸分析。
迴歸分析可以分爲 線性迴歸分析 和 邏輯迴歸分析。
2. 線性迴歸
線性迴歸就是將輸入項分別乘以一些常量,再將結果加起來得到輸出。線性迴歸包括一元線性迴歸和多遠線性迴歸。
線性迴歸模型的優缺點
- 優點:快速;沒有調節參數;可輕易解釋;了理解。
- 缺點:相比其他複雜一些的模型,其預測準確率不高,因爲它假設特徵和響應之間存在確定的線性關係,這種假設對於非線性的關係,線性模型顯然不能很好地進行數據建模。
2.1 簡單線性迴歸分析
線性迴歸分析中,如果僅有一個自變量與一個因變量,且其關係大致可以用一條直線表示,則稱之爲 簡單線性迴歸分析。
如果發現因變量 Y 和自變量 X 之間存在高度的正相關,則可以確定一條直線方程,使得所有的數據點儘可能接近這條擬合的直線。
其中 爲因變量, 爲截距, 爲相關係數, 爲自變量。
2.2 多元線性迴歸分析
多元線性迴歸分析是簡單線性迴歸分析的推廣,指的是多個因變量對多個自變量的迴歸分析。其中最常用的是只限於一個因變量但有多個自變量的情況,也叫做多重回歸分析。
其中, 代表截距, 爲迴歸係數。
2.3 非線性迴歸數據分析
數據挖掘中常用的一些非線性迴歸模型:
- 漸進迴歸模型
- 二次曲線模型
- 雙曲線模型
3. 用 python 實現一元線性迴歸
一個簡單的線性迴歸的例子就是房子價值預測問題。一般來說,房子越大,房屋的價值越高。
數據集:input_data.csv
說明:
No:編號
square_feet:平方英尺
price:價格(元/平方英尺)
代碼如下:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn import linear_model
# 讀取數據的函數
def get_data(file_name):
data = pd.read_csv(file_name)
X = []
Y = []
for square_feet, price in zip(data["square_feet"],data["price"]):
X.append([square_feet])
Y.append(price)
return X,Y
# 建立線性模型,並進行預測
def get_linear_model(X, Y, predict_value):
model = linear_model.LinearRegression().fit(X,Y)
pre = model.predict(predict_value)
predictions = {}
predictions["intercept"] = model.intercept_ # 截距值
predictions["coefficient"] = model.coef_ # 迴歸係數(斜率)
predictions["predictted_value"] = pre
return predictions
# 顯示線性擬合模型結果
def show_linear_line(X,Y):
model = linear_model.LinearRegression().fit(X,Y)
plt.scatter(X,Y)
plt.plot(X,model.predict(X),color="red")
plt.title("Prediction of House")
plt.xlabel("square feet")
plt.ylabel("price")
plt.show()
# 定義主函數
def main():
X, Y = get_data("input_data.csv")
print("X:",X)
print("Y:",Y)
predictions = get_linear_model(X,Y,[[700]])
print(predictions)
show_linear_line(X,Y)
main()
結果截圖:
4. 用 python 實現多元線性迴歸
當結果值影響因素有多個時,可以採用多元線性迴歸模型。例如:商品的銷售額可能與電視廣告投入、收音機廣告投入和報紙廣告投入有關係,可以有:
數據集:Advertising.csv
代碼如下:
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import explained_variance_score,\
mean_absolute_error,mean_squared_error,median_absolute_error,r2_score
# 1.讀取數據
data = pd.read_csv("Advertising.csv")
print(data.head())
print("shape:",data.shape)
# 2.分析數據
sns.pairplot(data, x_vars=["TV","radio","newspaper"], y_vars="sales",height=5,aspect=0.8,kind="reg")
plt.show()
# 3.建立線性迴歸模型
# (1)使用 pandas 構建 X(特徵向量)和 y(標籤列)
feature_cols = ["TV","radio","newspaper"]
X = data[feature_cols]
y = data["sales"]
# (2)構建訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=1) # 25% 測試
# (3)構建線性迴歸模型並訓練
model = LinearRegression().fit(X_train,y_train)
# (4)輸出模型結果
print("截距:",model.intercept_)
coef = zip(feature_cols, model.coef_)
print("迴歸係數:",list(coef))
# 4. 預測
y_pred = model.predict(X_test)
# 5. 評價
# 這個是自己寫函數計算
sum_mean = 0
for i in range(len(y_pred)):
sum_mean += (y_pred[i] - y_test.values[i])**2
sum_erro = np.sqrt(sum_mean/len(y_test))
print("均方根誤差(RMSE):",sum_erro)
# 這個是調用已有函數,以後就直接用
print("平均絕對誤差(MAE):",mean_absolute_error(y_test,y_pred))
print("均方誤差(MSE):",mean_squared_error(y_test,y_pred))
print("中值絕對誤差:",median_absolute_error(y_test,y_pred))
print("可解釋方差:",explained_variance_score(y_test,y_pred))
print("R方值:",r2_score(y_test,y_pred))
# 繪製 ROC 曲線
plt.plot(range(len(y_pred)),y_pred,"b",label="predict")
plt.plot(range(len(y_pred)),y_test,"r",label="test")
plt.xlabel("number of sales")
plt.ylabel("value of sales")
plt.legend(loc="upper right")
plt.show()
結果截圖:
說明:
- pandas 兩個主要的數據結構是 Series 和 DataFrame;Series 類似於一維數組,它由一組數據及一組與之有關的數據標籤(及索引)組成;DataFrame 是一個表格型的數據結構,它含有一組有序的列,每列可以是不同的值類型。DataFrame 既有行索引也有列索引。
- 在分析數據時,使用了 seaborn 包,這個包數據可視化效果更好。其實 seaborn 包 也屬於 Matplotlib 的內部包,只是需要單獨安裝。
- scikit-learn 要求 X 是一個特徵矩陣,y 是一個 Numpy 向量。因此,X 可以是 pandas 的 DataFrame,y 可以是 pandas 的 Series。
- 對於分類問題,評價測度是準確率,但其不適用於迴歸問題,因此使用針對連續數值的評價測度(evaluation metrics)。
5. 邏輯迴歸
邏輯迴歸也被稱爲廣義線性迴歸模型,它與線性迴歸模型的形式基本上相同,最大的區別就在於它們的因變量不同,如果是連續的,就是多重線性迴歸;如果是二項分佈,就是邏輯迴歸(Logistic);邏輯迴歸實際上是一種分類方法,主要用於二分類問題(即輸出只有兩種,分別代表兩個類別)。
邏輯迴歸的過程:面對一個迴歸或者分類問題,建立代價函數,然後通過優化方法迭代求解出最優的模型參數,然後測試驗證這個求解模型的好壞。
邏輯迴歸的優缺點
- 優點:速度快,適合二分類問題;簡單。易於理解,可以直接看到各個特徵的權重;能容易地更新模型吸收新的數據。
- 缺點:對數據和場景的適應能力有侷限性,不如決策樹算法強。
邏輯迴歸的常規步驟
- 尋找 函數(預測函數)
- 構造 函數(損失函數)
- 想辦法使 函數最小並求得迴歸參數 (θ)
5.1 構造預測函數(假設函數)
二類分類問題的概率與自變量之間的關係圖形往往是一個 S 型曲線,採用 sigmoid 函數實現,函數形式:
對於線性邊界情況,邊界形式如下:
說明: 爲輸入數據的特徵, 爲迴歸係數,也可以理解爲權重 。
最佳參數:
構造預測函數爲:
sigmod 函數輸出是介於 (0,1) 之間的,中間值是 0.5。 的輸出也是介於 (0,1) 之間的,也就表明了數據屬於某一類別的概率。例如, 則說明當前數據屬於 A 類; 則說明當前數據屬於 B 類。所以 sigmod 函數看成樣本數據的概率密度函數。
函數 的值有特殊的含義,它表示結果取 1 的概率,因此對於輸入 分類結果爲類別 1 和類別 0 的概率分別爲:
5.2 構造損失函數
機器學習模型中把 單個樣本 的預測值與真實值的差稱爲 損失,一般情況下,損失越小,模型越好(有可能存在 過擬合)。用於計算損失的函數稱爲 損失函數(Loss Function)。模型的每一次預測的好壞用損失函數度量。
代價函數 (Cost Function)是定義在整個訓練集上的,是所有樣本誤差的平均,也就是損失函數的平均。
與多元線性迴歸所採用的最小二乘法的參數估計相對應,最大似然法是邏輯迴歸所採用的參數估計法。其原理是找到這樣一個參數,可以讓樣本數據所包含的觀察值被觀察到的可能性最大。這種尋找最大可能性的方法需要反覆計算,對計算能力有很高的要求。最大似然法的優點是大樣本數據中參數的估計穩定、偏差小、估計方差小。
接下來使用概率論中極大似然估計的方法求解損失函數(需要大家有概率論和高數的知識儲備,後面有說明):
首先得到概率函數爲:
因爲樣本數據(m 個)獨立,所以它們的聯合分佈可以表示爲各邊際分佈的乘積,取 似然函數爲:
取對數似然函數:
最大似然估計就是要求使 取最大值時的 ,這裏可以使用 梯度上升法 求解,求得的 就是要求的最佳參數:
基於最大似然估計推導得到的 函數和 函數如下:
上面的分段函數可以合併爲一條式子:
說明:
- 梯度是求函數關於各個變量的偏導數,所以它代表函數值增長最快的方向。
- 梯度上升算法求函數的最大值,梯度下降算法求函數的最小值。
- 梯度上升法迭代公式:
其中 爲步長,步長決定了梯度在迭代過程中,每一步沿梯度方向前進的長度。( 也稱爲 學習率)
梯度下降公式就是將 + 號改爲 - 號。
5.3 梯度下降法求解最小值
因爲要求損失函數 最小值,所以採用梯度下降的方法。
1. 更新過程
更新過程可以寫成:
2. 向量化
約定訓練數據的矩陣形式如下, 的每一行爲一條訓練樣本,而每一列爲不同的特徵取值:
的參數 爲一列向量,所以實現 函數時要支持列向量作爲參數,並返回列向量。 的更新過程可以改爲:
3. 正則化
過擬合 即過分擬合了訓練數據,使得模型的複雜度提高,泛化能力較差(對未知數據的預測能力)。
可以使用正則化解決過擬合問題,正則化是結構風險最小化策略的實現,是在經驗風險上加一個正則化項或懲罰項。正則化一般是模型複雜度的單調遞增函數,模型越複雜,正則化項就越大。
正則項可以採取不同的形式,在迴歸問題中取平方損失,就是參數的 範數,也可以取 範數。取平方損失時,模型的損失函數變爲:
說明:
- 係數乘以 是因爲減小個別較大極端值對損失函數的影響,乘以一個小於 1 的係數,可以看做是減小噪聲(極端值)。也可以是,,但一般選擇 。
- λ 是正則項係數:
- 如果它的值很大,說明對模型的複雜度懲罰大,對擬合數據的損失懲罰小,這樣它就不會過分擬合數據,在訓練數據上的偏差較大,在未知數據上的方差較小,可能出現欠擬合的現象。
- 如果它的值很小,說明比較注重對訓練數據的擬合,在訓練數據上偏差會小,但是可能導致過擬合。
正則化後的梯度下降算法 的更新變爲:
6. 用 Python 實現邏輯迴歸
數據集:data.csv
說明:一共 100 條數據,前兩列是數據的兩個特徵,第三列是分類結果(標籤列)
代碼如下:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 定義讀取數據函數
def loadDateSet(filename):
df = pd.read_csv(filename) # 讀取數據
m = df.shape[0] # m爲數據條數
df["x0"] = np.ones((m,1)) # 爲數據增加一列值爲 1.0 的數據
data = df[["x0","x1","x2"]] # 爲數據的特徵 x0,x1,x2
label = df["label"] # 標籤列
return data,label
# 定義sigmod函數
def sigmod(x):
return 1.0 /(1 + np.exp(-x))
# 返回權重函數
def gradAscent(data,label):
m,n = data.shape # m(行數)=100,n(列數)=3(特徵數)
data = np.mat(data) # 將數據轉化爲矩陣 100*3
label = np.mat(label).T # 將標籤轉化爲矩陣 100*1
weights = np.ones((n,1)) # 初始化迴歸係數,每個係數初始化爲 1.0,三行一列
maxCricles = 5000 # 迭代次數
alpha = 0.001 # 步長(學習率)
for i in range(maxCricles):
h =sigmod(data*weights) # 將數據的特徵值*係數的值作爲 sigmod函數的輸入
error = label - h # 計算每個樣本的sigmod函數輸出與標籤的差值
weights = weights + alpha*data.T*error # 更新權重
#print("第 {} 次循環,error[0]= {}".format(i + 1, error[0]))
return weights
# 畫出最終分類的圖
def plotBestFit(data,label,weights):
data = np.array(data) # 將數據轉化爲數組
weights = np.array(weights) # 將權重轉化爲數組
m = data.shape[0] # 數據的條數m
x0 = []; y0 = []; # 標籤爲0的數據點的x座標,y座標
x1 = []; y1 = []; # 標籤爲1的數據點的x座標,y座標
for i in range(m):
if label[i] == 0:
x0.append(data[i,1]); y0.append(data[i,2])
else:
x1.append(data[i,1]); y1.append(data[i,2])
plt.scatter(x0,y0,c="red",marker="s")
plt.scatter(x1,y1,c="green")
x = np.arange(-3.0,3.0,0.1) # 直線的x座標
y = (-weights[0] - weights[1]*x)/weights[2] # 直線的y座標
plt.plot(x,y)
plt.xlabel("x1")
plt.ylabel("x2")
plt.show()
# 定義主函數
def main():
weights = gradAscent(data,label)
print("權重:\n",weights)
plotBestFit(data,label,weights)
main()
結果截圖:
下面的代碼是用 python 直接寫好的邏輯迴歸函數:以後直接使用。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
# 1.讀取數據
data = pd.read_csv("data.csv")
print(data.head())
print("shape:",data.shape)
# 2.建立邏輯迴歸模型
#(1)構建 X(特徵向量)和 y(標籤列)
feature_cols = ["x1","x2"]
X = data[feature_cols]
y = data["label"]
#(2)構建訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=1) # 25% 測試
#(3)構建邏輯迴歸模型並訓練
model = LogisticRegression().fit(X_train,y_train)
#(4)輸出模型結果
print("截距:",model.intercept_)
print("迴歸係數:",model.coef_)
# 3.預測
y_pred = model.predict([[0.5564,-1.5543]])
print("預測類別:",y_pred)
# 4.評價模型準確率
model.score(X_test,y_test)
運行結果截圖: