机器学习算法总结--线性回归和逻辑回归
1. 線性回歸
簡述
在統計學中,線性回歸(Linear Regression)是利用稱為線性回歸方程的最小平方函數對一個或多個自變量和因變量之間關系進行建模的一種回歸分析。這種函數是一個或多個稱為回歸系數的模型參數的線性組合(自變量都是一次方)。只有一個自變量的情況稱為簡單回歸,大于一個自變量情況的叫做多元回歸。
優點:結果易于理解,計算上不復雜。
缺點:對非線性數據擬合不好。
適用數據類型:數值型和標稱型數據。
算法類型:回歸算法
線性回歸的模型函數如下:
hθ=θTxh_\theta = \theta ^T x hθ?=θTx
它的損失函數如下:
J(θ)=12m∑i=1m(hθ(x(i))?y(i))2J(\theta) = {1\over {2m}} \sum_{i=1}^m (h_\theta(x^{(i)}) - y^{(i)})^2 J(θ)=2m1?i=1∑m?(hθ?(x(i))?y(i))2
通過訓練數據集尋找參數的最優解,即求解可以得到minJ(θ)minJ(\theta)minJ(θ)的參數向量θ\thetaθ,其中這里的參數向量也可以分為參數和w和b和w和b和w和b,分別表示權重和偏置值。
求解最優解的方法有最小二乘法和梯度下降法。
梯度下降法
梯度下降算法的思想如下(這里以一元線性回歸為例):
首先,我們有一個代價函數,假設是J(θ0,θ1)J(\theta_0,\theta_1)J(θ0?,θ1?),我們的目標是minθ0,θ1J(θ0,θ1)min_{\theta_0,\theta_1}J(\theta_0,\theta_1)minθ0?,θ1??J(θ0?,θ1?)。
接下來的做法是:
- 首先是隨機選擇一個參數的組合(θ0,θ1)(\theta_0,\theta_1)(θ0?,θ1?),一般是設θ0=0,θ1=0\theta_0 = 0,\theta_1 = 0θ0?=0,θ1?=0;
- 然后是不斷改變(θ0,θ1)(\theta_0,\theta_1)(θ0?,θ1?),并計算代價函數,直到一個局部最小值。之所以是局部最小值,是因為我們并沒有嘗試完所有的參數組合,所以不能確定我們得到的局部最小值是否便是全局最小值,選擇不同的初始參數組合,可能會找到不同的局部最小值。
下面給出梯度下降算法的公式:
repeat until convergence{
θj:=θj?α??θjJ(θ0,θ1)(forj=0andj=1)\theta_j := \theta_j - \alpha \frac{\partial}{\partial \theta_j} J(\theta_0,\theta_1)\quad (for\quad j=0 \quad and\quad j=1) θj?:=θj??α?θj???J(θ0?,θ1?)(forj=0andj=1)
}
也就是在梯度下降中,不斷重復上述公式直到收斂,也就是找到局部最小值局部最小值局部最小值\color{red}{局部最小值}局部最小值局部最小值。其中符號:=是賦值符號的意思。
而應用梯度下降法到線性回歸,則公式如下:
θ0:=θ0?α1m∑i=1m(hθ(x(i))?y(i))θ1:=θ1?α1m∑i=1m((hθ(x(i))?y(i))?x(i))\theta_0 := \theta_0 - \alpha \frac{1}{m}\sum_{i=1}^m (h_\theta(x^{(i)}) - y^{(i)})\ \\ \theta_1 := \theta_1 - \alpha \frac{1}{m}\sum_{i=1}^m ((h_\theta(x^{(i)}) - y^{(i)}) \cdot x^{(i)}) θ0?:=θ0??αm1?i=1∑m?(hθ?(x(i))?y(i))?θ1?:=θ1??αm1?i=1∑m?((hθ?(x(i))?y(i))?x(i))
公式中的α\alphaα稱為學習率(learning rate),它決定了我們沿著能讓代價函數下降程度最大的方向向下邁進的步子有多大。
在梯度下降中,還涉及都一個參數更新的問題,即更新(θ0,θ1)(\theta_0,\theta_1)(θ0?,θ1?),一般我們的做法是同步更新。
最后,上述梯度下降算法公式實際上是一個叫批量梯度下降(batch gradient descent),即它在每次梯度下降中都是使用整個訓練集的數據,所以公式中是帶有∑i=1m\sum_{i=1}^m∑i=1m?。
嶺回歸(ridge regression):
嶺回歸是一種專用于共線性數據分析的有偏估計回歸方法,實質上是一種改良的最小二乘估計法,通過放棄最小二乘法的無偏性,以損失部分信息、降低精度為代價,獲得回歸系數更為符合實際、更可靠的回歸方法,對病態數據的耐受性遠遠強于最小二乘法。
嶺回歸分析法是從根本上消除復共線性影響的統計方法。嶺回歸模型通過在相關矩陣中引入一個很小的嶺參數K(1>K>0),并將它加到主對角線元素上,從而降低參數的最小二乘估計中復共線特征向量的影響,減小復共線變量系數最小二乘估計的方法,以保證參數估計更接近真實情況。嶺回歸分析將所有的變量引入模型中,比逐步回歸分析提供更多的信息。
其他回歸還可以參考這篇文章。
代碼實現
Python實現的代碼如下:
#Import Library #Import other necessary libraries like pandas, numpy... from sklearn import linear_model #Load Train and Test datasets #Identify feature and response variable(s) and values must be numeric and numpy arraysx_train=input_variables_values_training_datasets y_train=target_variables_values_training_datasets x_test=input_variables_values_test_datasets# Create linear regression object linear = linear_model.LinearRegression()# Train the model using the training sets and check score linear.fit(x_train, y_train) linear.score(x_train, y_train)#Equation coefficient and Intercept print('Coefficient: \n', linear.coef_) print('Intercept: \n', linear.intercept_)#Predict Output predicted= linear.predict(x_test)上述是使用sklearn包中的線性回歸算法的代碼例子,下面是一個實現的具體例子。
# -*- coding: utf-8 -*- """ Created on Mon Oct 17 10:36:06 2016@author: cai """import os import numpy as np import pandas as pd import matplotlib.pylab as plt from sklearn import linear_model# 計算損失函數 def computeCost(X, y, theta):inner = np.power(((X * theta.T) - y), 2)return np.sum(inner) / (2 * len(X))# 梯度下降算法 def gradientDescent(X, y, theta, alpha, iters):temp = np.matrix(np.zeros(theta.shape))parameters = int(theta.ravel().shape[1])cost = np.zeros(iters)for i in range(iters):error = (X * theta.T) - yfor j in range(parameters):# 計算誤差對權值的偏導數term = np.multiply(error, X[:, j])# 更新權值temp[0, j] = theta[0, j] - ((alpha / len(X)) * np.sum(term))theta = tempcost[i] = computeCost(X, y, theta)return theta, costdataPath = os.path.join('data', 'ex1data1.txt') data = pd.read_csv(dataPath, header=None, names=['Population', 'Profit']) # print(data.head()) # print(data.describe()) # data.plot(kind='scatter', x='Population', y='Profit', figsize=(12, 8)) # 在數據起始位置添加1列數值為1的數據 data.insert(0, 'Ones', 1) print(data.shape)cols = data.shape[1] X = data.iloc[:, 0:cols-1] y = data.iloc[:, cols-1:cols]# 從數據幀轉換成numpy的矩陣格式 X = np.matrix(X.values) y = np.matrix(y.values) # theta = np.matrix(np.array([0, 0])) theta = np.matrix(np.zeros((1, cols-1))) print(theta) print(X.shape, theta.shape, y.shape) cost = computeCost(X, y, theta) print("cost = ", cost)# 初始化學習率和迭代次數 alpha = 0.01 iters = 1000# 執行梯度下降算法 g, cost = gradientDescent(X, y, theta, alpha, iters) print(g)# 可視化結果 x = np.linspace(data.Population.min(),data.Population.max(),100) f = g[0, 0] + (g[0, 1] * x)fig, ax = plt.subplots(figsize=(12, 8)) ax.plot(x, f, 'r', label='Prediction') ax.scatter(data.Population, data.Profit, label='Training Data') ax.legend(loc=2) ax.set_xlabel('Population') ax.set_ylabel('Profit') ax.set_title('Predicted Profit vs. Population Size')fig, ax = plt.subplots(figsize=(12, 8)) ax.plot(np.arange(iters), cost, 'r') ax.set_xlabel('Iteration') ax.set_ylabel('Cost') ax.set_title('Error vs. Training Epoch')# 使用sklearn 包里面實現的線性回歸算法 model = linear_model.LinearRegression() model.fit(X, y)x = np.array(X[:, 1].A1) # 預測結果 f = model.predict(X).flatten() # 可視化 fig, ax = plt.subplots(figsize=(12, 8)) ax.plot(x, f, 'r', label='Prediction') ax.scatter(data.Population, data.Profit, label='Training Data') ax.legend(loc=2) ax.set_xlabel('Population') ax.set_ylabel('Profit') ax.set_title('Predicted Profit vs. Population Size(using sklearn)') plt.show()上述代碼參考自Part 1 - Simple Linear Regression。具體可以查看我的Github。
2. 邏輯回歸
簡述
Logistic回歸算法基于Sigmoid函數,或者說Sigmoid就是邏輯回歸函數。Sigmoid函數定義如下:
11+e?z\frac{1}{1+e^{-z}}1+e?z1?。函數值域范圍(0,1)。
因此邏輯回歸函數的表達式如下:
hθ(x)=g(θTX)=11+e?θTX其中,g(z)=11+e?zh_\theta(x) =g(\theta^T X) = \frac{1}{1+e^{-\theta^TX}} \\ 其中,g(z) = \frac{1}{1+e^{-z}} hθ?(x)=g(θTX)=1+e?θTX1?其中,g(z)=1+e?z1?
其導數形式為:
g′(z)=ddz11+e?z=1(1+e?z)2(e?z)=11+e?z(1?11+e?z)=g(z)(1?g(z))g\prime (z) = \fracozvdkddzhkzd{dz} \frac{1}{1+e^{-z}} \\ = \frac{1}{(1+e^{-z})^2} (e^{-z}) \\ = \frac{1}{1+e^{-z}} (1- \frac{1}{1+e^{-z}}) \\ = g(z)(1-g(z)) g′(z)=dzd?1+e?z1?=(1+e?z)21?(e?z)=1+e?z1?(1?1+e?z1?)=g(z)(1?g(z))
代價函數
邏輯回歸方法主要是用最大似然估計來學習的,所以單個樣本的后驗概率為:
p(y∣x;θ)=(hθ(x))y(1?hθ(x))1?yp(y | x; \theta) = (h_\theta(x))^y(1-h_\theta(x))^{1-y} p(y∣x;θ)=(hθ?(x))y(1?hθ?(x))1?y
到整個樣本的后驗概率就是:
L(θ)=p(y∣X;θ)=∏i=1mp(y(i)∣x(i);θ)=∏i=1m(hθ(x(i)))y(i)(1?hθ(x(i)))1?y(i)L(\theta) = p(y | X;\theta) \\ = \prod_{i=1}^{m} p(y^{(i)} | x^{(i)};\theta)\\ = \prod_{i=1}^{m} (h_\theta(x^{(i)}))^{y^{(i)}}(1-h_\theta(x^{(i)}))^{1-y^{(i)}} L(θ)=p(y∣X;θ)=i=1∏m?p(y(i)∣x(i);θ)=i=1∏m?(hθ?(x(i)))y(i)(1?hθ?(x(i)))1?y(i)
其中,P(y=1∣x;θ)=hθ(x),P(y=0∣x;θ)=1?hθ(x)P(y=1|x;\theta) = h_\theta(x), P(y=0|x;\theta)=1-h_\theta(x)P(y=1∣x;θ)=hθ?(x),P(y=0∣x;θ)=1?hθ?(x)。
通過對數進一步簡化有:l(θ)=logL(θ)=∑i=1my(i)logh(x(i))+(1?y(i))log(1?h(x(i)))l(\theta) = logL(\theta) = \sum_{i=1}^{m}y^{(i)}logh(x^{(i)})+(1-y^{(i)})log(1-h(x^{(i)}))l(θ)=logL(θ)=∑i=1m?y(i)logh(x(i))+(1?y(i))log(1?h(x(i))).
而邏輯回歸的代價函數就是?l(θ)-l(\theta)?l(θ)。也就是如下所示:
J(θ)=?1m[∑i=1my(i)loghθ(x(i))+(1?y(i)log(1?hθ(x(i)))]J(\theta) = -\frac{1}{m} [\sum_{i=1}^my^{(i)}logh_\theta(x^{(i)})+(1-y^{(i)}log(1-h_\theta(x^{(i)}))] J(θ)=?m1?[i=1∑m?y(i)loghθ?(x(i))+(1?y(i)log(1?hθ?(x(i)))]
同樣可以使用梯度下降算法來求解使得代價函數最小的參數。其梯度下降法公式為:
總結
優點:
1、實現簡單;
2、分類時計算量非常小,速度很快,存儲資源低;
缺點:
1、容易欠擬合,一般準確度不太高
2、只能處理兩分類問題(在此基礎上衍生出來的softmax可以用于多分類),且必須線性可分;
適用數據類型:數值型和標稱型數據。
類別:分類算法。
試用場景:解決二分類問題。
代碼實現
首先是采用sklearn包中的邏輯回歸算法代碼:
#Import Library from sklearn.linear_model import LogisticRegression #Assumed you have, X (predictor) and Y (target) for training data set and x_test(predictor) of test_dataset# Create logistic regression objectmodel = LogisticRegression()# Train the model using the training sets and check score model.fit(X, y) model.score(X, y)#Equation coefficient and Intercept print('Coefficient: \n', model.coef_) print('Intercept: \n', model.intercept_)#Predict Output predicted= model.predict(x_test)接下來則是應用例子,如下所示:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ @Time : 2016/10/19 21:35 @Author : cai實現多類的邏輯回歸算法 """ import os import numpy as np import pandas as pd import matplotlib.pylab as plt from scipy.optimize import minimize from scipy.io import loadmat# 定義Sigmoid函數 def sigmoid(z):return 1 / (1 + np.exp(-z))# 定義 cost函數 def costReg(theta, X, y, lambdas):theta = np.matrix(theta)X = np.matrix(X)y = np.matrix(y)h = X * theta.Tfirst = np.multiply(-y, np.log(sigmoid(h)))second = np.multiply((1-y), np.log(1 - sigmoid(h)))reg = (lambdas / 2 * len(X)) * np.sum(np.power(theta[:, 1:theta.shape[1]], 2))return np.sum(first - second) / (len(X)) + reg# 梯度下降算法的實現, 輸出梯度對權值的偏導數 def gradient(theta, X, y, lambdas):theta = np.matrix(theta)X = np.matrix(X)y = np.matrix(y)parameters = int(theta.ravel().shape[1])grad = np.zeros(parameters)# 計算誤差error = sigmoid(X * theta.T) - ygrad = ((X.T * error) / len(X)).T + ((lambdas / len(X)) * theta)grad[0, 0] = np.sum(np.multiply(error, X[:, 0])) / len(X)return np.array(grad).ravel()# 實現一對多的分類方法 def one_vs_all(X, y, num_labels, lambdas):rows = X.shape[0]params = X.shape[1]# 每個分類器有一個 k * (n+1)大小的權值數組all_theta = np.zeros((num_labels, params + 1))# 增加一列,這是用于偏置值X = np.insert(X, 0, values=np.ones(rows), axis=1)# 標簽的索引從1開始for i in range(1, num_labels + 1):theta = np.zeros(params + 1)y_i = np.array([1 if label == i else 0 for label in y])y_i = np.reshape(y_i, (rows, 1))# 最小化損失函數fmin = minimize(fun=costReg, x0=theta, args=(X, y_i, lambdas), method='TNC', jac=gradient)all_theta[i-1, :] = fmin.xreturn all_thetadef predict_all(X, all_theta):rows = X.shape[0]params = X.shape[1]num_labels = all_theta.shape[0]# 增加一列,這是用于偏置值X = np.insert(X, 0, values=np.ones(rows), axis=1)X = np.matrix(X)all_theta = np.matrix(all_theta)# 對每個訓練樣本計算其類的概率值h = sigmoid(X * all_theta.T)# 獲取最大概率值的數組索引h_argmax = np.argmax(h, axis=1)# 數組是從0開始索引,而標簽值是從1開始,所以需要加1h_argmax = h_argmax + 1return h_argmaxdataPath = os.path.join('data', 'ex3data1.mat') # 載入數據 data = loadmat(dataPath) print(data) print(data['X'].shape, data['y'].shape)# print(np.unique(data['y'])) # 測試 # rows = data['X'].shape[0] # params = data['X'].shape[1] # # all_theta = np.zeros((10, params + 1)) # # X = np.insert(data['X'], 0, values=np.ones(rows), axis=1) # # theta = np.zeros(params + 1) # # y_0 = np.array([1 if label == 0 else 0 for label in data['y']]) # y_0 = np.reshape(y_0, (rows, 1)) # print(X.shape, y_0.shape, theta.shape, all_theta.shape)all_theta = one_vs_all(data['X'], data['y'], 10, 1) print(all_theta)# 計算分類準確率 y_pred = predict_all(data['X'], all_theta) correct = [1 if a == b else 0 for (a, b) in zip(y_pred, data['y'])] accuracy = (sum(map(int, correct)) / float(len(correct))) print('accuracy = {0}%'.format(accuracy * 100))實現代碼來自Part 4 - Multivariate Logistic Regression。具體可以查看我的github 。
總結
以上是生活随笔為你收集整理的机器学习算法总结--线性回归和逻辑回归的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何一步步学习到精通JavaScript
- 下一篇: 程序人生:摆脱情绪低潮的10种方法