1 导入数据,探索数据

  1. import pandas as pd
  2. import numpy as np
  3. from sklearn.model_selection import train_test_split
  4. weather = pd.read_csv(r"C:\Users\18700\Desktop\08支持向量机下\weatherAUS5000.csv",index_col=0)
  5. weather.head() #默认查看前5行

机器学习:13--SVM案例:明天会下雨吗? - 图1

  1. #将特征矩阵和标签Y分开
  2. X = weather.iloc[:,:-1]
  3. Y = weather.iloc[:,-1]
  4. X.shape
  5. #探索数据类型 查看缺失
  6. X.info()
  7. #探索缺失值
  8. X.isnull().mean() #.mean()可以直接查看缺失值占总值的比例 isnull().sum(全部的True)/X.shape[0]
  9. #可以看到需要不同的填补策略

输出结果

  1. Date 0.0000
  2. Location 0.0000
  3. MinTemp 0.0042
  4. MaxTemp 0.0026
  5. Rainfall 0.0100
  6. Evaporation 0.4318
  7. Sunshine 0.4858
  8. WindGustDir 0.0662
  9. WindGustSpeed 0.0662
  10. WindDir9am 0.0698
  11. WindDir3pm 0.0226
  12. WindSpeed9am 0.0102
  13. WindSpeed3pm 0.0162
  14. Humidity9am 0.0128
  15. Humidity3pm 0.0240
  16. Pressure9am 0.0988
  17. Pressure3pm 0.0992
  18. Cloud9am 0.3778
  19. Cloud3pm 0.3976
  20. Temp9am 0.0066
  21. Temp3pm 0.0176
  22. dtype: float64
  1. Y.isnull().sum() #返回要不是0,就是有空值
  2. #探索标签的分类
  3. np.unique(Y) #可以看到标签是二分类

2 分集,优先探索标签

分训练集和测试集,并做描述性统计

  1. #分训练集和测试集
  2. Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,Y,test_size=0.3,random_state=420)
  3. #恢复索引
  4. for i in [Xtrain, Xtest, Ytrain, Ytest]:
  5. i.index = range(i.shape[0])

先看标签是否存在问题

  1. #是否有样本不平衡问题?
  2. Ytrain.value_counts() #查看
  3. Ytest.value_counts()
  4. #可以看到有轻微的样本不均衡问题
  5. #将标签编码
  6. from sklearn.preprocessing import LabelEncoder #标签专用,第三章讲过
  7. encorder = LabelEncoder().fit(Ytrain) #LabelEncoder允许一维数据输入
  8. #构成的模型认得了:有两类:YES和NO,YES是1,NO是0,因为YES是少数类
  9. #使用训练集进行训练,然后在训练集和测试集上分别进行transform:相当是用训练集的训练结果分别对测试集和训练集进行改造
  10. Ytrain = pd.DataFrame(encorder.transform(Ytrain)) #将Ytrain转换维0,1,然后放回到Ytrain中
  11. Ytest = pd.DataFrame(encorder.transform(Ytest))
  12. #如果测试集中出现了训练集中没有出现过的标签类型,比如unkown,这时LabelEncoder就会报错。
  13. #如果报错就要重新分训练集和测试集
  14. Ytrain
  15. #Ytrian.to_csv("想要保存的地址.文件名.csv") #一般先将标签保存了,再去做其它的操作

机器学习:13--SVM案例:明天会下雨吗? - 图2
机器学习:13--SVM案例:明天会下雨吗? - 图3

3 探索特征,开始处理特征矩阵

3.1 描述性统计和异常值

  1. #描述性统计 通过观察最小值和1%,最大值和99%值之间的差异,可以判断出是否有数据偏差和异常值
  2. Xtrain.describe([0.01,0.05,0.1,0.25,0.5,0.75,0.9,0.99]).T
  3. Xtest.describe([0.01,0.05,0.1,0.25,0.5,0.75,0.9,0.99]).T

机器学习:13--SVM案例:明天会下雨吗? - 图4

