Skip to main content

Posts

Showing posts from November, 2018

tf.where()函数

tf.where()定义如下: where(condition, x=None, y=None,name=None) condition:一个Tensor,数据类型为tf.bool类型 如果x、y均为空,那么返回condition中值为True的位置的Tensor:例如:x就是condition,y是返回值

tf.segment_xxx系列函数测试

先看一段百度的上搜索到的结果: TensorFlow提供了一些操作,你可以使用基本的算术运算来分割输入的tensor。这里的分割操作是沿着第一个维度的一个分区,等价于这里定义了一个从第一个维度到第segment_ids维度的一个映射。segment_ids张量的长度必须和需要分割的tensor的第一维度的尺寸d0一样,其中segment_ids中的编号从0到k,并且k < d0。举个例子,如果我们需要分割的tensor是一个矩阵,那么segment_ids的映射就指向矩阵的每一行 --------------------- 是不是看了一脸懵逼,解释了好像没解释一球样? 我来试着解释一下: 学过线性代数都知道矩阵的基础行列变换,可以相互交换行或者列,甚至可以某一行或者列乘一个数加到另外一行或者列上。说这个的原因就是segmen_xxx系列函数和这个有关。只不过是只和行变换有关。 这个系列函数包含一个重要的参数,这个参数让很多初学者懵逼:segment_ids.就是这玩意儿让我也琢磨好几十分钟。汗。智商不够只有敲代码看错误信息来搞明白它是啥意思。 加入有一个m×n的矩阵要运用segment_sum函数,那么这个参数就必须是一个一行m个元素的量,为啥不说列表或者向量呢?因为作为参数,segment_sum对他们的处理是一样的。我们也经常看到有的编码用(a,b,c),也有的代码用[a,b,c],效果一样。 segment_ids这m个数,分别代表原真阵列的1~m行的数据,在函数运行后产生的新阵列中的位置,这时候会有这么两种情况: 新的行位置大于原先阵列的最大行位置。这时候,新阵列会扩充,直到行索引满足新的行索引。新添加的行,默认全部填充为0。(segment_prod函数填充为1) 若干新行的位置如果重叠怎么办?比如,第一行和第四行的位置都变为2,那么就在索引为2(也就是第三行)将它们加,显示相加以后的值 另外,TS要求segment_ids的值不能为降序。你可以是[0,0,0]或[0,0,1],不能是[2,1,1] 具体代码例子 点击这里运行 其他segment_xxx函数的原理一样,就不说了。可以看代码。 所以严格说,讲这类函数称为分割相关函数不合适。

tf.reduce_xxx函数

#书上称这一系列为规约函数。基本上都是降维 import tensorflow as tf import numpy as np t=np.random.randint(0,3,[3,4]) sess=tf.Session() print("Test matrix is:\n",t) print("现在测试tf.reduce_sum,对tensor中的元素求和") print("tf.reduce_sum():",sess.run(tf.reduce_sum(t))) print("tf.reduce_sun(axis=0):",sess.run(tf.reduce_sum(t,axis=0))) print("tf.reduce_sun(axis=1):",sess.run(tf.reduce_sum(t,axis=1))) print("-----------------------------------------------------------------------------------------------") print("现在测试tf.reduce_prod,对tensor中的元素求乘积") print("tf.reduce_prod():",sess.run(tf.reduce_prod(t))) print("tf.reduce_prod(axis=0):",sess.run(tf.reduce_prod(t,axis=0))) print("tf.reduce_prod(axis=1):",sess.run(tf.reduce_prod(t,axis=1))) print("tf.reduce_prod(axis=0,keep_dims=True):",sess.run(tf.reduce_prod(t,axis=0,keep_dims=True))) print("tf.reduce_prod(axis=1,keep_dims=True):",sess.run(tf

谈axis

