又是一次數據分析的例子(自殺分析)

前言

在這裏插入圖片描述
究竟是什麼讓我凌晨四點一邊看着人家吃美食,一邊敲代碼,寫博客,原因呢就是需要幫別人做這次的數據分析。
在這裏插入圖片描述

數據分析的背景

來自於kaggle的一次比賽
點這裏去查看/下載數據
在這裏插入圖片描述
在這裏插入圖片描述
關於數據集的介紹等下在代碼中可以看到,這裏就不多說了。
這次競賽就是通過一系列特徵來找到自殺率上升的信號(也就是影響自殺率的因素)

開始數據分析

1.導庫、導數據,簡單的數據處理

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import scikitplot as skplt
import sklearn as sk
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
plt.rcParams['font.sans-serif']='fangsong'
plt.rcParams['axes.unicode_minus']=False

import warnings
warnings.filterwarnings("ignore")
# 導入原始自殺數據集並重新命名列:

originaldata = pd.read_csv('./master.csv')

# 國家,  年份,  性別,  年齡,  自殺人數,  人口數量,  自殺人數/總人口*100000(自殺率),
# 國家-年份,     人類發展指數(用以衡量聯合國各成員國經濟社會發展水平的指標,是對傳統的GNP指標挑戰的結果。)
# 年度國內生產總值(衡量經濟發展的指標),      年人均國內生產總值:國內生產總值/人口 ,         世代
originaldata.columns = ['country', 'year', 'sex', 'age', 'suicides_no', 'population','suicidesper100k',
                      'country-year', 'yearlyHDI', 
                        'GDPpyear', 'GDPpcapita', 'generation']

originaldata.head()

在這裏插入圖片描述

# 修復和清理原始數據

# 將 年度國內生產總值 數據中 ','分割去除掉(比如2,156,624,900),並且轉換成float的數字類型
originaldata['GDPpyear'] = originaldata.apply(lambda x: float(x['GDPpyear'].replace(',', '')), axis=1)
originaldata['GDPpyear'].head(10)

# sex 轉換爲category類型
# Categoricals 是 pandas 的一種數據類型,對應着被統計的變量。Categoricals 是由固定的且有限數量的變量組成的。
originaldata.sex.astype('category')

在這裏插入圖片描述

# 導入額外功能的自殺數據集:
extra_data = pd.read_csv('./suicidedataextrafestures.csv')

# 國家,   年份,   性別,   年齡,    自殺人數,    人口數量,
# 自殺人數/總人口*100000(自殺率),   國家-年份,   人類發展指數(用以衡量聯合國各成員國經濟社會發展水平的指標,是對傳統的GNP指標挑戰的結果。)
# 年度國內生產總值(衡量經濟發展的指標) ,    年人均國內生產總值:國內生產總值/人口
# 世代, 自殺率,  使用互聯網的個人(占人口的百分比),     費用(佔國內生產總值的百分比),    僱員補償(工資)(佔開支的百分比)
# 失業總人數(佔勞動力總數的百分比),   醫生(每1 000人),    法律權利指數的強弱(0=弱至12=強),   勞動力總數
# 預期壽命,總計(年),        移動電話訂閱(每100人)
# 按原籍國或領土分列的難民人口,    貢獻型家庭工人總人數(佔總就業人數的百分比)(模擬勞工組織估計數)
# 獲得電力(占人口的百分比),        中學畢業率,共計(佔相關年齡組的百分比)
extra_data.columns = [
    'country', 'year', 'sex', 'age', 'suicides_no', 'population',
    'suicidesper100k', 'country-year', 'yearlyHDI',
    'GDPpyear', 'GDPpcapita', 
    'generation', 'suicide%', 'Internetusers', 'Expenses', 'employeecompensation',
    'Unemployment', 'Physiciansp1000', 'Legalrights', 'Laborforcetotal',
    'Lifeexpectancy', 'Mobilesubscriptionsp100',
    'Refugees', 'Selfemployed', 
    'electricityacess', 'secondarycompletion']

在這裏插入圖片描述
來自WDI數據庫的額外數據中1985年到1994年和2014年的數據空白太多,只能用1995-2013年的數據,因此我決定將數據限制在這段時間內。

df1 = extra_data.copy()
# 阿根廷的一系列數據
df = df1.iloc[np.where(df1.country == countrynames[0])] 
for i, x in enumerate(countrynames[1:]):
    df = df.append(df1.iloc[np.where(df1.country == x)])  #添加剩餘的國家數據
    
df = df[df.year >= 1995] #用 1995-2013年的數據  
df = df[df.year <= 2013]
df.head(100000000)

2.探索性數據分析

col = plt.cm.Spectral(np.linspace(0, 1, 20))

plt.figure(figsize=(8, 6))

