python資料分析完整流程-幸福感預測
一.資料背景及問題描述
- 資料來源 :課題來源于天池大賽,資料來源于中國人民大學中國調查與資料中心《中國綜合社會調查(CGSS)》項目,為多階分層抽樣的截面面訪調查。
- 研究背景 :在社會科學領域,幸福感的研究占有重要的位置。這個涉及了哲學、心理學、社會學、經濟學等多方學科的話題複雜而有趣;同時與大家生活息息相關,每個人對幸福感都有自己的衡量标準。如果能發現影響幸福感的共性,生活中是不是将多一些樂趣;如果能找到影響幸福感的政策因素,便能優化資源配置來提升國民的幸福感。目前社會科學研究注重變量的可解釋性和未來政策的落地,主要采用了線性回歸和邏輯回歸的方法,在收入、健康、職業、社交關系、休閑方式等經濟人口因素;以及政府公共服務、宏觀經濟環境、稅負等宏觀因素上有了一系列的推測和發現。
- 研究目标 :使用公開資料的問卷調查結果,選取其中多組變量,包括個體變量(性别、年齡、地域、職業、健康、婚姻與政治面貌等等)、家庭變量(父母、配偶、子女、家庭資本等等)、社會态度(公平、信用、公共服務等等),來預測其對幸福感的評價。
二.描述性統計
1. 資料介紹
1.1 标簽介紹
資料集的标簽是happiness變量,是一個取值為1到5的有序變量,表示幸福程度。數值越大表示幸福感越強,1表示感到非常不幸福,5表示非常幸福。
1.2 特征介紹
資料集中一共有139個特征,大緻可以分為兩類:第一類是與自身相關的,第二類是
與自身家庭相關的。第一類中與自身相關的可以大緻細分為3個方面:第一方面是外在,比如出生日期、性别、身高、體重、身體健康狀況等;第二方面是精神認知方面,比如是否有信仰宗教、社會公平度、對社會各項公共的滿意程度等,第三方面主要是經濟方面、比如過去現在以及将來所處社會等級、工作收入等。第二類是家庭基本資訊,比如父母親配偶的年齡、工作、政治面貌等。
2. 描述性統計
檢視資料的總體情況,可以看出共有140個變量,其中的happiness為标簽變量
data.info(verbose=True,null_counts=True)
2.1 标簽
發現資料存在12個異常值,由于12占整體的資料量較少,此處描述性統計暫時不統計标簽小于0的值,對結果影響不大,後續預處理将對标簽進行處理 統計标簽大于0
的分布從标簽餅圖可以看出覺得幸福的人最多,占樣本的60.3%,其次是非常幸福的人,占樣本的17.7%,感到非常不幸福的人較少僅占1.3%
label=data['happiness']
label.value_counts
colors=['steelblue','#ff9999','#7777aa','pink','#dd5555']
label_list=[]
label_c=[]
for i in range(1,6):
label_list.append(data.loc[label==i,'happiness'].count())
plt.pie(label_list,labels=[1,2,3,4,5],autopct='%.1f%%',colors=colors)
plt.legend()
2.2個人資訊描述
#樣本類型檢視
data['survey_type'].value_counts()
從樣本類型的統計看出,城市中的樣本占大多數。作出不同類别群體的幸福分布條形圖,從圖中可以看出兩個群體關于幸福感的整體趨勢是相同的,但城市類别中,感到特别幸福的人的比例略高于農村地區。
city=data[data['survey_type']==1]
rural=data[data['survey_type']==2]
city_list=[]
rural_list=[]
for i in range(1,6):
city_list.append(city.loc[city['happiness']==i,'happiness'].count())
rural_list.append(rural.loc[rural['happiness']==i,'happiness'].count())
width=0.35
plt.bar(range(1,6),city_list,width=width,label='city',color='pink')
plt.bar(np.arange(1,6)+width,rural_list,width=width,label='rural',color='#7777aa')
plt.xticks(np.arange(1,6)+0.1,[1,2,3,4,5])
plt.legend()
plt.show
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711104637748.png?x-oss-
process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNjEwMTYx,size_16,color_FFFFFF,t_70)
**#性别**
sex_list=[]
for i in range(1,3):
sex_list.append(data.loc[data['gender']==i,'happiness'].count())
plt.pie(sex_list,colors=['#7777aa','pink'],labels=['F','M'],autopct='%.1f%%')
plt.legend()
性别分布的餅圖如上圖所示,F代表男性,M代表女性,可以看出女性受訪者略多于男性,再做出不同性别的幸福感分布條形圖,可看出男女
的幸福感分布走勢基本相同,再通過比較均值進一步進行研究,這兩個類别幸福感均值的條形圖如圖,可以看出女性群體的幸福感均值略高于男性。
f=data.loc[data['gender']==1]
m=data[data['gender']==2]
f_list=[]
m_list=[]
for i in range(1,6):
f_list.append(f.loc[f['happiness']==i,'happiness'].count())
m_list.append(m.loc[m['happiness']==i,'happiness'].count())
width=0.35
plt.bar(range(1,6),f_list,width=width,label='f',color='pink')
plt.bar(np.arange(1,6)+width,m_list,width=width,label='m',color='#7777aa')
plt.xticks(np.arange(1,6)+0.1,[1,2,3,4,5])
plt.legend()
plt.show
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/2019071110475562.png?x-oss-
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711104837255.png?x-oss-
#年齡
用出生日期減去調查日期得到受訪者的年齡。年齡分布的盒形圖如下,從該圖可以看出,樣本中年齡大的有90多歲,小的不到20歲,大多數受訪者年齡為40-60歲。按照幸福程度分組,可以看出組别均值之間存在差異,感到非常幸福的人的年齡均值最大。
#年齡
data['survey_time']=pd.to_datetime(data['survey_time'])
data['survey_year']=data['survey_time'].dt.year
data['age']=data['survey_year']-data['birth']
plt.boxplot(data['age'],patch_artist='pink')
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711104959913.png?x-oss-
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711105011431.png?x-oss-
#身高
身高箱線圖如圖,身高最小值不到120cm、最大值超過190cm,有較多離群值。按照幸福感分組得到分組條形圖,如圖,幸福感為4即感到比較幸福的群體有較多離群值,同時也能看出
該群體的身高均值最大
plt.boxplot(data['height_cm'],patch_artist='pink')
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/2019071110505986.png?x-oss-
#體重
體重的箱線圖如圖。可以看出有較多樣本的體重最小的僅有40,有較多小的離群值。體重的機關是斤,考慮到受訪者都是成年人,猜想這部分體重小的離群點可能是受訪者混淆了機關,填的是以公斤計算的體重。在後續特征處理的時候考慮将體重乘以2。
plt.boxplot(data['weight_jin'],patch_artist='pink')
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711105128250.png?x-oss-
#身體健康
身體健康分布的餅圖如下圖,這是一個順序變量,1代表很不健康,5代表很健康。可以看出比較健康的人最多,占38.8%,很不健康的人最少,占3.1%。右圖反應的是健康各個等級的均值走勢圖,可以看出健康等級越高的群體,幸福感均值也越大。
health_list=[]
for i in range(1,6):
health_list.append(data.loc[data['health']==i,'happiness'].count())
plt.pie(health_list,labels=[1,2,3,4,5],autopct='%.1f%%')
plt.legend()
hp=[]
for i in range(1,6):
hp.append(data.loc[data['health']==i,'happiness'].mean())
plt.plot(range(1,6),hp,color='b',markersize=5,markeredgecolor='r',marker='o',label='health-happiness')
plt.title('不同健康情況的幸福感均值分布')
plt.xlabel('健康狀況')
plt.ylabel('幸福等級')
plt.legend()
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711105232170.png?x-oss-
**
2.3精神認知層面
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711105303399.png?x-oss-
#教育程度
教育程度的餅圖如圖,圖中數值的含義是:1=沒有受過任何教育;2=私塾、掃盲班;3=國小;4=國中;5=職業高中;6=普通高中;7=中專;8=技校;9=成人大學專科;10=正規大學專科;11=成人大學大學;12=正規大學大學;13=研究所學生即以上;14=其他。從圖中可以看出受訪者中學曆為國中的人最多,其次是國小,都不太高,可能是由于受訪者大多數較年長,以前的教育資源較缺乏。右圖是各個教育程度的幸福均值折線圖,可以看出不同類别之間存在着明顯的差異,教育程度為“其他”的幸福感最低,教育程度為2(國小)和13(研究所學生及以上)的兩個群體幸福感較高。
edu=[]
for i in range(1,15):
edu.append(data.loc[data['edu']==i,'happiness'].count())
plt.pie(edu,labels=np.arange(1,15),autopct='%.1f%%')
plt.legend()
edu_=data[data['edu']>0]
sns.pointplot('edu','happiness',data=edu_)
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711105357771.png?x-oss-
社會公平
社會公平性是取值1-5的有序變量,數值越大表示越覺得公平,1表示認為社會完全不公平,5表示認為完全。從分布的條形圖可以看出絕大多數的看法是4(認為社會較公平)。右圖是不同看法群體的均值,可以看出認為社會越公平的群體,幸福感均值也越大。
equ=data[data['equity']>0]
sns.countplot('equity',data=equ)
sns.pointplot('equity','happiness',data=equ)
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711105440360.png?x-oss-
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711105500307.png?x-oss-
社交
是取值為1-7的有序變量,取值越低,代表社交頻率越頻繁。從餅圖可以看出,2(很少社交)的人最多,其次是3(有時社交)。條形圖是不同社交程度群體的均值,可以看出社交頻率高的群體相對于頻次較低的群體幸福感均值高。
social=[]
for i in range(1,6):
social.append(data.loc[data['social_friend']==i,'happiness'].count())
plt.pie(social,labels=range(1,6),autopct='%.1f%%')
plt.legend()
lu=data[data['social_friend']>0]
sns.pointplot('social_friend','happiness',data=lu)
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711105551336.png?x-oss-
學習充電
這是一個順序變量,值越大表示課外充電頻率越高。可以看出将近一半的人空閑時間從不學習,僅有2.4%的人課外學習頻繁。右圖是不同學習頻率群體的均值,可以看出随着頻率的增加,幸福感均值也增加,群體4(經常學習)和群體5(學習非常頻繁)兩個群體差異較小
learn=[]
for i in range(1,6):
learn.append(data.loc[data['learn']==i,'happiness'].count())
plt.pie(learn,labels=range(1,6),autopct='%.1f%%')
plt.legend()
plt.title('學習充電分布')
st=data[data['learn']>0]
sns.pointplot('learn','happiness',data=st)
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711105656376.png?x-oss-
沮喪頻繁程度
為取值1-4的順序變量,值越小表示越頻繁。可以看出大多人很少感到沮喪,僅有1.1%的人總是感到沮喪。從折線圖可以得知沮喪程度越頻繁的群體,幸福感均值也就越低。
de=[]
for i in range(1,6):
de.append(data.loc[data['depression']==i,'happiness'].count())
plt.pie(de,labels=range(1,6),autopct='%.1f%%')
plt.legend()
plt.title('沮喪程度分布')
det=data[data['depression']>0]
sns.pointplot('depression','happiness',data=det)
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711105733738.png?x-oss-
2.4.社會經濟地位
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711105748362.png?x-oss-
關于受訪者主觀認為其所處的社會地位的6個問題中,涉及到多個時間點的資訊,以目前所處等級為基準,對其他3個變量進行相減做差并等頻分組,可以得到數年來受訪者所處等級的變化,可作為新的變量加入特征集,其分布直方圖如左下圖.
據統計,65.6%的受訪者認為目前所處社會等級高于14歲時家庭所處的等級,56.4%的受訪者認為目前所處的社會等級高于10年前,89.04%的受訪者認為未來10年後的所處等級會不低于現在;
data['now-14']=data['class']-data['class_14']
data['now-class_10_before']=data['class']-data['class_10_before']
plt.hist(data['now-14'])
plt.title('與十四歲對照等級變化分布圖')
data.loc[data['now-14']>0,'now-14'].count()/8000
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711105844857.png?x-oss-
plt.hist(data['now-class_10_before'])
plt.title('與十年前對照等級變化分布圖')
data.loc[data['now-class_10_before']>0,'now-class_10_before'].count()/8000
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711105917104.png?x-oss-
data['now-class_10_after']=data['class_10_after']-data['class']
plt.hist(data['now-class_10_after'])
plt.title('與十年後對照等級變化分布圖')
data.loc[data['now-class_10_after']>=0,'now-class_10_after'].count()/8000
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711110134670.png?x-oss-
2.4.家庭收入
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711110212581.png?x-oss-
收入
對收入進行分組,并統計不同組别對應得幸福感的不同,原始的收入資料分布具有大量極端值,右偏态顯著,對其進行5組分組。可以看出,出去少于3000的收入人群,可能為退休老人,退役軍官等,幸福感來源有所不同,其他人随着收入的增加,每組的幸福感均值也在增加,可見收入對幸福感有正向支撐作用。
def income_cut(income):
if income<=3000:
return 1
if 3000<income<=8000:
return 2
if 8000<income<=15000:
return 3
if 15000<income<=35000:
return 4
if income>35000:
return 5
data["income"]=data["income"].map(income_cut)
plt.hist(data['income'])
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711110243244.png?x-oss-
sns.pointplot('income','happiness',data=data)
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711110303362.png?x-oss-
房産擁有情況
在擁有房産小于4套時,幸福感随着房産的增多而增加,之後再随房産數量在增多,幸福感反而發生了大的波動,進一步加入性别因素,探究不同性别對于房産的不同感覺,可見男女在房産小于4時的幸福感趨勢基本相同,相對來說,高數量房産的擁有者多為女性,推測為女強人類型或者為異常值。
data_list=data[data['house']<10]
data_1=data_list[data_list['house']>0]
sns.pointplot('house','happiness',data=data_1)
sns.pointplot('house','happiness',data=data_1,hue='gender',color='r')
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711110345615.png?x-oss-
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711110353115.png?x-oss-
三.資料預處理
- 1缺失值填補
#去除嚴重缺失值
data=data.drop(['edu_other','invest_other','join_party','property_other','s_work_status','s_work_type','work_manage','work_status','work_type','work_yr'],axis=1)
#data.info(verbose=True,null_counts=True)
資料缺失值填補-方法1,按照資料分布進行填補
均值填充----資料分布近似正态
中位數填充—資料存在離群點或者偏态分布
衆數填充—資料為不分大小的标簽值,如男女
data['edu_yr'].describe()
data.loc[data['edu_yr']<0,'edu_yr']=np.NAN
data['edu_yr'].value_counts()
plt.hist(data['edu_yr'].dropna())
#發現被調查者取得畢業證年份呈明顯的右偏分布,是以可以取中位數進行缺失值填補
data['edu_yr']=data['edu_yr'].fillna(data['edu_yr'].median())
data['edu_status']=data['edu_status'].fillna(data['edu_status'].median())
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711110514140.png?x-oss-
缺失值處理–方法2
插值法填充,使用缺失值前一個和後一個的平均數
data['social_neighbor'] = data['social_neighbor'].interpolate()
data['social_friend'] = data['social_friend'].interpolate()
缺失值處理-方法3
随機森林填充 随機森林,指的是利用多棵樹對樣本進行訓練并預測的一種分類器。該分類器最早由Leo Breiman和Adele
Cutler提出。簡單來說,是一種bagging的思想,采用bootstrap,生成多棵樹,CART(Classification And
Regression
Tree)構成的。對于每棵樹,它們使用的訓練集是從總的訓練集中有放回采樣出來的,這意味着,總的訓練集中的有些樣本可能多次出現在一棵樹的訓練集中,也可能從未出現在一棵樹的訓練集中。對于一個有n行的資料集,out
of bag 的機率大概是1/e=1/3。n趨向無窮大的時候,(1-1/n)^n~1/e。
了解上這個1/n是每次抽樣的比率嗎?是以out of bag到底是什麼意思?
1.在與其它現有的算法相比,其預測準确率很好 2.在較大的資料集上計算速度依然很快 3.不需要降維,算法本身是采取随機降維的
4.他能處理有缺失值的資料集。算法内部有補缺失值的函數 5.能給出變量的重要性 6.能處理imbalanced data set
7.能給出觀測執行個體間的相似度矩陣,其實就是proximity啦,繼而能做clustering 和 location outlier
8.能對unlabeled data 進行無監督的學習,進行clustering 9.生成的森林可以保留,應用在新的資料集上
#目前的缺失列"hukou_loc","family_income","minor_child","marital_1st","s_birth","marital_now","s_edu","s_political","s_hukou","s_income","s_work_exper"
list=["hukou_loc","family_income","minor_child","marital_1st","s_birth","marital_now","s_edu","s_political","s_hukou","s_income","s_work_exper"]
from sklearn.ensemble import RandomForestClassifier
for i in list:
re=data[data[i].notnull()]
rn=data[data[i].isnull()]
re_x=re[["province","gender","religion","edu","political","floor_area","health","hukou","son","daughter","status_peer","public_service_1"]].astype(float)
re_y=re[i].astype(float)
rn_x=rn[["province","gender","religion","edu","political","floor_area","health","hukou","son","daughter","status_peer","public_service_1"]].astype(float)
model=RandomForestClassifier()
model.fit(re_x,re_y)
pr=model.predict(rn_x)
data.loc[data[i].isnull(),i]=pr
3.2.異常值處理
#異常值處理
index_abnormal_weight = data.loc[data.weight_jin<70].index
for i in index_abnormal_weight :
if data["gender"].iloc[i]==1:
data["weight_jin"].iloc[i]=data["weight_jin"].iloc[i]*2
if data["gender"].iloc[i]==2:
if (data["height_cm"].iloc[i]>140) or (data["health"].iloc[i]>2):
data["weight_jin"].iloc[i]=data["weight_jin"].iloc[i]*2
data["weight_jin"].describe()
data.loc[data['income']<0,'income']=0
3.3.離散化處理
#離散化處理
#income
def income_cut(income):
if income<=3000:
return 1
if 3000<income<=8000:
return 2
if 8000<income<=15000:
return 3
if 15000<income<=35000:
return 4
if income>35000:
return 5
data["income"]=data["income"].map(income_cut)
data["s_income"]=data["s_income"].map(income_cut)
data["family_income"]=data["family_income"].map(income_cut)
data["inc_exp"]=data["inc_exp"].map(income_cut)
#處理時間特征
data['survey_time']=pd.to_datetime(data['survey_time'])
data['survey_year']=data['survey_time'].dt.year
#問卷年齡
data['age']=data['survey_year']-data['birth']
data['age'].describe()
def age_cut(birth):
if birth<=18:
return 1
if 18<birth<=25:
return 2
if 25<birth<=40:
return 3
if 40<birth<=60:
return 4
if birth>60:
return 5
data['age']=data['age'].map(age_cut)
#出生年代
data['birth'].describe()
def birth_cut(birth):
if birth<=1940:
return 1
if 1940<birth<=1955:
return 2
if 1955<birth<=1970:
return 3
if 1970<birth<=1985:
return 4
if birth>1985:
return 5
data['birth']=data['birth'].map(birth_cut)
data['edu_yr']=data['edu_yr'].map(birth_cut)
data["s_birth"]=data["s_birth"].map(birth_cut)
data["s_birth"]=data["s_birth"].map(birth_cut)
data["marital_1st"]=data["marital_1st"].map(birth_cut)
data["marital_now"]=data["marital_now"].map(birth_cut)
#房屋面積分組
def floor(x):
if 0<=x<=50:
return 1
elif 50<x<=100:
return 2
elif 100<x<=200:
return 3
elif 200<x<=400:
return 4
elif x>400:
return 5
data["floor_area"]=data["floor_area"].map(floor)
#身高分組
def height(x):
if x<=130:
return 1
elif 130<x<=150:
return 2
elif 150<x<=170:
return 3
elif 170<x<=190:
return 4
elif x>190:
return 5
data["height_cm"]=data["height_cm"].map(height)
#體重分組
def weight(x):
if x<=70:
return 1
elif 70<x<=90:
return 2
elif 90<x<=110:
return 3
elif 110<x<=150:
return 4
elif x>150:
return 5
data["weight_jin"]=data["weight_jin"].map(weight)
#社會公共服務分組
def service(x):
if x<10:
return 0
elif 10<=x<30:
return 1
elif 30<x<=50:
return 2
elif 50<x<70:
return 3
elif 70<x<90:
return 4
else:
return 5
data["public_service_1"]=data["public_service_1"].map(service)
data["public_service_2"]=data["public_service_2"].map(service)
data["public_service_3"]=data["public_service_3"].map(service)
data["public_service_4"]=data["public_service_4"].map(service)
data["public_service_5"]=data["public_service_5"].map(service)
data["public_service_6"]=data["public_service_6"].map(service)
data["public_service_7"]=data["public_service_7"].map(service)
data["public_service_8"]=data["public_service_8"].map(service)
data["public_service_9"]=data["public_service_9"].map(service)
#提取标簽 并去除無關變量
y=data['happiness']
data=data.drop(["id"], axis=1)
data=data.drop(["happiness"], axis=1)
data=data.drop(["survey_time"], axis=1)
data=data.drop(["property_0"], axis=1)
#對标簽異常值進行處理
y.describe()
y[y<0]=y.median()
#去除異常值多的變量
data=data.drop(["f_birth"], axis=1)
data=data.drop(["m_birth"], axis=1)
#對省份按照區域進行重新劃分
data['province'].describe()
def pro(province):
if province in [1,15,9,10,19,24]:
return 1
if province in [12,13,20]:
return 2
if province in [21,22,18,16]:
return 3
if province in [4,7,17,11,3]:
return 4
if province in [8,14,30,29,23]:
return 5
if province in [6,2,26,25,28]:
return 6
if province in [27,5,31]:
return 7
data['province']=data['province'].map(pro)
3.4.獨熱編碼
需要進行獨熱編碼的有宗教,性别,省份,政治身份,戶口,戶口所在地等
from sklearn.preprocessing import OneHotEncoder
category_name=["survey_type","gender","religion","nationality","political",
"hukou","hukou_loc","province"]
category_feature=data[category_name]
category_feature
enc=OneHotEncoder(categories="auto")
category_feature=enc.fit_transform(category_feature).toarray()
category_feature=pd.DataFrame(category_feature)
data=pd.concat([data,category_feature],axis=1)
data.drop(category_name,axis=1)
3.5.特征選擇
特征選擇 模型在預處理後仍有176個變量,是以我們使用随機森林對特征進行選取,并對特征的重要性進行排序
可以看出對幸福感影響最大的前十個變量分别是社會地位,戶口所在地,房産擁有,健康狀況,沮喪程度等
用有抽樣放回的方法(bootstrap)從樣本集中選取n個樣本作為一個訓練集,用抽樣得到的樣本集生成一棵決策樹。在生成的每一個結點:随機不重複地選擇d個特征,利用這d個特征分别對樣本集進行劃分,找到最佳的劃分特征(可用基尼系數、增益率或者資訊增益判别)。重複步驟1到步驟2共k次,k即為随機森林中決策樹的個數。用訓練得到的随機森林對測試樣本進行預測,并用票選法決定預測的結果。
用随機森林進行特征重要性評估的思想就是看看每個特征在随機森林中的每顆樹上做了多大的貢獻,然後取平均值,最後比較特征之間的貢獻大小。
data=pd.DataFrame(data)
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import SelectFromModel
import matplotlib.pyplot as plt
import numpy as np
from plotly.graph_objs import *
from plotly.offline import init_notebook_mode, iplot
#定義一個由500顆決策樹組成的随機森林模型
rf_model = RandomForestClassifier(n_estimators=500,max_depth=5,random_state=0,n_jobs=-1)
#訓練
rf_model.fit(data,y)
#擷取特征的重要性
importances = rf_model.feature_importances_
#對特征的重要性進行排序
indices = np.argsort(importances)[::-1]
cols_name = data.columns[1:]
for f in range(10):
print("%2d) %-*s %f" % (f + 1,30,cols_name[indices[f]],importances[indices[f]]))
plt.figure(figsize=(10, 8))
plt.title("特征的重要性")
plt.bar(range(data.shape[1]),importances[indices],color="lightblue",align="center")
plt.xticks(range(data.shape[1]),cols_name)
plt.xlim([-1,data.shape[1]])
plt.show()
model = SelectFromModel(rf_model, prefit=True)
data= model.transform(data)
data.shape
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711111009173.png?x-oss-
四.模型建立
#模型拟合
#進行k折交叉驗證下的xgboost回歸
from sklearn.metrics import accuracy_score
from xgboost.sklearn import XGBRegressor
from sklearn.metrics import mean_squared_error
from sklearn.externals import joblib
from sklearn.model_selection import KFold
from sklearn.metrics import roc_curve,roc_auc_score,confusion_matrix
data=pd.DataFrame(data)
kfold = KFold(n_splits=10, shuffle = True, random_state= 11)
model = XGBRegressor(base_score=0.5, booster='gbtree', colsample_bylevel=0.1,
colsample_bytree=0.971, gamma=0.11, learning_rate=0.069, max_delta_step=0,
max_depth=4, min_child_weight=1, missing=None, n_estimators=300,
n_jobs=-1, nthread=50, objective='reg:linear', random_state=0,
reg_alpha=0.1, reg_lambda=1, scale_pos_weight=1, seed=None,
silent=True, subsample=1.0)
mse = []
auc=[]
i = 0
for train, test in kfold.split(data):
x_train = data.iloc[train]
y_train = y.iloc[train]
x_test = data.iloc[test]
y_test = y.iloc[test]
model.fit(x_train,y_train)
y_pred = model.predict(x_test)
y_test= pd.DataFrame(y_test)
xg_mse = mean_squared_error(y_true=y_test,y_pred=y_pred)
predictions = [round(value) for value in y_pred]
accuracy = accuracy_score(y_test, predictions)
mse.append(xg_mse)
auc.append(accuracy)
print("mean squared_error",xg_mse)
print("accuracy",accuracy)
joblib.dump(filename="xg"+str(i),value=model)
i+=1
print("xgboost-mean squared_error",np.mean(mse))
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20190711111328528.png?x-oss-