Python和TF张量计算中经常见的形参,代表什么意思呢?     首先请看一下官方帮助的解释:     轴用来为超过一维的数组定义的属性,二维数据拥有两个轴:第0轴沿着行的垂直往下,第1轴沿着列的方向水平延伸。如下图     注意看,官方对于0和1的解释是轴,也就是坐标轴。而坐标轴是有方向的,所以千万不要用行和列的思维去想axis,因为行和列是没有方向的,这样想会在遇到不同的例子时感到困惑。     根据官方的说法,1表示横轴,方向从左到右;0表示纵轴,方向从上到下。当axis=1时,数组的变化是横向的,而体现出来的是列的增加或者减少。我们拿图形举个例子:     我们有一个正方形,假设是4x4的     接下来我们让他横向增加一个单位,也就是长度+1,变成了一个5x4的长方形 也就是说,对于这个4x4的正方形而言,当axis=1时,体现的是横向的长度+1,而如果这是一个4行4列的二维数组同样也是如此,但是体现出来是增加了一列。     所以其实axis的重点在于方向,而不是行和列。具体到各种用法而言也是如此。当axis=1时,如果是求平均,那么是从左到右横向求平均;如果是拼接,那么也是左右横向拼接;如果是drop,那么也是横向发生变化,体现为列的减少。 当考虑了方向,即axis=1为横向,axis=0为纵向,而不是行和列,那么所有的例子就都统一了。题主的疑问也就迎刃而解。

tf.reverse反序

这个功能相当于矩阵的初等行列变换 我们看代码: import tensorflow as tf import numpy as np t=[[1,2,3],[4,5,6]] t0=tf.reverse(t,[0]) t1=tf.reverse(t,[1]) t21=tf.reverse(t,[0,1]) t22=tf.reverse(t,[1,0]) sess=tf.Session() print(sess.run(t0)) print(sess.run(t1)) print(sess.run(t21)) print(sess.run(t22)) 运行结果如下: 按行(axis=0)变换,上下行交换位置 [[4 5 6] [1 2 3]] axis=1按照横轴变换,前后列交换位置 [[3 2 1] [6 5 4]] 先纵轴变换,后横轴变换 [[6 5 4] [3 2 1]] 先横轴后纵轴变换 [[6 5 4] [3 2 1]]

tf.transpose矩阵的转置

二维矩阵的转置很简单,元素的i,j坐标交换就行。多为矩阵的转换复杂,遵循什么规律呢? 先看看代码: import tensorflow as tf import numpy as np print("二维矩阵的转置\n") t=[[1,2,3],[4,5,6]] t1=tf.transpose(t) t2=tf.transpose(t,[0,1])#[0,1]是正常的坐标轴排列顺序,运行结果不转置 t3=tf.transpose(t,[1,0]) sess=tf.Session() print("Default Transepose is:\n",sess.run(t1),"\n[0,1] Tranpose is:\n",sess.run(t2),"\n[1,0] Tranpose is:\n",sess.run(t3)) print("三维矩阵的转置") t=[[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]#这个三维矩阵有两张表格,每个表格都是2行3列 print("先测试不带perm参数的默认转置和参数顺序为不转置的正常坐标轴顺序[0,1,2]转置结果") t1=tf.transpose(t) t2=tf.transpose(t,[0,1,2]) print(sess.run(t1)) print(sess.run(t2)) 代码输出如下: 二维矩阵的转置 Default Transepose is: [[1 4] [2 5] [3 6]] [0,1] Tranpose is: [[1 2 3] [4 5 6]] [1,0] Tranpose is: [[1 4] [2 5] [3 6]] 三维矩阵的转置 先测试不带perm参数的默认转置和参数顺序为不转置的正常坐标轴顺序[0,1,2]转置结果 [[[ 1 7] [ 4 10]] [[ 2 8] [ 5 11]] [[ 3 9] [ 6 12]]] 这里分析一下元素的坐标在转换前和转换后的变化: 1:(0,0,0)==>(

什么是onehot编码

