ccc-sklearn-10-SVM(4)

2023-10-25 08:20
文章标签 ccc svm sklearn

本文主要是介绍ccc-sklearn-10-SVM(4),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.SVC的其他考虑

SVC处理多分类问题:参数decision_function_shape
支持向量机是天在生二分类的模型,所以支持向量机在处理多分类问题的时候,是把多分类问题转换成了二分类问题来解决。这种转换有两种模式,一种叫做“一对一”模式(one vs one),一种叫做“一对多”模式(one vs rest)。
在这里插入图片描述
ovo模式下,标签中的所有类别会被两两组合,每两个类别之间建一个SVC模型,每个模型生成一个决策边界,分别进行二分类,所以对于含有n个标签类别的数据,会产生 C n 2 C_{n}^{2} Cn2个模型。效果如上图

在这里插入图片描述
ovr模式下,标签中所有的类别会分别与其他类别进行组合,建立n_class个模型,每个模型生成一个决策边界,分别进行二分类。效果如上图
在这里插入图片描述

说明:

  • 通常情况下ovo模式比ovr模式更精确
  • 在二分类中,所有的支持向量都服务于唯一的超平面,在多分类问题中,每个支持向量都会被用来服务于多个超平面
  • 两个不同超平面的支持向量被用来决定一个拉格朗日乘数的取值,并且规定一个支持向量至少要被两个超平面使用
  • 在简单二分类中,decision_function只返回每个样本点到唯一的超平面的距离,而在多分类问题中这个接口将根据选择的多分类模式不同而返回不同的结构

SVC重要属性:

#属性n_support_:调用每个类别下的支持向量的数目
clf_proba.n_support_
#属性coef_:每个特征的重要性,这个系数仅仅适合于线性核
clf_proba.coef_
#属性intercept_:查看生成的决策边界的截距
clf_proba.intercept_
#属性dual_coef_:查看生成的拉格朗日乘数
clf_proba.dual_coef_
clf_proba.dual_coef_.shape
#支持向量的属性
clf_proba.support_vectors_
clf_proba.support_vectors_.shape
#注意到dual_coef_中生成的拉格朗日乘数的数目和的支持向量的数目一致
#注意到KKT条件的条件中的第五条,所有非支持向量会让拉格朗日乘数为0
#所以拉格朗日乘数的数目和支持向量的数目是一致的
#注意,此情况仅仅在二分类中适用!
2.SVC真实案例:预测明天是否降雨

数据集介绍:

特征/标签含义
Date观察日期
Location获取该信息的气象站的名称
MinTemp以摄氏度为单位的最低温度
MaxTemp以摄氏度为单位的最高温度
Rainfall当天记录的降雨量,单位为mm
Evaporation到早上9点之前的24小时的A级蒸发量(mm)
Sunshine白日受到日照的完整小时
WindGustDir在到午夜12点前的24小时中的最强风的风向
WindGustSpeed在到午夜12点前的24小时中的最强风速(km / h)
WindDir9am上午9点时的风向
WindDir3pm下午3点时的风向
WindSpeed9am上午9点之前每个十分钟的风速的平均值(km / h)
WindSpeed3pm下午3点之前每个十分钟的风速的平均值(km / h)
Humidity9am上午9点的湿度(百分比)
Humidity3am下午3点的湿度(百分比)
Pressure9am上午9点平均海平面上的大气压(hpa)
Pressure3pm上午9点的天空被云层遮蔽的程度,这是以“oktas”来衡量的,这个单位记录了云层遮挡天空的程度。0表示完全晴朗的天空,而8表示它完全是阴天
Cloud9am下午3点的天空被云层遮蔽的程度
Temp9am上午9点的摄氏度温度
Temp3pm下午3点的摄氏度温度
RainTomorrow目标变量:明天下雨了吗?

步骤一:导入库和数据

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_splitweather = pd.read_csv("data/weatherAUS5000.csv")
weather.head()

在这里插入图片描述
步骤二:数据初步探索

#分类特征和标签
X = weather.iloc[:,:-1]
Y = weather.iloc[:,:-1]
X.shape
#数据类型
X.info()
#缺失值
X.isnull().mean()
#标签分类
np.unique(Y)