3.2 处理异常值思路

  1. #处理异常值思路:如果有异常值,需要先看异常值出现的频率,如果只有一次,多半时输入错误,这种情况,直接删除;
  2. #如果出现多次,需要和业务人员沟通。人为造成的异常值时没有用的,需要删除。
  3. #有时异常值很多10%以上,我需要将异常值替换成非干扰项:比如用0或者把异常值当缺失值,用均值或者众数来填补。
  4. #先查看原始的数据结构
  5. Xtrain.shape
  6. Xtest.shape
  7. #观察异常值是大量存在,还是少数存在
  8. Xtrain.loc[Xtrain.loc[:,"Cloud9am"] == 9,"Cloud9am"]
  9. Xtest.loc[Xtest.loc[:,"Cloud9am"] == 9,"Cloud9am"]
  10. Xtest.loc[Xtest.loc[:,"Cloud3pm"] == 9,"Cloud3pm"]
  11. #少数存在,于是采取删除的策略
  12. #注意如果删除特征矩阵,则必须连对应的标签一起删除,特征矩阵的行和标签的行必须要一一对应
  13. Xtrain = Xtrain.drop(index = 71737)
  14. Ytrain = Ytrain.drop(index = 71737)
  15. #删除完毕之后,观察原始的数据结构,确认删除正确
  16. Xtrain.shape
  17. Xtest = Xtest.drop(index = [19646,29632])
  18. Ytest = Ytest.drop(index = [19646,29632])
  19. Xtest.shape
  20. #进行任何行删除之后,千万记得要恢复索引
  21. for i in [Xtrain, Xtest, Ytrain, Ytest]:
  22. i.index = range(i.shape[0])
  23. Xtrain.head()
  24. Xtest.head()

3.3 首先处理困难特征:日期

  1. #处理困难特征日期
  2. type(Xtrain.iloc[0,0]) #字符串
  3. #首先需要探索日期时连续性还是分类型特征
  4. #日期是一年分了365类的分类型变量
  5. #判断日期中是否有重复,
  6. Xtrain.iloc[:,0].value_counts() #日期不是连续型,是有重复的

机器学习:13--SVM案例:明天会下雨吗? - 图5

  1. Xtrain.iloc[:,0].value_counts().count()
  2. #2141
  3. ##如果我们把它当作分类型变量处理,类别太多,有2141类,如果换成数值型,会被直接当成连续型变量,如果做成哑变量,我们特征的维度会爆炸
  4. #所以日期不能单纯的当作连续型或者分类型,所以如果认为没有用的话,可以删除
  5. #Xtrain = Xtrain.drop(["Date"],axis=1)
  6. #Xtest = Xtest.drop(["Date"],axis=1)

3.3.1 将样本对应标签之间的联系,转换成是特征与标签之间的联系

  1. Xtrain["Rainfall"].head(20)
  2. #通过描述性表格可以看下,可以设置大于1mm就是下雨了
  3. Xtrain["Rainfall"].isnull().sum() #可以看到有空值
  4. Xtrain.loc[Xtrain["Rainfall"] >= 1,"RainToday"] = "Yes" #因为没有这一列RainToday,会自己添加
  5. Xtrain.loc[Xtrain["Rainfall"] < 1,"RainToday"] = "No"
  6. Xtrain.loc[Xtrain["Rainfall"] == np.nan,"RainToday"] = np.nan #将空值就赋值空值
  7. Xtest.loc[Xtest["Rainfall"] >= 1,"RainToday"] = "Yes"
  8. Xtest.loc[Xtest["Rainfall"] < 1,"RainToday"] = "No"
  9. Xtest.loc[Xtest["Rainfall"] == np.nan,"RainToday"] = np.nan
  10. Xtrain.head()

机器学习:13--SVM案例:明天会下雨吗? - 图6

  1. Xtrain.loc[:,"RainToday"].value_counts()
  2. Xtest.head()
  3. Xtest.loc[:,"RainToday"].value_counts()

输出结果

  1. No 2642
  2. Yes 825
  3. Name: RainToday, dtype: int64

