模型的假設檢驗(F與T):
F檢驗(主要檢驗模型是否合理)
'''
F檢驗:提出原假設和備擇假設 之后計算統計量與理論值 最后比較
F檢驗主要檢驗的是模型是否合理
'''
# 置信度95%時 F值(單邊)
1 """模型F的檢驗""" 2 # 計算統計量 3 4 # 導⼊第三⽅模塊 5 import numpy as np 6 # 計算建模數據中因變量的均值 7 ybar=train.Profit.mean() 8 # 統計變量個數和觀測個數 9 p=model2.df_model 10 n=train.shape[0] 11 # 計算回歸離差平⽅和 12 RSS=np.sum((model2.fittedvalues-ybar)**2) 13 # 計算誤差平⽅和 14 ESS=np.sum(model2.resid**2) 15 # 計算F統計量的值 16 F=(RSS/p)/(ESS/(n-p-1)) 17 print('F統計量的值:',F) 18 F統計量的值:174.6372 19 20 # 對比所得結論 21 22 # 導⼊模塊 23 from scipy.stats import f 24 # 計算F分布的理論值 25 F_Theroy = f.ppf(q=0.95, dfn = p,dfd = n-p-1) 26 print('F分布的理論值為:',F_Theroy) 27 out: 28 F分布的理論值為: 2.5026 29 30 """ 31 計算出來的F統計量值174.64遠遠⼤於F分布的理論值2.50 32 所以應當拒絕原假設(先假設模型不合理) 33 原假設就是先假設模型不合理 34 """
T檢驗(看參數是否合理)
"""T檢驗更加側重於檢驗模型的各個參數是否合理""" model.summary() # 絕對值越小影響越大
# 主要看這個研發成本
線性回歸模型的短板:
###########################################################
1.自變量的個數大於樣本數量 比如一家店的購物人數只有3個 但是影響人是否購物的因素有很多大於3
2.自變量之間存在多重共線性 簡單來說就是自變量之間不能有明顯的關系 比如昨天配置啞變量中三個州數據
###########################################################
如何去解決這個短板呢?解決方法如下:
# 嶺回歸模型 在線性回歸模型的基礎之上添加一個l2懲罰項(平方項、正則項) '''該模型最終轉變成求解圓柱體與橢圓拋物線的焦點問題'''
# 如下圖
# 交叉驗證 將所有數據都參與到模型的構建和測試中 最后生成多個模型 再從多個模型中篩選出得分最高(准確度)的模型
# 糖尿病小案例
1 # 導入第三方模塊 2 import pandas as pd 3 import numpy as np 4 from sklearn import model_selection 5 from sklearn.linear_model import Ridge,RidgeCV 6 import matplotlib.pyplot as plt 7 8 # 讀取糖尿病數據集 9 diabetes = pd.read_excel(r'diabetes.xlsx') 10 diabetes.head() 11 # 構造自變量(剔除患者性別、年齡和因變量) 12 predictors = diabetes.columns[2:-1] 13 # 將數據集拆分為訓練集和測試集 14 '''在之后稍微有點技術含量的模型都是要拆分4項的''' 15 X_train, X_test, y_train, y_test = model_selection.train_test_split(diabetes[predictors], diabetes['Y'], 16 test_size = 0.2, random_state = 1234 )
1 # 構造不同的Lambda值 后面的np.logspace就是個函數 2 Lambdas = np.logspace(-5, 2, 200) # 這里是個匿名函數 用來生成均勻的自定義點數 3 # 嶺回歸模型的交叉驗證 4 # 設置交叉驗證的參數,對於每一個Lambda值,都執行10重交叉驗證 5 ridge_cv = RidgeCV(alphas = Lambdas, normalize=True, scoring='neg_mean_squared_error', cv = 10) 6 # 模型擬合 7 ridge_cv.fit(X_train, y_train) 8 # 返回最佳的lambda值 9 ridge_best_Lambda = ridge_cv.alpha_ 10 ridge_best_Lambda # 最后得出Lanbda的值最佳是多少
1 # 導入第三方包中的函數 2 from sklearn.metrics import mean_squared_error 3 # 基於最佳的Lambda值建模 4 ridge = Ridge(alpha = ridge_best_Lambda, normalize=True) 5 ridge.fit(X_train, y_train) 6 # 返回嶺回歸系數 7 pd.Series(index = ['Intercept'] + X_train.columns.tolist(),data = [ridge.intercept_] + ridge.coef_.tolist()) 8 # 預測 9 ridge_predict = ridge.predict(X_test) 10 # 預測效果驗證 11 RMSE = np.sqrt(mean_squared_error(y_test,ridge_predict)) 12 RMSE # 所得到的值 越小越好
# Lasso回歸模型 在線性回歸模型的基礎之上添加一個l1懲罰項(絕對值項、正則項) 相較於嶺回歸降低了模型的復雜度 '''該模型最終轉變成求解正方體與橢圓拋物線的焦點問題'''
# 交叉驗證與上 方法非常接近
Logistic回歸模型:
將線性回歸的模型做Logit變換 既為Logistic模型
將預測問題變成了一個0到1之間的預測值
# 以性別和腫瘤作為患癌的參數案例
混淆矩陣:
混淆矩陣的關鍵就在下圖中的表格和最下面的文字概率
表格部分簡單理解就變成了右側的表
模型的評估方法:
# ROC曲線
通過計算AUC陰影部分的面積來判斷模型是否合理(通常大於0.8表示OK)
# KS曲線
通過計算兩條折現之間最大距離來衡量模型是否合理(通常大於0.4表示OK)
1 # 導入第三方模塊 2 import pandas as pd 3 import numpy as np 4 import matplotlib.pyplot as plt 5 6 # 自定義繪制ks曲線的函數 7 def plot_ks(y_test, y_score, positive_flag): 8 # 對y_test重新設置索引 9 y_test.index = np.arange(len(y_test)) 10 # 構建目標數據集 11 target_data = pd.DataFrame({'y_test':y_test, 'y_score':y_score}) 12 # 按y_score降序排列 13 target_data.sort_values(by = 'y_score', ascending = False, inplace = True) 14 # 自定義分位點 15 cuts = np.arange(0.1,1,0.1) 16 # 計算各分位點對應的Score值 17 index = len(target_data.y_score)*cuts 18 scores = np.array(target_data.y_score)[index.astype('int')] 19 # 根據不同的Score值,計算Sensitivity和Specificity 20 Sensitivity = [] 21 Specificity = [] 22 for score in scores: 23 # 正例覆蓋樣本數量與實際正例樣本量 24 positive_recall = target_data.loc[(target_data.y_test == positive_flag) & (target_data.y_score>score),:].shape[0] 25 positive = sum(target_data.y_test == positive_flag) 26 # 負例覆蓋樣本數量與實際負例樣本量 27 negative_recall = target_data.loc[(target_data.y_test != positive_flag) & (target_data.y_score<=score),:].shape[0] 28 negative = sum(target_data.y_test != positive_flag) 29 Sensitivity.append(positive_recall/positive) 30 Specificity.append(negative_recall/negative) 31 # 構建繪圖數據 32 plot_data = pd.DataFrame({'cuts':cuts,'y1':1-np.array(Specificity),'y2':np.array(Sensitivity), 33 'ks':np.array(Sensitivity)-(1-np.array(Specificity))}) 34 # 尋找Sensitivity和1-Specificity之差的最大值索引 35 max_ks_index = np.argmax(plot_data.ks) 36 plt.plot([0]+cuts.tolist()+[1], [0]+plot_data.y1.tolist()+[1], label = '1-Specificity') 37 plt.plot([0]+cuts.tolist()+[1], [0]+plot_data.y2.tolist()+[1], label = 'Sensitivity') 38 # 添加參考線 39 plt.vlines(plot_data.cuts[max_ks_index], ymin = plot_data.y1[max_ks_index], 40 ymax = plot_data.y2[max_ks_index], linestyles = '--') 41 # 添加文本信息 42 plt.text(x = plot_data.cuts[max_ks_index]+0.01, 43 y = plot_data.y1[max_ks_index]+plot_data.ks[max_ks_index]/2, 44 s = 'KS= %.2f' %plot_data.ks[max_ks_index]) 45 # 顯示圖例 46 plt.legend() 47 # 顯示圖形 48 plt.show()
1 # 導入虛擬數據 2 virtual_data = pd.read_excel(r'virtual_data.xlsx') 3 # 應用自定義函數繪制k-s曲線 4 plot_ks(y_test = virtual_data.Class, y_score = virtual_data.Score,positive_flag = 'P')
1 # 導入第三方模塊 2 import pandas as pd 3 import numpy as np 4 from sklearn import model_selection 5 from sklearn import linear_model 6 7 # 讀取數據 8 sports = pd.read_csv(r'Run or Walk.csv') 9 # 提取出所有自變量名稱 10 predictors = sports.columns[4:] 11 # 構建自變量矩陣 12 X = sports.loc[:,predictors] 13 # 提取y變量值 14 y = sports.activity 15 # 將數據集拆分為訓練集和測試集 16 X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size = 0.25, random_state = 1234) 17 18 # 利用訓練集建模 19 sklearn_logistic = linear_model.LogisticRegression() 20 sklearn_logistic.fit(X_train, y_train) 21 # 返回模型的各個參數 22 print(sklearn_logistic.intercept_, sklearn_logistic.coef_) 23 # 輸出結果如下
1 # 模型預測 2 sklearn_predict = sklearn_logistic.predict(X_test) 3 # 預測結果統計 4 pd.Series(sklearn_predict).value_counts()
1 # 導入第三方模塊 2 from sklearn import metrics 3 # 混淆矩陣 4 cm = metrics.confusion_matrix(y_test, sklearn_predict, labels = [0,1]) 5 cm
1 Accuracy = metrics.scorer.accuracy_score(y_test, sklearn_predict) 2 Sensitivity = metrics.scorer.recall_score(y_test, sklearn_predict) 3 Specificity = metrics.scorer.recall_score(y_test, sklearn_predict, pos_label=0) 4 print('模型准確率為%.2f%%:' %(Accuracy*100)) 5 print('正例覆蓋率為%.2f%%' %(Sensitivity*100)) 6 print('負例覆蓋率為%.2f%%' %(Specificity*100))
1 # 混淆矩陣的可視化 2 # 導入第三方模塊 3 import seaborn as sns 4 import matplotlib.pyplot as plt 5 %matplotlib 6 # 繪制熱力圖 7 sns.heatmap(cm, annot = True, fmt = '.2e',cmap = 'GnBu') 8 # 圖形顯示 9 plt.show()
sklearn_logistic.predict_proba(X_test)
1 # y得分為模型預測正例的概率 2 y_score = sklearn_logistic.predict_proba(X_test)[:,1] 3 # 計算不同閾值下,fpr和tpr的組合值,其中fpr表示1-Specificity,tpr表示Sensitivity 4 fpr,tpr,threshold = metrics.roc_curve(y_test, y_score) 5 # 計算AUC的值 6 roc_auc = metrics.auc(fpr,tpr) 7 8 # 繪制面積圖 9 plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black') 10 # 添加邊際線 11 plt.plot(fpr, tpr, color='black', lw = 1) 12 # 添加對角線 13 plt.plot([0,1],[0,1], color = 'red', linestyle = '--') 14 # 添加文本信息 15 plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc) 16 # 添加x軸與y軸標簽 17 plt.xlabel('1-Specificity') 18 plt.ylabel('Sensitivity') 19 # 顯示圖形 20 plt.show()
# 調用自定義函數,繪制K-S曲線 plot_ks(y_test = y_test, y_score = y_score, positive_flag = 1)
# -----------------------第一步 建模 ----------------------- # # 導入第三方模塊 import statsmodels.api as sm # 將數據集拆分為訓練集和測試集 X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size = 0.25, random_state = 1234) # 為訓練集和測試集的X矩陣添加常數列1 X_train2 = sm.add_constant(X_train) X_test2 = sm.add_constant(X_test) # 擬合Logistic模型 sm_logistic = sm.Logit(y_train, X_train2).fit() # 返回模型的參數 sm_logistic.params # -----------------------第二步 預測構建混淆矩陣 ----------------------- # # 模型在測試集上的預測 sm_y_probability = sm_logistic.predict(X_test2) # 根據概率值,將觀測進行分類,以0.5作為閾值 sm_pred_y = np.where(sm_y_probability >= 0.5, 1, 0) # 混淆矩陣 cm = metrics.confusion_matrix(y_test, sm_pred_y, labels = [0,1]) cm # -----------------------第三步 繪制ROC曲線 ----------------------- # # 計算真正率和假正率 fpr,tpr,threshold = metrics.roc_curve(y_test, sm_y_probability) # 計算auc的值 roc_auc = metrics.auc(fpr,tpr) # 繪制面積圖 plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black') # 添加邊際線 plt.plot(fpr, tpr, color='black', lw = 1) # 添加對角線 plt.plot([0,1],[0,1], color = 'red', linestyle = '--') # 添加文本信息 plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc) # 添加x軸與y軸標簽 plt.xlabel('1-Specificity') plt.ylabel('Sensitivity') # 顯示圖形 plt.show() # -----------------------第四步 繪制K-S曲線 ----------------------- # # 調用自定義函數,繪制K-S曲線 sm_y_probability.index = np.arange(len(sm_y_probability)) plot_ks(y_test = y_test, y_score = sm_y_probability, positive_flag = 1) '''代碼的整體思路就是這樣做下來'''
決策樹:
"""
決策樹與隨機森林
默認情況下解決分類問題(買與不買、帶與不帶、走與不走)
也可以切換算法解決預測問題(具體數值多少)
"""
樹其實是一種計算機底層的數據結構 與現實不同
計算機里面的樹都是自上而下的生長
決策樹則是算法模型中的一種概念 有三個主要部分
根節點 起始的最基本的判斷要素 所有分支的基礎
枝節點 根節點和枝節點存儲的都是條件判斷(中間節點)
葉子節點 就是沒法再繼續分支了
# 根節點與枝節點用於存放條件 葉子節點存放真正的數據結果
# 信息熵 eg : 信息熵小相當於紅路燈 只有三個數據非常有序 ''' 信息熵既可以用來解決分類問題(買與不買、帶與不帶、走與不走) 也可以用來解決預測問題 '''
條件熵
其實就是由信息熵再次細分而來
比如有九個用戶購買了商品五個沒有購買 那么條件熵就是繼續從購買不購買的用戶中再選擇一個條件(比如按照性別計算男和女的熵)
信息增益 信息增益可以反映出某個條件是否對最終的分類有決定性的影響 在構建決策樹時根節點與枝節點所放的條件按照信息增益由大到小排 ''' 也就是某個條件對於結果影響的大小 影響越大的條件在構建決策樹的時候越要靠根節點放 '''
信息增益率
決策樹中的ID3算法使⽤信息增益指標實現根節點或中間節點的字段選擇,但是該指標存在⼀個⾮常明顯的缺點,即信息增益會偏向於取值較多的字段。
為了克服信息增益指標的缺點,提出了信息增益率的概念,它的思想很簡單,就是在信息增益的基礎上進⾏相應的懲罰。
簡言之:信息增益會偏向於取值較多的指標
為平衡這一現象給他加入了懲罰項
即取值越多公式中會除以一個越大的數
# 基尼指數 可以讓模型解決預測問題(通過公式將模型數學化 從而解決連續性變量)
# 基尼指數增益 與信息增益類似,還需要考慮⾃變量對因變量的影響程度 因變量的基尼指數下降速度的快慢,下降得越快,⾃變量對因變量的影響就越強
隨機森林:
隨機森林中每顆決策樹都不限制節點字段選擇 #盡可能細分 有多棵樹組成的隨機森林 在解決分類問題的時候采用投票法 # 選擇樹 解決預測問題的時候采用均值法 # 回歸模型
1 # 導入第三方模塊 2 import pandas as pd 3 import numpy as np 4 import matplotlib.pyplot as plt 5 from sklearn import model_selection 6 from sklearn import linear_model 7 # 讀⼊數據 8 Titanic = pd.read_csv(r'Titanic.csv') 9 Titanic 10 # 刪除⽆意義的變量,並檢查剩余變量是否含有缺失值 11 Titanic.drop(['PassengerId','Name','Ticket','Cabin'], axis = 1, inplace = True) 12 Titanic.isnull().sum(axis = 0) 13 # 對Sex分組,⽤各組乘客的平均年齡填充各組中的缺失年齡 14 fillna_Titanic = [] 15 for i in Titanic.Sex.unique(): 16 update = Titanic.loc[Titanic.Sex == i,].fillna(value = {'Age': Titanic.Age[Titanic.Sex == i].mean()}, inplace 17 = False) 18 fillna_Titanic.append(update) 19 Titanic = pd.concat(fillna_Titanic) 20 # 使⽤Embarked變量的眾數填充缺失值 21 Titanic.fillna(value = {'Embarked':Titanic.Embarked.mode()[0]}, inplace=True)
1 # 將數值型的Pclass轉換為類別型,否則⽆法對其啞變量處理 2 Titanic.Pclass = Titanic.Pclass.astype('category') 3 # 啞變量處理 4 dummy = pd.get_dummies(Titanic[['Sex','Embarked','Pclass']]) 5 # ⽔平合並Titanic數據集和啞變量的數據集 6 Titanic = pd.concat([Titanic,dummy], axis = 1) 7 # 刪除原始的Sex、Embarked和Pclass變量 8 Titanic.drop(['Sex','Embarked','Pclass'], inplace=True, axis = 1) 9 # 取出所有⾃變量名稱 10 predictors = Titanic.columns[1:] 11 # 將數據集拆分為訓練集和測試集,且測試集的⽐例為25% 12 X_train, X_test, y_train, y_test = model_selection.train_test_split(Titanic[predictors], Titanic.Survived, 13 test_size = 0.25, random_state = 1234) 14 15 from sklearn.model_selection import GridSearchCV 16 from sklearn import tree,metrics 17 # 預設各參數的不同選項值 18 max_depth = [2,3,4,5,6] 19 min_samples_split = [2,4,6,8] 20 min_samples_leaf = [2,4,8,10,12] 21 # 將各參數值以字典形式組織起來 22 parameters = {'max_depth':max_depth, 'min_samples_split':min_samples_split, 23 'min_samples_leaf':min_samples_leaf} 24 # ⽹格搜索法,測試不同的參數值 25 grid_dtcateg = GridSearchCV(estimator = tree.DecisionTreeClassifier(), param_grid = parameters, cv=10) 26 # 模型擬合 27 grid_dtcateg.fit(X_train, y_train) 28 # 返回最佳組合的參數值 29 grid_dtcateg.param_grid 30 # 輸出結果如下圖
1 # 構建分類決策樹 2 CART_Class = tree.DecisionTreeClassifier(max_depth=3,min_samples_leaf=4,min_samples_split=2) 3 # 模型擬合 4 decision_tree = CART_Class.fit(X_train,y_train) 5 # 模型在測試集上的預測 6 pred = CART_Class.predict(X_test) 7 # 模型的准確率 8 print('模型在測試集的預測准確率:\n',metrics.accuracy_score(y_test,pred)) 9 print('模型在訓練集的預測准確率:\n', 10 metrics.accuracy_score(y_train,CART_Class.predict(X_train)))
K近鄰模型:
思想:根據位置樣本點周邊K個鄰居樣本完成預測或者分類 # K值的選擇 1.先猜測 2.交叉驗證 3.作圖選擇最合理的k值 准確率(越大越好) MSE(越小越好)
# 過擬合與欠擬合 # 就是精確度一個太高(過擬合 )一個太低 (欠擬合) # 太高模型的泛用性就會很差