第三次实验:支持向量机在仿真数据集上的应用


第三次实验:支持向量机在仿真数据集上的应用

前言

一、实验内容概述

二、编程思路及步骤

1、检查python以及机器学习的版本是否达到要求,导入一些基础的包,并设置字体、创建图像保存的地址。

2、生成符合实验要求的make_blobs数据集,输出其散点图并保存。

3、使用线性支持向量机对生成的数据进行分类

4、查找支持向量。

5、编写一个输出支持向量机边界线的函数,方便后续使用。

6、将第3、4和5步的结果可视化,并保存。

7、生成符合实验要求的make_moons数据集,输出其散点图并保存。

8、用线性核SVM对生成的moon data 进行分类,输出分类边界。

9、用高斯核SVM对生成的数据进行分类。

 后记 

附:源代码

3_make_blobs.py

 3_make_moons.py


前言

前两次实验写得太差了,就不上传了。


一、实验内容概述

1. 生成Blobs data 仿真数据,n_features=2, centers=2,其它未指定参数自定(若没有使用默认参数请标出实际使用值),在平面上绘制生成数据散点图;

2. 使用线性支持向量机(分别使用硬间隔和软间隔)对生成的数据进行分类,输出类似于下图的支持向量机边界线,标出支持向量,并分析比较两种间隔的分类效果;

3. 生成moon data,noise= 0.17,其它未指定参数自定(若没有使用默认参数请标出实际使用值),在平面上绘制生成数据散点图;

4. 分别用线性核SVM和高斯核SVM对生成的moon data 进行分类,输出类似下图的分类边界,并比较它们的分类效果。

二、编程思路及步骤

1、检查python以及机器学习的版本是否达到要求,导入一些基础的包,并设置字体、创建图像保存的地址。

# coding: utf-8
import sys
assert sys.version_info >= (3, 5)
import sklearn
assert sklearn.__version__ >= "0.20"
import os
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['Microsoft YaHei']
np.random.seed(211)
IMAGES_PATH = os.path.join(".", "images", "svm")

2、生成符合实验要求的make_blobs数据集,输出其散点图并保存。

 

from sklearn.datasets import make_blobs  # 多类单标签数据集
X1, Y1 = make_blobs(n_features=2,      # 每个样本两个特征维度
                    centers=2,         # 产生两个中心点
                    random_state=211)
plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1, s=25, edgecolor='k')
plt.title("生成的blobs数据集散点图")
plt.savefig(IMAGES_PATH + r'\blobs数据集的散点图.png', dpi=300)
plt.show()

3、使用线性支持向量机对生成的数据进行分类

        由于惩罚系数越小,街道越宽,间隔违规越多,故软间隔的惩罚系数应尽可能小,此处取0.5,硬间隔的惩罚系数应尽可能大,此处取100即可。

# 使用线性支持向量机对生成的数据进行分类
from sklearn import datasets
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC

scaler = StandardScaler()
# 软间隔分类:惩罚系数小,街道宽,间隔违规多
svm_clf1 = LinearSVC(C=0.5, loss="hinge", random_state=211)
# 硬间隔分类:C取100,模拟无穷大
svm_clf2 = LinearSVC(C=100, loss="hinge", random_state=211)

scaled_svm_clf1 = Pipeline([
        ("scaler", scaler),
        ("linear_svc", svm_clf1),
    ])
scaled_svm_clf2 = Pipeline([
        ("scaler", scaler),
        ("linear_svc", svm_clf2),
    ])

scaled_svm_clf1.fit(X1, Y1)
scaled_svm_clf2.fit(X1, Y1)

4、查找支持向量。

# Convert to unscaled parameters
b1 = svm_clf1.decision_function([-scaler.mean_ / scaler.scale_])
b2 = svm_clf2.decision_function([-scaler.mean_ / scaler.scale_])
w1 = svm_clf1.coef_[0] / scaler.scale_
w2 = svm_clf2.coef_[0] / scaler.scale_
svm_clf1.intercept_ = np.array([b1])
svm_clf2.intercept_ = np.array([b2])
svm_clf1.coef_ = np.array([w1])
svm_clf2.coef_ = np.array([w2])

# Find support vectors (LinearSVC does not do this automatically)
t = Y1 * 2 - 1
support_vectors_idx1 = (t * (X1.dot(w1) + b1) < 1).ravel()
support_vectors_idx2 = (t * (X1.dot(w2) + b2) < 1).ravel()
svm_clf1.support_vectors_ = X1[support_vectors_idx1]
svm_clf2.support_vectors_ = X1[support_vectors_idx2]

5、编写一个输出支持向量机边界线的函数,方便后续使用。

