相关理论可以看这篇文章 Deep Learning using Linear Support Vector Machines,ICML 2013
主要使用的是SVM的hinge loss形式的损失函数
原始的SVM的损失:(公式图片截取自开头的论文)
SVM的hinge loss形式的损失:(公式图片截取自开头的论文)
这里解决的是二分类问题,多分类的话和softmax一样,简单说明如下:(公式图片截取自开头的论文)
观察那个损失函数可以知道,它其实可以看做是一个 hinge loss 加上一个L2 regularization,前面的1/2就是L2正则项的系数lambda,这在CNN中很容易实现
使用CNN进行多分类的时候,最后一层的神经元个数是类别数目
使用softmax分类时,最后一层的激活函数设置为softmax就好
现在不用激活函数,或者激活函数设置为'linear',即即f(x)=x
prediction = Dense(7,activation='linear', #或者不适用激活函数?
kernel_regularizer=regularizers.l2(0.5),
name=name+'FC_linear')(x)
然后在keras后端添加一个自定义损失(在源代码的losses.py中)
def categorical_squared_hinge(y_true, y_pred):
"""
hinge with 0.5*W^2 ,SVM
"""
y_true = 2. * y_true - 1 # trans [0,1] to [-1,1],注意这个,svm类别标签是-1和1
vvvv = K.maximum(1. - y_true * y_pred, 0.) # hinge loss,参考keras自带的hinge loss
# vvv = K.square(vvvv) # 文章《Deep Learning using Linear Support Vector Machines》有进行平方
vv = K.sum(vvvv, 1, keepdims=False) #axis=len(y_true.get_shape()) - 1
v = K.mean(vv, axis=-1)
return v
最后,在编译模型的时候使用自定义损失,名字就是函数的名字了
model.compile( optimizer=adm, loss=['categorical_squared_hinge'], metrics=['accuracy'] )
更新:
有人说看不懂?
首先:
svm的预测输出是f(x) = w^T * x, f(x)>0表示一类, f(x)<0表示另一类, f(x)==0表示超平面, 这就是二分类了.
然后:
注意看损失函数, 原始损失s.t.里面是约束条件, 要求f(x)必须和标签t同号, 即f(x)*t>(1-ε)>0 (本来是f(x)*t>1, 1是间隔, 后来加入了松弛变量ε, 允许一些离群点, 为了增加分类器的容错性)!
再看hinge loss形式, 当f(x)与标签t不同号时, f(x)*t<0, 那么max(1-f(x)*t, 0)>1, 损失值肯定>1.
然而在优化hinge loss的时候(就是训练分类器的时候), 损失值逐渐下降, 分类器函数拟合这些点, 使得大部分点满足f(x)*t>0, 即预测输出f(x)与t同号!
所以分类器训练完毕后, 直接用f(x)>0表示一类, f(x)<0表示另一类. 这是针对二分类. 在CNN中实现时w就是最后一个全连接层的参数了
那么对于多分类呢, 常用的方法是one-versus-rest, 即一对多, 具体是啥可以网上查查
在开头那篇文章中, 做法是如果有K个类别, 就在CNN中训练K个二分类的svm分类器, 就是对应一个具有K个神经元输出的全连接层, 每个分类器表示1个类别, 最后预测输出值最大的那个神经元(svm分类器)对应的类别作为最终的预测类别!