在这里插入图片描述
在这里插入图片描述
特征矩阵由一部分分类变量和一部分连续变量组成,其中云层遮蔽程度虽然是以数字表示,但是本质却是分类变量。大多数特征都是采集的自然数据,比如蒸发量,日照时间,湿度等等,而少部分特征是人为构成的。还有一些是单纯表示样本信息的变量,比如采集信息的地点,以及采集的时间

步骤三:分训练集和描述性统计

Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,Y,test_size=0.3,random_state=420)
for i in [Xtrain, Xtest, Ytrain, Ytest]:i.index = range(i.shape[0])

注意恢复索引。由于现实中测试集一般不可获得,所以一般实验应该先分训练集和测试集在一步步进行预处理。否则会导致建模过程会受到测试集的影响。

#查看样本不平衡问题
Ytrain.value_counts()
Ytest.value_counts()
#标签编码
from sklearn.preprocessing import LabelEncoder
encorder = LabelEncoder().fit(Ytrain)
Ytrain = pd.DataFrame(encorder.transform(Ytrain))
Ytest = pd.DataFrame(encorder.transform(Ytest))

在这里插入图片描述
在这里插入图片描述

有一点点不平衡,暂时不做处理

步骤四:特征处理
4.1查看描述性统计

Xtrain.describe([0.01,0.05,0.1,0.25,0.5,0.75,0.9,0.99]).T
Xtest.describe([0.01,0.05,0.1,0.25,0.5,0.75,0.9,0.99]).T

在这里插入图片描述
在这里插入图片描述
4.2日期的处理

Xtrainc = Xtrain.copy()
Xtrainc.sort_values(by="Location")
Xtrainc.iloc[:,0].value_counts()

在这里插入图片描述
可以看到,日期并不是独一无二的,是有重复的。一般情况下,降雨和某日的日期关系确实不大。但是如果将时间范围扩大到月份,在雨季的降雨概率肯定是大于旱季的。所以可以取出日期中的月份创建新的特征Month

Xtrain["Date"] = Xtrain["Date"].apply(lambda x:int(x.split("-")[1]))
Xtrain = Xtrain.rename(columns={"Date":"Month"})
Xtrain.head()Xtest["Date"] = Xtest["Date"].apply(lambda x:int(x.split("-")[1]))
Xtest = Xtest.rename(columns={"Date":"Month"})
Xtest.head()

在这里插入图片描述
4.3降雨量的处理

Xtrain.loc[Xtrain["Rainfall"]>=1,"RainToday"]="Yes"
Xtrain.loc[Xtrain["Rainfall"] < 1,"RainToday"] = "No"
Xtrain.loc[Xtrain["Rainfall"]==np.nan,"RainToday"] = np.nanXtest.loc[Xtest["Rainfall"]>=1,"RainToday"]="Yes"
Xtest.loc[Xtest["Rainfall"] < 1,"RainToday"] = "No"
Xtest.loc[Xtest["Rainfall"]==np.nan,"RainToday"] = np.nan

对于降雨量大于1,认为会下雨。缺失值继续填补缺失nan
在这里插入图片描述
4.4地点的处理
我们需要让算法意识到,不同的地点因为气候不同,所以对“明天是否会下雨”有这不同的影响。所以可以考虑将地点转换为当地的气候。
在这里插入图片描述
上面这张地图将澳大利亚不同城市所在的气候区域划分为了八个。如果能够将49个城市转换成8种不同的气候。可以通过爬虫将各个城市对应的经纬度保存。