3.3.2 创造第二个特征month

  1. int(Xtrain.loc[0,"Date"].split("-")[1]) #提取出一个月份 int就是将提取的月份字符元素变为整数
  2. Xtrain["Date"] = Xtrain["Date"].apply(lambda x:int(x.split("-")[1]))
  3. #apply是对dataframe上某一列进行处理的一个函数
  4. #lambda 是匿名函数,lambda x是请在dataframe上这一列中的每一行执行冒号后面的命令
  5. Xtrain.loc[:,"Date"].value_counts() #可以看到变成了12个数字的分类型变量

输出结果

  1. 3 334
  2. 5 324
  3. 7 316
  4. 9 302
  5. 6 302
  6. 1 300
  7. 11 299
  8. 10 282
  9. 4 265
  10. 2 264
  11. 12 259
  12. 8 253
  13. Name: Date, dtype: int64
  1. #替换完毕后,我们需要修改列的名称
  2. #rename是比较少有的,可以用来修改单个列名的函数
  3. #我们通常都直接使用 df.columns = 某个列表 这样的形式来一次修改所有的列名
  4. #但rename允许我们只修改某个单独的列
  5. Xtrain = Xtrain.rename(columns={"Date":"Month"}) #里面是一个字典
  6. Xtrain.head()

机器学习:13--SVM案例:明天会下雨吗? - 图7

  1. #所有的操作要在测试集也运行下
  2. Xtest["Date"] = Xtest["Date"].apply(lambda x:int(x.split("-")[1]))
  3. Xtest = Xtest.rename(columns={"Date":"Month"})
  4. Xtest.head()

3.4 处理困难特征:地点

  1. Xtrain.loc[:,"Location"].value_counts().count() #超过25个类别的变量,都会被算法当成连续性变量,所以现在用地点分是不行的
  2. #49
  3. #我们有了澳大利亚全国主要城市的气候,也有了澳大利亚主要城市的经纬度(地点),我们就可以通过计算我们样
  4. #本中的每个气候站到各个主要城市的地理距离,来找出一个离这个气象站最近的主要城市,而这个主要城市的气候
  5. #就是我们样本点所在的地点的气候。
  6. #让我们把cityll.csv和cityclimate.csv来导入,来看看它们是什么样子:
  7. cityll = pd.read_csv(r"C:\Users\18700\Desktop\08支持向量机下\cityll.csv",index_col=0)
  8. city_climate = pd.read_csv(r"C:\Users\18700\Desktop\08支持向量机下\Cityclimate.csv")
  9. cityll.head() #每个城市对应的经纬度,是澳大利亚地图上的城市
  10. city_climate.head() #是每个城市的气候

机器学习:13--SVM案例:明天会下雨吗? - 图8

  1. #去掉度数符号
  2. cityll["Latitudenum"] = cityll["Latitude"].apply(lambda x:float(x[:-1])) #x[:-1]对纬度进行切片
  3. cityll["Longitudenum"] = cityll["Longitude"].apply(lambda x:float(x[:-1]))
  4. cityll.head()

机器学习:13--SVM案例:明天会下雨吗? - 图9

  1. #观察一下所有的经纬度方向都是一致的,全部是南纬,东经,因为澳大利亚在南半球,东半球,所以经纬度的方向我们可以舍弃了
  2. citylld = cityll.iloc[:,[0,5,6]] #取出城市名称和经纬度
  3. #将city_climate中的气候添加到我们的citylld中
  4. citylld["climate"] = city_climate.iloc[:,-1]
  5. citylld.head()

