2023.10.11学习-支持向量机2

2023.10.11学习

人工智能基础学习

复习了支持向量机的概念,并对核函数和软间隔多学习了一些。

​ 在应用于二分类的情况下,svc算法的目标是试图找到一个区分两类数据的平面,这个平面最好位于中间,这样的话分类的准确性较高,容许误差的能力较好,鲁棒性好。

拉格朗日乘子法:将有约束的极值问题转化为无约束的极值问题,就是在最优控制里面讲到的算法。

核函数

线性核函数 svc = SVC(kernel='linear') ,只有使用线性核函数的SVC有 coef_参数

非线性核函数:

(1)默认参数为高斯核函数 (kernel='rbf'),svc = SVC(),高斯分布即正态分布,一般认为这种方法比较好

(2)poly多项式核函数 svc = SVC(kernel='poly') (升维,数据由少变多),参数degree可指定最高幂次,偏置项coef0可设置常数项(对结果影响较小)

(3)sigmoid核函数 svc = SVC(kernel='sigmoid')

硬间隔软间隔

硬间隔:样本点完全线性可分,不容忍误差。

软间隔:允许个别点出现在间隔带中

C,可理解为错误样本的惩罚程度

C越大,正则化越大,松弛因子越小,分类严格,越容易出现过拟合;C趋于正无穷,则意味着数据完全线性可分

对于同一问题,使用不同的核函数效果不同,也并不是所有的数据用高斯核函数最好

from sklearn import datasets
from matplotlib import pyplot as plt
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from matplotlib.colors import ListedColormap

X, y = datasets.load_wine(return_X_y=True)  # 返回葡萄酒数据
# 参数:return_X_y=True则返回(data, target),数据类型为pandas DataFrames或Series。其默认参数为False, 返回类字典对象Bunch
print(X.shape, type(X))  # (178, 13) <class 'numpy.ndarray'>

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)  # 划分训练集和测试集
print(X_train.shape)  # (142, 13)

# 创建模型
svc = SVC(kernel='linear')

svc.fit(X_train, y_train)

print(svc.coef_, svc.intercept_)  # 权重参数和偏执截距
# 使用的数据共有三个类别,属性为13种,故数据的维度为(3, 13),svc.coef_为3个13维的向量(3个法向量,分别有13个维度)
# 因为使用的核函数为线性核函数,故intercept_对应3个截距

y_test_predict = svc.predict(X_test)

# 计算准确率
accuracy = accuracy_score(y_test, y_test_predict)
print(accuracy)  # 近1.0

# 创建模型(poly核函数)
svc = SVC(kernel='poly')  # 升维,将数据由少变多

svc.fit(X_train, y_train)

y_test_predict = svc.predict(X_test)

# 计算准确率
accuracy = accuracy_score(y_test, y_test_predict)
print(accuracy)  # 0.6944444444444444

# 写了个小函数省略代码行数
def svc_kernel_test(kernel):
    svc = SVC(kernel=kernel)
    svc.fit(X_train, y_train)
    y_test_predict = svc.predict(X_test)
    accuracy = accuracy_score(y_test, y_test_predict)
    print(accuracy)

svc_kernel_test('rbf')  # 0.6388888888888888

svc_kernel_test('sigmoid')  # 0.2777777777777778

说明对于葡萄酒数据的分类,使用线性核函数的效果是最好的。

——————————————

非线性核函数应用,以两个圆的散点分类为例

X, y = datasets.make_circles(n_samples=100, factor=0.7)  # 参数:生成100个数据,大小0.7
X += np.random.randn(100, 2)*0.05  # 给数据加一些噪声
print(X.shape, y.shape)  # (100, 2) (100,)
fig1 = plt.figure(figsize=(5, 5))
cmap = ListedColormap(colors=['red', 'blue'])  # 指定不同类别数据的颜色列表
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap)
plt.show()

# 先测试一下线性核函数
svc1 = SVC(kernel='linear')
svc1.fit(X, y)
print(svc1.score(X, y))  # 返回拟合精确度,参数是待测试的数据及其标签。0.53
y_predict = svc1.predict(X)
fig2 = plt.figure(figsize=(5, 5))
x_axis = np.linspace(-1.1, 1.1, 100).reshape(-1, 1)
w = svc1.coef_[0]
b = svc1.intercept_[0]
decision_boundary = (-x_axis*w[0] - b)/w[1]
plt.plot(x_axis, decision_boundary)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap)
plt.scatter(X[:, 0], X[:, 1], c=y_predict)
plt.title("kernel='linear'")
plt.show()

