python 支持向量机预测_揭开机器学习的面纱:SVM 100行代码实现[Python版]

之前对机器学习的理解,仅仅停留在书本上的推导公式,或者对一些开源工具的使用上。高大上的机器学习究竟如何训练、怎样预测的,对我们来说就像是一个黑盒充满神秘。今天,我们就以经典的机器学习算法SVM为例,抛开各种实际处理上的tricky, 实现一个简单纯洁的SVM,用CODING说话,揭开SVM的神秘面纱,让机器学习的过程更加接地气!

原理就不多说了:hinge损失函数+L2正则化+梯度下降,Python代码如下svm.py【注意,为了减少代码量,替身阅读效率,省掉了很多鲁棒性检测的代码】:

#!/usr/bin/python

#coding=utf8

import sys;

import random;

import math;

EPS = 0.000000001 # 很小的数字,用于判断浮点数是否等于0

def load_data(filename, data, dim):

'''

输入数据格式: label\tindex1:value1\tindex2:value2\tindex3:value3..., 其中index是特征的编号, 从1开始

data的数据格式: [[label, sample],[label, sample], ...], 其中sample: [v0, v1, v2, v3, ..., v[dim]]

'''

for line in open(filename, 'rt'):

sample = [0.0 for v in range(0, dim + 1)];

line = line.rstrip("\r\n\t ");

fields = line.split("\t");

label = int(fields[0]); # LABEL取值: 1 or -1

sample[0] = 1.0; #sample第一个元素用于存x0特征, 默认置为1.0[方便把 WX+b => WX]

for field in fields[1:]:

kv = field.split(":");

idx = int(kv[0]); # ensure idx >= 1

val = float(kv[1]);

sample[idx] = val;

data.append((label, sample));

def svm_train(data4train, dim, W, iterations, lm, lr):

'''

目标函数: obj(, W) = (对所有SUM{max{0, 1 - W*X*y}}) + lm / 2 * ||W||^2, 即:hinge+L2

'''

X = [0.0 for v in range(0, dim + 1)]; # =>

grad = [0.0 for v in range(0, dim + 1)]; # 梯度

num_train = len(data4train);

for i in range(0, iterations):

#每次迭代随机选择一个训练样本

index = random.randint(0, num_train - 1);

y = data4train[index][0]; # y其实就是label

for j in range(0, dim + 1):

X[j] = data4train[index][1][j];# sample的vj

#计算梯度

#for j in range(0, dim + 1):

#grad = lm * W[j];

WX = 0.0;

for j in range(0, dim + 1):

WX += W[j] * X[j];

if 1 - WX *y > 0:

for j in range(0, dim + 1):

grad[j] = lm * W[j] - X[j] * y;

else: # 1-WX *y <= 0的时候,目标函数的前半部分恒等于0, 梯度也是0

for j in range(0, dim + 1):

grad[j] = lm * W[j] - 0;

#更新权重, lr是学习速率

for j in range(0, dim + 1):

W[j] = W[j] - lr * grad[j];

def svm_predict(data4test, dim , W):

num_test = len(data4test);

num_correct = 0;

for i in range(0, num_test):

target = data4test[i][0]; #即label

X = data4test[i][1]; # 即sample

sum = 0.0;

for j in range(0, dim + 1):

sum += X[j] * W[j];

predict = -1;

#print sum;

if sum > 0: #权值>0,认为目标值为1

predict = 1;

if predict * target > 0: #预测值和目标值符号相同

num_correct += 1;

return num_correct * 1.0 / num_test;

if __name__ == "__main__":

'''

主函数:设置参数=>导入数据=>训练=>输出结果

'''

#设置参数

epochs = 100;#迭代轮数

iterations = 10;#每一轮中梯度下降迭代次数, 这个其实可以和epochs合并为一个参数

data4train = []; #训练集, 假设每个样本的特征数量都一样

data4test = []; #测试集, 假设每个样本的特征数量都一样

lm = 0.0001; #lambda, 对权值做正则化限制的权重

lr = 0.01; #lr, 是学习速率,用于调整训练收敛的速度

dim = 1000;#dim, 特征的最大维度, 所有样本不同特征总数

W = [0.0 for v in range(0, dim + 1)]; #权值

#导入测试集&训练集

load_data("train.txt", data4train, dim);

load_data("test.txt", data4test, dim);

#训练, 实际迭代次数=epochs * iterations

for i in range(0, epochs):

svm_train(data4train, dim, W, iterations, lm, lr);

accuracy = svm_predict(data4test, dim, W);

print "epoch:%d\taccuracy:%f"%(i, accuracy);

#输出结果权值

for i in range(0, dim + 1):

if math.fabs(W[i]) > EPS:

print "%d\t%f"%(i, W[i]);

sys.exit(0);

附:手工编的少量测试集和训练集数据:train test, 非常简陋的数据,可以简单用作测试。

运行python svm.py, 运行结果:

1.png

参考:飞旋的世界SVM的C代码实现,做了一些修正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值