这么高大上的名字,顾名思义,就是在编码中只有一个1,其他是0。 眼熟吧。在Pyton神经网络编程这本书中,已经见过了。神经网络的输出中,用1000000000代表1,用01000000000代表1,以此类推,用0000000001代表9。 tf.one_hot()函数是将input转化为one-hot类型数据输出,相当于将多个数值联合放在一起作为多个相同类型的向量,可用于表示各自的概率分布,通常用于分类任务中作为最后的FC层的输出,有时翻译成“独热”编码。 tensorflow的help中相关说明如下: one_hot(indices, depth, on_value=None, off_value=None, axis=None, dtype=None, name=None) 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]。 代码示例如下: --------------------- import tensorflow as tf import numpy as np t=[0,1,2,3,4]#onehot编码数据必须是整形 #indices, depth, on_value=None, off_value=None, axis=None, dtype=None indices=t depth=5#不能小于t的长度 sess=tf.Session() on_value=1#默认是1,也可以设置为其他值,比如9 off_value=0#默认是0,也可以设置为其他数值,比如2 axis=0

tf.gather用法

tf.gather(params, indices, validate_indices=None, name=None, axis=0) Gather slices from `params` axis `axis` according to `indices`. 从'params'的'axis'维根据'indices'的参数值获取切片。就是在axis维根据indices取某些值。 测试代码: import tensorflow as tf import numpy as np print("\n先测试一维张量\n") t=np.random.randint(1,10,5) g1=tf.gather(t,[2,1,4]) sess=tf.Session() print(t) print(sess.run(g1)) print("\n再测试二维张量\n") t=np.random.randint(1,10,[4,5]) g2=tf.gather(t,[1,2,2],axis=0) g3=tf.gather(t,[1,2,2],axis=1) print(t) print(sess.run(g2)) print(sess.run(g3)) 结果如下: 先测试一维张量 [7 4 7 1 3] [7 4 3] 再测试二维张量 [[5 5 7 4 3] [8 7 6 5 2] [6 9 4 4 8] [7 3 3 2 2]] [[8 7 6 5 2] [6 9 4 4 8] [6 9 4 4 8]] [[5 7 7] [7 6 6] [9 4 4] [3 3 3]]

tf.unstack 用法

看代码: import tensorflow as tf import numpy as np t=np.random.randint(1,10,(3,5)) ustack1=tf.unstack(t,axis=1) ustack2=tf.unstack(t,axis=0) sess=tf.Session() print(t) print(sess.run(ustack1)) print(sess.run(ustack2)) 输出结果如下: [[4 7 3 5 5] [3 5 8 4 1] [2 2 9 8 7]] [array([4, 3, 2]), array([7, 5, 2]), array([3, 8, 9]), array([5, 4, 8]), array([5, 1, 7])] [array([4, 7, 3, 5, 5]), array([3, 5, 8, 4, 1]), array([2, 2, 9, 8, 7])]

tf.concat and stack用法

tf.concat(values, axis, name='concat'):按照指定的已经存在的轴进行拼接 t1 = [[1, 2, 3], [4, 5, 6]] t2 = [[7, 8, 9], [10, 11, 12]] tf.concat([t1, t2], 0)  ==>  [ [1, 2, 3] [4, 5, 6] [7, 8, 9] [10, 11, 12] ] 按照行拼接,多了两行 tf.concat([t1, t2], 1)  ==> [ [1, 2, 3, 7, 8, 9] [4, 5, 6, 10, 11, 12] ] 按照接拼接,多了三列 类似的函数还有一个tf.stack tf.stack(values, axis=0, name='stack'):按照指定的新建的轴进行拼接 tf.concat([t1, t2], 1)  ==> [ [1, 2, 3, 7, 8, 9] [4, 5, 6, 10, 11, 12] ] tf.stack([t1, t2], 0)   ==>  [ [[1, 2, 3], [4, 5, 6]] [[7, 8, 9], [10, 11, 12]] ] 结果是三维矩阵,就0维和1维像堆叠在一起一样 tf.stack([t1, t2], 1)  ==> [[[1, 2, 3], [7, 8, 9]], [[4, 5, 6], [10, 11, 12]]] tf.stack([t1, t2], 2)  ==> [[[1, 7], [2, 8], [3, 9]], [[4, 10], [5, 11], [6, 12]]] 例子参见: https://colab.research.google.com/drive/1MWUJKxqbXHeVmzh3JctTRTNDtBf7WF-4

tf.split用法

按照行或者列分割一个矩阵 第一个参数是待切分的张量,第二个是切分的大小,共切分为三个,每一个分别为4列,15列,11列。第三个参数为1表示按照列切分,为0表示按照行切分。 切分的子块的大小加起来应该等于母块的大小。比如这个例子,4+15+11=30列 看下面的代码例子

