赞
踩
在泰坦尼克号之灾事件中,建立乘客获救情况(是/否)与其诸背景特征之间的量化模型,并且依据此模型来预测有某些背景的人在该海难中能否获救。
一个二分类问题。常用的分类算法有逻辑回归、随机森林、支持向量机(SVM)等等。
我们可以选择其中的一种算法进行模型建立,或是尝试使用多种算法建立模型并融合。
对于同一个问题,可以尝试多种思路进行解决,尤其是算法模型建立的过程,与问题的背景,数据的类型,分析计算条件的限制都有关系。
模型的建立和优化是一个动态的过程,其中有许多尝试和反复,先试图建立一个基本的模型,然后再一步步不断的优化。
优化过程包括:
A.分析现在模型的拟合状态(欠/过拟合?)
B.分析模型中使用的特征的贡献大小,进行特征选择,这也是特征工程的一部分。
C.预测失败案例产生的原因。
这个项目中的数据直接来源于Kaggle竞赛平台,是现成的数据。
import pandas as pd
titanic = pd.read_csv("titanic_train.csv")
titanic.head(5)
passengerId:乘客ID
survived:是否被救获
Pclass:乘客等级(舱位等级分为1/2/3等)
Name:乘客姓名
Sex:乘客性别
Age:乘客年龄
SibSp:siblings&spoused,该乘客在船上的堂兄弟妹/配偶人数
Ticket:船票信息 Fare:票价
Cabin:客舱
Embarked:登船港口
titanic.info()
print (titanic.describe()
遇到缺失值的情况,几种常见的处理方式如下:
1.如果缺值的样本占总数比例极高,我们可能就直接舍弃了,作为特征加入的话,可能反倒带入noise,影响最后的结果了
2.如果缺值的样本适中,而该属性非连续值特征属性(比如说类目属性),那就把NaN作为一个新类别,加到类别特征中
3.如果缺值的样本适中,而该属性为连续值特征属性,有时候我们会考虑给定一个step(比如这里的age,我们可以考虑每隔2/3岁为一个步长),然后把它离散化,之后把NaN作为一个type加到属性类目中。
4.有些情况下,缺失的值个数并不是特别多,那我们也可以试着根据已有的值,拟合一下数据,补充上。
titanic["Age"] = titanic["Age"].fillna(titanic["Age"].median())
print titanic.describe()
titanic.loc[titanic["Sex"] == "male", "Sex"] = 0
titanic.loc[titanic["Sex"] == "female", "Sex"] = 1
print(titanic.loc[:5,'Sex'])
print (titanic["Embarked"].unique())
titanic["Embarked"] = titanic["Embarked"].fillna('S')
titanic.loc[titanic["Embarked"] == "S", "Embarked"] = 0
titanic.loc[titanic["Embarked"] == "C", "Embarked"] = 1
titanic.loc[titanic["Embarked"] == "Q", "Embarked"] = 2
去除‘PassengerId’,‘Name’,‘Cabin’,将其余特征值加入
predictors = ['Survived', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked', 'Sex','Pclass']
train_df = titanic[predictors]
print(np.isnan(train_df).any())
train_np = train_df.values
# y即Survival的结果
y = train_np[:, 0]
# X即特征值
X = train_np[:, 1:]
# 导入线性模型中的逻辑回归模型
from sklearn.linear_model import LogisticRegression
import numpy as np
# 定义逻辑回归分类器
clf = LogisticRegression()
# 拟合模型
clf.fit(X, y)
数据预处理跟训练集一样,但是与训练集不同的是,测试集的‘Fare’有缺失值,预测时报错,需要补充缺失值
移步:https://blog.csdn.net/weixin_43746433/article/details/92675242
data_test = pd.read_csv('test.csv') print(data_test.describe()) data_test["Age"] = data_test["Age"].fillna(data_test["Age"].median()) data_test.loc[data_test["Sex"] == "male", "Sex"] = 0 data_test.loc[data_test["Sex"] == "female", "Sex"] = 1 data_test["Embarked"] = data_test["Embarked"].fillna('S') data_test.loc[data_test["Embarked"] == "S", "Embarked"] = 0 data_test.loc[data_test["Embarked"] == "C", "Embarked"] = 1 data_test.loc[data_test["Embarked"] == "Q", "Embarked"] = 2 test_df = data_test[[ 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked', 'Sex','Pclass']] print(np.isnan(test_df).any()) data_test["Fare"] = data_test["Fare"].fillna(data_test["Fare"].median()) test_df = data_test[[ 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked', 'Sex','Pclass']] print(np.isnan(test_df).any())
# 预测
predicted_np = clf.predict(test_np)
#print(predicted_np)
result=pd.DataFrame({'PassengerId':data_test['PassengerId'].values,'Survived':predicted_np.astype(np.int32)})
# 将结果导出到csv文件,不带索引
result.to_csv('predictions.csv', index=False)
预测的结果
我们使用的逻辑回归分类模型是线性分类模型,模型中隐含着一个成本函数,其形式是多远线性方程。模型确定的过程就是要使这个成本函数获得最小值的各个特征(也就是成本函数的自变量)的系数的确定过程。这个方程的系数有什么实际意义呢?如果系数为正,该特征与结果呈正相关,反之,呈负相关,越接近0,相关性越低。如果可以列出特征和其对应的系数,那么我们就可以直观的了解各特征对结果的影响,这也是应用线性模型的好处之一。
coefficients = pd.DataFrame({'columns':list(train_df.columns[1:]),'coef_':list(clf.coef_.T)})
print(coefficients)
在实际训练中,模型通常对训练数据表现好,对非训练数据拟合程度较差,通过将训练集本身随机分成K份,相当于有了多对训练集和测试集,同一个模型可以产生多个准确率,比较多个可能的模型进行交叉验证的结果的准确率方差后,可以比较各个模型的泛化能力。
K折验证
from sklearn import model_selection
from sklearn import linear_model
# 将训练集分成5份,4份用来训练模型,1份用来预测,这样就可以用不同的训练集在一个模型中训练
clf = linear_model.LogisticRegression()
# 定义特征集和结果集
X = train_df.values[:, 1:]
y = train_df.values[:, 0]
print(model_selection.cross_val_score(clf, X, y, cv=5))
过拟合
通过不断的进行特征工程,产生的特征越来越多,用这些特征去训练模型,会对我们的训练集拟合的越来越好,同时也可能在丧失泛化能力,从而在待预测的数据上,表现不佳,也就是发生过拟合现象。
欠拟合
从另一个角度上说,如果模型在待预测的数据上表现不佳,除掉上面说的过拟合问题,
也有可能是欠拟合,也就是说,即使在训练集上也表现得不那么好。
优化
在机器学习问题上,对于过拟合和欠拟合两种情形,我们优化的方式是不同的。
对于过拟合而言,通常以下策略对结果优化是有用的:
A 做一下特征选择,挑出较好的特征的子集来做训练
B 提供更多的数据,从而弥补原始数据的偏差问题,学习到的模型也会更准确。
而对于欠拟合,我们通常需要更多的特征,更复杂的模型来提高准确度。
著名的学习曲线(learning curve)可以帮助我们判定我们的模型现在所处的状态
我们以样本数据为横坐标,训练和交叉验证集上的错误率为纵坐标的两种状态分别如下:
过拟合(overfitting/high variance):
欠拟合(underfitting/high bias):
# 用sklearn的learning_curve得到training_score和cv_score,使用matplotlib画出learning curve def plot_learning_curve(estimator, title, X, y, ylim=None, cv=None, n_jobs=1, train_sizes=np.linspace(.05, 1., 20), verbose=0, plot=True): """ 画出data在某模型上的learning curve. 参数解释 ---------- estimator : 你用的分类器。 title : 表格的标题。 X : 输入的feature,numpy类型 y : 输入的target vector ylim : tuple格式的(ymin, ymax), 设定图像中纵坐标的最低点和最高点 cv : 做cross-validation的时候,数据分成的份数,其中一份作为cv集,其余n-1份作为training(默认为3份) n_jobs : 并行的的任务数(默认1) """ train_sizes, train_scores, test_scores = learning_curve( estimator, X, y, cv=cv, n_jobs=n_jobs, train_sizes=train_sizes, verbose=verbose) train_scores_mean = np.mean(train_scores, axis=1) train_scores_std = np.std(train_scores, axis=1) test_scores_mean = np.mean(test_scores, axis=1) test_scores_std = np.std(test_scores, axis=1) if plot: plt.rcParams['font.sans-serif'] = 'SimHei' ## 设置中文显示 plt.rcParams['axes.unicode_minus'] = False plt.figure() plt.title(title) if ylim is not None: plt.ylim(*ylim) plt.xlabel(u"训练样本数") plt.ylabel(u"得分") plt.gca().invert_yaxis() plt.grid() plt.fill_between(train_sizes, train_scores_mean - train_scores_std, train_scores_mean + train_scores_std, alpha=0.1, color="b") plt.fill_between(train_sizes, test_scores_mean - test_scores_std, test_scores_mean + test_scores_std, alpha=0.1, color="r") plt.plot(train_sizes, train_scores_mean, 'o-', color="b", label=u"训练集上得分") plt.plot(train_sizes, test_scores_mean, 'o-', color="r", label=u"交叉验证集上得分") plt.legend(loc="best") plt.draw() plt.show() plt.gca().invert_yaxis() midpoint = ((train_scores_mean[-1] + train_scores_std[-1]) + (test_scores_mean[-1] - test_scores_std[-1])) / 2 diff = (train_scores_mean[-1] + train_scores_std[-1]) - (test_scores_mean[-1] - test_scores_std[-1]) return midpoint, diff plot_learning_curve(clf, u"学习曲线", X, y)
目前的曲线看来,我们的model并不处于overfitting的状态(overfitting的表现一般是训练集上得分高,而交叉验证集上要低很多,中间的gap比较大)。因此我们可以再做些feature engineering的工作,添加一些新产出的特征或者组合特征到模型中。
模型融合的含义:当我们手头上有一堆在同一份数据集上训练得到的分类器(比如logistic regression,SVM,KNN,random forest,神经网络),那我们让他们都分别去做判定,然后对结果做投票统计,取票数最多的结果为最后结果。
模型融合可以比较好地缓解,训练过程中产生的过拟合问题,从而对于结果的准确度提升有一定的帮助。
首先,需要训练出多个同时具有可用性的模型。
思路是可以应用多个算法模型,或者是对同一个算法模型用不同的数据集进行训练(bagging)。
本文中用机器学习解决问题的过程大概如下图所示:
参考:https://blog.csdn.net/zs15321583801/article/details/79698341
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。