Tensorflow1笔记8

【北京大学】12 TensorFlow1.x的卷积神经网络模型VGGNet实现

张量是多维数组

常用函数

(2)np.load /np.save将数组以二进制格式读出或写入磁盘,扩展名为.npy
···
np.save(“名.npy”,某数组)
某变量 = np.load(“名.npy”,encoding ="").item()
#encoding可不写,有三个选项latin1 ASCI
···
(5)tf.nn.bias_add(乘加和,bias)#把bias加到乘加和上
(6)tf.reshape(tensor,[n行,m列])
或tf.reshape(tensor,[-1,m列])-1表示行随着m列自动计算
(7)np.argsort(列表)#对列表从小到大排序,返回索引值
(8)os.getcwd() # 返回当前工作目录
(9)os.path.join( , ,…) # 拼出整个路径,可引导到特定文件
(11)tf.conda(值,在哪个维),实现粘贴

t1 = [[1,2,3],[4,5,6]]
t2 = [[7,8,9],[10,11,12]]
#按照第0个维度粘
tf.concat([t1,t2],0) ==>[[1,2,3],[4,5,6],[7,8,9],[10,11,12]] # 
#按照第1个维度粘贴
tf.concat([t1,t2],1) ==>[[1,2,3,7,8,9],[4,5,6,10,11,12]]

12)fig = plt.figure(‘图名字’)可视化图片

img = io.imread(图片路径)
ax = fig.add_subplot(数 数 数)#分别是包含几行,包含几列,当前是第几个
例如

#coding:utf-8
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 100)
#新建figure对象
fig=plt.figure()
#新建子图1
ax1=fig.add_subplot(2,2,1)
ax1.plot(x, x)
#新建子图2
ax3=fig.add_subplot(2,2,2)
ax3.plot(x, x ** 2)
ax3.grid(color='r', linestyle='--', linewidth=1,alpha=0.3)
#新建子图3
ax4=fig.add_subplot(2,2,3)
ax4.plot(x, np.log(x))
plt.show()

ax.bar(bar的个数,bar的值,每个bar的名字,bar宽,bard色)#画出柱状图
ax.set_ylabel("")
ax.set_title("")
ax.text(文字x坐标,文字y坐标,文字内容,ha =‘center’,va =‘bottom’,fontsize = 7)

(13)ax = imshow(图)画子图

学会查找函数

Google官方文档
例如:tf.concat :https://tensorflow.google.cn/api_docs/python/tf/concat?hl=en
卷积神经网络(Convolutional Neural Network, CNN):
https://tensorflow.google.cn/tutorials/images/cnn?hl=zh_cn
————————————————
vgg16.npy下载地址: 链接:https://pan.baidu.com/s/1dMw3u-9bAWr8vgJyEtGF0Q ####密码:h8yb

app.py文件

是应用程序,实现图像识别


#coding:utf-8
import numpy as np
# Linux 服务器没有 GUI 的情况下使用 matplotlib 绘图,必须置于 pyplot 之前
#import matplotlib
#matplotlib.use('Agg') 
import tensorflow as tf
import matplotlib.pyplot as plt

# 下面三个是引用自定义模块
import vgg16
import utils
from Nclasses import labels

img_path = raw_input('Input the path and image name:')
#img_ready为1* 224*224,维度为3
img_ready = utils.load_image(img_path) # 调用 load_image()函数,对待测试的图像做一些预处理操作
#定义一个 figure 画图窗口,并指定窗口的名称,也可以设置窗口修的大小
#print "img_ready shape", tf.Session().run(tf.shape(img_ready))