import time
from selenium import webdriver #导入需要的模块,其中爬虫使用的是selenium
import pandas as pd
import numpy as np
df = pd.DataFrame(index=range(len(cityname))) #创建新dataframe用于存储爬取的数据
driver = webdriver.Chrome() #调用谷歌浏览器
time0 = time.time() #计时开始
#循环开始
for num, city in enumerate(cityname): #在城市名称中进行遍历driver.get('https://www.google.co.uk/webhp?hl=en&sa=X&ved=0ahUKEwimtcX24cTfAhUJE7wKHVkWB5AQPAgH')time.sleep(0.3)search_box = driver.find_element_by_name('q') #锁定谷歌的搜索输入框search_box.send_keys('%s Australia Latitude and longitude' % (city)) search_box.submit() #enter,确认开始搜索result = driver.find_element_by_xpath('//div[@class="Z0LcW"]').text #?爬取需要的经纬度,就是这里,怎么获取的呢?resultsplit = result.split(" ") #将爬取的结果用split进行分割df.loc[num,"City"] = city #向提前创建好的df中输入爬取的数据,第一列是城市名df.loc[num,"Latitude"] = resultsplit[0] #第二列是纬度df.loc[num,"Longitude"] = resultsplit[2] #第三列是经度df.loc[num,"Latitudedir"] = resultsplit[1] #第四列是纬度的方向df.loc[num,"Longitudedir"] = resultsplit[3] #第五列是经度的方向print("%i webcrawler successful for city %s" % (num,city)) #每次爬虫成功之后,就打印“城市”成功了time.sleep(1) #全部爬取完毕后,停留1秒钟
driver.quit() #关闭浏览器
print(time.time() - time0) #打印所需的时间

为什么需要城市的经纬度?
由于样本中的地点名称是气候站的名称,它们不一定代表所在城市的真实气候。可以利用经纬度算出不同气象站和城市之间的距离,选出一个离气象站最近的城市代表。
cityll和cityclimate文件结构如下
在这里插入图片描述
处理两张表
澳大利亚整体在南半球,东半球

#去掉度数符号
cityll["Latitudenum"] = cityll["Latitude"].apply(lambda x:float(x[:-1]))
cityll["Longitudenum"] = cityll["Longitude"].apply(lambda x:float(x[:-1]))
#只取名字和去掉度数后的经纬度
citylld = cityll.iloc[:,[0,5,6]]
citylld["climate"] = city_climate.iloc[:,-1]
citylld.head()

在这里插入图片描述
爬取训练集中城市的经纬度

#训练集中所有的地点
cityname = Xtrain.iloc[:,1].value_counts().index.tolist()
cityname
import time
from selenium import webdriver #导入需要的模块,其中爬虫使用的是selenium
import pandas as pd
import numpy as np
df = pd.DataFrame(index=range(len(cityname))) #创建新dataframe用于存储爬取的数据
driver = webdriver.Chrome() #调用谷歌浏览器
time0 = time.time() #计时开始
#循环开始
for num, city in enumerate(cityname): #在城市名称中进行遍历driver.get('https://www.google.co.uk/webhp?hl=en&sa=X&ved=0ahUKEwimtcX24cTfAhUJE7wKHVkWB5AQPAgH')time.sleep(0.3)search_box = driver.find_element_by_name('q') #锁定谷歌的搜索输入框search_box.send_keys('%s Australia Latitude and longitude' % (city)) #在输入框中输入“城市” 澳大利亚 经纬度    search_box.submit() #enter,确认开始搜索result = driver.find_element_by_xpath('//div[@class="Z0LcW"]').text #?爬取需要的经纬度,就是这里,怎么获取的呢?resultsplit = result.split(" ") #将爬取的结果用split进行分割df.loc[num,"City"] = city #向提前创建好的df中输入爬取的数据,第一列是城市名df.loc[num,"Latitude"] = resultsplit[0] #第二列是经度df.loc[num,"Longitude"] = resultsplit[2] #第三列是纬度df.loc[num,"Latitudedir"] = resultsplit[1] #第四列是经度的方向df.loc[num,"Longitudedir"] = resultsplit[3] #第五列是纬度的方向print("%i webcrawler successful for city %s" % (num,city)) #每次爬虫成功之后,就打印“城市”成功了time.sleep(1) #全部爬取完毕后,停留1秒钟
driver.quit() #关闭浏览器
print(time.time() - time0) #打印所需的时间
df.to_csv(r"C:\work\learnbetter\micro-class\week 8 SVM (2)\samplecity.csv")

同样处理经纬度的度数

samplecity["Latitudenum"] = samplecity["Latitude"].apply(lambda x:float(x[:-1]))
samplecity["Longitudenum"] = samplecity["Longitude"].apply(lambda x:float(x[:-1]))
samplecity = samplecity.iloc[:,[0,5,6]]
samplecity.head()

在这里插入图片描述
获取每个样本城市的气候