# 测试多项式poly核函数
svc2 = SVC(kernel='poly', degree=3)  # 参数degree:多项式的最高幂次,默认为3次
svc2.fit(X, y)
print(svc2.score(X, y))  # 三次:0.68; 二次:1.0
y2_predict = svc2.predict(X)

# 坐标数据生成与预测
x_1_axis = np.linspace(-1.1, 1.1, 100)
x_2_axis = np.linspace(-1.1, 1.1, 100)
print(x_1_axis.shape, x_2_axis.shape)  # (100,) (100,)
x_1_axis, x_2_axis = np.meshgrid(x_1_axis, x_2_axis)  # 网格交叉
print(x_1_axis.shape, x_2_axis.shape)  # (100, 100) (100, 100)
X_axis = np.column_stack([x_1_axis.ravel(), x_2_axis.ravel()])  # 列的合并
print(X_axis.shape)  # (10000, 2)

y2_axis_predict = svc2.predict(X_axis)

fig3 = plt.figure(figsize=(5, 5))
plt.scatter(X_axis[:, 0], X_axis[:, 1], c=y2_axis_predict)
plt.scatter(X[:, 0], X[:, 1], c=y2_predict, cmap=cmap)
plt.title("kernel='poly', degree=3")
plt.show()

# 测试高斯核函数
svc3 = SVC()
svc3.fit(X, y)
print(svc3.score(X, y))  # 1.0

y3_predict = svc3.predict(X)

y_axis_predict = svc3.predict(X_axis)

fig4 = plt.figure(figsize=(5, 5))
plt.scatter(X_axis[:, 0], X_axis[:, 1], c=y_axis_predict)
plt.scatter(X[:, 0], X[:, 1], c=y3_predict, cmap=cmap)
plt.title("kernel='rbf'")
plt.show()

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

关于软间隔的测试

C值较小,容忍一些错误,间隔大,防止过拟合

C值较大,分类严格,间隔小,可能过拟合

代码:(因为数据量较小,C值取的非常小了才看出来区别)

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler

# 绘制决策边界和上下边界曲线
def plot_svc_decision_line(svm_clf, xmin, xmax, sv=True):
    w = svm_clf.coef_[0]  # 权重参数w
    b = svm_clf.intercept_[0]  # 偏置参数b
    x0 = np.linspace(xmin, xmax, 1000)  # 设置横轴坐标数据
    decision_boundary = (-x0*w[0] - b)/w[1]  # 决策边界点值
    margin = 1/w[1]  # 最近点到决策边界的距离
    gutter_up = decision_boundary + margin  # 上分离曲线
    gutter_down = decision_boundary - margin  # 下分离曲线
    if sv:
        svs = svm_clf.support_vectors_  # 所有的支持向量
        plt.scatter(svs[:, 0], svs[:, 1], s=180, facecolors='r')  # 绘制支持向量点
    plt.plot(x0, decision_boundary, linewidth=2)  # 绘制决策边界
    plt.plot(x0, gutter_up, 'k--', linewidth=2)
    plt.plot(x0, gutter_down, 'k--', linewidth=2)
    
# 关于软间隔(C值)的测试
data_fault = pd.read_csv('data2.csv')
X2 = data_fault.drop('label', axis=1)
y2 = data_fault.loc[:, 'label']

fig2 = plt.figure()
y2_0 = plt.scatter(X2.loc[:, 'V1'][y2 == 0], X2.loc[:, 'V2'][y2 == 0])
y2_1 = plt.scatter(X2.loc[:, 'V1'][y2 == 1], X2.loc[:, 'V2'][y2 == 1])
plt.show()

svm_clf2 = SVC(kernel='linear', C=1)
svm_clf2.fit(X2, y2)

print(svm_clf2.predict([[50, 41]]))

plot_svc_decision_line(svm_clf2, 0, 160)
y2_0 = plt.scatter(X2.loc[:, 'V1'][y2 == 0], X2.loc[:, 'V2'][y2 == 0])
y2_1 = plt.scatter(X2.loc[:, 'V1'][y2 == 1], X2.loc[:, 'V2'][y2 == 1])
plt.title('C=1')
plt.show()

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值