机器学习:13--SVM案例:明天会下雨吗? - 图10

  1. #看下爬虫下来的训练集中所有地点的表格:
  2. samplecity = pd.read_csv(r"C:\Users\18700\Desktop\08支持向量机下\samplecity.csv",index_col=0)
  3. samplecity.head()
  4. #我们对samplecity也执行同样的处理:去掉经纬度中度数的符号,并且舍弃我们的经纬度的方向
  5. samplecity["Latitudenum"] = samplecity["Latitude"].apply(lambda x:float(x[:-1]))
  6. samplecity["Longitudenum"] = samplecity["Longitude"].apply(lambda x:float(x[:-1]))
  7. samplecityd = samplecity.iloc[:,[0,5,6]]
  8. samplecityd.head()
  9. #我们现在有了澳大利亚主要城市的经纬度和对应的气候,也有了我们的样本的地点所对应的经纬度,接下来
  10. #我们要开始计算我们样本上的地点到每个澳大利亚主要城市的距离
  11. #首先使用radians将角度转换成弧度
  12. from math import radians, sin, cos, acos
  13. citylld.loc[:,"slat"] = citylld.iloc[:,1].apply(lambda x : radians(x)) #将维度准换维为弧度
  14. citylld.loc[:,"slon"] = citylld.iloc[:,2].apply(lambda x : radians(x))
  15. samplecityd.loc[:,"elat"] = samplecityd.iloc[:,1].apply(lambda x : radians(x))
  16. samplecityd.loc[:,"elon"] = samplecityd.iloc[:,2].apply(lambda x : radians(x))
  17. samplecityd.head()
  18. citylld.head()

机器学习:13--SVM案例:明天会下雨吗? - 图11

  1. #查看气候的分布
  2. samplecityd["climate"].value_counts()
  3. #确认无误后,取出样本城市所对应的气候,并保存
  4. locafinal = samplecityd.iloc[:,[0,-1]]
  5. locafinal.columns = ["Location","Climate"]
  6. locafinal.head()
  7. #在这里设定locafinal的索引为地点,是为了之后进行map的匹配
  8. locafinal = locafinal.set_index(keys="Location")
  9. locafinal.head()
  10. #locafinal.to_csv(r"C:\work\learnbetter\micro-class\week 8 SVM (2)\samplelocation.csv") #然后将其保存
  11. #将location中的内容替换,并且确保匹配进入的气候字符串中不含有逗号,气候两边不含有空格
  12. #我们使用re这个模块来消除逗号
  13. #re.sub(希望替换的值,希望被替换成的值,要操作的字符串)
  14. #x.strip()是去掉空格的函数,将两边的空值都去掉
  15. import re
  16. Xtrain["Location"] = Xtrain["Location"].map(locafinal.iloc[:,0]).apply(lambda x:re.sub(",","",x.strip()))
  17. Xtest["Location"] = Xtest["Location"].map(locafinal.iloc[:,0]).apply(lambda x:re.sub(",","",x.strip()))
  18. #修改特征内容之后,我们使用新列名“Climate”来替换之前的列名“Location”
  19. #注意这个命令一旦执行之后,就再没有列"Location"了,使用索引时要特别注意
  20. Xtrain = Xtrain.rename(columns={"Location":"Climate"})
  21. Xtest = Xtest.rename(columns={"Location":"Climate"})
  22. Xtrain.head()
  23. Xtest.head()#这时地点就变成了气候,并且只有7个气候的分类文字型特征

机器学习:13--SVM案例:明天会下雨吗? - 图12

4 处理分类型变量:缺失值

在实际过程中,测试集和训练集的数据分布和性质都是相似的,因此我们统一使用训练集的众数和均值来对测试集进行填补。

  1. #查看缺失值的缺失情况
  2. Xtrain.isnull().mean()
  3. Month 0.000000
  4. Climate 0.000000
  5. MinTemp 0.004000
  6. MaxTemp 0.003143
  7. Rainfall 0.009429
  8. Evaporation 0.433429
  9. Sunshine 0.488571
  10. WindGustDir 0.067714
  11. WindGustSpeed 0.067714
  12. WindDir9am 0.067429
  13. WindDir3pm 0.024286
  14. WindSpeed9am 0.009714
  15. WindSpeed3pm 0.018000
  16. Humidity9am 0.011714
  17. Humidity3pm 0.026286
  18. Pressure9am 0.098857
  19. Pressure3pm 0.098857
  20. Cloud9am 0.379714
  21. Cloud3pm 0.401429
  22. Temp9am 0.005429
  23. Temp3pm 0.019714
  24. RainToday 0.009429
  25. dtype: float64

