Skip to content

Commit 7ff9764

Browse files
author
gaoyuan
committed
smooth_l1_loss_layer
1 parent 515543a commit 7ff9764

File tree

5 files changed

+156
-0
lines changed

5 files changed

+156
-0
lines changed

paddle/gserver/layers/CostLayer.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,65 @@ void SumOfSquaresCostLayer::backwardImp(Matrix& output,
192192
outputG.sumOfSquaresBp(output, *label.value);
193193
}
194194

195+
//
196+
// class SmoothL1CostLayer
197+
//
198+
199+
REGISTER_LAYER(smooth_l1, SmoothL1CostLayer);
200+
201+
bool SmoothL1CostLayer::init(const LayerMap& layerMap,
202+
const ParameterMap& parameterMap) {
203+
return CostLayer::init(layerMap, parameterMap);
204+
}
205+
206+
void SmoothL1CostLayer::forwardImp(Matrix& output,
207+
Argument& label,
208+
Matrix& target) {
209+
MatrixPtr targetCpu, labelCpu, outputCpu;
210+
if (useGpu_) {
211+
Matrix::resizeOrCreate(
212+
targetCpu, target.getHeight(), target.getWidth(), false, false);
213+
Matrix::resizeOrCreate(
214+
outputCpu, output.getHeight(), output.getWidth(), false, false);
215+
Matrix::resizeOrCreate(labelCpu,
216+
label.value->getHeight(),
217+
label.value->getWidth(),
218+
false,
219+
false);
220+
targetCpu->copyFrom(target);
221+
outputCpu->copyFrom(output);
222+
labelCpu->copyFrom(*label.value);
223+
targetCpu->smoothL1(*outputCpu, *(labelCpu));
224+
target.copyFrom(*targetCpu);
225+
} else {
226+
target.smoothL1(output, *label.value);
227+
}
228+
}
229+
230+
void SmoothL1CostLayer::backwardImp(Matrix& output,
231+
Argument& label,
232+
Matrix& outputG) {
233+
MatrixPtr outputGCpu, labelCpu, outputCpu;
234+
if (useGpu_) {
235+
Matrix::resizeOrCreate(
236+
outputGCpu, outputG.getHeight(), outputG.getWidth(), false, false);
237+
Matrix::resizeOrCreate(
238+
outputCpu, output.getHeight(), output.getWidth(), false, false);
239+
Matrix::resizeOrCreate(labelCpu,
240+
label.value->getHeight(),
241+
label.value->getWidth(),
242+
false,
243+
false);
244+
outputGCpu->copyFrom(outputG);
245+
outputCpu->copyFrom(output);
246+
labelCpu->copyFrom(*label.value);
247+
outputGCpu->smoothL1Bp(*outputCpu, *labelCpu);
248+
outputG.copyFrom(*outputGCpu);
249+
} else {
250+
outputG.smoothL1Bp(output, *label.value);
251+
}
252+
}
253+
195254
//
196255
// class RankingCost
197256
//

paddle/gserver/layers/CostLayer.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,29 @@ class SumOfSquaresCostLayer : public CostLayer {
159159
Matrix& outputGrad) override;
160160
};
161161

