&y就是得到y的地址,网上反卷积的用法的介绍比

作者: 编程  发布:2019-12-28

voidBT::isCompare(treeNode*Ptr,int*nn){intx,y;if(Ptr==NULL){*nn=0;}else{isCompare(Ptr-leftPtr,x);isCompare(Ptr-rightPtr,y);*nn=1+x+y;if(xy)cout"n当前节点"Ptr-data"的子树中,LNumRNum";}}怎么处理啊?

一.指针

转摘自:

这是一个最常用的容器中的最常用的方法,可是最近在用的时候却出现了问题。下面大家看看这是什么情况吧:

int  *Ptr;      //声明一个整型指针变量

今天来介绍一下Tensorflow里面的反卷积操作,网上反卷积的用法的介绍比较少,希望这篇教程可以帮助到各位

#include "stdafx.h"
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
    string s = "UIPower";
    string s2 = "owe";
    size_t x  = s.find("owe",1);
    size_t y  = s.find(s2,2);
    return 0;
}

int  y=7 ;      //声明一个整型变量并赋值为7

反卷积出自这篇论文:Deconvolutional Networks,有兴趣的同学自行了解

猜猜x,y分别是多少吧,有不少人认为是2,1吧,有没有中枪!反正我开始时这么认为的,但是经过测试发现不对啊,x,y居然都是3,什么情况?

Ptr = &y ;    //&是取地址符号,&y就是得到y的地址,然后将y的地址存储到Ptr的内存空间(将y的地址赋值给Ptr)

首先无论你如何理解反卷积,请时刻记住一点,反卷积操作是卷积的反向

跟踪进去看看find到底是怎么写的,发现下面这段代码

&取地址符号,  *引用指针指向的值

如果你随时都记住上面强调的重点,那你基本就理解一大半了,接下来通过一些函数的介绍为大家强化这个观念

   size_type __CLR_OR_THIS_CALL find(const _Elem *_Ptr,
       size_type _Off, size_type _Count) const
       {   // look for [_Ptr, _Ptr + _Count) beginnng at or after _Off
#if _HAS_ITERATOR_DEBUGGING
       if (_Count != 0)
           _DEBUG_POINTER(_Ptr);
#endif /* _HAS_ITERATOR_DEBUGGING */
       if (_Count == 0 && _Off <= _Mysize)
           return (_Off);  // null string always matches (if inside string)
       size_type _Nm;
       if (_Off < _Mysize && _Count <= (_Nm = _Mysize - _Off))
           {   // room for match, look for it
           const _Elem *_Uptr, *_Vptr;
           for (_Nm -= _Count - 1, _Vptr = _Myptr() + _Off;
               (_Uptr = _Traits::find(_Vptr, _Nm, *_Ptr)) != 0;
               _Nm -= _Uptr - _Vptr + 1, _Vptr = _Uptr + 1)
               if (_Traits::compare(_Uptr, _Ptr, _Count) == 0)
                   return (_Uptr - _Myptr());  // found a match
           }
       return (npos);  // no match
       }

示例

conv2d_transpose(value, filter, output_shape, strides, padding="SAME", data_format="NHWC", name=None)

这是xstring文件中的代码,应该是很底层的东西了这里的_Ptr是要查找的字符串,这里就是"owe"了,_Off是偏移量,也就是从哪个字符开始查找的,这里就是1了,_Count就是要查找的字符串的长度,这里就是3了,程序走到12行,这里的_Mysize就是整个字符串的长度,这里就是7了,这里要对_Count进行一个判断,也就是它的长度不能超过整个字符串的长度减去偏移量的大小,超过了就肯定找不到了,下面15行的循环_Vptr就是偏移后的字符,这里对应的应该是"IPower",_Nm是控制程序循环几次,这里处置设置为4,也就是只能有4种可能,"IPo","Pow","owe","wer",这里这个_Uptr = _Traits::find(_Vptr, _Nm, *_Ptr)) != 0这个函数跟进去看看是这样的:

地址         35         36

除去name参数用以指定该操作的name,与方法有关的一共六个参数:第一个参数value:指需要做反卷积的输入图像,它要求是一个Tensor第二个参数filter:卷积核,它要求是一个Tensor,具有[filter_height, filter_width, out_channels, in_channels]这样的shape,具体含义是[卷积核的高度,卷积核的宽度,卷积核个数,图像通道数]第三个参数output_shape:反卷积操作输出的shape,细心的同学会发现卷积操作是没有这个参数的,那这个参数在这里有什么用呢?下面会解释这个问题第四个参数strides:反卷积时在图像每一维的步长,这是一个一维的向量,长度4第五个参数padding:string类型的量,只能是"SAME","VALID"其中之一,这个值决定了不同的卷积方式第六个参数data_format:string类型的量,'NHWC'和'NCHW'其中之一,这是tensorflow新版本中新加的参数,它说明了value参数的数据格式。'NHWC'指tensorflow标准的数据格式[batch, height, width, in_channels],'NCHW'指Theano的数据格式,[batch, in_channels,height, width],当然默认值是'NHWC'

    static const _Elem *__CLRCALL_OR_CDECL find(_In_count_(_Count) const _Elem *_First, size_t _Count,
        const _Elem& _Ch)
        {   // look for _Ch in [_First, _First + _Count)
//      _DEBUG_POINTER(_First);
        return ((const _Elem *)::memchr(_First, _Ch, _Count));
        }

