基本上相当于把课本内容又整理了一遍,当然有些地方理解的不够清楚,可能有错误,看到了请指正_。因为不太会markdown的语法,所以直接用word写了截的图,doc文件和代码在这里

R spark ml_ 支持向量机 支持向量机代码_R spark ml_ 支持向量机

R spark ml_ 支持向量机 支持向量机代码_SVM_02


R spark ml_ 支持向量机 支持向量机代码_R spark ml_ 支持向量机_03


R spark ml_ 支持向量机 支持向量机代码_SVM_04


R spark ml_ 支持向量机 支持向量机代码_SVM_05


R spark ml_ 支持向量机 支持向量机代码_SMO_06


R spark ml_ 支持向量机 支持向量机代码_SMO_07


R spark ml_ 支持向量机 支持向量机代码_SMO_08


R spark ml_ 支持向量机 支持向量机代码_核函数_09


R spark ml_ 支持向量机 支持向量机代码_核函数_10

R spark ml_ 支持向量机 支持向量机代码_SMO_11


R spark ml_ 支持向量机 支持向量机代码_代码_12


R spark ml_ 支持向量机 支持向量机代码_SVM_13


R spark ml_ 支持向量机 支持向量机代码_代码_14


R spark ml_ 支持向量机 支持向量机代码_SVM_15


R spark ml_ 支持向量机 支持向量机代码_SVM_16


R spark ml_ 支持向量机 支持向量机代码_代码_17


R spark ml_ 支持向量机 支持向量机代码_SMO_18


R spark ml_ 支持向量机 支持向量机代码_R spark ml_ 支持向量机_19


R spark ml_ 支持向量机 支持向量机代码_R spark ml_ 支持向量机_20


R spark ml_ 支持向量机 支持向量机代码_SVM_21

C = 1
threshold = 1e-8  # 确保选择的a2使得损失函数有足够的下降
eps = 1e-30


# 参数顺序:K,b,alpha,y
def getL(K, alpha, y):  # 获取当前损失函数值
    l = 0
    for i in range(len(y)):
        for j in range(len(y)):
            l += 0.5 * alpha[i] * alpha[j] * y[i] * y[j] * K[i][j]
        l -= alpha[i]
    return l


def getGx(K, b, i, alpha, y):  # 获取预测值
    g = b
    for j in range(len(y)):
        g += alpha[j] * y[j] * K[j][i]
    return g


# 不要直接修改alpha,防止不满足目标函数阈值下降条件的情况出现
def getNewAlpha(K, b, i1, i2, alpha, y):
    eta = K[i1][i1] + K[i2][i2] - 2 * K[i1][i2]
    # ************
    # if eta < 1e-20:
    #     eta = 1e-20
    # ************
    a2_new_unc = alpha[i2] + y[i2] * ((getGx(K, b, i1, alpha, y) - y[i1]) - (getGx(K, b, i2, alpha, y) - y[i2])) / eta
    # 剪辑
    if y[i1] == y[i2]:
        L = max(0, alpha[i1] + alpha[i2] - C)
        H = min(C, alpha[i1] + alpha[i2])
    else:
        L = max(0, alpha[i2] - alpha[i1])
        H = min(C, C + alpha[i2] - alpha[i1])
    if a2_new_unc > H:
        a2_new = H
    elif a2_new_unc < L:
        a2_new = L
    else:
        a2_new = a2_new_unc

    a1_new = alpha[i1] + y[i1] * y[i2] * (alpha[i2] - a2_new)
    # a1 = y[i1] * st - a2_new * y[i1] * y[i2]

    E1 = getGx(K, b, i1, alpha, y) - y[i1]
    E2 = getGx(K, b, i2, alpha, y) - y[i2]
    b1_new = -1 * E1 - y[i1] * K[i1][i1] * (a1_new - alpha[i1]) - y[i2] * K[i2][i1] * (a2_new - alpha[i2]) + b
    b2_new = -1 * E2 - y[i1] * K[i1][i2] * (a1_new - alpha[i1]) - y[i2] * K[i2][i2] * (a2_new - alpha[i2]) + b
    if (a1_new > 0 and a1_new < C) and (a2_new and a2_new < C):
        bnew = b1_new
    else:
        bnew = (b1_new + b2_new) / 2
    return (a1_new, a2_new, bnew)


