亲宝软件园·资讯

展开

终于明白tf.reduce_sum()函数和tf.reduce_mean()函数用法

不想秃顶还想当程序猿 人气:0

解读tf.reduce_sum()函数和tf.reduce_mean()函数

在学习搭建神经网络的时候,照着敲别人的代码,有一句代码一直搞不清楚,就是下面这句了

loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction), reduction_indices=[1]))

刚开始照着up主写的代码是这样滴:

loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction)))

然后就出现了这样的结果:

709758.1
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan

怎么肥事,对于萌新小白首先想到的就是找度娘,结果找到的方法都不行,然后开始查函数,终于发现了原因,问题就出在reduce_sum()函数上,哈哈哈,然后小白又叕叕叕开始找博客学习reduce_sum()顺带学下reduce_mean(),结果看了好几篇,还是脑袋一片浆糊,为啥用reduction_indices=[1],不用reduction_indices=[0]或者干脆不用,费了九牛二虎之力终于让我给弄懂了,赶紧记录下来!!

-------------------分割线-------------------

1.tf.reduce_mean 函数

用于计算张量tensor沿着指定的数轴(tensor的某一维度)上的的平均值,主要用作降维或者计算tensor(图像)的平均值。

reduce_mean(input_tensor,
                axis=None,
                keep_dims=False,
                name=None,
                reduction_indices=None)

2.tf.reduce_sum函数

计算一个张量的各个维度上元素的总和,一般只需设置两个参数

reduce_sum ( 
    input_tensor , 
    axis = None , 
    keep_dims = False , 
    name = None , 
    reduction_indices = None
 )

最难的就是维度问题,反正本小白看了好几个博客都没弄太懂,最后还是按自己的理解,直接上例子

tf.reduce_sum
matrix1 = [[1.,2.,3.],            #二维,元素为列表
          [4.,5.,6.]]
matrix2 = [[[1.,2.],[3.,4.]],      #三维,元素为矩阵
           [[5.,6.],[7.,8.]]]

res_2 = tf.reduce_sum(matrix1)
res_3 = tf.reduce_sum(matrix2)
res1_2 = tf.reduce_sum(matrix1,reduction_indices=[0])
res1_3 = tf.reduce_sum(matrix2,reduction_indices=[0])
res2_2 = tf.reduce_sum(matrix1,reduction_indices=[1])
res2_3 = tf.reduce_sum(matrix2,reduction_indices=[1])

sess = tf.Session()
print("reduction_indices=None:res_2={},res_3={}".format(sess.run(res_2),sess.run(res_3)))
print("reduction_indices=[0]:res1_2={},res1_3={}".format(sess.run(res1_2),sess.run(res1_3)))
print("reduction_indices=[1]:res2_2={},res2_3={}".format(sess.run(res2_2),sess.run(res2_3)))

结果如下:

axis=None:res_2=21.0,res_3=36.0
axis=[0]:res1_2=[5. 7. 9.],res1_3=[[ 6.  8.]
                                    [10. 12.]]
axis=[1]:res2_2=[ 6. 15.],res2_3=[[ 4.  6.]
                                   [12. 14.]]

只需要把上面代码的reduce_sum部分换成renduce_mean即可

res_2 = tf.reduce_mean(matrix1)
res_3 = tf.reduce_mean(matrix2)
res1_2 = tf.reduce_mean(matrix1,axis=[0])
res1_3 = tf.reduce_mean(matrix2,axis=[0])
res2_2 = tf.reduce_mean(matrix1,axis=[1])
res2_3 = tf.reduce_mean(matrix2,axis=[1])

结果如下:

axis=None:res_2=3.5,res_3=4.5
axis=[0]:res1_2=[2.5 3.5 4.5],res1_3=[[3. 4.]
                                       [5. 6.]]
axis=[1]:res2_2=[2. 5.],res2_3=[[2. 3.]
                                 [6. 7.]]

可以看到,reduction_indices和axis其实都是代表维度,当为None时,reduce_sum和reduce_mean对所有元素进行操作,当为[0]时,其实就是按行操作,当为[1]时,就是按列操作,对于三维情况,把最里面的括号当成是一个数,这样就可以用二维的情况代替,最后得到的结果都是在原来的基础上降一维,下面按专业的方法讲解:

对于一个多维的array,最外层的括号里的元素的axis为0,然后每减一层括号,axis就加1,直到最后的元素为单个数字

如上例中的matrix1 = [[1., 2., 3.], [4., 5., 6.]]:

所以当reduction_indices/axis=[0],应对axis=0上的元素进行操作,故reduce_sum()得到的结果为[5. 7. 9.],即把两个数组对应元素相加;当reduction_indices/axis=[1],应对axis=1上的元素进行操作,故reduce_sum()得到的结果为[ 6. 15.],即把每个数组里的元素相加。reduce_mean()同理。

不难看出对于三维情况也是同样的思路,如上例中的matrix2 = [[[1,2],[3,4]], [[5,6],[7,8]]]:

当reduction_indices/axis=[0],reduce_sum()得到的结果应为[[ 6. 8.], [10. 12.]],即把两个矩阵对应位置元素相加;当reduction_indices/axis=[1],reduce_sum()得到的结果应为[[ 4. 6.], [12. 14.]],即把数组对应元素相加。reduce_mean()同理。

一句话就是对哪一维操作,计算完后外面的括号就去掉,相当于降维。

那么问题来了,当reduction_indices/axis=[2]时呢???

ValueError: Invalid reduction dimension 2 for input with 2 dimensions. for 'Sum_4' (op: 'Sum') with input shapes: [2,3], [1] and with computed input tensors: input[1] = <2>.

-------------------分割线-------------------

回到最开始自己的问题,为什么只有设置参数reduction_indices=[1],loss才不为Nan

loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction),reduction_indices=[1]))

本程序构建的是一个3层神经网络,输入层只有1个神经元,输入数据为100个样本点,即shape为(100,1)的列向量,隐藏层有10个神经元,输出层同样只有1个神经元,故最后输出数据的shape也为(100,1)的列向量,那么reduce_sum的参数即为一个二维数组。

那么再使用reduce_mean()求平均时,想要得到的结果是sum/100,这时就只有reduce_sum()传入参数reduction_indices=[1],才能实现想要的效果了。

完美解决!!!

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

加载全部内容

相关教程
猜你喜欢
用户评论