162+
/**
163+
* This cost layer compute smooth L1 loss for real-valued regression
164+
* tasks.
165+
* \f[
166+
* L =
167+
* y / -1 < y < 1 /
168+
* sign(y) / otherwise /
169+
* \f]
170+
*/
171+
class SmoothL1CostLayer : public CostLayer {
172+
public:
173+
explicit SmoothL1CostLayer(const LayerConfig& config) : CostLayer(config) {}
174+
175+
bool init(const LayerMap& layerMap,
176+
const ParameterMap& parameterMap) override;
177+
178+
void forwardImp(Matrix& output, Argument& label, Matrix& cost) override;
179+
180+
void backwardImp(Matrix& outputValue,
181+
Argument& label,
182+
Matrix& outputGrad) override;
183+
};
184+
162185
/**
163186
* A cost layer for learning to rank (LTR) task. This layer contains at leat
164187
* three inputs.

paddle/gserver/tests/test_LayerGrad.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,6 +1623,20 @@ TEST(Layer, PadLayer) {
16231623
}
16241624
}
16251625

1626+
TEST(Layer, smooth_l1) {
1627+
TestConfig config;
1628+
config.layerConfig.set_type("smooth_l1");
1629+
1630+
config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0});
1631+
config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_1", 1, 0});
1632+
config.layerConfig.add_inputs();
1633+
config.layerConfig.add_inputs();
1634+
1635+
for (auto useGpu : {false, true}) {
1636+
testLayerGrad(config, "smooth_l1", 100, false, useGpu, false, 2.0);
1637+
}
1638+
}
1639+
16261640
int main(int argc, char** argv) {
16271641
testing::InitGoogleTest(&argc, argv);
16281642
initMain(argc, argv);

paddle/math/Matrix.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3590,6 +3590,55 @@ void CpuMatrix::sumOfSquaresBp(Matrix& output, Matrix& label) {
35903590
}
35913591
}
35923592

3593+
void CpuMatrix::smoothL1(Matrix& output, Matrix& label) {
3594+
CHECK(output.useGpu_ == false && label.useGpu_ == false)
3595+
<< "Matrix type are not equal";
3596+
3597+
size_t numSamples = getHeight();
3598+
size_t dim = output.getWidth();
3599+
CHECK_EQ(label.getHeight(), numSamples);
3600+
CHECK_EQ(output.getHeight(), numSamples);
3601+
CHECK_EQ(label.getWidth(), dim);
3602+
CHECK_EQ(getWidth(), (size_t)1);
3603+
real* out = output.getData();
3604+
real* cost = getData();
3605+
real* lbl = label.getData();
3606+
3607+
for (size_t i = 0; i < numSamples; ++i, out += dim, cost += dim, lbl += dim) {
3608+
for (size_t j = 0; j < dim; ++j) {
3609+
cost[j] = std::fabs(out[j] - lbl[j]);
3610+
if (cost[j] < 1.0)
3611+
cost[j] = 0.5 * cost[j] * cost[j];
3612+
else
3613+
cost[j] = cost[j] - 0.5;
3614+
}
3615+
}
3616+
}
3617+
3618+
void CpuMatrix::smoothL1Bp(Matrix& output, Matrix& label) {
3619+
CHECK(output.useGpu_ == false && label.useGpu_ == false)
3620+
<< "Matrix type are not equal";
3621+
3622+
size_t numSamples = getHeight();
3623+
size_t dim = output.getWidth();
3624+
CHECK_EQ(label.getHeight(), numSamples);
3625+
CHECK_EQ(output.getHeight(), numSamples);
3626+
CHECK_EQ(label.getWidth(), dim);
3627+
CHECK_EQ(getWidth(), (size_t)1);
3628+
real* out = output.getData();
3629+
real* cost = getData();
3630+
real* lbl = label.getData();
3631+
3632+
// f'(x) = x if |x| < 1
3633+
// = sign(x) otherwise
3634+
for (size_t i = 0; i < numSamples; ++i, out += dim, cost += dim, lbl += dim) {
3635+
for (size_t j = 0; j < dim; ++j) {
3636+
cost[j] = out[j] - lbl[j];
3637+
if (std::fabs(cost[j]) >= 1) cost[j] = (0 < cost[j]) - (cost[j] < 0);
3638+
}
3639+
}
3640+
}
3641+
35933642
void CpuMatrix::tanh(Matrix& output) {
35943643
CHECK(isContiguous());
35953644
CHECK(output.isContiguous());

paddle/math/Matrix.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,14 @@ class Matrix : public BaseMatrix {
783783
LOG(FATAL) << "Not implemented";
784784
}
785785

786+
virtual void smoothL1(Matrix& output, Matrix& label) {
787+
LOG(FATAL) << "Not implemented";
788+
}
789+
790+
virtual void smoothL1Bp(Matrix& outputV, Matrix& label) {
791+
LOG(FATAL) << "Not implemented";
792+
}
793+
786794
virtual void tanh(Matrix& output) { LOG(FATAL) << "Not implemented"; }
787795

788796
virtual void tanhDerivative(Matrix& output) {
@@ -1720,6 +1728,9 @@ class CpuMatrix : public Matrix {
17201728
/// gradient of sumOfSquares.
17211729
void sumOfSquaresBp(Matrix& outputV, Matrix& label);
17221730

1731+
void smoothL1(Matrix& output, Matrix& label);
1732+
void smoothL1Bp(Matrix& output, Matrix& label);
1733+
17231734
void tanh(Matrix& output);
17241735
void tanhDerivative(Matrix& output);
17251736

0 commit comments

Comments
 (0)