tf.slice用法

函数:tf.slice(inputs, begin, size, name) 作用:从列表、数组、张量等对象中抽取一部分数据 begin和size是两个多维列表,他们共同决定了要抽取的数据的开始和结束位置 begin表示从inputs的哪几个维度上的哪个元素开始抽取 ,begin基于下标0开始 size表示在inputs的各个维度上抽取的元素个数 若begin[]或size[]中出现-1,表示抽取对应维度上的所有元素 测试:如下是一个三维Tensor数据表 import tensorflow as tf import numpy as np #这个代码演示测试tf.slice函数 t=[[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]],[[5,5,5],[6,6,6]]] s1=tf.slice(t,[1,0,0],[1,1,3]) #begin=[1,0,0],表明从第1维的[0,0]开始切片,也就是从[3,3,3]开始 #size=[1,1,3]表明切片后是1维,切片的尺寸为1行3列。 s2=tf.slice(t,[0,1,1],[2,1,1]) #begin=[0,1,1],表明从第0维的[1,1]开始切片,也就是从[2,2,2]的第二个2开始 #size=[2,1,1]表明切片后是2维,切片的尺寸为1行1列。 sess=tf.Session() print(sess.run(s1)) #输出结果为 [[[3 3 3]]] ,一行三列 print(sess.run(s2)) #输出结果: [[[2]] [[4]]] #测试维度: print(sess.run(s1).shape) print(sess.run(s2).shape) #结果如下 (1, 1, 3) (2, 1, 1) 下面的立体图说明切片的实际方法: (size的大小不能大于切片刀下方表格数据的尺寸,维度数不能大于被切片数据的维度) 以s2为例

tf.squeeze和tf.expand_dims的用法

import numpy as np import tensorflow as tf a=[[2,2,3,3],[4,5,6,4]] t1=tf.expand_dims(a,0,name="t1") t2=tf.expand_dims(a,1,name="t2") with tf.Session() as sess: print(sess.run(t1).shape) print(sess.run(tf.squeeze(t1,0)).shape) print(sess.run(t2).shape) print(sess.run(tf.squeeze(t2,1)).shape) 输出如下: (1, 2, 4) (2, 4) (2, 1, 4) (2, 4)

Session Run的用法

feed_dict参数的作用是替换图中的某个tensor的值。例如: a = tf.add(2, 5)                        #a=7 b = tf.multiply(a, 3)                 #b=3*7=21 with tf.Session() as sess:     print(sess.run(b))     replace_dict = {a:15}           #用15代替b算式中的a     print(sess.run(b, feed_dict = replace_dict)) --------------------- 输出如下: 21 45

TF random_normal和Python random.normal的用法

先看TF tf.random_normal()函数用于从服从指定正太分布的数值中取出指定个数的值。 tf.random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None) 再看NP np.random.normal()给出均值为loc,标准差为scale的高斯随机数(场). numpy.random.normal(loc=0.0, scale=1.0, size=None) 所谓正态分布==高斯分布,所以二者一回事 mean==loc==均值(或称期待值) stddev==scale==标准差 shape==size==输出形状,二者在处理这个参数时候(a,b)==[a,b],其中,np的normal对参数格式要求更灵活一些。 比如创建随机数的一行两列数组: np.random.normal([2])==np.random.normal((2))==np.random.normal(0,1,2)注意最后一种用法必须带上前面两个参数,否则传递参数时候会把2当作均值传递 而tf的random_normal对shape的要求不能是数字,必须为[]或()格式 再探究一下形状参数的规律,看下面代码 a=np.random.normal(0,1,(2,1)) b=np.random.normal(0,1,(1,2)) c=np.random.normal(0,1,(2)) print(a) print(a.shape) print(b) print(b.shape) print(c) print(c.shape) 程序输出如下 [[ 1.11843359] [-0.69801129]] (2, 1) [[-0.87110089 -0.46089345]] (1, 2) [ 0.88227522 -0.26728542] (2,) a,b是二维的矩阵,c是一维的矩阵(严格说一维的不是矩阵)

