SVM 对于数据集的分类分析,以及SVM功能分析

目录

SVM介绍

数据集介绍

线性SVM对于不同数据集的分类

线性SVM对鸢尾花数据集的分类

线性SVM对乳腺癌数据集的分类

不同数据集对线性SVM不同效果的对比

C值对线性SVM分类器的影响

C值在鸢尾花线性SVM中的影响

C值在乳腺癌线性SVM中的影响

差异对比

不同训练测试比对线性SVM的影响

鸢尾花数据集

乳腺癌数据集

不同kernel function对数据集分类的影响

介绍四种kernel function

测试不同kernel function

鸢尾花数据集

乳腺癌数据集

学习总结


SVM介绍

支持向量机(SVM)是一种强大的算法,广泛应用于回归和分类任务,通常通过找到最佳超平面来对数据点进行分类。SVM可以处理线性和非线性问题。在线性可分的情况下,SVM通过找到一条线(二维)或一个平面(高维)来分离不同类别的数据,以最大化两种数据之间的边距。对于线性不可分的情况,SVM引入了多项式核、Sigmoid核和径向基函数(RBF)等核函数,将数据转换为更高维的空间,在那里它变得线性可分,从而构建了一个非线性SVM。

数据集介绍

本次实验中一共用到两个数据集,一个是较小的Iris鸢尾花数据集,另一个是数据稍微多一点的威斯康星州乳腺癌数据集。

鸢尾花数据集链接:UCI Machine Learning Repository

威斯康星州乳腺癌数据集链接:UCI Machine Learning Repository

两个数据集的理解可以看我之前的笔记,这边不再赘述数据集的整理。

线性SVM对于不同数据集的分类

线性SVM对鸢尾花数据集的分类

import time
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
## 设置属性防止中文乱码
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
## Get data
# 'sepal length', 'sepal width', 'petal length', 'petal width'
iris_feature = u'花萼长度', u'花萼宽度', u'花瓣长度', u'花瓣宽度'
path = 'C:/数据集地址/iristest/iris.data'  
data = pd.read_csv(path, header=None)
x, y = data[list(range(4))], data[4]
y = pd.Categorical(y).codes 
x = x[[0, 1]] ## If use petal length and width, change to x[[2,3]]
training_ratios = np.linspace(0.1,0.9,9)

train_accuracies = []
test_accuracies = []
for ratio in training_ratios:
    ## Data segmentation
    x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=28, train_size=ratio)
    
    # 初始化线性SVM分类器
    clf = SVC(kernel='linear')
    
    # 训练分类器
    clf.fit(x_train, y_train)
    
    # 预测训练集
    y_train_pred = clf.predict(x_train)
    train_accuracy = accuracy_score(y_train, y_train_pred)
    train_accuracies.append(train_accuracy)
    
    # 预测测试集
    y_test_pred = clf.predict(x_test)
    test_accuracy = accuracy_score(y_test, y_test_pred)
    test_accuracies.append(test_accuracy)
# 绘制训练集比例与准确性的关系图
plt.figure(figsize=(10, 6))
plt.plot(training_ratios, train_accuracies, marker='o',label = '训练集准确率')
plt.plot(training_ratios, test_accuracies, marker='o',label = '测试集准确率')
plt.title('Effect of Training Set Size on Linear SVM Performance')
plt.xlabel('Training Set Ratio')
plt.ylabel('Accuracy')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

以上代码使用的是以花萼长度和花萼宽度为X-Y值。如果需要花瓣长度和花瓣宽度为xy值的话,x值改成x[[2,3]].

线性SVM对乳腺癌数据集的分类

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler

## 设置属性防止中文乱码
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False

## Get data
##定义特证名
column_names = ['id', 'clump_thickness', 'uniformity_of_cell_size', 'uniformity_of_cell_shape', 
                'marginal_adhesion', 'single_epithelial_cell_size', 'bare_nuclei', 'bland_chromatin', 
                'normal_nucleoli', 'mitoses', 'class']
