Class: Chainer::Functions::Connection::Deconvolution2DFunction
- Inherits:
-
Chainer::FunctionNode
- Object
- Chainer::FunctionNode
- Chainer::Functions::Connection::Deconvolution2DFunction
- Defined in:
- lib/chainer/functions/connection/deconvolution_2d.rb
Instance Attribute Summary collapse
-
#cover_all ⇒ Object
readonly
Returns the value of attribute cover_all.
-
#ph ⇒ Object
readonly
Returns the value of attribute ph.
-
#pw ⇒ Object
readonly
Returns the value of attribute pw.
-
#sx ⇒ Object
readonly
Returns the value of attribute sx.
-
#sy ⇒ Object
readonly
Returns the value of attribute sy.
Attributes inherited from Chainer::FunctionNode
Class Method Summary collapse
-
.deconvolution_2d(x, w, b: nil, stride: 1, pad: 0, outsize: nil) ⇒ Chainer::Variable
Two dimensional deconvolution function.
Instance Method Summary collapse
- #backward(indexes, grad_outputs) ⇒ Object
- #forward(inputs) ⇒ Object
-
#initialize(stride: 1, pad: 0, outsize: nil) ⇒ Deconvolution2DFunction
constructor
A new instance of Deconvolution2DFunction.
Methods inherited from Chainer::FunctionNode
#apply, #backward_accumulate, #forward_cpu, #get_retained_inputs, #get_retained_outputs, #label, #output_data, #retain_inputs, #retain_outputs, #unchain
Constructor Details
#initialize(stride: 1, pad: 0, outsize: nil) ⇒ Deconvolution2DFunction
Returns a new instance of Deconvolution2DFunction.
75 76 77 78 79 80 81 |
# File 'lib/chainer/functions/connection/deconvolution_2d.rb', line 75 def initialize(stride: 1, pad: 0, outsize: nil) @cover_all = nil @sy, @sx = stride.is_a?(::Array) ? stride : [stride, stride] @ph, @pw = pad.is_a?(::Array) ? pad : [pad, pad] @outh, @outw = outsize.nil? ? [nil, nil] : outsize end |
Instance Attribute Details
#cover_all ⇒ Object (readonly)
Returns the value of attribute cover_all.
5 6 7 |
# File 'lib/chainer/functions/connection/deconvolution_2d.rb', line 5 def cover_all @cover_all end |
#ph ⇒ Object (readonly)
Returns the value of attribute ph.
5 6 7 |
# File 'lib/chainer/functions/connection/deconvolution_2d.rb', line 5 def ph @ph end |
#pw ⇒ Object (readonly)
Returns the value of attribute pw.
5 6 7 |
# File 'lib/chainer/functions/connection/deconvolution_2d.rb', line 5 def pw @pw end |
#sx ⇒ Object (readonly)
Returns the value of attribute sx.
5 6 7 |
# File 'lib/chainer/functions/connection/deconvolution_2d.rb', line 5 def sx @sx end |
#sy ⇒ Object (readonly)
Returns the value of attribute sy.
5 6 7 |
# File 'lib/chainer/functions/connection/deconvolution_2d.rb', line 5 def sy @sy end |
Class Method Details
.deconvolution_2d(x, w, b: nil, stride: 1, pad: 0, outsize: nil) ⇒ Chainer::Variable
Two dimensional deconvolution function.
This is an implementation of two-dimensional deconvolution. In most of deep learning frameworks and papers, this function is called transposed convolution. But because of historical reasons (e.g. paper by Ziller Deconvolutional Networks) and backward compatibility, this function is called deconvolution
in Chainer.
It takes three variables: input image x
, the filter weight W
, and the bias vector b
.
-
$n$ is the batch size.
-
$c_I$ and $c_O$ are the number of the input and output channels, respectively.
-
$h_I$ and $w_I$ are the height and width of the input image, respectively.
-
$h_K$ and $w_K$ are the height and width of the filters, respectively.
-
$h_P$ and $w_P$ are the height and width of the spatial padding size, respectively.
Let $(s_Y, s_X)$ be the stride of filter application. Then, the output size $(h_O, w_O)$ is estimated by the following equations:
$ h_O &= s_Y (h_I - 1) + h_K - 2h_P, w_O &= s_X (w_I - 1) + w_K - 2w_P. $
Example > n = 10 > c_i, c_o = 1, 3 > h_i, w_i = 5, 10 > h_k, w_k = 10, 10 > h_p, w_p = 5, 5 > x = Numo::DFloat.new(n, c_i, h_i, w_i).rand > x.shape
> [10, 1, 5, 10]
> w = Numo::DFloat.new(c_i, c_o, h_k, w_k).rand > w.shape
> [1, 3, 10, 10]
> b = Numo::DFloat.new(c_o).rand > b.shape
> [3]
> s_y, s_x = 5, 5 > y = Chainer::Functions::Connection::Deconvolution2DFunction.deconvolution_2d(x, w, b: b, stride: [s_y, s_x], pad: [h_p, w_p]) > y.shape
> [10, 3, 20, 45]
> h_o = s_y * (h_i - 1) + h_k - 2 * h_p > w_o = s_x * (w_i - 1) + w_k - 2 * w_p > y.shape == [n, c_o, h_o, w_o]
> true
65 66 67 68 69 70 71 72 73 |
# File 'lib/chainer/functions/connection/deconvolution_2d.rb', line 65 def self.deconvolution_2d(x, w, b: nil, stride: 1, pad: 0, outsize: nil) func = Deconvolution2DFunction.new(stride: stride, pad: pad, outsize: outsize) if b.nil? args = x, w else args = x, w, b end func.apply(args).first end |
Instance Method Details
#backward(indexes, grad_outputs) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/chainer/functions/connection/deconvolution_2d.rb', line 122 def backward(indexes, grad_outputs) x, w = get_retained_inputs gy = grad_outputs.first ret = [] if indexes.include?(0) set_cover_all(x, w) if @cover_all.nil? gw = Chainer::Functions::Connection::Convolution2DFunction.convolution_2d(gy, w, stride: [@sy, @sx], pad: [@ph, @pw], cover_all: @cover_all) ret << gw end if indexes.include?(1) set_cover_all(x, w) if @cover_all.nil? gw = Chainer::Functions::Connection::Convolution2DGradW.new(self).apply([gy, x]).first ret << gw end if indexes.include?(2) gb = Chainer::Functions::Math::Sum.sum(gy, axis: [0, 2, 3]) ret << gb end ret end |
#forward(inputs) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/chainer/functions/connection/deconvolution_2d.rb', line 83 def forward(inputs) retain_inputs([0, 1]) x, w = inputs[0...2] b = inputs.size == 3 ? inputs[2] : nil unless inputs.all? { |i| i.is_a?(Numo::NArray) } if b.nil? raise TypeError, "Numo::NArray must not be used together w: #{w.class}, x: #{x.class}" else raise TypeError, "Numo::NArray must not be used together w: #{w.class}, x: #{x.class}, b: #{b.class}" end end kh, kw = w.shape[2..-1] _, _, x_h, x_w = x.shape gcol = Chainer::Utils::Math.tensordot(w, x, [0, 1]).cast_to(x.class) # - k, m, n: shape of out_channel # - b: number of inputs # - h, w: height and width of kernels # k, m, n, b, h, w -> b, k, m, n, h, w gcol = gcol.transpose(3, 0, 1, 2, 4, 5) if @outh.nil? @outh = Chainer::Utils::Conv.get_deconv_outsize(x_h, kh, @sy, @ph) raise TypeError, 'Height in the output should be positive.' if @outh <= 0 end if @outw.nil? @outw = Chainer::Utils::Conv.get_deconv_outsize(x_w, kw, @sx, @pw) raise TypeError, 'Width in the output should be positive.' if @outw <= 0 end y = Chainer::Utils::Conv.col2im(gcol, @sy, @sx, @ph, @pw, @outh, @outw) if !b.nil? y += b.reshape(1, b.size, 1, 1) end [y] end |