今天算是我的第一个10.24程序员节吧,记录由VGG16复现过程中初见的用法、函数等,以此起步。

1.a[len(a):len(a)]=[]

a=[]
a[len(a):len(a)]=[]可以用来扩展list,类似append,但是append,又类似于”整体加入“
a=[8,9] 
print(a) 
a[len(a):len(a)]=[1,2,3] 
print(a,) 
a.append([7,7]) 
print(a) 
a.append('b') 
print(a) 
a.append(a) 
print(a)

结果:

[8, 9]
[8, 9, 1, 2, 3]
[8, 9, 1, 2, 3, [7, 7]]
[8, 9, 1, 2, 3, [7, 7], 'b']
[8, 9, 1, 2, 3, [7, 7], 'b', [...]]

2.a[:-1]和a[::-1]

a = [0,1,2,3,4,5,6,7,8,9]

b = a[i:j] 表示复制a[i]到a[j-1],以生成新的list对象。b = a[1:3] 那么,b的内容是 [1,2]

当i缺省时,默认为0,当j缺省时,默认为len(alist), 当i,j都缺省时,a[:]就相当于完整复制一份a了

b = a[i:j:s],s表示步进,缺省为1.所以a[i:j:1]相当于a[i:j];当s<0时,i缺省时,默认为-1. j缺省时,默认为-len(a)-1

所以a[::-1]相当于 a[-1:-len(a)-1:-1],也就是从最后一个元素到第一个元素复制一遍。倒序。

3.tf.train.slice_input_producer()和tf.train.batch、tf.train.shuffle_batch

3.1tf.tain.slice_input_producer()是一个tensor生成器,作用是按照设定,每次从一个tensor列表中按顺序或者随机抽取出一个tensor放入文件名队列。还需要调用tf.train.start_queue_runners 函数来启动执行文件名队列填充的线程,之后计算单元才可以把数据读出来,否则文件名队列为空的,计算单元就会处于一直等待状态,导致系统阻塞。

tf.train.slice_input_producer(
    tensor_list,
    num_epochs=None, 
    shuffle=True,
    seed=None,
    capacity=32,
    shared_name=None,
    name=None
)
''' tensor_list:包含一系列tensor的列表,表中tensor的第一维度的值必须相等,即个数必须相等,有多少个图像,就应该有多少个对应的标签。
   num_epochs: 可选,是一个整数值,代表迭代的次数,如果设置 num_epochs=None,生成器可以无限次遍历tensor列表,如果设置为 num_epochs=N,生成器只能遍历tensor列表N次。
    shuffle: bool类型,设置是否打乱样本的顺序。一般情况下,如果shuffle=True,生成的样本顺序就被打乱了,在批处理的时候不需要再次打乱样本,使用 tf.train.batch函数就可以了;如果shuffle=False,就需要在批处理时候使用 tf.train.shuffle_batch函数打乱样本。
    seed: 可选的整数,是生成随机数的种子,在第三个参数设置为shuffle=True的情况下才有用。
    capacity:设置tensor列表的容量。
    shared_name:可选参数,如果设置一个‘shared_name’,则在不同的上下文环境(Session)中可以通过这个名字共享生成的tensor。
    name:可选,设置操作的名称。'''

输出为list:<class 'list'>: [<tf.Tensor 'input_producer/Gather:0' shape=() dtype=string>, <tf.Tensor 'input_producer/Gather_1:0' shape=() dtype=int32>]

[0]:输入队列;[1]:输出队列

tf.train.slice_input_producer([image,label],num_epochs=10)

 上式随机产生一个图片和标签,num_epochs=10,则表示把所有的数据过10遍,使用完所有的图片数据为一个epoch,这是重复使用10次。上面的用法表示你的数据集和标签已经全部加载到内存中了,如果数据集非常庞大,我们通过这个函数也可以只加载图片的路径,放入图片的path,注意path必须是一个list或者tensorlist.

 # 生成包含输入和目标图片地址名的list 
