Skip to content

Commit aa25071

Browse files
author
ranqiu
committed
add dot_prod_layer
1 parent 08bc08d commit aa25071

File tree

4 files changed

+160
-0
lines changed

4 files changed

+160
-0
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/* Copyright (c) 2016 PaddlePaddle Authors. 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+
#include "Layer.h"
16+
#include "paddle/math/Matrix.h"
17+
#include "paddle/utils/Logging.h"
18+
#include "paddle/utils/Stat.h"
19+
20+
namespace paddle {
21+
22+
/**
23+
* @brief A layer for computing the dot product of two vectors
24+
* Input1: vector (batchSize * dim)
25+
* Input2: vector (batchSize * dim)
26+
* Output: a matrix: (batchSize * 1)
27+
*/
28+
29+
class DotProdLayer : public Layer {
30+
public:
31+
explicit DotProdLayer(const LayerConfig& config) : Layer(config) {}
32+
33+
~DotProdLayer() {}
34+
35+
bool init(const LayerMap& layerMap,
36+
const ParameterMap& parameterMap) override;
37+
38+
void forward(PassType passType) override;
39+
void backward(const UpdateCallback& callback = nullptr) override;
40+
};
41+
42+
REGISTER_LAYER(dot_prod, DotProdLayer);
43+
44+
bool DotProdLayer::init(const LayerMap& layerMap,
45+
const ParameterMap& parameterMap) {
46+
Layer::init(layerMap, parameterMap);
47+
48+
CHECK_EQ(inputLayers_.size(), 2U);
49+
CHECK_EQ(1, getSize()) << "Dimension mismatch";
50+
51+
return true;
52+
}
53+
54+
void DotProdLayer::forward(PassType passType) {
55+
Layer::forward(passType);
56+
57+
MatrixPtr inV0 = getInputValue(0);
58+
MatrixPtr inV1 = getInputValue(1);
59+
60+
size_t batchSize = inV0->getHeight();
61+
CHECK_EQ(inV1->getHeight(), batchSize);
62+
63+
{
64+
REGISTER_TIMER_INFO("FwResetTimer", getName().c_str());
65+
reserveOutput(batchSize, 1);
66+
}
67+
68+
MatrixPtr outV = getOutputValue();
69+
{
70+
REGISTER_TIMER_INFO("FwDotProdTimer", getName().c_str());
71+
outV->sumOfProducts(*inV0, *inV1, 1, 0);
72+
}
73+
}
74+
75+
void DotProdLayer::backward(const UpdateCallback& callback) {
76+
MatrixPtr inV0 = getInputValue(0);
77+
MatrixPtr inV1 = getInputValue(1);
78+
MatrixPtr outG = getOutputGrad();
79+
MatrixPtr inG0 = getInputGrad(0);
80+
MatrixPtr inG1 = getInputGrad(1);
81+
82+
{
83+
REGISTER_TIMER_INFO("BwDotProdTimer", getName().c_str());
84+
85+
if (inG0) {
86+
inG0->addRowScale(0, *inV1, *outG);
87+
}
88+
89+
if (inG1) {
90+
inG1->addRowScale(0, *inV0, *outG);
91+
}
92+
}
93+
}
94+
95+
} // namespace paddle

paddle/gserver/tests/test_LayerGrad.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,21 @@ TEST(Layer, InterpolationLayer) {
10811081
}
10821082
}
10831083

1084+
TEST(Layer, DotProdLayer) {
1085+
TestConfig config;
1086+
config.layerConfig.set_type("dot_prod");
1087+
config.layerConfig.set_size(1);
1088+
1089+
config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0});
1090+
config.layerConfig.add_inputs();
1091+
config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0});
1092+
config.layerConfig.add_inputs();
1093+
1094+
for (auto useGpu : {false, true}) {
1095+
testLayerGrad(config, "dot_prod", 100, false, useGpu);
1096+
}
1097+
}
1098+
10841099
TEST(Layer, OuterProdLayer) {
10851100
TestConfig config;
10861101
config.layerConfig.set_type("out_prod");

python/paddle/trainer/config_parser.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3209,6 +3209,15 @@ def __init__(self, name, inputs, selected_indices, bias=False, **xargs):
32093209
self.set_layer_size(size)
32103210

32113211

3212+
@config_layer('dot_prod')
3213+
class DotProdLayer(LayerBase):
3214+
def __init__(self, name, inputs, device=None):
3215+
super(DotProdLayer, self).__init__(
3216+
name, 'dot_prod', 0, inputs, device=device)
3217+
config_assert(len(inputs) == 2, 'DotProdLayer must have 2 inputs')
3218+
self.set_layer_size(1)
3219+
3220+
32123221
@config_layer('out_prod')
32133222
class OuterProdLayer(LayerBase):
32143223
def __init__(self, name, inputs, device=None):

python/paddle/trainer_config_helpers/layers.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
'huber_classification_cost',
116116
'block_expand_layer',
117117
'maxout_layer',
118+
'dot_prod_layer',
118119
'out_prod_layer',
119120
'printer_layer',
120121
'print_layer',
@@ -197,6 +198,7 @@ class LayerType(object):
197198
SCALING_LAYER = 'scaling'
198199
TRANS_LAYER = 'trans'
199200
ROTATE_LAYER = 'rotate'
201+
DOT_PROD_LAYER = 'dot_prod'
200202
OUT_PROD_LAYER = 'out_prod'
201203
FEATURE_MAP_EXPAND_LAYER = 'featmap_expand'
202204

@@ -4140,6 +4142,45 @@ def maxid_layer(input, name=None, layer_attr=None):
41404142
size=l.config.size)
41414143

41424144

4145+
@wrap_name_default()
4146+
def dot_prod_layer(input1, input2, name=None, layer_attr=None):
4147+
"""
4148+
A layer for computing the dot product of two vectors.
4149+
4150+
The example usage is:
4151+
4152+
.. code-block:: python
4153+
4154+
dot_prod = dot_prod_layer(input1=vec1, input2=vec2)
4155+
4156+
:param name: The name of this layer. It is optional.
4157+
:type name: basestring
4158+
:param input1: The first input layer.
4159+
:type input: LayerOutput
4160+
:param input2: The second input layer.
4161+
:type input2: LayerOutput
4162+
:param layer_attr: The extra layer attribute. See ExtraLayerAttribute for
4163+
details.
4164+
:type layer_attr: ExtraLayerAttribute.
4165+
:return: LayerOutput object.
4166+
:rtype: LayerOutput
4167+
"""
4168+
assert isinstance(input1, LayerOutput)
4169+
assert isinstance(input2, LayerOutput)
4170+
assert input1.size == input2.size, ("Two inputs should have the same size.")
4171+
4172+
l = Layer(
4173+
name=name,
4174+
type=LayerType.DOT_PROD_LAYER,
4175+
inputs=[input1.name, input2.name],
4176+
**ExtraLayerAttribute.to_kwargs(layer_attr))
4177+
return LayerOutput(
4178+
name=name,
4179+
layer_type=LayerType.DOT_PROD_LAYER,
4180+
parents=[input1, input2],
4181+
size=l.config.size)
4182+
4183+
41434184
@wrap_name_default()
41444185
def out_prod_layer(input1, input2, name=None, layer_attr=None):
41454186
"""

0 commit comments

Comments
 (0)