Python1.0用C++实现残差网络图像分类

友情提示:

  • 阅读本文需要您已经掌握Pytorch的Python用法,并掌握C++语言。
  • 推荐使用Ubuntu/Mac系统实验(cmake可以自动找到已安装的opencv)。
  • 本实验需要已安装好opencv和pytorch 1.0,C++编译环境(Ubuntu需要g++,Mac需要XCode)和cmake。

Pytorch 1.0已经于近日推出,其中一个亮点功能是支持将python训练的模型导出到C++进行推理。相比于目前流行的caffe训练模型+opencv dnn模块推理,pytorch从Python训练到C++部署提供了一体化的方案,可谓攻城狮的福音。

Python导出模型

根据Pytorch官网教程,我们先导出残差网络Resnet18的模型和预训练权重:

# coding=utf-8
import torch
import torchvision
from torchvision import transforms
from PIL import Image
import json
import cv2

# 初始化模型
model = torchvision.models.resnet18(pretrained=True)
model.eval() #将模型置为推理状态

# 随机生成一个输入张量
example = torch.rand(1, 3, 224, 224)

# 利用跟踪数据流的方法生成导出模型
traced_script_module = torch.jit.trace(model, example)
output = traced_script_module(torch.ones(1, 3, 224, 224))
print output.shape
print output[0, :5]
traced_script_module.save("model.pt")

这样在当前目录下会生成一个model.pt文件,包含了模型定义和权重。

继续阅读

图像分类问题与成像回归问题的异同

图像信号处理与回归

在图像处理中,最传统的问题是成像,用术语说是“图像信号处理(Image Signal Processing, ISP)”,也就是解决从光传感器采集的电信号数据到输出数字图像的问题。设采集到的数据(raw数据,通常是Bayer图像)为z \in R^{n \times 1},输出数字图像为x \in R^{3n \times 1},表达ISP过程的函数为f,则

f:z \rightarrow x \tag{1}

我们知道机器学习问题可以分为分类(Classification)和回归(Regression)问题,那么上述问题是一个回归问题。它求取的是zx之间的函数关系f。注意到z仅有n个实数数据,x3n个实数或者[0, 255]的离散数据,这是一个以少预测多的问题。仅从数据入手问题是病态的。因此,在ISP过程中,我们必须穷尽所有已知知识去为问题添加先验约束,使得输出的x具有最大似然性。添加先验约束可以从以下角度去考虑:

  • 图像x的统计信息,这包括人工获得的统计分布和机器学习得到的统计规律,它们都利用Bayer图像z的相似图像簇获得x的预测。
  • 图像x的空间结构先验,这包括图像单通道的空间先验和交叉通道先验。广义上,可以认为空间先验是人工获得的统计分布,但是由于图像的二维矩阵和三通道结构具有的特殊性,从空间位置挖掘像素关联具有特别重要的作用,因此单独列出。
  • 最后,x忠于Bayer图像z

计算机视觉与分类

得到图像后,最重要的问题是理解图像——图像的内容是什么?最简单的回答是这张图像属于某个类别,也就是机器学习中的分类问题。设数字图像为x \in R^{3n \times 1},图像类别是y \in \{1,\cdots,K\},其中K为正整数,则图像分类问题是求取一个函数

g: x \rightarrow y \tag{2}

注意x依然具有3n个变量,而y是一个离散变量。这是一个从多预测少的问题。从数据量来看,问题本身的病态性没有ISP那么大,但是也没有ISP那样的图像空间结构先验,g的求取完全依赖已有的图像数据,即

  • 利用与x相似的图像及其类别获得x类别的预测。

总结

成像问题(回归)与图像分类(分类)相比,成像问题有图像空间结构先验但是问题更病态,而图像分类仅依靠图像数据但问题病态性相对较低。目前效果比较好的机器学习方法多数仅仅使用数据而不是规则,适合解决图像分类问题而不适合解决成像回归问题。这种不适合的表现在于:方法少,性能不好,结果不稳定。不适合的内因在于问题本身的病态性,使得仅从有限数据学习统计规律去超越人工规则的困难大。不适合的外因在于机器学习的模型设计没有充分利用图像空间结构信息,没有充分学习到空间结构与图像数值的关联。