首先找出分类特征

  1. #首先找出,分类型特征都有哪些
  2. cate = Xtrain.columns[Xtrain.dtypes == "object"].tolist()
  3. cate
  4. #除了特征类型为"object"的特征们,还有虽然用数字表示,但是本质为分类型特征的云层遮蔽程度
  5. cloud = ["Cloud9am","Cloud3pm"]
  6. cate = cate + cloud
  7. cate
  8. #输出结果
  9. ['Climate',
  10. 'WindGustDir',
  11. 'WindDir9am',
  12. 'WindDir3pm',
  13. 'RainToday',
  14. 'Cloud9am',
  15. 'Cloud3pm']

对于分类数据,使用众数来进行填补

  1. #对于分类型特征,我们使用众数来进行填补
  2. from sklearn.impute import SimpleImputer
  3. si = SimpleImputer(missing_values=np.nan,strategy="most_frequent") #实例化
  4. #注意,我们使用训练集数据来训练我们的填补器,本质是在生成训练集中的众数
  5. si.fit(Xtrain.loc[:,cate]) #在分类数据上进行训练
  6. #然后我们用训练集中的众数来同时填补训练集和测试集
  7. Xtrain.loc[:,cate] = si.transform(Xtrain.loc[:,cate])
  8. Xtest.loc[:,cate] = si.transform(Xtest.loc[:,cate])
  9. Xtrain.head()
  10. Xtest.head()
  1. #查看分类型特征是否依然存在缺失值
  2. Xtrain.loc[:,cate].isnull().mean() #可以看到已经没有缺失值了
  3. #输出结果
  4. Climate 0.0
  5. WindGustDir 0.0
  6. WindDir9am 0.0
  7. WindDir3pm 0.0
  8. RainToday 0.0
  9. Cloud9am 0.0
  10. Cloud3pm 0.0
  11. dtype: float64

处理分类型变量,将分类型变量编码

  1. #将所有的分类型变量编码为数字,一个类别是一个数字
  2. from sklearn.preprocessing import OrdinalEncoder #只允许二维以上的数据输入的编码的类,区别于labelenconder
  3. oe = OrdinalEncoder()
  4. #利用训练集进行fit
  5. oe = oe.fit(Xtrain.loc[:,cate])
  6. #用训练集的编码结果来编码训练和测试特征矩阵
  7. #在这里如果测试特征矩阵报错,就说明测试集中出现了训练集中从未见过的类别
  8. Xtrain.loc[:,cate] = oe.transform(Xtrain.loc[:,cate])
  9. Xtest.loc[:,cate] = oe.transform(Xtest.loc[:,cate])
  10. Xtrain.loc[:,cate].head()
  11. Xtest.loc[:,cate].head()

机器学习:13--SVM案例:明天会下雨吗? - 图13

5 处理连续性变量

1 填补缺失值

  1. col = Xtrain.columns.tolist()#取出所有列的名称
  2. col
  3. for i in cate:
  4. col.remove(i) #提出分类型列的名称
  5. col
  6. #实例化模型,填补策略为"mean"表示均值
  7. impmean = SimpleImputer(missing_values=np.nan,strategy = "mean")
  8. #用训练集来fit模型
  9. impmean = impmean.fit(Xtrain.loc[:,col])
  10. #分别在训练集和测试集上进行均值填补
  11. Xtrain.loc[:,col] = impmean.transform(Xtrain.loc[:,col])
  12. Xtest.loc[:,col] = impmean.transform(Xtest.loc[:,col])
  13. Xtrain.head()
  14. Xtest.head()
  15. Xtrain.isnull().mean() #可以看到已经没有缺失值了
  16. Xtest.isnull().mean() #可以看到已经没有缺失值了

