机器学习:支持向量机

支持向量机(Support Vector Machine)是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的广义线性分类器,其学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解。

在这里插入图片描述

假设两类数据可以被 H = x : w T x + b ≥ c H = {x:w^Tx + b \ge c} H=x:wTx+bc分离,垂直于法向量 w w w,移动 H H H直到碰到某个训练点,可以得到两个超平面 H 1 H_1 H1 H 2 H_2 H2,两个平面称为支撑超平面,题目分别支撑两类数据。而位于 H 1 H_1 H1 H 2 H_2 H2正中间的超平面是分离这两类数据的最好选择。支持向量就是离分隔超平面最近的那些点。

法向量 w w w有很多种选择,超平面 H 1 H_1 H1 H 2 H_2 H2之间的距离称为间隔,这个间隔是 w w w的函数,**目的就是寻找这样的 w w w使得间隔达到最大。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在求解最优化问题中,拉格朗日乘子法(Lagrange Multiplier)和KKT(Karush Kuhn Tucker)条件是两种最常用的方法。在有等式约束时使用拉格朗日乘子法,在有不等约束时使用KKT条件。

  • 拉格朗日乘子法

    拉格朗日乘子法是一种寻找多元函数在一组约束下的极值的方法。通过引入拉格朗日乘子,可将有 d d d个变量与 k k k个约束条件的最优化问题转化为具有 d + k d+k d+k个变量的无约束优化问题求解。

  • 二次规划

    二次规划是一类典型的优化问题,包括凸二次优化和非凸二次优化。在此类问题中,目标函数是变量的二次函数,而约束条件是变量的线性不等式。
    m i n 1 2 x T Q x + c T x s . t . A ⃗ x ⃗ ≤ b ⃗ min \frac{1} {2} x^T Q x + c^T x \\ s.t. \vec{A} \vec{x} \le \vec{b} min21xTQx+cTxs.t.A x b

具体公式证明:【整理】深入理解拉格朗日乘子法(Lagrange Multiplier) 和KKT条件 - mo_wang - 博客园 (cnblogs.com)

序列最小优化(Sequential Minimal Optimization,SMO)

序列最小优化是将大优化问题分界成多个小优化问题来求解。

SMO算法工作原理:每次循环中选择两个变量进行优化处理。一旦找到一对合适的变量,那么就增大其中一个同时减小另一个。这里的“合适”指的是两个变量必须要符合一定的条件,条件之一就是这两个变量必须要在间隔边界之外,而其第二个条件则是这两个变量还没有进行过区间化处理或者不在边界上。

在这里插入图片描述

代码实现

参考《机器学习实战》,代码链接:https://github.com/golitter/Decoding-ML-Top10/tree/master/SVM

这里采用简化的SMO代码,数据集是https://blog.caiyongji.com/assets/mouse_viral_study.csv。

data_processing.py

import numpy as np
import pandas as pd# https://zhuanlan.zhihu.com/p/350836534
def data_processing():data_csv = pd.read_csv('mouse_viral_study.csv')data_csv = data_csv.dropna()# print(data_csv)X = data_csv.iloc[:-1, 0:2].values# print(X)Y = data_csv.iloc[:-1, 2].map({0: -1, 1: 1}).valuesY = Y.reshape(-1, 1)# print(Y.shape)return X, Y# X, Y = data_processing()
# print(X)

工具模块,smo_assist.py

import random
def select_Jrandom(i:int, m:int) -> int:"""随机选择一个不等于 i 的整数"""j = iwhile j == i:j = int(random.uniform(0, m))return jdef clip_alpha(alpha_j:float, H:float, L:float) -> float:"""修剪 alpha_j"""if alpha_j > H:alpha_j = Hif alpha_j < L:alpha_j = Lreturn alpha_j

简化SMO的代码实现,smoSimple.py

