图片风格转换--深度学习介绍
前言
先举个机器学习的应用例子:图片的风格转换。
原图.jpg 处理后的图.jpg机器学习
通过计算机强大的计算能力进行迭代运算、试错得到相关知识。
形象生动的描述请看:机器学习
深度学习
神经网络上图是一个网络神经示意图,左边的是输入层,最右边的是
输出层
,两层之间的叫隐藏层
,隐藏层大于2的神经网络就叫深度神经网络,深度学习就是基于深度神经网络的机器学习,深度学习是机器学习中的一种。
深度学习的相关概念
1、感知器
2、线性单元和梯度下降
3、神经网络和反向传播算法
4、卷积神经网络
一、感知器
感知器.png1、输入权值:
x1,x2...是值,w1,w2....是权重。
2、激活函数 :
这里举个最简单的例子,采用阶跃函数
阶跃函数.png
输入权值,经过激活函数后就是0或1。
3、输出:
感知器就是通过输入的权重与值,经过激活函数预算,再通过输出公式得出结果
二、线性单元和梯度下降
1、什么是线性单元
激活函数为线性函数的感知器就叫做线性单元。
当面对的数据集不是线性可分的时候,『感知器规则』可能无法收敛,所以我们用可导的线性函数来替代感知器的激活函数,例如f(x) = x
之后,线性单元将返回一个实数值而不是0,1分类。因此线性单元用来解决回归问题。
2、监督学习和无监督学习
机器学习有一类学习方法叫做监督学习,它是说为了训练一个模型,我们要提供这样一堆训练样本:每个训练样本即包括输入特征x,也包括对应的输出y(y也叫做标记,label)。也就是说,我们要找到很多人,我们既知道他们的特征x(工作年限,行业...),也知道他们的收入y。我们用这样的样本去训练模型,让模型既看到我们提出的每个问题(输入特征x),也看到对应问题的答案(标记y)。当模型看到足够多的样本之后,它就能总结出其中的一些规律。然后,就可以预测那些它没看过的输入所对应的答案了。
另外一类学习方法叫做无监督学习,这种方法的训练样本中只有x而没有y。模型可以总结出特征x的一些规律,但是无法知道其对应的答案y。
3、线性单元的目标函数
所有误差之和.png Paste_Image.png 误差模型的训练,实际上就是求取到合适的w,使误差E取得最小值。这在数学上称作优化问题,而就是我们优化的目标,称之为目标函数
4、梯度下降优化算法
梯度是一个向量,它指向函数值上升最快的方向,梯度的反方向当然就是函数值下降最快的方向.沿着梯度相反方向去修改x的值,进行迭代获得最小值。
Paste_Image.png首先我们选择一个点开始,x0,接下来迭代x1,x2,x3..一直到函数最小值。
梯度下降算法的公式如下:
梯度下降算法公式.png
三、神经网络和反向传播算法
神经元
神经元就是激活函数或tanh函数的感知器。
多个神经元构成神经网络
神经网络的输出
神经网络实际上就是一个输入向量x(向量,不是普通的变量,具有方向)到输出向量y的函数,即:
反向传播算法(Back Propagation)
我们需要知道一个神经网络的每个连接上的权值是如何得到的。我们可以说神经网络是一个模型,那么这些权值就是模型的参数,也就是模型要学习的东西。然而,一个神经网络的连接方式、网络的层数、每层的节点数这些参数,则不是学习出来的,而是人为事先设置的。对于这些人为设置的参数,我们称之为超参数(Hyper-Parameters)。而我们需要做的是通过算法对神经网络进行训练,反向传播算法是神经网络训练算法。
计算一个节点的误差项,需要先计算每个与其相连的下一层节点的误差项。这就要求误差项的计算顺序必须是从输出层开始,然后反向依次计算每个隐藏层的误差项,直到与输入层相连的那个隐藏层。这就是反向传播算法的名字的含义,最后我们可以通过计算出的误差反过来修正权重。
就这样,通过不断迭代,不断修正权重对神经网络进行训练。
神经网络的输出.png四、卷积神经网络
适合图像、语音识别任务的神经网络结构——卷积神经网络
1、Relu激活函数
在卷积神经网络中Relu函数更为适合作为激活函数,公式如下:
Relu.pngRelu函数图像如下图所示:
采用Relu函数,有以下优点:
速度快
减轻梯度消失问题
稀疏性
2、卷积神经网络
一个卷积神经网络由若干卷积层、Pooling层、全连接层组成
我们可以发现卷积神经网络的层结构和全连接神经网络的层结构有很大不同。全连接神经网络每层的神经元是按照一维排列的,也就是排成一条线的样子;而卷积神经网络每层的神经元是按照三维排列的,也就是排成一个长方体的样子,有宽度、高度和深度
实践应用:
一、通过深度学习对图片进行风格转换
原图与名画合成新图片:
原图.jpg bigjiasuo.jpg 14764268560.0-10-bigjiasuo-googlenet-content-1e4-512.jpg 14764182840.0-10-fango-googlenet-content-1e4-512.jpg主要的流程是:利用Caffe框架进行深度学习,通过梯度算法,完成颜色、线条等的训练集,然后对图片进行重绘。
1、框架、依赖等准备
(1)、安装python、pip、numpy。
(2)、安装深度学习框架caffe
(3)、下载训练模型:我采用的是googlenet model
(4)、下载style-transfer代码,根据自己的需求进行修改、优化。
(5)、根据style-transfer文档运行。
这几个步骤操作起来都是比较困难的,也算是个不小的门槛。其中Caffe的安装琐碎,会出现很多意外,是个大难题;style-transfer代码修改是最核心的部分。
2、核心代码展示
梯度处理代码:
def _compute_style_grad(F, G, G_style, layer):
(Fl, Gl) = (F[layer], G[layer])
c = Fl.shape[0]**-2 * Fl.shape[1]**-2
El = Gl - G_style[layer]
loss = c/4 * (El**2).sum()
grad = c * sgemm(1.0, El, Fl) * (Fl>0)
return loss, grad
def _compute_content_grad(F, F_content, layer):
Fl = F[layer]
El = Fl - F_content[layer]
loss = (El**2).sum() / 2
grad = El * (Fl>0)
return loss, grad
矩阵计算
def _compute_reprs(net_in, net, layers_style, layers_content, gram_scale=1):
(repr_s, repr_c) = ({}, {})
net.blobs["data"].data[0] = net_in
net.forward()
for layer in set(layers_style)|set(layers_content):
F = net.blobs[layer].data[0].copy()
F.shape = (F.shape[0], -1)
repr_c[layer] = F
if layer in layers_style:
repr_s[layer] = sgemm(gram_scale, F, F.T)
return repr_s, repr_c
进行转换:
def transfer_style(self, img_style, img_content, length=512, ratio=1e5,
n_iter=512, init="-1", verbose=False, callback=None):
# assume that convnet input is square
orig_dim = min(self.net.blobs["data"].shape[2:])
# rescale the images
scale = max(length / float(max(img_style.shape[:2])),
orig_dim / float(min(img_style.shape[:2])))
img_style = rescale(img_style, STYLE_SCALE*scale)
scale = max(length / float(max(img_content.shape[:2])),
orig_dim / float(min(img_content.shape[:2])))
img_content = rescale(img_content, scale)
# compute style representations
self._rescale_net(img_style)
layers = self.weights["style"].keys()
net_in = self.transformer.preprocess("data", img_style)
gram_scale = float(img_content.size)/img_style.size
G_style = _compute_reprs(net_in, self.net, layers, [],
gram_scale=1)[0]
# compute content representations
self._rescale_net(img_content)
layers = self.weights["content"].keys()
net_in = self.transformer.preprocess("data", img_content)
F_content = _compute_reprs(net_in, self.net, [], layers)[1]
# generate initial net input
# "content" = content image, see kaishengtai/neuralart
if isinstance(init, np.ndarray):
img0 = self.transformer.preprocess("data", init)
elif init == "content":
img0 = self.transformer.preprocess("data", img_content)
elif init == "mixed":
img0 = 0.95*self.transformer.preprocess("data", img_content) + \
0.05*self.transformer.preprocess("data", img_style)
else:
img0 = self._make_noise_input(init)
# compute data bounds
data_min = -self.transformer.mean["data"][:,0,0]
data_max = data_min + self.transformer.raw_scale["data"]
data_bounds = [(data_min[0], data_max[0])]*(img0.size/3) + \
[(data_min[1], data_max[1])]*(img0.size/3) + \
[(data_min[2], data_max[2])]*(img0.size/3)
# optimization params
grad_method = "L-BFGS-B"
reprs = (G_style, F_content)
minfn_args = {
"args": (self.net, self.weights, self.layers, reprs, ratio),
"method": grad_method, "jac": True, "bounds": data_bounds,
"options": {"maxcor": 8, "maxiter": n_iter, "disp": verbose}
}
# optimize
self._callback = callback
minfn_args["callback"] = self.callback
if self.use_pbar and not verbose:
self._create_pbar(n_iter)
self.pbar.start()
res = minimize(style_optfn, img0.flatten(), **minfn_args).nit
self.pbar.finish()
else:
res = minimize(style_optfn, img0.flatten(), **minfn_args).nit
return res
二、其他比较出名的应用:
1、谷歌的deepdream:可以让你的机器自己做梦。
效果图.png2、雅虎的色情图片检测神经网络:效果不知道,千万不能结合爬虫去爬图片,违法的。