[kaggle系列 三] 使用SVM判断是否能从泰坦尼克号生还

来源:互联网 发布:win7开启443端口 编辑:程序博客网 时间:2024/06/05 05:01

题目

连接:https://www.kaggle.com/c/titanic

前言

和前几篇差不多,这次换成svm,实际上,对于svm的理解是有了,知道是怎么做的了,但具体公式如何推导,还是不会,但是,这不影响写代码,使用现成的库函数就可以搞定,有时候,这些工具大大简化了我们的学习成本,知道基本原理,然后去使用就行了,具体的细节也不用去关心。用陶渊明的话来说,就是,“好读书,不求甚解;每有会意,便欣然忘食.”。在机器学习方面,对于我这种人来说,更多的精力应该放在如何应用,如何处理数据与训练好模型上,去理解底层原理然后对学习方法进行一些改进之类的,只能说现在还达不到那种境界。

SVM

这里简单介绍一下svm的基本原理就结束了~ 我认为这个大概理解一下就行了,后面真的遇到瓶颈的时候再仔细研究一下吧~
SVM全称是支持向量机(Support Vector Machine),听起来还是挺高端的,让我想起来搞acm的时候第一次听到AC自动机的时候,哈哈。
SVM的分类方法其实和逻辑回归类似,想象我们有一堆数据,这个数据有两个属性,也就是x是一个二维向量,那么就是类似这样一个图:

在实际数据中,红色的是一类,蓝色的是一类,我们想要用一个线性函数来将这些数据分类,即在函数图像将平面分成两个区域,一个区域内的点认为是红色类,另一个区域内的点认为是蓝色的点。仔细思考一下就可以发现,这是不可能实现的,无论如何在平面中画线,都不能比较完美的分割。所以svm算法提出了一个思路:把n维空间无法解决的问题,放在n+1或者更高维度的空间中去分类。想象我们把上图中的二维平面的点放到三维空间中,我们就可以构造出这样的集合:

在三维空间中,二维平面中的点由于多了一维,有了“高度”,我们就可以用一个平面将这两个集合完美划分:

在svm算法体系中,这个平面就叫做“超平面”,这是一个抽象的面的概念,在一维空间里就是一个点,二维空间里就是一条直线,三维空间里就是一个平面,以此类推。
那么如何把一个n维空间中的点映射到更高维上去呢?这就要用核函数(Kernel)去构造,常见的核函数有:线性核函数、多项式核函数、径向核函数、高斯核函数等等……至于这些函数如何运作的,这里就不介绍了(其实是因为不会,嘻嘻)。值得一提的是,核函数并没有增加更多的维度,也就是你原来的输入是二维向量,那升维以后的输入也是相同的,核函数的其他维度表示的只是一个变量代换的关系。

拟合问题与奥卡姆剃刀原则

上面提到svm可以把n维空间中的点映射到更高维,那么,升维操作是不是做越多越好呢?比如把上图中的二维空间中的点映射到十维空间中,是不是比映射到三维空间中结果更好?

下面用一个多项式函数拟合模型来解释这个问题:

在上面这个图中,用了3个模型拟合一个训练样本,图左是用一个线性函数来进行拟合,最终的模型会欠拟合,它无法捕捉数据中的曲率信息,图中是用一个二次函数来拟合,从效果上看,它的泛化能力比较好,没有明显的过拟合或者欠拟合现象。图右是一个9阶的多项式函数拟合结果,这会导致过拟合,虽然在训练数据上表现的很好,但是没有一个比较有效的结构信息,在真实数据中,并没有想前两个点之间中有一个“深谷”。

那么,如何选择拟合模型的维度,或者说容量?能够比较好的拟合数据,有良好的泛化能力,不至于有明显的欠拟合或过拟合的现象发生呢?许多早期的学者提出一个简约原则,现代广泛被称为奥卡姆剃刀。该原则说,“如无必要,勿增实体”,在同样能够解释已知观测现象的假设中,我们应该挑选“最简单”的那一个。所以,不只是针对svm,对于所有机器学习模型来说,都有各种各样的过拟合与欠拟合问题,其实都可以遵循这个简单的原则,模型的能力如果可以对数据进行解释,那么就不要去增加它的复杂度。

代码与结果

下面上代码,尝试了各种核函数,其中,线性核函数(linear)表现的最好,准确率有0.76555。

import csvimport osfrom sklearn import svmdef readData(fileName):    result = {}    with open(fileName,'rb') as f:        rows = csv.reader(f)        for row in rows:            if result.has_key('attr_list'):                for i in range(len(result['attr_list'])):                    key = result['attr_list'][i]                    if not result.has_key(key):                        result[key] = []                    result[key].append(row[i])            else:                result['attr_list'] = row    return resultdef writeData(fileName, data):    csvFile = open(fileName, 'w')    writer = csv.writer(csvFile)    n = len(data)    for i in range(n):        writer.writerow(data[i])    csvFile.close()def convertData(dataList):    hashTable = {}    count = 0.0    for i in range(len(dataList)):        if not hashTable.has_key(dataList[i]):            hashTable[dataList[i]] = count            count += 1        dataList[i] = hashTable[dataList[i]]def convertValueData(dataList):    sumValue = 0.0    count = 0    for i in range(len(dataList)):        if dataList[i] == "":            continue        sumValue += float(dataList[i])        count += 1        dataList[i] = float(dataList[i])    avg = sumValue / count    for i in range(len(dataList)):        if dataList[i] == "":            dataList[i] = avgdef dataPredeal(data):    convertValueData(data["Age"])    convertData(data["Fare"])    convertData(data["Pclass"])    convertData(data["Sex"])    convertData(data["SibSp"])    convertData(data["Parch"])    convertData(data["Embarked"])def getX(data):     x = []    ignores = {"PassengerId":1, "Survived":1, "Name":1,"Ticket":1, "Cabin":1, "Fare":1, "Embarked":1}        for i in range(len(data["PassengerId"])):        x.append([])        for j in range(len(data["attr_list"])):            key = data["attr_list"][j]            if not ignores.has_key(key):                x[i].append(data[key][i])    return xdef getLabel(data):    label = []    for i in range(len(data["PassengerId"])):        label.append(int(data["Survived"][i]))    return labeldef calResult(x,label, input_x):    svmcal = svm.SVC(kernel='linear').fit(x, label)    return svmcal.predict(input_x)def run():    dataRoot = '../../kaggledata/titanic/'    data = readData(dataRoot + 'train.csv')    test_data = readData(dataRoot + 'test.csv')    dataPredeal(data)    dataPredeal(test_data)    x = getX(data)    label = getLabel(data)    input_x = getX(test_data)    x_result = calResult(x, label,input_x)    res = [[test_data["PassengerId"][i], x_result[i]] for i in range(len(x_result))]    res.insert(0, ["PassengerId", "Survived"])    writeData(dataRoot + 'result.csv', res) run()
阅读全文
0 0
原创粉丝点击