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

题目

连接: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 csv
import os
from sklearn import svm

def 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 result

def 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] = avg

def 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 x

def getLabel(data):
    label = []
    for i in range(len(data["PassengerId"])):
        label.append(int(data["Survived"][i]))
    return label

def 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()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容