05_核支持向量機

描述

核支持向量機(通常簡稱為SVM)可以推廣到更復雜模型的擴展,這些模型無法被輸入空間的超平面定義。

SVM 的核心思想是找到一個最優的超平面,將不同類別的數據分開。這個超平面不僅要能夠正確分類數據,還要使得兩個類別之間的間隔(margin)最大化。

  • 超平面
    • 在二維空間中,超平面是一個直線
    • 在三維空間中,超平面是一個平面
    • 在更高維空間中,超平面是一個分割空間的超平面
  • 支持向量
    • 支持向量是離超平面最近的樣本點,這些支持向量對于定義超平面至關重要
    • 支持向量機通過最大化支持向量到超平面的距離(及最大化間隔)來選擇最佳超平面
  • 最大間隔
    • SVM的目標是最大化分類間隔,使得分類邊界盡可能遠離兩類數據點,這可以有效地減少模型的泛化誤差
  • 核技巧
    • 對于非線性可分的數據,SVM使用核函數將數據映射到更高維的空間,在這個空間中,數據可能是線性可分的。
    • 常用的核函數有:線性核、多項式核、徑向基函數(RBF)核等。

線性模型在低維空間中可能非常受限,因為線和平面的靈活性有限。有一種方法可以讓線性模型更加靈活,就是添加更多的特。

下面舉個例子,添加輸入特征的交互項或多項式:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import mglearn
import warnings
warnings.filterwarnings('ignore')X,Y=mglearn.datasets.make_blobs(centers=4,random_state=8) # 隨機創造一些數據
Y=Y%2mglearn.discrete_scatter(X[:, 0], X[:, 1], Y)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

執行上例,可以看到數據有明顯的分類

from sklearn.svm import LinearSVC
linear_svm = LinearSVC().fit(X, Y)mglearn.plots.plot_2d_separator(linear_svm, X)
mglearn.discrete_scatter(X[:, 0], X[:, 1], Y)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

用于分類的線性模型只能用一條直線來劃分數據點,對這個數據集無法給出較好的結果

X_new = np.hstack([X,X[:,1:]**2])from mpl_toolkits.mplot3d import Axes3D,art3dfigure = plt.figure()
ax = Axes3D(figure, elev=-152, azim=-26)
mask = Y == 0
ax.scatter(X_new[mask, 0], X_new[mask, 1], X_new[mask, 2], c='b',cmap=mglearn.cm2, s=60)
ax.scatter(X_new[~mask, 0], X_new[~mask, 1], X_new[~mask, 2], c='r', marker='^', cmap=mglearn.cm2, s=60)
ax.set_xlabel("feature0")
ax.set_ylabel("feature1")
ax.set_zlabel("feature1 ** 2")
figure.add_axes(ax)
plt.show()

上例中添加第二個特征的平方(feature1 ** 2)作為一個新特征。現在我們將每個數據點表示為三維點 (feature0, feature1, feature1 ** 2),而不是二維點 (feature0, feature1)。

linear_svm_3d = LinearSVC().fit(X_new,Y )
coef, intercept = linear_svm_3d.coef_.ravel(), linear_svm_3d.intercept_
figure = plt.figure()
ax = Axes3D(figure, elev=-152, azim=-26)
xx = np.linspace(X_new[:, 0].min() - 2, X_new[:, 0].max() + 2, 50)
yy = np.linspace(X_new[:, 1].min() - 2, X_new[:, 1].max() + 2, 50)
XX, YY = np.meshgrid(xx, yy)
ZZ = (coef[0] * XX + coef[1] * YY + intercept) / -coef[2]
ax.plot_surface(XX, YY, ZZ, rstride=8, cstride=8, alpha=0.3)
ax.scatter(X_new[mask, 0], X_new[mask, 1], X_new[mask, 2], c='b',cmap=mglearn.cm2, s=60)
ax.scatter(X_new[~mask, 0], X_new[~mask, 1], X_new[~mask, 2], c='r', marker='^',cmap=mglearn.cm2, s=60)
ax.set_xlabel("feature0")
ax.set_ylabel("feature1")
ax.set_zlabel("feature1 ** 2")
figure.add_axes(ax)
plt.show()