地理中两点距离公式如下:
d i s t = R ∗ a c r c o s ( s i n ( s l a t ) ∗ s i n ( e l a t ) + c o s ( s l a t ) ∗ c o s ( e l a t ) ∗ c o s ( s l o n − e l o n ) ) dist = R*acrcos(sin(slat)*sin(elat)+cos(slat)*cos(elat)*cos(slon-elon)) dist=Racrcos(sin(slat)sin(elat)+cos(slat)cos(elat)cos(slonelon))
其中R是地球半径,slat是起始地点维度,slon是起始地点经度;elat是结束地点维度,elon是结束地点的经度。公式由来不做解释。。

首先使用radians将角度转换为弧度

from math import radians ,sin,cos,acos
citylld.loc[:,"slat"] = citylld.iloc[:,1].apply(lambda x : radians(x))
citylld.loc[:,"slon"] = citylld.iloc[:,2].apply(lambda x : radians(x))
samplecity.loc[:,"elat"] = samplecity.iloc[:,1].apply(lambda x : radians(x))
samplecity.loc[:,"elon"] = samplecity.iloc[:,2].apply(lambda x : radians(x))

在这里插入图片描述
对于每一个气象站找出距离最近的城市并获取其气候

import sys
for i in range(samplecity.shape[0]):slat = citylld.loc[:,"slat"]slon = citylld.loc[:,"slon"]elat = samplecity.loc[i,"elat"]elon = samplecity.loc[i,"elon"]dist = 6371.01 * np.arccos(np.sin(slat)*np.sin(elat) + np.cos(slat)*np.cos(elat)*np.cos(slon.values - elon))          city_index = np.argsort(dist)[0]samplecity.loc[i,"closest_city"] = citylld.loc[city_index,"City"]samplecity.loc[i,"climate"] = citylld.loc[city_index,"climate"]
samplecity.head()

在这里插入图片描述
简单查看信息,并保存相应数据

samplecity["climate"].value_counts()
locafinal = samplecity.iloc[:,[0,-1]]
locafinal.head()
locafinal.columns = ["Location","climate"]
#设定locafinal索引为地点,为了之后的map匹配
locafinal = locafinal.set_index(keys="Location")
locafinal.to_csv(r"data/samplelocation.cav")
locafinal.head()

在这里插入图片描述
最后通过每个样本城市对应的气候替换原本气象站的名称

import re 
#sub消除逗号,strip去掉空格
Xtrain["Location"] = Xtrain["Location"].map(locafinal.iloc[:,0]).apply(lambda x:re.sub(",","",x.strip()))
Xtest["Location"] = Xtest["Location"].map(locafinal.iloc[:,0]).apply(lambda x:re.sub(",","",x.strip()))
#重命名
Xtrain = Xtrain.rename(columns={"Location":"Climate"})
Xtest = Xtest.rename(columns={"Location":"Climate"})
Xtrain.head()
Xtest.head()

在这里插入图片描述
步骤五:处理分类型变量
一般来说,如果是分类型数据使用众数进行填补;如果是连续性数据使用均值填补。这里假设测试集合训练集的数据分布和性质都是相似的,因此统一使用训练集的众数和均值来进行填补。
找出所有分类型特征并使用众数来进行填补

cate = Xtrain.columns[Xtrain.dtypes == "object"].tolist()

在这里插入图片描述
除了特征类型为“object”的特征,还有用数字表示但本质为分类型特征的云层遮蔽程度

cloud = ["Cloud9am","Cloud3pm"]
cate = cate + cloud
cate

在这里插入图片描述

from sklearn.impute import  SimpleImputer
si = SimpleImputer(missing_values=np.nan,strategy="most_frequent")
si.fit(Xtrain.loc[:,cate])
Xtrain.loc[:,cate] = si.transform(Xtrain.loc[:,cate])
Xtest.loc[:,cate] = si.transform(Xtest.loc[:,cate])
Xtrain.head()
#查看分类型特征是否依然有缺失值
Xtrain.loc[:,cate].isnull().mean()

在这里插入图片描述
将分类型变量编码
本质是将训练集中已经存在的类别转换成数字,然后再使用接口transform分别在测试集合训练集上进行编码。如果测试集汇总出现了训练集汇总从未出现过的类别就会报错,需要调整模型。