from smo_assist import (select_Jrandom, clip_alpha)import numpy as np
import pdbdef smoSimple(data_mat_in:np.ndarray, class_labels:np.ndarray, C:float, toler:float, max_iter:int):"""data_mat_in: 数据集class_labels: 类别标签C: 松弛变量toler: 容错率max_iter: 最大迭代次数"""b = 0; # 初始化bm, n = np.shape(data_mat_in) # m: 样本数, n: 特征数alphas = np.zeros((m, 1)) # 初始化alphaiter = 0 # 迭代次数while iter < max_iter:alphaPairsChanged = 0for i in range(m):fXi = float(np.multiply(alphas, class_labels).T @ (data_mat_in @ data_mat_in[i, :].T)) + b"""(1 , m) * (m, n) * (n, 1) = (1, 1) = 标量再 加上 b 就是 f(x) 的值"""Ei = fXi - float(class_labels[i])"""Ei = f(x) - y 预测误差"""if (# 第一种情况:样本被误分类,且权重可以增加((class_labels[i] * Ei < -toler) # 预测误差与标签方向相反,且误差大于容忍度and (alphas[i] < C)) # 当前权重小于正则化参数 C,可以增加权重or # 第二种情况:样本被误分类,且权重需要调整((class_labels[i] * Ei > toler) # 预测误差与标签方向相同,且误差大于容忍度and (alphas[i] > 0)) # 当前权重大于 0,需要调整权重):j = select_Jrandom(i, m)fxj = float(np.multiply(alphas, class_labels).T @ (data_mat_in @ data_mat_in[j, :].T)) + bEj = fxj - float(class_labels[j])alpha_j_old = alphas[j].copy(); alpha_i_old = alphas[i].copy()if (class_labels[i] != class_labels[j]):L = max(0, alphas[j] - alphas[i]) # 左边界H = min(C, C + alphas[j] - alphas[i]) # 右边界else:L = max(0, alphas[j] + alphas[i] - C)H = min(C, alphas[j] + alphas[i])if L == H: continue # 跳出本次循环eta = 2.0 * data_mat_in[i, :] @ data_mat_in[j, :].T - data_mat_in[i, :] @ data_mat_in[i, :].T - data_mat_in[j, :] @ data_mat_in[j, :].T"""计算 eta = K11 + K22 - 2 * K12 = 2 * x_i * x_j - x_i * x_i - x_j * x_j """     if eta >= 0:continuealphas[j] -= class_labels[j] * (Ei - Ej) / eta # 更新权重alphas[j] = clip_alpha(alphas[j], H, L) # 调整权重if abs(alphas[j] - alpha_j_old) < 0.00001:continue # 跳出本次循环,不更新 ialphas[i] += class_labels[j] * class_labels[i] * (alpha_j_old - alphas[j]) # 更新权重b1 = b - Ei - class_labels[i] * (alphas[i] - alpha_i_old) * data_mat_in[i, :] @ data_mat_in[i, :].T - class_labels[j] *(alphas[j] - alpha_j_old) * data_mat_in[i, :] @ data_mat_in[j, :].Tb2 = b - Ej - class_labels[i] * (alphas[i] - alpha_i_old) * data_mat_in[i, :] @ data_mat_in[j, :].T - class_labels[j] *(alphas[j] - alpha_j_old) * data_mat_in[j, :] @ data_mat_in[j, :].T"""更新 b"""     if 0 < alphas[i] < C:b = b1elif 0 < alphas[j] < C:b = b2else:b = (b1 + b2) / 2.0alphaPairsChanged += 1if alphaPairsChanged == 0:iter += 1else:iter = 0return b, alphasif __name__ == '__main__':print(  smoSimple(np.array([[1, 2], [3, 4]]), np.array([[-1],[1]]), 0.6, 0.001, 40))

test.py

from data_processing import *
from smoSimple import *
import numpy as np
import matplotlib.pyplot as plt# 数据处理和 SVM 训练
data_mat_in, class_labels = data_processing()
b, alphas = smoSimple(data_mat_in, class_labels, 0.6, 0.001, 40)# 打印结果
print("Bias (b):", b)
print("Non-zero alphas:", alphas[alphas > 0])# 打印数据形状
print("Shape of data_mat_in:", np.shape(data_mat_in))
print("Shape of class_labels:", np.shape(class_labels))# 将 Y 转换为一维数组(如果它是二维的)
Y = class_labels
# 提取不同类别的索引
class_1_indices = np.where(Y == 1)[0]  # 类别为 1 的样本索引
class_2_indices = np.where(Y == -1)[0]  # 类别为 -1 的样本索引
X = data_mat_in# 绘制散点图
plt.figure(figsize=(8, 6))
plt.scatter(X[class_1_indices, 0], X[class_1_indices, 1], c='blue', label='Class 1', alpha=0.5)
plt.scatter(X[class_2_indices, 0], X[class_2_indices, 1], c='red', label='Class -1', alpha=0.5)# 计算权重向量 w
w = np.dot((alphas * Y).T, X).flatten()
# print(f"w: {w}")
print("Shape of X:", X.shape)  # 应该是 (m, n)
print("Shape of Y:", Y.shape)  # 应该是 (m, 1)
print("Shape of alphas:", alphas.shape)  # 应该是 (m, 1)# 绘制超平面
# 超平面方程:w[0] * x1 + w[1] * x2 + b = 0
# 解出 x2: x2 = -(w[0] * x1 + b) / w[1]
x1 = np.linspace(np.min(X[:, 0]), np.max(X[:, 0]), 100)
x2 = -(w[0] * x1 + b) / w[1]
print(f"w_shape: {w.shape}")
# 绘制超平面
plt.plot(x1, x2, label='SVM Hyperplane', color='green', linewidth=2)# 标出支持向量
support_vectors_indices = np.where(alphas > 0)[0]  # 找到所有支持向量的索引
plt.scatter(X[support_vectors_indices, 0], X[support_vectors_indices, 1], facecolors='none', edgecolors='k', s=50, label='Support Vectors')# 添加图例和标签
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.title('Scatter Plot of Data with SVM Hyperplane')
plt.legend()# 显示图形
plt.show()

