Caffe应该是目前深度学习领域应用最广泛的几大框架之一了,尤其是视觉领域。绝大多数用Caffe的人,应该用的都是基于分类的网络,但有的时候也许会有基于回归的视觉应用的需要,查了一下Caffe官网,还真没有很现成的例子。这篇举个简单的小例子说明一下如何用Caffe和卷积神经网络(CNN: Convolutional Neural Networks)做基于回归的应用。
原理
最经典的CNN结构一般都是几个卷积层,后面接全连接(FC: Fully Connected)层,最后接一个Softmax层输出预测的分类概率。如果把图像的矩阵也看成是一个向量的话,CNN中无论是卷积还是FC,就是不断地把一个向量变换成另一个向量(事实上对于单个的filter/feature channel,Caffe里最基础的卷积实现就是向量和矩阵的乘法:Convolution in Caffe: a memo),最后输出就是一个把制定分类的类目数作为维度的概率向量。因为神经网络的风格算是黑盒子学习,所以很直接的想法就是把最后输出的向量的值直接拿来做回归,最后优化的目标函数不再是cross entropy等,而是直接基于实数值的误差。
EuclideanLossLayer
Caffe内置的EuclideanLossLayer就是用来解决上面提到的实值回归的一个办法。EuclideanLossLayer计算如下的误差:
\begin{align}\notag \frac 1 {2N} \sum_{i=1}^N \| x^1_i - x^2_i \|_2^2\end{align}
所以很简单,把标注的值和网络计算出来的值放到EuclideanLossLayer比较差异就可以了。
给图像混乱程度打分的简单例子
用一个给图像混乱程度打分的简单例子来说明如何使用Caffe和EuclideanLossLayer进行回归。
生成基于Ising模型的数据
这里采用统计物理里非常经典的Ising模型的模拟来生成图片,Ising模型可能是统计物理里被人研究最多的模型之一,不过这篇不是讲物理,就略过细节,总之基于这个模型的模拟可以生成如下的图片:
图片中第一个字段是编号,第二个字段对应的分数可以大致认为是图片的有序程度,范围0~1,而这个例子要做的事情就是用一个CNN学习图片的有序程度并预测。
生成图片的Python脚本源于Monte Carlo Simulation of the Ising Model using Python,基于Metropolis算法对Ising模型的模拟,做了一些并行和随机生成图片的修改,在每次模拟的时候随机取一个时间(1e3到1e7之间)点输出到图片,代码如下:
import os
import sys
import datetime
from multiprocessing import Process
import numpy as np
from matplotlib import pyplot
LATTICE_SIZE = 100
SAMPLE_SIZE = 12000
STEP_ORDER_RANGE = [3, 7]
SAMPLE_FOLDER = 'samples'
#----------------------------------------------------------------------#
# Check periodic boundary conditions
#----------------------------------------------------------------------#
def bc(i):
if i+1 > LATTICE_SIZE-1:
return 0
if i-1 < 0:
return LATTICE_SIZE - 1
else:
return i
#----------------------------------------------------------------------#
# Calculate internal energy
#----------------------------------------------------------------------#
def energy(system, N, M):
return -1 * system[N,M] * (system[bc(N-1), M] \
+ system[bc(N+1), M] \
+ system[N, bc(M-1)] \
+ system[N, bc(M+1)])
#----------------------------------------------------------------------#
# Build the system
#----------------------------------------------------------------------#
def build_system():
system = np.random.random_integers(0, 1, (LATTICE_SIZE, LATTICE_SIZE))
system[system==0] = - 1
return system
#-------------------------------------------