输出结果

  1. Month 0.0
  2. Climate 0.0
  3. MinTemp 0.0
  4. MaxTemp 0.0
  5. Rainfall 0.0
  6. Evaporation 0.0
  7. Sunshine 0.0
  8. WindGustDir 0.0
  9. WindGustSpeed 0.0
  10. WindDir9am 0.0
  11. WindDir3pm 0.0
  12. WindSpeed9am 0.0
  13. WindSpeed3pm 0.0
  14. Humidity9am 0.0
  15. Humidity3pm 0.0
  16. Pressure9am 0.0
  17. Pressure3pm 0.0
  18. Cloud9am 0.0
  19. Cloud3pm 0.0
  20. Temp9am 0.0
  21. Temp3pm 0.0
  22. RainToday 0.0
  23. dtype: float64

2 处理连续性变量:无量纲化
数据的无量纲化是SVM执行前的重要步骤,因此我们需要对数据进行无量纲化。但注意,这个操作我们不对分类型变量进行。

  1. col.remove("Month") #因为不想把month也归一化
  2. col
  3. from sklearn.preprocessing import StandardScaler #把数据转换为均值为0,方差为1的数据;
  4. #标准化不改变数据的分布,不会把数据变成正态分布
  5. ss = StandardScaler()
  6. ss = ss.fit(Xtrain.loc[:,col])
  7. Xtrain.loc[:,col] = ss.transform(Xtrain.loc[:,col])
  8. Xtest.loc[:,col] = ss.transform(Xtest.loc[:,col])
  9. Xtrain.head()
  10. Xtest.head()

机器学习:13--SVM案例:明天会下雨吗? - 图14

6 建模和模型评估

  1. from time import time #随时监控运行时间
  2. import datetime
  3. from sklearn.svm import SVC
  4. from sklearn.model_selection import cross_val_score
  5. from sklearn.metrics import roc_auc_score, recall_score
  6. Ytrain = Ytrain.iloc[:,0].ravel() #需要将二维变为一维结构,如果是通过实现保存的csv导入的话
  7. Ytest = Ytest.iloc[:,0].ravel()
  8. #建模选择自然是我们的支持向量机SVC,首先用核函数的学习曲线来选择核函数
  9. #我们希望同时观察,精确性,recall以及AUC分数
  10. times = time() #因为SVM是计算量很大的模型,所以我们需要时刻监控我们的模型运行时间
  11. for kernel in ["linear","poly","rbf","sigmoid"]:
  12. clf = SVC(kernel = kernel
  13. ,gamma="auto"
  14. ,degree = 1
  15. ,cache_size = 5000
  16. ).fit(Xtrain, Ytrain)
  17. result = clf.predict(Xtest) #首先获取模型结果
  18. score = clf.score(Xtest,Ytest) #接口socre返回accuracy
  19. recall = recall_score(Ytest, result) #得到召回得分 输入(真实值,预测值)
  20. auc = roc_auc_score(Ytest,clf.decision_function(Xtest)) #得到auc(真实值,置信度)
  21. print("%s 's testing accuracy %f, recall is %f', auc is %f" % (kernel,score,recall,auc))
  22. print(datetime.datetime.fromtimestamp(time()-times).strftime("%M:%S:%f"))

机器学习:13--SVM案例:明天会下雨吗? - 图15

7 模型调参

1 要求最高recall

  1. #首先可以打开我们的class_weight参数,使用balanced模式来调节我们的recall:
  2. times = time()
  3. for kernel in ["linear","poly","rbf","sigmoid"]:
  4. clf = SVC(kernel = kernel
  5. ,gamma="auto"
  6. ,degree = 1
  7. ,cache_size = 5000
  8. ,class_weight = "balanced"
  9. ).fit(Xtrain, Ytrain)
  10. result = clf.predict(Xtest)
  11. score = clf.score(Xtest,Ytest)
  12. recall = recall_score(Ytest, result)
  13. auc = roc_auc_score(Ytest,clf.decision_function(Xtest))
  14. print("%s 's testing accuracy %f, recall is %f', auc is %f" % (kernel,score,recall,auc))
  15. print(datetime.datetime.fromtimestamp(time()-times).strftime("%M:%S:%f"))
  16. #可以看到recall明显提升了,并且线性核最好

