用卷积神经网络实现步骤mnist分类为什么会死机

3:用tensorflow搭个神经网络出来
&&&&&&& 为什么用tensorflow呢,应为谷歌是亲爹啊,虽然有些人说caffe更适合图像啊mxnet效率更高等等,但爸爸就是爸爸,Android都能那么火,一个道理嘛。其实这些个框架一通百通,就是语法不一样了些。从tensorflow开始吧。
&&&&&&& 关于tf的安装详见另一篇博文,此处tensorflow的学习基本来自Udacity中google的深度学习课程。
1:tensorflow的计算图
在tensorflow中编写代码可以分成两个部分,首先是要定义一个计算的流程,或者叫计算图,然后再建立一个任务,让tensorflow调用系统资源去运算这个东西,举个栗子:
import tensorflow as tf #导入tensorflow库
matrix1=tf.constant([[3.,3.]])#创建常量节点
matrix2=tf.constant([2.],[2.])
product=tf.matmul(matrix1,matrix2)#创建矩阵乘法节点
上边并没有运算具体的值,而只是一个运算图。
真正的计算要用到session:
sess=tf.Session()#启动默认图
#运行这里会有一堆运行信息出来
result = sess.run(product)#调用sess的run方法来执行矩阵乘法节点的操作,product代表了矩阵乘法这个节点的输出
print result
sess.close()#完成任务后关闭会话
这就是tf的基础运行方式,对于变量,使用Variable方法定义:
W1=tf.Variable(tf.zeros((2,2)), name=”weights”)
sess.run(tf.initialize_all_variables())#变量需要预先初始化
print sess.run(W1)
另一个栗子:
state = tf.Variable(0,name=”counter”)
new_value=tf.add(state, tf.constant(1))#对state加1
update=tf.assign(state,new_value)#将自增后的值重新赋值给state
with tf.Session() as sess: #使用with可以省去close()操作,还可以处理一些操作出现的异常(也可以用try)
sess.run(tf.initialize_all_variables())
print(sess.run(state))#输出计数器值
for _ in range(3):
sess.run(update)
print(sess.run(state))
为毛谷歌爸爸这么蛋疼呢,直接算不好吗?其实一点也不蛋疼,这么设计,同样一套计算图,就可以扔给不同的设备或者分布式的设备去运算了:
with tf.Session() as sess:
with tf.device(“/gpu:1”):
另一个好处就是python的运算效率较低,所以设计成使用python编写运算图,之后再使用python之外的运算器(比如底层的C++)去计算。
2:使用tensorflow搭建一个卷积神经网络
这里会详解Google发布在udacity中使用CNN分类not_MINIST数据代码,这些代码包含在了tensorflow源代码中的examples中
&1&:准备数据(notMINIST)
代码的第一部分是载入数据:
# These are all the modules we'll be using later. Make sure you can import them
# before proceeding further.
from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
import sys
import tarfile
from IPython.display import display, Image
from scipy import ndimage
from sklearn.linear_model import LogisticRegression
from six.moves.urllib.request import urlretrieve
import tensorflow as tf
from six.moves import cPickle as pickle
from six.moves import range
# Config the matplotlib backend as plotting inline in IPython
%matplotlib inline
url = '/books1000/'
last_percent_reported = None
def download_progress_hook(count, blockSize, totalSize):
"""A hook to report the progress of a download. This is mostly intended for users with
slow internet connections. Reports every 5% change in download progress.
global last_percent_reported
percent = int(count * blockSize * 100 / totalSize)
if last_percent_reported != percent:
if percent % 5 == 0:
sys.stdout.write("%s%%" % percent)
sys.stdout.flush()
sys.stdout.write(".")
sys.stdout.flush()
last_percent_reported = percent
def maybe_download(filename, expected_bytes, force=False):
"""Download a file if not present, and make sure it's the right size."""
if force or not os.path.exists(filename):
print('Attempting to download:', filename)
filename, _ = urlretrieve(url + filename, filename, reporthook=download_progress_hook)
print('\nDownload Complete!')
statinfo = os.stat(filename)
if statinfo.st_size == expected_bytes:
print('Found and verified', filename)
raise Exception(
'Failed to verify ' + filename + '. Can you get to it with a browser?')
return filename
train_filename = maybe_download('notMNIST_large.tar.gz', )
test_filename = maybe_download('notMNIST_small.tar.gz', 8458043)
上边的代码是下载所需要的数据集压缩包,下一步是解压
num_classes = 10
np.random.seed(133)
def maybe_extract(filename, force=False):
root = os.path.splitext(os.path.splitext(filename)[0])[0]
# remove .tar.gz
if os.path.isdir(root) and not force:
# You may override by setting force=True.
print('%s already present - Skipping extraction of %s.' % (root, filename))
print('Extracting data for %s. This may take a while. Please wait.' % root)
tar = tarfile.open(filename)
sys.stdout.flush()
tar.extractall()
tar.close()
data_folders = [
os.path.join(root, d) for d in sorted(os.listdir(root))
if os.path.isdir(os.path.join(root, d))]
if len(data_folders) != num_classes:
raise Exception(
'Expected %d folders, one per class. Found %d instead.' % (
num_classes, len(data_folders)))
print(data_folders)
return data_folders
train_folders = maybe_extract(train_filename)
test_folders = maybe_extract(test_filename)
解压后可以查看一下代码文件所在的文件夹中会有两个文件夹not_MNIST_large和not_MNIST_small,large用来训练,small用来验证,每个文件夹中都有10个文件夹,分别保存了A到J的图像(28*28),这些图像就是数据集,标签就是A到J,当然之前下载的压缩文件也在。下一步是将这些数据转换成python中更容易处理的pickle格式,为了确保内存装得下,我们把每一个类别分别转换成一个独立的pickle文件,同时也对数据进行去均值和归一化,在这个过程中可能会有一些文件是不可读的,跳过即可,无所谓:
image_size = 28
# Pixel width and height.
pixel_depth = 255.0
# Number of levels per pixel.
def load_letter(folder, min_num_images):
"""Load the data for a single letter label."""
image_files = os.listdir(folder)
dataset = np.ndarray(shape=(len(image_files), image_size, image_size),
dtype=np.float32)
print(folder)
num_images = 0
for image in image_files:
image_file = os.path.join(folder, image)#文件路径拼接
image_data = (ndimage.imread(image_file).astype(float) -
pixel_depth / 2) / pixel_depth #去均值和归一化
if image_data.shape != (image_size, image_size):
raise Exception('Unexpected image shape: %s' % str(image_data.shape))
dataset[num_images, :, :] = image_data
num_images = num_images + 1
except IOError as e:
print('Could not read:', image_file, ':', e, '- it\'s ok, skipping.')
dataset = dataset[0:num_images, :, :]
if num_images & min_num_images:
raise Exception('Many fewer images than expected: %d & %d' %
(num_images, min_num_images))
print('Full dataset tensor:', dataset.shape)
print('Mean:', np.mean(dataset))
print('Standard deviation:', np.std(dataset))
return dataset
def maybe_pickle(data_folders, min_num_images_per_class, force=False):
dataset_names = []
for folder in data_folders:#本例中就是not_MNIST_large/A, not_MNIST_large/B等等
set_filename = folder + '.pickle'#folders是A到J,设定文件名
dataset_names.append(set_filename)#往dataset_names后边添加set_filename
if os.path.exists(set_filename) and not force:
# You may override by setting force=True.
print('%s already present - Skipping pickling.' % set_filename)
print('Pickling %s.' % set_filename)
dataset = load_letter(folder, min_num_images_per_class)
with open(set_filename, 'wb') as f:
pickle.dump(dataset, f, pickle.HIGHEST_PROTOCOL)
except Exception as e:
print('Unable to save data to', set_filename, ':', e)
return dataset_names
train_datasets = maybe_pickle(train_folders, 45000)
test_datasets = maybe_pickle(test_folders, 1800)
上边的代码就是把数据压缩到了一个pickle文件中去了,这样生成的数据文件可以在后续的程序中继续使用,这也就是没有直接采集图像数据的原因之一,下一步是将这些pickle文件中的数据进行合并和分类,生成一个拥有训练集、测试集合验证集的文件,训练数据的量取决于内存,如果非要使用超出内存的量的数据必须就分开运算了。
def make_arrays(nb_rows, img_size):#在merge_dagasets方法中把数据转换成图片个数*imgsize*imgsize(28),同时建一个标签向量,大小为nb_rows
if nb_rows:
dataset = np.ndarray((nb_rows, img_size, img_size), dtype=np.float32)
labels = np.ndarray(nb_rows, dtype=np.int32)
dataset, labels = None, None
return dataset, labels
def merge_datasets(pickle_files, train_size, valid_size=<span style="color: #):
num_classes = len(pickle_files)
valid_dataset, valid_labels = make_arrays(valid_size, image_size)
train_dataset, train_labels = make_arrays(train_size, image_size)
vsize_per_class = valid_size // num_classes
tsize_per_class = train_size // num_classes
start_v, start_t = 0, 0
end_v, end_t = vsize_per_class, tsize_per_class
end_l = vsize_per_class+tsize_per_class
for label, pickle_file in enumerate(pickle_files):#将分布在10个pickle文件中的数据合并成一个张量
with open(pickle_file, 'rb') as f:
letter_set = pickle.load(f)
# 将读取到的pickle文件中的数据打乱
np.random.shuffle(letter_set)
if valid_dataset is not None:
valid_letter = letter_set[:vsize_per_class, :, :]
valid_dataset[start_v:end_v, :, :] = valid_letter
valid_labels[start_v:end_v] = label
start_v += vsize_per_class
end_v += vsize_per_class
train_letter = letter_set[vsize_per_class:end_l, :, :]
train_dataset[start_t:end_t, :, :] = train_letter
train_labels[start_t:end_t] = label
start_t += tsize_per_class
end_t += tsize_per_class
except Exception as e:
print('Unable to process data from', pickle_file, ':', e)
return valid_dataset, valid_labels, train_dataset, train_labels
train_size = 200000
valid_size = 10000
test_size = 10000
valid_dataset, valid_labels, train_dataset, train_labels = merge_datasets(
train_datasets, train_size, valid_size)
_, _, test_dataset, test_labels = merge_datasets(test_datasets, test_size)
print('Training:', train_dataset.shape, train_labels.shape)
print('Validation:', valid_dataset.shape, valid_labels.shape)
print('Testing:', test_dataset.shape, test_labels.shape)
最后将数据再次打乱保存后,就得到了最后的pickle文件。
def randomize(dataset, labels):
permutation = np.random.permutation(labels.shape[0])
shuffled_dataset = dataset[permutation,:,:]
shuffled_labels = labels[permutation]
return shuffled_dataset, shuffled_labels
train_dataset, train_labels = randomize(train_dataset, train_labels)
test_dataset, test_labels = randomize(test_dataset, test_labels)
valid_dataset, valid_labels = randomize(valid_dataset, valid_labels)
pickle_file = 'notMNIST.pickle'
f = open(pickle_file, 'wb')
save = {#存到一个dictionary中去
'train_dataset': train_dataset,#num*28*28
'train_labels': train_labels,#num*10
'valid_dataset': valid_dataset,#…
'valid_labels': valid_labels,
'test_dataset': test_dataset,
'test_labels': test_labels,
pickle.dump(save, f, pickle.HIGHEST_PROTOCOL)
except Exception as e:
print('Unable to save data to', pickle_file, ':', e)
statinfo = os.stat(pickle_file)
print('Compressed pickle size:', statinfo.st_size)
上面是一些预操作,然后我们读取这个pickle文件,得到卷积神经网络要使用的数据文件:
pickle_file = 'notMNIST.pickle'
with open(pickle_file, 'rb') as f:
save = pickle.load(f)
train_dataset = save['train_dataset']
train_labels = save['train_labels']
valid_dataset = save['valid_dataset']
valid_labels = save['valid_labels']
test_dataset = save['test_dataset']
test_labels = save['test_labels']
# hint to help gc free up memory
print('Training set', train_dataset.shape, train_labels.shape)
print('Validation set', valid_dataset.shape, valid_labels.shape)
print('Test set', test_dataset.shape, test_labels.shape)
Training set (, 28) (200000,)
Validation set (1) (10000,)
Test set (1) (18724,)
可见训练集、验证集和测试集的原始格式。如果要将数据用到一个人工神经网络中,就要把每个图像数据都转换成一个长×宽维的向量,而在卷积神经网络中我们需要将图片数据转换成长×宽×深度的样子,同时将labels转换成one-hot encodings格式,于是:
image_size = 28
num_labels = 10
num_channels = 1 # grayscale,如果要使用RGB格式数据就是3了
import numpy as np
def reformat(dataset, labels):
dataset = dataset.reshape(
(-1, image_size, image_size, num_channels)).astype(np.float32)
#-1表示我懒得计算该填什么数字,由python通过a和其他的值3推测出来(这句话来自知乎,感觉好精辟啊)
labels = (np.arange(num_labels) == labels[:,None]).astype(np.float32)
#这句写的很迷,肿么解释。。。
#labels[:,None]相当于把shape为(20w,)的labels转换成shape为(20w,1)的数组,从[1,2,3,4...]到[[1],[2],[3],…]
#np.arange是生成了一个[0,1,2,3...]的(10,)的数组
#判断一个(10,)是否等于一个(10,1)的数组,或者说判断一个列向量是否等于一个行向量,可理解为矩阵乘法了,定义乘法规则为一样就是true,不一样就是false,那么这个判断式的结果就是一个20w*10的数组。
return dataset, labels
train_dataset, train_labels = reformat(train_dataset, train_labels)
valid_dataset, valid_labels = reformat(valid_dataset, valid_labels)
test_dataset, test_labels = reformat(test_dataset, test_labels)
print('Training set', train_dataset.shape, train_labels.shape)
print('Validation set', valid_dataset.shape, valid_labels.shape)
print('Test set', test_dataset.shape, test_labels.shape)
运行结果为:
Training set (, 28, 1) ()
Validation set (1, 1) (10000, 10)
Test set (1, 1) (10000, 10)
下一步我们先定义一个用来检测预测精度的方法:
def accuracy(predictions, labels):
return (100.0 * np.sum(np.argmax(predictions, 1) == np.argmax(labels, 1))
/ predictions.shape[0])#注意这里的argmax方法返回的是数组的索引值。
&2&:Draw a graph
前边说过了,tensorflow中进行运算,首先需要构建一个运算图,在这里将建立一个拥有两个卷积层和一个全连接层的卷积神经网络,算这个东西需要很土豪的显卡,所以限制了一下深度和全卷积层的节点。
batch_size = 16 #SGD每次选取的图片个数
patch_size = 5 #卷积窗口大小
depth = 16 #卷积深度,就是特征图的个数
num_hidden = 64 #全连接层隐层大小
graph = tf.Graph()
with graph.as_default():
# Input data.4
tf_train_dataset = tf.placeholder(
tf.float32, shape=(batch_size, image_size, image_size, num_channels))#每次选出batch_size个图片参与运算
tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))
tf_valid_dataset = tf.constant(valid_dataset)
tf_test_dataset = tf.constant(test_dataset)
# Variables.
layer1_weights = tf.Variable(tf.truncated_normal(
[patch_size, patch_size, num_channels, depth], stddev=0.1))#随机初始化第一卷积层权重参数,depth*num_channels张特征图,滑动窗口大小为5*5
layer1_biases = tf.Variable(tf.zeros([depth]))#第一卷积层bias项初始化为0
layer2_weights = tf.Variable(tf.truncated_normal(#随机初始化第二卷积层权重参数,depth*depth张特征图,滑动窗口5*5
[patch_size, patch_size, depth, depth], stddev=0.1))
layer2_biases = tf.Variable(tf.constant(1.0, shape=[depth]))#第二卷积层bias项初始化为0
layer3_weights = tf.Variable(tf.truncated_normal(
[image_size // 4 * image_size // 4 * depth, num_hidden], stddev=0.1))#全连接层第一层,//4是因为后边定义模型的时候定义stride为2,
#所以两次卷积后的数据就是7*7*16*16了???????
layer3_biases = tf.Variable(tf.constant(1.0, shape=[num_hidden]))
layer4_weights = tf.Variable(tf.truncated_normal(#全连接层第二层
[num_hidden, num_labels], stddev=0.1))
layer4_biases = tf.Variable(tf.constant(1.0, shape=[num_labels]))
def model(data):
conv = tf.nn.conv2d(data, layer1_weights, [1, 2, 2, 1], padding='SAME')#这里1,2,2,1是stride,依次对应到data的格式中去
#same padding是补0的那种padding模式,比较便于运算,所以基本上都用这种的。
hidden = tf.nn.relu(conv + layer1_biases)
conv = tf.nn.conv2d(hidden, layer2_weights, [1, 2, 2, 1], padding='SAME')
hidden = tf.nn.relu(conv + layer2_biases)
shape = hidden.get_shape().as_list()
reshape = tf.reshape(hidden, [shape[0], shape[1] * shape[2] * shape[3]])
hidden = tf.nn.relu(tf.matmul(reshape, layer3_weights) + layer3_biases)
return tf.matmul(hidden, layer4_weights) + layer4_biases
# Training computation.
logits = model(tf_train_dataset)
loss = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(logits, tf_train_labels))
# Optimizer.
optimizer = tf.train.GradientDescentOptimizer(0.05).minimize(loss)#梯度下降
# Predictions for the training, validation, and test data.
train_prediction = tf.nn.softmax(logits)
valid_prediction = tf.nn.softmax(model(tf_valid_dataset))
test_prediction = tf.nn.softmax(model(tf_test_dataset))
这里看程序的话感觉好像是计算了,尤其是最后几句话,其实并没有计算的,下一步才是使用session来计算。
num_steps = 1001
#batch_size=16
with tf.Session(graph=graph) as session:
#tf.global_variables_initializer().run()#for old version of tf0
session.run(tf.initialize_all_variables())
print('Initialized')
for step in range(num_steps):
offset = (step * batch_size) % (train_labels.shape[0] - batch_size)#这句是防止迭代次数过多超出数据集范围,就通过取余数改变取batch的偏置
batch_data = train_dataset[offset:(offset + batch_size), :, :, :]
batch_labels = train_labels[offset:(offset + batch_size), :]
feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels}
_, l, predictions = session.run(
[optimizer, loss, train_prediction], feed_dict=feed_dict)
if (step % 50 == 0):
print('Minibatch loss at step %d: %f' % (step, l))
print('Minibatch accuracy: %.1f%%' % accuracy(predictions, batch_labels))
print('Validation accuracy: %.1f%%' % accuracy(
valid_prediction.eval(), valid_labels))
print('Test accuracy: %.1f%%' % accuracy(test_prediction.eval(), test_labels))
以上就是实用卷积神经网络简单的区分not_MNIST数据的程序,池化层我还没加上,还有dropout防止过拟合也没有添加,待续。先看rfcn吧。
阅读(...) 评论()当前位置: >>
卷积神经网络CNN
卷积神经网络(CNN) 一、简介卷积神经网络 (Convolutional Neural Networks, 简称 CNN) 是近年发展起来, 并引起广泛重视的一种高效的识别方法。 1962 年, Hubel 和 Wiesel 在研究猫脑皮层中用于局部敏感和方向选择的神经 元时发现其独特的局部互连网络结构可以有效地降低反馈神经网络的复杂性, 继 [1] 7863 而提出了卷积神经网络 (Convolutional Neural Networks-简称 CNN) 。 现在, CNN 已经成为众多科学领域的研究热点之一,特别是在模式分类领域,由于该 网络避免了对图像的复杂前期预处理,可以直接输入原始图像,因而得到了更为 广泛的应用。 Fukushima 在 1980 年基于神经元间的局部连通性和图像的层次组织转换, 为 解决模式识别问题,提出的新识别机(Neocognitron)是卷积神经网络的第一个 实现网络[2]。他指出,当在不同位置应用具有相同参数的神经元作为前一层的 patches 时,能够实现平移不变性 1296。随着 1986 年 BP 算法以及 T-C 问题[3](即 权值共享和池化)9508 的提出,LeCun 和其合作者遵循这一想法,使用误差梯度 (the error gradient)设计和训练卷积神经网络,在一些模式识别任务中获得了最 先进的性能[4][5]。 在 1998 年, 他们建立了一个多层人工神经网络, 被称为 LeNet-5[5], 用于手写数字分类,这是第一个正式的卷积神经网络模型 3579。 类似于一般的神经 网络,LeNet-5 有多层,利用 BP 算法来训练参数。它可以获得原始图像的有效 表示,使得直接从原始像素(几乎不经过预处理)中识别视觉模式成为可能。然 而,由于当时大型训练数据和计算能力的缺乏,使得 LeNet-5 在面对更复杂的问 题时,如大规模图像和视频分类,不能表现出良好的性能。 因此,在接下来近十年的时间里,卷积神经网络的相关研究趋于停滞,原因 有两个: 一是研究人员意识到多层神经网络在进行 BP 训练时的计算量极其之大, 当时的硬件计算能力完全不可能实现;二是包括 SVM 在内的浅层机器学习算法 也渐渐开始暂露头脚。直到 2006 年,Hinton 终于一鸣惊人,在《科学》上发表 文章,使得 CNN 再度觉醒,并取得长足发展。随后,更多的科研工作者对该网 络进行了改进。其中,值得注意的是 Krizhevsky 等人提出的一个经典的 CNN 架 构,相对于图像分类任务之前的方法,在性能方面表现出了显著的改善 2674。他 们方法的整体架构,即 AlexNet[9](也叫 ImageNet) ,与 LeNet-5 相似,但具有更 深的结构。它包括 8 个学习层(5 个卷积与池化层和 3 个全连接层) ,前边的几 层划分到 2 个 GPU 上, (和 ImageNet 是同一个)并且它在卷积层使用 ReLU 作 为非线性激活函数,在全连接层使用 Dropout 减少过拟合。该深度网络在 ImageNet 大赛上夺冠,进一步掀起了 CNN 学习热潮。 一般地,CNN 包括两种基本的计算,其一为特征提取,每个神经元的输入 与前一层的局部接受域相连,并提取该局部的特征。一旦该局部特征被提取后, 它与其它特征间的位置关系也随之确定下来;其二是特征映射,网络的每个计算 层由多个特征映射组成, 每个特征映射是一个平面,平面上所有神经元的权值相 等。特征映射结构采用影响函数核小的 sigmoid 函数作为卷积网络的激活函数, 使得特征映射具有位移不变性。此外,由于一个映射面上的神经元共享权值,因 而减少了网络自由参数的个数。这两种操作形成了 CNN 的卷积层。此外,卷积 神经网络中的每一个卷积层都紧跟着一个用来求局部平均与二次提取的计算层, 即池化层,这种特有的两次特征提取结构减小了特征分辨率。 CNN 主要用来识别位移、 缩放及其他形式扭曲不变性的二维图形。 由于 CNN 的特征检测层通过训练数据进行学习,所以在使用 CNN 时,避免了显式地特征 抽取, 而隐式地从训练数据中进行学习;再者由于同一特征映射面上的神经元权 值相同, 所以网络可以并行学习,这也是卷积网络相对于神经元彼此相连网络的 一大优势。 卷积神经网络以其局部权值共享的特殊结构在语音识别和图像处理方 面有着独特的优越性, 其布局更接近于实际的生物神经网络,权值共享降低了网 络的复杂性, 特别是多维输入向量的图像可以直接输入网络这一特点避免了特征 提取和分类过程中数据重建的复杂度。注:红色数字表示相应文献的引用量。二、卷积神经网络 vs 神经网络2.1 神经网络首先简要介绍下神经网络。神经网络的每个单元如下:其对应的公式如下:3 ,
+ )其中,该单元也可以被称作是 Logistic 回归模型。当将多个单元组合起来并 具有分层结构时, 就形成了神经网络模型。下图展示了一个具有一个隐含层的神 经网络。 其对应的公式如下:比较类似的,可以拓展到有2,3,4,5, …个隐含层。 神经网络的训练方法也同 Logistic 类似,不过由于其多层性,还需要利用链 式求导法则对隐含层的节点进行求导,即梯度下降+链式求导法则,专业名称为 反向传播。 神经网络的权值调整过程如下(BP 算法) :①计算误差函数 J =x ∈D Jxω =2?J1D k=1t k ? zk 2 ;? net k ?ω kj②误差函数对权系数偏微分的计算 &1&对输出层权系数的微分:?ω = ? net ×kj k?J(求导链式法则) + ωk0 zk = (net k )输出层第个神经元的总输入:net k =nH j=1 ωkj yj?J ?J ?zk ?net k = × = ?(t k ? zk ) ×
′ (net k ) = yj ?net k ?zk ?net k ?ωkj 令? net = δk ,可得?ω = δk yjk kj?J?J&2&对隐层权系数的微分:?ω = ? net ×ji j?J?J? net j ?ω ji d i=1 ωji xi隐含层第j个神经元的总输入:net j =+ ωj0 yj =
(net j ) ?yj ?J ?J = × =( ?net j ?yj ?net j?J ?Jj ji?yj ?J ?net k )× =( ?net j k=1 ?net k ?yjcc k=1δk ωkj ) ×
′ (net j )令? net = δj ,可得?ω = δj xi &3&权系数的更新 ωkj ← ωkj ? η ?ω ωji ← ωji ?η?ωkj?J?Jji根据计算误差修正权值, 最终使得误差值J最小, 此时就建立好了神经网络模 型。卷积神经网络的权值调整过程也多采用 BP 算法。2.2 卷积神经网络目前有许多 CNN 架构的变体,但它们的基本结构非常相似。CNN 的基本体 系结构通常由三种层构成,分别是卷积层、池化层和全连接层。Input 64×64 C1:feature map 6@(60×60) S1:feature map 6@(30×30) C1:feature map 16@(26×26) S1:feature map 16@(13×13) Output layer ClassiferConvolution 5×5Subsampling 2 ×2Convolution 5×5Subsampling 2×2ConvolutionFull connectionlayer0layer1layer2卷积层旨在学习输入的特征表示。 如图, 卷积层由几个特征图 (feature maps) 组成。 一个特征图的每个神经元与它前一层的临近神经元相连,这样的一个邻近 区域叫做该神经元在前一层的局部感知野。为了计算一个新的特征图,输入特征 图首先与一个学习好的卷积核(也被称为滤波器、特征检测器)做卷积,然后将 结果传递给一个非线性激活函数。通过应用不同的卷积核得到新的特征图。注意 到,生成一个特征图的核是相同的。 (也就是权值共享)这样的一个权值共享模 式有几个优点,如可以减少模型的复杂度,使网络更易训练等。激活函数描述 CNN 的非线性度,对多层网络检测非线性特征十分理想。典型的激活函数有 sigmoid、tanh 和 ReLU。 池化层旨在通过降低特征图的分辨率实现空间不变性。它通常位于两个卷积 层之间。 每个池化层的特征图和它相应的前一卷积层的特征图相连,因此它们的 特征图数量相同。 典型的池化操作是平均池化和最大池化。通过叠加几个卷积和 池化层,我们可以提取更抽象的特征表示。 几个卷积和池化层之后,通常有一个或多个全连接层。它们将前一层所有的 神经元与当前层的每个神经元相连接,在全连接层不保存空间信息。 下面对各层进行详细的分析与介绍: 在图像处理中, 往往把图像表示为像素的向量, 比如一个 1000× 1000 的图像, 可以表示为一个 1000000 的向量。在上一节中提到的神经网络中,如果隐含层数 目与输入层一样,即也是 1000000 时,那么输入层到隐含层的参数数据为 1000000 × 1000000 = 1012 ,这样就太多了,基本没法训练,所以必需先减少 参数加快速度。 2.2.1 卷积层(The convolutional layer) 1、局部感知 卷积神经网络有两种神器可以降低参数数目,第一种神器叫做局部感知野。 一般认为人对外界的认知是从局部到全局的, 而图像的空间联系也是局部的像素 联系较为紧密,而距离较远的像素相关性则较弱。因而,每个神经元其实没有必 要对全局图像进行感知, 只需要对局部进行感知,然后在更高层将局部的信息综 合起来就得到了全局的信息。 网络部分连通的思想,也是受启发于生物学里面的 视觉系统结构。 视觉皮层的神经元就是局部接受信息的(即这些神经元只响应某 些特定区域的刺激) 。如下图所示:左图为全连接,右图为局部连接。在上右图中,假如每个神经元只和它前一层邻近的 10× 10 个像素值相连,那 么权值数据为 1000000× 100 个参数,减少为原来的万分之一。而那 10× 10 个像 素值对应的 10× 10 个参数,其实就相当于卷积操作。 2、权值共享 但其实这样的话参数仍然过多,那么就启动第二级神器,即权值共享。在上 面的局部连接中,每个神经元都对应 100 个参数,一共 1000000 个神经元,如果 这 1000000 个神经元的 100 个参数都是相等的,那么参数数目就变为 100 了。 怎么理解权值共享呢?我们可以这 100 个参数(也就是卷积操作)看成是提 取特征的方式,该方式与位置无关。这其中隐含的原理则是:图像的一部分的统 计特性与其他部分是一样的。 这也意味着我们在这一部分学习的特征也能用在另 一部分上,所以对于这个图像上的所有位置,我们都能使用同样的学习特征。 更直观一些,当从一个大尺寸图像中随机选取一小块,比如说 8× 8 作为样 本,并且从这个小块样本中学习到了一些特征,这时我们可以把从这个 8× 8 样 本中学习到的特征作为探测器,应用到这个图像的任意地方中去。特别是,我们 可以用从 8× 8 样本中所学习到的特征跟原本的大尺寸图像作卷积,从而对这个 大尺寸图像上的任一位置获得一个不同特征的激活值。 如下图所示,展示了一个 3× 3 的卷积核在 5× 5 的图像上做卷积的过程。每个 卷积都是一种特征提取方式, 就像一个筛子, 将图像中符合条件的部分筛选出来。 (图片为 gif 格式) 3、多卷积核 上面所述只有 100 个参数时,表明只有 1 个 10× 10 的卷积核,显然,特征提 取是不充分的,我们可以添加多个卷积核,比如 32 个卷积核,可以学习 32 种特 征。在有多个卷积核时,如下图所示:上图右,不同颜色表明不同的卷积核。每个卷积核都会将图像生成为另一幅 图像。 比如两个卷积核就可以将生成两幅图像,这两幅图像可以看做是一张图像 的不同的通道,如下图所示。 下图展示了在四个通道上的卷积操作,有两个卷积核,生成两个通道。其中 需要注意的是,四个通道上每个通道对应一个卷积核,先将 1 忽略,只看 0 , 那么在 0 的某位置( , )处的值,是由四个通道上(, )处邻近区域的卷积结果相 加然后再取激活函数(假设选择 tanh 函数)值得到的。3 0
) ) + 0 ) 所以, 在上图由 4 个通道卷积得到 2 个通道的过程中, 参数的数目为 4× 2× 2× 2 个,其中 4 表示 4 个通道,第一个 2 表示生成 2 个通道,最后的 2× 2 表示卷积核 大小。 2.2.2 池化层(The pooling layer) 在通过卷积获得了特征 (features) 之后,下一步我们希望利用这些特征去做 分类。理论上讲,人们可以用所有提取得到的特征去训练分类器,例如 softmax 分类器,但这样做面临计算量的挑战。例如:对于一个 96× 96 像素的图像,假 设我们已经学习得到了 400 个定义在 8× 8 输入上的特征(即:有 400 个卷积核), 每一个特征和图像卷积都会得到一个 (96 ? 8 + 1) × (96 ? 8 + 1) = 7921 维的卷 积特征, 由于有 400 个特征, 所以每个样例 (example) 都会得到一个 7921 × 400 = 3,168,400 维的卷积特征向量。 学习一个拥有超过 3 百万特征输入的分类器十 分不便,并且容易出现过拟合 (over-fitting)。 为了解决这个问题,首先回忆一下,我们之所以决定使用卷积后的特征是因 为图像具有一种“静态性”的属性, 这也就意味着在一个图像区域有用的特征极有 可能在另一个区域同样适用。因此,为了描述大的图像,一个很自然的想法就是 对不同位置的特征进行聚合统计,例如,人们可以计算图像一个区域上的某个特 定特征的平均值 (或最大值)。 这些概要统计特征不仅具有低得多的维度 (相比使 用所有提取得到的特征), 同时还会改善结果(不容易过拟合)。这种聚合的操作就 叫做池化 (pooling),有时也称为平均池化或者最大池化 (取决于计算池化的方 法)。 形式上,在获取到我们前面讨论过的卷积特征后,我们要确定池化区域的大 小(假定为 × ),来池化我们的卷积特征。那么,我们把卷积特征划分到数个 大小为 × 的不相交区域上,然后用这些区域的平均(或最大)特征来获取池化 后的卷积特征。这些池化后的特征便可以用来做分类。 2.2.3 全连接层(Fully-connected layers) 几个卷积和池化层之后,通常有一个或多个全连接层,旨在执行对原始图像 的高级抽象。 它们将前一层所有的神经元与当前层的每个神经元相连接,即与标 准神经网络各层之间的连接相同,在全连接层不保存空间信息。最后的全连接层的输出传递到输出层。对于分类任务,softmax 回归由于其 可 以 生 成 输 出 的 well-formed 概 率 分 布 [4] 而 被 普 遍 使 用 。 给 定 训 练 集
∈ 1, … , , ∈ 0, … ,
? 1 , 其中
是第 个输入图像块,
是它的类标签,第 个输入属于第类的预测值
可以用如下的 softmax 函数转换: ?1
=0,softmax 将预测转换为非负值,并进行正则化处理。至此,卷积神经网络的基本结构和原理已经阐述完毕。 在实际应用中,往往使用多层卷积,然后再使用全连接层进行训练,多层卷 积的目的是一层卷积学到的特征往往是局部的,层数越高,学到的特征就越全局 化。 2.2.4 问题 1、预处理步骤 利用 PCA 或 ZCA 白化矩阵调整权值。白化的目的就是降低输入的冗余性; 更正式的说,希望通过白化过程使得学习算法的输入具有如下性质: (1)特征之 间相关性较低;(2)所有特征具有相同的方差。 利用 PCA 或 ZCA 白化矩阵后,卷积层输出的特征激活值等于(
+ ),其中是白化矩阵,是前一层图像块的均值,此时,相当于对图像块做卷积而不是之前的 ,同时神经元单元的偏置也变为 ?
。 补充:PCA 白化和 ZCA 白化算法 首先,我们需要确保数据的均值(近似)为零。对于自然图像,我们通过减 去每个图像块(patch)的均值(近似地)来达到这一目标。为此,我们计算每个图 像块的均值,并从每个图像块中减去它的均值;avg = mean(x, 1); % 分别为每个图像块计算像素强度的均值 x = x - repmat(avg, size(x, 1), 1);其次,计算 = 1 ( ) ( )
=1( )( ) ,假设 为一数据结构,其中每列表示一个训练样本(所以是一个 × 的矩阵) ;sigma = x * x&#39; / size(x, 2);接下来,PCA 计算∑的特征向量。但是由于∑是对称半正定的矩阵,用 svd 函数在数值计算上更加稳定。矩阵 U 将包含 Sigma 的特征向量(一个特征向 量一列,从主向量开始排序) ,矩阵 S 对角线上的元素将包含对应的特征值(同 样降序排列) 。矩阵 V 等于 U 的转置,可以忽略。[U,S,V] = svd(sigma);最后,计算 PCA 白化后的数据
和 ZCA 白化后的数据
:xPCAwhite = diag(1./sqrt(diag(S) + epsilon)) * U&#39; *%diag 函数功能: 矩阵对角元素的提取和创建对角阵 xZCAwhite = U * diag(1./sqrt(diag(S) + epsilon)) * U&#39; *%epsilon MATLAB 本身内建的常数,它是一 10 的-52 次方的小数,可以作为反复运算时比较之用2、如何计算卷积核? 常用的计算卷积核的方法,一种是 BP 算法,上面神经网络中已经讨论过: 3、窄卷积 vs 宽卷积 在上文中解释卷积运算的时候,忽略了如何使用滤波器的一个小细节。在矩 阵的中部使用 3× 3 的滤波器没有问题,在矩阵的边缘该怎么办呢?左上角的元 素没有顶部和左侧相邻的元素,该如何滤波呢?解决的办法是采用补零法 (zero-padding) 。所有落在矩阵范围之外的元素值都默认为 0。这样就可以对输 入矩阵的每一个元素做滤波了, 输出一个同样大小或是更大的矩阵。补零法又被 称为是宽卷积,不使用补零的方法则被称为窄卷积。如图所示:图中滤波器长度为 5,输入长度为 7。当滤波器长度相对输入向量的长度较 大时,宽卷积很有用,或者说很有必要。在上图中,窄卷积输出的长度是 (7 ? 5) + 1 = 3 ,宽卷积输出的长度是 (7 + 2 ? 4 ? 5) + 1 = 11 。一般形式为
+ 1 4、步长 卷积运算的另一个超参数是步长,即每一次滤波器平移的距离。上面所有例 子中的步长都是 1,相邻两个滤波器有重叠。步长越大,则用到的滤波器越少, 输出的值也越少。下图来自斯坦福的 cs231 课程网页 4,分别是步长为 1 和 2 的 情况: 三、卷积神经网络在各个领域的应用在过去的十几年间,卷积神经网络被广泛的应用在了各个领域,包括计算机 视觉、语音识别、自然语言处理等[8]。3.1 计算机视觉在计算机视觉中的应用包括:图像分类、对象追踪、姿态估计、视觉显著性 检测、行为识别、场景标识等。 ①图像分类 CNN 已经被用于图像分类很长时间,相比于其他的方法,CNN 由于其特征 学习和分类学习的结合能力, 在大规模数据集上实现了更高的分类准确率。对大 规模图像分类的突破是在 2012 年, Alex Krizhevsky 等人[9]建立的 AlexNet 网络, 在 ILSVRC2012 比赛中实现了最佳的性能。 (1)AlexNet 网络介绍: ImageNet LSVRC 是一个图片分类的比赛,其训练集包括 127W+张图片,验 证集有 5W 张图片,测试集有 15W 张图片。本文截取 2012 年 Alex Krizhevsky 的 CNN 结构进行说明,该结构在 2012 年取得冠军,top-5 错误率为 15.3%。 下图即为 Alex 的 CNN 结构图。需要注意的是,该模型采用了 2-GPU 并行 结构, 即所有卷积层都是将模型参数分为 2 部分进行训练的。 在这里, 更进一步, 并行结构分为数据并行与模型并行。数据并行是指在不同的 GPU 上,模型结构 相同,但将训练数据进行切分,分别训练得到不同的模型,然后再将模型进行融 合。而模型并行则是,将若干层的模型参数进行切分,不同的 GPU 上使用相同 的数据进行训练,得到的结果直接连接作为下一层的输入。随着 AlexNet 的成功,一些工作对它的性能进行了改进。三个最具代表性的 网络是 ZFNet、 VGGNet 和 GoogleNet。 ZFNet 提高 AlexNet 性能通过减少第一层 滤波器的大小从11 × 11到7 × 7以及减少卷积层数目从 5 到 2。 在这样的设置中, 之间卷积层的大小被扩展以便于获得更有意义的特征。 VGGNet 将网络深度扩展 到 19 层并在每个卷积层使用非常小的滤波器,大小为3 × 3。结果表明深度是提 高性能至关重要的因素。GoogleNet 增加了网络的深度和宽度,相比于较浅和较 窄的网络,在计算需求的适当增加上实现了显著的质量提升。 值得一提的是, 在 2015 年的 ImageNet LSVRC 比赛中, 取得冠军的 GoogleNet 已经达到了 top-5 错误率 6.67%。可见,深度学习的提升空间还很巨大。 (2)DeepID 网络介绍: DeepID 网络结构是香港中文大学的 Sun Yi 开发出来用来学习人脸特征的卷 积神经网络[13]。每张输入的人脸被表示为 160 维的向量,学习到的向量经过其 他模型进行分类,在人脸验证实验上对 10000 类的分类准确率达到了 97.45%, 更进一步的,原作者改进了 CNN(DeepID2[14]) ,又达到了 99.15%的正确率。 如下图所示,该结构与 ImageNet 的具体参数类似:上图模型的基本参数为: 输入:31× 39 大小的图片,1 通道 第一层 卷积: 4× 4 大小的卷积核 20 个-&得到 20 个 28× 36 大小的卷积特征。 max-pooling:2× 2 的核-&池化得到 20 个 14× 18 大小的卷积特征。 第二层 卷积:3× 3 卷积核 40 个-&得到 40 个 12× 16 大小的卷积特征。 max-pooling: 2× 2 的核-&池化得到 40 个 6× 8 大小的卷积特征。 第三层 卷积: 3× 3 的卷积核 60 个-&得到 60 个 4× 6 大小的卷积特征 max-pooling: 2× 2 的核-&池化得到 60 个 2× 3 大小的卷积特征。 第四层 卷积:2× 2 的卷积核 80 个-&得到 80 个 1× 2 大小的卷积特征。 全连接层 以第四层卷积(160 维)和第三层 max-pooling 的输出(60× 2× 3=360 维)作 为全连接层的输入,这样可以学习到局部的和全局的特征。 Softmax 层 输出的每一维都是图片属于该类别的概率。 ②对象追踪 Object tracking 对象追踪在计算机视觉的应用中起着重要作用,对象追踪的成功在很大程度 上依赖于如何健壮的表示目标外观,它面临的挑战如视点改变、光照变化以及遮 挡等。 Fan 等人[10]使用 CNN 作为基础学习器,学习一个独立的分类专用网络来追 踪对象。在实验中,作者设计了一个具有移位变体结构的 CNN 追踪器。在离线 训练期间学习特征, 与传统追踪器不同的是, CNN 追踪器只提取局部空间结构, 通过考虑两个连续帧的图像来提取空间和时间结构。 由于时间信息的大规模信号 趋向于在移动对象附近变化, 因此时间结构能够提供原始的速度信号,便于对象 追踪。③姿态估计/行为识别 类似于其他的视觉识别任务,人体姿态的估计任务由于 CNN 的大规模学习 能力以及更全面训练的可扩展性而实现了巨大的性能提升。 DeepPose[11]是 CNN 在人体姿态估计问题中的第一个应用(2014) 。在这个应 用中,姿态估计被视为一个基于 CNN 的回归问题来求解人体关节坐标。提出串 联 7 层 CNN 来构成姿态的整体表示。不同于之前明确设计图形化模型和部分探 测器的工作,DeepPose 描述人体姿态估计的整体视图,通过将整个图像作为最 终人体姿态的输入和输出,来获得每个人体关节的完整内容。 ④场景标记 场景标记(也被称为场景解析、场景语义分割)建立了对深度场景理解的桥 梁,其目标是将语义类(路、水、海洋等)与每个像素关联。一般来说,由于尺 度、光照以及姿态变化因素影响,自然图像中的“事物”像素(汽车、人等)是 完全不同的,而“物体”像素(路、海洋等)是非常相似的。因此,图像的场景 标记具有挑战性。 最近,CNN 已经被成功地应用在场景标记任务中。在这个场景中,CNN 被 用来直接从局部图像块中建模像素的类估计,它们能够学习强大的特征,来区分 局部视觉像素微妙的变化。Farabet 等人首次将 CNN 应用在场景标记任务中[30], 用不同尺度的图像块来调整多尺度卷积网络,结果表明 CNN 网络性能明显优于 比采用手工提取特征的系统。 3.2 自然语言处理(NLP)1NLP 任务的输入不再是像素点了, 大多数情况下是以矩阵表示的句子或者文 档。矩阵的每一行对应于一个分词元素,一般是一个单词,也可以是一个字符。 也就是说每一行是表示一个单词的向量。通常,这些向量都是 word embeddings (一种底维度表示)的形式,如 word2vec 和 GloVe,但是也可以用 one-hot 向量 的形式,也即根据词在词表中的索引。若是用 100 维的词向量表示一句 10 个单 词的句子,我们将得到一个 10x100 维的矩阵作为输入。这个矩阵相当于是一幅 “图像”。 在计算机视觉的例子里,滤波器每次只对图像的一小块区域运算,但在处理 自然语言时滤波器通常覆盖上下几行(几个词) 。因此,滤波器的宽度也就和输 入矩阵的宽度相等了。尽管高度,或者区域大小可以随意调整,但一般滑动窗口 的覆盖范围是 2~5 行。综上所述,处理自然语言的卷积神经网络结构是这样的。 以句子分类[12]/文本分类 2 为例: 这里对滤波器设置了三种尺寸:2、3 和 4 行,每种尺寸各有两种滤波器。每 个滤波器对句子矩阵做卷积运算,得到(不同程度的)特征字典。然后对每个特 征字典做最大值池化,也就是只记录每个特征字典的最大值。这样,就由六个字 典生成了一串单变量特征向量(univariate feature vector) ,然后这六个特征拼接 形成一个特征向量,传给网络的倒数第二层。最后的 softmax 层以这个特征向量 作为输入,用其来对句子做分类;我们假设这里是二分类问题,因此得到两个可 能的输出状态。 位置不变性和局部组合性对图像来说很直观,但对 NLP 却并非如此。人们 也许会很在意一个词在句子中出现的位置。相邻的像素点很有可能是相关联的 (都是物体的同一部分) ,但单词并不总是如此。在很多种语言里,短语之间会 被许多其它词所隔离。同样,组合性也不见得明显。单词显然是以某些方式组合 的,比如形容词修饰名词,但若是想理解更高级特征真正要表达的含义是什么, 并不像计算机视觉那么明显了。 由此看来,卷积神经网络似乎并不适合用来处理 NLP 任务。递归神经网络 (Recurrent Neural Network) 更直观一些。 它们模仿我们人类处理语言的方式 (至 少是我们自己所认为的方式) :从左到右的顺序阅读。庆幸的是,这并不意味着 CNNs 没有效果。所有的模型都是错的,只是一些能被利用。实际上 CNNs 对 NLP 问题的效果非常理想。正如词袋模型(Bag of Words model) ,它明显是基于 错误假设的过于简化模型,但这不影响它多年来一直被作为 NLP 的标准方法, 并且取得了不错的效果。 CNNs 的主要特点在于速度快,非常的快。卷积运算是计算机图像的核心部 分,在 GPU 级别的硬件层实现。相比于 n-grams,CNNs 表征方式的效率也更胜 一筹。由于词典庞大,任何超过 3-grams 的计算开销就会非常的大。即使 Google 也最多不超过 5-grams。卷积滤波器能自动学习好的表示方式,不需要用整个词 表来表征。那么用尺寸大于 5 行的滤波器完全合情合理了。许多在 CNN 卷积第 一层学到的滤波器捕捉到的特征与 n-grams 非常相似(但不局限) ,但是以更紧 凑的方式表征。3.3 语音识别[6]利用 CNN 进行语音处理的一个关键问题是如何将语音特征向量映射成适合 CNN 处理的特征图。我们可以直观的将输入“图像”考虑成一个具有静态、delta 以及 delta-delta 特征 (即第一和第二时间派生物 derivatives) 的频谱图, 如下图 a, 选择 15 帧长度的内容窗口。当然还有多种选择可以精确地将语音特征转化为特 征图,如图 b 所示,语音特征可以被表示成 3 个二维的特征图,每个代表 MFSC (mel-frequency spectral coefficients)特征的信息(即静态、delta 以及 delta-delta 特征)沿着频率和时间轴的分布。在这种情况下,一个二维卷积被执行来同时正 规化频率和时间变化,得到3个二维特征图,每个特征图有15 × 40 = 600维。另 外,可以只考虑正规化频率变化。如图 c 所示,在这种情况下,相同的 MFSC 特征被组 织作 为一维 特征图 , 每一 帧的 3 种特征 作为 一个特 征图,得到 15 × 3 = 45个特征图,每个特征图有 40 维。 [6]中采用的是如图 c 所示的一维特征图进行卷积操作。四、对卷积神经网络的改进自从 2012 年 AlexNet 的成功之后,出现了各种对 CNN 的改进,从对下面四 个方面(卷积层、池化层、正则化以及激活函数)的改进来看:4.1 卷积层CNN 的基本卷积滤波器是底层局部图像块( patch)的一个广义的线性模型 (GLM) 。对隐含概念的线性可分实例的提取效果较好。目前有两种可以提高滤 波器特征表示能力的对卷积层的改进工作。 ①Network in network(NIN) :是由 Lin 等人[15]提出的一种网络结构。它用一 个微网络(micro-network,如多层感知机卷积 mlpconv,使得滤波器能够更加接 近隐含概念的抽象表示) 代替了卷积层的线性滤波器。 NIN 的整体结构就是这些 为网络的堆积。 卷积层和 mlpconv 层的区别: (从特征图的计算上来看) 形式上,卷积层的特征图计算公式是: , , = max? (
, , 0) 其中, , 是特征图的像素索引, , 是以(, )为中心的输入块, 是特征图的 通道索引。 而 mlpconv 层的特征图计算公式是: ?1
1 , 0) , , 1 = max? 1
,(每一层特征图之间有连接,类似于循环神经网络结构 RNN) 其中,是 mlpconv 层的层数。 可以发现,mlpconv 层的特征图计算公式相当于在正常卷积层进行级联交叉 通道参数池化。 ②Inception module:是由 Szegedy 等人[16]提出,可以被看做 NIN 的逻辑顶点 (logical culmination) ,使用多种滤波器的大小来捕捉不同大小的不同可视化模 式,通过 inception module 接近最理想的稀疏结构。特别地,inception module 由 一个池化操作和三种卷积操作组成。1 × 1的卷积被放在3 × 3和5 × 5的卷积之前 作为维度下降模块,在不增加计算复杂度的情况下增加 CNN 的深度和宽度。在 inception module 作用下,网络参数可以被减少到 5 百万,远小于 AlexNet 的 6 千万和 ZFNet 的 7 千 5 百万。4.2 池化层池化是 CNN 的一个重要概念, 它通过减少卷积层的连接数量降低计算负担。 目前为止在 CNN 中使用的典型的池化操作是平均池化或者最大池化,同时也存 在着一些改进的池化操作,如 池化、混合池化、随机池化等。 ① 池化:是一个受生物学启发在复杂细胞上建立的池化过程。Bruna 的理 论分析表明 池化相比于最大池化能提供更好的泛化[17]。
池化公式为: (
=1 | | ) ,其中11 , … ,
是一组有限的输入节点,当 = 1 时,
池化就相当于平均池化,当
= 2时,是2 池化,当 = ∞时,即 max? (|1 |, … , | |)相当于最大池化。 ②混合池化:受随机 Dropout[18]和 DropConnect[19]启发,Yu 等人[20]提出混合 池化方法,即最大池化和平均池化的结合。 混合池化方法公式化为:
max( , )∈
+ (1 ? ) |1 |( , )∈ ,其中 是第个特征图相应位置(, )处池化操作的输出, 是 0~1 之间的随机值,
是位置(, )的局部邻域, 是第个特征图池化区域 内在(,
)处的元素。 在前向传播过程中,被记录,并在反向传播中被调整。 [21] ③随机池化 (Stochastic pooling) : 保证特征图的非线性激活值可以被利用。 具体地,随机池化先对每个区域
通过正则化区域内的激活值计算概率
)。然后从基于的多项分布中采样来选择区域内的一个位置 。池化的激活值 =
,其中 ~ (1 , … , | | )。随机池化被证明具有最大池化的优点, 并且可以避免过拟合。 此外,还有频谱池化(Spectral pooling) 、立体金字塔状池化(Spatial pyramid pooling(SPP))以及多尺度无序池化(Multi-scale Orderless Pooling)等。4.3 正则化 Regularization过拟合是深度 CNN 一个不可忽视的问题,这一问题可以通过正则化有效地 减少。这里介绍两种有效的正则化技术:Dropout 和 DropConnect。 ①Dropout: 也就是在每次训练的时候, 让网络某些隐含层神经元以一定的概 率不工作。它最先由 Hinton 等人(在深度学习的推广中起了关键作用)在 2012 年提出[18],它已经被证明对减少过拟合十分有效。在[18]中,他们将 Dropout 应 用在全连接层,Dropout 的输出是 =
? (),其中 = 1 , 2 , … ,
是特 征提取器的输出,(大小是 × )是一个全链接的权重矩阵,(?)是一个非线 性激活函数,是一个大小为 的 binary mask,元素服从伯努利分布(也叫二项 分布) ,即 ~()。Dropout 可以防止网络过于依赖任何一个神经元, 使网络即使在某些信息缺失的情况下也能是准确的。 目前存在着几种对 Dropout 的改进,例如:Wang 等人[22]中提出了一种快速 Dropout 方法,通过抽样或整合一个高斯近似值来实现更快的 Dropout 训练。Ba 等人[23]提出一种自适应 Dropout 方法, 使用一个与深度网络共享参数的二进制置 信网络计算每个隐含变量的 Dropout 概率。在 Tompson 等人[24]中发现在1 × 1卷 积层之前应用标准 Dropout 会增加训练时间但不能防止过拟合, 因此他们提出了 一种新的 Dropout 方法叫做 SpatialDropout, 在整个特征图上扩展了 Dropout 的值。 这种新的 Dropout 在训练数据量很小时性能很好。 ② DropConnect[19]:将 Dropout 的想法更进一步,代替了其设置神经元的输 出为 0, 而是在前向传导时, 输入的时候随机让一些输入神经元以一定的概率不 工作, 在 BP 训练时, 这些不工作的神经元显然也不会得到误差贡献。 DropConnect 的输出 = (( ?
)),其中 ~()。此外,在训练过程中也掩盖 了误差。和 Dropout 的区别就在于,Dropout 一个输出不工作了,那么这个输出 作为下一级输入时对于下一级就一点都不工作,但是 DropConnect 不会,泛化能 力更强一点。 下图给出了 No-Drop、Dropout 和 DropConnect 网络的区别: 4.4 对激活函数的改进在某个任务中,一个合适的激活函数能显著改善 CNN 的性能。为了用连续 型的函数表达神经元的非线性变换能力, 常采用 S 型的 sigmoid 和 tanh 函数作为 激活函数。其中 sigmoid 函数,即 x = 1+ ? ,是神经元的非线性作用函数。由 于 BP 权值的调整采用梯度下降(Gradient Descent)公式?W = ?η
,这个公 式要求对网络输出值和训练差值
求导,所以要求网络输出值处处可导,而 Sigmoid 函数正好满足处处可导,因此神经元的激活函数常用 sigmoid 型。tanh 函数 x =
+ ? ,与 sigmoid 函数趋势类似,如下图所示。
1除了上述 S 型的函数外,ReLU(Rectified linear unit (ReLU))[25]也是常用的 激活函数的一种。ReLU 激活函数被定义为: = max? (0,
),其中 是第 个通 道的输入,因此 ReLU 是一个分段线性函数,如下图 a 所示。ReLU 简单的 max 操作使得它的计算速度比 sigmoid 和 tanh 函数快, 并且允许网络很容易地获得稀 疏表示。[16]中的实验表明了使用 ReLU 作为激活函数的深度网络可以被有效地 训练。尽管 ReLU 在 0 点处的不连续损害了 BP 算法的性能,并且它具有不活跃 的零梯度单元, 可能会导致基于梯度的优化不能够调整权值。但大量实证研究表 明 ReLU 仍然比 sigmoid 和 tanh 激活函数效果更好。 针对这一缺点,之后出现了很多对 ReLU 激活函数的改进工作: ① Leaky ReLU ( LReLU ) [26] 或 Parametric ReLU ( PReLU ) [27] :
(如图 b 所示) ,其中是(0,1)之间的一个预定义的参数。
& 0 与 ReLU 相比,LReLU 压缩了负轴部分而不是将它始终映射为 0,使得函数在不 活跃单元也具有了较小的非零梯度,从而便于权值调整。 ② Randomized ReLU(RReLU)[28]:在 RReLU 中,负轴部分的参数是从均 匀分布的训练样本中随机抽取的,随后在测试样本中确定。函数被定义为:
( ) ≥ 0 (如图 c 所示) ,其中 ( ) 表示第个样本第 个通道的
( ) & 0输入, ( ) 表示对应的样本参数, ( ) 表示对应的输出。由于该函数的随机性质 使得它可以减少过拟合。[28]同时针对标准图像分类任务对 ReLU、LReLU 以及 RReLU 函数进行评估,得出结论:在调整激活单元的负轴部分加入非零梯度可 以提高分类性能。 ③ Exponential Linear Unit (ELU)[29]: 指数线性单元可以更快地学习深度神经 网络,提高分类准确率。ELU 利用了饱和函数作为负轴部分,对噪声具有鲁棒
≥ 0 性。函数被定义为: = (如图 d 所示) ,其中是预定 (exp? ( ) ? 1)
& 0 义的参数用来控制负输入的值。五、卷积神经网络在音乐推荐中的应用 3自动音乐推荐系统由于其允许听众根据自己的偏好发现新音乐并使在线音 乐商店能够根据自己的用户订购音乐商品而得到长足发展。 许多推荐系统依赖于 惯用模式, 即从用户的消费和评价中获取的用户偏好, 并分析这些信息的相关性。 这就是协同过滤方法(collaborative filtering approach) 。例如,如果两个用户基本 上听相同的歌,那么他们的偏好是相似的,相反,如果有两首歌被同一用户组的 人听, 那么它们听起来是相似的。另一种方法是从内容和元数据中预测用户的偏 好。 只有在惯用数据可用的情况下,协同过滤方法是优于基于内容的推荐方法的。 当惯用数据不可用时, 协同过滤方法面临着冷启动问题,即不能有效的推荐新的 和不流行的歌曲。 协同过滤方法被分为基于近邻的和基于模型的方法,其中基于 模型的方法试图建模用户与其音乐列表的隐含特性,通常表示成隐含因子向量。 这种方法在 Netflix Prize 中被证明是非常有效的。所以基于协同过滤方法的缺陷 以及结合隐含因子模型,文章利用卷积神经网络建立基于内容的音乐推荐方法 [31]&3 。 目前存在许多不同种类的与音乐相关的信息可以用来实现音乐推荐:标签、 作曲家和唱片信息、歌词、网站上的文本信息(如评价、访谈等)以及音频信号 本身。 在这些信息资源中, 音频信号是最难以被有效使用的, 这是因为, 一方面, 音频间存在相当大的语义鸿沟(semantic gap) ,另一方面,音乐存在着影响听众 偏好的多种方面。有一些很容易从音频信号中获取,如音乐的流派和乐器信息, 有一些较难获取, 如音乐的情感, 还有一些完全无法获取, 如作曲家的地理位置、 抒情主题等。 尽管面临着这些问题,但通过分析音频信号来进行音乐推荐仍然是 一种理想的方式。 所以文章试图训练一个卷积神经网络模型来预测音乐音频信号 的隐含因子。 文章所采用方法的基本思想是利用加权矩阵因式分解( WMF)算法从训练 集可用的惯用数据中提取隐含因子向量,作为 ground truth 数据,然后通过训练 一个回归模型来预测歌曲的隐含因子,如下图 a,最后使用 t-SNE 算法将其映射 到二维的协同过滤空间(即用户和歌曲空间) ,如下图 b,相似的歌曲被聚集在 一起,说唱音乐在左上角,电子音乐在右下角。a) b) 本文训练的卷积神经网络包括 4 个卷积层和 3 个全连接层,如下图 c 所示, 垂直方向是时间轴。c) 使用 3s 的音频片段的 mel-频谱图作为网络的输入(具有 599 帧和 128 个频 点) ,它是通过计算音频信号每个短时重叠窗口的傅里叶变换得到的,每个傅里 叶变换组成一帧,这些连续的帧连接为一个矩阵,形成频谱图。最后,频率坐标 从一个线性尺度变为 mel 尺度来降低维数,频率大小按对数比例缩小。 卷积层的滤波器如图中红色矩形框所示,采用 ReLU 激活函数,注意到,不 同于图像的情况, 频谱图两个坐标轴的意义是不同的,所以这些卷积只在时间维 度上移动。 在卷积层之间,最大池化操作,图中简化为“MP” ,被用来在时间轴上做降 采样, 降低中间表示分辨率的同时保证时间不变性(也是为了让之后层次的神经 元视野更广,得到原始输入的高级抽象表示) 。 在最后一层卷积之后,添加了一层全局时间池化层,包括均值、最大值和欧 几里得距离(L2-norm)三种池化函数,这一层在整个时间轴上有效地统计之前 学习到的特征。 这么做的原因是,从音频信号中检测出的特征的绝对位置与当前 的实验目的不太相关。这与图像不同,对于图像来说,如果我们检测出这个特征 在最上方,那么它可能代表的是一片云,如果在最下方,那么它可能是一只羊。 而对于音乐推荐, 我们通常指对音乐中某些特征的存在与否感兴趣,所以这里需 要在整个时间轴上做池化。 全局池化后的特征被送入两层 2048 维、激活函数为 ReLU 的全连接层中。 最后一层是输出层,它预测从 vector_exp 算法(协同过滤算法中的一种)中 获得的 40 个隐含因子。 通过训练这个神经网络来最小化从协同过滤算法中获得的隐含因子和从音 频中预测的隐含因子之间的均方差(MSE) 。参考文献[1] Hubel D H, Wiesel T N. Receptive fields, binocular interaction and functional architecture in the cat&#39;s visual cortex[J]. Journal of Physiology, ):106C154. [2] Fukushima K. Neocognitron: A self-organizing neural network model for a mechanism of pattern recognition unaffected by shift in position[J]. Biological Cybernetics, ):193-202. [3] Rumelhart D E, Hinton G E, Williams R J. Learning Internal Representations by Error Propagation[C]// MIT Press, . [4] Lé cun Y, Bottou L, Bengio Y, et al. Gradient-based learning applied to document recognition[J]. Proceedings of the IEEE, ):. [5] Lecun Y, Boser B, Denker J S, et al. Backpropagation Applied to Handwritten Zip Code Recognition[J]. Neural Computation, ):541-551. [6] Abdel-Hamid O, Mohamed A R, Jiang H, et al. Convolutional Neural Networks for Speech Recognition[J]. IEEE/ACM Transactions on Audio Speech & Language Processing, ):. [7] ScienceOpen. Visualizing and Comparing Convolutional Neural Networks[J]. 2014. [8] Gu J, Wang Z, Kuen J, et al. Recent Advances in Convolutional Neural Networks[J]. Computer Science, 2015. [9] Krizhevsky A, Sutskever I, Hinton G E. ImageNet Classification with Deep Convolutional Neural Networks[J]. Advances in Neural Information Processing Systems, ):2012. [10] Fan J, Xu W, Wu Y, et al. Human Tracking Using Convolutional Neural Networks[J]. IEEE Transactions on Neural Networks, ):. [11] Toshev A, Szegedy C. DeepPose: Human Pose Estimation via Deep Neural Networks[C]// Computer Vision & Pattern Recognition. IEEE, 60. [12] Zhang Y, Wallace B. A Sensitivity Analysis of (and Practitioners&#39; Guide to) Convolutional Neural Networks for Sentence Classification[J]. Computer Science, 2015. [13] Sun Y, Wang X, Tang X. Deep Learning Face Representation from Predicting 10,000 Classes[C]// Computer Vision and Pattern Recognition. IEEE, 98. [14] Sun Y, Wang X, Tang X. Deep Learning Face Representation by Joint Identification-Verification[J]. Advances in Neural Information Processing Systems, 8-1996. [15] Lin M, Chen Q, Yan S. Network In Network[J]. Computer Science, 2013. [16] Szegedy C, Liu W, Jia Y, et al. Going deeper with convolutions[C]// IEEE Conference on Computer Vision and Pattern Recognition. IEEE, . [17] Bruna J, Szlam A, Lecun Y. Signal Recovery from Pooling Representations[J]. Statistics, . [18] Hinton G E, Srivastava N, Krizhevsky A, et al. Improving neural networks by preventing co-adaptation of feature detectors[J]. Computer Science, ):pá gs. 212-223. [19] Wan L, Zeiler M, Zhang S, et al. Regularization of neural networks using dropconnect[C]// International Conference on Machine Learning. 66. [20] Yu D, Wang H, Chen P, et al. Mixed Pooling for Convolutional Neural Networks[M]// Rough Sets and Knowledge Technology. . [21] Zeiler M D, Fergus R. Stochastic Pooling for Regularization of Deep Convolutional Neural Networks[J]. Computer Science, 2013. [22] Wang S I, Manning C D. Fast dropout training[C]// International Conference on Machine Learning. . [23] Ba L J, Frey B. Adaptive dropout for training deep neural networks[J]. Advances in Neural Information Processing Systems, 92. [24] Tompson J, Goroshin R, Jain A, et al. Efficient object localization using Convolutional Networks[C]// Computer Vision and Pattern Recognition. IEEE, . [25] Nair V, Hinton G E. Rectified Linear Units Improve Restricted Boltzmann Machines Vinod Nair[C]// International Conference on Machine Learning. . [26] A. L. Maas, A. Y. Hannun, and A. Y. Ng. Rectifier nonlinearitiesimprove neural network acoustic models[C]// in ICML, 2013. [27] He K, Zhang X, Ren S, et al. Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification[C]// IEEE International Conference on Computer Vision. IEEE, 34. [28] Xu B, Wang N, Chen T, et al. Empirical Evaluation of Rectified Activations in Convolutional Network[J]. Computer Science, 2015. [29] Clevert, Djork-Arné , Unterthiner T, Hochreiter S. Fast and Accurate Deep Network Learning by Exponential Linear Units (ELUs)[J]. Computer Science, 2015. [30] Farabet C, Couprie C, Najman L, et al. Learning Hierarchical Features for Scene Labeling[J]. IEEE Transactions on Pattern Analysis & Machine Intelligence, ):. [31] Oord A V D, Dieleman S, Schrauwen B. Deep content-based music recommendation[J]. Advances in Neural Information Processing Systems, 3-2651.参考网页1/2015/11/understanding-convolutional-neural-networks-for-nlp/ 卷 积 神 经网络在自然语言处理的应用 2/2015/12/implementing-a-cnn-for-text-classification-in-tensorflow/ 利 用 卷积神经网络实现文本分类。 。 3http://benanne.github.io//spotify-cnns.html(Recommending music on Spotify with deep learning)利用 CNN 实现在 Spotify 上的音乐推荐 4 http://cs231n.github.io/convolutional-networks/卷积神经网络介绍
卷积神经网络 CNN 代码解析 deepLearnToolbox-master 是一个深度学习 matlab 包,里面含有很多机器学习算法,如卷积神经网络 CNN,深 度信念网络 DBN,自动编码 ...卷积神经网络CNN相关代码注释_计算机软件及应用_IT/计算机_专业资料。卷积神经网络CNN相关代码注释 cnnexamples.m [plain] view plaincopy 1. 2. 3. 4. 5. 6....神经网络到卷积神经网络 推导与实践 摘要 卷积神经网络(Convolutional Neural Network, CNN)是一种源于人工神经网 络(Neural Network, NN)的深度机器学习方法,近年来...卷积神经网络CNN_计算机软件及应用_IT/计算机_专业资料。1、动机 卷积神经网络(CNN)是多层感知机(MLP)的一个变种模型,它是从生物学概念中演 化而来的。从 Hubel...卷积神经网络全面解析(2)_计算机软件及应用_IT/计算机_专业资料。卷积神经网络全面解析(2) 一、介绍 这个文档讨论的是 CNNs 的推导和实现。CNN 架构的连接比权值...一文读懂卷积神经网络 CNN 第一点, 在学习 Deep learning 和 CNN 之前, 总以为它们是很了不得的知识, 总以为它们能解决很多问题, 学习了之后,才知道它们不过...卷积神经网络全面解析之代码详解本文介绍多层感知机算法,特别是详细解读其代码实现,基于 python theano,代码来自:Convolutional Neural Networks (LeNet)。 一、CNN ...卷积神经网络摘要:卷积神经网络是近年来广泛应用于模式识别、图像处理等领域的一种高效识别算法,它具有结构简 单、训练参数少和适应性强等特点。本文从卷积神经网络...卷积神经网络(CNN)代码实现(MNIST) 解析共 7 层:依次为输入层、C1 层、S2 层、C3 层、S4 层、C5 层、输出层,C 代表卷积层(特 征提取),S 代表降采样层...卷积神经网络全面解析之算法实现 前言从理解卷积神经到实现它,前后花了一个月时间,现在也还有一些地方没有理解透彻, CNN 还是有一定难度的,不是看哪个的博客和一...
All rights reserved Powered by
copyright &copyright 。文档资料库内容来自网络,如有侵犯请联系客服。

我要回帖

更多关于 cnn 卷积神经网络 的文章

 

随机推荐