#数据路径
path = 'C:/数据集地址/breast+cancer+wisconsin+original/breast-cancer-wisconsin.data'  

#加载数据
data = pd.read_csv(path, header=None, names=column_names)

# 处理缺失值(将'?'替换为NaN并删除有缺失值的行)
data.replace('?', np.nan, inplace=True)
data.dropna(inplace=True)

# 将特征和标签分开
x = data.iloc[:, 1:-1]  # 所有特征列(去掉id和class列)
y = data['class']       # 标签列

# 将标签从2和4映射到0和1
y = y.map({2: 0, 4: 1})

# 选择用于训练的特征,可以更改为所需的特征列
x = x[['clump_thickness', 'uniformity_of_cell_size']]  

# 将数据集分割为训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.6, random_state=28)

# 标准化特征
scaler = StandardScaler()
x_train = scaler.fit_transform(x_train)
x_test = scaler.transform(x_test)

# 初始化线性SVM分类器
clf = SVC(kernel='linear')

# 训练分类器
clf.fit(x_train, y_train)

## Calculate the accuracy/precision of the model
print (clf.score(x_train, y_train)) 
print ('训练集准确率:', accuracy_score(y_train, clf.predict(x_train)))
print (clf.score(x_test, y_test))
print ('测试集准确率:', accuracy_score(y_test, clf.predict(x_test)))

## 计算决策函数的结构值以及预测值(decision_function计算的是样本x到各个分割平面的距离<也就是决策函数的值>)
print ('decision_function:\n', clf.decision_function(x_train))
print ('\npredict:\n', clf.predict(x_train))

# 创建网格以绘制决策边界
h = .02  # 网格步长
x_min, x_max = x_train[:, 0].min() - 1, x_train[:, 0].max() + 1
y_min, y_max = x_train[:, 1].min() - 1, x_train[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))

# 预测网格中所有点的标签
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) # 预测分类值
Z = Z.reshape(xx.shape) # 使之与输入的形状相同

# 绘制结果
cm_light = mpl.colors.ListedColormap([ '#A0FFA0', '#A0A0FF'])
plt.figure(facecolor='w')

plt.figure(figsize=(10, 6))
plt.contourf(xx, yy, Z, cmap=cm_light, alpha=0.8)
#所有样本点
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train, edgecolors='k', facecolors='g',s=50)
#测试数据集
plt.scatter(x_test[:, 0], x_test[:, 1], c=y_test, s=120, edgecolors='k',facecolors='b', zorder=10)
plt.xlabel('Clump Thickness')
plt.ylabel('Uniformity of Cell Size')
plt.title('Breast Cancer Wisconsin SVM Classification')
plt.grid(b=True, ls=':')
plt.tight_layout(pad=1.5)
plt.show()

不同数据集对线性SVM不同效果的对比

在相同参数和线性核的情况下,上述两个例子的测试结论是鸢尾花lris数据集的测试集准确度为0.783,乳腺癌症数据集的检测集准确度是0.953。
Iris数据集包含3个类别和4个特征,只有150个样本。当数据集较小时,其类别之间的边界相对更复杂,使得分类器难以正确分类所有数据点。癌症数据集有699个样本,可以提供更多信息,帮助模型更好地学习和归纳。同时,癌症乳腺数据集包含30个特征,仅包含两个类别,从而更容易在特征空间中分离数据。
我们可以看到,在线性SVM的情况下,具有更多特征和更少类别的较大数据集可以更好地进行分类。

C值对线性SVM分类器的影响

在支持向量机中,正则化参数C值是控制模型复杂度和核训练误差的关键参数。C值在调节模型中的正则化强度、泛化能力和过拟合效应方面起着重要作用。
SVM的目标是在超平面上找到一个决策边界,使数据点之间的间距最大化,同时最小化分类误差。对于二元分类问题,优化问题可以表示为