变量        Ptr          y

开始之前务必了解卷积的过程,参考我的另一篇文章:

这个函数的意思是在_First中找第一个字符_Ch出现的位置,并把包括_Ch在内的总共_Count个字符返回,所以这里返回得到的_Uptr是字符串"ower",对这个_Uptr判断其是否为空,如果为空说明没有找到以字符_Ch开始的字符串,直接跳出for循环,如果找到了就对这个字符串和_Ptr做比较,函数_Traits::compare(_Uptr, _Ptr, _Count)比较_Ptr和_Uptr的前3个字符,这里_Count是要查询的字符串的长度,匹配成功返回_Ptr在_Uptr中首次出现的下标,如果为0就说明正确匹配了,下面看关键的返回值,真心不明白这个_Myptr()函数干了说明,但是貌似没有起到加偏移量的作用,因为最后返回得到的x是3,也就是字符"o"首次出现的下标,所以我在想,这个最后返回的结果是不是应该加上_Off这个开始时候的偏移量!

值            36           7

首先定义一个单通道图和3个卷积核

_Elem *__CLR_OR_THIS_CALL _Myptr()
        {   // determine current pointer to buffer for mutable string
        return (_BUF_SIZE <= _Myres ? _Bx._Ptr : _Bx._Buf);
        }

这里采用简化的说法(计算机中内存地址一般是以16位16进制数表示,例如0x7ffc111e6da0)。

[python]view plaincopy

翻译过来的意思是确定当前的可变的字符串缓冲区的指针,_BUF_SIZE是16,_Myres是15,返回的自然是_Bx._Buf这个字符串指针了,而_Bx._Buf这个字符串就是,最后的return``(_Uptr - _Myptr()); 两个指针做差返回的是两个指针的相对位置差,自然会得到3这样的答案,分析原因,我觉得,可能系统以为_Myptr()返回的会是_Vptr这个指针,但是实际返回的是_Ptr这个指针,这里涉及到缓冲区的操作,不是很清楚里面的具体情况,但是根据实际结果看这里系统确实返回的是_Ptr的地址,所以不奇怪为什么都会是3这个结果了!

此时,运行在内存中的变量由三部分组成,一是地址,二是变量名,三是变量值(可能为空)。

x1 = tf.constant(1.0, shape=[1,3,3,1])

本文出自 “卖萌程序员” 博客,请务必保留此出处

(1) int  *Ptr; 语句声明了一个指针,假设系统将这个变量名Ptr存储在35号地址单元,这时候它还没有值,我们表示成这样。

kernel = tf.constant(1.0, shape=[3,3,3,1])

#include "stdafx.h"#include stri...

变量        Ptr          

先别着急!我们不直接用反卷积函数,而是再定义一些图

地址         35        

[python]view plaincopy

值            

x2 = tf.constant(1.0, shape=[1,6,6,3])

(2)int  y = 7; 这里定义一个值为7的整型变量y,假设系统将这个变量名y和变量值存储在35号地址单元旁边的36号地址单元,示例如下

x3 = tf.constant(1.0, shape=[1,5,5,3])

地址         35         36

x2是6×6的3通道图,x3是5×5的3通道图

变量        Ptr          y

好了,接下来对x3做一次卷积操作

值                          7

[python]view plaincopy

(3)Ptr = &y; 这个语句用&y得到y的存储地址也就是36,然后将36赋值给Ptr,也就是存储到35号地址存放变量值的空间

y2 = tf.nn.conv2d(x3, kernel, strides=[1,2,2,1], padding="SAME")

地址         35         36

所以返回的y2是一个单通道的图,如果你了解卷积过程,很容易看出来y2是[1,3,3,1]的Tensor,y2的结果如下:

变量        Ptr          y

[python]view plaincopy

值            36           7

