SVM Tensorflow 实现
SVM Tensorflow implementation
我一直在关注吴教授的讲座,并尝试使用 tensorflow 在我的 jupyter notebook 上实现 SVM。但是,我的模型似乎没有正确收敛。
我想我的损失函数有误,最终可能无法正确拟合我的模型。
下面是我的模型的全图构造代码:
tf.reset_default_graph()
#training hyper parameters
learning_rate = 0.000001
C = 20
gamma = 50
X = tf.placeholder(tf.float32, shape=(None,2))
Y = tf.placeholder(tf.float32, shape=(None,1))
landmark = tf.placeholder(tf.float32, shape=(None,2))
W = tf.Variable(np.random.random((num_data)),dtype=tf.float32)
B = tf.Variable(np.random.random((1)),dtype=tf.float32)
batch_size = tf.shape(X)[0]
#RBF Kernel
tile = tf.tile(X, (1,num_data))
diff = tf.reshape( tile, (-1, num_data, 2)) - landmark
tile_shape = tf.shape(diff)
sq_diff = tf.square(diff)
sq_dist = tf.reduce_sum(sq_diff, axis=2)
F = tf.exp(tf.negative(sq_dist * gamma))
WF = tf.reduce_sum(W * F, axis=1) + B
condition = tf.greater_equal(WF, 0)
H = tf.where(condition, tf.ones_like(WF),tf.zeros_like(WF))
ERROR_LOSS = C * tf.reduce_sum(Y * tf.maximum(0.,1-WF) + (1-Y) * tf.maximum(0.,1+WF))
WEIGHT_LOSS = tf.reduce_sum(tf.square(W))/2
TOTAL_LOSS = ERROR_LOSS + WEIGHT_LOSS
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
train = optimizer.minimize(TOTAL_LOSS)
我正在使用高斯内核并将整个训练集作为地标。
损失函数与讲座中显示的完全相同,只要我正确地实现了它。
我很确定我遗漏了什么。
请注意,内核矩阵应具有 batch_size^2
个条目,而您的张量 WF
具有形状 (batch_size, 2)
。这个想法是为数据集中的每一对 (x_i, x_j) 计算 K(x_i, x_j),然后使用这些内核值作为 SVM 的输入.
我在 SVM 上使用 Andrew Ng's lecture notes 作为参考;在第 20 页,他导出了最终的优化问题。您需要用内核函数替换内积 <x_i, x_j>
。
我建议从线性内核而不是 RBF 开始,并将您的代码与开箱即用的 SVM 实现(如 sklearn's)进行比较。这将帮助您确保您的优化代码正常工作。
最后一点:虽然应该可以使用梯度下降来训练 SVM,但在实践中几乎从来没有用这种方式训练过。 SVM 优化问题可以通过二次规划来解决,大多数训练 SVM 的方法都利用了这一点。
我一直在关注吴教授的讲座,并尝试使用 tensorflow 在我的 jupyter notebook 上实现 SVM。但是,我的模型似乎没有正确收敛。
我想我的损失函数有误,最终可能无法正确拟合我的模型。
下面是我的模型的全图构造代码:
tf.reset_default_graph()
#training hyper parameters
learning_rate = 0.000001
C = 20
gamma = 50
X = tf.placeholder(tf.float32, shape=(None,2))
Y = tf.placeholder(tf.float32, shape=(None,1))
landmark = tf.placeholder(tf.float32, shape=(None,2))
W = tf.Variable(np.random.random((num_data)),dtype=tf.float32)
B = tf.Variable(np.random.random((1)),dtype=tf.float32)
batch_size = tf.shape(X)[0]
#RBF Kernel
tile = tf.tile(X, (1,num_data))
diff = tf.reshape( tile, (-1, num_data, 2)) - landmark
tile_shape = tf.shape(diff)
sq_diff = tf.square(diff)
sq_dist = tf.reduce_sum(sq_diff, axis=2)
F = tf.exp(tf.negative(sq_dist * gamma))
WF = tf.reduce_sum(W * F, axis=1) + B
condition = tf.greater_equal(WF, 0)
H = tf.where(condition, tf.ones_like(WF),tf.zeros_like(WF))
ERROR_LOSS = C * tf.reduce_sum(Y * tf.maximum(0.,1-WF) + (1-Y) * tf.maximum(0.,1+WF))
WEIGHT_LOSS = tf.reduce_sum(tf.square(W))/2
TOTAL_LOSS = ERROR_LOSS + WEIGHT_LOSS
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
train = optimizer.minimize(TOTAL_LOSS)
我正在使用高斯内核并将整个训练集作为地标。
损失函数与讲座中显示的完全相同,只要我正确地实现了它。
我很确定我遗漏了什么。
请注意,内核矩阵应具有 batch_size^2
个条目,而您的张量 WF
具有形状 (batch_size, 2)
。这个想法是为数据集中的每一对 (x_i, x_j) 计算 K(x_i, x_j),然后使用这些内核值作为 SVM 的输入.
我在 SVM 上使用 Andrew Ng's lecture notes 作为参考;在第 20 页,他导出了最终的优化问题。您需要用内核函数替换内积 <x_i, x_j>
。
我建议从线性内核而不是 RBF 开始,并将您的代码与开箱即用的 SVM 实现(如 sklearn's)进行比较。这将帮助您确保您的优化代码正常工作。
最后一点:虽然应该可以使用梯度下降来训练 SVM,但在实践中几乎从来没有用这种方式训练过。 SVM 优化问题可以通过二次规划来解决,大多数训练 SVM 的方法都利用了这一点。