目前爲止,咱們探討了單變量/特徵的迴歸模型,如今咱們對房價模型增長更多的特徵,例如房間數樓層等,構成一個含有多個變量的模型.。python
例如:算法
x(1) = [40, 1, 1, 10] x(2) = [96, 2, 1, 5] x(3) = [135, 3, 2, 20]
例如:dom
x(1)1 = 40 x(1)2 = 1 .......
import numpy as np # 1). 模擬數據 X1 = 2 * np.random.randn(100, 1) X2 = 4 * np.random.rand(100, 1) X3 = 6 * np.random.rand(100, 1) y = 4 + 3 * X1 + 4 * X2 + 5 * X3 + np.random.randn(100, 1) # 2). 實現梯度降低算法 # np.c_是將數據組合成向量格式: (n, 1) (n,1) = (n, 2) X_b = np.c_[np.ones((100, 1)), X1, X2, X3] # 初始化theta的值, 須要計算四個theta的值; theta = np.random.randn(4, 1) # 設置學習率和收斂次數 learning_rate = 0.1 n_iterations = 1000 # 根據公式計算 for iteration in range(n_iterations): # 梯度降低公式 = 1/樣本數 * (預測值 - 真實值) *Xi gradients = 1 / 100 * X_b.T.dot(X_b.dot(theta) - y) # theta = theta - 學習率 * 梯度值 theta = theta - learning_rate * gradients print(theta)
在咱們面對多維特徵問題的時候,咱們要保證這些特徵都具備相近的尺度,這將幫助梯度降低算法更快地收斂。而特徵縮放是爲了確保特徵在一個數量級上。 函數
以房價問題爲例,假設咱們使用兩個特徵,房屋的尺寸和房間的數量,其中x1 = 房屋面積(0-400 m2), x2 = 臥室數量(1-5), 以兩個參數分別爲橫縱座標,繪製代價函數的等高線圖能,看出圖像會顯得很扁,梯度降低算法須要很是屢次的迭代才能收斂。學習
解決方法一:測試
x1 = 房屋面積 / 400
x2 = 臥室數量 / 5字體
也能夠把最大值換成標準差,或者最大值 – 最小值。優化
梯度降低算法收斂所須要的迭代次數根據模型的不一樣而不一樣,咱們不能提早預知,咱們能夠繪製迭代次數和代價函數的圖表來觀測算法在什麼時候趨於收斂。
梯度降低算法的每次迭代受到學習率的影響,spa
嘗試在以下的數值中選擇α : …, 0.001, 0.003, 0.01, 0.03, 0.1, 0.3, 1,…
設計
如何選擇?
隨機梯度降低思想:把m個樣本分紅m份,每次用1份作梯度降低;也就是說,當有m個樣本時,批梯度降低只能作一次梯度降低,可是隨機梯度降低能夠作m次。
import numpy as np import random X = 2 * np.random.rand(100, 1) Y = 4 + 3 * X + np.random.randn(100, 1) X_b = np.c_[np.ones((100, 1)), X] # 每輪epochs處理m個樣本; n_epochs = 1000 # 學習率 a0 = 0.1 # 定義衰減率 decay_rate = 1 def learning_schedule(epoch_num): """ 定義一個學習率衰減的函數 """ return (1.0 / (decay_rate * epoch_num + 1)) * a0 # 初始化theta值 theta = np.random.randn(2, 1) # 初始化隨機值 num = [i for i in range(100)] m = 100 for epoch in range(n_epochs): rand = random.sample(num, 100) for i in range(m): random_index = rand[i] xi = X_b[random_index:random_index + 1] yi = Y[random_index:random_index + 1] # 隨機梯度降低值 gradients = xi.T.dot(xi.dot(theta) - yi) # 學習率 learning_rate = learning_schedule(epoch+1) theta = theta - learning_rate * gradients print(theta)
隨機梯度降低會喪失向量帶來的加速,因此咱們不會太用隨機梯度降低。
import numpy as np import random X = 2 * np.random.rand(100, 1) y = 4 + 3 * X + np.random.randn(100, 1) X_b = np.c_[np.ones((100, 1)), X] # print(X_b) n_epochs = 500 a = 0.03 m = 100 num = [i for i in range(100)] theta = np.random.randn(2, 1) batch_num = 5 batch_size = m // 5 # epoch 是輪次的意思,意思是用m個樣本作一輪迭代 for epoch in range(n_epochs): # 生成100個不重複的隨機數 for i in range(batch_num): start = i*batch_size end = (i+1)*batch_size xi = X_b[start:end] yi = y[start:end] gradients = 1/batch_size * xi.T.dot(xi.dot(theta)-yi) print(a) learning_rate = a theta = theta - learning_rate * gradients print(theta)
在作Mini-batch的時候,由於噪聲的緣由,可能訓練結果不是收斂的,而是在最低點周圍晃動,若是咱們要解決這個問題,那咱們就須要減小學習率,讓他在儘可能小的範圍內晃動
1 epoch = 1 次遍歷全部的數據
import numpy as np import random X = 2 * np.random.rand(100, 1) y = 4 + 3 * X + np.random.randn(100, 1) X_b = np.c_[np.ones((100, 1)), X] # print(X_b) n_epochs = 500 t0, t1 = 5, 50 m = 100 num = [i for i in range(100)] def learning_schedule(t): return float(t0) / (t + t1) theta = np.random.randn(2, 1) batch_num = 5 batch_size = m // 5 # epoch 是輪次的意思,意思是用m個樣本作一輪迭代 for epoch in range(n_epochs): # 生成100個不重複的隨機數 for i in range(batch_num): start = i*batch_size end = (i+1)*batch_size xi = X_b[start:end] yi = y[start:end] gradients = 1/batch_size * xi.T.dot(xi.dot(theta)-yi) learning_rate = learning_schedule(epoch*m + i) theta = theta - learning_rate * gradients print(theta)
過擬合的問題出如今變量(θ)過多的時候,這時候咱們沒有更多的數據去擬合模型,雖然損失函數的值基本接近於0。
房價預測時, 假設咱們不知道房屋面積,可是知道房屋的長寬。
注:若是咱們採用多項式迴歸模型,在運行梯度降低算法前,特徵縮放很是有必要。
首先, 咱們能夠在損失函數中,加入關於theta3和theta4的項, 迫使若損失函數想要最小化, 必須讓theta3和theta4儘量的小。
而後正則化, 公式以下圖:
""" 嶺迴歸 方法一: 嶺迴歸運用了L2正則化 """ import numpy as np from sklearn.linear_model import Ridge from sklearn.linear_model import SGDRegressor X = 2 * np.random.rand(100, 1) y = 4 + 3 * X + np.random.randn(100, 1) # alpha是懲罰項裏的alpha, solver處理數據的方法,auto是根據數據自動選擇,svd是解析解,sag就是隨機梯度降低 ridge_reg = Ridge(alpha=1, solver='auto') # 學習過程 ridge_reg.fit(X, y) # 預測 print(ridge_reg.predict([[1.5], [2], [2.5]])) # 打印截距 print(ridge_reg.intercept_) # 打印係數 print(ridge_reg.coef_) """ 方法二: 嶺迴歸和sgd & penalty=2是等價的 """ sgd_reg = SGDRegressor(penalty='l2') sgd_reg.fit(X, y.ravel()) print(sgd_reg.predict([[1.5], [2], [2.5]])) # 打印截距 print("W0=", sgd_reg.intercept_) # 打印係數 print("W1=", sgd_reg.coef_)
""" Lasso 迴歸 Lasso用的是l1的正則化 """ import numpy as np from sklearn.linear_model import Lasso from sklearn.linear_model import SGDRegressor X = 2 * np.random.rand(100, 1) y = 4 + 3 * X + np.random.randn(100, 1) lasso_reg = Lasso(alpha=0.15) lasso_reg.fit(X, y) print(lasso_reg.predict([[1.5]])) print(lasso_reg.coef_) sgd_reg = SGDRegressor(penalty='l1', n_iter=1000) sgd_reg.fit(X, y.ravel()) print(sgd_reg.predict([[1.5]])) print(sgd_reg.coef_)
import numpy as np from sklearn.linear_model import ElasticNet X = 2 * np.random.rand(100, 1) Y = 4 + 3 * X + np.random.randn(100, 1) elastic_reg = ElasticNet(alpha=0.15, l1_ratio=0.5) elastic_reg.fit(X, Y) print(elastic_reg.predict([[1.5]])) print(elastic_reg.coef_) print(elastic_reg.intercept_) from sklearn.linear_model import SGDRegressor elastic_reg = SGDRegressor(penalty='elasticnet') elastic_reg.fit(X, Y) print(elastic_reg.predict([[1.5]])) print(elastic_reg.coef_)
梯度降低:
正規方程:
總結:根據經驗,當特徵數量到10000的時候,是會換成梯度降低比較好
import numpy as np import matplotlib.pyplot as plt from sklearn.preprocessing import PolynomialFeatures from sklearn.linear_model import LinearRegression # 1). 數據準備; # 樣本數 m = 100 X = 6 * np.random.randn(m, 1) - 3 Y = 0.5 * X ** 2 + X + 2 + np.random.randn(m, 1) # 2). 處理 # 2-1). 將一個高階方程轉化爲一個一階方程;(多元線性迴歸) # degree:用幾維處理數據; poly_features = PolynomialFeatures(degree=2, include_bias=False) # fit_transform === fit() + transform(), 其中transform就是用來作歸一化的; X_poly = poly_features.fit_transform(X, Y) # 2-2). 處理一階方程 line_reg = LinearRegression() line_reg.fit(X_poly, Y) print(line_reg.coef_) print(line_reg.intercept_)
import numpy as np import matplotlib.pyplot as plt from sklearn.preprocessing import PolynomialFeatures from sklearn.linear_model import LinearRegression # 1). 數據準備; # 樣本數 m = 100 X = 6 * np.random.randn(m, 1) - 3 Y = 7 * X ** 2 + 5 *X + 2 + np.random.randn(m, 1) # plt.plot(X, Y, 'b.') # plt.show() # 設置圖像維度及線條的字體顯示 d = {1: 'g-', 2: 'r.', 10: 'y*'} # d = {2: 'g-'} for i in d: # 2). 處理 # 2-1). 將一個高階方程轉化爲一個一階方程;(多元線性迴歸) # degree:用幾維處理數據; poly_features = PolynomialFeatures(degree=i, include_bias=False) # fit_transform === fit() + transform(), 其中transform就是用來作歸一化的; X_poly = poly_features.fit_transform(X) print(X_poly) # 2-2). 處理一階方程 line_reg = LinearRegression() line_reg.fit(X_poly, Y) print(line_reg.coef_) print(line_reg.intercept_) y_predict = line_reg.predict(X_poly) plt.plot(X_poly[:, 0], y_predict, d[i]) plt.show()