李航博士-统计学习方法-SVM-python实现

2023-05-16

下面的代码是根据李航博士《统计学习方法》一书写的SVM的实现。还有些问题,贴出来大家给些建议。

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
Created on Thu Oct 19 16:05:09 2017


@author: ocean
"""
import numpy as np


def kernel(x1,x2):
    np_x1 = np.array(x1)
    np_x2 = np.array(x2)
    return np.dot(np_x1,np_x2)


class svm(object):
    def __init__(self,train_data,label, C=0.1, b = 0):
        #each row is a sample
        self.x = train_data
        self.y = label
        self.N = x.shape[0]
        self.alpha = np.zeros([self.N])#N by 1
        self.C = C
        self.b = b
        self.support_vector_idx=set()# the index of support vector, i.e., 0<alpha[support_vector_idx[i]]<C
    #
    def predict(self, xi):
        '''
        output the prediction of xi
        '''
        s = 0
        for j in xrange(self.N):
            s = s + self.alpha[j]*self.y[j]*kernel(self.x[j,:],xi)
        p = s + self.b
        return p
    #
    def choose_alpha1(self):
        '''
        see p 128-129
        '''
        epsilon = 1e-5
        for idx in self.support_vector_idx:
            if abs (self.y[idx]*self.predict(self.x[idx,:]) - 1) < epsilon:
                continue
            return idx
        for idx in xrange(self.N):
            if abs(self.alpha[idx]-0)<epsilon and self.y[idx]*self.predict(self.x[idx,:])>=1-epsilon:
                continue
            if abs(self.alpha[idx]-self.C)<epsilon and self.y[idx]*self.predict(self.x[idx,:]) <=1+epsilon:
                continue
            return idx
    #
    def choose_alpha2(self, alpha1_idx):
        E1 = self.predict(self.x[alpha1_idx,:]) - self.y[alpha1_idx]
        alpha2_idx = 0
        max_e = -9999999999
        for i in xrange(self.N):
            if i == alpha1_idx:
                continue
            E2 = self.predict(self.x[i,:]) - self.y[i]
            if abs(E1-E2) > max_e:# |E1-E2|
                max_e = abs(E1-E2)
                alpha2_idx = i
        return alpha2_idx
    #
    def get_L_H(self, alpha1_idx, alpha2_idx):
        y1 = self.y[alpha1_idx]
        y2 = self.y[alpha2_idx]
        alpha1 = self.alpha[alpha1_idx]
        alpha2 = self.alpha[alpha2_idx]
        #
        if y1 != y2:
            L = max(0, alpha2-alpha1)
            H = min(self.C, self.C+alpha2-alpha1)
        else:
            L = max(0, alpha2+alpha1-self.C)
            H = min(C, alpha2+alpha1)
        return L,H
    #
    def update_alpha_b(self, alpha1_idx,alpha2_idx):
        y1 = self.y[alpha1_idx]
        y2 = self.y[alpha2_idx]
        E1 = self.predict(self.x[alpha1_idx,:]) - self.y[alpha1_idx]
        E2 = self.predict(self.x[alpha2_idx,:]) - self.y[alpha2_idx]
        eta = kernel(self.x[alpha1_idx,:], self.x[alpha1_idx,:]) \
              +kernel(self.x[alpha2_idx,:], self.x[alpha2_idx,:]) \
              -2*kernel(self.x[alpha1_idx,:], self.x[alpha2_idx,:])
        alpha1_old = self.alpha[alpha1_idx]
        alpha2_old = self.alpha[alpha2_idx]
        #
        L,H = self.get_L_H(alpha1_idx,alpha2_idx)
        #
        alpha2_new_unc = alpha2_old + (y2*(E1-E2))/eta
        #
        if alpha2_new_unc > H:
            alpha2_new = H
        elif alpha2_new_unc < L:
            alpha2_new = L
        else:
            alpha2_new = alpha2_new_unc
        #
        alpha1_new = alpha1_old + y1*y2*(alpha2_old-alpha2_new)
        #
        self.update_b(alpha1_idx,alpha2_idx,alpha1_new,alpha2_new)
        
        self.alpha[alpha1_idx] = alpha1_new
        self.alpha[alpha2_idx] = alpha2_new
        self.update_support_vector_idx(alpha1_idx,alpha2_idx)
        #
    #see p 129-130
    def update_b(self,alpha1_idx,alpha2_idx,alpha1_new,alpha2_new):
        y1 = self.y[alpha1_idx]
        y2 = self.y[alpha2_idx]
        x1 = self.x[alpha1_idx,:]
        x2 = self.x[alpha2_idx,:]
        alpha1_old = self.alpha[alpha1_idx]
        alpha2_old = self.alpha[alpha2_idx]
        K11 = kernel(x1,x1)
        K21 = kernel(x2,x1)
        K12 = kernel(x1,x2)
        K22 = kernel(x2,x2)
        E1 = self.predict(x1) - self.y[alpha1_idx]
        E2 = self.predict(x2) - self.y[alpha2_idx]
        #
        b1_new = -E1 - y1*K11*(alpha1_new-alpha1_old) - y2*K21*(alpha2_new-alpha2_old) + self.b
        b2_new = -E2 - y1*K12*(alpha1_new-alpha1_old) - y2*K22*(alpha2_new-alpha2_old) + self.b
        
        epsilon = 1e-5
        if (alpha1_new>0 and alpha1_new < self.C) and (alpha2_new > 0 and alpha2_new < self.C):
            assert(abs(b1_new - b2_new)<epsilon)
            self.b = b1_new
        else:
            self.b = (b1_new + b2_new)/2
            
    #
    def update_support_vector_idx(self, alpha1_idx,alpha2_idx):
        epsilon = 1e-5
        alpha1_new = self.alpha[alpha1_idx]
        alpha2_new = self.alpha[alpha2_idx]
        #
        if alpha1_new > 0 and alpha1_new < self.C:
            self.support_vector_idx.add(alpha1_idx)
        else:
            try:
                self.support_vector_idx.remove(alpha1_idx)
            except:
                pass
        #
        if alpha2_new > 0 and alpha2_new < self.C:
            self.support_vector_idx.add(alpha2_idx)
        else:
            try:
                self.support_vector_idx.remove(alpha2_idx)
            except:
                pass


    #
    def is_stop(self):
        epsilon = 1e-5
        #condition 1,2,3
        s = 0        
        for i in xrange(self.N):
            alphai = self.alpha[i]
            yi = self.y[i]
            xi = self.x[i,:]
            g_xi = self.predict(xi)
            #
            s += alphai*yi
            #
            if alphai < -epsilon or alphai > self.C + epsilon:
                return False
            #
            if (abs(alphai-0)<epsilon and yi*g_xi >=1) \
               or (alphai > 0-epsilon and alphai < self.C+epsilon and abs(yi*g_xi-1)<epsilon) \
               or (abs(alphai - self.C)<epsilon and yi*g_xi <= 1):
                continue
            else:
                return False
        if abs(s - 0)<=epsilon:
            return True
        else:
            return False
    #
    def train(self):
        while True:
            alpha1_idx = self.choose_alpha1()
            alpha2_idx = self.choose_alpha2(alpha1_idx)
            #
            self.update_alpha_b(alpha1_idx,alpha2_idx)
            #
            if self.is_stop():
                break
            print self.alpha
            print self.support_vector_idx
            for i in xrange(self.N):
                print self.predict(self.x[i,:])
        


#load data
x = np.loadtxt('train_data')
y = np.loadtxt('train_label')
n = x.shape[0]
#initialize alpha,C
#alpha_0 = np.zeros([n,1])
C = 0.1
b = 0
my_svm = svm(x,y,C,b)
my_svm.train()
print my_svm.alpha
print my_svm.support_vector_idx


#################下面是产生随机样本的代码###########

#代码是别人的,连接丢失了怎么也找不到,大家如果知道,请联系我,我尽快引用上。


# encoding=utf8
import numpy as np
import random
import matplotlib
import matplotlib.pyplot as plt


N = 10 #生成训练数据的个数


# AX=0 相当于matlab中 null(a','r')
def null(a, rtol=1e-5):
    u, s, v = np.linalg.svd(a)
    rank = (s > rtol*s[0]).sum()
    return rank, v[rank:].T.copy()


# 符号函数,之后要进行向量化
def sign(x):
    if x > 0:
        return 1
    elif x == 0:
        return 0
    elif x < 0:
        return -1
#noisy=False,那么就会生成N的dim维的线性可分数据X,标签为y
#noisy=True, 那么生成的数据是线性不可分的,标签为y
def mk_data(N, noisy=False):
    rang = [-10,10]
    dim = 2


    X=np.random.rand(dim,N)*(rang[1]-rang[0])+rang[0]


    while True:
        Xsample = np.concatenate((np.ones((1,dim)), np.random.rand(dim,dim)*(rang[1]-rang[0])+rang[0]))
        k,w=null(Xsample.T)
        y = sign(np.dot(w.T,np.concatenate((np.ones((1,N)), X))))
        if np.all(y):
            break


    if noisy == True:
        idx = random.sample(range(1,N), N/10)


        for id in idx:
            y[0][id] = -y[0][id]


    return (X,y,w)


def data_visualization(X,y,title):
    class_1 = [[],[]]
    class_2 = [[],[]]


    size = len(y)


    for i in xrange(size):
        X_1 = X[0][i]
        X_2 = X[1][i]


        if y[i] == 1:
            class_1[0].append(X_1)
            class_1[1].append(X_2)
        else:
            class_2[0].append(X_1)
            class_2[1].append(X_2)




    plt.figure(figsize=(8, 6), dpi=80)
    plt.title(title)


    axes = plt.subplot(111)


    type1 = axes.scatter(class_1[0], class_1[1], s=20, c='red')
    type2 = axes.scatter(class_2[0], class_2[1], s=20, c='green')




    plt.show()


def rebuild_features(features):
    size = len(features[0])


    new_features = []
    for i in xrange(size):
        new_features.append([features[0][i],features[1][i]])


    return new_features


def generate_dataset(size, noisy = False, visualization = True):
    global sign
    sign = np.vectorize(sign)
    X,y,w = mk_data(size,False)
    y = list(y[0])


    if visualization:
        data_visualization(X,y,'all data')         #数据可视化


    testset_size = int(len(y)*0.333)


    indexes = [i for i in xrange(len(y))]
    test_indexes = random.sample(indexes,testset_size)
    train_indexes = list(set(indexes)-set(test_indexes))


    trainset_features = [[],[]]
    trainset_labels = []


    testset_features = [[],[]]
    testset_labels = []


    for i in test_indexes:
        testset_features[0].append(X[0][i])
        testset_features[1].append(X[1][i])
        testset_labels.append(y[i])




    if visualization:
        data_visualization(testset_features,testset_labels,'test set')


    for i in train_indexes:
        trainset_features[0].append(X[0][i])
        trainset_features[1].append(X[1][i])
        trainset_labels.append(y[i])


    if visualization:
        data_visualization(trainset_features,trainset_labels,'train set')


    return rebuild_features(trainset_features),trainset_labels,rebuild_features(testset_features),testset_labels






if __name__ == '__main__':


    size = 1000
    generate_dataset(size)


    # generate_dataset
    # print sign
    # sign = np.vectorize(sign)
    # X,y,w = mk_data(size,False)
    #
    # data_visualization(X,y)
# encoding=utf8

上面的svm代码存在一些小问题,如果大家看出来请留言....








本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

李航博士-统计学习方法-SVM-python实现 的相关文章

  • 路由器开发(一)—— 路由器硬件结构及软件体系

    一 路由器的硬件构成 路由器主要由以下几个部分组成 xff1a 输入 输出接口部分 包转发或交换结构部分 xff08 switching fabric xff09 路由计算或处理部分 如图所示 图1 路由器的基本组成 输入端口是物理链路和输
  • Linux 设备驱动开发思想 —— 驱动分层与驱动分离

    前面我们学习I2C USB SD驱动时 xff0c 有没有发现一个共性 xff0c 就是在驱动开发时 xff0c 每个驱动都分层三部分 xff0c 由上到下分别是 xff1a 1 XXX 设备驱动 2 XXX 核心层 3 XXX 主机控制器
  • C++ 学习基础篇(一)—— C++与C 的区别

    编程的学习学无止境 xff0c 只掌握一门语言是远远不够的 xff0c 现在我们开始C 43 43 的学习之路 xff0c 下面先看下C 43 43 与C 的区别 一 C 43 43 概述 1 发展历史 1980年 xff0c Bjarne
  • Linux 网络协议栈开发基础篇(七)—— 网桥br0

    一 桥接的概念 简单来说 xff0c 桥接就是把一台机器上的若干个网络接口 连接 起来 其结果是 xff0c 其中一个网口收到的报文会被复制给其他网口并发送出去 以使得网口之间的报文能够互相转发 交换机就是这样一个设备 xff0c 它有若干
  • 常用的18个免费论文文献网站,分享给大家

    1 掌桥科研 掌桥科研文献资源库涵盖中英文期刊 xff0c 会议 xff0c 报告等多种资源 xff0c 拥有1 2多亿文献资源 xff0c 值得一提的是 xff0c 它整合了目前国际上主流的英文文献数据库 xff0c 涵盖了诸如Sprin
  • 必备外文文献网站,有外文文献翻译功能

    国内好多同学面对外文文献论文都有一个共同的槽点 xff0c 那就是翻译的问题 xff0c 好不容易找到了自己想要的外文文献 xff0c 结果那长篇大论的专业术语看不懂 xff0c 还需另找软件翻译 xff0c 这确实太麻烦了 图片来自于网络
  • 国内常用的5个中文期刊论文网站,5个外文文献网站

    作为一名科研汪 xff0c 日常工作就是找资料 xff0c 查文献 xff0c 做实验 xff0c 现在我给大家分享10个中外文献论文网站 xff0c 助同僚们在日常中能节省一些时间 xff0c 能更快有效地找到自己需要的资料文献 5个中文
  • 能查阅国外文献的8个论文网站(最新整理)

    这几天又新发现了几个论文网站 xff0c 有用的话请拿走 xff01 1 CALIS公共目录检索系统 这里是 传送门 2 掌桥科研一站式服务平台 这里是 传送门 3 NSTL文献检索 这里是 传送门 4 CASHL目录系统 这里是 传送门
  • java里的自动装箱和自动拆箱

    所有的基本类型都有与之对应的类 xff0c 例如 xff1a int Integer byte Byte short Short long Long float Float double Double char Char boolean B
  • 热门文献|陈国生:实证化中医基础理论依据及应用

    题名 xff1a 实证化中医基础理论依据及应用 作者 xff1a 陈国生 摘要 xff1a 中医基础理论在日地月天体运行图中的反映以成不争的事实 xff0c 然而笼统地概念对经络名称的划分 对称的机制 手足经络的区别 还需要加以澄清 xff
  • 全球IEEE期刊大全(综合整理,附原文论文下载地址)

    本文整理了来自全球的IEEE期刊 xff0c 一共有67种 xff0c 共计305236篇论文 期刊类别 xff1a 1 Industrial Electronics IEEE Transactions on 2 IEEE transact
  • 论文怎么添加引用参考文献(附word添加引用标注教程)

    第一步 xff1a 登录 掌桥科研 xff0c 掌桥科研是专业检索下载论文的网站 xff0c 能找到各个学科专业的中外学术期刊和论文 xff08 1 3亿多篇 xff09 地址 xff1a zhangqiaokeyan com LSDN 2
  • 2020年经济学专业论文选题参考(20个选题+部分参考文献)

    2020年经济学专业论文选题参考 xff08 20个选题 43 部分参考文献 xff09 1 一带一路 沿线主要区域集团人口及社会经济分布特征 2 房价 金融发展对技术创新的影响 3 共享经济背景下资源有效利用研究 4 基于新农村建设的农业
  • 自动化技术、计算机技术核心期刊整理及介绍

    本文由掌桥科研整理 xff0c 平台提供中外文献检索获取 xff0c 拥有1 3亿 43 篇 xff0c 中外专利1 4亿 43 条 xff0c 月更新百万篇 xff0c 是科研人员与硕博研究生必备平台之一 内容参考网站 xff1a 掌桥科
  • intel cpu 分类 i7、i5、i3、T系列、P系列

    现在市场的CPU有T系列 P系列 E系列 还有i3 i5 i7 T系列 xff0c 是intel 双核 xff0c 主要应用于笔记本 包括奔腾双核和酷睿双核 xff0c 2以下的 xff0c 比如T2140 xff0c 是奔腾双核 2以上
  • 2021年计算机保研面试题

    准备计算机保研面试题 注意点 大家都是第一次 没有保研经验 xff0c 所以担心会被问专业课知识相关的东西 但是结合博主自己的经历 xff0c 本人双非保到某985 xff0c 过程中问的最多的是项目相关问题 xff0c 并不会设计太多专业
  • 阿里云源码编译内核并替换

    1 介绍 阿里云新机器 xff1a 系统Ubuntu 16 04内存16G4核CPU 源码编译Linux最新stable版本内核 xff0c 并替换现有内核使用新内核 2 编译 2 1 安装依赖 apt update apt apt get
  • 记录一次wordpress站点迁移过程

    迁移和备份还原的区别是针对不同的install而言的 xff0c 使用上的区别可能是访问的IP会变 几乎所有系统的备份还原都主要涉及下面两个方面 xff0c wordpress也不例外 xff1a 数据库 xff1a mysqldump x
  • ubuntu16.04桌面美化

    先晒一张桌面图 xff1a 电脑是笔记本 xff0c 尺寸13 3 1080P 主要修改如下 xff1a 桌面壁纸 主题 缩放Unity面板左上角 34 Ubuntu Desktop 34 下部类似MacOS中的启动栏 桌面壁纸 主题 缩放
  • Java Math类的函数计算方法汇总

    java lang Math类中包含基本的数字操作 xff0c 如指数 对数 平方根和三角函数 java math是一个包 xff0c 提供用于执行任意精度整数 BigInteger 算法和任意精度小数 BigDecimal 算法的类 ja

随机推荐

  • Ubuntu截图快捷键

    系统设置 键盘 截图查看截图键的设置 xff1a 总结下 xff1a 对整个屏幕截图 xff1a Prt Sc xff08 PrintScreen xff0c 打印按钮 xff09 当前当前窗口截图 xff1a Alt 43 Prt Sc自
  • Ubuntu翻译任何选中的文字

    1 问题 Google Chrome浏览器可以集成Google Translator插件 xff0c 实现浏览器页面文字的翻译 xff0c 但是除了浏览器 xff0c PDF LibreOffice等软件上面的文字也经常需要翻译 Ubunt
  • 关于字符集和编码你应该知道的

    1 Introduction 大部分程序员都会认为 xff1a plain text 61 ascii 61 character xff0c 如我们使用的A字符 xff0c 就是一个字节 8bits Unicode字符集占用2个字节 xff
  • 2019 年 吉林大学 软件学硕967 回忆题

    2019年吉林大学软件工程专业硕士967回忆 一简单题 1给了一个中缀表达式转化为后缀表达式 2给了一组数字 xff0c 用快速排序进行排序 xff0c 写出每一趟的过程 3给了一组11个元素的有序表 xff0c 进行二分查找33 xff0
  • 南京工业大学校园网(智慧南工)自动登录

    前言 南京工业大学校园网 智慧南工 Njtech Home宿舍网自动登录 多平台可用 目前实现windows xff0c macos xff0c openwrt xff0c ios平台自动登录 由于gitee所有项目私有 xff0c 公开需
  • js前端实现语言识别(asr)与录音

    js前端实现语言识别与录音 前言 实习的时候 xff0c 领导要求验证一下在web前端实现录音和语音识别 xff0c 查了一下发现网上有关语音识别也就是语音转文字几乎没有任何教程 其实有一种方案 xff0c 前端先录音然后把录音传到后端 x
  • [Nice_try]python基础学习笔记(六)

    六 函数 局部变量 全局变量 6 1 1函数的概念 将特定功能的代码集成到一个模块中 xff0c 在需要调用的时候进行调用 可以防止内容的重复编写 6 1 2函数的定义 span class token keyword def span 函
  • 论文写作感悟

    以下是学习论文写作课程之后的一些感悟以及收获 xff0c 总结如下 xff1a 关于格式 xff1a 1 在写论文的过程中 xff0c 使用LaTeX排版系统能够让论文显得更加专业 xff0c 而且对公式 排版的处理会更加美观 2 在论文中
  • 软件工程概论第一次作业

    习题 一 单项选择 1 软件是计算机系统中与硬件相互依存的另一部分 xff0c 它是包括 1 B 2 A 及 3 D 的完整集合 其中 xff0c 1 B 是按事先设计的功能和性能要求执行的指令序列 2 A 是使程序能够正确操纵信息的数据结
  • Java递归发实现Fibonacci数列,尾递归实现Fibonacci数列,并获取计算所需时间

    递归法计算Fibonacci数列 xff1a 它可以递归地定义为 xff1a 第n个Fibonacci数列可递归地计算如下 xff1a int fibonacci int n if n lt 61 1 return 1 return fib
  • apache-options配置之Indexes

    配置 Options Indexes FollowSymLinks Indexs的配置的作用是如果不存在Index html文件的时候 xff0c 将该目录下的文件树列出来 一般在线上使用
  • gcr.io和quay.io拉取镜像失败

    k8s在使用编排 xff08 manifest xff09 工具进行yaml文件启动pod时 xff0c 会遇到官方所给例子中spec containers image包含 xff1a quay io coreos example gcr
  • yacs直接读取yaml文档(python)

    yacs在我理解是一种读写配置文件的python包 在机器学习领域 xff0c 很多模型需要设置超参数 xff0c 当超参数过多时 xff0c 不方便管理 xff0c 于是出现了很多类似yaml xff0c yacs的包 关于yacs的使用
  • 基于Gensim的Word2Vec增量式训练方法

    Word2Vec训练好以后 xff0c 随着时间的积累 xff0c 出现一些新词 xff0c 此时可能需要在已有的模型基础上重新训练 xff0c 以补充这些新词汇 xff0c 亦即增量式训练 本文分析了基于Gensim的Word2Vec的增
  • Numpy/Pytorch中函数参数dim/axis到底怎么用?

    numpy或pytorch中很多函数可指定参数dim或axis 例如sum函数 xff0c dim 61 0或dim 61 1是对矩阵列 行进行求和 xff0c 时间久了 xff0c 就搞混了 xff0c 如果是高维array tensor
  • Tensorflow中截断高斯分布(truncated norm)采样的python实现

    Tensorflow中可调用函数tf truncated normal来进行截断高斯分布的采样 什么是截断高斯分布 xff0c 看下图 xff0c 分布在 0 1和0 1处被截断了 xff0c 具体如下 import tensorflow
  • tf.contrib.image.transform与opencv中PerspectiveTransform

    tensorflow中tf contrib image transform函数可对图像做透视变换 xff0c 用法如下 读取图像 img 61 cv2 imread 39 home xp1 Pictures 004545 jpg 39 in
  • 转:模式识别 机器学习 计算机视觉 相关资料 论坛 网站 牛人...

    转自 http www cnblogs com kshenf archive 2012 02 07 2342034 html 常用牛人主页链接 xff08 计算机视觉 模式识别 机器学习相关方向 陆续更新 xff09 牛人主页 xff08
  • 李航统计学习方法EM算法三枚硬币例子Q函数推导

    具体推导如下 xff1a 上面推导省略了第i次迭代的i的标记 当得到上式以后 xff0c 可以参考 http www cnblogs com Determined22 p 5776791 html 来继续一下推导 当然 xff0c 参考博客
  • 李航博士-统计学习方法-SVM-python实现

    下面的代码是根据李航博士 统计学习方法 一书写的SVM的实现 还有些问题 xff0c 贴出来大家给些建议 usr bin env python2 coding utf 8 34 34 34 Created on Thu Oct 19 16