因此,如果从机器学习的角度来改进现有的成像算法,最重要的是改进模型,使得模型能学习到学习到空间结构与图像数值的关联。一种直接的思路是利用优化模型将已有规则先验与机器学习先验融合在一个模型中,另一种是改进具体的机器学习模型(如深度网络结构),强化图象空间结构约束,其具体形式还有待研究。

交叉通道先验简介

交叉通道先验是Heide13年论文中提出的一种RGB彩色图像统计先验,常被用于图像复原的优化目标函数中。

交叉通道先验的物理意义

我们提出在反卷积过程中共享不同通道的信息,从而一个通道保留的频率信息可以帮助其他通道重建。交叉通道先验基于这样的假设:图象所有通道在相同位置的边缘和色调变化是稀疏的。[1]这个假设可以导出两个通道$l,k$之间的先验
\begin{equation}
\begin{aligned}
& \nabla i_k ./ i_k \approx \nabla i_l ./ i_l \\
\Leftrightarrow & \nabla i_k \cdot i_l \approx \nabla i_l \cdot i_k
\end{aligned}
\end{equation}
其中乘法$\cdot$除法$./$都是元素操作。注意使用时我们用$\mathcal{l}_1$范数的形式。

最小化问题

通过交叉通道先验,全通道反卷积可以形式化为一个优化问题
\begin{equation}
(i_{1,2,3})_{opt} = \text{argmin}_{i_{1,2,3}} \sum_{c=1}^3 (
\Vert B_c ic - j_c \Vert_2^2 + \lambda_c \sum\{a=1}^5 \Vert H_a i_c \Vert_1 \\

  • \sum_{l \neq c} \beta_{cl} \sum_{a=1}^2 \Vert H_a i_c \cdot i_l - H_a i_l \cdot i_c \Vert_1
    )
    \tag{1}
    \end{equation}
    其中卷积矩阵$H_{1,2}$实现一阶导数,$H_{3,4,5}$实现二阶导数。式(1)中第一项是数据保真项,第二项确保梯度和边缘服从重尾分布(heavey-tailed distribution),最后一项表示交叉通道先验。
    继续阅读

一维向量和二维矩阵卷积的等价矩阵乘法实现

经过学习和探索,掌握了一维卷积和二维卷积的矩阵乘法实现。

对于一维向量的卷积,Matlab提供了convmtx计算向量对应的乘法矩阵。它是一个Toeplitz矩阵。

% By TomHeaven, hanlin_tan@nudt.edu.cn @ 2016.09.28
x = [1 2 3]';
y = [4 5 6]';
 
n = length(y);
H = convmtx(x,n);
z = H*y;
 
z_c = conv(x, y);
 
diff = norm(z - z_c)

二维卷积(图像与核卷积)的矩阵乘法形式,矩阵的构造方法可以通过简单的算理推演得到。它是一个Band(带宽)矩阵。

设二维图像矩阵为$X \in R^{m \times n}$,卷积核矩阵为$Y \in R^{p \times p}$。它们按行优先展开得到的向量分别为$x,y$。
继续阅读

浅谈图象的全变分和去噪

全变分(Total variation),也称为全变差,是图象复原中常用的一个名词。本文简要介绍全变分的概念以及在图象去噪中的应用。

一维信号的全变分和去噪

一维连续函数的全变分

一维连续实函数f(x)在区间[a, b] \subset R上的全变分定义为参数曲线x \rightarrow f(x), x \in [a,b]的弧长。其表达式为

V_a^b(f) = \int_a^b |f'(x)|dx

说白了,所谓的“变分”就是|f(x+\Delta x) - f(x)|,对于连续函数\Delta x \rightarrow 0。而全变分是对函数定义的区间而言的,就是将“变分”在区间上累加起来。

继续阅读