文章目录
正则项是通过添加信息来解决不适定问题或者防止过拟合,其应用范围很广,包括机器学习、数据统计以及图像中。常见的正则项有L0、L1、L2,本文讲述的是关于L1正则项。L1正则化项是指权重向量x中各元素的绝对值之和,可以表示为**||x||1。**
在机器学习中,分类是指针对输入数据中的给定示例预测其类别标签的预测性建模问题。常见的分类任务有四种:二分类、多类别分类、多标签分类、不平衡分类。
多类别分类是指具有两个以上类别标签的分类任务,通常使用多元概率分布模型来对多类别分类任务进行建模。可用于多类别分类任务的算法有:k最近邻算法、决策树、朴素贝叶斯、随机森林、梯度提升等,但用于二分类的算法逻辑回归和支持向量机也适用于多类别分类问题。
支持向量机(Support Vector Machine, SVM),是一类按监督学习方式对数据进行分类的线性分类器。其核心思想是在特征空间内找到使不同类别的样本间距最大的决策边界。SVM模型中经常会引入正则化项(regularization term)来提高模型鲁棒性或者引入先验知识。L1 - regularized SVM就是在模型中加入L1正则化项(也即 ||x||1 ),将特征向量的稀疏性(会令特征向量x中某一些参数等于0)这个先验知识引入到模型中,进而提高分类效率。
本文将讲述使用MindOpt优化带L1正则项SVM多分类问题。
问题描述
分类是机器学习领域中最基本的任务之一。其目的是建立输入向量x与分类变量y之间的映射关系。例如:
- 在计算机视觉中,我们需要把一张张图片根据其内容分类为"动物",“轮船”, "植物"等类别,供下游的任务使用。在这个应用中,x就是图片像素组成的向量,而分类变量y则是指向其具体类别的标量。
- 我们会把收到的电子邮件根据其标题,发件人,内容,附带图片或链接等分类为"重要邮件", “推销邮件”, "垃圾邮件"等。在这个应用中,x就是电子邮件的向量化输入,y则是指向具体类别的标量。
问题模型
假设我们有m组数据 { x i , y i } i = 1 m \{x_i, y_i\}_{i=1}^m {xi,yi}i=1m , 其中 x i ∈ R d x_i\in \mathbb{R}^d xi∈Rd是特征向量, y i ∈ { 1 , 2 , ⋯ , K } y_i\in\{1,2,\cdots, K\} yi∈{1,2,⋯,K}是特征向量 x i x_i xi对应的类别标签。因此,所有的数据都属于这K个分类。
在多分类问题中,我们需要找到一个参数矩阵
W
∈
R
K
×
d
W\in\mathbb{R}^{K \times d}
W∈RK×d来对未曾见过的数据样本
x
x
x进行分类。例如,在得到参数矩阵
W
W
W后,我们会计算
s
=
W
x
∈
R
K
s = Wx\in \mathbb{R}^K
s=Wx∈RK。
通过分类向量
s
s
s的每个element的大小,我们可以确定当前数据样本
x
x
x的类别。
ℓ 1 \ell_1 ℓ1- regularized SVM的问题模型如下:
其中 W W W是待优化的参数矩阵, w k T w_k^T wkT是 W W W的第k行, w y i T w_{y_i}^T wyiT是 W W W的第 y i y_i yi行,其中 y i ∈ { 1 , ⋯ , K } y_i\in\{1,\cdots,K\} yi∈{1,⋯,K}是第 i i i个样本 x i x_i xi所属的类别。 { ξ i } i = 1 m \{\xi_i\}_{i=1}^m {ξi}i=1m也是待优化的变量,其中 ξ i \xi_i ξi是非负标量。如果 y i = k y_i=k yi=k, 我们有 e i k = 1 e_i^k=1 eik=1; 如果 y i ≠ k y_i \neq k yi=k, 我们有 e i k = 0 e_i^k = 0 eik=0.
建模为线性规划问题
为了把上面的 ℓ 1 \ell_1 ℓ1- regularized SVM建模为线性规划问题,我们引入辅助变量 Z ∈ R K × d Z\in \mathbb{R}^{K \times d} Z∈RK×d,其中 z i j z_{ij} zij需要满足的约束为 ∣ w i j ∣ ≤ z i j , z i j ≥ 0 |w_{ij}| \le z_{ij}, z_{ij} \ge 0 ∣wij∣≤zij,zij≥0. 有了辅助变量 Z Z Z, 我们可以把上面的SVM问题建模为线性规划问题:
其中 z k T z_k^T zkT就是辅助变量 Z Z Z的第 k k k行。以上问题进一步等价于
如果令 p k = z k − w k , q k = z k + w k p_k = z_k - w_k, q_k = z_k + w_k pk=zk−wk,qk=zk+wk, 我们有
将以上关系带入到上面的线性规划问题中,我们有
- 变量: [ P , Q , ξ ] ∈ R 2 K d + m [P, Q, \xi] \in \mathbb{R}^{2Kd + m} [P,Q,ξ]∈R2Kd+m, 其中每个变量都是非负的
- 不等式约束: K m Km Km个不等式约束
- 以上问题可以转化为
其中: θ = [ p 1 T , ⋯ , p K T , q 1 T , ⋯ , q K T , ξ 1 , ⋯ , ξ m ] T ∈ R 2 K d + m \theta = [p_1^T,\cdots, p_K^T, q_1^T,\cdots, q_K^T, \xi_1, \cdots, \xi_m]^T \in \mathbb{R}^{2Kd + m} θ=[p1T,⋯,pKT,q1T,⋯,qKT,ξ1,⋯,ξm]T∈R2Kd+m, A ∈ R K m × ( 2 K d + m ) , b ∈ R K m A\in \mathbb{R}^{Km \times (2Kd + m)}, b\in \mathbb{R}^{Km} A∈RKm×(2Kd+m),b∈RKm
准备数据
选择1:直接用示例数据
我们在文件夹 src/model/mnist.scale100_tianchi
存了一份已OK的数据。可在云上建模求解查看该示例数据。
点开后如下截图所示:
选择2:通过mnist.scale数据集和libSVM生成数据
请参考原文C/S版代码原文来查看 选择2. 通过mnist.scale数据集和libSVM生成数据(含代码)
章节来自行生成数据,数据生成所需的依赖库本Notebook暂不支持,请在个人电脑上运行生成数据,然后将数据上传上来(可以直接拖folder里)。
使用MindOpt求解器的API
直接采用求解器的API,需要查阅API文档来理解API的意思,没有建模语言可读性高。请参阅https://solver.damo.alibaba.com/doc/html/API%20reference/API-python/index.html来查看PythonAPI的使用说明。
关于Python的例子,在文档的5.建模与优化求解章节有Python的示例。这里是个LP的问题,我们可以参考:https://solver.damo.alibaba.com/doc/html/model/lp/linear%20optimization-python.html
下面我们分两种方式描述在本平台环境中的运行方法:
方法1:cell中直接输入代码运行
# LP_6_svm.py
from mindoptpy import *
import time
if __name__ == "__main__":
# parameters
data_folder = "./model/mnist.scale100_tianchi/"
soln_file = "./model/LP_6_svm.sol"
MDO_INFINITY = MdoModel.get_infinity()
# read file meta for size of A
f = open(data_folder+"meta", "r")
A_size = []
for line in f:
num = int(line.split(' ')[-1][:-1])
A_size.append(num)
m, n = A_size[1], A_size[0]
f.close()
# read file b
b = []
f = open(data_folder+"b", "r")
for line in f:
b_element = float(line[:-1])
b.append(b_element)
f.close()
# read file c
c = []
f = open(data_folder+"c", "r")
for line in f:
c_element = float(line[:-1])
c.append(c_element)
f.close()
# --------Step 1. Establish LP model-----------
model = MdoModel()
try:
# -----Step 2. Input model.-----------
# Set minimize problem
model.set_int_attr("MinSense", 1)
# Add empty constraints.
cons = []
for j in range(m):
cons_name = "c" + str(j)
cons.append(model.add_cons(-MDO_INFINITY, b[j], None, cons_name))
# Input columns.
f = open(data_folder+"A", "r")
col = []
for j in range(n):
col.append(MdoCol())
for idx, line in enumerate(f):
line_lst = line.split('\t')
row_id, col_id, val = int(line_lst[0]), int(line_lst[1]), float(line_lst[2][:-1])
col[col_id].add_term(cons[row_id], val)
# Add variables.
# Note that the nonzero elements are inputted in a column-wise order here.
x = []
for j in range(n):
x_name = "x" + str(j)
x.append(model.add_var(0.0, MDO_INFINITY, c[j], col[j], x_name, False))
print('LP model is established.\n')
# ------Step3. Solve the problem and populate the result.-------
model.solve_prob()
model.display_results()
time.sleep(0.01) #for print
status_code, status_msg = model.get_status()
if status_msg == "OPTIMAL":
print("----\n")
print("The solver terminated with an OPTIMAL status (code {0}).".format(status_code))
print("目标函数最优取值是: {0}".format(model.get_real_attr("PrimalObjVal")))
print(" - 原始解 : {}".format(model.get_real_attr("PrimalObjVal")))
print(" - 对偶解 : {}".format(model.get_real_attr("DualObjVal")))
print(" - 求解耗时 : {} sec.".format(model.get_real_attr("SolutionTime")))
print("变量太多,请打开结果文件"+soln_file+"来查看变量取值")
else:
print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))
except MdoError as e:
print("Received Mindopt exception.")
print(" - Code : {}".format(e.code))
print(" - Reason : {}".format(e.message))
except Exception as e:
print("Received exception.")
print(" - Reason : {}".format(e))
finally:
# Step 5. Free the model.
model.free_mdl()
运行代码后得到如下结果:
Start license validation (current time : 01-MAR-2023 21:00:37).
License validation terminated. Time : 0.002s
LP model is established.
Model summary.
- Num. variables : 15700
- Num. constraints : 1000
- Num. nonzeros : 556788
- Bound range : [1.0e+00,1.0e+00]
- Objective range : [5.0e-01,1.0e+00]
- Matrix range : [2.0e-03,1.0e+00]
Presolver started.
Presolver terminated. Time : 0.089s
Simplex method started.
Iteration Objective Dual Inf. Primal Inf. Time
0 0.00000e+00 2.7794e+11 2.4000e+01 0.11s
3 1.69224e+00 6.9867e+00 0.0000e+00 0.12s CG pass 1
11 1.27594e+00 2.7885e+00 0.0000e+00 0.12s CG pass 2
End of column generation.
0 0.00000e+00 2.5246e+11 3.2000e+01 0.12s optimizing a block (26.5%)
41 1.94879e+00 0.0000e+00 0.0000e+00 0.12s
0 0.00000e+00 2.1551e+11 2.2000e+01 0.12s
4 2.23388e+00 3.8777e+00 0.0000e+00 0.12s CG pass 1
8 1.98044e+00 2.0357e+01 0.0000e+00 0.12s CG pass 2
End of column generation.
0 0.00000e+00 2.1533e+11 2.2000e+01 0.12s
3 2.79271e+00 1.0703e+01 0.0000e+00 0.12s CG pass 1
7 2.11345e+00 3.4990e+01 0.0000e+00 0.12s CG pass 2
End of column generation.
Model fingerprint: ==gZ3ZWYhRmZ3Z2bkV2dndmZ
Postsolver started.
Simplex method terminated. Time : 0.018s
Optimizer summary.
- Optimizer used : Simplex method
- Optimizer status : OPTIMAL
- Total time : 0.129s
Solution summary. Primal solution
- Objective : 6.4074250003e+00
----
The solver terminated with an OPTIMAL status (code 1).
目标函数最优取值是: 6.4074250003085975
- 原始解 : 6.4074250003085975
- 对偶解 : 6.407425000308594
- 求解耗时 : 0.129049877 sec.
变量太多,请打开结果文件./model/LP_6_svm.sol来查看变量取值
方法2:命令行直接运行.py文件
上面是直接在cell中运行所有的脚本,我们也可以建立个新文档,将Python代码存在src/python_src
文件夹的LP_6_svm.py文件(方法一中的源代码),需要注意文件的相对目录变化。然后在Launcher中打开Terminal,执行python xx.py
文件来运行。
您也可以下载本.py文件,在自己的电脑上安装MindOpt求解器,然后在自己电脑的环境运行。
Luancher可以点击左上角的+打方块打开,Terminal在最下方,如截图示意。打开的窗口可以拖动调整位置。
然后在Terminal命令行里运行如下指令:
cd src/python_src
python LP_6_svm.py
运行得到的结果,同方法1:
求解结果
目标函数最优取值是: 6.4074250003085975。 解文件存在src/model/LP_6_svm.sol
。
联系我们
钉钉答疑群:32451444
钉钉活动群:18890022111
邮箱地址:solver.damo@list.alibaba-inc.com
更多更新通知:https://solver.damo.alibaba.com