SVM的损失函数由两部分组成:区间最大化部分(用于最大化分类超平面的区间,从而增强模型的泛化能力)和误分类部分。误分类部分用于衡量数据点的误分类损失,并由C参数加权。正则化参数C值在确定错误分类部分中错误分类的惩罚程度方面起着加权作用。
较大的C值对模型误分类的容忍度较低,并且更倾向于正确分类训练集中的每个数据点,即使它需要牺牲较大的间隔。这将增加模型的复杂性并导致过拟合。较小的C值对错误分类具有更高的容忍度,并且更倾向于找到平滑的决策边界,即使这意味着一些训练数据点会被错误分类。这将增加间隔,但可能会导致填充不足。

C值在鸢尾花线性SVM中的影响

​
import time
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import StandardScaler

## Get data
# 'sepal length', 'sepal width', 'petal length', 'petal width'
iris_feature = u'花萼长度', u'花萼宽度', u'花瓣长度', u'花瓣宽度'
path = 'C:/数据集地址/iristest/iris.data'  
data = pd.read_csv(path, header=None)
x, y = data[list(range(4))], data[4]
y = pd.Categorical(y).codes 
x = x[[0, 1]] ## If use petal length and width, change to x[[2,3]]

## 数据分割
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=28, train_size=0.6)

#不同C值
C_values = np.logspace(-3, 3, 10)

#储存训练核测试准确率
train_scores = []
test_scores = []
time_scores = []

#不同C值模型使用
for C in C_values:
    svm_model =SVC(C=C, kernel='linear')
    t1 =time.time()
    svm_model.fit(x_train, y_train)
    t2 =time.time()
    
    # 在训练集和测试集上评估准确率
    train_acc = accuracy_score(y_train, svm_model.predict(x_train))
    test_acc = accuracy_score(y_test, svm_model.predict(x_test))
    
    # 保存训练和测试准确率
    train_scores.append(train_acc)
    test_scores.append(test_acc)
    time_scores.append(t2-t1)

# 绘制准确率折线图
plt.figure(figsize=(14, 6))
plt.subplot(1, 2, 1)
plt.plot(C_values, train_scores, marker='o', label='Train Accuracy')
plt.plot(C_values, test_scores, marker='o', label='Test Accuracy')
plt.xscale('log')
plt.xlabel('C value (log scale)')
plt.ylabel('Accuracy')
plt.title('Effect of C value on Accuracy')
plt.legend()
plt.grid(True)

# 绘制训练时间折线图
plt.subplot(1, 2, 2)
plt.plot(C_values, time_scores, marker='o', label='Training Time')
plt.xscale('log')
plt.xlabel('C value (log scale)')
plt.ylabel('Training Time (seconds)')
plt.title('Effect of C value on Training Time')
plt.legend()
plt.grid(True)


plt.tight_layout()
plt.show()

​

由于线性核的决策边界相对简单,通常使用较小的C值来更好地控制模型的复杂性并避免过饱和。因此,尝试了10^-3到10^3总共7个不同的C值。我们可以看到,当C值为10^-1时,SVM分类器的准确率最高。
我们可以看到,当C值很小(如10^-3和10^-2)时,测试集和训练集的准确性都很低。这是因为过小的C值会使模型对错误分类的数据点更加容忍,使SVM更倾向于找到平滑的决策边界,这是不匹配的,导致分类性能不佳。同时,鸢尾花数据集的特点也给分类带来了一定的障碍。Iris数据集有三个类别,数据点之间的类别边界相对清晰。如果C值较小,则模型无法捕捉到这一清晰的边界,因此表现不佳。
同时,我还试图研究C值对SVM分类器模型训练时间的影响,得出的结论是,在这个数据集中,C值对训练时间几乎没有影响。虽然折线图可能看起来有很大的变化,但实际的时间差很小。

C值在乳腺癌线性SVM中的影响

import time
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score

# 加载乳腺癌数据集
breast_cancer = datasets.load_breast_cancer()
X_cancer = breast_cancer.data
y_cancer = breast_cancer.target

