回歸(Regression)
”回歸到中等“
房價預測:
- 回歸分析(regression analysis)用來建立方程模擬兩個或者多個變量之間如何關聯
- 被預測的變量叫做:因變量(dependent variable),輸出(output)
- 被用來進行預測的變量叫做:自變量(independent variable),輸入(input)
- 一元線性回歸包含一個自變量和一個因變量
- 以上兩個變量的關系用一條直線來模擬
- 如果包含兩個以上的自變量,則稱作多元回歸分析(multiple regression)
這個方程對應的圖像是一條直線,稱作回歸線。其中,\(\theta_1\)為回歸線的斜率,\(\theta_0\)為回歸線的截距.\(x\)是因為只有一個自變量。
一元線性回歸——正相關:
一元線性回歸——負相關:
一元線性回歸——不相關:
判斷哪一條線最好:
代價函數(Cost Function)
- 最小二乘法
- 真實值y,預測值\(h_\theta(x)\),則誤差平方為\((y -h_\theta(x))^2\)
- 找到核視的參數,使的誤差平方和:
假設的目標一元線性回歸方程:
該方程的參數有兩個分別為:
該方程的代價函數為:
預期的目標是:
即
為了研究簡化以上步驟,先只對\(\theta_1\)進行研究,截距\(\theta_0 = 0\)
得到的方程如下:
該方程的代價函數為:
預期目標變為:
舉例:這里令\(\theta_0 = 0\),改變\(\theta_1\)的值,觀察costFunction的變化情況:
將大量\(\theta_1\)帶入運算,最終得到關於\(\theta_1\)的costfunction的圖像:
而若同時考慮\(\theta_0\)與\(\theta_1\)時,圖像如下:
這便是代價函數(cost function)
梯度下降法(Gradient Descent)
當我們有了一個代價函數\(j(\theta_0,\theta_1)\)后,如何去尋找\(min_{(\theta_0,\theta_1)}j(\theta_0,\theta_1)\)呢?
我們需要:
- 初始化\(\theta_0,\theta_1\)
- 不斷改變\(\theta_0,\theta_1\),直到\(j(\theta_0,\theta_1)\)達到一個全局最小值,或者局部極小值。(不斷迭代,優化函數模型)
此時我們便需要梯度下降函數來幫助我們尋找極小值(最小值)
在圖像上任取一點,在對這個點求導,這個導數,便是這個點的梯度,我們沿着這個梯度不斷下降,便可以成功的到達最低點,也就是\(arg~min~j(\theta_0,\theta_1)\)。當然如果我們初始點選的位置不好,那便會下降到局部的極小值點處,而非全局最小值點。如圖:
這個迭代方法,稱為梯度下降法,用函數表示成:
梯度下降函數(gradient-decent)
其中\(\alpha\)稱為學習率(learning rate)
注:
在對\(j(\theta_0,\theta_1)\)更新時,我們需要的是同步更新,即:
而不是以下這種異步更新:
這種方法有可能會得到正確的答案,但異步更新並不是梯度下降函數所定義的跟新方法。
學習率
關於學習率,它是用來調節每次函數梯度下降時,下降的高度。用圖說話:
下圖是關於\(\theta_1\)的costfunction
當我們將學習率設置的比較恰當時,比較理想的情況如下:
而下面這種情況便是學習率設置過大,導致無法下降到極小值點:
但是學習率也不能設置過小,設置過小,會導致函數迭代次數過多,消耗大量資源,時間消耗較大:
梯度下降法的缺點也很明顯,不同的起點選擇,有可能會下降到局部極小值,而不能正確的取到全局最小值,如圖:
可見學習率不能太小,也不能太大,可以多嘗試一些值(0.1.0.001,0.003,0.002,。。。)
用梯度下降法來求解線性回歸
梯度下降法:
線性回歸的模型和代價函數:
對上式分別求偏導得:
用以上方法,便可對簡單的線性模型進行線性回歸
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
#載入數據
data = pd.read_csv("data.csv",encoding="gbk",header=None)
#數據切割
x_data = data.iloc[:,0]
y_data = data.iloc[:,1]
#設置圖像大小
plt.xlim(20,80)
plt.ylim(20,120)
#顯示散點圖
plt.scatter(x_data,y_data,c = 'r')
plt.show()
#設置學習率
lr = 0.0001
#截距theta1
theta1 = 0
#斜率theta0
theta0 = 0
#樣本總個數
m = len(x_data)
#最大迭代次數
epochs = 50
#代價函數
def CostFunction(theta0, theta1, x_data, y_data, m):
totalError = 0
for i in range(m):
totalError += ((theta0 + theta1 * x_data[i]) - y_data[i])**2
return totalError / float(( 2 * m))
a = np.ones(50)
b = np.ones(50)
ans = np.ones(50)
#梯度下降函數
def gradient_decent(theta0, theta1, lr, m, x_data, y_data , epochs):
for i in range(epochs):
theta0_grad = 0
theta1_grad = 0
for j in range(m):
theta0_grad += (theta0 + theta1 * x_data[j]) - y_data[j]
theta1_grad += ((theta0 + theta1 * x_data[j]) - y_data[j]) * x_data[j]
theta0 = theta0 - lr * (1 / m) * theta0_grad
theta1 = theta1 - lr * (1 / m) * theta1_grad
a[i] = theta0;
b[i] = theta1;
ans[i] = CostFunction(theta0,theta1,x_data,y_data,m)
##每迭代5次,輸出一次圖像
#if i % 5 == 0:
# print("epochs:",i)
# plt.plot(x_data,y_data,'b.')
# plt.plot(x_data,theta1 * x_data + theta0,'r')
# plt.show()
return theta0,theta1
theta0,theta1 = gradient_decent(theta0, theta1, lr, m, x_data, y_data , epochs)
plt.scatter(x_data,y_data,c = 'r')
plt.plot(x_data,theta0 + theta1 * x_data,'b')
plt.show()
print(theta0,theta1,CostFunction(theta0,theta1,x_data ,y_data , m))
#3D梯度下降
ax = plt.axes(projection='3d')
ax.plot3D(a,b,ans,'red')
#3d等高線梯度下降
A,B = np.meshgrid(a,b)
ans = CostFunction(A,B,x_data,y_data,m)
fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(A,B,ans,rstride = 1,cstride = 1,cmap = plt.get_cmap('rainbow'))
#2d等高線
plt.contourf(A,B,ans,7,alpha = 0.75,cmap = plt.cm.hot)
plt.show()
凸函數(convex)
在處理線性回歸問題時,若采用梯度下降的方法,我們理想的代價函數函數便是上圖右側的凸函數(convex),而左側的非凸函數(non-convex)很容易取到局部極小值,對線性回歸有很大的干擾,往往得不到正確的結果。