agedistf = pd.DataFrame(df.groupby('sex').get_group('female').groupby('age').suicides_no.sum())

agedistm = pd.DataFrame(df.groupby('sex').get_group('male').groupby('age').suicides_no.sum())

plt.bar(agedistm.index, agedistm.suicides_no, color=col[18])
plt.bar(agedistf.index, agedistf.suicides_no, color=col[8])
plt.legend(['male', 'female'], fontsize=16)
plt.ylabel('Count', fontsize=14)
plt.xlabel('Suicides per 100K', fontsize=14)
plt.show()

在這裏插入圖片描述

總體看下來,不管是哪個年齡段,男性的自殺率都要比女性高。 尤其是25-34歲以及35-54歲年齡段是自殺的高峯期,男女自殺率接近於3:1,而原因是因爲工作和生活壓力較大,家庭、情感以及經濟問題會導致精神崩潰,很容易走上絕路。這是個緊迫而又嚴肅的問題,不僅要重視身體健康更要重視精神健康。 其次是55-74歲,55歲以上的老年人也已經成爲自殺率很高的人羣,多是因爲孤獨而導致抑鬱。此外,與子女的矛盾、生理機能喪失也是導致老人抑鬱自殺的原因 而15-24歲的青少年也是自殺高危年齡段,這可能是由於青年人學業的壓力以及開始走出校園走向工作崗位,並嘗試獨立生活而又缺乏生活經驗,同時又要面臨成家立業的巨大壓力所導致的。

col = plt.cm.Spectral(np.linspace(0, 1, 22))
plt.figure(figsize=(12, 15))

plt.subplot(211)
#自殺率(放大1000倍)的平均值最高的前10個國家
df.groupby(['country']).suicidesper100k.mean().nlargest(10).plot(kind='bar', color=col) 
plt.xlabel('Average Suicides/100k', size=20)
plt.ylabel('Country', fontsize=20)
plt.title('Top 10 countries', fontsize=30)

plt.figure(figsize=(12, 15))

plt.subplot(212)
#自殺人數的平均值最高的前10個國家
df.groupby(['country']).suicides_no.mean().nlargest(10).plot(kind='bar', color=col)
plt.xlabel('Average Suicides_no', size=20)
plt.ylabel('Country', fontsize=20);
plt.title('Top 10 countries', fontsize=30)
plt.show()

在這裏插入圖片描述
在這裏插入圖片描述
自殺率排在前10的國家爲 俄羅斯(歐洲)、 匈牙利(歐洲)、烏克蘭(歐洲)、 克羅地亞 (歐洲)、日本(亞洲)、澳大利亞 (大洋洲)、芬蘭 (歐洲)、古巴 (美洲)、比利時(歐洲)、 瑞士(歐洲)

自殺人數排前10的國家爲 俄羅斯(歐洲)、美國(美洲)、日本(亞洲)、烏克蘭(歐洲)、德國(歐洲)、法國(歐洲)、 巴西(美洲)、波蘭(歐洲)、泰國 (亞洲)、英國(歐洲)
可以發現歐洲國家的自殺人數和自殺率都非常高,例如俄羅斯、烏克蘭、英國等。 也可以發現俄羅斯、日本等國家高居自殺率都偏高,這些國家是GDP、就業、奢侈品等方面最強大的國家,並且經濟實力也位於世界前列,而導致自殺率高的一個客觀原因是人口基數大,主觀原因可能是生活節奏飛快,生活代價很高,失業率嚴重、人際關係緊張等。

plt.figure(figsize=(10, 16))

#總人口的各個年齡段的性別分佈
plt.subplot(311)
sns.barplot(x='sex', y='population', hue='age', data=df, palette="Greens")  #hue按年齡分組
plt.xticks(ha='right', fontsize=20)
plt.ylabel('Population', fontsize=20)
plt.xlabel('Sex', fontsize=20)
plt.title("不同年齡段的男、女總人口數")
plt.legend(fontsize=14, loc='best')

#自殺人數的各個年齡段的性別分佈
plt.subplot(312)
sns.barplot(x='sex', y='suicides_no', hue='age', data=df, palette="Greens")
plt.xticks(ha='right', fontsize=20)
plt.ylabel('suicides incidences', fontsize=20)
plt.xlabel('Sex', fontsize=20)
plt.title("不同年齡段的男、女自殺人口數")
plt.legend(fontsize=14)

#自殺率(放大1000倍)的各個年齡段的性別分佈
plt.subplot(313)
sns.barplot(x='sex', y='suicidesper100k', hue='age', data=df,palette="Greens")
plt.xticks(ha='right', fontsize=20);
plt.ylabel('suicidesper100k',fontsize=20);
plt.xlabel('Sex',fontsize=20);
plt.title("不同年齡段的男、女自殺率")
plt.legend(fontsize=14);

