SMOアルゴリズムの2019.6.9svm

SMO効率的な最適化アルゴリズム
シーケンシャル最小限の最適化(シーケンシャル最小の最適化、SMO)アルゴリズム:SVMを実現する最も人気のある実装があり、多くのがあります。
以下の説明は、複数のデータセットに拡張カーネル(カーネル)方式のSVMと呼ぶことにします。
注意:SVM直感的な幾何学的な意味が、そのアルゴリズムが複雑で、それは数式が多数派生しているが含まれます。
シーケンシャル最小最適化(シーケンシャル最小の最適化、SMO)

著者の作成:ジョン・プラットが
作成:1996年
SMOの目的は:SVM訓練するために
SMOの目標を:アルファaとb、一度取得したアルファのシリーズを見つけ、重みベクトルwを計算し、分離超平面を得ることは容易です。
SMOは考えた:最適化問題を解決するために、小さな数に大きな最適化問題です。
SMO原理:2つのα最適化処理を経て各サイクルは、一度アルファの適切なペアを見つけるために、その後、一方の減少を増加させました。
適切な手段は、ここで特定の条件満たさなければならない
2つのα間隔の境界の外側になければならない
アルファ両方のセクションはされていないか、境界処理上ではありません。
アルファ2変更しながら理由、その理由は、我々は制約を有することである:(\ sum_ {i = 1 } ^ {M} a_iを・label_i = 0) のみ修飾アルファは、制約の故障につながる可能性がある場合。
SMO擬似コードを次のように
0に初期化アルファベクトルとベクトルを作成
反復回数が最大反復回数(外部ループ)未満である場合
:各データ・ベクトル(内側ループ)のデータセット内の
データベクトルを最適化することができるならば
、確率的にデータベクトルを選択し、さらに
、これら二つのベクトルを最適化する
二つのベクトルが最適化されるようにされていない場合、インナーループが終了し
、すべてのベクトルが最適化されていない場合、反復の数が増加するが、次のサイクルに進み
SVMの特徴と
利点を:一般化(特ににより個々の拡張一般的には、それは次のようになります。サンプル)エラーレート後の新しいモデルのトレーニングは、計算コスト、簡単に結果を理解します。
短所:元の分類を変更することなく、パラメータ選択および調整敏感カーネル関数は、バイナリ分類を処理するためにのみ適しています。
データの種類:データの種類および公称数値の
テキストファイル形式:

-1 3.542485 1.977398
3.018896 2.556416 -1
7.551510 -1.580030 1
2.114999 -0.004466 -1
8.127113 1.274372 1
製造データ