# 输出支持向量机边界线
def plot_svc_decision_boundary(svm_clf, xmin, xmax):
    w = svm_clf.coef_[0]
    b = svm_clf.intercept_[0]

    x0 = np.linspace(xmin, xmax, 200)
    decision_boundary = -w[0]/w[1] * x0 - b/w[1]

    margin = 1/w[1]
    gutter_up = decision_boundary + margin
    gutter_down = decision_boundary - margin

    svs = svm_clf.support_vectors_
    plt.scatter(svs[:, 0], svs[:, 1], s=180, facecolors='#FFAAAA')
    plt.plot(x0, decision_boundary, "k-", linewidth=2)
    plt.plot(x0, gutter_up, "k--", linewidth=2)
    plt.plot(x0, gutter_down, "k--", linewidth=2)

6、将第3、4和5步的结果可视化,并保存。

# 先创建图形网络
# ax是一个包含两个Axes对象的数组
fig, ax = plt.subplots(ncols=2, figsize=(10, 2.7), sharey=True)

plt.sca(ax[0])
plt.plot(X1[:, 0][Y1==1], X1[:, 1][Y1==1], "g^", label="类A")
plt.plot(X1[:, 0][Y1==0], X1[:, 1][Y1==0], "bs", label="类B")
plot_svc_decision_boundary(svm_clf1, 0, 15)
plt.xlabel("特征一", fontsize=14)
plt.ylabel("特征二", fontsize=14)
plt.legend(loc="upper right", fontsize=14)    # 设置图例的位置_右上
plt.title("软间隔分类 C取{}".format(svm_clf1.C), fontsize=16)
plt.axis([3, 12, -12.5, 7])

plt.sca(ax[1])
plt.plot(X1[:, 0][Y1==1], X1[:, 1][Y1==1], "g^")
plt.plot(X1[:, 0][Y1==0], X1[:, 1][Y1==0], "bs")
plot_svc_decision_boundary(svm_clf2, 0, 15)
plt.xlabel("特征一", fontsize=14)
plt.title("硬间隔分类 C取{}".format(svm_clf2.C), fontsize=16)
plt.axis([3, 12, -12.5, 7])

plt.suptitle("软/硬间隔分类")
plt.savefig(IMAGES_PATH + r'\软硬间隔分类.png', dpi=300)
plt.show()

7、生成符合实验要求的make_moons数据集,输出其散点图并保存。

# 生成数据集并输出散点图
from sklearn.datasets import make_moons
X, y = make_moons(noise=0.17,  # 加入高斯噪声
                  random_state=211)
plt.scatter(X[:, 0], X[:, 1], marker='o', c=y, s=25, edgecolor='k')
plt.title("生成的moons数据集散点图")
plt.savefig(IMAGES_PATH + r'\moons数据集的散点图.png', dpi=300)
plt.show()

8、用线性核SVM对生成的moon data 进行分类,输出分类边界。

       如果模型过拟合,可以减小多项式核的阶数,如果是过拟合,可以增大阶数,经检验,4阶线性核SVM效果最佳。

# 用线性核SVM对生成的数据进行分类
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import PolynomialFeatures
from sklearn.svm import LinearSVC

polynomial_svm_clf = Pipeline([
        ("poly_features", PolynomialFeatures(degree=4)),
        ("scaler", StandardScaler()),
        ("svm_clf", LinearSVC(C=10, loss="hinge", random_state=211,max_iter=10000))
    ])

polynomial_svm_clf.fit(X, y)

plot_predictions(polynomial_svm_clf, [-1.5, 2.5, -1, 1.5])
plot_dataset(X, y, [-1.5, 2.5, -1, 1.5])
plt.title("4阶的多项式线性核SVM分类器", fontsize=16)
plt.savefig(IMAGES_PATH + r'\线性核SVM.png', dpi=300)
plt.show()

9、用高斯核SVM对生成的数据进行分类。

       增大y使钟型曲线更窄,导致每个样本的影响范围变的更小,判定边界最终变得更不规则,在单个样本周围环绕。相反的﹐较小的y值使钟型曲线更宽﹐样本有更大的影响范围﹐判定边界最终则更加平滑。所以如果模型过拟合,你应该减小y值﹐若欠拟合﹐则增大y(与超参数c 相似)。

# 用高斯核SVM对生成的数据进行分类
from sklearn.svm import SVC

gamma1, gamma2 = 0.1, 5
C1, C2 = 0.001, 1000
hyperparams = (gamma1, C1), (gamma1, C2), (gamma2, C1), (gamma2, C2)

svm_clfs = []
for gamma, C in hyperparams:
    rbf_kernel_svm_clf = Pipeline([
            ("scaler", StandardScaler()),
            ("svm_clf", SVC(kernel="rbf", gamma=gamma, C=C))
        ])
    rbf_kernel_svm_clf.fit(X, y)
    svm_clfs.append(rbf_kernel_svm_clf)

fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10.5, 7), sharex=True, sharey=True)

for i, svm_clf in enumerate(svm_clfs):
    plt.sca(axes[i // 2, i % 2])
    plot_predictions(svm_clf, [-1.5, 2.45, -1, 1.5])
    plot_dataset(X, y, [-1.5, 2.45, -1, 1.5])
    gamma, C = hyperparams[i]
    plt.title(r"$\gamma = {}, C = {}$".format(gamma, C), fontsize=16)
    if i in (0, 1):
        plt.xlabel("")
    if i in (1, 3):
        plt.ylabel("")

plt.suptitle("高斯核SVM")
plt.savefig(IMAGES_PATH + r'\高斯核SVM.png', dpi=300)
plt.show()

 后记 

新手上路,请多指正!


附:源代码

3_make_blobs.py

# coding: utf-8
import sys
assert sys.version_info >= (3, 5)
import sklearn
assert sklearn.__version__ >= "0.20"
import os
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['Microsoft YaHei']
np.random.seed(211)
IMAGES_PATH = os.path.join(".", "images", "svm")

# 输出支持向量机边界线
def plot_svc_decision_boundary(svm_clf, xmin, xmax):
    w = svm_clf.coef_[0]
    b = svm_clf.intercept_[0]

    x0 = np.linspace(xmin, xmax, 200)
    decision_boundary = -w[0]/w[1] * x0 - b/w[1]

    margin = 1/w[1]
    gutter_up = decision_boundary + margin
    gutter_down = decision_boundary - margin

    svs = svm_clf.support_vectors_
    plt.scatter(svs[:, 0], svs[:, 1], s=180, facecolors='#FFAAAA')
    plt.plot(x0, decision_boundary, "k-", linewidth=2)
    plt.plot(x0, gutter_up, "k--", linewidth=2)
    plt.plot(x0, gutter_down, "k--", linewidth=2)

# 生成数据集并输出散点图
from sklearn.datasets import make_blobs  # 多类单标签数据集
X1, Y1 = make_blobs(n_features=2,      # 每个样本两个特征维度
                    centers=2,         # 产生两个中心点
                    random_state=211)
plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1, s=25, edgecolor='k')
plt.title("生成的blobs数据集散点图")
plt.savefig(IMAGES_PATH + r'\blobs数据集的散点图.png', dpi=300)
plt.show()

# 使用线性支持向量机对生成的数据进行分类
from sklearn import datasets
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC

scaler = StandardScaler()
# 软间隔分类:惩罚系数小,街道宽,间隔违规多
svm_clf1 = LinearSVC(C=0.5, loss="hinge", random_state=211)
# 硬间隔分类:C取100,模拟无穷大
svm_clf2 = LinearSVC(C=100, loss="hinge", random_state=211)

scaled_svm_clf1 = Pipeline([
        ("scaler", scaler),
        ("linear_svc", svm_clf1),
    ])
scaled_svm_clf2 = Pipeline([
        ("scaler", scaler),
        ("linear_svc", svm_clf2),
    ])

scaled_svm_clf1.fit(X1, Y1)
scaled_svm_clf2.fit(X1, Y1)

# Convert to unscaled parameters
b1 = svm_clf1.decision_function([-scaler.mean_ / scaler.scale_])
b2 = svm_clf2.decision_function([-scaler.mean_ / scaler.scale_])
w1 = svm_clf1.coef_[0] / scaler.scale_
w2 = svm_clf2.coef_[0] / scaler.scale_
svm_clf1.intercept_ = np.array([b1])
svm_clf2.intercept_ = np.array([b2])
svm_clf1.coef_ = np.array([w1])
svm_clf2.coef_ = np.array([w2])

# Find support vectors (LinearSVC does not do this automatically)
t = Y1 * 2 - 1
support_vectors_idx1 = (t * (X1.dot(w1) + b1) < 1).ravel()
support_vectors_idx2 = (t * (X1.dot(w2) + b2) < 1).ravel()
svm_clf1.support_vectors_ = X1[support_vectors_idx1]
svm_clf2.support_vectors_ = X1[support_vectors_idx2]

# 先创建图形网络
# ax是一个包含两个Axes对象的数组
fig, ax = plt.subplots(ncols=2, figsize=(10, 2.7), sharey=True)

plt.sca(ax[0])
plt.plot(X1[:, 0][Y1==1], X1[:, 1][Y1==1], "g^", label="类A")
plt.plot(X1[:, 0][Y1==0], X1[:, 1][Y1==0], "bs", label="类B")
plot_svc_decision_boundary(svm_clf1, 0, 15)
plt.xlabel("特征一", fontsize=14)
plt.ylabel("特征二", fontsize=14)
plt.legend(loc="upper right", fontsize=14)    # 设置图例的位置_右上
plt.title("软间隔分类 C取{}".format(svm_clf1.C), fontsize=16)
plt.axis([3, 12, -12.5, 7])

plt.sca(ax[1])
plt.plot(X1[:, 0][Y1==1], X1[:, 1][Y1==1], "g^")
plt.plot(X1[:, 0][Y1==0], X1[:, 1][Y1==0], "bs")
plot_svc_decision_boundary(svm_clf2, 0, 15)
plt.xlabel("特征一", fontsize=14)
plt.title("硬间隔分类 C取{}".format(svm_clf2.C), fontsize=16)
plt.axis([3, 12, -12.5, 7])

plt.suptitle("软/硬间隔分类")
plt.savefig(IMAGES_PATH + r'\软硬间隔分类.png', dpi=300)
plt.show()

 3_make_moons.py

# coding: utf-8
import sys
assert sys.version_info >= (3, 5)
import sklearn
assert sklearn.__version__ >= "0.20"
import os
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['Microsoft YaHei']
np.random.seed(211)
IMAGES_PATH = os.path.join(".", "images", "svm")

def plot_dataset(X, y, axes):
    plt.plot(X[:, 0][y==0], X[:, 1][y==0], "bs")
    plt.plot(X[:, 0][y==1], X[:, 1][y==1], "g^")
    plt.axis(axes)
    plt.grid(True, which='both')
    plt.xlabel(r"$x_1$", fontsize=20)
    plt.ylabel(r"$x_2$", fontsize=20, rotation=0)

def plot_predictions(clf, axes):
    x0s = np.linspace(axes[0], axes[1], 100)
    x1s = np.linspace(axes[2], axes[3], 100)
    x0, x1 = np.meshgrid(x0s, x1s)
    X = np.c_[x0.ravel(), x1.ravel()]
    y_pred = clf.predict(X).reshape(x0.shape)
    y_decision = clf.decision_function(X).reshape(x0.shape)
    plt.contourf(x0, x1, y_pred, cmap=plt.cm.brg, alpha=0.2)
    plt.contourf(x0, x1, y_decision, cmap=plt.cm.brg, alpha=0.1)

# 生成数据集并输出散点图
from sklearn.datasets import make_moons
X, y = make_moons(noise=0.17,  # 加入高斯噪声
                  random_state=211)
plt.scatter(X[:, 0], X[:, 1], marker='o', c=y, s=25, edgecolor='k')
plt.title("生成的moons数据集散点图")
plt.savefig(IMAGES_PATH + r'\moons数据集的散点图.png', dpi=300)
plt.show()

# 用线性核SVM对生成的数据进行分类
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import PolynomialFeatures
from sklearn.svm import LinearSVC

polynomial_svm_clf = Pipeline([
        ("poly_features", PolynomialFeatures(degree=4)),
        ("scaler", StandardScaler()),
        ("svm_clf", LinearSVC(C=10, loss="hinge", random_state=211,max_iter=10000))
    ])

polynomial_svm_clf.fit(X, y)

plot_predictions(polynomial_svm_clf, [-1.5, 2.5, -1, 1.5])
plot_dataset(X, y, [-1.5, 2.5, -1, 1.5])
plt.title("4阶的多项式线性核SVM分类器", fontsize=16)
plt.savefig(IMAGES_PATH + r'\线性核SVM.png', dpi=300)
plt.show()

# 用高斯核SVM对生成的数据进行分类
from sklearn.svm import SVC

gamma1, gamma2 = 0.1, 5
C1, C2 = 0.001, 1000
hyperparams = (gamma1, C1), (gamma1, C2), (gamma2, C1), (gamma2, C2)

svm_clfs = []
for gamma, C in hyperparams:
    rbf_kernel_svm_clf = Pipeline([
            ("scaler", StandardScaler()),
            ("svm_clf", SVC(kernel="rbf", gamma=gamma, C=C))
        ])
    rbf_kernel_svm_clf.fit(X, y)
    svm_clfs.append(rbf_kernel_svm_clf)

fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10.5, 7), sharex=True, sharey=True)

for i, svm_clf in enumerate(svm_clfs):
    plt.sca(axes[i // 2, i % 2])
    plot_predictions(svm_clf, [-1.5, 2.45, -1, 1.5])
    plot_dataset(X, y, [-1.5, 2.45, -1, 1.5])
    gamma, C = hyperparams[i]
    plt.title(r"$\gamma = {}, C = {}$".format(gamma, C), fontsize=16)
    if i in (0, 1):
        plt.xlabel("")
    if i in (1, 3):
        plt.ylabel("")

plt.suptitle("高斯核SVM")
plt.savefig(IMAGES_PATH + r'\高斯核SVM.png', dpi=300)
plt.show()
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