看了台湾某教授的一部分ML课程,手痒痒,于是去下载了libsvm来玩玩。正巧学长介绍了kaggle这个有趣的网站,里面有很多数据的竞赛,就拿这个经典的泰坦尼克例子来学习吧-> [懒人请点] (https://www.kaggle.com/c/titanic)。
一、首先把titanic的数据下载下来,共三个文件: gender_submission.csv、test.csv、train.csv,分别是提交格式、测试集和训练集。用pandas的库函数来看看train set里究竟有哪些数据吧!
import pandas
titanic = pandas.read_csv('train.csv')
titanic.describe()
大致就是乘客ID、是否存活、舱位、年龄等等(由于测试集已经被作者处理过,所以建议读者亲自看一看,也可以直接打开train.csv观察)。
二、在大致观察过这些数据后,不难发现,直观上乘客存活的几率与年龄、性别、舱位、登船号有很大关联(年龄、登船口等数据有缺失部分待处理),而与其他数据如姓名、家人数量、票价等关联度不大,或者说没有明显的关系,那我们接下来做一个简单的处理:
def preDataHandle(f):
data_train = pd.read_csv(f)
#把年龄的缺失值用现有数据的中位数来替代并赋值给原数据
data_train['Age'] = data_train['Age'].fillna(data_train['Age'].median())
#把男性置0,女性置1
data_train.loc[data_train['Sex'] == 'male', 'Sex'] = 0
data_train.loc[data_train['Sex'] == 'female', 'Sex'] = 1
#把登船口的缺失值用S替代(整体数据S偏多),并将所有登船口转换为数字
data_train['Embarked'] = data_train['Embarked'].fillna('S')
data_train.loc[data_train['Embarked'] == 'S', 'Embarked'] = 0
data_train.loc[data_train['Embarked'] == 'C', 'Embarked'] = 1
data_train.loc[data_train['Embarked'] == 'Q', 'Embarked'] = 2
#print data_train.describe()
#返回处理后的数据集
return data_train
这个函数的作用就是把数据进行第一遍整理,使其杂字后续步骤中可用。
三、要知道,学习过libsvm的同学都知道,它要求的数据格式是固定的,形如 <label> <index1>:<value1> <index2>:<value2> ...
因此还要把数据整理成新的格式,包括测试集哦!
#训练集数据格式整理
def txtFileProduce1(f, data_train):
with open(f, 'w') as file:
for i in range(len(data_train)):
#data.Survived和data['Survived']此处等价
#python要求读写文件的数据是字符串
file.write(str(data_train.Survived[i])
+ ' ' + '1:' + str(data_train.Age[i])
+ ' ' + '2:' + str(data_train.Sex[i])
+ ' ' + '3:' + str(data_train.Embarked[i]) + '\n')
因为测试集中没有Survived数据,所以需要重写一个函数,这里的是否存活数据来源于提交样本。
#测试集数据格式整理
def txtFileProduce2(f, data_test):
data_test0 = pd.read_csv('gender_submission.csv')
with open(f, 'w') as file:
for i in range(len(data_test)):
file.write(str(data_test0.Survived[i]) + ' ' + '1:' + str(data_test.Age[i])
+ ' ' + '2:' + str(data_test.Sex[i])
+ ' ' + '3:' + str(data_test.Embarked[i]) + '\n')
经过处理后的数据就变成了如下图的格式:
四、整理好数据,就能用libsvm内置的SVM模型来跑拉!
def function():
#数据的第一次整理
data_train = preDataHandle('train.csv')
data_test = preDataHandle('test.csv')
#数据的第二次整理,生成txt文件
txtFileProduce1('trained.txt', data_train)
txtFileProduce2('tested.txt', data_test)
#读入数据,y指标签值,x指特征值
y, x = svm_read_problem('trained.txt')
yy, xx = svm_read_problem('tested.txt')
#训练数据,返回svm模型实例
model = svm_train(y, x)
#对测试集进行存活预测
p_labs, p_acc, a_vals = svm_predict(yy, xx, model)
#p_labs返回的是存活的预测值,列表格式,因此需要遍历取出来
p_labels = [int(x) for x in p_labs]
#生成符合提交格式的csv文件
result = pd.DataFrame({
'PassengerId': data_test['PassengerId'].as_matrix(),
'Survived': p_labels
})
result.to_csv('result.csv', index=False)
跑出来的结果如下:
可以看到,准确度Accuracy接近94%。但是别高兴的太早,这个准确度来源于kaggle上的提交样本,就是前文提到的gender_submission.csv。具体结果如何,还要把result.csv上传到titanic。
五、上传得到的结果如图:
结果表示,我们用libsvm的默认svm模型跑出来的分数是0.71292,竟然还不如titanic给出的样本高。。。不过没关系,在后续的学习中,可以慢慢学习不同的svm模型和不同的核函数,通过不断地调试参数来达到目的准确率。而作者第一次提交得到0分是因为数据格式不对,所以p_labels那行用了int(x),可见不能忽视这些小东西啊。
感谢以下参考文献:
http://www.cnblogs.com/cutd/p/5713520.html
http://blog.youkuaiyun.com/han_xiaoyang/article/details/49797143