#将所有分离型变量编码为数字,一个类别为一个数字
from sklearn.preprocessing import OrdinalEncoder
oe = OrdinalEncoder()
oe = oe.fit(Xtrain.loc[:,cate])
Xtrain.loc[:,cate] = oe.transform(Xtrain.loc[:,cate])
Xtest.loc[:,cate] = oe.transform(Xtest.loc[:,cate])
Xtrain.loc[:,cate].head()

在这里插入图片描述
步骤六:处理连续型变量
可以采用算法进行填补。但考虑到数据的解释性以及时间的消耗,这里采用更加方便的均值和中位数进行填补。
去除所有的非连续型变量并进行填充

col = Xtrain.columns.tolist()
for i in cate:col.remove(i)
col

在这里插入图片描述

impmean = SimpleImputer(missing_values=np.nan,strategy="mean")
impmean = impmean.fit(Xtrain.loc[:,col])
Xtrain.loc[:,col] = impmean.transform(Xtrain.loc[:,col])
Xtest.loc[:,col] = impmean.transform(Xtest.loc[:,col])
Xtrain.head()

在这里插入图片描述
对连续型变量进行无量纲化
数据的无量纲化是SVM执行前的重要步骤。转换成均值为0,方差为一的分布。但不是正态分布!

#由于month有分类特征,所以剔除
col.remove("Month")
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss = ss.fit(Xtrain.loc[:,col])
Xtrain.loc[:,col] = ss.transform(Xtrain.loc[:,col])
Xtest.loc[:,col] = ss.transform(Xtest.loc[:,col])

在这里插入图片描述
步骤七:建模与模型评估
导入库

from time import time
import datetime
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
from sklearn.metrics import roc_auc_score, recall_score
import pytz

导入模型并计算运行时间

Ytrain = Ytrain.iloc[:,0].ravel()
Ytest = Ytest.iloc[:,0].ravel()times = time()
for kernel in ["linear","poly","rbf","sigmoid"]:clf = SVC(kernel = kernel,gamma="auto",degree=1,cache_size = 5000).fit(Xtrain,Ytrain)result = clf.predict(Xtest)score = clf.score(Xtest,Ytest)recall = recall_score(Ytest,result)auc = roc_auc_score(Ytest,clf.decision_function(Xtest))print("%s 's testing accuracy %f,recall is %f',auc is %f" %(kernel,score,recall,auc))print(datetime.datetime.fromtimestamp(time()-times,pytz.timezone('UTC')).strftime("%M:%S:%f"))

在这里插入图片描述
可以看到,线性模型的效果最佳。现在可以考虑以下方式调参:

  • 得到最高的recall,不惜一切代价判断少数类
  • 追求最高的预测准确率,让accuracy更高
  • 希望recall,ROC和accuracy的平衡

步骤八:模型调参
8.1追求最高的recall
balance模式下模型

times = time()
for kernel in ["linear","poly","rbf","sigmoid"]:clf = SVC(kernel = kernel,gamma="auto",degree=1,cache_size = 5000,class_weight="balanced").fit(Xtrain,Ytrain)result = clf.predict(Xtest)score = clf.score(Xtest,Ytest)recall = recall_score(Ytest,result)auc = roc_auc_score(Ytest,clf.decision_function(Xtest))print("%s 's testing accuracy %f,recall is %f',auc is %f" %(kernel,score,recall,auc))print(datetime.datetime.fromtimestamp(time()-times,pytz.timezone('UTC')).strftime("%M:%S:%f"))

在这里插入图片描述
此时综合效果好的还是linear,所以可以在linear核函数下手动调节少数类占比

times = time()
clf = SVC(kernel = "linear",gamma="auto",degree=1,cache_size = 5000,class_weight={1:10}).fit(Xtrain,Ytrain)
result = clf.predict(Xtest)
score = clf.score(Xtest,Ytest)
recall = recall_score(Ytest,result)
auc = roc_auc_score(Ytest,clf.decision_function(Xtest))
print("%s 's testing accuracy %f,recall is %f',auc is %f" %(kernel,score,recall,auc))
print(datetime.datetime.fromtimestamp(time()-times,pytz.timezone('UTC')).strftime("%M:%S:%f"))

在这里插入图片描述