可以用線性模型(三維空間中的平面)將這兩個類別分開。

核技巧

向數據表示中添加非線性特征,可以讓線性模型變得更強大。但是,通常來說并不知道要添加哪些特征。有一種巧妙的數學技巧,可以在更高維空間中學習分類器,而不用實際計算可能非常大的新的數據表示。這種技巧叫作核技巧(kernel trick)。它的原理是直接計算擴展特征表示中數據點之間的距離(準確地說是內積),而不用實際對擴展進行計算。

對于支持向量機,將數據映射到更高維空間中有兩種常用的方法:

  • 多項式核:在一定階數內計算原始特征所有可能的多項式(比如 feature1 ** 2 * feature2 ** 5)
  • 徑向基函數核(高斯核):(對應無限維的特征空間)考慮所有階數的所有可能的多項式,但階數越高,特征的重要性越小。

不過在實踐中,核 SVM 背后的數學細節并不是很重要,主要是掌握用法、參數調優。

理解SVM

在訓練過程中,SVM 學習每個訓練數據點對于表示兩個類別之間的決策邊界的重要性。通常只有一部分訓練數據點對于定義決策邊界來說很重要:位于類別之間邊界上的那些點。這些點叫作支持向量(support vector)。

想要對新樣本點進行預測,需要測量它與每個支持向量之間的距離。分類決策是基于它與支持向量之間的距離以及在訓練過程中學到的支持向量重要性(保存在 SVC 的 dual_coef_屬性中)來做出的。

from sklearn.svm import SVCX,Y = mglearn.tools.make_handcrafted_dataset()
svm = SVC(kernel='rbf',C=10,gamma=0.1).fit(X,Y)
mglearn.plots.plot_2d_separator(svm, X, eps=.5)
mglearn.discrete_scatter(X[:, 0], X[:, 1], Y)
sv = svm.support_vectors_
sv_labels = svm.dual_coef_.ravel() > 0
mglearn.discrete_scatter(sv[:, 0], sv[:, 1], sv_labels, s=15, markeredgewidth=3)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

執行上例子,SVM 給出了非常平滑且非線性(不是直線)的邊界。

gamma 參數:用于控制高斯核的寬度,它決定了點與點之間“靠近”是指多大的距離。

C 參數:正則化參數,與線性模型中用到的類似,它限制每個點的重要性(或者更確切地說,每個點的 dual_coef_)。

fig,axes=plt.subplots(3,3,figsize=(15,10))for ax,C in zip(axes,[-1,0,3]):for a,gamma in zip(ax,range(-1,2)):mglearn.plots.plot_svm(log_C=C,log_gamma=gamma,ax=a)axes[0,0].legend(['class 0','class 1','sv class 0','sv class 1'],ncol=4,loc=(.9,1.2))

執行上例:

從左到右,將參數 gamma 的值從 0.1 增加到 10。gamma 較小,說明高斯核的半徑較大,許多點都被看作比較靠近。這一點可以在圖中看出:左側的圖決策邊界非常平滑,越向右的圖決策邊界更關注單個點。小的 gamma 值表示決策邊界變化很慢,生成的是復雜度較低的模型,而大的 gamma 值則會生成更為復雜的模型。

從上到下,將參數 C 的值從 0.1 增加到 1000。與線性模型相同,C 值很小,說明模型非常受限,每個數據點的影響范圍都有限。可以看到,左上角的圖中,決策邊界看起來幾乎是線性的,誤分類的點對邊界幾乎沒有任何影響。再看左下角的圖,增大 C 之后這些點對模型的影響變大,使得決策邊界發生彎曲來將這些點正確分類。

將 RBF 核 SVM 應用到乳腺癌數據集上。默認情況下,C=1,gamma=1/n_features:

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_splitcancer = load_breast_cancer()X_train,X_test,Y_train,Y_test=train_test_split(cancer.data,cancer.target,random_state=42)svc = SVC(C=1,gamma=1.0/len(X_train[0]))
svc.fit(X_train,Y_train)print(svc.score(X_train,Y_train),svc.score(X_test,Y_test))