# 分割数据集为训练集和测试集
X_cancer_train, X_cancer_test, y_cancer_train, y_cancer_test = train_test_split(X_cancer, y_cancer, test_size=0.3, random_state=42)

# 标准化数据
scaler_cancer = StandardScaler().fit(X_cancer_train)
X_cancer_train = scaler_cancer.transform(X_cancer_train)
X_cancer_test = scaler_cancer.transform(X_cancer_test)

# 定义C值范围
C_values = np.logspace(-3, 3, 10)

# 存储训练和测试准确率以及训练时间
train_accuracies = []
test_accuracies = []
training_times = []

for C in C_values:
    # 训练LinearSVM模型
    svm_cancer = SVC(kernel='linear', C=C)
    start_time = time.time()
    svm_cancer.fit(X_cancer_train, y_cancer_train)
    end_time = time.time()
    
    # 预测并评估性能
    y_cancer_train_pred = svm_cancer.predict(X_cancer_train)
    y_cancer_test_pred = svm_cancer.predict(X_cancer_test)
    
    train_accuracy = accuracy_score(y_cancer_train, y_cancer_train_pred)
    test_accuracy = accuracy_score(y_cancer_test, y_cancer_test_pred)
    training_time = end_time - start_time
    
    train_accuracies.append(train_accuracy)
    test_accuracies.append(test_accuracy)
    training_times.append(training_time)

# 绘制准确率折线图
plt.figure(figsize=(14, 6))
plt.subplot(1, 2, 1)
plt.plot(C_values, train_accuracies, label='Train Accuracy')
plt.plot(C_values, test_accuracies, label='Test Accuracy')
plt.xscale('log')
plt.xlabel('C value (log scale)')
plt.ylabel('Accuracy')
plt.title('Effect of C value on Accuracy')
plt.grid(True)
plt.legend()

# 绘制训练时间折线图
plt.subplot(1, 2, 2)
plt.plot(C_values, training_times, label='Training Time')
plt.xscale('log')
plt.xlabel('C value (log scale)')
plt.ylabel('Training Time (seconds)')
plt.title('Effect of C value on Training Time')
plt.legend()
plt.grid(True)

plt.tight_layout()
plt.show()

训练集的准确性随着C值的增加而逐渐提高,达到近100%。因为较大的C值降低了模型对错误分类数据点的容忍度,所以它更严格地拟合训练数据。这减少了训练集上的错误,提高了训练精度。
当C值较小时,测试集的精度逐渐提高,达到最大值,然后随着C值的进一步增加而降低。当C值较小时,模型相对简单,对错误分类的惩罚过于宽松,导致拟合不足,从而降低测试集的准确性。当C值达到中等范围时,该模型在复杂性和泛化能力之间达到了平衡,从而在测试集上表现最佳。当C值太大时,模型会变得太复杂,并过度拟合训练数据。这就是为什么我们可以看到,尽管训练集的准确率接近100%,但测试集的泛化能力下降,测试集的准确度也下降。
从第二条折线图可以看出,训练时间随着C值的增加而逐渐增加。这是因为增加的C值要求模型更严格地拟合数据,并且模型需要更长的训练时间进行计算。

差异对比

在上述实验中,发现两个数据集对线性SVM模型的C值的响应存在显著差异。特别是在测试集的准确性方面,我们可以看到虹膜数据集在C值较大时可以适应,而乳腺癌症数据集存在严重的过拟合现象。原因可能是癌症数据集更加复杂。这表明在调整C值时,我们需要根据特定数据集的特征和分布进行选择,以找到最佳方法。

不同训练测试比对线性SVM的影响

鸢尾花数据集

import time
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

## 设置属性防止中文乱码
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False

## Get data
# 'sepal length', 'sepal width', 'petal length', 'petal width'
iris_feature = u'花萼长度', u'花萼宽度', u'花瓣长度', u'花瓣宽度'
path = 'C:/数据集地址/iristest/iris.data'  
data = pd.read_csv(path, header=None)
x, y = data[list(range(4))], data[4]
y = pd.Categorical(y).codes 
x = x[[0, 1]] ## If use petal length and width, change to x[[2,3]]