plt.subplots_adjust(top=1.2)
plt.show()

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
圖1爲 各個不同年齡段的男、女總人口數據柱狀圖。 就總人口而言 各個年齡段的男女比例差不多。
圖2爲 各個不同年齡段的男、女自殺人口數據柱狀圖。 可以很明顯的看出男性的自殺人數遠遠大於女性自殺人數。 其可能的原因男性所承受的壓力要多於女性,精神方面會變得脆弱,並會導致身體不健康以及精神不健康。
圖3爲 各個不同年齡段的男、女自殺率人口數據柱狀圖。 就75+,也就是老年階段,從側面也反映出老齡化的問題。 在老齡化進程加速的狀況下,社會保障體系和社會經濟文化的發展難以滿足老年人的物質和精神需求, 多重矛盾造就了本該安享晚年的老年人,出現了比年輕人更嚴重的生存和精神壓力。 所以,老年人的生存現狀需要受到重視,應該不斷出臺老年人的保障措施,來保障老年人的老年生活。

plt.figure(figsize=(12, 16))

# 具體按性別和年份 來看 男女的自殺率
plt.subplot(311)
sns.lineplot(x='year', y='suicidesper100k', hue='sex', data=df, palette="hot")  #hue按年齡分組
plt.xticks(ha='right', fontsize=20)
plt.ylabel('suicidesper100k', fontsize=20)
plt.xlabel('year', fontsize=20)
plt.legend(fontsize=14, loc='best')  
plt.title("性別年份與自殺率關係圖")
plt.show()

在這裏插入圖片描述
圖爲 具體按性別和年份 來看 男女的自殺率 1995年-2013年男性自殺率遠遠大於女性。 女性自殺率水平在0.005%左右,男性自殺率水平在0.02%左右,男性自殺率約是女性的4倍。從時間來看,在這區間,全球範圍綜合自殺率並沒有出現明顯的下降
結合分析,在全球範圍內,男性自殺率高於女性,約爲女性自殺率的4倍左右。在現代社會中男性承擔的社會責任相對較大,相應的壓力也會增加。所以一個國家應該關注於提升人民生活質量,健全保障體系。在每個家庭面對突發的困難是能夠提供一定的保障,例如失業,生病,意外事故等。
全球範圍內,年齡越大的人羣自殺率相對較高。在現在全球人口老齡化的趨勢下,這種情況無疑更加嚴峻。關於老年人羣的生活的物質條件需要改善,其心理更需要梳理與關注。

plt.figure(figsize=(8, 6))

#選出year列並且去除重複的年份
year = originaldata.groupby('year').year.unique()

#各個年份的自殺人數彙總
#使用seaborn進行可視化,輸入的數據必須爲dataframe
totalpyear = pd.DataFrame(originaldata.groupby('year').suicides_no.sum())   

plt.plot(year.index[0:31], totalpyear[0:31], color=col[18])  #選取範圍爲[0:31]  1985年到2015年
plt.xlabel('year', fontsize=15)
plt.ylabel('Total number of suicides in the world', fontsize=15)
plt.show()

在這裏插入圖片描述

世界自殺人數趨勢2000年之前逐步上升,2000年後呈現緩慢下降趨勢 在2000年之前,人們所處的地區條件乏善可陳,人羣受教育程度偏低,社會動盪,經濟發展水平不高。 之後,隨着科技的進步以及社會經濟不斷髮展,社會更加安穩。混亂、貧窮、飢餓的現象變少,人們的的焦慮有改善。各國政府在醫療保健上的投入和家庭護理的提升也會使自殺趨勢降低。

plt.figure(figsize=(20, 8))

# 自殺率(放大1000倍)的分佈情況,y軸爲個數
plt.subplot(121)
plt.hist(df.suicidesper100k, bins=30, color=col[18])   #bins:條形數
plt.xlabel('Suicides per 100K of population', fontsize=25)
plt.xticks(rotation = 0,                 fontsize = 20)  
plt.ylabel('count', fontsize=25)
plt.yticks(                              fontsize = 20)   

# 年人均國內生產總值的分佈情況,y軸爲個數
plt.subplot(122)
plt.hist(df.GDPpcapita, bins=30, color=col[7])
plt.xlabel('GDP', fontsize=25)
plt.xticks(rotation = 0,fontsize = 20)  
plt.ylabel('count', fontsize=25)
plt.yticks(fontsize = 20)   
plt.show()

在這裏插入圖片描述

plt.figure(figsize=(8, 5))

# suicides:“GDP年度國內生產總值(美元)”,“僱員補償%”,“失業人數%”,“預期壽命” 按“年份”分組
suicides = df[['year', 'GDPpyear', 'Selfemployed', 'Unemployment', 'Lifeexpectancy']].groupby('year').mean()