# 定义画图窗口,并指定窗口名称
fig=plt.figure(u"Top-5 预测结果") 
with tf.Session() as sess:
 # 定义一个维度为[1,224,224,3],类型为 float32 的 tensor 占位符
 x = tf.placeholder(tf.float32, [1, 224, 224, 3])
 vgg = vgg16.Vgg16() # 类 Vgg16 实例化出 vgg,读出npy文件保存的模型参数
 
 # 调用类的成员方法 forward(),并传入待测试图像,这也就是网络前向传播的过程
 vgg.forward(x) 
 # 将一个 batch 的数据喂入网络,得到网络的预测输出
 #probablity 存着1000个概率,其列表索引值是Nclasses.py中labels的键
 probablity = sess.run(vgg.prob, feed_dict={x:img_ready})
 # np.argsort 函数返回预测值(probability 的数据结构[[各预测类别的概率值]])由小到大的索引值,
 
 # 并取出预测概率最大的五个索引值
 top5 = np.argsort(probability[0])[-1:-6:-1]  #x.argsort()[::-1]#输出x中元素从大到小排列的对应的index(索引)
 print "top5:",top5
 
 # 定义两个 list---对应的概率值和实际标签(zebra)
 values = []
 bar_label = []
 for n, i in enumerate(top5): # 枚举上面取出的五个索引值
 print "n:",n
 print "i:",i
 values.append(probability[0][i]) # 将索引值对应的预测概率值取出并放入 values
 bar_label.append(labels[i]) # 根据索引值取出对应的实际标签并放入 bar_label
 print i, ":", labels[i], "----", utils.percent(probability[0][i]) # 打印属于某个类别的概率
 
 ####
 ax = fig.add_subplot(111) # 将画布划分为一行一列,并把下图放入其中
 # bar()函数绘制柱状图,参数 range(len(values)是柱子下标,values 表示柱高的列表(也就是五个预测概率值,
 # tick_label 是每个柱子上显示的标签(实际对应的标签),width 是柱子的宽度,fc 是柱子的颜色)
 
 ax.bar(range(len(values)), values, tick_label=bar_label, width=0.5, fc='g')
 ax.set_ylabel(u'probability') # 设置横轴标签
 ax.set_title(u'Top-5') # 添加标题
 for a,b in zip(range(len(values)), values):
 # 在每个柱子的顶端添加对应的预测概率值,a,b 表示坐标,b+0.0005 表示要把文本信息放置在高于每个柱子顶端0.0005 的位置,
 # center 是表示文本位于柱子顶端水平方向上的的中间位置,bottom 是将文本水平放置在柱子顶端垂直方向上的底端位置,fontsize 是字号, utils.percent使值用百分比显示
 ax.text(a, b+0.0005, utils.percent(b), ha='center', va = 'bottom', fontsize=7) 
 plt.savefig('./result.jpg') # 保存图片
 plt.show() # 弹窗展示图像(linux 服务器上将该句注释掉)

vgg16.py文件:读取模型参数,搭建模型

在这里插入图片描述