training_ratios = np.linspace(0.1,0.9,9)

train_accuracies = []
test_accuracies = []

for ratio in training_ratios:
    ## Data segmentation
    x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=28, train_size=ratio)
    
    # 初始化线性SVM分类器
    clf = SVC(kernel='linear')
    
    # 训练分类器
    clf.fit(x_train, y_train)
    
    # 预测训练集
    y_train_pred = clf.predict(x_train)
    train_accuracy = accuracy_score(y_train, y_train_pred)
    train_accuracies.append(train_accuracy)
    
    # 预测测试集
    y_test_pred = clf.predict(x_test)
    test_accuracy = accuracy_score(y_test, y_test_pred)
    test_accuracies.append(test_accuracy)

# 绘制训练集比例与准确性的关系图
plt.figure(figsize=(10, 6))
plt.plot(training_ratios, train_accuracies, marker='o',label = '训练集准确率')
plt.plot(training_ratios, test_accuracies, marker='o',label = '测试集准确率')
plt.title('Effect of Training Set Size on Linear SVM Performance')
plt.xlabel('Training Set Ratio')
plt.ylabel('Accuracy')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

不同的数据分类也会对SVM模型训练的准确性产生不同的影响。在这项研究中,改变了训练集和测试集的比率,并使用0.1到0.9的10个比率值来比较和研究比率对SVM模型训练准确性的影响。比率值表示训练集和总数据集之间的比率。如果该比率为0.1,则意味着总数据将分为10%用于训练,90%用于测试。

一般来说,训练比率越高,模型通常需要学习的信息就越多,从而提高了测试集的准确性。然而,在我们的研究中,我们会发现测试结果与预期不一致。
在实验中,当训练数据比率为0.1时,由于给定的数据量不足,训练集的准确性异常高。然而,由于缺乏全面的训练,模型在训练过程中学习到的特征不能很好地推广到测试数据中,导致测试集的准确性低。随着训练数据比例的增加,测试集的准确性也逐渐提高。
然而,当训练数据比率为0.9时,测试集的准确性实际上非常低。这是因为模型对训练数据进行了过度拟合,尽管数据的训练精度很高,但在测试数据上表现不佳。当训练数据比为0.5时,测试集的精度最高,最接近训练集的精度。

乳腺癌数据集

import time
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score

# 加载乳腺癌数据集
breast_cancer = datasets.load_breast_cancer()
x_cancer = breast_cancer.data
y_cancer = breast_cancer.target

#定义ratio范围
training_ratios = np.linspace(0.1,0.9,9)

# 存储训练和测试准确率
train_accuracies = []
test_accuracies = []

for ratio in training_ratios:
    ## Data segmentation
    # 分割数据集为训练集和测试集
    x_cancer_train, x_cancer_test, y_cancer_train, y_cancer_test  = train_test_split(x_cancer, y_cancer, random_state=28, train_size=ratio)
    
    # 标准化数据
    scaler_cancer = StandardScaler().fit(x_cancer_train)
    x_cancer_train = scaler_cancer.transform(x_cancer_train)
    x_cancer_test = scaler_cancer.transform(x_cancer_test)

    
    # 初始化线性SVM分类器
    clf = SVC(kernel='linear')
    
    # 训练分类器
    clf.fit(x_cancer_train, y_cancer_train)
    
    # 预测训练集
    y_train_pred = clf.predict(x_cancer_train)
    train_accuracy = accuracy_score(y_cancer_train, y_train_pred)
    train_accuracies.append(train_accuracy)
    
    # 预测测试集
    y_test_pred = clf.predict(x_cancer_test)
    test_accuracy = accuracy_score(y_cancer_test, y_test_pred)
    test_accuracies.append(test_accuracy)