# suicides['Suicides'] 爲各年份的自殺率總數
suicides['Suicides'] = df[['country', 'year', 'suicidesper100k']].groupby('year').sum()

# suicides.index :從1995到2013年,   
# GDPpyear/suicides.GDPpyear.max()  : GDP年度國內生產總值/最大GDP年度國內生產總值
plt.plot(suicides.index, suicides.GDPpyear/suicides.GDPpyear.max(), color=col[1])  

# suicides.Unemployment:失業總人數(佔勞動力總數的百分比)(模擬勞工組織估計數)
# suicides.Unemployment.max():最大值
plt.plot(suicides.index, suicides.Unemployment/suicides.Unemployment.max(), color=col[7])

# suicides.Lifeexpectancy  ; 各年的預期壽命
plt.plot(suicides.index, suicides.Lifeexpectancy/suicides.Lifeexpectancy.max(), color=col[14])

# suicides.Suicides :各年的自殺率
plt.plot(suicides.index, suicides.Suicides/suicides.Suicides.max(), color=col[17])

plt.legend(
            ['global average GDPpyear',                            #紅線
            'global average Unemployment',                         #黃線
            'global average Life expectancy',                      #綠線
            'Total suicides per 100k'], fontsize=14, loc='best'    #藍線
            )
plt.ylabel('Normalized', fontsize=14)
plt.xlabel('year', fontsize=14)
plt.title("各年份全球平均GDP、平均失業率、平均預期壽命、平均自殺率趨勢圖")
plt.show()

在這裏插入圖片描述
從圖中可以看出
自1995 - 2013年,

  1. 全球的GDP不斷上漲,1995年到2000年緩慢上漲,2000年以後經濟增長的勢頭更強;受到金融危機的影響,2008年經濟下滑後又開始增長。
  2. 全球的失業率也隨經濟,社會發展,1995-2008逐年降低,之後又攀升。
  3. 全球的人預期壽命也隨着經濟的不斷髮展逐年上升,人民生活水平提高。
  4. 全球的整體自殺率是呈下降趨勢的,背後的原因可能是社會的安穩,國家政府的干預,各國政府在醫療保健上的投入和家庭護理的提升。
corr = total.corr() #相關係數矩陣,即給出了任意兩個變量之間的相關係數

# 相關矩陣的上三角部分與下三角對稱。因此,熱圖不需要顯示整個矩陣。在下一步隱藏上三角形。
# 設置mask隱藏上三角
# np.zeros_like() 返回一個零數組,其形狀和類型與給定的數組相同。
# 該 dtype=np.bool 參數會覆蓋數據類型,因此我們的數組是一個布爾數組。
# np.triu_indices_from(mask) 返回數組上三角形的索引。
# 現在,我們將上三角形設置爲True。 mask[np.triu_indices_from(mask)]= True
mask = np.zeros_like(corr, dtype=np.bool)
mask[np.triu_indices_from(mask)] = True

# 在Seaborn中創建熱圖
f, ax = plt.subplots(figsize=(10, 8))
# 生成自定義發散顏色圖
cmap = sns.diverging_palette(220, 10, as_cmap=True)

# 繪製熱圖
# 數據爲 corr
# vmax,vmin:分別是熱力圖的顏色取值最大和最小範圍
# center:數據表取值有差異時,設置熱力圖的色彩中心對齊值;通過設置center值,可以調整生成的圖像顏色的整體深淺
# square:設置熱力圖矩陣小塊形狀,默認值是False
# linewidths(矩陣小塊的間隔),
# cbar_kws:熱力圖側邊繪製顏色刻度條時,相關字體設置,默認值是None
sns.heatmap(corr, mask=mask, cmap=cmap, vmax=1, vmin=-1, center=0,  
            square=True, linewidths=0.2, cbar_kws={"shrink": 0.8})

在這裏插入圖片描述

3.數據預處理

# 對使用互聯網的個人(占人口的百分比) 用最小值填充 在原數據直接修改
total.Internetusers.fillna(total.Internetusers. min(), inplace=True)

# 對難民人口用8填充
total.Refugees.fillna(total.Refugees. min(), inplace=True)

#對僱員補償(佔開支的百分比)用均值填充
total.employeecompensation.fillna(total.employeecompensation.mean(), inplace=True)

# 對總人口用均值填充
total.population.fillna(total.population.mean(), inplace=True)

自殺風險的二元分類

對自殺數據進行二元分類,根據 自殺率(擴大1000倍) 作爲高/低自殺風險來劃分風險等級。
在“total”data frame中添加一個額外的列作爲‘risk’。

  • Suicides < mean(Suicides) --> 低風險 --> class 0
  • Suicides > mean(Suicides) --> 高風險 --> class 1
