package com.jd;
import java.util.ArrayList;
import java.util.List;
public class _4_support_vector_machine {
static class dim_two{
public List<Double> L = new ArrayList<Double>();
public dim_two(double x1, double x2, double flag){
L.add(x1);
L.add(x2);
L.add(flag);
}
}
static List<List<Double>> example_init(){
List<List<Double>> examples = new ArrayList<List<Double>>();
examples.add(new dim_two(0.0,1.0,1.0).L);
examples.add(new dim_two(1.0,2.0,1.0).L);
examples.add(new dim_two(2.0,3.0,1.0).L);
examples.add(new dim_two(1.0,0.0,-1.0).L);
examples.add(new dim_two(2.0,1.0,-1.0).L);
// examples.add(new dim_two(3.0,2.0,-1.0).L);
// examples.add(new dim_two(4.0,3.0,-1.0).L);
return examples;
}
static List<Double> L_copy(List<Double> L){
List<Double> L1 = new ArrayList<Double>();
for(Double d:L){
L1.add(d);
}
return L1;
}
static List<List<Double>> liner_core(List<List<Double>> X){
List<List<Double>> core = new ArrayList<List<Double>>();
for(int i=0; i<X.size(); i++){
List<Double> L = new ArrayList<Double>();
for(int j=0; j<X.size(); j++){
double core_ij = 0;
for(int k=0; k<X.get(0).size(); k++){
core_ij += X.get(i).get(k)*X.get(j).get(k);
}
L.add(core_ij);
}
core.add(L);
}
return core;
}
static void alpha_Q(List<Double> Y, List<Double> alpha, List<List<Double>>core, int idex1, int idex2){
double a = 0;
double b = 0;
a = -0.5*Y.get(idex1)*Y.get(idex1)*(core.get(idex1).get(idex1)-2*core.get(idex1).get(idex2)+core.get(idex2).get(idex2));
b = 1-Y.get(idex1)/Y.get(idex2);
for(int i=0; i<Y.size(); i++){
if(i==idex1 || i==idex2){
continue;
}
b += 2*Y.get(idex1)*(core.get(idex1).get(i)-core.get(idex2).get(i)-core.get(idex1).get(idex2)+core.get(idex2).get(idex2))*alpha.get(i)*Y.get(i);
}
double sum_c = 0;
for(int i=0; i<Y.size(); i++) {
if (i == idex1 || i == idex2) {
continue;
}
sum_c -= alpha.get(i)*Y.get(i);
}
//调整范围上下限
double length = 10;
double limit_sup = length;
double limit_low = 0;
if(Math.abs(Y.get(idex1)-Y.get(idex2)) < 10E-10){
limit_sup = Math.min(limit_sup,sum_c/Y.get(idex1));
limit_low = Math.max(limit_low,sum_c/Y.get(idex1)-length);
}else{
limit_sup = Math.min(limit_sup, sum_c/Y.get(idex1)+length);
limit_low = Math.max(limit_low, sum_c/Y.get(idex1));
}
double x1;
double x2;
if(a == 0){
if(b > 0){
x1 = limit_sup;
}else{
x1 = limit_low;
}
}else if(a > 0){
if(-b/(2*a) < (limit_low+limit_sup)/2){
x1 = limit_sup;
}else {
x1 = limit_low;
}
}else {
if(-b/(2*a) < limit_low){
x1 = limit_low;
}else if(-b/(2*a) > limit_sup){
x1 = limit_sup;
}else{
x1 = -b/(2*a);
}
}
x2 = (sum_c-x1*Y.get(idex1))/Y.get(idex2);
alpha.set(idex1,x1);
alpha.set(idex2,x2);
}
static List<Double> find_weight(List<List<Double>> examples){
List<Double> w = new ArrayList<Double>();
//X,Y,alpha初始化
List<List<Double>> X = new ArrayList<List<Double>>();
List<Double> Y = new ArrayList<Double>();
for(int i=0; i<examples.size(); i++){
List<Double> L = new ArrayList<Double>();
for(int j=0; j<examples.get(i).size()-1; j++){
L.add(examples.get(i).get(j));
}
X.add(L);
Y.add(examples.get(i).get(examples.get(i).size()-1));
}
//X,Y按标签分开,保证输入样本的时候按照flag标签严格的分开了,正样本在前面,负样本在后
for(int i=0; i<Y.size()-1; i++){
for(int j=i+1; j<Y.size(); j++){
//正样本放前面
if(Y.get(i) < Y.get(j)){
double temp = Y.get(i);
Y.set(i,Y.get(j));
Y.set(j,temp);
List<Double> temp_L = L_copy(X.get(i));
X.set(i,L_copy(X.get(j)));
X.set(j,L_copy(temp_L));
}
}
}
List<Double> alpha = new ArrayList<Double>();
for(int i=0; i<Y.size()-1; i++){
alpha.add(1.0);
}
double sum_last = 0;
for(int i=0; i<Y.size()-1; i++){
sum_last -= alpha.get(i)*Y.get(i);
}
alpha.add(sum_last/Y.get(Y.size()-1));
//核矩阵生成
List<List<Double>> core = liner_core(X);
//标记负样本开始的地址
int idex_n = 0;
for(int i=0; i<Y.size(); i++){
if(Y.get(i) == -1){
idex_n = i;
break;
}
}
//当全是正样本或全是负样本时,返回空的List
if(idex_n == 0 || Y.get(0) == -1){
return new ArrayList<Double>();
}
List<Double> alpha_1 = L_copy(alpha);
System.out.println(alpha);
//开始迭代权重,每次选两个
int flag = 0;
int times = 100000;
while(true){
for(int i=0; i<Y.size()-1; i++){
for(int j=i+1; j<Y.size(); j++) {
alpha_Q(Y,alpha,core,i,j);
}
}
System.out.println(alpha);
double error = 0;
for(int i=0; i<alpha.size(); i++){
error += (alpha.get(i)-alpha_1.get(i))*(alpha.get(i)-alpha_1.get(i));
}
if(error < 10E-3 || flag >times){
break;
}
alpha_1 = L_copy(alpha_1);
flag += 1;
}
for(int i=0; i<X.get(0).size(); i++){
w.add(0.0);
}
for(int i=0; i<X.size(); i++){
for(int j=0; j<X.get(i).size(); j++){
w.set(j,w.get(j)+alpha.get(i)*Y.get(i)*X.get(i).get(j));
}
}
List<Double> L_b = new ArrayList<Double>();
for(int i=0; i<X.size(); i++){
if(Math.abs(alpha.get(i))<10E-3){
continue;
}
double sum_part = 0;
for(int j=0; j<X.get(i).size(); j++){
sum_part += X.get(i).get(j)*w.get(j);
}
L_b.add(Y.get(i)-sum_part);
}
double b = 0;
for(Double i: L_b){
b += i;
}
b = b/L_b.size();
w.add(b);
return w;
}
public static void main(String[] args) throws Exception {
List<List<Double>> examples = example_init();
//现在开始训练模型参数,入参为LL型,每个L最后一位为flag,故维数为size-1;
List<Double> w = find_weight(examples);
System.out.println(w);
}
}
# -*- coding: utf-8 -*-
"""
Created on Wed Jun 13 16:41:48 2018
@author: zhangchaoyu
"""
import matplotlib.pyplot as plt
def alpha_init(Y):
alpha = []
#正样本在前,负样本在后
for i in range(len(Y)):
if(Y[i] == -1):
num_a = i
break
num_n = len(Y)-num_a
#这样初始化alpha所产生的w相当于从负样本中心指向正样本中心的方向
for i in range(num_a):
alpha.append(1/num_a)
for i in range(num_n):
alpha.append(-1/num_n)
return alpha
def liner_core(X):
core = []
for i in range(len(X)):
L = []
for j in range(len(X)):
core_ij = 0
for k in range(len(X[0])):
core_ij += X[i][k]*X[j][k]
L.append(core_ij)
core.append(L)
return core
def standard(L):
sum_norm2 = 0
for e in L:
sum_norm2 += e*e
L1 = []
for e in L:
L1.append(e/pow(sum_norm2,0.5))
return L1
def alpha_Q(Y,alpha,core,idex1,idex2):
#计算约束值
sum_c = 0
for i in range(len(Y)):
if(i==idex1 or i==idex2):
continue
sum_c -= alpha[i]*Y[i]
#计算二次函数的a和b
a = -0.5*(core[idex1][idex1]-2*core[idex1][idex2]+core[idex2][idex2])
b = 1-Y[idex1]/Y[idex2]-sum_c*Y[idex1]*(core[idex1][idex2]-core[idex2][idex2])
for i in range(len(Y)):
if(i==idex1 or i==idex2):
continue
b -= Y[idex1]*(core[idex1][i]-core[idex2][i])*alpha[i]*Y[i]
#设置idex1变量的上下限,保证idex1和idex2都在可行范围内
max_range = 10
if(Y[idex1] == Y[idex2]):
limit_sup = min(max_range, sum_c/Y[idex1])
limit_low = max(0, sum_c/Y[idex1]-max_range)
else:
limit_sup = min(max_range, sum_c/Y[idex1]+max_range)
limit_low = max(0, sum_c/Y[idex1])
#二次函数,根据可行区间分类讨论
epsilon = 0.001
if(abs(a)<epsilon):
if(b>0):
x1 = limit_sup
else:
x1 = limit_low
elif(a>=epsilon):
if(-b/(2*a) < (limit_low+limit_sup)/2):
x1 = limit_sup
else:
x1 = limit_low
else:
if(-b/(2*a) < limit_low):
x1 = limit_low
elif(-b/(2*a) > limit_sup):
x1 = limit_sup
else:
x1 = -b/(2*a)
x2 = (sum_c - x1*Y[idex1])/Y[idex2]
alpha[idex1] = x1
alpha[idex2] = x2
return standard(alpha)
def alpha_error(alpha,alpha1):
sum_e = 0
for i in range(len(alpha)):
sum_e += pow(alpha[i]-alpha1[i],2)
return sum_e
def L_copy(L):
L1 = []
for e in L:
L1.append(e)
return L1
def plot(examples, w):
min_x = examples[0][0]
max_x = examples[0][0]
min_y = examples[0][1]
max_y = examples[0][1]
for e in examples:
min_x = min(min_x, e[0])
max_x = max(max_x, e[0])
min_y = min(min_y, e[1])
max_y = max(max_y, e[1])
x = [min_x,max_x]
y = [(-w[0]*min_x-w[2])/w[1], (-w[0]*max_x-w[2])/w[1]]
plt.figure()
plt.plot(x,y,color='k',linewidth=1.0,linestyle='--')
for e in examples:
if(e[2] == 1):
plt.scatter(e[0],e[1],c='r')
else:
plt.scatter(e[0],e[1],c='b')
def find_weight(examples):
#X,Y初始化
X = []
Y = []
for e in examples:
X.append(e[:-1])
Y.append(e[-1])
#保证正样本和负样本分开
for i in range(len(Y)):
for j in range(i+1,len(Y)):
if(Y[i]<Y[j]):
temp = Y[i]
Y[i] = Y[j]
Y[j] = temp
temp = X[i]
X[i] = X[j]
X[j] = temp
#当全是正样本或全是负样本,返回空值
if(Y[0] == -1 or Y[-1] == 1):
return []
#alpha初始化
alpha = standard(alpha_init(Y))
#核矩阵生成
core = liner_core(X)
#设置最大迭代次数
times = 1000
alpha1 = L_copy(alpha)
#两两优化
for flag in range(times):
for i in range(len(Y)-1):
for j in range(i+1,len(Y)):
alpha = alpha_Q(Y,alpha,core,i,j)
#当迭代之后的数值变动不大时返回结果
if(alpha_error(alpha,alpha1) < 0.001):
print("end at times"+str(flag))
break
alpha1 = L_copy(alpha)
#输出w
w = []
for i in range(len(X[0])):
w.append(0)
for i in range(len(X)):
for j in range(len(X[i])):
w[j] += alpha[i]*Y[i]*X[i][j]
L_b = []
for i in range(len(X)):
if(alpha[i] > 0.001):
sum_part = 0
for j in range(len(X[i])):
sum_part += w[j]*X[i][j]
L_b.append(Y[i]-sum_part)
b = 0
for i in range(len(L_b)):
b += L_b[i]
w.append(b/len(L_b))
return w
def example_init():
examples = []
examples.append([1,0,-1])
examples.append([2,1,-1])
#examples.append([3,2,-1])
examples.append([4,3,-1])
examples.append([0,1,1])
examples.append([1,2,1])
examples.append([2,3,1])
examples.append([3,4,1])
return examples
if __name__ == '__main__':
examples = example_init()
w = find_weight(examples)
plot(examples, w)