times = time()
clf = SVC(kernel = "linear",gamma="auto",degree=1,cache_size = 5000,class_weight={1:15}).fit(Xtrain,Ytrain)
result = clf.predict(Xtest)
score = clf.score(Xtest,Ytest)
recall = recall_score(Ytest,result)
auc = roc_auc_score(Ytest,clf.decision_function(Xtest))
print("%s 's testing accuracy %f,recall is %f',auc is %f" %(kernel,score,recall,auc))
print(datetime.datetime.fromtimestamp(time()-times,pytz.timezone('UTC')).strftime("%M:%S:%f"))

在这里插入图片描述
可以看到少数类占比越大,最后recall结果越好,精准捕捉了每一个雨天
8.2追求最高准确率
首先查看样本均衡度

valuec = pd.Series(Ytest).value_counts()
valuec
valuec[0]/valuec.sum()

在这里插入图片描述
查看模型的特异度

from sklearn.metrics import confusion_matrix as CM
clf = SVC(kernel = "linear",gamma="auto",cache_size = 5000).fit(Xtrain,Ytrain)
result = clf.predict(Xtest)
cm = CM(Ytest,result,labels=(1,0))
cm

在这里插入图片描述可以看到特异度很高,可以尝试稍微调整class_weight将模型想少数类的方向调整

irange = np.linspace(0.01,0.05,10)
for i in irange:times = time()clf = SVC(kernel = "linear",gamma="auto",degree=1,cache_size = 5000,class_weight={1:1+i}).fit(Xtrain,Ytrain)result = clf.predict(Xtest)score = clf.score(Xtest,Ytest)recall = recall_score(Ytest,result)auc = roc_auc_score(Ytest,clf.decision_function(Xtest))print("%s 's testing accuracy %f,recall is %f',auc is %f" %(kernel,score,recall,auc))print(datetime.datetime.fromtimestamp(time()-times,pytz.timezone('UTC')).strftime("%M:%S:%f"))

在这里插入图片描述在0.02333333时得到了更高的准确度,继续细化曲线

irange = np.linspace(0.018889,0.027778,10)
for i in irange:times = time()clf = SVC(kernel = "linear",gamma="auto",degree=1,cache_size = 5000,class_weight={1:1+i}).fit(Xtrain,Ytrain)result = clf.predict(Xtest)score = clf.score(Xtest,Ytest)recall = recall_score(Ytest,result)auc = roc_auc_score(Ytest,clf.decision_function(Xtest))print("%s 's testing accuracy %f,recall is %f',auc is %f" %(kernel,score,recall,auc))print(datetime.datetime.fromtimestamp(time()-times,pytz.timezone('UTC')).strftime("%M:%S:%f"))

在这里插入图片描述
此时已经没有更好的结果了。说明以及到了极限。尝试下线性模型表现效果好的逻辑回归

from sklearn.linear_model  import LogisticRegression as LR
logclf = LR(solver="liblinear").fit(Xtrain,Ytrain)
logclf.score(Xtest,Ytest)
C_range= np.linspace(3,5,10)
for C in C_range:logclf = LR(solver="liblinear",C=C).fit(Xtrain,Ytrain)print(C,logclf.score(Xtest,Ytest))

在这里插入图片描述
一动不动。。。。也许要继续提高模型准确度需要使用更加强劲的算法如梯度提升树叭

8.3追求召回率和准确率的平衡
在选定线性核的情况下,调节class_weight并不能使我们的模型有较大的改善。现在调节线性核函数的C值查看效果

###======【TIME WARNING:10mins】======###
import matplotlib.pyplot as plt
C_range = np.linspace(0.01,20,20)
recallall = []
aucall = []
scoreall = []
for C in C_range:times = time()clf = SVC(kernel = "linear",C=C,cache_size = 5000,class_weight = "balanced").fit(Xtrain, Ytrain)result = clf.predict(Xtest)score = clf.score(Xtest,Ytest)recall = recall_score(Ytest, result)auc = roc_auc_score(Ytest,clf.decision_function(Xtest))recallall.append(recall)aucall.append(auc)scoreall.append(score)print("under C %f, testing accuracy is %f,recall is %f', auc is %f" %
(C,score,recall,auc))print(datetime.datetime.fromtimestamp(time()-times).strftime("%M:%S:%f"))print(max(aucall),C_range[aucall.index(max(aucall))])
plt.figure()
plt.plot(C_range,recallall,c="red",label="recall")
plt.plot(C_range,aucall,c="black",label="auc")
plt.plot(C_range,scoreall,c="orange",label="accuracy")
plt.legend()
plt.show()

