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

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

作者: bakaqian | 来源:发表于2017-09-17 14:43 被阅读671次

    题目

    连接: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()
    

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/ivapsxtx.html