input_files = [os.path.join(dirname, 'input', f) for f in flist] 
output_files = [os.path.join(dirname, 'output', f) for f in flist] 
# 内部自动转换为Constant String的Tensor,并排队进入队列 
input_queue, output_queue = tf.train.slice_input_producer( [input_files, output_files], shuffle=self.shuffle, seed=0123, num_epochs=self.num_epochs) 
# tf.train.slice_input_producer()每次取一对【输入-目标】对,交给ReadFile这个Op 
input_file = tf.read_file(input_queue) 
output_file = tf.read_file(output_queue) 
# 生成RGB格式的图像tensor 
im_input = tf.image.decode_jpeg(input_file, channels=3) 
im_output = tf.image.decode_jpeg(output_file, channels=3)

#此部分参考:https://www.jianshu.com/p/8ba9cfc738c2

3.2tf.train.batch()

tf.train.batch(tensors, batch_size, num_threads=1, capacity=32,
          enqueue_many=False, shapes=None, dynamic_pad=False,
          allow_smaller_final_batch=False, shared_name=None, name=None)

tf.train.batch是按顺序读取数据,队列中的数据始终是一个有序的队列,作为训练一个batch的数据,等待tensor出队执行计算。
假设现在有个test.tfrecord文件,里面按从小到大顺序存放整数0~100队列的capacity=20,开始队列内容为0,1,..,19=>读取10条记录后,队列剩下10,11,..,19,然后又补充10条变成=>10,11,...,29,
队头一直按顺序补充,队尾一直按顺序出队,到了第100条记录后,又重头开始补充0,1,2...

输出的形状 [batch_size, x, y, z],深度学习中长为[batchsize,W,H,channel]

# Creates batches of 32 images and 32 labels.
image_batch, label_batch = tf.train.shuffle_batch(
      [single_image, single_label],
      batch_size=32,
      num_threads=4,
      capacity=50000,
      min_after_dequeue=10000)

这段代码写的是从[single_image, single_label]利用4个线程读取32行
输出尺寸是image_batch:【batch_size,single_image】  label_batch:【batch_size,single_label】
如:single_image:Tensor("strided_slice:0", shape=(224, 224, 3), dtype=float32)
      single_label:Tensor("one_hot:0", shape=(2,), dtype=uint8)
输出image_batch:Tensor("shuffle_batch:0", shape=(64, 224, 224, 3), dtype=float32)
   label_batch:Tensor("shuffle_batch:1", shape=(64, 2), dtype=uint8)
3.3tf.train.shuffle_batch()

tf.train.shuffle_batch(tensor_list, batch_size, capacity, min_after_dequeue, num_threads=1, seed=None,enqueue_many=False, shapes=None, name=None)

capacity是队列的长度
min_after_dequeue是出队后,队列至少剩下min_after_dequeue个数据,因此队列中剩下的数据也是乱序的,队头也是一直在补充(我猜也是按顺序补充),
比如batch_size=5,capacity=10,min_after_dequeue=5,
初始是有序的0,1,..,9(10条记录),
然后打乱8,2,6,4,3,7,9,2,0,1(10条记录),
队尾取出5条,剩下7,9,2,0,1(5条记录),
然后又按顺序补充进来,变成7,9,2,0,1,10,11,12,13,14(10条记录),
再打乱13,10,2,7,0,12...1(10条记录),再出队...

以上部分可参考:原文:https://blog.csdn.net/ying86615791/article/details/73864381  

综上:一个非常好使的,用于深度学习的代码段:

自动获取每个batch的数据, 使用队列可以把图片及对应的标签准确的取出来,同时还自动打乱顺序,非常好使用。

就像前面说的[0]:输入队列;[1]:输出队列,这里[0]:输入图像队列;[1]:标签队列,也就是输出结果队列