在这里插入图片描述

ML_AI_SourceCode-/支持向量机 at master · sjyttkl/ML_AI_SourceCode- (github.com)

机器学习:支持向量机(SVM)-CSDN博客

【整理】深入理解拉格朗日乘子法(Lagrange Multiplier) 和KKT条件 - mo_wang - 博客园 (cnblogs.com)

机器学习(四):通俗理解支持向量机SVM及代码实践 - 知乎 (zhihu.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/8860.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

相互作用感知的蛋白-小分子对接模型 - Interformer 评测

Interformer 是一个应用于分子对接和亲和力预测的深度学习模型&#xff0c;基于 Graph-Transdormer 架构的模型&#xff0c;利用相互作用&#xff08;氢键、疏水&#xff09;感知的混合密度网络&#xff08;interaction-aware mixture den sity network&#xff0c; MDN&#x…

如果我想设计一款复古风格的壁纸,应该选什么颜色?

设计复古风格的壁纸时&#xff0c;选择合适的颜色是营造怀旧和经典氛围的关键。复古风格通常使用一些温暖、柔和且带有岁月痕迹的色调。以下是一些适合复古风格壁纸的颜色选择和搭配建议&#xff1a; 一、复古风格的主色调 棕色系&#xff1a; 特点&#xff1a;棕色是复古风格的…

AI 浪潮席卷中国年,开启科技新春新纪元

在这博主提前祝大家蛇年快乐呀&#xff01;&#xff01;&#xff01; 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;其影响力已经渗透到社会生活的方方面面。在中国传统节日 —— 春节期间&#xff0c;AI 技术也展现出了巨大的潜力&#xff0c;为中国年带…

WPS数据分析000007

目录 一、分列 智能分列 出生日期 数值转换 公式不运算 二、数据对比 离职员工 新入职员工 都在职的员工 三、合并计算 四、拆分表格 合并表格 一、分列 智能分列 出生日期 数据求和 文本型数字左对齐&#xff1b;数值型数字右对齐 数值转换 方式一&#xff1a; 方…

fps一些内容添加

1 增强输入要点记录 输入 &#xff1a;输入值的类型 布尔 1d&#xff0c;2d&#xff0c;3d 映射&#xff1a;就是确定按键输入键位&#xff0c;输入类型&#xff0c;和一些触发器&#xff08;按键方式&#xff09;修改器&#xff08;对输出值进行修改&#xff09; 基本的&am…

深入探讨数据库索引类型:B-tree、Hash、GIN与GiST的对比与应用

title: 深入探讨数据库索引类型:B-tree、Hash、GIN与GiST的对比与应用 date: 2025/1/26 updated: 2025/1/26 author: cmdragon excerpt: 在现代数据库管理系统中,索引技术是提高查询性能的重要手段。当数据量不断增长时,如何快速、有效地访问这些数据成为了数据库设计的核…

【反悔堆】【hard】力扣871. 最低加油次数

汽车从起点出发驶向目的地&#xff0c;该目的地位于出发位置东面 target 英里处。 沿途有加油站&#xff0c;用数组 stations 表示。其中 stations[i] [positioni, fueli] 表示第 i 个加油站位于出发位置东面 positioni 英里处&#xff0c;并且有 fueli 升汽油。 假设汽车油…

知识库建设对提升团队协作与创新能力的影响分析

内容概要 在当今快速变革的商业环境中&#xff0c;知识库建设的重要性愈发凸显。它不仅是信息存储的载体&#xff0c;更是推动组织内部沟通与协作的基石。通过系统整理与管理企业知识&#xff0c;团队成员能够便捷地访问相关信息&#xff0c;使得协作过程更为流畅&#xff0c;…

SpringBoot-Vue整合百度地图

文章目录 一、Spring Boot整合百度地图的步骤1. 申请百度地图的AK值2. 创建实体类3. 创建Controller层4. 前端集成百度地图4.1 在Vue项目中安装百度地图Vue组件库4.2 在Vue项目中引入百度地图API4.3 创建地图组件 二、实现功能说明1. 前端部分&#xff1a;2. 后端部分&#xff…

【Docker】快速部署 Nacos 注册中心

【Docker】快速部署 Nacos 注册中心 引言 Nacos 注册中心是一个用于服务发现和配置管理的开源项目。提供了动态服务发现、服务健康检查、动态配置管理和服务管理等功能&#xff0c;帮助开发者更轻松地构建微服务架构。 步骤 拉取镜像 docker pull nacos/nacos-server启动容器…

RAG技术:通过向量检索增强模型理解与生成能力

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

Java设计模式:行为型模式→策略模式

Java 策略模式详解 1. 定义 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一系列的算法&#xff0c;将每一个算法封装起来&#xff0c;并使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户。通过这种模式&#xf…

linux通过deb包安装(命令模式)

通过下载deb包安装Chrome浏览器 - lyy19s Wikihttps://lyy1119.github.io/%E8%BD%AF%E4%BB%B6%E4%BD%BF%E7%94%A8/Linux/InstallChrome/

C基础寒假练习(4)

输入带空格的字符串&#xff0c;求单词个数、 #include <stdio.h> // 计算字符串长度的函数 size_t my_strlen(const char *str) {size_t len 0;while (str[len] ! \0) {len;}return len; }int main() {char str[100];printf("请输入一个字符串: ");fgets(…

Android View 的事件分发机制解析

前言&#xff1a;当一个事件发生时&#xff08;例如触摸屏幕&#xff09;&#xff0c;事件会从根View&#xff08;通常是Activity的布局中的最顶层View&#xff09;开始&#xff0c;通过一个特定的路径传递到具体的View&#xff0c;这个过程涉及到三个关键的阶段&#xff1a;事…

WPS数据分析000005

目录 一、数据录入技巧 二、一维表 三、填充柄 向下自动填充 自动填充选项 日期填充 星期自定义 自定义序列 1-10000序列 四、智能填充 五、数据有效性 出错警告 输入信息 下拉列表 六、记录单 七、导入数据 ​编辑 八、查找录入 会员功能 Xlookup函数 VL…

【Spring】Spring启示录

目录 前言 一、示例程序 二、OCP开闭原则 三、依赖倒置原则DIP 四、控制反转IOC 总结 前言 在软件开发的世界里&#xff0c;随着项目的增长和需求的变化&#xff0c;如何保持代码的灵活性、可维护性和扩展性成为了每个开发者必须面对的问题。传统的面向过程或基于类的设计…

爬虫基础之爬取某基金网站+数据分析

声明: 本案例仅供学习参考使用&#xff0c;任何不法的活动均与本作者无关 网站:天天基金网(1234567.com.cn) --首批独立基金销售机构-- 东方财富网旗下基金平台! 本案例所需要的模块: 1.requests 2.re(内置) 3.pandas 4.pyecharts 其他均需要 pip install 模块名 爬取步骤: …

set集合

set集合 Set系列集合&#xff1a; 无序&#xff1a;存取顺序不一致 不重复&#xff1a;可以去除重复 无索引&#xff1a;没有带索引的方法&#xff0c;所以不能使用普通for循环遍历&#xff0c;也不能通过索引来获取元素 可以看出set是无序的存和打印的顺序不一样 Set接中的…

借DeepSeek-R1东风,开启创业新机遇

DeepSeek-R1的崛起 DeepSeek-R1的推出引发了广泛关注&#xff0c;在AI领域引起了一阵旋风。作为新一代的智能模型&#xff0c;它在多项任务中表现出了卓越的能力。普通人可以借助这个强大的工具&#xff0c;开启属于自己的创业之路&#xff0c;抓住时代带来的机遇。 内容创作…