# 绘制训练集比例与准确性的关系图
plt.figure(figsize=(10, 6))
plt.plot(training_ratios, train_accuracies, marker='o',label = 'Train Accuracy')
plt.plot(training_ratios, test_accuracies, marker='o',label = 'Test Accuracy')
plt.title('Effect of Training Set Size on Linear SVM Performance')
plt.xlabel('Training Set Ratio')
plt.ylabel('Accuracy')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

在折线图中,我们可以看到训练集的准确率通常很高,接近100%。虽然测试集的精度随着比率的变化而略有变化,但总体精度相对较高,在0.90到0.96之间保持稳定。
这是因为癌症乳腺数据集较大,接近虹膜数据集的5倍,因此虽然比例较小,但对癌症乳腺数据集测试集的准确性影响不大。然而,当比率为0.9时,测试集的准确性显著降低,这可能是由于测试集的比例较小,数据代表性不足。
通过这些分析,我们可以看到,在训练模型时,有必要根据具体情况选择合适的训练集比率,以实现最佳性能。不同数据集的特征也会对模型的性能产生不同的影响。

不同kernel function对数据集分类的影响

介绍四种kernel function

使用的核有:线性核,多项式核、sigmoid核和径向基函数(RBF),并与我们刚刚尝试的线性核进行了比较。首先,我需要介绍这些不同内核的区别和优缺点。

  • 线性核是最简单的核函数,计算复杂度低。其数学表达式为:K(x,y)=x·y,其中x,y是输入向量,·表示点积。它简单易懂,计算效率高,参数少,适用于线性可分数据。然而,线性核不能处理复杂的非线性关系。
  • 多项式核多项式核表达式为:K(x,y)=(γx*y+r)^d多核可以处理线性和非线性关系,具有很强的适应性。它可以通过参数调整来控制模型的复杂性。同时,它具有很强的表达能力,适用于具有多项式特征关系的数据。然而,多个内核有多个参数,调优过程很复杂。此外,高阶多项式核很容易导致过拟合,需要适当的正则化。
  • Sigmoid Kernel Sigmoid Kernel表达式为:K(x,y)=tanh(γx·y+r)Sigmoid可以处理非线性关系,类似于神经网络的激活函数,可以在一定程度上模拟神经网络的行为。然而,Sigmoid的调谐过程复杂且不稳定,需要仔细调整参数。
  • 径向基函数核(RBF):RBF核表达式为:K(x,y)=exp(-γ||x-y||^2)RBF可以处理具有非线性关系的数据。与多项式核相比,RBF只有gamma参数和SVM的内置C值,这使得参数调整相对简单。RBF可以将低维特征映射到高维空间,使非线性可分数据在高维空间中线性可分。能够适应数据的复杂性,具有高度的灵活性,适用于各种类型的数据集。同时,RBF还具有良好的泛化能力。缺点是参数调整过程很复杂。在处理大规模数据集时,计算工作量大,训练时间长。

测试不同kernel function

鸢尾花数据集
import time
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

## 设置属性防止中文乱码
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False

## Get data
# 'sepal length', 'sepal width', 'petal length', 'petal width'
iris_feature = u'花萼长度', u'花萼宽度', u'花瓣长度', u'花瓣宽度'
path = 'C:/数据集地址/iristest/iris.data'  
data = pd.read_csv(path, header=None)
x, y = data[list(range(4))], data[4]
y = pd.Categorical(y).codes 
x = x[[0, 1]] ## If use petal length and width, change to x[[2,3]]

## 数据分割
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=28, train_size=0.6)

## 数据SVM分类器构建
svm_models = {
    'Polynomial Kernel': SVC(kernel='poly', degree=3, gamma='auto', random_state=42),
    'Sigmoid Kernel': SVC(kernel='sigmoid', gamma='auto', random_state=42),
    'RBF Kernel': SVC(kernel='rbf', gamma='auto', random_state=42),
    'Linear Kernel': SVC(kernel='linear', random_state=42)
}

# 存储每个核函数下的训练准确率和测试准确率,耗时
train_accuracies = []
test_accuracies = []
time_scores = []