loadDataSet DEF(filename)で:
「」「
全体の特徴マトリックスとのカテゴリラベル列取得する行によってファイル解析された行
のArgs:
fileNameにファイル名
戻り値:
Datamat特性行列
labelMat基づいてラベル
」「」
Datamat = []
labelMat = [ 】
FR =オープン(filename)で
fr.readlinesにおけるライン分()
。lineArr = line.strip()スプリット( '\のT')
dataMat.append([フロート(lineArr [0])、フロート(lineArr [1] )])
labelMat.append(フロート(lineArr [2]))
Datamat、labelMatリターン
分析:なし

トレーニングアルゴリズム

DEF smoSimple(dataMatIn、classLabels、C、トーラー、MAXITER):
「」 "smoSimple

Args:
    dataMatIn    特征集合
    classLabels  类别标签
    C   松弛变量(常量值),允许有些数据点可以处于分隔面的错误一侧。
        控制最大化间隔和保证大部分的函数间隔小于1.0这两个目标的权重。
        可以通过调节该参数达到不同的结果。
    toler   容错率(是指在某个体系中能减小一些因素或选择对某个系统产生不稳定的概率。)
    maxIter 退出前最大的循环次数
Returns:
    b       模型的常量值
    alphas  拉格朗日乘子
"""
dataMatrix = mat(dataMatIn)
# 矩阵转置 和 .T 一样的功能
labelMat = mat(classLabels).transpose()
m, n = shape(dataMatrix)

# 初始化 b和alphas(alpha有点类似权重值。)
b = 0
alphas = mat(zeros((m, 1)))

# 没有任何alpha改变的情况下遍历数据的次数
iter = 0
while (iter < maxIter):
    # w = calcWs(alphas, dataMatIn, classLabels)
    # print("w:", w)

    # 记录alpha是否已经进行优化,每次循环时设为0,然后再对整个集合顺序遍历
    alphaPairsChanged = 0
    for i in range(m):
        # print 'alphas=', alphas
        # print 'labelMat=', labelMat
        # print 'multiply(alphas, labelMat)=', multiply(alphas, labelMat)
        # 我们预测的类别 y[i] = w^Tx[i]+b; 其中因为 w = Σ(1~n) a[n]*label[n]*x[n]
        fXi = float(multiply(alphas, labelMat).T*(dataMatrix*dataMatrix[i, :].T)) + b
        # 预测结果与真实结果比对,计算误差Ei
        Ei = fXi - float(labelMat[i])

        # 约束条件 (KKT条件是解决最优化问题的时用到的一种方法。我们这里提到的最优化问题通常是指对于给定的某一函数,求其在指定作用域上的全局最小值)
        # 0<=alphas[i]<=C,但由于0和C是边界值,我们无法进行优化,因为需要增加一个alphas和降低一个alphas。
        # 表示发生错误的概率:labelMat[i]*Ei 如果超出了 toler, 才需要优化。至于正负号,我们考虑绝对值就对了。
        '''
        # 检验训练样本(xi, yi)是否满足KKT条件
        yi*f(i) >= 1 and alpha = 0 (outside the boundary)
        yi*f(i) == 1 and 0<alpha< C (on the boundary)
        yi*f(i) <= 1 and alpha = C (between the boundary)
        '''
        if ((labelMat[i]*Ei < -toler) and (alphas[i] < C)) or ((labelMat[i]*Ei > toler) and (alphas[i] > 0)):

            # 如果满足优化的条件,我们就随机选取非i的一个点,进行优化比较
            j = selectJrand(i, m)
            # 预测j的结果
            fXj = float(multiply(alphas, labelMat).T*(dataMatrix*dataMatrix[j, :].T)) + b
            Ej = fXj - float(labelMat[j])
            alphaIold = alphas[i].copy()
            alphaJold = alphas[j].copy()

            # L和H用于将alphas[j]调整到0-C之间。如果L==H,就不做任何改变,直接执行continue语句
            # labelMat[i] != labelMat[j] 表示异侧,就相减,否则是同侧,就相加。
            if (labelMat[i] != labelMat[j]):
                L = max(0, alphas[j] - alphas[i])
                H = min(C, C + alphas[j] - alphas[i])
            else:
                L = max(0, alphas[j] + alphas[i] - C)
                H = min(C, alphas[j] + alphas[i])
            # 如果相同,就没法优化了
            if L == H:
                print("L==H")
                continue

            # eta是alphas[j]的最优修改量,如果eta==0,需要退出for循环的当前迭代过程
            # 参考《统计学习方法》李航-P125~P128<序列最小最优化算法>
            eta = 2.0 * dataMatrix[i, :]*dataMatrix[j, :].T - dataMatrix[i, :]*dataMatrix[i, :].T - dataMatrix[j, :]*dataMatrix[j, :].T
            if eta >= 0:
                print("eta>=0")
                continue

            # 计算出一个新的alphas[j]值
            alphas[j] -= labelMat[j]*(Ei - Ej)/eta
            # 并使用辅助函数,以及L和H对其进行调整
            alphas[j] = clipAlpha(alphas[j], H, L)
            # 检查alpha[j]是否只是轻微的改变,如果是的话,就退出for循环。
            if (abs(alphas[j] - alphaJold) < 0.00001):
                print("j not moving enough")
                continue
            # 然后alphas[i]和alphas[j]同样进行改变,虽然改变的大小一样,但是改变的方向正好相反
            alphas[i] += labelMat[j]*labelMat[i]*(alphaJold - alphas[j])
            # 在对alpha[i], alpha[j] 进行优化之后,给这两个alpha值设置一个常数b。
            # w= Σ[1~n] ai*yi*xi => b = yj- Σ[1~n] ai*yi(xi*xj)
            # 所以:  b1 - b = (y1-y) - Σ[1~n] yi*(a1-a)*(xi*x1)
            # 为什么减2遍? 因为是 减去Σ[1~n],正好2个变量i和j,所以减2遍
            b1 = b - Ei- labelMat[i]*(alphas[i]-alphaIold)*dataMatrix[i, :]*dataMatrix[i, :].T - labelMat[j]*(alphas[j]-alphaJold)*dataMatrix[i, :]*dataMatrix[j, :].T
            b2 = b - Ej- labelMat[i]*(alphas[i]-alphaIold)*dataMatrix[i, :]*dataMatrix[j, :].T - labelMat[j]*(alphas[j]-alphaJold)*dataMatrix[j, :]*dataMatrix[j, :].T
            if (0 < alphas[i]) and (C > alphas[i]):
                b = b1
            elif (0 < alphas[j]) and (C > alphas[j]):
                b = b2
            else:
                b = (b1 + b2)/2.0
            alphaPairsChanged += 1
            print("iter: %d i:%d, pairs changed %d" % (iter, i, alphaPairsChanged))
    # 在for循环外,检查alpha值是否做了更新,如果更新则将iter设为0后继续运行程序
    # 直到更新完毕后,iter次循环无变化,才退出循环。
    if (alphaPairsChanged == 0):
        iter += 1
    else:
        iter = 0
    print("iteration number: %d" % iter)
return b, alphas

おすすめ

転載: blog.csdn.net/weixin_43732462/article/details/91355604