7、SVM学习总结

 
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)
    
    





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值