# 训练和评估模型
for label, model in svm_models.items():
    t1 = time.time() 
    model.fit(x_train, y_train)
    t2 = time.time() 
    train_time = t2 - t1
    y_train_pred = model.predict(x_train)
    y_test_pred = model.predict(x_test)
    train_acc = accuracy_score(y_train, y_train_pred)
    test_acc = accuracy_score(y_test, y_test_pred)
    
    train_accuracies.append(train_acc)
    test_accuracies.append(test_acc)
    time_scores.append(train_time)
    print(f"{label} - Training Accuracy: {train_acc:.2f}, Testing Accuracy: {test_acc:.2f}")

# 绘制训练和测试准确率对比图
plt.figure(figsize=(10, 6))
labels = list(svm_models.keys())
x = np.arange(len(labels))

#bar柱形图
#plt.bar(x - width/2, train_accuracies, width, label='训练准确率')
#plt.bar(x + width/2, test_accuracies, width, label='测试准确率')

# plot折线图
plt.subplot(121)
plt.plot(labels, train_accuracies, lw=2, marker='o', label=u'训练集准确率')
plt.plot(labels, test_accuracies, lw=2, marker='s', label=u'测试集准确率')
plt.xlabel('Kernel Functions')
plt.ylabel('准确率')
plt.title('不同Kernel对SVM模型准确率的影响图')
plt.xticks(x, labels)
plt.legend()
plt.grid(True)
plt.tight_layout()

plt.subplot(122)
plt.plot(labels, time_scores, lw=2, marker='o', label='时长')
plt.xlabel('Kernel Functions')
plt.ylabel('模型训练耗时')
plt.title('不同Kernel对SVM模型耗时的影响')
plt.xticks(x, labels)
plt.legend()
plt.grid(True)
plt.tight_layout()

plt.show()

根据实验结果,线性核和RBF核在精度上表现更好。多项式核测试集具有较高的精度,但训练时间相对较长。然而,sigmoid内核在iris数据集上表现不佳。

乳腺癌数据集
import time
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score

# 加载乳腺癌数据集
breast_cancer = datasets.load_breast_cancer()
X_cancer = breast_cancer.data
y_cancer = breast_cancer.target

# 分割数据集为训练集和测试集
X_cancer_train, X_cancer_test, y_cancer_train, y_cancer_test = train_test_split(X_cancer, y_cancer, test_size=0.3, random_state=42)

# 标准化数据
scaler_cancer = StandardScaler().fit(X_cancer_train)
X_cancer_train = scaler_cancer.transform(X_cancer_train)
X_cancer_test = scaler_cancer.transform(X_cancer_test)

# 定义不同的核函数
kernels = {
    'Polynomial Kernel': SVC(kernel='poly', degree=3, gamma='auto', random_state=42),
    'Sigmoid Kernel': SVC(kernel='sigmoid', gamma='auto', random_state=42),
    'RBF Kernel': SVC(kernel='rbf', gamma='auto', random_state=42),
    'Linear Kernel': SVC(kernel='linear', random_state=42)
}

# 存储结果
train_accuracies = []
test_accuracies = []
training_times = []
kernel_names = []

for name, svm in kernels.items():
    # 训练SVM模型
    start_time = time.time()
    svm.fit(X_cancer_train, y_cancer_train)
    end_time = time.time()
    
    # 预测并评估性能
    y_cancer_train_pred = svm.predict(X_cancer_train)
    y_cancer_test_pred = svm.predict(X_cancer_test)
    
    train_accuracy = accuracy_score(y_cancer_train, y_cancer_train_pred)
    test_accuracy = accuracy_score(y_cancer_test, y_cancer_test_pred)
    training_time = end_time - start_time
    
    train_accuracies.append(train_accuracy)
    test_accuracies.append(test_accuracy)
    training_times.append(training_time)
    kernel_names.append(name)