# 小於平均值的爲低風險,大於平均值的爲高風險
total['risk'] = total.Suicides.copy()
total['risk'] = np.where(total.risk < total.Suicides.mean(), 0, 1)
plt.figure(figsize=(16, 5))

plt.subplot(121)
plt.hist(total.risk, color=col[8])
plt.ylabel('counts', fontsize=20)
plt.xlabel('Suicide risk', fontsize=20)
plt.title("自殺高低風險數量")

plt.subplot(122)
sns.distplot(total.Suicides[total.risk == 0], bins=10)
sns.distplot(total.Suicides[total.risk == 1], bins=20)  
plt.xlabel('Suicides', fontsize=20)
plt.title("自殺高低風險分佈情況")
plt.show()

在這裏插入圖片描述

# 對國家進行 標準化標籤,將標籤值統一轉換成range(標籤值個數-1)範圍內
# 相當於fit(X).transform(X),意思就是先進行fit(),進行數據擬合,然後在進行transform() 進行標準化處理

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
total.country = le.fit_transform(total.country)  
total.country.unique()

# 爲建立模型準備數據
# totalfeatures 數據的 11個特徵
# array和asarray都可以將結構數據轉化爲ndarray   
# ndarray是Numpy中的數據結構,是一個多維數組,可以理解爲矩陣,具有矢量運算能力,快速、節省空間

X = np.asarray(total[totalfeatures])
y = np.asarray(total['risk'])

# 對數據應用標準定標器,因爲ML算法的工作假設是數據是正態分佈的
# 標準化數據
# sklearn.preprocessing.StandardScaler() 可保存訓練集中的均值、方差參數,然後直接用於轉換測試集數據。
scaler = StandardScaler()
scaler.fit(X)
X_scaled = scaler.transform(X)

劃分訓練集、測試集和驗證集

# 將數據集拆分爲訓練集和測試集 576行 11個特徵
# 首先將該數據3/4作爲訓練集,1/4作爲測試集;再由訓練集劃分1/5作爲驗證集
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.25, random_state=4)
X_train,X_valid,y_train,y_valid=train_test_split(X_train,y_train,test_size=0.2,random_state=4)
print('Train set:', X_train.shape, y_train.shape)
print('Test set:', X_test.shape, y_test.shape)
print('Test set:', X_valid.shape, y_valid.shape)
# GDP = 僱員報酬 + 固定資產消耗 + 生產稅和進口稅淨額 + 營業盈餘
# 這裏面的“僱員報酬”僅僅只是GDP其中的一個組成部分
ax1 = total[total['risk'] == 1][0:200].plot(kind='scatter', x='GDPpcapita', y='employeecompensation', color='DarkRed',
                                            label='high risk', figsize=(6, 5), fontsize=12)
total[total['risk'] == 0][0:200].plot(kind='scatter', x='GDPpcapita', y='employeecompensation', color='DarkBlue',
                                            label='low risk', ax=ax1)

plt.ylabel('employeecompensation', fontsize=16)
plt.xlabel('GDP per capita', fontsize=16)
plt.legend(fontsize=14)


# 預期壽命 和 貢獻型家庭工人總人數(佔總就業人數的百分比) 的高低風險
ax1 = total[total['risk'] == 1][0:200].plot(kind='scatter', x='Lifeexpectancy', y='Selfemployed', color='DarkRed',
                                            label='high risk', figsize=(6, 5), fontsize=12)
total[total['risk'] == 0][0:200].plot(kind='scatter', x='Lifeexpectancy', y='Selfemployed', color='DarkBlue',
                                            label='low risk', ax=ax1);

plt.ylabel('Selfemployed', fontsize=16)
plt.xlabel('Lifeexpectancy', fontsize=16)
plt.legend(fontsize=14)


# 人均國內生產總值(美元) 和 失業總人數(佔勞動力總數的百分比) 的高低風險
ax1 = total[total['risk'] == 1][0:200].plot(kind='scatter', x='GDPpcapita', y='Unemployment', color='DarkRed',
                                            label='high risk', figsize=(6, 5), fontsize=12);
total[total['risk'] == 0][0:200].plot(kind='scatter', x='GDPpcapita', y='Unemployment', color='DarkBlue',
                                            label='low risk', ax=ax1);

plt.ylabel('Unemployment', fontsize=16)
plt.xlabel('GDP per capita', fontsize=16)
plt.legend(fontsize=14)
plt.show()

在這裏插入圖片描述
圖1爲 人均GDP 和 僱員的報酬(工資)(佔開支的百分比) 的關於自殺率高低的一個分類。

僱員的報酬(工資) 是 人均GDP 的一部分,人均gdp集中在5000-50000美元;而工資佔開銷的 10%-30%,在人均gdp大致相同的情況下,工資越高,那麼自殺率相對會低,但是即使人均gdp很高的情況下,工資如果很低,自殺率也會偏高。