執行上例,這個模型在訓練集上的分數十分完美,但在測試集上的精度打了6折,存在相當嚴重的過擬合。雖然 SVM 的表現通常都很好,但它對參數的設定和數據的縮放非常敏感。特別地,它要求所有特征有相似的變化范圍。

為SVM預處理數據

plt.plot(X_train.min(axis=0), 'o', label="min")
plt.plot(X_train.max(axis=0), '^', label="max")
plt.legend(loc=4)
plt.xlabel("Feature index")
plt.ylabel("Feature magnitude")
plt.yscale("log")

執行上例可以明顯看出,乳腺癌數據集的特征具有完全不同的數量級。這對其他模型來說(比如線性模型)可能是小問題,但對核 SVM 卻有極大影響。

解決這個問題的一種方法就是對每個特征進行縮放,使其大致都位于同一范圍。核 SVM常用的縮放方法就是將所有特征縮放到 0 和 1 之間。

min_on_training = X_train.min(axis=0) # 計算訓練集中每個特征的最小值
range_on_training = (X_train-min_on_training).max(axis=0) # 計算訓練集中每個特性的范圍(最大值-最小值)
# 減去最小值,然后除以范圍
# 這樣每個特征都是min=0和max=1
X_train_scaled = (X_train-min_on_training)/range_on_training
print("Minimum for each feature\n{}".format(X_train_scaled.min(axis=0)))
print("Maximum for each feature\n {}".format(X_train_scaled.max(axis=0)))# 利用訓練集的最小值和范圍對測試集做相同的變換
X_test_scaled = (X_test - min_on_training) / range_on_trainingsvc = SVC()
svc.fit(X_train_scaled,Y_train)
print(svc.score(X_train_scaled,Y_train),svc.score(X_test_scaled,Y_test))

可以嘗試增大 C 或 gamma 來擬合更為復雜的模型

svc = SVC(C=1000,gamma=2.0/len(X_train[0]))
svc.fit(X_train_scaled,Y_train)
print(svc.score(X_train_scaled,Y_train),svc.score(X_test_scaled,Y_test))

執行上面的兩個例子,可以明顯看到,測試得分有大幅度提高。

優缺點、參數

核支持向量機是非常強大的模型,在各種數據集上的表現都很好。SVM 允許決策邊界很復雜,即使數據只有幾個特征。它在低維數據和高維數據(即很少特征和很多特征)上的表現都很好,但對樣本個數的縮放表現不好。

SVM 的另一個缺點是,預處理數據和調參都需要非常小心。這也是為什么很多應用中用的都是基于樹的模型,比如隨機森林或梯度提升(需要很少的預處理,甚至不需要預處理)。此外,SVM 模型很難檢查,可能很難理解為什么會這么預測,而且也難以將模型向非專家進行解釋。

不過 SVM 仍然是值得嘗試的,特別是所有特征的測量單位相似(比如都是像素密度)而且范圍也差不多時。

參數:gamma 和 C 控制的都是模型復雜度,較大的值都對應更為復雜的模型。

  • C:正則化參數,較小的 C 值可以讓算法盡量適應“大多數”數據點,而較大的 C 值更強調每個數據點都分類正確的重要性。
  • gamma :用于控制高斯核的寬度,高斯核的半徑較大,許多點都被看作比較靠近。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/81724.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81724.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/81724.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java + 鴻蒙雙引擎:ZKmall開源商城如何定義下一代B2C商城技術標準?

在 B2C 電商領域持續革新的當下,技術架構的優劣成為決定商城競爭力的核心要素。ZKmall開源商城以其創新融合的 Java 與鴻蒙雙引擎,為下一代 B2C 商城技術標準勾勒出全新藍圖,在性能、兼容性、拓展性等關鍵維度實現了重大突破。 一、Java 技術…

關于 Web 漏洞原理與利用:3. CSRF(跨站請求偽造)