输出结果

  1. linear 's testing accuracy 0.796667, recall is 0.775510', auc is 0.870062
  2. 00:18:704683
  3. poly 's testing accuracy 0.793333, recall is 0.763848', auc is 0.871448
  4. 00:21:757529
  5. rbf 's testing accuracy 0.803333, recall is 0.600583', auc is 0.819713
  6. 00:30:587768
  7. sigmoid 's testing accuracy 0.562000, recall is 0.282799', auc is 0.437119
  8. 00:35:731341
  1. # 在锁定了线性核函数之后,我甚至可以将class_weight调节得更加倾向于少数类
  2. times = time()
  3. clf = SVC(kernel = "linear"
  4. ,gamma="auto"
  5. ,cache_size = 5000
  6. ,class_weight = {1:10} #注意,这里写的其实是,类别1比例是10,隐藏了类别0:1,类别0比例是1
  7. ).fit(Xtrain, Ytrain)
  8. result = clf.predict(Xtest)
  9. score = clf.score(Xtest,Ytest)
  10. recall = recall_score(Ytest, result)
  11. auc = roc_auc_score(Ytest,clf.decision_function(Xtest))
  12. print("testing accuracy %f, recall is %f', auc is %f" % (score,recall,auc))
  13. print(datetime.datetime.fromtimestamp(time()-times).strftime("%M:%S:%f"))
  14. #此时我们的目的就是追求一个比较高的AUC分数和比较好的recall,那我们的模型此时就算是很不错了

输出结果

  1. testing accuracy 0.636667, recall is 0.912536', auc is 0.866360
  2. 00:33:176004

2 追求平衡

  1. #我们前面经历了多种尝试,选定了线性核,并发现调节class_weight并不能够使我们模型有较大的改善。现在我们
  2. #来试试看调节线性核函数的C值能否有效果:
  3. #需要运行很久
  4. import matplotlib.pyplot as plt
  5. C_range = np.linspace(0.01,20,10)
  6. recallall = []
  7. aucall = []
  8. scoreall = []
  9. for C in C_range:
  10. times = time()
  11. clf = SVC(kernel = "linear",C=C,cache_size = 5000
  12. ,class_weight = "balanced"
  13. ).fit(Xtrain, Ytrain)
  14. result = clf.predict(Xtest)
  15. score = clf.score(Xtest,Ytest)
  16. recall = recall_score(Ytest, result)
  17. auc = roc_auc_score(Ytest,clf.decision_function(Xtest))
  18. recallall.append(recall)
  19. aucall.append(auc)
  20. scoreall.append(score)
  21. print("under C %f, testing accuracy is %f,recall is %f', auc is %f" % (C,score,recall,auc))
  22. print(datetime.datetime.fromtimestamp(time()-times).strftime("%M:%S:%f"))
  23. print(max(aucall),C_range[aucall.index(max(aucall))])
  24. plt.figure()
  25. plt.plot(C_range,recallall,c="red",label="recall")
  26. plt.plot(C_range,aucall,c="black",label="auc")
  27. plt.plot(C_range,scoreall,c="orange",label="accuracy")
  28. plt.legend()
  29. plt.show()