圖2爲 預期壽命 和 供養家庭職工總人數(佔總就業人數的百分比) 的高低風險

預期壽命分佈在70-82歲,而在預期壽命相同的情況下,若供養家庭職工總人數多,則自殺風險相對會低

圖3爲 人均國內生產總值(美元) 和 失業總人數(佔勞動力總數的百分比) 的高低風險
人均gdp越高,自殺率還是較低的;在人均gdp較低(0-15000美元)下,失業的人數反而不算高;但在中產和富裕階級中,失業人數越高,自殺風險更大。

# 關於年份的高低自殺風險
fig = plt.figure(figsize=(30, 30))

plt.subplot(4, 3, 1)
sns.distplot(total[total.columns[0]][total.risk == 0], label='low risk')
sns.distplot(total[total.columns[0]][total.risk == 1], label='high risk')       
plt.legend(loc='best', fontsize=18)  
plt.xlabel(total.columns[0], fontsize=18)
plt.show()

在這裏插入圖片描述

4.建模

根據他的要求,使用邏輯迴歸、決策樹、隨機森林這三種模型,並且對比找到最好的分類模型。

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import recall_score,accuracy_score
from sklearn.metrics import precision_recall_fscore_support
from sklearn.metrics import confusion_matrix, classification_report

LR = LogisticRegression(C=0.001, solver='liblinear').fit(X_train, y_train)

# 預測類別:0還是1
yLRhat = LR.predict(X_valid)
 
# 預測 0或1的概率(例如 [0.54689436, 0.45310564] 預測出來爲0)
yLRhat_prob = LR.predict_proba(X_valid)

cm = confusion_matrix(y_valid, yLRhat)
print('\n confusion matrix:混淆矩陣 \n', cm)
print('此時模型準確率爲:',accuracy_score(y_valid, yLRhat))
print('********************************************************')
print('\n')
print('邏輯迴歸模型的分類報告\n', classification_report(y_valid, yLRhat))

skplt.metrics.plot_confusion_matrix(y_valid,yLRhat,normalize=True)
plt.show()

在這裏插入圖片描述
在這裏插入圖片描述
這裏的超參數調整我使用網格搜索,因爲邏輯迴歸的超參數較少且模型訓練的比較快,而且網格搜索自帶就有交叉驗證。

from sklearn.model_selection import GridSearchCV

param={"tol":[1e-4, 1e-3,1e-2], "C":[0.4, 0.6, 0.8]}
grid = GridSearchCV(LogisticRegression(),param_grid=param, cv=5)#這裏是5折交叉驗證
grid.fit(X_train,y_train)
print(grid.best_params_)
print(grid.best_score_)

#得到最好的邏輯迴歸分類器
best_LR=grid.best_estimator_ 

#進行訓練、預測
best_LR.fit(X_train,y_train)
pred=best_LR.predict(X_valid)

cm = confusion_matrix(y_valid, pred)
print('\n confusion matrix:混淆矩陣 \n', cm)
print('最好的邏輯迴歸模型準確率爲:',accuracy_score(y_valid, pred))
print('********************************************************')
print('\n')
print('最好的邏輯迴歸模型的分類報告\n', classification_report(y_valid, pred))

在這裏插入圖片描述
邏輯迴歸分類效果並不好,再來看看決策樹

from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix, classification_report

# 決策樹學習
# 函數爲創建一個決策樹模型
# criterion:gini或者entropy,前者是基尼係數,後者是信息熵。
# max_depth:  int or None, optional (default=None) 設置決策隨機森林中的決策樹的最大深度,深度越大,越容易過擬合,推薦樹的深度爲:5-20之間。
# max_leaf_nodes: 通過限制最大葉子節點數,可以防止過擬合,默認是"None”,即不限制最大的葉子節點數。
DT = DecisionTreeClassifier(criterion="entropy", max_depth=7, max_leaf_nodes=30)
DT.fit(X_train, y_train)
ydthat = DT.predict(X_valid)

print('***決策樹模型***')

#決策樹模型性能評估
print('驗證集上的準確率:', DT.score(X_valid, y_valid))
print('訓練集上的準確率:', DT.score(X_train, y_train))

# 混淆矩陣
print('CM\n', confusion_matrix(y_valid, ydthat))
print('********************************************************')

print('決策樹模型的分類報告\n', classification_report(y_valid, ydthat))

DTfeat_importance = DT.feature_importances_
DTfeat_importance = pd.DataFrame([totalfeatures, DT.feature_importances_]).T

# 特徵重要性排序
print("特徵重要性排名如下:")
print(f'\n一共有{DT.n_features_}個特徵')
print(DTfeat_importance.sort_values(by=1, ascending=False))

在這裏插入圖片描述

