Python數據分析與挖掘
目錄
線性迴歸
- 迴歸分析
- 目標函數:線性迴歸方程
- 一個或多個自變量和因變量之間的關係進行建模(其中爲權重,爲bias偏置值):
- 一維特徵:
- 二維特徵:
- N維特徵:
梯度下降算法
構建損失函數
- 未得到目標線性方程,得到上述公式中的參數
- 爲確定所選的效果好壞使用損失函數(loss function)來評估函數的好壞
- 損失函數如下(MSE誤差平方和):
梯度下降法
- 使用了導數的概念,對點的導數反映了函數在該點處的瞬時變化速率
- 推廣到多維函數中,梯度反映了多維圖形中變化速率最快的方向
- 起始時導數爲正,減小後並以新的爲基點重新求導,一直迭代就會找到最小的
- StochasticGradientDescent(SGD)隨機梯度下降
其中:爲隨機的樣本點 - 代碼實現
import random
import matplotlib.pyplot as plt
x = [(0.,3), (1.,3) ,(2.,3), (3.,2), (4.,4), (0.,3) , (1.,3.1) ,(2.,3.5), (3.,2.1) , (4.,4.2)]
#y[i] is the output of y = theta0 * x[0] + theta1 * x[1] +theta2 * x[2]
y = [95.364,97.217205,75.195834,60.105519,49.342380, 100.364,100.217205,100.195834,100.105519,12.342380]
epsilon = 0.001
#learning rate
alpha = 0.001
diff = [0,0]
error1 = 0
error0 =0
m = len(x)
#init the parameters to zero
theta0 = 0
theta1 = 0
theta2 = 0
epoch = 0
error_array = []
epoch_array = []
while True:
#calculate the parameters
# 線性迴歸:h(x) = theta0 + theta1 * x[i][0] + theta2 * x[i][1]
# 損失函數(評測指標MSE):累和 (1/2) * (y - h(x)) ^ 2
# d((1/2) * (y - h(x)) ^ 2) / dtheta0 = (y - h(x)) * (-1) * (1)
# theta0 = theta0 - (-alpha * (y - h(x))* 1 )
# theta1 = theta1 - (-alpha * (y - h(x))* x[i][0])
# theta2 = theta2 - (-alpha * (y - h(x))* x[i][1])
# 1. 隨機梯度下降算法在迭代的時候,每迭代一個新的樣本,就會更新一次所有的theta參數。
i = random.randint(0, m - 1)
# (y - h(x))
diff[0] = y[i]-( theta0 * 1 + theta1 * x[i][0] + theta2 * x[i][1] )
# - (y - h(x))x
gradient0 = - diff[0]* 1
gradient1 = - diff[0]* x[i][0]
gradient2 = - diff[0]* x[i][1]
# theta = theta - ( - alpha * (y - h(x))x )
theta0 = theta0 - alpha * gradient0
theta1 = theta1 - alpha * gradient1
theta2 = theta2 - alpha * gradient2
#theta3
#calculate the cost function
error1 = 0
# 此處error爲一個相對的Error值。
for i in range(len(x)):
error1 += (y[i]-( theta0 * 1 + theta1 * x[i][0] + theta2 * x[i][1]))**2
error1 = error1 / m
print("delta error {}".format(abs(error1-error0)))
error_array.append(error1)
epoch_array.append(epoch)
if epoch == 500:
break
else:
error0 = error1
epoch += 1
print(' theta0 : %f, theta1 : %f, theta2 : %f, sgd error1 : %f, epoch : % f'%(theta0,theta1,theta2,error1, epoch))
print('Done: theta0 : %f, theta1 : %f, theta2 : %f'%(theta0,theta1,theta2))
plt.plot(epoch_array, error_array, color='blue', linewidth=3)
plt.xlabel('epochs')
plt.ylabel('errors')
plt.show()
- BatchGradientDescent(BGD)批量隨機梯度下降
- 代碼實現
import matplotlib.pyplot as plt
#Training data set
#each element in x represents (x0,x1,x2)
x = [(0.,3) , (1.,3) ,(2.,3), (3.,2) , (4.,4), (0.,3) , (1.,3.1) ,(2.,3.5), (3.,2.1) , (4.,4.2)]
#y[i] is the output of y = theta0 * x[0] + theta1 * x[1] +theta2 * x[2]
y = [95.364,97.217205,75.195834,60.105519,49.342380, 100.364,100.217205,100.195834,100.105519,12.342380]
#learning rate
alpha = 0.001
diff = [0,0]
error1 = 0
error0 =0
m = len(x)
#init the parameters to zero
theta0 = 0
theta1 = 0
theta2 = 0
sum0 = 0
sum1 = 0
sum2 = 0
epoch = 0
error_array = []
epoch_array = []
while True:
#calculate the parameters
# 線性迴歸:hi(x) = theta0 + theta1 * x[i][1] + theta2 * x[i][2]
# 損失函數:(1/2) 累加 * (y - h(x)) ^ 2
# theta = theta - 累和( - alpha * (y - h(x))x )
# 1. 隨機梯度下降算法在迭代的時候,每迭代一個新的樣本,就會更新一次所有的theta參數。
#calculate the parameters
# 2. 批梯度下降算法在迭代的時候,是完成所有樣本的迭代後纔會去更新一次theta參數
print(m)
for i in range(m):
#begin batch gradient descent
diff[0] = y[i]-( theta0 + theta1 * x[i][0] + theta2 * x[i][1] )
sum0 = sum0 + ( -alpha * diff[0]* 1)
sum1 = sum1 + ( -alpha * diff[0]* x[i][0])
sum2 = sum2 + ( -alpha * diff[0]* x[i][1])
#end batch gradient descent
theta0 = theta0 - sum0 / m
theta1 = theta1 - sum1 / m
theta2 = theta2 - sum2 / m
sum0 = 0
sum1 = 0
sum2 = 0
#calculate the cost function
error1 = 0
for i in range(m):
error1 += ( y[i]-( theta0 + theta1 * x[i][0] + theta2 * x[i][1] ) )**2
error1 = error1 / m
error_array.append(error1)
epoch_array.append(epoch)
if epoch == 200:
break
else:
error0 = error1
epoch += 1
print(' theta0 : %f, theta1 : %f, theta2 : %f, bgd error1 : %f, epoch: %f'%(theta0,theta1,theta2,error1,epoch))
print('Done: theta0 : %f, theta1 : %f, theta2 : %f'%(theta0,theta1,theta2))
plt.plot(epoch_array, error_array, color='blue', linewidth=3)
plt.xlabel('epochs')
plt.ylabel('errors')
plt.show()
對比兩類梯度下降法各有利弊,SGD的計算量小,但隨機性強,有時可以快速收斂,有時則收斂的很慢,loss曲線抖動下降;MGD的計算量大,但包含批量的樣本,收斂效果比較好,loss曲線平滑下降。
Logistic Regression算法
- 針對分類問題,利用迴歸問題的思路,解決分類問題。
sigmoid函數
- sigmoid函數是一個s形的曲線
- 取值在(0, 1)之間
- 在遠離0的地方函數的值會很快接近0或1
構造目標函數
- 將預測結果轉化成預測某類別的概率公式(3)中y爲真實的類別
構造損失函數-極大似然估計
- 根據上述公式構建損失函數,目的:通過的取值使預測正確類別的概率最大化
- Lossfunction:
- 由於累乘的式子難以求導,因此對上式進行對數處理,轉化爲累加
- 轉化爲類似線性迴歸問題中求最小損失函數的問題:
梯度下降
- 首先求解損失函數梯度
- 使用梯度下降求解最優參數
多分類問題
- 解決方案:one vs rest
- 適合場景:類別可以同時出現,互相不互斥的情況
- 參考資料:one-vs-rest與one-vs-one以及sklearn的實現
優化算法:牛頓法
- 牛頓法比梯度下降法收斂的要快(迭代次數更少)
- 梯度下降法每次只從當前位置選一個上升速度最大的方向走一步
- 牛頓法在選擇方向時,不僅會考慮上升速度是否夠大,還會考慮你走了一步之後,上升速度是否會變得更大(即二階導數,類似物理上的加速度)
- 紅色的牛頓法的迭代路徑,綠色的是梯度下降法的迭代路徑。
- 由於最速梯度下降收斂速度並不“最速”,局部搜索中最速下降的方向和全局的最小值方向並不一致,所以就有後來改進的方法,包括牛頓法以及擬牛頓法。
切線法
- 牛頓法的幾何意義
- 從上圖可以總結出如下公式:
其中分母上的二階導函數可以理解爲正則項,當一階導數下降方向不是最優方向,進行修改,而且由於二階導數包含數值,因此也不用設置學習率,下降的步長是最優的。
另一種理解方式
- 隨時函數最小值 = 損失函數導數爲0
- 將損失函數進行泰勒展開:
其中爲一階導數,爲二階導數 - 對(4)式等式兩端進行求導,轉化爲梯度下降:
最終的結果與切線法得到的結果表達式是一樣的
改進:擬牛頓法
- 牛頓法中需要計算二階導數矩陣,其尺寸爲的,其中N爲特徵的數量,計算代價很大
- 而擬牛頓法不在使用二階導數矩陣,而是選取相似矩陣
Softmax Regression算法
- Softmax解決多分類的分類器,即類標籤y的取值大於等於2
- 類標記爲:
- 假設函數爲對於每一個樣本估計其所屬的類別的概率
- 每一個樣本估計所屬類別概率爲:
即對預測數的各類別的值取後除以所有類別概率值取的總和
Softmax迴歸代價函數
- 類似於Logistic迴歸,在Softmax的代價函數中引入指示函數,其具體形式爲:
- 那麼,對於Softmax迴歸的代價函數爲交叉熵:
- Sofrmax迴歸求解
- 對上述的代價函數,可以使用梯度下降法進行求解,首先對其進行求梯度:
- 對上述的代價函數,可以使用梯度下降法進行求解,首先對其進行求梯度:
L1/L2正則化
- 爲了防止過擬合,擬合過程中通常都傾向於讓權值儘可能小,最後構造一個所有參數都比較小的模型
- 參數值小的模型比較簡單,能適應不同的數據集,也在一定程度上避免了過擬合現象
- 對於一個線性迴歸方程,若參數很大,那麼只要數據偏移一點點,就會對結果
造成很大的影響 - 但如果參數足夠小,數據偏移得多一點也不會對結果造成什麼影響
L1
- L1正則化是指權值向量中各個元素的絕對值之和,通常表示爲
- 如下圖所示,圖中等值線是J0的等值線,黑色方形是L函數的圖形。在圖中,當J0等值線與L首次相交的地方就是最優解。上圖中J0與L在L的一個頂點處相交,這個頂點就是最優解。
- 正則化和“帶約束的目標函數”是等價的對L1正則化建立數學模型如下:
- 通過拉格朗日乘子法,可以變爲如下形式:
L2
- L2正則化是指權值向量中各個元素的平方和然後再求平方根(在Ridge迴歸的L2正則化項有平方符號),通常表示爲
- 如下圖所示,二維平面下L2正則化的函數圖形是個圓,與方形相比,被磨去了棱角。
- 對比L1和L2兩圖,採用L1範數時平方誤差項等值線與正則化項等值線的交點出現在座標軸上,即或爲0,而採用L2範數時,兩者的交點常出現在某個象限中,即或均非0;換而言之,採用L1範數比L2範數更容易於得到稀疏解。
- 正則化和“帶約束的目標函數”是等價的對L1正則化建立數學模型如下:
- 通過拉格朗日乘子法,可以變爲如下形式:
L1和L2對比
其中c爲超參數,控制L1和L2的限制區域大小,c越小對損失函數的約束越大;圖中像素點表示[0, 1]的取值,0爲白色1爲黑色。可以看出L1下是很多權值爲0,做到了稀疏性。
參考資料:L1與L2範數
正則化目的
- 預防或修復過擬合情況
- 其他方式:
- 數據層面:
- 增加數據(行上擴展)
- 減少feature,特徵選擇
- 模型層面:
- 模型融合
- 數據層面:
Ridge與Lasso
- L1正則化和L2正則化可以看做是損失函數的懲罰項
- Lasso迴歸
- 對於線性迴歸模型,使用L1正則化的模型建叫做Lasso迴歸
- Lasso迴歸的損失函數,式中加號後面一項即爲L1正則化項
- Ridge
- Ridge迴歸的損失函數,式中加號後面一項即爲L2正則化項
ElasticNet
對於ElasticNet迴歸,可以看做是Lasso和ridge迴歸的組合