[[[[12.]

(4)*Ptr为获得Ptr中存储的地址所指向的值,也就是36号地址存放的值

[18.]

       *Ptr -->  36  -->  7          即 *Ptr = 7;            //Ptr存放的是地址36,地址36存放的值是7, *符号在这里获得36存储的值

[12.]]

cout << *Ptr ;  输出为7

[[18.]

cout << Ptr ;   输出为36                    //实际上的地址是类似与这样的 0x7ffeb92a2be4

[27.]

cout << &Ptr ;  输出为它的地址35    //同上,它也是16位16进制

[18.]]

cout << &y ;   输出y的地址36           //同上

[[12.]

二.结构与链表实现

[18.]

[12.]]]]

又一个很重要的部分!tf.nn.conv2d中的filter参数,是[filter_height, filter_width, in_channels, out_channels]的形式,而tf.nn.conv2d_transpose中的filter参数,是[filter_height, filter_width, out_channels,in_channels]的形式,注意in_channels和out_channels反过来了!因为两者互为反向,所以输入输出要调换位置

既然y2是卷积操作的返回值,那我们当然可以对它做反卷积,反卷积操作返回的Tensor,应该和x3的shape是一样的(不难理解,因为是卷积的反过程)

[python]view plaincopy

y3 = tf.nn.conv2d_transpose(y2,kernel,output_shape=[1,5,5,3], strides=[1,2,2,1],padding="SAME")

好,现在返回的y3果然是[1,5,5,3]的Tensor,结果如下:

[python]view plaincopy

[[[[12.12.12.]

[30.30.30.]

[18.18.18.]

[30.30.30.]

[12.12.12.]]

[[30.30.30.]

[75.75.75.]

[45.45.45.]

[75.75.75.]

[30.30.30.]]

[[18.18.18.]

[45.45.45.]

[27.27.27.]

[45.45.45.]

[18.18.18.]]

[[30.30.30.]

[75.75.75.]

[45.45.45.]

[75.75.75.]

[30.30.30.]]

[[12.12.12.]

[30.30.30.]

[18.18.18.]

[30.30.30.]

[12.12.12.]]]]

这个结果是怎么得来的?可以用一张动图来说明,图片来源:反卷积的真正含义

看起来,tf.nn.conv2d_transpose的output_shape似乎是多余的,因为知道了原图,卷积核,步长显然是可以推出输出图像大小的,那为什么要指定output_shape呢?

看这样一种情况:

[python]view plaincopy

y4 = tf.nn.conv2d(x2, kernel, strides=[1,2,2,1], padding="SAME")

我们把上面的x2也做卷积,获得shape为[1,3,3,1]的y4如下:

[python]view plaincopy

[[[[27.]

[27.]

[18.]]

[[27.]

[27.]

[18.]]

[[18.]

[18.]

[12.]]]]

[1,6,6,3]和[1,5,5,3]的图经过卷积得到了相同的大小,[1,3,3,1]

让我们再反过来看,那么[1,3,3,1]的图反卷积后得到什么呢?产生了两种情况。所以这里指定output_shape是有意义的,当然随意指定output_shape是不允许的,如下情况程序会报错:

[python]view plaincopy

y5 = tf.nn.conv2d_transpose(x1,kernel,output_shape=[1,10,10,3],strides=[1,2,2,1],padding="SAME")

以上是stride为2的情况,为1时也类似,当卷积核大于原图时,默认用VALID方式(用SAME就无意义了)参考下图:

程序清单:

[python]view plaincopy

importtensorflow as tf

x1 = tf.constant(1.0, shape=[1,3,3,1])

x2 = tf.constant(1.0, shape=[1,6,6,3])

x3 = tf.constant(1.0, shape=[1,5,5,3])

kernel = tf.constant(1.0, shape=[3,3,3,1])

y1 = tf.nn.conv2d_transpose(x1,kernel,output_shape=[1,6,6,3],

strides=[1,2,2,1],padding="SAME")

y2 = tf.nn.conv2d(x3, kernel, strides=[1,2,2,1], padding="SAME")

y3 = tf.nn.conv2d_transpose(y2,kernel,output_shape=[1,5,5,3],

strides=[1,2,2,1],padding="SAME")

y4 = tf.nn.conv2d(x2, kernel, strides=[1,2,2,1], padding="SAME")

'''''

Wrong!!This is impossible

y5 = tf.nn.conv2d_transpose(x1,kernel,output_shape=[1,10,10,3],strides=[1,2,2,1],padding="SAME")

'''

sess = tf.Session()

tf.global_variables_initializer().run(session=sess)

x1_decov, x3_cov, y2_decov, x2_cov=sess.run([y1,y2,y3,y4])

print(x1_decov.shape)

print(x3_cov.shape)

print(y2_decov.shape)

print(x2_cov.shape)

本文由9159.com发布于编程,转载请注明出处:&y就是得到y的地址,网上反卷积的用法的介绍比

关键词:

上一篇:没有了
下一篇:没有了