一、原理: 利用用戶登錄態偽造操作 CSRF(Cross-Site Request Forgery,跨站請求偽造)是攻擊者“借刀殺人”,借用用戶瀏覽器中已有的登錄狀態,誘導用戶完成攻擊者指定的操作。 1. 基本機制分解 1&#xf…

【HTML5】【AJAX的幾種封裝方法詳解】

【HTML5】【AJAX的幾種封裝方法詳解】 AJAX (Asynchronous JavaScript and XML) 封裝是為了簡化重復的異步請求代碼,提高開發效率和代碼復用性。下面我將介紹幾種常見的 AJAX 封裝方式。 方法1. 基于原生 XMLHttpRequest 的封裝 XMLHttpRequest。其主要特點如下…

C++ - 網絡編程之初始連接(Winsock2 概述、初始連接案例、初始連接案例解讀)

一、Winsock2 概述 Winsock2&#xff08;Windows Sockets 2&#xff09;是微軟提供的 Windows 平臺網絡編程庫 二、初始連接案例 1、Server #include <winsock2.h> #include <ws2tcpip.h> #include <iostream>#pragma comment(lib, "ws2_32.lib&quo…

Spring Cloud Gateway深度解析:原理、架構與生產實踐

文章目錄 前言一、概述二、核心架構設計及設計原理2.1 分層架構模型網絡層&#xff08;I/O模型&#xff09;核心處理層 2.2 核心組件協作流程路由定位階段過濾器執行階段 2.3 響應式編程模型實現Reactor上下文傳遞背壓處理機制 2.4 動態路由設計原理2.5 異常處理體系2.6 關鍵路…

游戲開發實戰(一):Python復刻「崩壞星穹鐵道」嗷嗚嗷嗚事務所---源碼級解析該小游戲背后的算法與設計模式【純原創】

文章目錄 奇美拉項目游戲規則奇美拉(Chimeras)檔案領隊成員 結果展示&#xff1a; 奇美拉項目 由于項目工程較大&#xff0c;并且我打算把我的思考過程和實現過程中踩過的坑都分享一下&#xff0c;因此會分3-4篇博文詳細講解本項目。本文首先介紹下游戲規則并給出奇美拉檔案。…

說一下響應狀態碼有哪些?

HTTP響應狀態碼分類(RFC 7231標準) 1. 1xx(信息類) 臨時響應,表示請求已被接收,需要繼續處理 100 Continue:客戶端應繼續發送請求體 101 Switching Protocols:服務器同意升級協議(如WebSocket) 102 Processing(WebDAV):服務器正在處理但未完成 2. 2xx(成功類)…

Linux多進程 寫時拷貝 物理地址和邏輯地址

如果不采用寫時拷貝技術 直接fork子進程 會發生什么&#xff1f; 如上圖所示 橙色為父進程所占內存空間 綠色為子進程所占內存空間。 如果子進程只是需要做出一點點和父進程不一樣的 其余和父進程均為相同 第一 就會出現復制開銷比較大&#xff1b;第二占用內存空間 所以 …

【TTS回顧】Bert-VITS2深度解析:融合BERT的多語言語音合成模型

一、基本介紹 Bert-VITS2是基于VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的改進版本,通過整合BERT語義編碼能力,顯著提升了語音合成的自然度和表現力。項目地址:https://github.com/fishaudio/Bert-VITS2 語種自然度相似度流…

win11下docker 的使用方案

Windows 11 Docker 使用方式對比 特性Docker Desktop (使用 WSL 2 后端)直接在 WSL 2 中安裝 Docker Engine安裝與易用性極簡&#xff0c;一鍵安裝&#xff0c;提供直觀的 GUI 界面 管理容器、鏡像、卷等相對復雜&#xff0c;需手動在 Linux 環境中安裝 Docker Daemon 并配置G…

配合本專欄前端文章對應的后端文章——從模擬到展示:一步步搭建傳感器數據交互系統

對應文章&#xff1a;進一步完善前端框架搭建及vue-konva依賴的使用&#xff08;Vscode&#xff09;-CSDN博客 目錄 一、后端開發 1.模擬傳感器數據 2.前端頁面呈現數據后端互通 2.1更新模擬傳感器數據程序&#xff08;多次請求&#xff09; 2.2&#x1f9e9; 功能目標 …