输出结果

  1. under C 0.010000, testing accuracy is 0.800000,recall is 0.752187', auc is 0.870634
  2. 00:02:383540
  3. under C 1.062105, testing accuracy is 0.796000,recall is 0.775510', auc is 0.870009
  4. 00:18:778634
  5. under C 2.114211, testing accuracy is 0.794000,recall is 0.772595', auc is 0.870178
  6. 00:32:681368
  7. under C 3.166316, testing accuracy is 0.795333,recall is 0.772595', auc is 0.870158
  8. 00:45:965365
  9. under C 4.218421, testing accuracy is 0.795333,recall is 0.772595', auc is 0.870153
  10. 01:00:687411
  11. under C 5.270526, testing accuracy is 0.795333,recall is 0.772595', auc is 0.870128
  12. 01:13:145664
  13. under C 6.322632, testing accuracy is 0.796000,recall is 0.775510', auc is 0.870060
  14. 01:15:696609
  15. under C 7.374737, testing accuracy is 0.795333,recall is 0.772595', auc is 0.870029
  16. 01:36:831459
  17. under C 8.426842, testing accuracy is 0.796000,recall is 0.775510', auc is 0.870130
  18. 01:48:398771
  19. under C 9.478947, testing accuracy is 0.795333,recall is 0.772595', auc is 0.870092
  20. 01:55:052874
  21. under C 10.531053, testing accuracy is 0.795333,recall is 0.772595', auc is 0.870110
  22. 02:16:715196
  23. under C 11.583158, testing accuracy is 0.795333,recall is 0.772595', auc is 0.870095
  24. 02:15:012162
  25. under C 12.635263, testing accuracy is 0.795333,recall is 0.772595', auc is 0.870075
  26. 02:44:417261

用最佳的C来运行

  1. #用最佳的C来运行
  2. times = time()
  3. clf = SVC(kernel = "linear",C=3.1663157894736838,cache_size = 5000
  4. ,class_weight = "balanced"
  5. ).fit(Xtrain, Ytrain)
  6. result = clf.predict(Xtest)
  7. score = clf.score(Xtest,Ytest)
  8. recall = recall_score(Ytest, result)
  9. auc = roc_auc_score(Ytest,clf.decision_function(Xtest))
  10. print("testing accuracy %f,recall is %f', auc is %f" % (score,recall,auc))
  11. print(datetime.datetime.fromtimestamp(time()-times).strftime("%M:%S:%f"))
  12. #可以看到,这种情况下模型的准确率,Recall和AUC都没有太差,但是也没有太好,这也许就是模型平衡后的一种结果。
  13. #输出结果
  14. testing accuracy 0.795333,recall is 0.772595', auc is 0.870158
  15. 00:45:282936
  1. ##要想让AUC面积更进一步,我们需要绘制ROC曲线,查看我们是否可以通过调整阈值来对这个模型进行改进。
  2. from sklearn.metrics import roc_curve as ROC
  3. import matplotlib.pyplot as plt
  4. FPR, Recall, thresholds = ROC(Ytest,clf.decision_function(Xtest),pos_label=1) #(真实值,置信度,正样本是1)
  5. area = roc_auc_score(Ytest,clf.decision_function(Xtest))
  6. plt.figure()
  7. plt.plot(FPR, Recall, color='red',
  8. label='ROC curve (area = %0.2f)' % area)
  9. plt.plot([0, 1], [0, 1], color='black', linestyle='--')
  10. plt.xlim([-0.05, 1.05])
  11. plt.ylim([-0.05, 1.05])
  12. plt.xlabel('False Positive Rate')
  13. plt.ylabel('Recall')
  14. plt.title('Receiver operating characteristic example')
  15. plt.legend(loc="lower right")
  16. plt.show()

机器学习:13--SVM案例:明天会下雨吗? - 图16

以此模型为基础,求解最佳阈值

  1. maxindex = (Recall - FPR).tolist().index(max(Recall - FPR)) #先找出插值最大的点的索引
  2. thresholds[maxindex] #然后查看这个值
  3. #基于我们选出的最佳阈值,我们来认为确定y_predict,并确定在这个阈值下的recall和准确度的值:
  4. from sklearn.metrics import accuracy_score as AC
  5. times = time()
  6. clf = SVC(kernel = "linear",C=3.1663157894736838,cache_size = 5000
  7. ,class_weight = "balanced"
  8. ).fit(Xtrain, Ytrain)
  9. prob = pd.DataFrame(clf.decision_function(Xtest))
  10. prob.head()
  11. prob.loc[prob.iloc[:,0] >= thresholds[maxindex],"y_pred"]=1 #判断>置信度的为1,并添加到y_pred。
  12. prob.loc[prob.iloc[:,0] < thresholds[maxindex],"y_pred"]=0
  13. prob.head()

机器学习:13--SVM案例:明天会下雨吗? - 图17