#tensorflow学习笔记(北京大学) vgg16.py 完全解析 
#QQ群:476842922(欢迎加群讨论学习
#!/usr/bin/python
#coding:utf-8
import inspect
import os
import numpy as np
import tensorflow as tf
import time
import matplotlib.pyplot as plt
#样本RGB的平均值
VGG_MEAN = [103.939, 116.779, 123.68] 
class Vgg16():
    def  __init__(self, vgg16_path=None): #模型参数导入
        if vgg16_path is None:
            #返回当前工作目录
            vgg16_path = os.path.join(os.getcwd(), "vgg16.npy") 
            #遍历其内键值对,导入模型参数
            self.data_dict = np.load(vgg16_path, encoding='latin1').item() 
 
     ####
    def forward(self, images):
        
        print("build model started")
        #获取前向传播开始时间
        start_time = time.time() 
        #逐个像素乘以255
        rgb_scaled = images * 255.0 
        #从GRB转换彩色通道到BRG
        red, green, blue = tf.split(rgb_scaled,3,3) #rgb_scaled切分为3份
        #减去每个通道的像素平均值,这种操作可以移除图像的平均亮度值
        #该方法常用在灰度图像上
        bgr = tf.concat([     
            blue - VGG_MEAN[0],
            green - VGG_MEAN[1],
            red - VGG_MEAN[2]],3)
            
        #构建VGG的16层网络(包含5段卷积,3层全连接),并逐层根据命名空间读取网络参数
        #第一段卷积,含有两个卷积层,后面接最大池化层,用来缩小图片尺寸
        self.conv1_1 = self.conv_layer(bgr, "conv1_1") 
        #传入命名空间的name,来获取该层的卷积核和偏置,并做卷积运算,最后返回经过激活函数后的值
        self.conv1_2 = self.conv_layer(self.conv1_1, "conv1_2")
        #根据传入的pooling名字对该层做相应的池化操作
        self.pool1 = self.max_pool_2x2(self.conv1_2, "pool1") #“”内为自定义命名
        
        #第二段卷积,包含两个卷积层,一个最大池化层
        self.conv2_1 = self.conv_layer(self.pool1, "conv2_1")
        self.conv2_2 = self.conv_layer(self.conv2_1, "conv2_2")
        self.pool2 = self.max_pool_2x2(self.conv2_2, "pool2")
        #第三段卷积,包含三个卷积层,一个最大池化层
        self.conv3_1 = self.conv_layer(self.pool2, "conv3_1")
        self.conv3_2 = self.conv_layer(self.conv3_1, "conv3_2")
        self.conv3_3 = self.conv_layer(self.conv3_2, "conv3_3")
        self.pool3 = self.max_pool_2x2(self.conv3_3, "pool3")
        
        #第四段卷积,包含三个卷积层,一个最大池化层
        self.conv4_1 = self.conv_layer(self.pool3, "conv4_1")
        self.conv4_2 = self.conv_layer(self.conv4_1, "conv4_2")
        self.conv4_3 = self.conv_layer(self.conv4_2, "conv4_3")
        self.pool4 = self.max_pool_2x2(self.conv4_3, "pool4")
        
        #第五段卷积,包含三个卷积层,一个最大池化层
        self.conv5_1 = self.conv_layer(self.pool4, "conv5_1")
        self.conv5_2 = self.conv_layer(self.conv5_1, "conv5_2")
        self.conv5_3 = self.conv_layer(self.conv5_2, "conv5_3")
        self.pool5 = self.max_pool_2x2(self.conv5_3, "pool5")
        
        #第六层全连接
        #根据命名空间name做加权求和运算
        self.fc6 = self.fc_layer(self.pool5, "fc6")
        #经过relu激活函数
        self.relu6 = tf.nn.relu(self.fc6) 
        
        #第七层全连接
        self.fc7 = self.fc_layer(self.relu6, "fc7")
        self.relu7 = tf.nn.relu(self.fc7)
        
        #第八层全连接
        self.fc8 = self.fc_layer(self.relu7, "fc8")
        self.prob = tf.nn.softmax(self.fc8, name="prob") #使其服从概率分布
        
        #得到全向传播时间
        end_time = time.time() 
        print(("time consuming: %f" % (end_time-start_time)))
        
        #清空本次读取到的模型参数字典
        self.data_dict = None 
    
    #定义卷积运算    
    def conv_layer(self, x, name):
        #根据命名空间name找到对应卷积层的网络参数
        with tf.variable_scope(name): 
            #读到该层的卷积核
            w = self.get_conv_filter(name) 
            #卷积运算
            conv = tf.nn.conv2d(x, w, [1, 1, 1, 1], padding='SAME') 
            #读到偏置项
            conv_biases = self.get_bias(name) 
            #加上偏置,并做激活计算
            result = tf.nn.relu(tf.nn.bias_add(conv, conv_biases)) 
            return result
    
    #定义获取卷积核的参数
    def get_conv_filter(self, name):
        #根据命名空间从参数字典中获取对应的卷积核
        return tf.constant(self.data_dict[name][0], name="filter") 
    
    #定义获取偏置项的参数
    def get_bias(self, name):
        #根据命名空间从参数字典中获取对应的偏置项
        return tf.constant(self.data_dict[name][1], name="biases")
    
    #定义最大池化操作
    def max_pool_2x2(self, x, name):
        return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME', name=name)
    
    #定义全连接层的全向传播操作
    def fc_layer(self, x, name):
        #根据命名空间name做全连接层的计算
        with tf.variable_scope(name): 
            #获取该层的维度信息列表
            shape = x.get_shape().as_list() 
            dim = 1
            for i in shape[1:]:
                #将每层的维度相乘
                dim *= i 
            #改变特征图的形状,也就是将得到的多维特征做拉伸操作,只在进入第六层全连接层做该操作
            x = tf.reshape(x, [-1, dim])
            #读到权重值
            w = self.get_fc_weight(name) 
            #读到偏置项值
            b = self.get_bias(name) 
            #对该层输入做加权求和,再加上偏置
            result = tf.nn.bias_add(tf.matmul(x, w), b) 
            return result
    
    #定义获取权重的函数
    def get_fc_weight(self, name): 
        #根据命名空间name从参数字典中获取对应1的权重
        return tf.constant(self.data_dict[name][0], name="weights")

