优化的SMO算法 Parameters: i - 标号为i的数据的索引值 oS - 数据结构 Returns: 1 - 有任意一对alpha值发生变化 0 - 没有任意一对alpha值发生变化或变化太小
(i, oS)
| 160 | return aj |
| 161 | |
| 162 | def innerL(i, oS): |
| 163 | """ |
| 164 | 优化的SMO算法 |
| 165 | Parameters: |
| 166 | i - 标号为i的数据的索引值 |
| 167 | oS - 数据结构 |
| 168 | Returns: |
| 169 | 1 - 有任意一对alpha值发生变化 |
| 170 | 0 - 没有任意一对alpha值发生变化或变化太小 |
| 171 | """ |
| 172 | #步骤1:计算误差Ei |
| 173 | Ei = calcEk(oS, i) |
| 174 | #优化alpha,设定一定的容错率。 |
| 175 | if ((oS.labelMat[i] * Ei < -oS.tol) and (oS.alphas[i] < oS.C)) or ((oS.labelMat[i] * Ei > oS.tol) and (oS.alphas[i] > 0)): |
| 176 | #使用内循环启发方式2选择alpha_j,并计算Ej |
| 177 | j,Ej = selectJ(i, oS, Ei) |
| 178 | #保存更新前的aplpha值,使用深拷贝 |
| 179 | alphaIold = oS.alphas[i].copy(); alphaJold = oS.alphas[j].copy(); |
| 180 | #步骤2:计算上下界L和H |
| 181 | if (oS.labelMat[i] != oS.labelMat[j]): |
| 182 | L = max(0, oS.alphas[j] - oS.alphas[i]) |
| 183 | H = min(oS.C, oS.C + oS.alphas[j] - oS.alphas[i]) |
| 184 | else: |
| 185 | L = max(0, oS.alphas[j] + oS.alphas[i] - oS.C) |
| 186 | H = min(oS.C, oS.alphas[j] + oS.alphas[i]) |
| 187 | if L == H: |
| 188 | print("L==H") |
| 189 | return 0 |
| 190 | #步骤3:计算eta |
| 191 | eta = 2.0 * oS.K[i,j] - oS.K[i,i] - oS.K[j,j] |
| 192 | if eta >= 0: |
| 193 | print("eta>=0") |
| 194 | return 0 |
| 195 | #步骤4:更新alpha_j |
| 196 | oS.alphas[j] -= oS.labelMat[j] * (Ei - Ej)/eta |
| 197 | #步骤5:修剪alpha_j |
| 198 | oS.alphas[j] = clipAlpha(oS.alphas[j],H,L) |
| 199 | #更新Ej至误差缓存 |
| 200 | updateEk(oS, j) |
| 201 | if (abs(oS.alphas[j] - alphaJold) < 0.00001): |
| 202 | print("alpha_j变化太小") |
| 203 | return 0 |
| 204 | #步骤6:更新alpha_i |
| 205 | oS.alphas[i] += oS.labelMat[j]*oS.labelMat[i]*(alphaJold - oS.alphas[j]) |
| 206 | #更新Ei至误差缓存 |
| 207 | updateEk(oS, i) |
| 208 | #步骤7:更新b_1和b_2 |
| 209 | b1 = oS.b - Ei- oS.labelMat[i]*(oS.alphas[i]-alphaIold)*oS.K[i,i] - oS.labelMat[j]*(oS.alphas[j]-alphaJold)*oS.K[i,j] |
| 210 | b2 = oS.b - Ej- oS.labelMat[i]*(oS.alphas[i]-alphaIold)*oS.K[i,j]- oS.labelMat[j]*(oS.alphas[j]-alphaJold)*oS.K[j,j] |
| 211 | #步骤8:根据b_1和b_2更新b |
| 212 | if (0 < oS.alphas[i]) and (oS.C > oS.alphas[i]): oS.b = b1 |
| 213 | elif (0 < oS.alphas[j]) and (oS.C > oS.alphas[j]): oS.b = b2 |
| 214 | else: oS.b = (b1 + b2)/2.0 |
| 215 | return 1 |
| 216 | else: |
| 217 | return 0 |
| 218 | |
| 219 | def smoP(dataMatIn, classLabels, C, toler, maxIter, kTup = ('lin',0)): |