在这里插入图片描述
在这里插入图片描述
可以看到,随着C值变大,模型运行速度越来越慢。因为C值 的改变消耗比较大。其次C值很小的时候,模型的各项指标都很低,但C到1以上后,模型的表现开始稳定,之后再提高C值模型的效果也没有显著提高。代入最佳C值,查看准确率和Recall具体值

times = time()
clf = SVC(kernel = "linear",C=3.1663157894736838,cache_size = 5000,class_weight = "balanced").fit(Xtrain, Ytrain)
result = clf.predict(Xtest)
score = clf.score(Xtest,Ytest)
recall = recall_score(Ytest, result)
auc = roc_auc_score(Ytest,clf.decision_function(Xtest))
print("testing accuracy %f,recall is %f', auc is %f" % (score,recall,auc))
print(datetime.datetime.fromtimestamp(time()-times,pytz.timezone('UTC')).strftime("%M:%S:%f"))

在这里插入图片描述
可以看到结果都比较一般。绘制ROC曲线

from sklearn.metrics import roc_curve as ROC
import matplotlib.pyplot as plt
FPR, Recall, thresholds = ROC(Ytest,clf.decision_function(Xtest),pos_label=1)
area = roc_auc_score(Ytest,clf.decision_function(Xtest))
areaplt.figure()
plt.plot(FPR, Recall, color='red',label='ROC curve (area = %0.2f)' % area)
plt.plot([0, 1], [0, 1], color='black', linestyle='--')
plt.xlim([-0.05, 1.05])
plt.ylim([-0.05, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('Recall')
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
plt.show()

在这里插入图片描述
以此调节最佳阈值:

maxindex = (Recall - FPR).tolist().index(max(Recall - FPR))
thresholds[maxindex]

在这里插入图片描述
通过选出来的最佳阈值,确定y_predict,并确定此时的recall和准确率

from sklearn.metrics import accuracy_score as ACclf = SVC(kernel = "linear",C=3.1663157894736838,cache_size = 5000,class_weight = "balanced").fit(Xtrain, Ytrain)
prob = pd.DataFrame(clf.decision_function(Xtest))
prob.head()
prob.loc[prob.iloc[:,0] >= thresholds[maxindex],"y_pred"]=1
prob.loc[prob.iloc[:,0] < thresholds[maxindex],"y_pred"]=0

在这里插入图片描述

times = time()
score = AC(Ytest,prob.loc[:,"y_pred"].values)
recall = recall_score(Ytest, prob.loc[:,"y_pred"])
print("testing accuracy %f,recall is %f" % (score,recall))
print(datetime.datetime.fromtimestamp(time()-times,pytz.timezone('UTC')).strftime("%M:%S:%f"))

在这里插入图片描述
效果甚至不如手动调参。可见,最求平衡的话,SVC本身的结果就十分优秀率,调节阈值和C值的效果都很有限。

3.SVM总结

SVM原理,包括决策边界,损失函数,拉格朗日函数,拉格朗日对偶函数,软间隔硬间隔,核函数以及核函数的各种应用。我们了解了SVC类的各种重要参数,属性和接口,其中参数包括软间隔的惩罚系数C,核函数kernel,核函数的相关参数gamma,coef0和degree,解决样本不均衡的参数class_weight,解决多分类问题的参数decision_function_shape,控制概率的参数probability,控制计算内存的参数cache_size,属性主要包括调用支持向量的属性support_vectors_和查看特征重要性的属性coef_。接口中,学习了最核心的decision_function。除此之外,还有分类模型的模型评估指标:混淆矩阵和ROC曲线,还介绍了部分特征工程和数据预处理的思路。

这篇关于ccc-sklearn-10-SVM(4)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/281243

相关文章

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

SVM编程实现python

深入解析python版SVM源码系列--简化版SMO算法 SVM使用SMO算法来解决其中涉及到的二次规划问题。一个简单版本的SMO算法的实现如下: ''' 随机选择随机数,不等于J '''def selectJrand(i,m):j=i #we want to select any J not equal to iwhile (j==i):j = int(random

【机器学习 sklearn】模型正则化L1-Lasso,L2-Ridge

#coding:utf-8from __future__ import divisionimport sysreload(sys)sys.setdefaultencoding('utf-8')import timestart_time = time.time()import pandas as pd# 输入训练样本的特征以及目标值,分别存储在变量X_train与y_train之中。

【机器学习 sklearn】特征筛选feature_selection

特征筛选更加侧重于寻找那些对模型的性能提升较大的少量特征。 继续沿用Titannic数据集,这次试图通过特征刷选来寻找最佳的特征组合,并且达到提高预测准确性的目标。 #coding:utf-8from __future__ import divisionimport sysreload(sys)sys.setdefaultencoding('utf-8')import timest

结合sklearn说一下特征选择

特征选择(排序)对于数据科学家、机器学习从业者来说非常重要。好的特征选择能够提升模型的性能,更能帮助我们理解数据的特点、底层结构,这对进一步改善模型、算法都有着重要作用。 特征选择主要有两个功能: 减少特征数量、降维,使模型泛化能力更强,减少过拟合增强对特征和特征值之间的理解 拿到数据集,一个特征选择方法,往往很难同时完成这两个目的。通常情况下,我们经常不管三七二十一,选择一种自己最熟悉或者

机器学习项目——基于机器学习(决策树 随机森林 朴素贝叶斯 SVM KNN XGBoost)的帕金森脑电特征识别研究(代码/报告材料)

完整的论文代码见文章末尾 以下为核心内容和部分结果 问题背景 帕金森病(Parkinson’s Disease, PD)是一种常见的神经退行性疾病,其主要特征是中枢神经系统的多巴胺能神经元逐渐丧失,导致患者出现运动障碍、震颤、僵硬等症状。然而,除运动症状外,帕金森病患者还常常伴有一系列非运动症状,其中睡眠障碍是最为显著的非运动症状之一。 脑电图(Electroencephalogram, E

《西瓜书》第六章 SVM支持向量机 笔记

文章目录 6.1 间隔与支持向量6.1.1 超平面6.1.2 支持向量6.1.3 间隔6.1.4 最大间隔 6.2 对偶问题6.2.1 凸二次规划6.2.2 对偶问题6.2.3 支持向量机的一个重要性质 6.3 核函数6.3.1 支持向量展开式6.3.2 核函数定理6.3.3 常用的核函数6.3.4 核函数特点 6.4 软间隔与正则化6.4.1 硬间隔6.4.2 软间隔6.4.3 替代损失6

SVM实例

数据源:R自带的iris数据(R的e1071包没装下来,so用Scala写了;鸢尾花(iris)是数据挖掘常用到的一个数据集,包含150种鸢尾花的信息,每50种取自三个鸢尾花种之一(setosa,versicolour或virginica)。每个花的特征用下面的5种属性描述萼片长度(Sepal.Length)、萼片宽度(Sepal.Width)、花瓣长度(Petal.Length)、花瓣宽度(Pe

svm系列九

接下来要说的东西其实不是松弛变量本身,但由于是为了使用松弛变量才引入的,因此放在这里也算合适,那就是惩罚因子C。回头看一眼引入了松弛变量以后的优化问题: 注意其中C的位置,也可以回想一下C所起的作用(表征你有多么重视离群点,C越大越重视,越不想丢掉它们)。这个式子是以前做SVM的人写的,大家也就这么用,但没有任何规定说必须对所有的松弛变量都使用同一个惩罚因子,我们完全可以给每一个离群点

svm系列八

现在我们已经把一个本来线性不可分的文本分类问题,通过映射到高维空间而变成了线性可分的。就像下图这样:   圆形和方形的点各有成千上万个(毕竟,这就是我们训练集中文档的数量嘛,当然很大了)。现在想象我们有另一个训练集,只比原先这个训练集多了一篇文章,映射到高维空间以后(当然,也使用了相同的核函数),也就多了一个样本点,但是这个样本的位置是这样的:   就是图中黄色那个