Skip to content

Commit cfc965d

Browse files
authored
Merge pull request #269 from wangyang59/deconv
2 parents 8d4c453 + 1c58e27 commit cfc965d

19 files changed

+1203
-338
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ build/
55
.vscode
66
.idea
77
.project
8+
.cproject
89
.pydevproject
10+
Makefile

paddle/gserver/layers/ConvBaseLayer.cpp

Lines changed: 57 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@ limitations under the License. */
1414

1515
#include "paddle/utils/Logging.h"
1616
#include "ConvBaseLayer.h"
17+
#include "paddle/math/MathUtils.h"
1718
namespace paddle {
1819

1920
bool ConvBaseLayer::init(const LayerMap& layerMap,
2021
const ParameterMap& parameterMap) {
2122
/* Initialize the basic parent class */
2223
Layer::init(layerMap, parameterMap);
24+
isDeconv_ = (config_.type() == "exconv" || config_.type() == "cudnn_conv")
25+
? false : true;
2326

2427
/* Initialize the convolutional layer parameter */
2528
numFilters_ = config_.num_filters();
@@ -42,8 +45,20 @@ bool ConvBaseLayer::init(const LayerMap& layerMap,
4245
outputW_.push_back(conf.output_x());
4346
}
4447

48+
CHECK(inputLayers_.size() == parameters_.size());
49+
for (size_t i = 0; i < inputLayers_.size(); i++) {
50+
size_t height, width;
51+
height = filterPixels_[i] * filterChannels_[i];
52+
width = (!isDeconv_) ? numFilters_ : channels_[i];
53+
54+
// create a new weight
55+
CHECK_EQ(parameters_[i]->getSize(), width * height);
56+
Weight* w = new Weight(height, width, parameters_[i]);
57+
weights_.emplace_back(w);
58+
}
59+
4560
/* initialize the biases_ */
46-
if (biasParameter_.get() != NULL) {
61+
if (biasParameter_.get()) {
4762
if (sharedBiases_) {
4863
CHECK_EQ((size_t)numFilters_, biasParameter_->getSize());
4964
biases_ =
@@ -70,23 +85,48 @@ size_t ConvBaseLayer::calOutputSize() {
7085
clearAndReserve(&outputH_);
7186
clearAndReserve(&outputW_);
7287
size_t layerSize = 0;
73-
for (size_t i = 0; i < inputLayers_.size(); i++) {
74-
imgSizeH_.push_back(inputLayers_[i]->getOutput().getFrameHeight());
75-
imgSizeW_.push_back(inputLayers_[i]->getOutput().getFrameWidth());
76-
if (imgSizeH_[i] == 0)
77-
imgSizeH_[i] = config_.inputs(i).conv_conf().img_size();
78-
if (imgSizeW_[i] == 0)
79-
imgSizeW_[i] = config_.inputs(i).conv_conf().img_size();
80-
outputH_.push_back(outputSize(imgSizeH_[i], filterSizeY_[i], paddingY_[i],
81-
strideY_[i], caffeMode_));
82-
outputW_.push_back(outputSize(imgSizeW_[i], filterSize_[i], padding_[i],
83-
stride_[i], caffeMode_));
84-
CHECK_EQ(outputH_[i], outputH_[0]);
85-
CHECK_EQ(outputW_[i], outputW_[0]);
88+
89+
auto setLayerSize = [&](IntV& inH, IntV& inW, IntV& outH, IntV& outW) {
90+
for (size_t i = 0; i < inputLayers_.size(); i++) {
91+
inH.push_back(inputLayers_[i]->getOutput().getFrameHeight());
92+
inW.push_back(inputLayers_[i]->getOutput().getFrameWidth());
93+
if (isDeconv_) {
94+
if (inH[i] == 0)
95+
inH[i] = config_.inputs(i).conv_conf().output_x();
96+
if (inW[i] == 0)
97+
inW[i] = config_.inputs(i).conv_conf().output_x();
98+
outH.push_back(
99+
imageSize(inH[i], filterSizeY_[i], paddingY_[i], strideY_[i],
100+
caffeMode_));
101+
outW.push_back(
102+
imageSize(inW[i], filterSize_[i], padding_[i], stride_[i],
103+
caffeMode_));
104+
} else {
105+
if (inH[i] == 0)
106+
inH[i] = config_.inputs(i).conv_conf().img_size();
107+
if (inW[i] == 0)
108+
inW[i] = config_.inputs(i).conv_conf().img_size();
109+
outH.push_back(
110+
outputSize(inH[i], filterSizeY_[i], paddingY_[i], strideY_[i],
111+
caffeMode_));
112+
outW.push_back(
113+
outputSize(inW[i], filterSize_[i], padding_[i], stride_[i],
114+
caffeMode_));
115+
}
116+
CHECK_EQ(outH[i], outH[0]);
117+
CHECK_EQ(outW[i], outW[0]);
118+
}
119+
getOutput().setFrameHeight(outH[0]);
120+
getOutput().setFrameWidth(outW[0]);
121+
layerSize = outH[0] * outW[0] * size_t(numFilters_);
122+
};
123+
124+
if (isDeconv_) {
125+
setLayerSize(outputH_, outputW_, imgSizeH_, imgSizeW_);
126+
} else {
127+
setLayerSize(imgSizeH_, imgSizeW_, outputH_, outputW_);
86128
}
87-
getOutput().setFrameHeight(outputH_[0]);
88-
getOutput().setFrameWidth(outputW_[0]);
89-
layerSize = outputH_[0] * outputW_[0] * size_t(numFilters_);
129+
90130
return layerSize;
91131
}
92132

paddle/gserver/layers/ConvBaseLayer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ class ConvBaseLayer : public Layer {
2828
protected:
2929
typedef std::vector<int> IntV;
3030

31+
/// True if it's deconv layer, false if it's convolution layer
32+
bool isDeconv_;
33+
3134
/// The number of filters.
3235
int numFilters_;
3336
/// The x dimension of the padding.
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
/* Copyright (c) 2016 Baidu, Inc. All Rights Reserve.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License. */
14+
15+
16+
#include "ExpandConvBaseLayer.h"
17+
18+
#include "paddle/utils/Logging.h"
19+
namespace paddle {
20+
21+
bool ExpandConvBaseLayer::init(const LayerMap &layerMap,
22+
const ParameterMap &parameterMap) {
23+
/* Initialize the basic convolutional parent class */
24+
ConvBaseLayer::init(layerMap, parameterMap);
25+
26+
/* The class fields channels_ and numFilters_ are the same as in the config
27+
* i.e., channels_ is the for the input and numFilters_ is for the output
28+
*
29+
* But in order for the variables in convTrans having the same semantic
30+
* meaning as in conv, we need to swap channels_ and numFilters here for
31+
* convTrans, and in other functions too.
32+
* */
33+
int channel;
34+
int numFilters;
35+
/* Initialize the projection */
36+
for (auto &inputConfig : config_.inputs()) {
37+
const ConvConfig &conf = inputConfig.conv_conf();
38+
numFilters = isDeconv_ ? conf.channels() : numFilters_;
39+
subM_.push_back(numFilters / conf.groups());
40+
subN_.push_back(conf.output_x() * conf.output_x());
41+
channel = isDeconv_ ? numFilters_ : conf.channels();
42+
subK_.push_back(channel * conf.filter_size() * conf.filter_size() /
43+
conf.groups());
44+
/* Consistent caffe mode for multiple input */
45+
caffeMode_ = conf.caffe_mode();
46+
}
47+
48+
getOutputSize();
49+
50+
return true;
51+
}
52+
53+
size_t ExpandConvBaseLayer::getOutputSize() {
54+
CHECK_NE(inputLayers_.size(), 0UL);
55+
size_t layerSize = ConvBaseLayer::calOutputSize();
56+
subN_.clear();
57+
for (size_t i = 0; i < inputLayers_.size(); i++) {
58+
subN_.push_back(outputH_[i] * outputW_[i]);
59+
}
60+
return layerSize;
61+
}
62+
63+
void ExpandConvBaseLayer::resetExpandInput(size_t height, size_t width) {
64+
Matrix::resizeOrCreate(expandInput_, height, width, false, useGpu_);
65+
}
66+
67+
void ExpandConvBaseLayer::addSharedBias() {
68+
size_t mapW = getOutputSize() / numFilters_;
69+
size_t mapH = getOutputValue()->getElementCnt() / mapW;
70+
MatrixPtr out =
71+
Matrix::create(getOutputValue()->getData(), mapH, mapW, false, useGpu_);
72+
73+
Matrix::resizeOrCreate(transOutValue_, mapW, mapH, false, useGpu_);
74+
75+
out->transpose(transOutValue_, false); // false means no memory allocation
76+
transOutValue_->reshape(transOutValue_->getElementCnt() / numFilters_,
77+
numFilters_);
78+
79+
MatrixPtr bias =
80+
Matrix::create(biases_->getW()->getData(), 1,
81+
biases_->getW()->getElementCnt(), false, useGpu_);
82+
transOutValue_->addBias(*bias, 1.0f);
83+
84+
transOutValue_->reshape(mapW, mapH);
85+
transOutValue_->transpose(out, false); // false means no memory allocation
86+
87+
out->clear();
88+
bias->clear();
89+
}
90+
91+
void ExpandConvBaseLayer::addUnsharedBias() {
92+
MatrixPtr outValue = getOutputValue();
93+
MatrixPtr bias =
94+
Matrix::create(biases_->getW()->getData(), 1,
95+
biases_->getW()->getElementCnt(), false, useGpu_);
96+
outValue->addBias(*bias, 1.0f);
97+
}
98+
99+
100+
void ExpandConvBaseLayer::expandOneFrame(MatrixPtr image, size_t startIdx,
101+
int inIdx) {
102+
int channel = isDeconv_ ? numFilters_ : channels_[inIdx];
103+
104+
resetExpandInput(subK_[inIdx] * groups_[inIdx], subN_[inIdx]);
105+
real *imgData = image->getData() + startIdx * image->getWidth();
106+
MatrixPtr imageTmp = Matrix::create(
107+
imgData, 1, imgSizeH_[inIdx] * imgSizeW_[inIdx] * channel, false,
108+
useGpu_);
109+
expandInput_->convExpand(*imageTmp, imgSizeH_[inIdx], imgSizeW_[inIdx],
110+
channel, filterSize_[inIdx],
111+
filterSize_[inIdx], stride_[inIdx], stride_[inIdx],
112+
padding_[inIdx], padding_[inIdx],
113+
outputH_[inIdx], outputW_[inIdx]);
114+
imageTmp->clear();
115+
}
116+
117+
void ExpandConvBaseLayer::expandFwdOnce(MatrixPtr image, MatrixPtr out,
118+
int inIdx, int startIdx) {
119+
int subM = subM_[inIdx];
120+
int subN = subN_[inIdx];
121+
int subK = subK_[inIdx];
122+
123+
expandOneFrame(image, startIdx, inIdx);
124+
125+
int numFilters = isDeconv_ ? channels_[inIdx] : numFilters_;
126+
127+
real *outData =
128+
out->getData() + startIdx * subN * numFilters;
129+
130+
real *wgtData = weights_[inIdx]->getW()->getData();
131+
real *expInData = expandInput_->getData();
132+
for (int g = 0; g < groups_[inIdx]; ++g) {
133+
MatrixPtr A =
134+
Matrix::create(wgtData, subK, subM, true, useGpu_); // mark transpose
135+
MatrixPtr B = Matrix::create(expInData, subK, subN, false, useGpu_);
136+
MatrixPtr C = Matrix::create(outData, subM, subN, false, useGpu_);
137+
C->mul(A, B, 1, 1);
138+
139+
A->clear();
140+
B->clear();
141+
C->clear();
142+
wgtData += subK * subM;
143+
expInData += subK * subN;
144+
outData += subM * subN;
145+
}
146+
}
147+
148+
void ExpandConvBaseLayer::bpropActs(MatrixPtr out, MatrixPtr image,
149+
int inpIdx) {
150+
int channel = isDeconv_ ? numFilters_ : channels_[inpIdx];
151+
152+
int subM = subM_[inpIdx];
153+
int subN = subN_[inpIdx];
154+
int subK = subK_[inpIdx];
155+
size_t batchSize = image->getHeight();
156+
157+
/* reset the expand-grad memory */
158+
resetExpandInput(subK * groups_[inpIdx], subN);
159+
160+
real *localGradData = out->getData();
161+
real *tgtGradData = image->getData();
162+
for (size_t n = 0; n < batchSize; n++) {
163+
real *wgtData = weights_[inpIdx]->getW()->getData();
164+
real *expandInData = expandInput_->getData();
165+
166+
for (int g = 0; g < groups_[inpIdx]; g++) {
167+
// create temporary matrix
168+
MatrixPtr C = Matrix::create(expandInData, subK, subN, false, useGpu_);
169+
MatrixPtr B = Matrix::create(localGradData, subM, subN, false, useGpu_);
170+
MatrixPtr A = Matrix::create(wgtData, subK, subM, false, useGpu_);
171+
C->mul(A, B); // mul
172+
173+
// clear the temporary matrix
174+
A->clear();
175+
B->clear();
176+
C->clear();
177+
178+
expandInData += subK * subN;
179+
localGradData += subM * subN;
180+
wgtData += subK * subM;
181+
}
182+
183+
// shrink one frame outGrad
184+
MatrixPtr oneGradTmp = Matrix::create(
185+
expandInput_->getData(), subK * groups_[inpIdx], subN, false, useGpu_);
186+
MatrixPtr vTmp = Matrix::create(
187+
tgtGradData, 1,
188+
imgSizeH_[inpIdx] * imgSizeW_[inpIdx] * channel, false,
189+
useGpu_);
190+
vTmp->convShrink(*oneGradTmp, imgSizeH_[inpIdx], imgSizeW_[inpIdx],
191+
channel, filterSize_[inpIdx],
192+
filterSize_[inpIdx], stride_[inpIdx], stride_[inpIdx],
193+
padding_[inpIdx], padding_[inpIdx],
194+
outputH_[inpIdx], outputW_[inpIdx], 1.0f, 1.0f);
195+
vTmp->clear();
196+
oneGradTmp->clear();
197+
198+
// move the data-pointer
199+
tgtGradData += imgSizeH_[inpIdx] * imgSizeW_[inpIdx] * channel;
200+
}
201+
}
202+
203+
void ExpandConvBaseLayer::bpropWeights(MatrixPtr image, MatrixPtr out,
204+
int inpIdx) {
205+
MatrixPtr weightGrad = weights_[inpIdx]->getWGrad();
206+
207+
int subM = subM_[inpIdx];
208+
int subN = subN_[inpIdx];
209+
int subK = subK_[inpIdx];
210+
size_t batchSize = image->getHeight();
211+
resetExpandInput(subK * groups_[inpIdx], subN);
212+
213+
real *gradData = out->getData();
214+
215+
for (size_t n = 0; n < batchSize; n++) { // frame by frame
216+
// expand
217+
expandOneFrame(image, n, inpIdx);
218+
real *wGradData = weightGrad->getData();
219+
real *expandInData = expandInput_->getData();
220+
221+
// expand-mul one-group by one
222+
for (int g = 0; g < groups_[inpIdx]; g++) {
223+
MatrixPtr A = Matrix::create(expandInData, subK, subN, false, useGpu_);
224+
MatrixPtr B = Matrix::create(gradData, subM, subN, true, useGpu_);
225+
MatrixPtr C = Matrix::create(wGradData, subK, subM, false, useGpu_);
226+
C->mul(A, B, 1, 1);
227+
228+
A->clear();
229+
B->clear();
230+
C->clear();
231+
gradData += subM * subN;
232+
wGradData += subK * subM;
233+
expandInData += subK * subN;
234+
}
235+
}
236+
}
237+
238+
void ExpandConvBaseLayer::bpropSharedBias(MatrixPtr biases, MatrixPtr v) {
239+
size_t mapW = getOutputSize() / numFilters_;
240+
size_t mapH = v->getElementCnt() / mapW;
241+
MatrixPtr vTmp = Matrix::create(v->getData(), mapH, mapW, false, useGpu_);
242+
243+
Matrix::resizeOrCreate(transOutValue_, mapW, mapH, false, useGpu_);
244+
245+
vTmp->transpose(transOutValue_, false); // false means no memory allocation
246+
transOutValue_->reshape(transOutValue_->getElementCnt() / numFilters_,
247+
numFilters_);
248+
biases->collectBias(*transOutValue_, 1.0f);
249+
}
250+
251+
void ExpandConvBaseLayer::bpropBiases(MatrixPtr v) {
252+
MatrixPtr biases =
253+
Matrix::create(biases_->getWGrad()->getData(), 1,
254+
biases_->getWGrad()->getElementCnt(), false, useGpu_);
255+
if (sharedBiases_) {
256+
bpropSharedBias(biases, v);
257+
} else {
258+
biases->collectBias(*v, 1.0f);
259+
}
260+
biases->clear();
261+
}
262+
263+
} // namespace paddle

0 commit comments

Comments
 (0)