def SMO(K, b, alpha, y):
    flag = True
    while flag == True:
        # flag = false说明找不到可以优化的a1,a2
        flag = False
        preL = getL(K, alpha, y)
        for i1 in range(len(alpha)):
            gxi1 = getGx(K, b, i1, alpha, y)
            if alpha[i1] > 0 and alpha[i1] < C and abs(y[i1] * gxi1 - 1) > eps:
                E1 = gxi1 - y[i1]
                maxDiff = 0  # |使得E1 - E2|最大
                posi2 = 0
                for i2 in range(len(alpha)):
                    if i1 == i2:
                        continue
                    E2 = getGx(K, b, i2, alpha, y) - y[i2]
                    if abs(E1 - E2) > maxDiff:
                        maxDiff = abs(E1 - E2)
                        posi2 = i2

                a1_new, a2_new, b_new = getNewAlpha(K, b, i1, posi2, alpha, y)
                # 更新alpha
                alpha[i1], a1_new = a1_new, alpha[i1]
                alpha[posi2], a2_new = a2_new, alpha[posi2]
                curL = getL(K, alpha, y)

                # 找到解,更新b
                if preL - curL >= threshold:
                    b = b_new
                    flag = True
                    break
                # 没有达到预定条件,那么搜索在0-C内的a2
                # if preL - curL < threshold:
                else:
                    alpha[i1], a1_new = a1_new, alpha[i1]
                    alpha[posi2], a2_new = a2_new, alpha[posi2]
                    for i2 in range(len(alpha)):
                        if i2 == i1 or i2 == posi2:
                            continue
                        if alpha[i2] > 0 and alpha[i2] < C:
                            # i2写成了posi2
                            a1_new, a2_new, b_new = getNewAlpha(K, b, i1, i2, alpha, y)
                            alpha[i1], a1_new = a1_new, alpha[i1]
                            alpha[i2], a2_new = a2_new, alpha[i2]
                            curL = getL(K, alpha, y)
                            # 满足条件则停止
                            if preL - curL >= threshold:
                                b = b_new
                                flag = True
                                break
                            else:
                                alpha[i1], a1_new = a1_new, alpha[i1]
                                alpha[i2], a2_new = a2_new, alpha[i2]
                    if flag:
                        break
                    # 如果还是不满足,就搜索全部的a2
                    else:
                        for i2 in range(len(alpha)):
                            if i2 == i1 or i2 == posi2:
                                continue
                            if abs(alpha[i2] - 0) <= eps or abs(alpha[i2] - C) <= eps:
                                a1_new, a2_new, b_new = getNewAlpha(K, b, i1, i2, alpha, y)
                                alpha[i1], a1_new = a1_new, alpha[i1]
                                alpha[i2], a2_new = a2_new, alpha[i2]
                                curL = getL(K, alpha, y)

                                if preL - curL >= threshold:
                                    b = b_new
                                    flag = True
                                    break
                                else:
                                    alpha[i1], a1_new = a1_new, alpha[i1]
                                    alpha[i2], a2_new = a2_new, alpha[i2]
            if flag:
                break

        if flag == False:
            for i1 in range(len(alpha)):
                gxi1 = getGx(K, b, i1, alpha, y)
                if ((alpha[i1] - 0) <= eps and y[i1] * gxi1 < 1) or ((alpha[i1] - C) < eps and y[i1] * gxi1 > 1):
                    E1 = gxi1 - y[i1]
                    maxDiff = 0  # |使得E1 - E2|最大
                    posi2 = 0
                    for i2 in range(len(alpha)):
                        if i2 == i1:
                            continue
                        E2 = getGx(K, b, i2, alpha, y) - y[i2]
                        if abs(E1 - E2) > maxDiff:
                            maxDiff = abs(E1 - E2)
                            posi2 = i2

                    a1_new, a2_new, b_new = getNewAlpha(K, b, i1, posi2, alpha, y)
                    # 更新alpha
                    alpha[i1], a1_new = a1_new, alpha[i1]
                    alpha[posi2], a2_new = a2_new, alpha[posi2]
                    curL = getL(K, alpha, y)

                    if preL - curL >= threshold:
                        b = b_new
                        flag = True
                        break

                    # 没有达到预定条件,那么搜索在0-C内的a2
                    # if preL - curL < threshold:
                    else:
                        alpha[i1], a1_new = a1_new, alpha[i1]
                        alpha[posi2], a2_new = a2_new, alpha[posi2]

                        for i2 in range(len(alpha)):
                            if i2 == i1 or i2 == posi2:
                                continue
                            if alpha[i2] > 0 and alpha[i2] < C:
                                a1_new, a2_new, b_new = getNewAlpha(K, b, i1, i2, alpha, y)
                                alpha[i1], a1_new = a1_new, alpha[i1]
                                alpha[i2], a2_new = a2_new, alpha[i2]
                                curL = getL(K, alpha, y)
                                # 满足条件则停止
                                if preL - curL >= threshold:
                                    b = b_new
                                    flag = True
                                    break
                                else:
                                    alpha[i1], a1_new = a1_new, alpha[i1]
                                    alpha[i2], a2_new = a2_new, alpha[i2]
                        if flag:
                            break
                        # 如果还是不满足,就搜索全部的a2
                        else:
                            for i2 in range(len(alpha)):
                                if i2 == i1 or i2 == posi2:
                                    continue
                                if (alpha[i2] - 0) <= eps or (alpha[i2] - C) <= eps:
                                    a1_new, a2_new, b_new = getNewAlpha(K, b, i1, i2, alpha, y)
                                    alpha[i1], a1_new = a1_new, alpha[i1]
                                    alpha[i2], a2_new = a2_new, alpha[i2]
                                    curL = getL(K, alpha, y)

                                    if preL - curL >= threshold:
                                        b = b_new
                                        flag = True
                                        break
                                    else:
                                        alpha[i1], a1_new = a1_new, alpha[i1]
                                        alpha[i2], a2_new = a2_new, alpha[i2]
                if flag:
                    break

    return alpha, b


