此为中文翻译版python
咱们将学习如何为Kaggle竞赛生成一个提交答案(submisson
)。Kaggle是一个你经过完成算法和全世界机器学习从业者进行竞赛的网站。若是你的算法精度是给出数据集中最高的,你将赢得比赛。Kaggle也是一个实践你机器学习技能的很是有趣的方式。
Kaggle网站有几种不一样类型的比赛。其中的预测一个就是预测在泰坦尼克号沉没的时候哪一个乘客会成为幸存者。 在这个任务和下一个任务咱们将学习如何提交咱们的答案。
咱们的数据是csv
格式。你能够在这里下载数据开始比赛。
每一行重现了一个在泰坦尼克的乘客以及和他们有关的一些信息。让咱们来看一下各列:git
一个好的开始就是有条理的思考各个列和咱们的预测之间的逻辑关系。
咱们都知道妇女和儿童更可能被救。所以,年龄
和性别
极可能更好的帮助咱们预测。认为乘客的船层可能会影响结果也是符合逻辑的,由于第一层的船舱更靠近船的甲板。Fare
票价和乘客所住船层相关,并且多是高度相关的,可是也可能会增长一些额外的信息。SibSp、Parch
兄弟姐妹、配偶、父母/孩子的数量极可能关系到是否被某一个或不少我的救,会有不少人去帮助你或者有不少人想到你尝试去救你。
像Embarked
登船(也许有一些信息和怎么靠近船的顶部的人的船舱有关),Ticket
票号和Name
名字。
这一步一般是习得相关的领域知识[要对业务比较深刻],这对于绝大多数机器学习任务来讲很是很是很是的重要。
咱们很是细致的处理特征以便咱们能从咱们现有的数据中得到最有用的信息来帮助咱们进行预测。算法
咱们将使用Python3,pandas库和scikit-learn库来分析咱们的数据而且生成一个提交答案submisson
。咱们将使用代码框进行交互式编程,就和你看到的下面那个同样。若是你对Python还不熟悉,你可能想看一看咱们的课程。
一个好的第二步就是仔细观察数据中的高级描述。在这种状况下,咱们使用pandas的.describe()
方法来查看每一列数值的特性的不一样之处。编程
# We can use the pandas library in python to read in the csv file. # This creates a pandas dataframe and assigns it to the titanic variable. titanic = pandas.read_csv("titanic_train.csv") # Print the first 5 rows of the dataframe. print(titanic.describe())
在上一节你使用.describe()
方法查看titanic
数据框的时候,你可能注意到年龄列只有714个计数,而其余列都有891个计数。这代表在年龄列有一些缺失值——空值(null,NA,非数字)。
这就意味着数据并非彻底的干净,咱们必须本身清洗数据。咱们不但愿不得不删除有缺失数据的行,由于更多的数据能帮助咱们训练出一个更好的算法。固然,咱们也不想删除整列,由于age年龄极可能对咱们的分析很是重要。
有不少种策略来处理缺失数据,可是一种简单的方法就是将那一列的缺失值用中位数填充。
咱们能够像字典同样经过数据框索引选取一个单列。这样会给咱们一个pandas Series(序列):数组
titanic['Age']
咱们可使用.fillna
方法替换序列中的任何缺失值。.fillna
能够传入一个参数用参数的值来替换缺失值。
在咱们的例子中,咱们打算用列的中位数来填充:app
titanic['Age'].fillna(titanic['Age'].median())
以后咱们必须将替换后的结果赋值回原来的列:dom
titanic['Age'] = titanic['Age'].fillna(titanic['Age'].median())
前两节咱们使用过.describe()
,你也许也主要到并非全部的列都显示出来了。只有数值列显示了。咱们的列中有几个是非数值的,当你开始作预测的时候这将是一个问题——咱们不能将非数值列传入机器学习算法中而且指望机器学习算法能理解他们。
咱们在训练咱们的算法时要么必须排除这些非数值列(Name
, Sex
, Cabin
, Embarked
, Ticket
),要么就要找到一种方法将他们转换成数值列。
咱们将忽略Ticket
, Cabin
,Name
这三行。由于咱们不能从他们中提取出太多有用的信息。Cabin
列大多数值都是缺失的(891行中只有204行数值),并且起初看起来好像也不是特别有用的列。若是没有一些关于船票号码意义的专业领域知识和哪些名字的特色像大户或者有钱家庭,那么Ticket
和Name
列也不太可能会告诉咱们太多的信息。机器学习
Sex
列性别列是非数值的,可是咱们想把它保留——他可能很是有用。咱们将每个性别用数值码替换将其转换成一个数值列。以后机器学习算法可以使用这些类别去作预测。
为了完成这个目的,咱们首先要找出列中全部的惟一性别(咱们知道有male男和female女,可是有没有可能谁在数据集用的是其余缺失值代码呢?)。咱们将0赋值给male,将1赋值给female。
咱们能够选择Sex
列的全部值为male的行而且用0替换male:函数
titanic.loc[titanic['Sex']=='male','Sex'] = 0 titanic.loc[titanic['Sex']=='female','Sex'] = 1 # 有一个问题就是我本身测试的时候,describe()方法仍是不显示性别。
Embarked
列咱们如今能够用和转换Sex
列相同的方法将Embarked
列转换成数值码。Embarked
列的惟一值是S,C,Q
和缺失值nan
。每一个字母是一个登船港口名字的缩写。
第一步是替换列中的缺失值。大部分共同的登船港口都是S
,因此咱们假设每一个人都是从那儿上船的。将Embarked
列的缺失值全都替换成S
。
咱们分别将0
赋值给S
,将1
赋值给C
,将2
赋值给Q
,替换每一个值相应的代码:性能
# Find all the unique values for "Embarked". 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
如今咱们的数据已经清洗得干净了一点了,咱们准备开始探索一些机器学习。咱们开始的一些行数据看起来像这样:
Age |Sex |Survived
----|----|--------
10 | 0 |0
5 | 1 |1
30 | 0 |0
若是咱们想利用Age
列的数据来预测是否有人幸存或者没有幸存,咱们可使用一种叫作线性回归的方法。线性回归的等式以下:(y=mx+b),y
的值是咱们设法预测的,m
是一个叫作斜率的系数,x
是一列的值,b
是一个叫作截距的常数。
咱们能够经过赋值-2
给m
,赋值20
给b
作一个预测。咱们获得这样的结果:
Age | Sex | Survived | Predictions |
---|---|---|---|
10 | 0 | 0 | -2*10+20=0 |
5 | 1 | 1 | -2*5+20=10 |
30 | 0 | 0 | -2*30+20=-40 |
若是咱们将获得的预测结果中任何大于0的值转换成1,任何小于等于0的值换成0,咱们将获得这样的结果:
Age | Sex | Survived | Predictions |
---|---|---|---|
10 | 0 | 0 | 0 |
5 | 1 | 1 | 1 |
30 | 0 | 0 | 0 |
这个简单的模型预测幸存者至关好。线性模型能够是一个很是强大的算法,可是也有一些缺点:
咱们以后会讨论如何处理这两个问题。如今,咱们将学习如何自动的计算线性回归的回归系数,如何用多列数据来预测一个结果。
咱们如今使用线性回归在咱们的训练数据集上作预测。
咱们想用除咱们作预测以外的不一样的数据来训练算法。若是咱们想避免过拟合这是很是关键的。过拟合是当一个模型拟合它自己过于复杂,不显著。每一个数据都有其独有的特色且不存在于全集。例如:若是我要求你利用一辆车的马力和其余特征,而且给你一个随机的很是高的最高速度数据集,来预测一辆车的最高速度,你将会创建一个速度太高的模型。解决的办法就是用你没有用来训练模型的数据去测试性能。
每个机器学习算法均可以过拟合,即便有的(像线性回归)很是不容易。若是你测试(评估)你的算法和你训练算法是用的同一个数据集,那么你极可能不知道它的性能好究竟是算法很好仍是由于过拟合它本身的噪声。
幸运的是,交叉验证是一个很简单的避免过拟合的方法。交叉验证,你将你的数据分红一些数字部分(或子类)。咱们使用3
做为一个例子。而后你这样作:
这种方式,评价咱们生成的预测的精度的整个数据集和曾经训练咱们的模型没有相同的数据。
咱们可使用极好的scikit-learn
库来作预测。咱们将使用skelearn的一个助手来将数据分红交叉验证的子类,而后用每个子类分别来训练算法作预测。最后,咱们将获得一个预测列表,每个列表项包含了相关子类的预测数据。
# Import the linear regression class from sklearn.linear_model import LinearRegression # Sklearn also has a helper that makes it easy to do cross validation from sklearn.cross_validation import KFold # The columns we'll use to predict the target predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"] # Initialize our algorithm class alg = LinearRegression() # Generate cross validation folds for the titanic dataset. It return the row indices corresponding to train and test. # We set random_state to ensure we get the same splits every time we run this. kf = KFold(titanic.shape[0], n_folds=3, random_state=1) predictions = [] for train, test in kf: # The predictors we're using the train the algorithm. Note how we only take the rows in the train folds. train_predictors = (titanic[predictors].iloc[train,:]) # The target we're using to train the algorithm. train_target = titanic["Survived"].iloc[train] # Training the algorithm using the predictors and target. alg.fit(train_predictors, train_target) # We can now make predictions on the test fold test_predictions = alg.predict(titanic[predictors].iloc[test,:]) predictions.append(test_predictions)
如今咱们有了预测结果,咱们能够测试咱们的偏差了。
第一步咱们须要先定义偏差的度量标准,因此咱们先算出咱们模型的精度。从Kaggle竞赛的描述,偏差的度量标准是正确预测的百分比。咱们将使用这个相同的度量标准来测试咱们本地模型的性能。
这个度量标准将基本上是predictions
中找到的值和他们在titanic['Survived']
的副本中准确对应的值的数量而后再除以乘客的总数。
在咱们这么作以前,咱们须要先将三个预测数据集合并到一个列中。由于每个预测数据集是一个numpy(python科学计算库[注:真正的科学计算库应该是scipy,而numpy主要是矩阵数组等数据处理运算])数组,咱们可使用一个numpy方法将他们链接到一个列里。
算出predictions
预测值中和titanic["Survived"]
副本中准确相同的值的比例。这个计算结过应该是一个浮点数(小数)并将它赋值给变量accuracy
。
import numpy as np # The predictions are in three separate numpy arrays. Concatenate them into one. # We concatenate them on axis 0, as they only have one axis. predictions = np.concatenate(predictions, axis=0) # Map predictions to outcomes (only possible outcomes are 1 and 0) predictions[predictions > .5] = 1 predictions[predictions <=.5] = 0 accuracy = sum(predictions[predictions == titanic['Survived']])/(titanic['Survived'].count())
咱们有了咱们的第一个预测结果!但是结果并非很好,只有78.3%的正确率。在视频中,咱们曾提到一种方式使线性回归的输出值介于0
和1
之间。这种方法叫作逻辑回归。
一个好的方法就是将逻辑回归当成是线性回归的逻辑输出,因此他的值就是0
和1
。用逻辑函数 logit function来完成。输入任何值到逻辑函数都将经过“压缩”极值匹配成0
和1
。这对咱们来讲很是完美,由于咱们只关心两种输出结果。
Sklearn
有一个逻辑回归的类咱们可使用。经过使用一个Sklearn
助手函数可使咱们全部的交叉验证和测试变得更简单。
咱们的正确度已经能够了,可是还不是很是好。咱们任然能够尝试一些方法来使它变得更好,在下一个任务将会讨论。
可是咱们须要提交一个答案到比赛中。咱们须要在测试数据上采起一个和训练数据上同样的校准的步骤来完成这个事情。若是咱们没有校准操做,咱们就不可以利用它作出有效的预测。
这些操做要在咱们对列全部的改变以前进行。
处理titanic_test
和处理titanic
用一样的方法。
这涉及到:
titanic['Age'].median()
去找到中位数。Sex
列中的全部male
换成0
,全部female
换成1
。S
填充Embarked
列中的全部缺失值。Embarked
列中的S
换成0
,C
换成1
,Q
换成2
。Fare
列的缺失值替换掉。用.fillna
将测试集中的缺失值用中位数替换掉。训练集中的Fare
列没有缺失值了,可是测试集有时会不一样。titanic_test = pandas.read_csv("titanic_test.csv") titanic_test['Age'] = titanic_test['Age'].fillna(titanic_test['Age'].median()) titanic_test['Fare'] = titanic_test['Fare'].fillna(titanic_test['Fare'].median()) titanic_test.loc[titanic_test['Sex'] == 'male','Sex'] = 0 titanic_test.loc[titanic_test['Sex'] == 'female','Sex'] = 1 titanic_test['Embarked'] = titanic_test['Embarked'].fillna('S') titanic_test.loc[titanic_test['Embarked'] == 'S', 'Embarked'] = 0 titanic_test.loc[titanic_test['Embarked'] == 'C', 'Embarked'] = 1 titanic_test.loc[titanic_test['Embarked'] == 'Q', 'Embarked'] = 2
如今咱们有了咱们须要生成一个比赛提交答案的全部东西了。
首先,咱们必须先在训练数据上训练一个算法。而后咱们在测试数据集上作一个预测。最后,咱们生成一个包含预测和乘客id的csv文件。
一旦你完成了下面步骤的代码,你就能用submission.to_csv('kaggle.csv, index=False')
输出一个csv结果。这将会给你的第一个条件全部须要的东西——虽然这没有给你很好的准确率。(~0.75)
# Initialize the algorithm class alg = LogisticRegression(random_state=1) # Train the algorithm using all the training data alg.fit(titanic[predictors], titanic["Survived"]) # Make predictions using the test set. predictions = alg.predict(titanic_test[predictors]) # Create a new dataframe with only the columns Kaggle wants from the dataset. submission = pandas.DataFrame({ "PassengerId": titanic_test["PassengerId"], "Survived": predictions })
咱们只是生成了一个调教文件,可是准确率不是很好(0.75)。因为咱们的预测在不一样的数据集上致使在测试集上的分数低于咱们在交叉验证上的分数。在下一个任务中咱们将学习如何生成更好的特征和使用更好的模型来提升咱们的分数。
恭喜你完成了这个任务!