持续更新中。。。
7. 预测模型
首先将train分为训练集和测试集:
# 将目标变量和特征分开
X_train = train.drop('Survived',axis=1)
y_train = train['Survived']
# 将train分为训练集和测试集
# 用sklearn.model_selection 里的train_test_split
import sklearn
from sklearn.model_selection import train_test_split
X_train,x_test,Y_train,y_test = train_test_split(X_train,y_train,test_size=0.3,random_state=101)
# 待预测的数据集
X_test = test.copy()
下面开始使用不同的算法训练模型:
a. Logistic Regression
Logistic Regression用于二分类任务中,它与传统线性回归模型相比,多了一步将线性回归输出值映射到Sigmoid函数(即形似S的函数,代表有对率函数)中,可以定义大于0.5的值归为1(正)类,小于0.5的值归为0(负)类。LR过程就是找出分类回归系数W的过程。
优点是:计算代价不高,容易理解和实现;缺点是:容易欠拟合,分类精度可能不高。
其中Z为线性回归输出:
通过梯度下降算法找出代价函数的最小值。
下面使用sklearn.linear_model中的LogisticRegression训练模型并预测:
from sklearn.linear_model import LogisticRegression
LR=LogisticRegression()
LR.fit(X_train,Y_train)
Y_pred1 = LR.predict(x_test)
LR_score = round(LR.score(x_test,y_test)*100,2)
LR_score
77.99
# 用classification_report查看查准率precision、召回率recall、F1 score
from sklearn.metrics import classification_report,confusion_matrix
print(classification_report(y_test,Y_pred1))
# 混淆矩阵confusion_matrix
cm = pd.DataFrame(confusion_matrix(y_test,Y_pred1),['Actual: No','Actual: Survived'],['Predict: No','Predict: Survived'])
print(cm)
precision recall f1-score support
0 0.78 0.86 0.82 154
1 0.78 0.68 0.72 114
avg / total 0.78 0.78 0.78 268
Predict: No Predict: Survived
Actual: No 132 22
Actual: Survived 37 77
# 查看各特征在logistic regression模型中的系数
coeff_df = pd.DataFrame(X_train.columns)
coeff_df.columns = ['Feature']
# 系数
coeff_df['Correlation'] = pd.Series(LR.coef_[0])
coeff_df.sort_values(by='Correlation', ascending=False)
Feature | Correlation | |
---|---|---|
6 | Fare_log | 0.646626 |
7 | Has_Cabin | 0.487101 |
10 | Embarked_gender | 0.342207 |
2 | Parch | 0.164608 |
3 | Name_length | 0.046629 |
0 | Pclass | -0.061263 |
4 | Age_level | -0.199004 |
9 | Deck | -0.285174 |
1 | Sex | -0.288856 |
5 | Familysize | -0.565775 |
8 | Title | -1.13175 |
在此模型中,Fare_log/Familysize/Title系数较高,对结果影响较大。
b. Support Vector Machines支持向量机
一种二分类模型,目的是寻找一个超平面来对样本进行分割,分割的原则是间隔最大化,最终转化为一个凸二次规划问题来求解。
线性可分支持向量机:
在样本空间中,划分超平面可以用如下线性方程表示:
等价于:
样本中满足yi(wTxi+b)=1,它们被称为“支持向量”。虚线称为边界,两条虚线间的距离称为间隔(margin)。
SVM需使得间隔最大化。
下面使用sklearn.svm中的SVC和LinearSVC来训练模型并预测:
from sklearn.svm import SVC,LinearSVC
svc=SVC()
svc.fit(X_train,Y_train)
Y_pred2 = svc.predict(x_test)
svc_score = round(svc.score(x_test,y_test)*100,2)
svc_score
79.1
查看precision,recall,F1score:
print(classification_report(y_test,Y_pred2))
cm2 = pd.DataFrame(confusion_matrix(y_test,Y_pred2),['Actual: No','Actual: Survived'],['Predict: No','Predict: Survived'])
print(cm2)
precision recall f1-score support
0 0.80 0.86 0.82 154
1 0.78 0.70 0.74 114
avg / total 0.79 0.79 0.79 268
Predict: No Predict: Survived
Actual: No 132 22
Actual: Survived 34 80
c. k_Nearest Neighbors algorithm(KNN) k近邻算法
核心思想:未标记样本类别由距离其最近的k个邻居投票决定。
KNN原理简单,容易实现,结果精度高,无需估计参数,无需训练模型,可用于分类(投票)和回归(平均值);
不足:当样本容量不平衡时,可能导致需预测的样本中大容量类的样本占多数;可解释性差;处理时间长,计算所有距离并排名。
from sklearn.neighbors import KNeighborsClassifier
# n_neighbors为k值(默认5), leaf_size叶子节点样本数(默认30),weights权重(默认统一权重uniform),metric闵可夫斯基空间,p=2(Lp=L2欧式距离)
knn = KNeighborsClassifier(n_neighbors=10,leaf_size=26,weights='uniform',metric='minkowski',p=2,algorithm='auto',n_jobs=1)
knn.fit(X_train,Y_train)
Y_pred3 = knn.predict(x_test)
knn_score = round(knn.score(x_test,y_test)*100,2)
knn_score
75.37
print(classification_report(y_test,Y_pred3))
cm3 = pd.DataFrame(confusion_matrix(y_test,Y_pred3),['Actual: No','Actual: Survived'],['Predict: No','Predict: Survived'])
print(cm3)
precision recall f1-score support
0 0.76 0.84 0.80 154
1 0.75 0.63 0.69 114
avg / total 0.75 0.75 0.75 268
Predict: No Predict: Survived
Actual: No 130 24
Actual: Survived 42 72
KNN算法k值得选择非常重要,k值太小结果会对噪音样本异常敏感,过拟合;k值过大,k近邻中距离较远的点会影响结果,使错误的可能性增大。因此,接下来对不同k值预测结果进行对比,找出最适合的k值:
# 为knn重新划分训练集和测试集
x_train_knn,x_test_knn,y_train_knn,y_test_knn = train_test_split(X_train1,y_train1,test_size=0.33,random_state=0)
nn_score=[]
best_prediction = [-1,-1]
from sklearn.metrics import accuracy_score
for i in range(1,100):
# weights='distance'权重等于距离的倒数
knn = KNeighborsClassifier(n_neighbors=i,weights='distance')
knn.fit(x_train_knn,y_train_knn)
score = accuracy_score(y_test_knn,knn.predict(x_test_knn))
if score > best_prediction[1]:
best_prediction=[i,score]
nn_score.append(score)
print(best_prediction)
plt.plot(range(1,100),nn_score)
[5, 0.8203389830508474]
k=5时knn算法准确率最高为0.82。
d. Naive Bayes classifier朴素贝叶斯分类
朴素贝叶斯通过考虑特征的概率来预测分类。
贝叶斯法则:
可以理解x,y为样本的两个特征,Ci为分类值(C1,C2,C3...Ck),对于固定的数据集,p(x,y)是固定的,因此,p(ci|x,y)正比于p(x,y|ci)p(ci).
当存在n个特征时:X = (x1,x2...xn)
p(x1,x2...xn|ci)p(ci)=p(x1,x2...xn,ci)
p(x1,x2...xn,ci)=p(x1|x2,x3...xn,ci)p(x2|x3,x4...xn,ci)...p(xn|ci)p(ci)
朴素贝叶斯的“朴素”指的是样本与样本间相互独立,没有关联。
因此,p(x1|x2,x3...xn,ci)=p(x1|ci),那么p(x1,x2...xn|ci)p(ci)可以表示为:
这样就可以计算出X分别在不同分类条件Ci下的概率.
在scikit-learn中,提供了3中朴素贝叶斯分类算法:GaussianNB(高斯朴素贝叶斯)、MultinomialNB(多项式朴素贝叶斯)、BernoulliNB(伯努利朴素贝叶斯)
- 高斯模型
当特征是连续变量的时候,假设特征分布为正态分布,根据样本算出均值和方差,再求得概率。 - 伯努利模型
伯努利模型适用于离散特征的情况,伯努利模型中每个特征的取值只能是1和0。
- 多项式模型:多项式模型在计算先验概率P(Yk)P(Yk)和条件概率P(xi|Yk)P(xi|Yk)时,会做一些平滑处理,具体公式为:
# 高斯朴素贝叶斯
from sklearn.naive_bayes import GaussianNB
gaussian = GaussianNB()
gaussian.fit(X_train,Y_train)
Y_pred4 = gaussian.predict(x_test)
gaussian_score = round(gaussian.score(x_test,y_test)*100,2)
gaussian_score
75.37
print(classification_report(y_test,Y_pred4))
cm4=pd.DataFrame(confusion_matrix(y_test,Y_pred4),['Actual: No','Actual: Survived'],['Predict: No','Predict: Survived'])
print(cm4)
precision recall f1-score support 0 0.81 0.74 0.78 154 1 0.69 0.77 0.73 114 avg / total 0.76 0.75 0.75 268 Predict: No Predict: Survived Actual: No 114 40 Actual: Survived 26 88
e. 决策树
决策树是一个类似于流程图的树结构,分支节点表示对一个特征进行测试,根据测试结果进行分类,树叶节点代表一个类别。
要判断从哪个特征进行分裂,就要对信息进行量化,量化的方式有:
ID3: 信息增益
条件熵:
其中pi=P(X=xi),X,Y代表了两个事件,而它们之间有时有联系的(也就是联合概率分布),条件熵H(Y|X)代表了在一直随机变量X的情况下,Y的不确定性的大小。
信息增益:熵H(Y)和条件熵H(Y|X)的差。定义如下:
I(Y,X)=H(Y)−H(Y|X)
熵越大,事物越不确定,信息增益越大,该特征越适合做分裂点。
C4.5: 信息增益比
CART: 基尼系数
from sklearn.tree import DecisionTreeClassifier
decision_tree = DecisionTreeClassifier()
decision_tree.fit(X_train,Y_train)
Y_pred4 = decision_tree.predict(x_test)
DT_score = round(decision_tree.score(x_test,y_test)*100,2)
DT_score
78.73
print(classification_report(y_test,Y_pred5))
cm5 = pd.DataFrame(confusion_matrix(y_test,Y_pred5),['Actual: No','Actual: Survived'],['Predict: No','Predict: Survived'])
print(cm5)
precision recall f1-score support 0 0.80 0.84 0.82 154 1 0.77 0.71 0.74 114 avg / total 0.79 0.79 0.79 268 Predict: No Predict: Survived Actual: No 130 24 Actual: Survived 33 81
f. 随机森林
用随机的方式建立一个森林,森林里有很多决策树,每棵树之间无关联,有新输入样本时,让森林中每一颗决策树分别进行判断,看该样本属于哪一类,哪类被选择最多,就预测这个样本为那一类。
from sklearn.ensemble import RandomForestClassifier
random_forest=RandomForestClassifier(n_estimators=100)
random_forest.fit(X_train,Y_train)
Y_pred6=random_forest.predict(x_test)
RF_score=round(random_forest.score(x_test,y_test)*100,2)
RF_score
78.73
print(classification_report(y_test,Y_pred6))
cm6 = pd.DataFrame(confusion_matrix(y_test,Y_pred6),['Actual: No','Actual: Survived'],['Predict: No','Predict: Survived'])
print(cm6)
precision recall f1-score support 0 0.79 0.85 0.82 154 1 0.78 0.70 0.74 114 avg / total 0.79 0.79 0.79 268 Predict: No Predict: Survived Actual: No 131 23 Actual: Survived 34 80