TF入门:关于图的我的理解

    TensorFlow以下简称TF,里面很多华丽的新词汇,什么基于数据流图,什么张量等等,而且TF的代码编写方式大大出乎初学者的意料,和我们以前传统的编写代码方式很不同,初学一头雾水。。我先讲一下我理解的概念:     先说什么是图。     先扯远一些,说说编码历史。     最初我们编码需要自己写一个流程图,上面有什么判断循环之类的图形和线条,然后我们按照流程图的思路编写代码。后来随着系统越来越复杂,产生了类的概念,我们像搭积木一样,利用类组建编程。这时候,设计的一个个类是静止的,只有在函数里面引用或者在主函数里面调用,才会运行这些积木。再往后,又将各种类打包,形成类库的概念,此时编程就是模块化编程。我们看到,基本代码在一层层的被封装,看起来变得更容易使用,但是产生的很多新东西需要我们接受,理解并花时间去学习。     我们知道神经网络就是一个个节点,权重关系和激活函数组成的,构成就这么简单,在设计神经网络之前,我们往往要规划网络的节点数,权重等,就像画出网络图一样:     我们编程的时候,就像画图或者设计图一样,先产生一个个的节点或权重变量,这部分代码运行所在空间,就是图,貌似很酷很炫的名字。而数据在节点之间的来回传递,就是数据流。基于这个牵强的图概念和数据的流动,就是所谓的数据流图。     简单说一下什么是张量,有一个炫酷高深的名词。 说白了就是几维的数据。一个数字是标量:0维,两个成对的是向量:1维,一个表格是矩阵:2维,向上还有3维4维的数据,成为n维数据,都可以称为张量,事实上经常将3维以上的称为张量。其实就是数据的一种格式。

神经网络(容易被忽视的基础知识)

神经网络(容易被忽视的基础知识) Evan 180 人赞了该文章 以下大多笔记主要来自cs231n和其他深度学习资料和一些我自己的补充,首先CS231n一个非常不错的deep learning课,值得一看,奉上 链接 ,然后,cs231n本身是有笔记的- 链接 ,最后,知乎上的一些大神对这个笔记进行了翻译--- 链接 。在这里,我主要是将一些重要的笔记,我认为是比较容易被我们忽视的,加上查阅其他博文,做一个笔记和心得总结! 这次主要讲解的内容有: 基本神经元 作为线性分类器的单个神经元 为什么要是深度神经网而不是”肥胖“神经网络? 为什么在人工神经网络中的神经元需要激活函数? 一些主要的激活函数 神经网络中的偏置有什么意义? 初始化神经网络的参数可以全为0吗,其他普通线性分类器呢? 交叉熵损失存在的意义和与平方差损失相比有什么好处? 神经元 下面图表的左边展示了一个生物学的神经元,右边展示了一个常用的数学模型。乍一看还是有点相似的,事实上也是,人工神经网络中的神经元也有受到生物神经元的启发。总结要点: 在生物的神经元(也就是左图)中,树突将信号传递到细胞体,信号在细胞体中相加。如果最终之和高于某个阈值,那么神经元将会 激活 ,向其轴突输出一个峰值信号, 注意这里输出是一个脉冲信号! 在数学计算模型(也就是右图)中,首先将输入 进行加权求和加上偏执 ,得到待激励值,然后将该值作为输入,输入到 激活函数 中,最后输出的是一个 激励后的值 ,这里的激活函数可以看成对生物中神经元的激活率建模。由于历史原因,激活函数常常选择使用 sigmoid函数  , 当然还有很多其他激活函数,下面再仔细聊! 需要注意: 1.一个神经元可以看成 包含两个部分 ,一个是对输入的加权求和加上偏置,一个是激活函数对求和后的激活或者抑制。2.注意生物中的神经元要复杂的多,其中一个是生物中的输出是一个脉冲,而现在大多数的数学模型神经输出的就是一个值,当然现在也有一些脉冲人工神经网络,可以自行了解! 作为线性分类器的单个神经元 比如基础的逻辑回归,结合上面的神经元知识,可以发现,逻辑回归就是激活函数是 sigmoid 的单层简单神经网络。也就是说,只要在神经元的输出端