题目
连接: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()
网友评论