def getK(X, f):
    K = [0] * len(X)
    for i in range(len(K)):
        K[i] = [0] * len(X)
    # print(len(K))
    # print(len(K[0]))
    for i in range(len(X)):
        for j in range(len(X)):
            for k in range(len(X[i])):
                K[i][j] += f(X[i][k]) * f(X[j][k])
    return K


# X = [[3,3],[4,3],[1,1]]
# y = [1,1,-1]
# K = getK(X,lambda x:x)
# alpha = [0,0,0]
# b = 0
# alpha,b = SMO(K,b,alpha,y)
# print(alpha,b)

import random
import numpy as np
import matplotlib.pyplot as plt


def kernelF(x, xi, f):
    Kx_xi = 0
    for i in range(len(x)):
        Kx_xi += f(x[i]) * f(xi[i])
    return Kx_xi


#定义椭圆x^2 + 4y^2 = 4
# 圆圈是训练集数据,三角形是测试集数据,用颜色标记正负例
# theta = np.arange(0, 2.1 * np.pi ,0.1 * np.pi)
# plt.plot(2 * np.cos(theta),np.sin(theta),c='red')
#
# X = [[random.uniform(-2.5,2.5),random.uniform(-1.5,1.5)] for _ in range(50)]
# y = [0] * len(X)
# for i in range(len(X)):
#     if X[i][0] ** 2 + 4 * X[i][1] ** 2 <= 4:
#         y[i] = 1
#         plt.scatter(X[i][0],X[i][1],c='blue',marker='o')
#     else:
#         y[i] = -1
#         plt.scatter(X[i][0], X[i][1], c='green',marker='o')
#
# K = getK(X,lambda x:x ** 2)
# b = 0
# alpha = [0] * len(X)
# alpha,b = SMO(K,b,alpha,y)
#
# for i in range(50):
#     xi = [random.uniform(-2.5,2.5),random.uniform(-1.5,1.5)]
#     pred = b
#     for idx in range(len(alpha)):
#         pred += alpha[idx] * y[idx] * kernelF(xi,X[idx],lambda x:x ** 2)
#     if pred >= 0:
#         plt.scatter(xi[0], xi[1], c='blue', marker='^')
#     else:
#         plt.scatter(xi[0], xi[1], c='green', marker='^')
# plt.show()
# plt.axis('equal')


# 定义直线x + y = 0
# 圆圈是训练集数据,三角形是测试集数据,用颜色标记正负例
x = np.arange(-5, 5, 1)
plt.plot(x, -1 * x, c='red')

X = [[random.uniform(-5, 5), random.uniform(-5, 5)] for _ in range(20)]
y = [0] * len(X)
for i in range(len(X)):
    if X[i][0] + X[i][1] <= 0:
        y[i] = 1
        plt.scatter(X[i][0], X[i][1], c='blue', marker='o')
    else:
        y[i] = -1
        plt.scatter(X[i][0], X[i][1], c='green', marker='o')

K = getK(X, lambda x: x)
b = 0
alpha = [0] * len(X)
alpha,b = SMO(K, b, alpha, y)

for i in range(100):
    xi = [random.uniform(-5, 5), random.uniform(-5, 5)]
    pred = b
    for idx in range(len(alpha)):
        pred += alpha[idx] * y[idx] * kernelF(xi, X[idx], lambda x: x)
    if pred >= 0:
        plt.scatter(xi[0], xi[1], c='blue', marker='^')
    else:
        plt.scatter(xi[0], xi[1], c='green', marker='^')
plt.show()
plt.axis('equal')

总结:这是第二遍看有监督学习部分,每次都有新收获吧。公式看着挺多,但是大部分仅仅是长和复杂而已,难度不高,当然确实也有几个地方比较难理解。。。