# 通過cv_results觀察過程並做圖
max_depth=np.arange(0,20,3)
max_leaf_nodes=np.arange(0,30,3)
min_samples_leaf =np.arange(0,20,2)
param1= {'criterion':['entropy'],'max_depth':max_depth}
param2= {'criterion':['entropy'],'min_samples_leaf':min_samples_leaf}
param3= {'criterion':['entropy'],'max_leaf_nodes':max_leaf_nodes}


clf1 = GridSearchCV(DecisionTreeClassifier(),param_grid=param1,cv=6)
clf1.fit(X_train,y_train)

clf2 = GridSearchCV(DecisionTreeClassifier(),param_grid=param2,cv=6)
clf2.fit(X_train,y_train)


clf3 = GridSearchCV(DecisionTreeClassifier(),param_grid=param3,cv=6)
clf3.fit(X_train,y_train)



fig = plt.figure()
ax = fig.add_subplot(311)
ax.plot(min_samples_leaf,clf2.cv_results_['mean_test_score'],'g*-')
plt.title('決策樹模型網格搜索的訓練過程')


ax = fig.add_subplot(312)
ax.plot(max_depth,clf1.cv_results_['mean_test_score'],'g*-')

ax = fig.add_subplot(313)
ax.plot(max_leaf_nodes,clf3.cv_results_['mean_test_score'],'g*-')
plt.show()

在這裏插入圖片描述

best_DT = DecisionTreeClassifier(criterion="entropy", max_depth=15, max_leaf_nodes=25,min_samples_leaf=4)
best_DT.fit(X_train, y_train)
ydthat =best_DT.predict(X_valid)

print('***決策樹模型***')

#決策樹模型性能評估
print('驗證集上的準確率:',best_DT.score(X_valid, y_valid))
print('訓練集上的準確率:',best_DT.score(X_train, y_train))

# 混淆矩陣
print('CM\n', confusion_matrix(y_valid, ydthat))
print('********************************************************')

print('決策樹模型的分類報告\n', classification_report(y_valid, ydthat))

DTfeat_importance = best_DT.feature_importances_
DTfeat_importance = pd.DataFrame([totalfeatures, DT.feature_importances_]).T

# 特徵重要性排序
print("特徵重要性排名如下:")
print(f'\n一共有{best_DT.n_features_}個特徵')
print(DTfeat_importance.sort_values(by=1, ascending=False))

在這裏插入圖片描述
在這裏插入圖片描述

# 隨機森林可以視爲多顆決策樹的集成,魯棒性更強,泛化能力更好,不易產生過擬合現象。但是噪聲比較大的情況下會過擬合。

from sklearn.ensemble import RandomForestClassifier

random_forest = RandomForestClassifier(n_estimators=20, max_depth=10, min_samples_split=2, min_samples_leaf=5,
                                       max_leaf_nodes=20, max_features=len(totalfeatures)) 

random_forest.fit(X_train, y_train)

yrfhat = random_forest.predict(X_valid)
feat_importance = random_forest.feature_importances_
rffeat_importance = pd.DataFrame([totalfeatures, random_forest.feature_importances_]).T

print('******************Random forest classifier**************')
print('訓練集上的準確率', random_forest.score(X_train, y_train))
print('驗證集上的準確率', random_forest.score(X_valid,y_valid))
print('混淆矩陣\n', confusion_matrix(y_valid, yrfhat))
print('********************************************************')
print('隨機森林的分類報告\n', classification_report(y_valid, yrfhat))
print(rffeat_importance.sort_values(by=1, ascending=False))
#我們首先對n_estimators進行網格搜索:
param_test1 = {'n_estimators':[50,120,160,200,250]}
gsearch1 = GridSearchCV(estimator = RandomForestClassifier(), param_grid = param_test1,cv=5)
gsearch1.fit(X_train,y_train)
print( gsearch1.best_params_, gsearch1.best_score_)

#接着我們對決策樹最大深度max_depth和內部節點再劃分所需最小樣本數min_samples_split進行網格搜索。
param_test2 = {'max_depth':[1,2,3,5,7,9,11,13,20],'min_samples_split':[5,10,25,50,100,120,150]}
gsearch2 = GridSearchCV(estimator = RandomForestClassifier(n_estimators=200),param_grid = param_test2, cv=5)
gsearch2.fit(X_train,y_train)
print( gsearch2.best_params_, gsearch2.best_score_)


#最好的隨機森林模型
best_rf=RandomForestClassifier(n_estimators=200, max_depth=20, min_samples_split=10) 

best_rf .fit(X_train, y_train)

yrfhat = best_rf .predict(X_valid)
feat_importance = best_rf.feature_importances_
rffeat_importance = pd.DataFrame([totalfeatures, random_forest.feature_importances_]).T