# 绘制准确率折线图
plt.figure(figsize=(14, 6))
plt.subplot(1, 2, 1)
plt.plot(kernel_names, train_accuracies, label='Train Accuracy')
plt.plot(kernel_names, test_accuracies, label='Test Accuracy')
plt.xlabel('Kernel Function')
plt.ylabel('Accuracy')
plt.title('Effect of Kernel Function on Accuracy')
plt.grid(True)
plt.legend()
# 绘制训练时间折线图
plt.subplot(1, 2, 2)
plt.plot(kernel_names, training_times, label='Training Time')
plt.xlabel('Kernel Function')
plt.ylabel('Training Time (seconds)')
plt.title('Effect of Kernel Function on Training Time')
plt.grid(True)
plt.legend()

plt.tight_layout()
plt.show()

# 可视化点图
plt.figure(figsize=(20, 20))
for i, (name, svm) in enumerate(kernels.items(), 1):
    plt.subplot(2, 2, i)
    svm.fit(X_cancer_train[:, :2], y_cancer_train)  # 使用前两个特征进行可视化
    x_min, x_max = X_cancer_train[:, 0].min() - 1, X_cancer_train[:, 0].max() + 1
    y_min, y_max = X_cancer_train[:, 1].min() - 1, X_cancer_train[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.01), np.arange(y_min, y_max, 0.01))
    Z = svm.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    
    plt.contourf(xx, yy, Z, alpha=0.8)
    plt.scatter(X_cancer_train[:, 0], X_cancer_train[:, 1], c=y_cancer_train, edgecolors='k', marker='o')
    plt.title(name)
    plt.xlabel('Feature 1')
    plt.ylabel('Feature 2')
    plt.grid(True)

plt.tight_layout()
plt.show()

在癌症数据集的实验数据中,线性核和RBF核的精度表现良好,而多项式核和S型核的精度较差。这是因为癌症数据集具有很强的线性可分性,允许线性核和RBF核有效地处理数据。相比之下,多项式核和sigmoid核不适合这个数据集。
不同数据集对不同核函数的响应是不一样的。在选择核函数时,我们需要综合考虑数据特性和计算资源,以实现最佳的模型性能。

学习总结

通过分析支持向量机在各种数据集上的分类能力,探索不同参数和核函数的影响,我学到了很多东西,加深了对支持向量机的理解,积累了很多经验,引发了很多思考。我深入研究了SVM的原理,并为实验准备了两个不同的数据集。我研究了正则化参数C值和训练比对模型性能的影响,以及不同核函数对不同数据集的实验和分析效果。虽然这些反思和研究报告可能看起来只有几段,但从分析研究数据、研究原则、尝试代码、分析现象到通过无数过程寻找原因,这份研究报告给我带来了很多收获。
在改变正则化参数的实验中,我意识到了参数调整在训练模型中的重要性。C值决定了SVM的惩罚强度,较小的C值会导致训练不足和拟合不足,而较大的C值则试图正确分类所有训练样本并导致过拟合。因此,在正式应用SVM时,我们需要为给定的数据集找到最佳的C值,并仔细调整参数。
在改变训练和测试数据比率的实验中,我发现适度的训练数据对于保持模型训练的有效性是必要的。
在寻找适合数据集的最佳核函数的实验中,我理解并测试了不同的核函数。在了解它们的特性的同时,我也了解了如何使用不同的内核函数。例如,实验中的四个核函数,线性核适用于线性可分数据,具有很高的计算效率。多项式核适用于具有多项式关系的数据,但它们更复杂。sigmoid核类似于神经网络中的激活函数,但在上述两个数据集上表现不佳。尽管RBF核需要更长的训练时间,但它们适用于大多数情况,特别能够分析具有复杂非线性边界的数据。
这个学习报告是我学习SVM的灵感,引导我探索和接近机器学习的世界。通过对不同数据集、核函数和SVM参数的实践经验,我对如何构建有效的机器学习模型和机器学习的复杂性有了初步的了解,并对其产生了浓厚的兴趣。

  • 16
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值