李宏毅机器学习作业2:Winner还是Losser(含训练数据)
訓練數據以及源代碼在我的Github:https://github.com/taw19960426/DeepLearning/tree/master/%E4%BD%9C%E4%B8%9A/%E4%BD%9C%E4%B8%9A2%E6%95%B0%E6%8D%AE
一、作業說明
給定訓練集spam_train.csv,要求根據每個ID各種屬性值來判斷該ID對應角色是Winner還是Losser(收入是否大于50K),這是一個典型的二分類問題。
-
CSV文件,大小為4000行X59列;
-
4000行數據對應著4000個角色,ID編號從1到4001;
-
59列數據中, 第一列為角色ID,最后一列為分類結果,即label(0、1兩種),中間的57列為角色對應的57種屬性值;
二、思路分析
2.1 思路分析
這是一個典型的二分類問題,結合課上所學內容,決定采用Logistic回歸算法。
與線性回歸用于預測不同,Logistic回歸則常用于分類(通常是二分類問題)。Logistic回歸實質上就是在普通的線性回歸后面加上了一個sigmoid函數,把線性回歸預測到的數值壓縮成為一個概率,進而實現二分類(關于線性回歸模型,可參考上一次作業)。
在損失函數方面,Logistic回歸并沒有使用傳統的歐式距離來度量誤差,而使用了交叉熵(用于衡量兩個概率分布之間的相似程度)。
2.2 數據預處理
在機器學習中,數據的預處理是非常重要的一環,能直接影響到模型效果的好壞。本次作業的數據相對簡單純凈,在數據預處理方面并不需要花太多精力。
首先是空值處理(盡管沒看到空值,但為了以防萬一,還是做一下),所有空值用0填充(也可以用平均值、中位數等,視具體情況而定)。
接著就是把數據范圍盡量scale到同一個數量級上,觀察數據后發現,多數數據值為0,非0值也都在1附近,只有倒數第二列和倒數第三列數據值較大,可以將這兩列分別除上每列的平均值,把數值范圍拉到1附近。
由于并沒有給出這57個屬性具體是什么屬性,因此無法對數據進行進一步的挖掘應用。
上述操作完成后,將表格的第2列至58列取出為x(shape為4000X57),將最后一列取出做label y(shape為4000X1)。進一步劃分訓練集和驗證集,分別取x、y中前3500個樣本為訓練集x_test(shape為3500X57),y_test(shape為3500X1),后500個樣本為驗證集x_val(shape為500X57),y_val(shape為500X1)。
數據預處理到此結束。
#數據的預處理df=pd.read_csv('spam_train.csv')#讀文件df=df.fillna(0)#空值用0填充array=np.array(df)#轉化為對象(4000,49)x=array[:,1:-1]#拋棄第一列和最后一列shape(4000,47)y=array[:,-1]#最后一列label#將倒數第二列和第三列除以平均值x[:,-1]=x[:,-1]/np.mean(x[:,-1])x[:, -2] = x[:, -2] / np.mean(x[:, -2])#劃分測試集和驗證集x_train=x[0:3500,:]y_train = y[0:3500]x_val=x[3500:4001,:]y_val=y[3500:4001]2.3 模型建立
2.3.1 線性回歸
先對數據做線性回歸,得出每個樣本對應的回歸值。下式為對第n個樣本xnx^{n}xn的回歸,回歸結果為yny^{n}yn。
yn=∑i=157wixin+b\mathrm{y}^{n}=\sum_{i=1}^{57} w_{i} x_{i}^{n}+b yn=i=1∑57?wi?xin?+b
2.3.2 sigmoid函數壓縮回歸值
之后將回歸結果送進sigmoid函數,得到概率值。
pn=11+e?ynp^{n}=\frac{1}{1+e^{-y^{n}}} pn=1+e?yn1?
2.3.3 誤差反向傳播
接著就到重頭戲了。眾所周知,不管線性回歸還是Logistic回歸,其關鍵和核心就在于通過誤差的反向傳播來更新參數,進而使模型不斷優化。因此,損失函數的確定及對各參數的求導就成了重中之重。在分類問題中,模型一般針對各類別輸出一個概率分布,因此常用交叉熵作為損失函數。交叉熵可用于衡量兩個概率分布之間的相似、統一程度,兩個概率分布越相似、越統一,則交叉熵越小;反之,兩概率分布之間差異越大、越混亂,則交叉熵越大。
下式表示k分類問題的交叉熵,P為label,是一個概率分布,常用one_hot編碼。例如針對3分類問題而言,若樣本屬于第一類,則P為(1,0,0),若屬于第二類,則P為(0,1,0),若屬于第三類,則為(0,0,1)。即所屬的類概率值為1,其他類概率值為0。Q為模型得出的概率分布,可以是(0.1,0.8,0.1)等。
Loss?n=?∑1kPnln?Qn\operatorname{Loss}^{n}=-\sum_{1}^{k} P^{n} \ln Q^{n} Lossn=?1∑k?PnlnQn
針對本次作業而言,雖然模型只輸出了一個概率值p,但由于處理的是二分類問題,因此可以很快求出另一概率值為1-p,即可視為模型輸出的概率分布為Q(p,1-p)。將本次的label視為概率分布P(y,1-y),即Winner(label為1)的概率分布為(1,0),分類為Losser(label為0)的概率分布為(0,1)。
Loss?n=?[y^nln?pn+(1?y^n)ln?(1?pn)]\operatorname{Loss}^{n}=-\left[\hat{y}^{n} \ln p^{n}+\left(1-\hat{y}^{n}\right) \ln \left(1-p^{n}\right)\right] Lossn=?[y^?nlnpn+(1?y^?n)ln(1?pn)]
損失函數對權重w求偏導,可得:
?Lossn?wi=?xi[y^n?pn]\frac{\partial L o s s^{n}}{\partial w_{i}}=-x_{i}\left[\hat{y}^{n}-p^{n}\right] ?wi??Lossn?=?xi?[y^?n?pn]
同理,損失函數對偏置b求偏導,可得:
?Lossn?b=?[y^n?pn]\frac{\partial L o s s^{n}}{\partial b}=-\left[\hat{y}^{n}-p^{n}\right] ?b?Lossn?=?[y^?n?pn]
課件上的公式:
-
加正則化Loss?n=?∑1kpnln?Qn+λ(wi)2\operatorname{Loss}^{n}=-\sum_{1}^{k} p^{n} \ln Q^{n}+\lambda\left(w_{i}\right)^{2} Lossn=?1∑k?pnlnQn+λ(wi?)2
-
Loss?n=∑n?[y^nln?fw,b(xn)+(1?y^n)ln?(1?fw,b(xn))]\operatorname{Loss}^{n}=\sum_{n}-\left[\hat{y}^{n} \ln f_{w, b}\left(x^{n}\right)+\left(1-\hat{y}^{n}\right) \ln \left(1-f_{w, b}\left(x^{n}\right)\right)\right] Lossn=n∑??[y^?nlnfw,b?(xn)+(1?y^?n)ln(1?fw,b?(xn))]
-
fw,b(x)=σ(z)=1/1+exp?(?z)\begin{array}{l}{f_{w, b}(x)=\sigma(z)} {=1 / 1+\exp (-z)}\end{array} fw,b?(x)=σ(z)=1/1+exp(?z)?
-
z=w?x+b=∑iwixi+b\quad z=w \cdot x+b=\sum_{i} w_{i} x_{i}+bz=w?x+b=i∑?wi?xi?+b
2.3.4 參數更新
求出梯度后,再拿原參數減去梯度與學習率的乘積,即可實現參數的更新。
#平均數b_g/=numw_g/=num#adagradbg2_sum+=b_g**2wg2_sum+=w_g**2#更新w和bweights-=Learning_rate/wg2_sum**0.5*w_gbias-=Learning_rate/bg2_sum**0.5*b_g三、代碼分享與結果顯示
3.1 源代碼
import numpy as np import pandas as pddef train(x_train,y_train,epoch):num=x_train.shape[0]'''y.shape 返回的一個元組,代表 y 數據集的信息如(行,列)y.shape[0], 意思是:返回 y 中行的總數。這個值在 y 是單特征的情況下 和 len(y) 是等價的,即數據集中數據點的總數。'''dim=x_train.shape[1]bias=0#偏置初始化weights=np.ones(dim)#權重初始化Learning_rate=1#學習率和正則項系數初始化Regular_coefficient=0.001#用于存放偏置值的梯度平方和,adagrad用到bg2_sum=0wg2_sum=np.zeros(dim)#迭代求w,bfor i in range(epoch):b_g=0#初始化w_g=np.zeros(dim)# 計算梯度,梯度計算時針對損失函數求導,在所有數據上for j in range(num):z=weights.dot(x_train[j,:])+bias#Z函數表達式sigmoid=1/(1+np.exp(-z))#sigmoid function#損失函數對b求導b_g+=((-1)*(y_train[j]-sigmoid))# 損失函數對w求導,并且有正則化(防overfitting)for k in range(dim):w_g[k]+=(-1)*(y_train[j]-sigmoid)*x_train[j,k]+2*Regular_coefficient*weights[k]#平均數b_g/=numw_g/=num#adagradbg2_sum+=b_g**2wg2_sum+=w_g**2#更新w和bweights-=Learning_rate/wg2_sum**0.5*w_gbias-=Learning_rate/bg2_sum**0.5*b_g# 每訓練3輪,輸出一次在訓練集上的正確率# 在計算loss時,由于涉及g()運到lo算,因此可能出現無窮大,計算并打印出來的loss為nan# 有興趣的同學可以把下面涉及到loss運算的注釋去掉,觀察一波打印出的lossif i%3==0:Correct_quantity=0result=np.zeros(num)#loss=0for j in range(num):z = weights.dot(x_train[j, :]) + bias # Z函數表達式sigmoid = 1 / (1 + np.exp(-z)) # sigmoid functionif sigmoid>=0.5:result[j]=1else:result[j]=0if result[j]==y_train[j]:Correct_quantity+=1.0#loss += (-1) * (y_train[j] * np.ln(sigmoid) + (1 - y_train[j]) * np.ln(1 - sigmoid))#print(f"epoch{0},the loss on train data is::{1}", i, loss / num)print(f"epoch{0},the Correct rate on train data is:{1}",i,Correct_quantity/num)return weights,bias#對求出來的W和b驗證一下效果 def validate(x_val,y_val,weights,bias):num=x_val.shape[0]Correct_quantity = 0result = np.zeros(num)loss=0for j in range(num):z = weights.dot(x_val[j, :]) + bias # Z函數表達式sigmoid = 1 / (1 + np.exp(-z)) # sigmoid functionif sigmoid >= 0.5:result[j] = 1if sigmoid < 0.5:result[j] = 0if result[j] == y_val[j]:Correct_quantity += 1.0#驗證集上的損失函數#loss += (-1) * (y_val[j] * np.log(sigmoid) + (1 - y_val[j]) * np.ln(1 - sigmoid))return Correct_quantity/numdef main():#數據的預處理df=pd.read_csv('spam_train.csv')#讀文件df=df.fillna(0)#空值用0填充array=np.array(df)#轉化為對象(4000,49)x=array[:,1:-1]#拋棄第一列和最后一列shape(4000,47)y=array[:,-1]#最后一列label#將倒數第二列和第三列除以平均值x[:,-1]=x[:,-1]/np.mean(x[:,-1])x[:, -2] = x[:, -2] / np.mean(x[:, -2])#劃分測試集和驗證集x_train=x[0:3500,:]y_train = y[0:3500]x_val=x[3500:4001,:]y_val=y[3500:4001]#迭代次數為30次epoch=30w,b=train(x_train,y_train,epoch)#驗證集上的結果Correct_rate=validate(x_val,y_val,w,b)print(f"The Correct rate on val data is:{0}",Correct_rate)if __name__ == '__main__':main()3.2 結果顯示
可以看出,在訓練30輪后,分類正確率能達到94%左右。
參考資料:
- https://www.cnblogs.com/HL-space/p/10785225.html
- http://www.luyixian.cn/news_show_4755.aspx
- https://www.cnblogs.com/luhuan/p/7925790.html
- https://blog.csdn.net/u013541048/article/details/81335256
總結
以上是生活随笔為你收集整理的李宏毅机器学习作业2:Winner还是Losser(含训练数据)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【ML】 李宏毅机器学习二:Logist
- 下一篇: Linux 文件系统详解