这篇文章适合给谁看?
我是一名从能源转行做数分的研二学生,看了近4个月python,之前对计算机接近0基础(c语言都考不过),首先这篇适合给那些跟我一样转行的朋友,转行不易,坚持第一!其次这篇文章也适合给那些准备面试的朋友,了解数据分析的大概流程,粗数据如何处理,这点比能多调用一个学习包更有作用~这篇文章大部分都是我从别的博客上引用的,感谢网路上的各位大神~
项目概述:
这是一个二分类问题,提供的特征有Pclass,Sex,SibSp,Parch,Embarked这类的离散值(包含离散的数字和文本),Age这类连续的数字以及Name,Fare,Ticket这类的文本,其中包含有缺失值;最后要对乘客进行0,1预测(1表示生还)。
对粗数据进行观察:
观察样本特征:使用.head()方法观察缺失数据:使用.info()方法观察数字特征:使用.describe()方法,可以得到平均值,中位数,平均生还率等等观察字符串特征:使用.describe(include=[‘O’]),可以得到分类数,频率较高值等等
利用图表对数据进行观察:
对于离散的特征,利用表格观察其与分类间的关系,比如:
print train_df
[['Pclass','Survived']].groupby([
'Pclass'],as_index=False).mean().sort_values(by=
'Survived',ascending=False)
生成结果:
P
class Survived
0 1 0.629630
1 2 0.472826
2 3 0.242363
Sex Survived
0 female
0.742038
1 male
0.188908
SibSp Survived
1 1 0.535885
2 2 0.464286
0 0 0.345395
3 3 0.250000
4 4 0.166667
5 5 0.000000
6 8 0.000000
Parch Survived
3 3 0.600000
1 1 0.550847
2 2 0.500000
0 0 0.343658
5 5 0.200000
4 4 0.000000
6 6 0.000000
由此可见:一等舱的乘客、女性、有1个兄弟姐妹或配偶(SibSp)以及有三个子女或父母(Parch)的乘客生还几率最大,这有利于之后做特征 - 对于连续的特征,利用直方图观察其与分类间的关系,比如:
g = sns.FacetGrid(train_df, col=
'Survived')
g.
map(plt.hist,
'Age', bins=
4)
plt.show()
生成结果: 由此可见:年龄与生还率有很大的关系,小孩生还的几率更大,这表明,年龄与生还率并不是简单的线性关系,这一点如果要给年龄切片做哑变量时会用到
进行简单的特征工程:
之所以称之为简单,是因为把一些看上去没什么用的特征直接删除了,比如Ticket以及Cabin,这两者都是看上去杂乱无章的。 - 对缺失值进行填充处理,可以用0填充,也可以用平均值,中位数等等,比如:
dataset[
'Title'] = dataset[
'Title'].fillna(
0)
#fillna()用来填充缺失值,此处用
0取代缺失值,也可以fillna(
'missing')
guess_ages = np.zeros((
2,
3))
#根据sex与pclass来对age进行更精确的填充
for dataset
in combine:
for i
in range(
0,
2):
for j
in range(
0,
3):
guess_df = dataset[(dataset[
'Sex'] == i) & \
(dataset[
'Pclass'] == j +
1)][
'Age'].dropna()
#dropna()用来删除缺失数据
# if(i==1)&(j==1):
# print guess_df
# age_mean = guess_df.mean() #平均值
# age_std = guess_df.std()#标准差
# age_guess = rnd.uniform(age_mean - age_std, age_mean + age_std) #给出随机数的最小值和最大值,随机生成中间值
age_guess = guess_df.median()
#中位数
# Convert random age float to nearest .5 age
guess_ages[i, j] =
int(age_guess /
0.5 +
0.5) *
0.5
for i
in range(
0,
2):
for j
in range(
0,
3):
dataset.loc[(dataset.Age.isnull()) & (dataset.Sex == i) & (dataset.Pclass == j +
1), \
'Age'] = guess_ages[i, j]
将连续的数字型特征离散化: 如何选择切割的点呢?可以简单粗暴地均分:
#对于age进行数字上的切割,将连续变幻的量变成离散值
train_df[
'AgeBand']=pd.cut(train_df[
'Age'],
5)
print train_df
[['AgeBand','Survived']].groupby([
'AgeBand'],as_index=False).mean().sort_values(by=
'AgeBand',ascending=True)
结果如下:
AgeBand Survived
0 (-0.08, 16] 0.550000
1 (16, 32] 0.337374
2 (32, 48] 0.412037
3 (48, 64] 0.434783
4 (64, 80] 0.090909
然后就可以为不同年龄段打上标签:
for dataset
in combine:
dataset.loc[dataset[
'Age']<=
16,
'Age']=
0
dataset.loc[(dataset[
'Age']>
16)&(dataset[
'Age']<=
32),
'Age']=
1
dataset.loc[(dataset[
'Age']>
32)&(dataset[
'Age']<=
48),
'Age']=
2
dataset.loc[(dataset[
'Age'] >
48) & (dataset[
'Age'] <=
64),
'Age'] =
3
dataset.loc[dataset[
'Age'] >
64,
'Age']=
4
可以做一些新的特征,比如将两个原有的特征相加:for dataset in combine: dataset['FamilySize']=dataset['SibSp']+dataset['Parch']+1 print train_df[['FamilySize','Survived']].groupby(['FamilySize'],as_index=False).\ mean().sort_values(by='Survived',ascending=False) 结果如下:
FamilySize Survived
3 4 0.724138
2 3 0.578431
1 2 0.552795
6 7 0.333333
0 1 0.303538
4 5 0.200000
5 6 0.136364
7 8 0.000000
8 11 0.000000
上图表明:新特征FamilySize为4时,生还的几率高达72%!最后根据此将乘客分为有家属和无家属两类; 最初的特征如下:
[
'PassengerId' 'Pclass' 'Name' 'Sex' 'Age' 'SibSp' 'Parch' 'Ticket' 'Fare' 'Cabin' 'Embarked']
最后的特征如下:
P
class Sex Age Fare Embarked Title IsAlone Age*Class
整个代码如下:
# -*- coding: utf-
8 -*-
#data analysis
and wrangling
import pandas as pd
import numpy as np
import random as rnd
#visualization
import seaborn as sns
import matplotlib.pyplot as plt
#machine learning
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC,LinearSVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import Perceptron #感知机
from sklearn.linear_model import SGDClassifier #随机梯度下降分类器
from sklearn.tree import DecisionTreeClassifier
#acquire data
train_df=pd.read_csv(
'/Users/apple/Desktop/titanic/train.csv')
test_df=pd.read_csv(
'/Users/apple/Desktop/titanic/test.csv')
combine=[train_df,test_df] #生成list
#analyze by describing data
print train_df.columns.values
print '_'*
40
print train_df.head() #展示头
5组数据,可以用tail展示最后
5组数据
print '_'*
40
print test_df.head()
print '_'*
40
print test_df.info()#用来查看数据的基本状态,有多少数据缺失
print '_'*
40
print train_df.describe()
print '_'*
40
print train_df.describe(include=[
'O'])#include=[
'O']用来描述categorical features,即都是字符串
print '_'*
40
#这种表格的方法适用于分类的种类比较少的(离散的)情况,如果是连续分布的(比如说年龄),那么用图来表示最靠谱
print train_df
[['Pclass','Survived']].groupby([
'Pclass'],as_index=False
).mean().sort_values(by=
'Survived',ascending=False)
print train_df
[['Sex','Survived']].groupby([
'Sex'],as_index=False
).mean().sort_values(by=
'Survived',ascending=False)
print train_df
[['SibSp','Survived']].groupby([
'SibSp'],as_index=False
).mean().sort_values(by=
'Survived',ascending=False)
print train_df
[['Parch','Survived']].groupby([
'Parch'],as_index=False
).mean().sort_values(by=
'Survived',ascending=False)
#利用直方图(histgram)可以用来看连续特征值对于结果的影响,bins用来调整展示密度
g = sns.FacetGrid(train_df, col=
'Survived')
g.map(plt.hist,
'Age', bins=
4)#bins指把数值区间分成几块
plt.show()
train_df = train_df.drop([
'Ticket',
'Cabin'], axis=
1)#默认的是删除行,axis=
1表示删除列
test_df = test_df.drop([
'Ticket',
'Cabin'], axis=
1)
combine = [train_df, test_df]
#为了查看名称
for dataset
in combine:
dataset[
'Title'] = dataset.Name.str.extract(
' ([A-Za-z]+)\.',expand=False)#expanf=True&False似乎没什么区别
print pd.crosstab(train_df[
'Title'], train_df[
'Sex'])
for dataset
in combine:
dataset[
'Title'] = dataset[
'Title'].replace([
'Lady',
'Countess',
'Capt',
'Col', \
'Don',
'Dr',
'Major',
'Rev',
'Sir',
'Jonkheer',
'Dona'],
'Rare')
dataset[
'Title'] = dataset[
'Title'].replace(
'Mlle',
'Miss')
dataset[
'Title'] = dataset[
'Title'].replace(
'Ms',
'Miss')
dataset[
'Title'] = dataset[
'Title'].replace(
'Mme',
'Mrs')
print train_df
[['Title', 'Survived']].groupby([
'Title'], as_index=False).mean().sort_values(by=
'Survived',ascending=False)
title_mapping = {
"Mr":
1,
"Miss":
2,
"Mrs":
3,
"Master":
4,
"Rare":
5}
for dataset
in combine:
dataset[
'Title'] = dataset[
'Title'].map(title_mapping)
dataset[
'Title'] = dataset[
'Title'].fillna(
0)#fillna()用来填充缺失值,此处用
0取代缺失值,也可以fillna(
'missing')
#
print train_df.head()
#将姓名与PassengerId这两个没用的属性删去:
train_df=train_df.drop([
'Name',
'PassengerId'],axis=
1)
test_df=test_df.drop([
'Name'],axis=
1)
combine=[train_df,test_df]
#
print train_df.shape,test_df.shape
#将一些文字的属性匹配成数字,因为大部分的算法只会处理数字,这也是在做特征工程
for dataset
in combine:
dataset[
'Sex']=dataset[
'Sex'].map({
'female':
1,
'male':
0}).astype(int)
#
print train_df.head()
guess_ages = np.zeros((
2,
3))
for dataset
in combine:
for i
in range(
0,
2):
for j
in range(
0,
3):
guess_df = dataset[(dataset[
'Sex'] == i) & \
(dataset[
'Pclass'] == j +
1)][
'Age'].dropna() #dropna()用来删除缺失数据
#
if(i==
1)&(j==
1):
#
print guess_df
# age_mean = guess_df.mean() #平均值
# age_std = guess_df.std()#标准差
# age_guess = rnd.uniform(age_mean - age_std, age_mean + age_std) #给出随机数的最小值和最大值,随机生成中间值
age_guess = guess_df.median() #中位数
# Convert random age float to nearest
.5 age
guess_ages[i, j] = int(age_guess /
0.5 +
0.5) *
0.5
for i
in range(
0,
2):
for j
in range(
0,
3):
dataset.loc[(dataset.Age.isnull()) & (dataset.Sex == i) & (dataset.Pclass == j +
1), \
'Age'] = guess_ages[i, j]
dataset[
'Age'] = dataset[
'Age'].astype(int)
#对于age进行数字上的切割,将连续变幻的量变成离散值
train_df[
'AgeBand']=pd.cut(train_df[
'Age'],
5)
print train_df
[['AgeBand','Survived']].groupby([
'AgeBand'],as_index=False).mean().sort_values(by=
'AgeBand',ascending=True)
#将不同区间的age打上编号
for dataset
in combine:
dataset.loc[dataset[
'Age']<=
16,
'Age']=
0
dataset.loc[(dataset[
'Age']>
16)&(dataset[
'Age']<=
32),
'Age']=
1
dataset.loc[(dataset[
'Age']>
32)&(dataset[
'Age']<=
48),
'Age']=
2
dataset.loc[(dataset[
'Age'] >
48) & (dataset[
'Age'] <=
64),
'Age'] =
3
dataset.loc[dataset[
'Age'] >
64,
'Age']=
4
#
print train_df.head()
#删除AgeBand栏
train_df=train_df.drop([
'AgeBand'],axis=
1)
combine=[train_df,test_df]
#
print train_df.head()
#将parch与sibsp两个特征合并,制作新的特征familysize
for dataset
in combine:
dataset[
'FamilySize']=dataset[
'SibSp']+dataset[
'Parch']+
1
#
print train_df
[['FamilySize','Survived']].groupby([
'FamilySize'],as_index=False).mean().\
# sort_values(by=
'Survived',ascending=False)
#create another feature called IsAlone
for dataset
in combine:
dataset[
'IsAlone']=
0
dataset.loc[dataset[
'FamilySize']==
1,
'IsAlone']=
1
#
print train_df
[['IsAlone','Survived']].groupby([
'IsAlone'],as_index=False).mean().\
# sort_values(by=
'Survived',ascending=False)
#drop Parch, SibSp,
and FamilySize features
in favor of IsAlone
train_df=train_df.drop([
'Parch',
'SibSp',
'FamilySize'],axis=
1)
test_df = test_df.drop([
'Parch',
'SibSp',
'FamilySize'], axis=
1)
combine=[train_df,test_df]
#
print train_df.head()
#We can also create an artificial feature combining Pclass
and Age.
for dataset
in combine:
dataset[
'Age*Class']=dataset.Age*dataset.Pclass
print train_df.loc[:,[
'Age*Class',
'Age',
'Pclass']].head(
10)#其中:的含义是从第一个到最后一个
#补充分类特征,因为Embarked只有两个缺失,所以直接使用最常见的来填充
freq_port=train_df.Embarked.dropna().mode()[
0]#mode是求众数!!!
#
print freq_port
for dataset
in combine:
dataset[
'Embarked']=dataset[
'Embarked'].fillna(freq_port)
#
print train_df
[['Embarked','Survived']].groupby([
'Embarked'],as_index=False).mean().\
# sort_values(by=
'Survived',ascending=False)
#Converting categorical feature to numeric
for dataset
in combine:
dataset[
'Embarked']=dataset[
'Embarked'].map({
'S':
0,
'C':
1,
'Q':
2}).astype(int)
#
print train_df.head()
#对于fare采用同样的处理,fare:连续值,不完整,用剩余的中位数进行填充
test_df[
'Fare'].fillna(test_df[
'Fare'].dropna().median(),inplace=True)
train_df[
'Fare'].fillna(train_df[
'Fare'].dropna().median(),inplace=True)#inplace参数的意思就是代替原来的变量,深拷贝
#
print train_df.head()
#像对于age一样,对于fare制造fareband
train_df[
'FareBand']=pd.qcut(train_df[
'Fare'],
4)#qcut是按照分位数进行划分的,以解决cut无法让所划分区间数量相等的问题
#
print train_df
[['FareBand','Survived']].groupby([
'FareBand'],as_index=False).\
# mean().sort_values(by=
'FareBand',ascending=True)
#将fare特征变化为离散的数字
for dataset
in combine:
dataset.loc[dataset[
'Fare']<=
7.91,
'Fare']=
0
dataset.loc[(dataset[
'Fare']>
7.91)&(dataset[
'Fare']<=
14.454),
'Fare']=
1
dataset.loc[(dataset[
'Fare'] >
14.454) & (dataset[
'Fare'] <=
31),
'Fare'] =
2
dataset.loc[dataset[
'Fare'] >
31,
'Fare'] =
3
dataset.Fare=dataset[
'Fare'].astype(int)
train_df = train_df.drop([
'FareBand'], axis=
1)
combine = [train_df, test_df]
print train_df.head()
print '_'*
40
print test_df.head()
print '_'*
40
X_train=train_df.drop(
'Survived',axis=
1)
Y_train=train_df.Survived
#
print X_train,Y_train
X_test=test_df.drop(
'PassengerId',axis=
1).copy()
#
print X_train.shape,Y_train.shape,X_test.shape
# Logistic Regression
logreg = LogisticRegression()
logreg.fit(X_train, Y_train)
Y_pred = logreg.predict(X_test)
acc_log = round(logreg.score(X_train, Y_train) *
100,
2)
print acc_log
使用Logistic Regression回归,训练值为81.26,测试值为76.56
对lg学习方法进行调整:
是否存在过拟合? 用lg时,测试值比训练值低了近5%,不由让人怀疑是不是发生了过拟合,一个比较常用的办法就是正则化:
penalty=
'l2'
penalty表示正则化,有l1与l2两种选择,默认为l2,两种结果类似:
l1(81
.14,76
.555)
l2(81.26,76.555)
其中()前者为训练数据,后者为预测数据,本文都采用这种模式。 实际上,l1与l2两种正则化各有特点,l1可以用来降维,即将一些系数降为0。 在lg中,C=1.0 也与正则化有关, C为正则化系数λ的倒数,必须为正数,默认为1。和SVM中的C一样,值越小,说明对模型的复杂度惩罚越大,就越不会过拟合。 下面补充以下,为什么λ越大,就能防止过拟合? 上图发生了过拟合,一种解决的办法是直接将x^3和x^4删去,但如果这两者也是特征的话,这样做就代表了特征的丢失;还有一种思路是对参数3和参数4进行惩罚,并且令两个参数很小,一个简单的办法就是给原有的Cost函数加上两个略大惩罚项,例如: 这样两个参数的值会很小,就避免了过拟合。
我这里有一个疑问: 可以给单独几个特征进行正则化处理吗?由上图可见,在lg中,是对所有特征用同一个λ进行正则化,但是实际中,可能有些特征是起决定作用的,我们不希望它被正则化,那该怎么操作?
对计算损失函数方法的选择: solver='liblinear' solver参数决定了我们对逻辑回归损失函数的优化方法,有四种算法可以选择:
从上面的描述可以看出,newton-cg、lbfgs和sag这三种优化算法时都需要损失函数的一阶或者二阶连续导数,因此不能用于没有连续导数的L1正则化,只能用于L2正则化。而liblinear通吃L1正则化和L2正则化。 同时,sag每次仅仅使用了部分样本进行梯度迭代,所以当样本量少的时候不要选择它,而如果样本量非常大,比如大于10万,sag是第一选择。但是sag不能用于L1正则化,所以当你有大量的样本,又需要L1正则化的话就要自己做取舍了。要么通过对样本采样来降低样本量,要么回到L2正则化。 但是liblinear也有自己的弱点!我们知道,逻辑回归有二元逻辑回归和多元逻辑回归。对于多元逻辑回归常见的有one-vs-rest(OvR)和many-vs-many(MvM)两种。而MvM一般比OvR分类相对准确一些。而liblinear只支持OvR,不支持MvM,这样如果我们需要相对精确的多元逻辑回归时,就不能选择liblinear了。也意味着如果我们需要相对精确的多元逻辑回归不能使用L1正则化了。 对此,我做了以下对比:
l2_c1_liblinear(81.26,76.555)l2_c1_lbfgs(81.37,76.555)
可见,虽然改变计算方法会给提升一点点测试集的准确率,但是对于测试集上的效果却没有什么改变,至此,我觉得应该换一种机器学习的方法了,我决定使用svm!
使用大名鼎鼎的svm算法!
svm名字由来:
在使用svm之前,先回答一个问题:什么是支持向量机? 由上图可以看到:两个支撑着中间的 gap 的超平面,它们到中间的纯红线separating hyper plane 的距离相等,即我们所能得到的最大的 geometrical margin,而“支撑”这两个超平面的必定会有一些点,而这些“支撑”的点便叫做支持向量Support Vector。 很显然,由于这些 supporting vector 刚好在边界上,所以它们满足,而对于所有不是支持向量的点,也就是在“阵地后方”的点,则显然有。这一点非常重要,因为在对损失函数增加拉格朗日算子时,得到的目标函数: 注意到如果 xi 是支持向量的话,上式中红颜色的部分是等于 0 的(因为支持向量的 functional margin 等于 1 ),而对于非支持向量来说,functional margin 会大于 1 ,因此红颜色部分是大于零的,而a又是非负的,为了满足最大化,必须等于 0 。这一点对使用核函数拟合非线性时非常重要,因为分类函数为: 所谓 Supporting Vector 也在这里显示出来——事实上,所有非Supporting Vector 所对应的系数都是等于零的,因此对于新点的内积计算实际上只要针对少量的“支持向量”而不是所有的训练数据即可。
首先使用svm中的linear核,结果如下:
svm_linear(78.68,76.555)
发现这个结果并没有比lg回归好,失望脸;
接下来使用svm中的RBF核(高斯核)
在svm中,使用核的目的是为了解决:维度灾难,作为最常用的svm核,从理论上讲, RBF一定不比线性核函数差,但是在实际应用中,却面临着几个重要的超参数的调优问题。如果调的不好,可能比线性核函数还要差,在享受RBF对非线性数据的良好分类效果前,我们需要对主要的超参数进行选取:惩罚系数C以及RBF核函数的系数γ: 一言以蔽之:c越大,gamma越小,越容易过拟合!
惩罚系数C 虽然svm有核函数这么一个杀手锏,但是对于异常值还是有点束手无策,在没有松弛系数的svm中,outlier对结果的影响很大,因为因为超平面本身就是只有少数几个 support vector 组成的,如果这些 support vector 里又存在 outlier 的话,其影响就很大了,如下图: 用黑圈圈起来的那个蓝点是一个 outlier ,它偏离了自己原本所应该在的那个半空间,如果直接忽略掉它的话,原来的分隔超平面还是挺好的,但是由于这个 outlier 的出现,导致分隔超平面不得不被挤歪了,变成途中黑色虚线所示(这只是一个示意图,并没有严格计算精确坐标),同时 margin 也相应变小了。当然,更严重的情况是,如果这个 outlier 再往右上移动一些距离的话,我们将无法构造出能将数据分开的超平面来。 为了处理这种情况,SVM 允许数据点在一定程度上偏离一下超平面。例如上图中,黑色实线所对应的距离,就是该 outlier 偏离的距离,如果把它移动回来,就刚好落在原来的超平面上,而不会使得超平面发生变形了,这就是松弛系数的由来。 原来的约束条件为: 考虑到outlier问题,约束条件变成了: 其中称为松弛变量 (slack variable) ,对应数据点xi允许偏离的 functional margin 的量。当然,如果我们将松弛变量任意大的话,那任意的超平面都是符合条件的了。所以,我们在原来的目标函数后面加上一项,使得这些松弛变量的总和也要最小: 其中C是一个参数,用于控制目标函数中两项(“寻找 margin 最大的超平面”和“保证数据点偏差量最小”)之间的权重。注意,其中 松弛变量是需要优化的变量(之一),而C是一个事先确定好的常量。 由上面的损失函数公式还可以看出:当C比较大时,我们的损失函数也会越大,这意味着我们不愿意放弃比较远的离群点。这样我们会有更加多的支持向量,也就是说支持向量和超平面的模型也会变得越复杂,也容易过拟合。反之,当C比较小时,意味我们不想理那些离群点,会选择较少的样本来做支持向量,最终的支持向量和超平面的模型也会简单。scikit-learn中默认值是1。跟RBF核函数有关的参数gamma: gamma是选择RBF函数作为kernel后,该函数自带的一个参数。隐含地决定了数据映射到新的特征空间后的分布,gamma越大,支持向量越少,gamma值越小,支持向量越多。支持向量的个数影响训练与预测的速度。 此外大家注意RBF公式里面的sigma和gamma的关系如下: 这里面需要注意的就是gamma的物理意义,原博客的理解:如果gamma设的太大,sigma会很小,sigma很小的高斯分布长得又高又瘦, 会造成只会作用于支持向量样本附近,对于未知样本分类效果很差,存在训练准确率可以很高,(如果让无穷小,则理论上,高斯核的SVM可以拟合任何非线性数据,但容易过拟合)而测试准确率不高的可能,就是通常说的过训练;而如果设的过小,则会造成平滑效应太大,无法在训练集上得到特别高的准确率,也会影响测试集的准确率。进行测试: Grid Search是用在Libsvm中的参数搜索方法。很容易理解:就是在C,gamma组成的二维参数矩阵中,依次实验每一对参数的效果。 进行调参的代码:
svc = SVC(kernel=
'rbf', probability=
True)
param_grid = {
'C': [
1500,
1600,
1700,
1800,
1900],
'gamma': [
0.002,
0.003,
0.004,
0.005,
0.006]}
grid_search = GridSearchCV(svc, param_grid, n_jobs=-
1, verbose=
True)
grid_search.fit(X_train, Y_train)
best_parameters = grid_search.best_estimator_.get_params()
print '_'*
40
for para, val in
list(best_parameters.items()):
print(para, val)
print '_'*
40
model = SVC(kernel=
'rbf', C=best_parameters[
'C'], gamma=best_parameters[
'gamma'], probability=
True)
model.fit(X_train, Y_train)
acc_svc = round(model.score(X_train, Y_train) *
100,
2)
print acc_svc
结果如下:
Fitting
3 folds
for each of 25 candidates, totalling
75 fits
[
Parallel(n_jobs=-
1)]: Done
42 tasks | elapsed:
7.0s
[
Parallel(n_jobs=-
1)]: Done
75 out of 75 | elapsed:
13.3s finished
________________________________________
(
'kernel',
'rbf')
(
'C',
1500)
#
set the parameter C
of C-SVC,epsilon-SVR,
and nu-SVR (
default 1)
(
'verbose',
False)
(
'probability',
True)
(
'degree',
3)
(
'shrinking',
True)
# whether
to use the shrinkingheuristics(启发式),
0 or 1 (
default 1)
(
'max_iter', -
1)
(
'decision_function_shape', None)
(
'random_state', None)
(
'tol',
0.001)
(
'cache_size',
200)
(
'coef0',
0.0)
(
'gamma',
0.004)
#
set gamma
in kernel
function(default 1/num_features)
('class_weight', None)
________________________________________
83.61
虽然c高达1500,但是测试结果为79.426%,比c=1时的结果(77.99)要高出近1.5%!
在下一篇中,我将更换另外的几个常用机器学习方法,最后做一些特征工程,提高准确率~