print('******************隨機森林模型**************')
print('訓練集上的準確率',best_rf.score(X_train, y_train))
print('驗證集上的準確率',best_rf.score(X_valid,y_valid))
print('混淆矩陣\n', confusion_matrix(y_valid, yrfhat))
print('********************************************************')
print('最好的隨機森林模型的分類報告\n', classification_report(y_valid, yrfhat))
print(rffeat_importance.sort_values(by=1, ascending=False))

在這裏插入圖片描述
在這裏插入圖片描述
通過roc比較三種模型性能

models = [best_LR, best_DT,best_rf]
modelnames = ['Logistic regression',  'Random Forest', 'Decison tree']


for i, x in enumerate(models):
    y_true = y_test
    y_probas = x.predict_proba(X_test)
    ax1 = skplt.metrics.plot_roc(y_true, y_probas, plot_micro=False, plot_macro=True, classes_to_plot=[], figsize=(5, 5))
    plt.axis((-0.01, 1, 0, 1.1))
    plt.legend([modelnames[i]], loc='best')

在這裏插入圖片描述

dtpred=best_DT.predict(X_test)
rfpred=best_rf.predict(X_test)

dt_score=accuracy_score(y_test,dtpred)
rf_score=accuracy_score(y_test,rfpred)

print("決策樹在測試集上準確率爲:",dt_score)
print("隨機森林在測試集上準確率爲:",rf_score)

if dt_score>rf_score:
    print("決策樹模型是三者中最好的分類模型")
else:
    print("隨機森林是三者中最好的分類模型")

在這裏插入圖片描述
在這裏插入圖片描述

5.分析與總結


分析:

從上面的條形圖中我們可以發現影響自殺率的主要特徵是employeecompensation、Selfemployed、Refugees、country、GDPpyear、population

首先我們的自殺率=自殺人數/總人口數
接下來我們就對這幾個特徵影響自殺率的原因進行分析:

  1. employeecompensation(工資)當工資低,佔開支的百分比較少時,也就意味着生活質量很低,從而自殺率升高;
  2. Selfemployed(個體經營家庭總人數佔比)當個體經營家庭總人數佔比高時,就業壓力相對較小,所以自殺率較低;
  3. Refugees(難民人口)當難民人口較多時,難民生存困難,很有可能就因爲各種原因墮落消沉從而導致自殺率升高;
  4. country(國家)發達國家的人民生活節奏快,競爭壓力大,失業率高,所以自殺率高;
  5. GDPpyear(國家的年度生產總值)經濟發展快速的國家,也就有更大的就業競爭壓力,從而GDPpyear高的國家自殺率高;
  6. population(人口數量)由於我們計算的是自殺率,從而人口數量也是一個影響因素;當具有相同自殺人數時,人口總數越高,自殺率越低;而人口基數越大,自殺率也會升高。

總結:

對於一個國家來說

  • 當人們工資少,那麼自殺率會升高(最重要!!!也說明了物質社會人們對於物質的需求還是很渴望的)
  • 當每個家庭和睦、家庭氛圍好,家庭壓力小,那麼自殺率會降低
  • 當難民較多,那麼自殺率會升高
  • 當國家越發達,GDP越高,那麼生活節奏飛快,生活成本很高,失業率嚴重、人際關係緊張等,從而導致自殺率高
  • 對於人口數量多的國家,自殺人數處於正態分佈,當人口數量足夠大時,相應的自殺率也就很小

全球範圍內,年齡越大的人羣自殺率相對較高。在現在全球人口老齡化的趨勢下,這種情況無疑更加嚴峻。關於老年人羣的生活的物質條件需要改善,其心理更需要梳理與關注。而男性比起女性來說社會壓力更大,從而自殺率也更大,所以公司也應該定期對職員進行心理疏導。

6.不足與改進:

不足:

從這次數據分析基本得到了結論,也與實際相符合,但是回顧來看,模型依然是過擬合的,我們只能減小過擬合程度;對於網格搜索的超參數由於各種原因限制,我們也無法實驗所有的超參數,從而也無法真正得到最優參數與最優模型,得到的只能是相對較好的,泛化能力較強的模型;但是隨機森林作爲最好的分類模型,雖然它的受噪音影響小,魯棒性更強,但是如果數據噪音較大也容易過擬合。

改進:

  1. 我們可以嘗試更多的分類模型,比如:SVM、KNN、MLP或者是更復雜的神經網絡
  2. 我們可以先對數據特徵做處理,比如特徵提取(PCA、LDA、SVD),特徵提取(Filter、Wrapper、Embedded),或者基於不純度的減少量作爲指標,得到最主要的特徵再進行建模
  3. 加入更多的超參數進行搜索,得到更貼近最好的分類模型

最後

這個世界有意思的事情還是很多的,稍微別那麼在乎物質需求方面,會發現世界的另一面。總之還是積極向上點吧,我繼續極限導數微分積分去了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章