疯狂的机器学习实战-银行营销预测
機(jī)器學(xué)習(xí)實戰(zhàn)-銀行營銷預(yù)測
問題:
數(shù)據(jù)集:
鏈接:https://pan.baidu.com/s/1TUOLr8jFbT38p_iUh1iBsQ
提取碼:1234
策略:使用四個模型先粗測當(dāng)前預(yù)測準(zhǔn)確度,對其中準(zhǔn)確度較高的進(jìn)一步調(diào)優(yōu)
算法簡單介紹:
1.KNN算法
通過以某個數(shù)據(jù)為中心:
? 分析離其最近的K個鄰居的類別;
? 獲得該數(shù)據(jù)可能的類別
? 如果取K=1
? 待分類樣本的類別就是最近鄰居的類
2.SVM算法
SVM(Support Vector Machine)中文名為支持向量機(jī),是常見的一種判別方法。在機(jī)器學(xué)習(xí)領(lǐng)域,是一個有監(jiān)督的學(xué)習(xí)模型,通常用來進(jìn)行模式識別、分類以及回歸分析。
二維上,就是找一分割線W?X+b =0把兩類分開,區(qū)分兩個類別并且能使間隔(margin)最大
3.AdaBoost算法
該算法其實是一個簡單的弱分類算法提升過程,這個過程通過不斷的訓(xùn)練,可以提高對數(shù)據(jù)的分類能力。1. 先通過對N個訓(xùn)練樣本的學(xué)習(xí)得到第一個弱分類器;
2. 將分錯的樣本和其他的新數(shù)據(jù)一起構(gòu)成一個新的N個的訓(xùn)練樣本,通過對這個樣本的學(xué)習(xí)得到第二個弱分類器 ;
3. 將1和2都分錯了的樣本加上其他的新樣本構(gòu)成另一個新的N個的訓(xùn)練樣本,通過對這個樣本的學(xué)習(xí)得到第三個弱分類器;
4. 最后,將各個訓(xùn)練得到的弱分類器組合成強(qiáng)分類器。誤差率低的弱分類器在最終分類器中占的比例較大,反之較小。
4.隨機(jī)森林算法
隨機(jī)森林顧名思義,是用隨機(jī)的方式建立一個森林,森林里面有很多的決策樹組成,隨機(jī)森林的每一棵決策樹之間是沒有關(guān)聯(lián)的。在得到森林之后,當(dāng)有一個新的輸入樣本進(jìn)入的時候,就讓森林中的每一棵決策樹分別進(jìn)行一下判斷,看看這個樣本應(yīng)該屬于哪一類(對于分類算法),然后看看哪一類被選擇最多,就預(yù)測這個樣本為那一類。
完整代碼見最后:
1.導(dǎo)入數(shù)據(jù)
#訓(xùn)練集和測試集的導(dǎo)入 trainfile = pd.read_csv(r'.\bank-additional-full.csv', sep=';') testfile = pd.read_csv(r'.\bank-additional.csv', sep=';')2.數(shù)據(jù)處理:
下面驗證對于該數(shù)據(jù)集缺失較多的列刪除后的可行性:
刪除前的4個算法準(zhǔn)確率:
刪除后的4個算法準(zhǔn)確率:
(決策樹應(yīng)該改為隨機(jī)森林)
下面驗證對該數(shù)據(jù)集缺失數(shù)據(jù)替換或者刪除的可行性探究:
#刪除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)替換前:
替換后:
刪除前:
刪除后:
這里我們采取的最高準(zhǔn)確性比較所以選擇的刪除行
**
3.特征分析
**
1. 分析特征:
通過分析個特征的數(shù)據(jù)選取其中差異化較大的特征作為最后我們用于模型訓(xùn)練的特征使用
部分情況如下:
比如這里的contact分布情況就相差很大所以我們這里就要選擇其作為之后模型訓(xùn)練的一個特征值使用
比如這里的day_of_week其對結(jié)果數(shù)據(jù)的差異化就不明顯所以不需要選擇其作為最后模型訓(xùn)練的特征值
2. 特征工程:
1.對以上選擇的特征值進(jìn)行數(shù)值化編碼(方便處理數(shù)據(jù))
2.離散化處理,處理數(shù)據(jù)中的極大極小值
3.對選取特征標(biāo)準(zhǔn)化或者歸一化處理(作用:使得數(shù)據(jù)具有同等重要的作用,特別是在按距離分類的算法如K近鄰算法d=sqrt((a-b)^2…)如果不做歸一化或者標(biāo)準(zhǔn)化處理,如果此時a值較大,b值較小則最后可能對結(jié)果有同等重要性的數(shù)據(jù)只有一個被用上了,因為在距離函數(shù)中a大則其對結(jié)果數(shù)據(jù)起主導(dǎo)作用,b對結(jié)果的影響非常的小,甚至可以忽略。這種情況下,分類的特征就變少了,使得預(yù)測結(jié)果不準(zhǔn)確。(我們要的應(yīng)該是對于那些對結(jié)果數(shù)據(jù)差異化明顯的數(shù)據(jù)盡可能的加入,這樣的預(yù)測準(zhǔn)確率才高)
4.樣本均衡
具體過程如下:
1.二分變量數(shù)值化:
2.將其它分類變量(包括有序和無序)數(shù)值化
3.數(shù)據(jù)離散化:
把無限空間中有限的個體映射到有限的空間中去,以此提高算法的時空效率。
通俗的說,離散化是在不改變數(shù)據(jù)相對大小的條件下,對數(shù)據(jù)進(jìn)行相應(yīng)的縮小。
4.數(shù)據(jù)標(biāo)準(zhǔn)化:
標(biāo)準(zhǔn)化數(shù)據(jù)通過減去均值然后除以方差(或標(biāo)準(zhǔn)差),這種數(shù)據(jù)標(biāo)準(zhǔn)化方法經(jīng)過處理后數(shù)據(jù)符合標(biāo)準(zhǔn)正態(tài)分布,即均值為0,標(biāo)準(zhǔn)差為1,轉(zhuǎn)化函數(shù)為:x =(x - 均值)/方差
預(yù)處理結(jié)果:
4.4個模型的簡單測試
綜上結(jié)果可知:在默認(rèn)值參數(shù)下KNN算法是最優(yōu)的,正確率是最高的。
5.選擇當(dāng)前最優(yōu)模型并對其調(diào)優(yōu)
距離參數(shù)通過手動調(diào)整發(fā)現(xiàn)曼哈頓距離最好,對于K值的選擇我們使用for循環(huán)進(jìn)行的查找(本來想使用二分,但是考慮到其不是順序的所以就直接使用的線性查找)
另外其實這里取K=1時是最大的準(zhǔn)確率在98%,但這其實是因為:
K值較小就意味著整體模型變得復(fù)雜,容易發(fā)生過擬合
K值較大就意味著整體模型變得簡單,容易發(fā)生欠擬合
最終結(jié)果:
最后我們?nèi)〉腒值為3
6.對未來的展望:
優(yōu)點:
1、通過多種分類模型對比,使我們對題目了解跟全面,結(jié)構(gòu)更清晰,準(zhǔn)確度更高
2、精度高、對異常值不敏感、無數(shù)據(jù)輸入假定。
缺點:
1、對部分屬性進(jìn)行了直接刪除,忽略了數(shù)據(jù)相關(guān)性對結(jié)果的影響;
2、對部分非有序變量采用直接轉(zhuǎn)變?yōu)閿?shù)字的做法,使變量值之間的權(quán)重不相同;
展望:
1、更細(xì)致的特征選擇,如派生屬性;
2、采用更好的方法解決數(shù)據(jù)不平衡問題,如:代價敏感學(xué)習(xí)方法;
3、更細(xì)致的調(diào)參;
4、長視其他分類模型,如:神經(jīng)網(wǎng)絡(luò)等
5、因為前面是選擇的當(dāng)前最優(yōu)算法,所以可能存在其他三個算法調(diào)優(yōu)之后其準(zhǔn)確度更高的情況。之后可以繼續(xù)嘗試其他算法調(diào)參后的準(zhǔn)確度
完整代碼:
import pandas as pd#訓(xùn)練集和測試集的導(dǎo)入 trainfile = pd.read_csv(r'.\bank-additional-full.csv', sep=';') testfile = pd.read_csv(r'.\bank-additional.csv', sep=';')# 數(shù)據(jù)預(yù)處理 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為每列的眾數(shù)# 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)# 分類變量數(shù)值化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)# # 離散化處理數(shù)據(jù)# 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) #特征對結(jié)果影響分析 # 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("各年齡段的人數(shù)") # 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("各特征的相關(guān)性") # 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()# 數(shù)據(jù)規(guī)范化到正態(tài)分布的數(shù)據(jù) 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準(zhǔn)確率:", accuracy_score(test_y, predict_y))#引入支持向量機(jī)算法 from sklearn.svm import SVC svc = SVC() svc.fit(train_x, train_y) predict_y = svc.predict(test_x) print("svm準(zhǔn)確率:", 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準(zhǔn)確率:", 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("隨機(jī)森林準(zhǔn)確率:", accuracy_score(test_y, predict_y))print("由此得KNN算法為當(dāng)前4個算法的最優(yōu)算法,所以我們對KNN算法進(jìn)行進(jìn)一步的調(diào)參,過程如下:")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準(zhǔn)確率:", accuracy_score(test_y, predict_y)) print("最優(yōu)k值為:") print(max_index) print("最優(yōu)準(zhǔn)確率:") print(max)瘋狂之處在于這個只用了兩天來做 (ó﹏ò。)
總結(jié)
以上是生活随笔為你收集整理的疯狂的机器学习实战-银行营销预测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库-DQL练习(附答案)
- 下一篇: 自创迷宫