ValueError: Object arrays cannot be loaded when allow_pickle=False
查看其他人的经验,发现是numpy的版本有问题。
方法一:出错的地方就是这一行:

data = np.load(‘path’)

修改为下面这个就跑通了:

data = np.load(‘path’,allow_pickle=True)

就是加了个allow_pickle=True
方法二:
卸载之前装的numpy1.17,

安装pip install numpy==1.16.2

utils.py文件:读入图片,概率显示

from skimage import io, transform
没有安装所谓的skimage.io
pip install scikit-image

#!/usr/bin/python
#coding:utf-8
from skimage import io, transform
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from pylab import mpl

mpl.rcParams['font.sans-serif']=['SimHei'] # 正常显示中文标签
mpl.rcParams['axes.unicode_minus']=False # 正常显示正负号
#预处理
def load_image(path):
 fig = plt.figure("Centre and Resize") #新建名称为Centre and Resize的图
 
 img = io.imread(path) # 根据传入的路径读入图片
 img = img / 255.0 # 将像素归一化到[0,1]
 
 # 将该画布分为一行三列
 ax0 = fig.add_subplot(131) # 把下面的图像放在该画布的第一个位置
 ax0.set_xlabel(u'Original Picture') # 添加子标签
 ax0.imshow(img) # 添加展示该图像
 
 short_edge = min(img.shape[:2]) # 找到该图像的最短边
 y = (img.shape[0] - short_edge) / 2 
 x = (img.shape[1] - short_edge) / 2 # 把图像的 w 和 h 分别减去最短边,并求平均
 crop_img = img[y:y+short_edge, x:x+short_edge] # 取出切分出的中心图像
 print crop_img.shape
 
 ax1 = fig.add_subplot(132) # 把下面的图像放在该画布的第二个位置
 ax1.set_xlabel(u"Centre Picture") # 添加子标签
 ax1.imshow(crop_img)
 
 re_img = transform.resize(crop_img, (224, 224)) # resize 成固定的 imag_szie
 
 ax2 = fig.add_subplot(133) # 把下面的图像放在该画布的第三个位置
 ax2.set_xlabel(u"Resize Picture") # 添加子标签
 ax2.imshow(re_img)
img_ready = re_img.reshape((1, 224, 224, 3))
 return img_ready
 
# 定义百分比转换函数
def percent(value):
 return '%.2f%%' % (value * 100)

Nclasses.py文件

含label字典

#每个图像的真实标签,以及对应的索引值
labels = {
0: ‘tench\n Tinca tinca’,
1: ‘goldfish\n Carassius auratus’,…

vgg16.npy文件

包含了神经网络的全部参数
self.data_dict = np.load(vgg16_path, encoding=‘latin1’).item() 改为
self.data_dict = np.load(vgg16_path, encoding=‘latin1’,allow_pickle=True).item()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值