# 把图片数据转化为三维矩阵
class ImageDataGenerator(object):
    def __init__(self, images, labels, batch_size, num_classes):
        self.filenames = images
        self.labels = labels
        self.batch_size = batch_size
        self.num_class = num_classes
        self.image_batch, self.label_batch = self.image_decode()
    def image_decode(self):
        '''# 建立文件队列,把图片和对应的实际标签放入队列中
        #注:在没有运行tf.train.start_queue_runners(sess=sess)之前,数据实际上是没有放入队列中的'''
        file_queue = tf.train.slice_input_producer([self.filenames, self.labels])

        # 把图片数据转化为三维BGR矩阵
        image_content = tf.read_file(file_queue[0])#[0]:输入队列;[1]:输出队列
        image_data = tf.image.decode_jpeg(image_content, channels=3)
        image = tf.image.resize_images(image_data, [224, 224])

        #预处理是从每个像素中减去在训练集上计算的平均RGB值
        img_centered = tf.subtract(image, VGG_MEAN)
        img_bgr = img_centered[:, :, ::-1]#[::-1]倒序 RGB→BGR

        labels = tf.one_hot(file_queue[1],self.num_class, dtype=tf.uint8)

        # 分batch从文件队列中读取数据
        image_batch, label_batch = tf.train.shuffle_batch([img_bgr, labels],
                                                          batch_size=self.batch_size,
                                                          capacity=2000,
                                                          min_after_dequeue=1000)
        return image_batch, label_batch

4.tf.one_hot()

tf.one_hot()函数是将input转化为one-hot类型数据输出,相当于将多个数值联合放在一起作为多个相同类型的向量,可用于表示各自的概率分布,通常用于分类任务中作为最后的FC层的输出,有时翻译成“独热”编码(one-hot encoding),独热编码一般是在有监督学习中对数据集进行标注时候使用的,指的是在分类问题中,将存在数据类别的那一类用X表示,不存在的用Y表示,这里的X常常是1, Y常常是0。
举个例子:
比如我们有一个5类分类问题,我们有数据(Xi,Yi),其中类别Yi有五种取值(因为是五类分类问题),所以如果Yj为第一类那么其独热编码为: [1,0,0,0,0],如果是第二类那么独热编码为:[0,1,0,0,0],也就是说只对存在有该类别的数的位置上进行标记为1,其他皆为0。这个编码方式经常用于多分类问题,特别是损失函数为交叉熵函数的时候。

one_hot(indices, depth, on_value=None, off_value=None, axis=None, dtype=None, name=None)
    Returns a one-hot tensor.

indices表示输入的多个数值,通常是矩阵形式;depth表示输出的尺寸。由于one-hot类型数据长度为depth位,其中只用一位数字表示原输入数据,这里的on_value就是这个数字,默认值为1,one-hot数据的其他位用off_value表示,默认值为0。

tf.one_hot()函数规定输入的元素indices从0开始,最大的元素值不能超过(depth - 1),因此能够表示(depth + 1)个单位的输入。若输入的元素值超出范围,输出的编码均为 [0, 0 … 0, 0]。

indices = 0 对应的输出是[1, 0 … 0, 0], indices = 1 对应的输出是[0, 1 … 0, 0], 依次类推,最大可能值的输出是[0, 0 … 0, 1]。

例子:

labels = tf.one_hot(file_queue[1],self.num_class, dtype=tf.uint8)
#file_queue[1]:标签;self.num_class:分类类别

5.x=tf.reshape(botton,[-1,in_size])

x=tf.reshape(botton,[-1,25088])

这里如上层pool5的尺寸为[7,7,512],加上维度就是botton=[3,7,7,512],设置in_size=25088(7*7*512)

把x转为最后一个维度的向量,也就是(3,25088,)。

6.tf.nn.bias_add(): 

通俗解释:一个叫bias的向量加到一个叫value的矩阵上,是向量与矩阵的每一行进行相加,得到的结果和value矩阵大小相同。如 value:(3,25088),bias维度是[3,25088]

5.6常常合用用来求结果值:这里相当于[X‘W,X'W,.....]+[b1,b2,......]。

    def fc_layer(self, bottom, in_size, out_size, name):
        with tf.variable_scope(name):
            weights, biases = self.get_fc_var(in_size, out_size, name)

            x = tf.reshape(bottom, [-1, in_size])#flatten
            fc = tf.nn.bias_add(tf.matmul(x, weights), biases)#tf.matmul 矩阵相乘 tf.nn.bias_add是向量与矩阵的每一行进行相加,得到的结果和value矩阵大小相同。

            return fc

猜你喜欢

转载自blog.csdn.net/m0_37644085/article/details/83343465