前兩篇博客分別對拉勾中關於 python 數據分析有關的信息進行獲取(http://www.javashuo.com/article/p-qnpnnrdm-eo.html)和對獲取的數據進行可視化分析(http://www.javashuo.com/article/p-vhbptmji-t.html),此次咱們就用 sklearn 對不一樣學歷和工做經驗的 python 數據分析師作一個簡單的工資預測。因爲在前面兩篇博客中已經瞭解了數據集的大概,就直接進入正題。html
在這以前先導入模塊並讀入文件,不只有訓練數據文件,還有一組自擬的測試數據文件。python
import pandas as pd import numpy as np import matplotlib.pyplot as plt train_file = "analyst.csv" test_file = "test.csv" # 讀取文件得到數據 train_data = pd.read_csv(train_file, encoding="gbk") train_data = train_data.drop('ID', axis=1) test_data = pd.read_csv(test_file, encoding="gbk") train_data.shape, test_data.shape
爲了更好地進行分析,咱們要對薪資作一個預處理。因爲其分佈比較散亂,不少值的個數只有1。爲了避免形成過大的偏差,根據其分佈狀況,能夠將它分紅【5k 如下、5k-10k、10k-20k、20k-30k、30k-40k、40k 以上】,爲了更加方便咱們分析,取每一個薪資範圍的中位數,並劃分到咱們指定的範圍內。git
salarys = train_data['薪資'].unique() # 獲取到薪資的不一樣值 for salary in salarys: # 根據'-'進行分割並去掉'k',分別將兩端的值轉換成整數 min_sa = int(salary.split('-')[0][:-1]) max_sa = int(salary.split('-')[1][:-1]) # 求中位數 median_sa = (min_sa + max_sa) / 2 # 判斷其值並劃分到指定範圍 if median_sa < 5: train_data.replace(salary, '5k如下', inplace=True) elif median_sa >= 5 and median_sa < 10: train_data.replace(salary, '5k-10k', inplace=True) elif median_sa >= 10 and median_sa < 20: train_data.replace(salary, '10k-20k', inplace=True) elif median_sa >= 20 and median_sa < 30: train_data.replace(salary, '20k-30k', inplace=True) elif median_sa >= 30 and median_sa < 40: train_data.replace(salary, '30k-40k', inplace=True) else: train_data.replace(salary, '40k以上', inplace=True)
處理完成後,咱們能夠將「薪資」單獨提取出來看成訓練集的 label。github
y_train = train_data.pop('薪資').values
因爲變量都不是numerical變量,在訓練的時候計算機沒辦法識別,所以要對它們進行轉換。 當咱們用numerical來表達categorical的時候,要注意,數字自己有大小的含義,因此亂用數字會給以後的模型學習帶來麻煩。因而咱們能夠用One-Hot的方法來表達category。算法
pandas自帶的get_dummies方法,能夠一鍵作到One-Hot。 這裏按個人理解解釋一下One-Hot:好比說data['學歷要求']有'大專', '本科', '碩士', '不限'。但data['學歷要求']=='本科',則他能夠用字典表示成這樣{'大專': 0, '本科':1, '碩士':0, '不限':0},用向量表示爲[0, 1, 0, 0] 。app
在此以前,將測試集和訓練集組合起來一塊兒處理,稍微方便一點。性能
data = pd.concat((train_data, test_data), axis=0) dummied_data = pd.get_dummies(data) dummied_data.head()
爲了更好地理解 One-Hot ,把處理後的結果展現出來,獲得的結果是這樣的:學習
固然,也能夠用別的方法,好比用數字代替不一樣的值,這也是能夠的。測試
上次可視化分析的時候就已經知道數據集中不存在缺失值了,爲了走一下流程並確保正確性,再次看一下是否有缺失值。spa
dummied_data.isnull().sum().sort_values(ascending=False).head(10)
OK,很好,沒有缺失值。這些值比較簡單,不須要作那麼多工做,但仍是要先把訓練集和測試集分開。
X_train = dummied_data[:train_data.shape[0]].values
X_test = dummied_data[-test_data.shape[0]:].values
from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import cross_val_score features_scores = [] max_features = [.1, .2, .3, .4, .5, .6, .7, .8, .9] for max_feature in max_features: clf = DecisionTreeClassifier(max_features=max_feature) features_score = cross_val_score(clf, X_train, y_train, cv=5) features_scores.append(np.mean(features_score)) plt.plot(max_features, features_scores)
這個過程主要是經過交叉驗證得到使模型更好時的參數,交叉驗證大概能夠理解爲,把訓練集分紅幾部分,而後分別把他們設置爲訓練集和測試集,重複循環訓練獲得的結果取平均值。Emmm... 感受這樣講仍是有點籠統,仍是上網查來得詳細吧哈哈。
而後咱們獲得的參數和值得關係如圖所示:
可見當 max_features = 0.2 時達到最大,大概有0.5418。
集成學習簡單理解就是指採用多個分類器對數據集進行預測,從而提升總體分類器的泛化能力。這裏將採用sklearn 的 AdaBoostClassifier(adaptive boosting) 經過改變訓練樣本的權值,學習多個分類器,並將這些分類器進行線性組合,提升泛化性能。
from sklearn.ensemble import AdaBoostClassifier n_scores = [] estimator_nums = [5, 10, 15, 20, 25, 30, 35, 40] for estimator_num in estimator_nums: clf = AdaBoostClassifier(n_estimators=estimator_num, base_estimator=dtc) n_score = cross_val_score(clf, X_train, y_train, cv=5) n_scores.append(np.mean(n_score)) plt.plot(estimator_nums, n_scores)
當 estimators=20 的時候,score最高,大概有0.544,雖然跟單個決策樹的 score 的值相差不大,但整體仍是有所提高。
參數選擇完畢,就能夠創建模型了。
dtc = DecisionTreeClassifier(max_features=0.2) abc = AdaBoostClassifier(n_estimators=20)
# 訓練
abc.fit(X_train, y_train)
dtc.fit(X_train, y_train)
# 預測
y_dtc = dtc.predict(X_test)
y_abc = abc.predict(X_test)
test_data['薪資(單個決策樹)'] = y_dtc
test_data['薪資(boosting)'] = y_abc
至於結果,總不可能預測得很完美,並且不一樣模型的結果也會有所不一樣,更況且它預測出來的結果是否符合常理還有待商榷,因此就把它看成一個小項目就行了,具體代碼在這裏:https://github.com/MaxLyu/Lagou_Analyze