疯狂的机器学习实战-银行营销预测
機器學習實戰-銀行營銷預測
問題:
數據集:
鏈接:https://pan.baidu.com/s/1TUOLr8jFbT38p_iUh1iBsQ
提取碼:1234
策略:使用四個模型先粗測當前預測準確度,對其中準確度較高的進一步調優
算法簡單介紹:
1.KNN算法
通過以某個數據為中心:
? 分析離其最近的K個鄰居的類別;
? 獲得該數據可能的類別
? 如果取K=1
? 待分類樣本的類別就是最近鄰居的類
2.SVM算法
SVM(Support Vector Machine)中文名為支持向量機,是常見的一種判別方法。在機器學習領域,是一個有監督的學習模型,通常用來進行模式識別、分類以及回歸分析。
二維上,就是找一分割線W?X+b =0把兩類分開,區分兩個類別并且能使間隔(margin)最大
3.AdaBoost算法
該算法其實是一個簡單的弱分類算法提升過程,這個過程通過不斷的訓練,可以提高對數據的分類能力。1. 先通過對N個訓練樣本的學習得到第一個弱分類器;
2. 將分錯的樣本和其他的新數據一起構成一個新的N個的訓練樣本,通過對這個樣本的學習得到第二個弱分類器 ;
3. 將1和2都分錯了的樣本加上其他的新樣本構成另一個新的N個的訓練樣本,通過對這個樣本的學習得到第三個弱分類器;
4. 最后,將各個訓練得到的弱分類器組合成強分類器。誤差率低的弱分類器在最終分類器中占的比例較大,反之較小。
4.隨機森林算法
隨機森林顧名思義,是用隨機的方式建立一個森林,森林里面有很多的決策樹組成,隨機森林的每一棵決策樹之間是沒有關聯的。在得到森林之后,當有一個新的輸入樣本進入的時候,就讓森林中的每一棵決策樹分別進行一下判斷,看看這個樣本應該屬于哪一類(對于分類算法),然后看看哪一類被選擇最多,就預測這個樣本為那一類。
完整代碼見最后:
1.導入數據
#訓練集和測試集的導入 trainfile = pd.read_csv(r'.\bank-additional-full.csv', sep=';') testfile = pd.read_csv(r'.\bank-additional.csv', sep=';')2.數據處理:
下面驗證對于該數據集缺失較多的列刪除后的可行性:
刪除前的4個算法準確率:
刪除后的4個算法準確率:
(決策樹應該改為隨機森林)
下面驗證對該數據集缺失數據替換或者刪除的可行性探究:
#刪除unknown大于30%的列 for col in csvfile.columns:if type(csvfile[col][0]) is str:if 'unknown' in csvfile[col].tolist():col_mode=csvfile[col].mode()[0]csvfile[col].replace('unkonwn',col_mode,inplace=True)替換前:
替換后:
刪除前:
刪除后:
這里我們采取的最高準確性比較所以選擇的刪除行
**
3.特征分析
**
1. 分析特征:
通過分析個特征的數據選取其中差異化較大的特征作為最后我們用于模型訓練的特征使用
部分情況如下:
比如這里的contact分布情況就相差很大所以我們這里就要選擇其作為之后模型訓練的一個特征值使用
比如這里的day_of_week其對結果數據的差異化就不明顯所以不需要選擇其作為最后模型訓練的特征值
2. 特征工程:
1.對以上選擇的特征值進行數值化編碼(方便處理數據)
2.離散化處理,處理數據中的極大極小值
3.對選取特征標準化或者歸一化處理(作用:使得數據具有同等重要的作用,特別是在按距離分類的算法如K近鄰算法d=sqrt((a-b)^2…)如果不做歸一化或者標準化處理,如果此時a值較大,b值較小則最后可能對結果有同等重要性的數據只有一個被用上了,因為在距離函數中a大則其對結果數據起主導作用,b對結果的影響非常的小,甚至可以忽略。這種情況下,分類的特征就變少了,使得預測結果不準確。(我們要的應該是對于那些對結果數據差異化明顯的數據盡可能的加入,這樣的預測準確率才高)
4.樣本均衡
具體過程如下:
1.二分變量數值化:
2.將其它分類變量(包括有序和無序)數值化
3.數據離散化:
把無限空間中有限的個體映射到有限的空間中去,以此提高算法的時空效率。
通俗的說,離散化是在不改變數據相對大小的條件下,對數據進行相應的縮小。
4.數據標準化:
標準化數據通過減去均值然后除以方差(或標準差),這種數據標準化方法經過處理后數據符合標準正態分布,即均值為0,標準差為1,轉化函數為:x =(x - 均值)/方差
預處理結果:
4.4個模型的簡單測試
綜上結果可知:在默認值參數下KNN算法是最優的,正確率是最高的。
5.選擇當前最優模型并對其調優
距離參數通過手動調整發現曼哈頓距離最好,對于K值的選擇我們使用for循環進行的查找(本來想使用二分,但是考慮到其不是順序的所以就直接使用的線性查找)
另外其實這里取K=1時是最大的準確率在98%,但這其實是因為:
K值較小就意味著整體模型變得復雜,容易發生過擬合
K值較大就意味著整體模型變得簡單,容易發生欠擬合
最終結果:
最后我們取的K值為3
6.對未來的展望:
優點:
1、通過多種分類模型對比,使我們對題目了解跟全面,結構更清晰,準確度更高
2、精度高、對異常值不敏感、無數據輸入假定。
缺點:
1、對部分屬性進行了直接刪除,忽略了數據相關性對結果的影響;
2、對部分非有序變量采用直接轉變為數字的做法,使變量值之間的權重不相同;
展望:
1、更細致的特征選擇,如派生屬性;
2、采用更好的方法解決數據不平衡問題,如:代價敏感學習方法;
3、更細致的調參;
4、長視其他分類模型,如:神經網絡等
5、因為前面是選擇的當前最優算法,所以可能存在其他三個算法調優之后其準確度更高的情況。之后可以繼續嘗試其他算法調參后的準確度
完整代碼:
import pandas as pd#訓練集和測試集的導入 trainfile = pd.read_csv(r'.\bank-additional-full.csv', sep=';') testfile = pd.read_csv(r'.\bank-additional.csv', sep=';')# 數據預處理 def Pretreatment(csvfile):# 刪除'poutcome'列-nonexistent占比超過80%csvfile.drop(['poutcome'], axis=1, inplace=True)# 刪除unknown大于30%的列for col in csvfile.columns:if (type(csvfile[col][0])) is str:#只有str類型才有‘unknown’項num = csvfile[csvfile[col] == 'unknown'][col].count()if (num / len(csvfile) > 0.3):csvfile.drop(col, axis=1, inplace=True)# 刪除含有'unknown'的行for index, row in csvfile.iterrows():if ('unknown' in row.values):csvfile.drop([index], inplace=True)# 替換unknown為每列的眾數# for col in csvfile.columns.tolist():# if (type(csvfile[col][0])) is str:# if ('unknown' in csvfile[col].tolist()):# col_mode = csvfile[col].mode()[0]# csvfile[col].replace('unknown', col_mode, inplace=True)# 分類變量數值化csvfile.replace(['yes', 'no'], [1, 0], True) # 替換yes,no為1,0;csvfile['nr.employed'].replace([5191.0, 5228.1], [0, 1], True) # 替換nr.employed列元素為0,1;educationlist = ["illiterate", "basic.4y", "basic.6y", "basic.9y", "high.school", "professional.course","university.degree"]educationvalue = [i for i in range(0, len(educationlist))]joblist = ["admin.", "blue-collar", "entrepreneur", "housemaid", "management", "retired", "self-employed","services", "student", "technician", "unemployed"]jobvalue = [i for i in range(0, len(joblist))]maritallist = ["divorced", "married", "single"]maritalvalue = [i for i in range(0, len(maritallist))]contactlist = ["cellular", "telephone"]contactvalue = [0, 1]monthlist = ['month_apr', 'month_aug', 'month_dec', 'month_jul', 'month_jun', 'month_mar', 'month_may', 'month_nov','month_oct', 'month_sep']monthvalue = [i for i in range(0, len(monthlist))]day_of_weeklist = ['day_of_week_fri', 'day_of_week_mon', 'day_of_week_thu', 'day_of_week_tue', 'day_of_week_wed']day_of_weekvalue = [i for i in range(0, len(day_of_weeklist))]csvfile['day_of_week'].replace(day_of_weeklist, day_of_weekvalue, True)csvfile['month'].replace(monthlist, monthvalue, True)csvfile['contact'].replace(contactlist, contactvalue, True)csvfile['job'].replace(joblist, jobvalue, True)csvfile['marital'].replace(maritallist, maritalvalue, True)csvfile['education'].replace(educationlist, educationvalue, True)# # 離散化處理數據# csvfile['age']=pd.qcut(csvfile['age'],10)# csvfile['age']=pd.factorize(csvfile['age'])[0]# csvfile['duration']=pd.qcut(csvfile['duration'],10)# csvfile['duration']=pd.factorize(csvfile['duration'])[0]# csvfile['campaign']=pd.qcut(csvfile['campaign'],5,duplicates='drop')# csvfile['campaign']=pd.factorize(csvfile['campaign'])[0]# csvfile['pdays'] = pd.qcut(csvfile['pdays'], 10, duplicates='drop')# csvfile['pdays'] = pd.factorize(csvfile['pdays'])[0]return csvfiledata = Pretreatment(trainfile) data_test = Pretreatment(testfile) #特征對結果影響分析 # import matplotlib.pyplot as plt # import seaborn as sns # plt.rcParams['font.sans-serif'] = 'SimHei' # plt.figure(figsize=(20, 8), dpi=256) # sns.countplot(x='age', data=data) # plt.title("各年齡段的人數") # plt.savefig('./1.png') # # plt.figure(figsize=(18, 16), dpi=512) # plt.subplot(221) # sns.countplot(x='contact', data=data) # plt.title("contact分布情況") # # plt.subplot(222) # sns.countplot(x='day_of_week', data=data) # plt.title("day_of_week分布情況") # # # plt.subplot(223)#前面刪列時將其刪除了所以就不需要再分析它了 # # sns.countplot(x='default', data=data) # # plt.title("default分布情況") # # plt.subplot(224) # sns.countplot(x='education', data=data) # plt.xticks(rotation=70) # plt.title("education分布情況") # # plt.savefig('./2.png') # # plt.figure(figsize=(18, 16), dpi=512) # plt.subplot(221) # sns.countplot(x='housing', data=data) # plt.title("housing分布情況") # # plt.subplot(222) # sns.countplot(x='job', data=data) # plt.xticks(rotation=70) # plt.title("job分布情況") # # plt.subplot(223) # sns.countplot(x='loan', data=data) # plt.title("loan分布情況") # # plt.subplot(224) # sns.countplot(x='marital', data=data) # plt.xticks(rotation=70) # plt.title("marital分布情況") # # plt.savefig('./3.png') # # plt.figure(figsize=(18, 8), dpi=512) # plt.subplot(221) # sns.countplot(x='month', data=data) # plt.xticks(rotation=30) # # plt.subplot(222) # sns.countplot(x='poutcome', data=data) # plt.xticks(rotation=30) # plt.savefig('./4.png') # # plt.figure(figsize=(10, 8), dpi=256) # plt.rcParams['axes.unicode_minus'] = False # sns.heatmap(data.corr(), annot=True) # plt.title("各特征的相關性") # plt.savefig('./5.png') # plt.show()#圖像顯示 from sklearn.preprocessing import LabelEncoderfeatures = ['age','job', 'marital', 'education', 'housing', 'loan', 'contact', 'month', 'duration','campaign', 'pdays', 'previous', 'emp.var.rate', 'cons.price.idx', 'cons.conf.idx', 'euribor3m', 'nr.employed']le_x = LabelEncoder() for feature in features:data[feature] = le_x.fit_transform(data[feature])data_test[feature] = le_x.fit_transform(data_test[feature])col = data.columns.values.tolist()# 數據規范化到正態分布的數據 from sklearn.preprocessing import StandardScaler import numpy as npss = StandardScaler() train_x=np.array(data[col[0:-2]]) train_y=data['y']test_x=np.array(data_test[col[0:-2]]) test_y=data_test['y']train_x = ss.fit_transform(train_x) test_x = ss.transform(test_x)from sklearn.ensemble import AdaBoostClassifier from sklearn.metrics import accuracy_score ada = AdaBoostClassifier() ada.fit(train_x, train_y) predict_y = ada.predict(test_x) print("Adaoost準確率:", accuracy_score(test_y, predict_y))#引入支持向量機算法 from sklearn.svm import SVC svc = SVC() svc.fit(train_x, train_y) predict_y = svc.predict(test_x) print("svm準確率:", accuracy_score(test_y, predict_y)) # ans.append(accuracy_score(test_y, predict_y)) # #引入Knn算法 from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score knn = KNeighborsClassifier() knn.fit(train_x, train_y) predict_y = knn.predict(test_x) print("KNN準確率:", accuracy_score(test_y, predict_y)) from sklearn.tree import DecisionTreeClassifier dtc = DecisionTreeClassifier() dtc.fit(train_x, train_y) predict_y = dtc.predict(test_x) print("隨機森林準確率:", accuracy_score(test_y, predict_y))print("由此得KNN算法為當前4個算法的最優算法,所以我們對KNN算法進行進一步的調參,過程如下:")max=0 max_index=1 for i in range(2,30,1):# print(i)knn = KNeighborsClassifier(p=1,n_neighbors=i)#選擇的曼哈頓距離knn.fit(train_x, train_y)predict_y = knn.predict(test_x)KNN2=accuracy_score(test_y, predict_y)if KNN2>max:max=KNN2max_index=iprint("KNN準確率:", accuracy_score(test_y, predict_y)) print("最優k值為:") print(max_index) print("最優準確率:") print(max)瘋狂之處在于這個只用了兩天來做 (ó﹏ò。)
總結
以上是生活随笔為你收集整理的疯狂的机器学习实战-银行营销预测的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库-DQL练习(附答案)
- 下一篇: 自创迷宫