课程链接:智能计算系统第四章
导读:
编程框架在整个智能计算系统中起着承上启下的作用,在某种意义上像信息产业里的操作系统,是智能计算系统中非常关键的核心枢纽。
本章首先介绍深度学习编程框架的概念及作用,随后介绍目前应用最广的编程框架 TensorFlow 的基本概念及编程模型,最后通过程序示例来介绍如何基于 TensorFlow 实现 深度学习的预测和训练。
主要是在实现部分:学习到实现深度学习算法所需要的编程框架的简单用法
主流深度学习编程框架 | 支持语言 |
---|---|
TensorFlow | Python/C/C++/Java/Go |
caffe2 | Python/C++ |
Pytorch | Python |
Keras | Python |
cognitive Toolkit | Python/C++/C# |
MXNet | Python/C++/R/Scala/Julia |
TensorFlow受Google推动,是目前使用人数最多,影响最大的编程框架。应用:AlphaGo
TensorFlow及其变种可以工作于各种类型的异构系统,包括手机,平板电脑等移动设备,数百台机器和数千种计算设备(如GPU)的大规模分布式系统。
第1代分布式深度学习平台—DistBelief
第2代大规模机器学习系统—TensorFlow
版本历史
时间 | 版本号 | 更新内容 |
---|---|---|
2015.11 | 0.5 | 第1个发布版本 |
2016.04 | 0.8 | 支持分布式计算,支持大规模智能应用的部署使用。 |
2016.06 | 0.9 | 增加了对多平台的支持,包括IOS,Raspberry Pi等 |
2016.09 | 0.10 | 提供深度学习高级抽象库TensorFlow-Slim,方便快速定义和训练模型,有效扩大了用户群体。 |
2017.02 | 1.0 | 第1个正式版。增加了多个提升性能及易用性的更新,包括线性代数编译器XLA,调试工具TensorFlow Debugger,对安卓的支持等。 |
2017.07 | 1.2 | 增加了面向infiniBand等高性能网络的RDMA通信方案,解决了分布式训练时通信开销过大的问题。 |
2018.03 | 1.7 | 推出TensorBoard可视化工具,有效辅助用户理解算法模型及工作流程。 |
2020.01 | 2.1 | 目前的最新版本,支持静态/动态图 |
import tensorflow as tf
构建计算图
X=tf.constant([[3.,3.]])
W=tf.constant([[2.],[2.]])
y=tf.matnul(X,W)
执行计算图,创建会话,执行运算。
with tf.Session() as sess:
result=sess.run(y)
print(result)
属性名 | 功能说明 |
---|---|
tf.operation.name | 操作的名称 |
tf.operation.type | 操作的类型, 如add |
tf.operation.inputs | 操作的输入 |
tf.operation.outputs | 操作的输出 |
tf.operation.control_inputs | 该操作的控制依赖列表 |
tf.operation.device | 执行该操作所使用的设备 |
tf.operation.graph | 操作所属的计算图 |
tf.operation.traceback | 实例化该操作时的调用栈 |
操作类型 | 常用算子 |
---|---|
标量运算 | add,subtract,multiply,div,greater,less,equal,abs,sign,square,pow,log,sin,cos |
矩阵运算 | matmul,matrix_inverse,matrix_determinant,matrix_transpose |
逻辑操作 | logical_and,is_finite |
神经网络运算 | convolution,max_pool,bias_add,softmax,dropout,sigmoid,relu |
储存,恢复 | save,restore |
初始化操作 | zeros_initializer,random_normal_initializer,orthogonal_initializer |
随机运算 | random_gamma,multinomial,random_normal,random_shuffle |
tensor的常见属性名 | 含义 |
---|---|
dtype | tensor存储的数据类型 |
shape | tensor各阶的长度 |
name | tensor在计算图中的名称 |
op | 计算出此tensor的操作 |
device | 计算出此tensor所用的设备名 |
graph | 包含此tensor的计算图 |
阶数 | 对应的数据形式 |
---|---|
0 | 标量 |
1 | 向量 |
2 | 矩阵 |
n | n维数组 |
TensorFlow数据类型 | 说明 |
---|---|
int8/int16/int32/int64 | 8/16/32/64位有符号整数 |
float16/float32/float64 | 半精度/单精度/双精度浮点数 |
bfloat16 | 裁短浮点数 |
uint8/uint16/uint32/uint64 | 8/16/32/64位无符号整数 |
bool | 布尔值 |
string | 字符串 |
complex64/complex128 | 单精度/双精度复数 |
qint8/qint16/qint32 | 量化的8位/16位/32位有符号整数 |
quint8/quint16 | 量化的8位/16位无符号整数 |
例如:X=tf.constant([2,3],dtype=tf.float32)
深度学习不需要全部float32,容忍非精确计算(不同类别的大间距现象)
函数名称 | 功能 |
---|---|
tf.shape(tensor) | 返回tensor的shape值 |
tf.to_double(x,name=“ToDouble”) | 将x转为64位浮点类型:其他类型写法类似 |
tf.cast(x,dtype) | 将x转化为dtype类型数据 |
tf.reshape(tensor,shape) | 修改tensor各阶的长度为shape |
tf.slice(input,begin,size) | 从由begin指定位置开始的input中提取一个尺寸为size的切片 |
tf.split(value,num_or_size_splits,axis) | 沿着第axis阶对value进行切割,切割成num_or_size_splits份 |
tf.concat(values,axis) | 沿着第axis阶对value进行连接操作 |
print(tensor):只会出现"名称,格式大小,数据类型“
如果需要查看张量tensor的,只需要允许会话session。
输入参数 | 功能说明 |
---|---|
target | 会话连接的执行引擎,认为进程内引擎。 |
graph | 执行计算时加载的计算图。默认值为当前代码中唯一的计算图。当代码中定义多幅计算图时,使用graph指定待加载的计算图。 |
config | 指定相关配置项,如设备数量,并行线程数,GPU配置参数等。 |
sess=tf.Session(target='',graph=None,config=None)
输入参数 | 功能说明 |
---|---|
fetches | 本会话需计算的张量或操作。 |
feed_dict | 指定会话执行时需填充的张量或操作,及对应的填充数据。 |
options | 设置会话运行时的控制选项。 |
run_metadata | 设置会话运行时的非张量信息输出。 |
print(sess.run(x3,feed_dict={x1:[[1,2,3],[4,5,6]],x2:[[1,2],[3,4],[5,6]]}))
with ef.Session() as sess:
result=sess.run(y)
print(result)
import tensorflow as tf
a=tf.placeholder(tf.int32)
b=tf.placeholder(tf.int32)
c=tf.multiply(a,b)
with tf.Session() as sess:
print(sess.run(c,feed_dict={a:100,b:200}))
输入参数 | 功能说明 |
---|---|
feed_dict | 指定需填充的张量或操作,及对应的填充数据。 |
session | 指定求解此tensor或操作的会话 |
import tensorflow as tf
a=tf.constant([[1.0,2.0]])
b=tf.constant([[3.0],[4.0]])
c=tf.constant([[5.0],[6.0]])
y1=tf.matmul(a,b)
y2=tf.matmul(a,c)
with tf.Session() as sess:
y1.eval()
y2.eval()
sess.run([y1,y2])
常用属性 | 含义 |
---|---|
dtype | 变量的数据类型 |
shape | 变量的长度 |
name | 变量在计算图中的名称 |
op | 变量操作 |
device | 存储此变量所用的设备名 |
graph | 包含此变量的计算图 |
initialized_value | 变量的初值 |
initializer | 为变量赋值的初始化操作 |
trainable | 是否在训练时被优化器更新 |
将一个tensor传递给Variable()构造函数,创建时需要指定变量的形状和数据类型。
(1).使用tf.Variable()函数直接定义
(2).使用TensorFlow内置的函数来定义变量初值,可以是常量或随机值
#以标准差0.35的正态分布,初始化一个状态为[20,40]的变量。
r=tf.Variable(tf.random_normal([20,40],stddev=0.35))
#初始化一个形状为[2,3]的变量,里面的元素值全部为0。
z=tf.Variable(tf.zeros([2,3]))
(3).用其他变量的初始值来定义新变量
#创建一个随机变量
weights=tf.Variable(tf.random_normal([784,200],stddev=0.35),name="weights")
#创建一个与weights的值相同的变量
w2=tf.Variable(weights.initialized_value(),name="w2")
#创建一个值为weights2倍的变量
w_twice=tf.Variable(weights.initialized_value()*2,name="w_twice")
创建变量后还需要进行变量初始化。最简单的变量初始化方法:使用tf.global_variables_initializer()对所有变量初始化
sess.run(tf.global_variables_initializer())
更新函数 | 功能说明 |
---|---|
tf.assign() | 【强制】更新变量的值 |
tf.assign_add() | 【强制】加法赋值 |
tf.assign_sub() | 【强制】减法赋值 |
tf.train.**Optimizer | 使用多种优化方法【自动】更新参数 |
tf.placeholder()的输入参数 | 功能说明 |
---|---|
name | 在计算图中的名字 |
dtype | 填充数据的数据类型 |
shape | 填充数据的shape值 |
使用时需和feed_dict参数配合,用feed_dict提交数据,进行参数传递
#因为需要重复输入x,而每建一个x就会产生一个节点,计算图的效率会低,所以使用占位符。
x=tf.placeholder(tf.float32,shape=(1,2))
#运行y时占位符填上,feed_dict为字典,变量名不可变。
y_1=sess.run(a,feed_dict={x:[[0.7,0.9]]})
import tensorflow as tf
#创建一个先进先出队列,指定队列中可以保存三个元素,并指定类型为浮点型
q=tf.FIFOQueue(3,'float')
#使用enqueue_many函数来初始化队列中的元素
init=q.enqueue_many(([0.,0.,0.],))
#使用Dequeue函数将队列中第1个元素出队列,这个元素值将被存在变量x中
x=q.dequeue()
y=x+1
#将+1后的值再重新加入队列中
q_inc=q.enqueue([y])
init.run()
q_inc.run()
用VGG_19-图像风格迁移训练实现举例【5层conv-pool】
import cv2
import numpy as np
def train_vgg():
sess=tf.Session()
#构建模型,使用与模型推理时相同的网络结构
models=build_vggnet(vgg19_npy_path)
#获取输入的内容图像,风格图像
img_content=load_image('./content,jpg')
img_style=load_image('./style.jpg')
#生成噪音图像
img_random=get_random_img(img_content)
sess.run(tf.global_variables_initializer())
#定义损失函数
total_loss=loss(sess,models,img_content,img_style)
#创建优化器
optimizer=tf.train.AdamOptimizer(2.0)
#定义模型训练方法
train_op=optimizer.minimize(total_loss)
sess.run(tf.global_variables_initializer())
#使用噪声图像进行训练
sess.run(models['input'].assign(img_random))
#训练迭代3000次
for i in range(3000):
#完成一次反向传播
sess.run(train_op)
if i%100==0:
#每完成100次训练, 打印中间结果,从而监测训练效果
img_transfer=sess.run(models['input'])
print('Iteration %d' % (i))
print('cost:',sess.run(total_loss))
#训练结束,保存训练结果,显示图像
...
if __name__ == '__main__':
train_vgg()
with tf.Session():
input=tf.placeholder(tf.float32)
classifier=...
print(classifier.eval(feed_dict={input:one_numpy_ndarray}))
利用常量进行数据预取
training_data=... #some data like numpy array
training_labels=...
with tf.Session():
input_data=tf.constant(training_data)
input_labels=tf.constant(training_labels)
利用变量进行数据预取
training_data=... #some data like numpy array
training_labels=...
with tf.Session() as sess:
data_initializer=tf.placeholder(dtype=training_data.dtype,shape=training_data.shape)
label_initializer=tf.placeholder(dtype=training_labels.dtype,shape=training_labels.shape)
input_data=tf.Variable(data_initializer,trainable=False,collections=[])
input_labels=tf.Variable(label_initializer,trainable=False,collections=[])
...
sess.run(input_data.initializer,feed_dict={data_initializer:training_data})
sess.run(input_labels.initializer,feed_dict={label_initializer:training_labels})
...
使用一个队列作为模型训练的输入,多个线程准备训练样本,一个训练线程执行一个训练操作。
TensorFlow提供了两个类来帮助多线程的实现
#用来保存文件名称的FIFO队列
filename_queue=tf.train.string_input producer( ["file0.csv"," file1.csv"] )
#根据csv文件选用的读取器,不同种类文件读取器种类也不同
reader=tf.TextLineReader()
key,value=reader.read(filename_queue)
#为处理出现空值情况设置的默认值,以及给定解码器输出的类型
record_defaults = [[1], [1], [1], [1], [1]]
col1,col2,col3,col4,col5=tf.decode_csv(value,record_defaults=record_defaults)
features=tf.stack([col1,co12,col3,col4])
with tf.Session() as sess:
#创建协调器
coord = tf.train.Coordinator()
#在调用run或eva1执行读取之前,必须用tf.train.start_queue_runners来填充队列
threads=tf.train.start_queue_runners(coord=coord)
for i in range(10):
#拿到每次读取的结果
example,label=sess.run([features,col5])
print " example =",example, ",label=",label
coord.request_stop()
coord.join(threads)
#file0.csv,file1.csv的内容
#file0.csv
111,222,333,444,555
222,333,444,555,666
333,444,555,666,777
444,555,666,777,888
#file1.csv
555,444,333,222,111
666,555,444,333,222
777,666,555,444,333
888,777,666,555,444
#随机生成的样本队列
example=[111 222 333 444],label=555
example=[222 333 444 555],label=666
example=[333 444 555 666],label=777
example=[444 555 666 777],label=888
example=[555 444 333 222],label=111
example=[666 555 444 333],label=222
example=[777 666 555 444],label=333
example=[888 777 666 555],label=444
example=[555 444 333 222],label=111
example=[666 555 444 333],label=222
def read_my_file_format(filename_queue):
reader=tf.SomeReader()
key,record_string=reader.read(filename_queue)
example,label=tf.some_decoder(record_string)
processed_example=some_processing(example)
return processed_example,label
def input_pipeline(filenames,batch_size,num_epochs=None):
filename_queue=tf.train.string_input_producer(filenames,num_epochs=num_epochs,shuffle=True)
example,label=read_my_file_format(filename_queue)
#出队操作后的所剩数据的最小值
min_after_dequeue=10000
#队列的容量
capacity=min_after_dequeue+3*batch_size
example_batch,label_batch=tf.train.shuffle_batch([example,label],batch_size=batch_size,capacity=capacity,min_after_dequeue=min_after_dequeue)
return example_batch,label_batch
包含两个基础类:Dataset和Iterator
基本函数
类别 | 基本函数及功能说明 |
---|---|
四则运算 | tf.add() , tf.sub() , tf.mul() |
科学计算 | tf.abs() , tf.square() , tf.sin() |
比较操作 | tf.greater()(返回True/False) |
条件判断 | tf.where(condition,tensor_x,tensor_y)(condition是True就返回tensor_x,否则返回tensor_y) |
降维操作 | tf.reduce_sum() , tf.reduce_mean() (将高维矩阵元素以 求和 或 均值 的方式 变为一维 ) |
#调用损失函数的示例
loss=tf.reduce_mean(tf.square(y-y_data))
#实际值和预测值的差值平方,再求平均值,训练的目的就是要让这个loss越来越小
应用在图画风格迁移实例的代码
def loss(sess, models, img_content, img_style):
#计算内容损失函数
sess.run(models['input'].assign(img_content))
#内容图像在conv4_2层的特征矩阵
p=sess.run(models['conv4_2'])
#输入图像在conv4_2层的特征矩阵
x = models['conv4_2']
M=p.shape[1]*p.shape[2]
N =p.shape[3]
content_loss=(1.0 /(4*M*N))*tf.reduce_sum(tf.pow(p-x,2))
#计算风格损失函数
sess.run(models['input'].assign(img.style))
style_loss = 0.0
for layer_name,w in STYLE_ LAYERS:
#风格图像在layer_name各层的特征矩阵
a = sess.run(models[layer_name])
#输入图像在layer_name各层的特征矩阵
x=models[layer_name]
M=a.shape[1]*a.shape[2]
N = a.shape[3]
A=gram_matrix(a,M,N)
G=gram_matrix(x,M,N)
style_loss+=(1.0/(4*N**2*M**2))*tf.reduce_sum(tf.pow(G-A, 2))*w
total_lossALPHA * content_loss + BETA * style_loss
return total_loss
def gram_matrix(x, M, N):
x=tf.reshape(x,(M,N))
return tf.matmul(tf.transpose(x),x)
tf.nn.softmax_cross_entropy_with_logits(labels,logits)
tf.nnsparse_softmax_cross_entropy_with_logits(labels,logits)
参数 | 含义 |
---|---|
logits | 网络最后一层的输出 |
labels | 标签,分类或分割等问题中的标准答案 |
tf.nn.sigmoid_cross_entropy_with_logits(labels,logits)
tf.nn.weighted_cross_entropy_with_logits(targets,logits,pos_weight)
该函数功能及计算方法与tf.nn.sigmoid_cross_entropy_with_logits类似,但加了权重功能,是计算具有权重的sigmoid交叉熵函数
目的:增加或减小正样本在计算交叉熵时的loss
计算方法:loss=-pos_weight* targets*log(sigmoid(logits))-(1-targets)*log(1-sigmoid(logits))
令x=logits,z=targets,q=pos_weight,则有:
l o s s = q z ∗ − l o g ( s i g m o i d ( x ) ) + ( 1 − z ) ∗ − l o g ( 1 − s i g m o i d ( x ) ) loss=qz*-log(sigmoid(x))+(1-z)*-log(1-sigmoid(x)) loss=qz∗−log(sigmoid(x))+(1−z)∗−log(1−sigmoid(x))
= q z ∗ − l o g ( 1 1 + e − x ) + ( 1 − z ) ∗ − l o g ( e − x 1 + e − x ) =qz*-log(\frac{1}{1+e^{-x}})+(1-z)*-log(\frac{e^{-x}}{1+e^{-x}}) =qz∗−log(1+e−x1)+(1−z)∗−log(1+e−xe−x)
= q z ∗ l o g ( 1 + e − x ) + ( 1 − z ) ∗ ( l o g ( 1 + e − x ) − l o g ( e − x ) ) =qz*log(1+e^{-x})+(1-z)*(log(1+e^{-x})-log(e^{-x})) =qz∗log(1+e−x)+(1−z)∗(log(1+e−x)−log(e−x))
= ( q z + 1 − z ) ∗ l o g ( 1 + e − x ) + x ( 1 − z ) =(qz+1-z)*log(1+e^{-x})+x(1-z) =(qz+1−z)∗log(1+e−x)+x(1−z)
= x ( 1 − z ) + ( 1 + ( q − 1 ) ∗ z ) ∗ l o g ( 1 + e − x ) =x(1-z)+(1+(q-1)*z)*log(1+e^{-x}) =x(1−z)+(1+(q−1)∗z)∗log(1+e−x)
令l=(1+(q-1)*z),为保证稳定性并避免溢出,实现中采用:
l o s s = m a x ( x , 0 ) − x z + l ∗ l o g ( 1 + e − ∣ x ∣ ) loss=max(x,0)-xz+l*log(1+e^{-|x|}) loss=max(x,0)−xz+l∗log(1+e−∣x∣)
优化器的功能是实现优化算法,可以自动为用户计算模型参数的梯度值
TensorFlow中支持的优化器函数
操作 | 功能 |
---|---|
tf.train.Optimizer.minimize(loss,global_step=None,var_list=None) | 使用最小化损失函数的方法来训练模型,执行该操作时会内部依次调用compute_gradients和apply_gradients操作 |
tf.train.Optimizer.compute_gradients(loss,var_list=None) | 对var_list中列出的模型参数计算梯度,返回(梯度,模型参数)组成的列表 |
tf.train.Optimizer.apply_gradients(grads_and_vars) | 将计算出的梯度更新到模型参数上,返回更新参数的操作 |
一般采用最小化损失函数的方法:train_op= tf.train.Optimizer.minimize(loss,global_step=None,var_list=None)
对于模型层次较多的网络,由于输入数据不合法,求导精度限制等原因,可能出现梯度爆炸或梯度消失的问题,使得模型训练无法快速收敛。
解决方法:
TensorFlow中内置的梯度处理功能
方法 | 功能 |
---|---|
tf.clip_by_value(t,clip_value_min,clip_value_max) | 将梯度t裁剪到[clip_value_min,clip_value_max]区间 |
tf.clip_by_norm(t,clip_norm) | 对梯度t的L2范数进行裁剪,clip_norm为裁剪阈值 |
tf.clip_by_average_norm(t,clip_norm) | 对梯度t的平均L2范数进行裁剪,clip_norm为裁剪阈值 |
tf.clip_by_global_norm(t_list,clip_norm) | 对梯度t_list进行全局规范化加和裁剪,clip_norm为裁剪阈值 |
tf.global_norm(t_list) | 计算t_list中所有梯度的全局范式 |
整体流程
#创建Adam优化器
optimizer=tf.train.AdamOptimizer(learning_rate)
#计算梯度
grads=optimizer.compute_gradients(loss)
#对梯度的L2范数进行裁剪
grads=tf.clip_by_norm(grads,clip_norm)
#更新模型参数
train_op=optimizer.apply_gradients(grads)
在模型训练中,使用tf.train.Saver()来保存模型中的所有变量
import tensorflow as tf
weights=tf.Variable(tf.random_normal([30,60],stddev=0.35),name="weights")
w2=tf.Variable(weights.initialized_value(),name="w2")
#实例化saver对象
saver=tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for step in xrange(1000000):
#执行模型训练
sess.run(training_op)
if step%1000==0:
#将训练得到的变量值保存到检查点文件中
saver.save(sess,'./ckpt/my-model')
当需要基于某个checkpoint继续训练模型参数时,需要从.ckpt文件中恢复出已保存的变量
同样使用tf.train.Saver()来恢复变量,恢复变量时不需要先初始化变量
import tensorflow as tf
weights=tf.Variable(tf.random_normal([30,60],stddev=0.35),name="weights")
w2=tf.Variable(weights.initialized_value(),name="w2")
#模型路径只需要给出文件夹名称
model_path="./ckpt"
#实例化saver对象
saver=tf.train.Saver()
with tf.Session() as sess:
#找到存储变量值的位置
ckpt=tf.train.latest_checkpoint(model_path)
#恢复变量
saver.restore(sess,ckpt)
print(sess.run(weights))
print(sess.run(w2))
def load_image(path):
img=cv2.imread(path,cv2.IMREAD_COLOR)
resize_img=cv2.resize(img,(224,224))
norm_img=resize_img/255.0
return np.reshape(norm_img,(1,224,224,3))#NHWC的四维张量
使用tf.nn模块定义基本运算单元
def basic_calc(caltype,nin,inwb=None):
if caltype=='conv':
#nin:本层输入:inwb:inwb[0],inwb[1]==weights,bias
return tf.nn.relu(tf.nn.conv2d(nin,inwb[0],strides=[1,1,1,1],padding='SAME')+inwb[1])
elif caltype=='pool':
return tf.nn.max_pool(nin,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
def read_wb(vgg19_npy_path,name):
#从vgg_npy_path路径中读取模型参数到数组data_dict
data_dict=np.load(vgg19_npy_path,encoding='latin1').item()
weights=data_dict[name][0]
weights=tf.constant(weights)
bias=data_dict[name][1]
bias=tf.constant(bias)
return weights,bias片
tf.nn是TensorFlow中用于深度学习计算的核心模块,提供神经网络相关操作的支持,包括卷积,池化,损失,分类等。
操作 | 说明 |
---|---|
tf.nn.conv2d(input,filter,strides,padding) | 在给定的input和filter下计算卷积 |
tf.nn.depthwise_conv2d(input,filter,strides,padding) | 卷积核能相互独立的在自己的通道上面进行卷积操作 |
tf.nn.separable_conv2d(input,depthwise_filter,pointwise_filter,strides,padding) | 在纵深卷积depthwise_filter之后进行逐点卷积separable_filter |
tf.nn.bias_add(value,bias) | 对输入加上偏置 |
操作 | 说明 |
---|---|
tf.nn.relu(features) | 计算relu函数 |
tf.nn.elu(features) | 计算elu函数 |
tf.nn.dropout(x,keep_prob) | 计算dropout,其中keep_prob是keep概率。 |
tf.sigmoid(x) | 计算sigmoid函数 |
tf.tanh(x) | 计算tanh函数 |
操作 | 说明 |
---|---|
tf.nn.avg_pool(value,ksize,strides,padding) | 平均方式池化 |
tf.nn.max_pool(value,ksize,strides,padding) | 最大值方法池化 |
tf.nn.max_pool_with_argmax(input,ksize,strides,padding) | 返回一个二维元组(output,argmax),最大值pooling,返回最大值及其相应的索引 |
操作 | 说明 |
---|---|
tf.nn.l2_loss(t) | output=sum(t**2)/2 |
def build_vggnet(vgg19_npy_path):
models={}
models['input']=tf.Variable(np.zeros((1,224,224,3)).astype('float32'))
models['conv1_1']=basic_calc('conv',models['input'],read_wb(vgg19_npy_path,'conv1_1' ))
models['conv1_2']=basic_calc('conv',models['conv1_1'],read_wb(vgg19_npy_path,'conv1_2'))
models['pool1']=basic_calc('pool',mode1s['conv1_2'])
models['conv2_1']=basic_calc('conv',mode1s['pool1'],read_wb(vgg19_npy_path,'conv2_1'))
mode1s['conv2_2']=basic_calc('conv',models['conv2_1'],read_wb(vgg19_npy_path,'conv2_2'))
models['pool2']=basic_calc('pool',models['conv2_2'])
mode1s['conv3_1']=basic_calc('conv',models['pool2'],read_wb(vgg19_npy_path,'conv3_1'))
mode1s['conv3_2']=basic_calc('conv',models['conv3_1'],read_wb(vgg19_npy_path,'conv3_2'))
models['conv3_3']=basic_calc('conv',mode1s['conv3_2'],read_wb(vgg19_npy_path,'conv3_3'))
models['conv3_4']=basic_calc('conv',models['conv3_3'],read_wb(vgg19_npy_path,'conv3_4'))
mode1s['pool3']=basic_calc('pool',mode1s['conv3_4'])
models['conv4_1']=basic_calc('conv',models['pool3'],read_wb(vgg19_npy_path,'conv4_1'))
mode1s['conv4_2']=basic_calc('conv',models['conv4_1'],read_wb(vgg19_npy_path,'conv4_2'))
mode1s['conv4_3']=basic_calc('conv',models['conv4_2'],read_wb(vgg19_npy_path,'conv4_3'))
mode1s['conv4_4']=basic_calc('conv',models['conv4_3'],read_wb(vgg19_npy_path,'conv4_4'))
models['pool4']=basic_calc('pool',models['conv4_4'])
models['conv5_1']=basic_calc('conv',models['pool4'],read_wb(vgg19_npy_path,'conv5_1'))
models['conv5_2']=basic_calc('conv',mode1s['conv5_1'],read_wb(vgg19_npy_path,'conv5_2'))
models['conv5_3']=basic_calc('conv',models['conv5_2'],read_wb(vgg19_npy_path,'conv5_3'))
models['conv5_4']=basic_calc('conv',mode1s['conv5_3'],read_wb(vgg19_npy_path,'conv5_4'))
models['pool5']=basic_calc('pool',models['conv5_4'])
return models
#模型文件路径,需要加载
vgg19_npy_path='./vgg_models.npy'
#获取输入的内容图像
img_content=load_image('./content.jpg')
#创建会话进行执行
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())#变量初始化
#开始计算模型输出的部分
models=build_vggnet(vgg19_npy_path)
sess.run(models['input'].assign(img_content))
res=sess.run(models['pool5'])
#接下来对res做其他处理
...
这里因为还没实践,听的云里雾里的,准备开始上手实战看看再来修正
目前就先按课程写个笔记,之后如果遇到问题再来回顾。(感觉这章视频杂音比较多)