牛客網NC209794:使徒襲來

牛客網NC209794:使徒襲來 題目背景 問題分析 數學建模 設三位駕駛員的戰斗力分別為 a, b, c已知條件&#xff1a;a b c n (n為輸入的正整數)目標&#xff1a;求 a b c 的最小值 解題思路 根據算術-幾何平均值不等式(AM-GM不等式)&#xff0c;對于任意正實數a, b, c&a…

動態規劃之爬樓梯模型

文章目錄 爬樓梯模型LeetCode 746. 使用最小花費爬樓梯思路Golang 代碼 LeetCode 377. 組合總和 Ⅳ思路Golang 代碼 LeetCode 2466. 統計構造好字符串的方案數思路Golang 代碼 LeetCode 2266. 統計打字方案數思路Golang 代碼 爬樓梯模型 爬樓梯模型是動態規劃當中的一個經典模型…

【每天一個知識點】湖倉一體(Data Lakehouse)

“湖倉一體”&#xff08;Data Lakehouse&#xff09;是一種融合了數據湖&#xff08;Data Lake&#xff09;與數據倉庫&#xff08;Data Warehouse&#xff09;優勢的新型數據架構。它既繼承了數據湖對多類型數據的靈活存儲能力&#xff0c;也具備數據倉庫對結構化數據的高效查…

Linux | mdadm 創建軟 RAID

注&#xff1a;本文為 “Linux mdadm RAID” 相關文章合輯。 略作重排&#xff0c;未整理去重。 如有內容異常&#xff0c;請看原文。 Linux 下用 mdadm 創建軟 RAID 以及避坑 喵??&#xfecc;?? Oct 31, 2023 前言 linux 下組軟 raid 用 mdadm 命令&#xff0c;multi…

Unity自定義shader打包SpriteAtlas圖集問題

Unity打包圖集還是有一些坑的&#xff0c;至于圖集SpriteAtlas是什么請參考我之前寫的文章&#xff1a;【Sprite Atlas】Unity新圖集系統SpriteAtlas超詳細使用教程_spriteatlas 使用-CSDN博客 問題&#xff1a; 今天碰到的問題是&#xff0c;shader繪制的時候&#xff0c;因…

如何用 OceanBase 的 LOAD DATA 旁路導入進行大表遷移

前言 在日常工作中&#xff0c;我們時常會遇到需要將某個大數據量的單表進行遷移的情況。在MySQL中&#xff0c;針對這樣的大表&#xff0c;我們通常會選擇先將原表導出為csv格式&#xff0c;然后利用LOAD DATA語法來導入csv文件&#xff0c;這種方法相較于mysqldump在效率上有…

VR 互動實訓的顯著優勢?

&#xff08;一&#xff09;沉浸式學習&#xff0c;提升培訓效果? 在 VR 互動實訓中&#xff0c;員工不再是被動的知識接受者&#xff0c;而是主動的參與者。以銷售培訓為例&#xff0c;員工戴上 VR 設備&#xff0c;就能置身于逼真的銷售場景中&#xff0c;與虛擬客戶進行面對…

OpenCV 第6課 圖像處理之幾何變換(重映射)

1. 概述 簡單來說,重映射就是把一副圖像內的像素點按照規則映射到到另外一幅圖像內的對應位置上去,形成一張新的圖像。 因為原圖像與目標圖像的像素坐標不是一一對應的。一般情況下,我們通過重映射來表達每個像素的位置(x,y),像這樣: g(x,y)=f(h(x,y)) 在這里g()是目標圖…

Java虛擬機 - 程序計數器和虛擬機棧

運行時數據結構 Java運行時數據區程序計數器為什么需要程序計數器執行流程虛擬機棧虛擬機棧作用虛擬機棧核心結構運行機制 Java運行時數據區 首先介紹Java運行時數據之前&#xff0c;我們要了解&#xff0c;對于計算機來說&#xff0c;內存是非常重要的資源&#xff0c;因為內…