提交 7eedca16 编写于 作者: L liaogang

Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into SWIG_COMPILER

...@@ -4,6 +4,7 @@ cache: ...@@ -4,6 +4,7 @@ cache:
- $HOME/third_party - $HOME/third_party
- $HOME/.ccache - $HOME/.ccache
- $HOME/.cache/pip - $HOME/.cache/pip
- $HOME/Library/Caches/Homebrew
sudo: required sudo: required
dist: trusty dist: trusty
os: os:
...@@ -54,7 +55,9 @@ before_install: ...@@ -54,7 +55,9 @@ before_install:
fi fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then paddle/scripts/travis/before_install.osx.sh; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then paddle/scripts/travis/before_install.osx.sh; fi
- if [[ "$JOB" == "PRE_COMMIT" ]]; then sudo ln -s /usr/bin/clang-format-3.8 /usr/bin/clang-format; fi - if [[ "$JOB" == "PRE_COMMIT" ]]; then sudo ln -s /usr/bin/clang-format-3.8 /usr/bin/clang-format; fi
- pip install numpy wheel protobuf sphinx recommonmark sphinx_rtd_theme virtualenv pre-commit requests==2.9.2 LinkChecker # Paddle is using protobuf 3.1 currently. Protobuf 3.2 breaks the compatibility. So we specify the python
# protobuf version.
- pip install numpy wheel 'protobuf==3.1' sphinx recommonmark sphinx_rtd_theme virtualenv pre-commit requests==2.9.2 LinkChecker
script: script:
- paddle/scripts/travis/main.sh - paddle/scripts/travis/main.sh
notifications: notifications:
......
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
set(CBLAS_FOUND OFF) set(CBLAS_FOUND OFF)
## Find MKL First. ## Find MKL First.
set(MKL_ROOT $ENV{MKLROOT} CACHE PATH "Folder contains MKL") set(INTEL_ROOT "/opt/intel" CACHE PATH "Folder contains intel libs")
set(MKL_ROOT ${INTEL_ROOT}/mkl CACHE PATH "Folder contains MKL")
find_path(MKL_INCLUDE_DIR mkl.h PATHS find_path(MKL_INCLUDE_DIR mkl.h PATHS
${MKL_ROOT}/include) ${MKL_ROOT}/include)
......
...@@ -6,25 +6,15 @@ passed to C++ side of Paddle. ...@@ -6,25 +6,15 @@ passed to C++ side of Paddle.
The user api could be simpler and carefully designed. The user api could be simpler and carefully designed.
""" """
import py_paddle.swig_paddle as api
from py_paddle import DataProviderConverter
import paddle.trainer.PyDataProvider2 as dp
import numpy as np
import random import random
from mnist_util import read_from_mnist
from paddle.trainer_config_helpers import *
import paddle.v2
import numpy as np
import paddle.v2 as paddle_v2
import py_paddle.swig_paddle as api
from paddle.trainer_config_helpers import *
from py_paddle import DataProviderConverter
def network_config(): from mnist_util import read_from_mnist
imgs = data_layer(name='pixel', size=784)
hidden1 = fc_layer(input=imgs, size=200)
hidden2 = fc_layer(input=hidden1, size=200)
inference = fc_layer(input=hidden2, size=10, act=SoftmaxActivation())
cost = classification_cost(
input=inference, label=data_layer(
name='label', size=10))
outputs(cost)
def init_parameter(network): def init_parameter(network):
...@@ -67,7 +57,7 @@ def input_order_converter(generator): ...@@ -67,7 +57,7 @@ def input_order_converter(generator):
def main(): def main():
api.initPaddle("-use_gpu=false", "-trainer_count=4") # use 4 cpu cores api.initPaddle("-use_gpu=false", "-trainer_count=4") # use 4 cpu cores
optimizer = paddle.v2.optimizer.Adam( optimizer = paddle_v2.optimizer.Adam(
learning_rate=1e-4, learning_rate=1e-4,
batch_size=1000, batch_size=1000,
model_average=ModelAverage(average_window=0.5), model_average=ModelAverage(average_window=0.5),
...@@ -79,8 +69,20 @@ def main(): ...@@ -79,8 +69,20 @@ def main():
updater = optimizer.create_local_updater() updater = optimizer.create_local_updater()
assert isinstance(updater, api.ParameterUpdater) assert isinstance(updater, api.ParameterUpdater)
# define network
images = paddle_v2.layer.data(
name='pixel', type=paddle_v2.data_type.dense_vector(784))
label = paddle_v2.layer.data(
name='label', type=paddle_v2.data_type.integer_value(10))
hidden1 = paddle_v2.layer.fc(input=images, size=200)
hidden2 = paddle_v2.layer.fc(input=hidden1, size=200)
inference = paddle_v2.layer.fc(input=hidden2,
size=10,
act=paddle_v2.activation.Softmax())
cost = paddle_v2.layer.classification_cost(input=inference, label=label)
# Create Simple Gradient Machine. # Create Simple Gradient Machine.
model_config = parse_network_config(network_config) model_config = paddle_v2.layer.parse_network(cost)
m = api.GradientMachine.createFromConfigProto(model_config, m = api.GradientMachine.createFromConfigProto(model_config,
api.CREATE_MODE_NORMAL, api.CREATE_MODE_NORMAL,
optimizer.enable_types()) optimizer.enable_types())
...@@ -97,8 +99,7 @@ def main(): ...@@ -97,8 +99,7 @@ def main():
# DataProvider Converter is a utility convert Python Object to Paddle C++ # DataProvider Converter is a utility convert Python Object to Paddle C++
# Input. The input format is as same as Paddle's DataProvider. # Input. The input format is as same as Paddle's DataProvider.
converter = DataProviderConverter( converter = DataProviderConverter(input_types=[images.type, label.type])
input_types=[dp.dense_vector(784), dp.integer_value(10)])
train_file = './data/raw_data/train' train_file = './data/raw_data/train'
test_file = './data/raw_data/t10k' test_file = './data/raw_data/t10k'
......
import numpy
import paddle.v2 as paddle
import mnist_util
def train_reader():
train_file = './data/raw_data/train'
generator = mnist_util.read_from_mnist(train_file)
for item in generator:
yield item
def main():
paddle.init(use_gpu=False, trainer_count=1)
# define network topology
images = paddle.layer.data(
name='pixel', type=paddle.data_type.dense_vector(784))
label = paddle.layer.data(
name='label', type=paddle.data_type.integer_value(10))
hidden1 = paddle.layer.fc(input=images, size=200)
hidden2 = paddle.layer.fc(input=hidden1, size=200)
inference = paddle.layer.fc(input=hidden2,
size=10,
act=paddle.activation.Softmax())
cost = paddle.layer.classification_cost(input=inference, label=label)
parameters = paddle.parameters.create(cost)
for param_name in parameters.keys():
array = parameters.get(param_name)
array[:] = numpy.random.uniform(low=-1.0, high=1.0, size=array.shape)
parameters.set(parameter_name=param_name, value=array)
adam_optimizer = paddle.optimizer.Adam(learning_rate=0.01)
def event_handler(event):
if isinstance(event, paddle.event.EndIteration):
para = parameters.get('___fc_2__.w0')
print "Pass %d, Batch %d, Cost %f, Weight Mean Of Fc 2 is %f" % (
event.pass_id, event.batch_id, event.cost, para.mean())
else:
pass
trainer = paddle.trainer.SGD(update_equation=adam_optimizer)
trainer.train(train_data_reader=train_reader,
topology=cost,
parameters=parameters,
event_handler=event_handler,
batch_size=32, # batch size should be refactor in Data reader
data_types={ # data_types will be removed, It should be in
# network topology
'pixel': images.type,
'label': label.type
})
if __name__ == '__main__':
main()
...@@ -32,4 +32,6 @@ def process(settings, file_name): ...@@ -32,4 +32,6 @@ def process(settings, file_name):
word_slot = [ word_slot = [
settings.word_dict[w] for w in words if w in settings.word_dict settings.word_dict[w] for w in words if w in settings.word_dict
] ]
if not word_slot:
continue
yield word_slot, label yield word_slot, label
...@@ -138,7 +138,11 @@ def main(): ...@@ -138,7 +138,11 @@ def main():
batch = [] batch = []
for line in sys.stdin: for line in sys.stdin:
batch.append([predict.get_index(line)]) words = predict.get_index(line)
if words:
batch.append([words])
else:
print('All the words in [%s] are not in the dictionary.' % line)
if len(batch) == batch_size: if len(batch) == batch_size:
predict.batch_predict(batch) predict.batch_predict(batch)
batch = [] batch = []
......
...@@ -279,6 +279,12 @@ concat_layer ...@@ -279,6 +279,12 @@ concat_layer
:members: concat_layer :members: concat_layer
:noindex: :noindex:
seq_concat_layer
----------------
.. automodule:: paddle.trainer_config_helpers.layers
:members: seq_concat_layer
:noindex:
Reshaping Layers Reshaping Layers
================ ================
...@@ -302,6 +308,12 @@ repeat_layer ...@@ -302,6 +308,12 @@ repeat_layer
:members: repeat_layer :members: repeat_layer
:noindex: :noindex:
seq_reshape_layer
-----------------
.. automodule:: paddle.trainer_config_helpers.layers
:members: seq_reshape_layer
:noindex:
Math Layers Math Layers
=========== ===========
......
# PaddlePaddle Design Doc
## Ingredients
As our design principle is starting from the essence: how could we
allow users to express and solve their problems at neural networks.
Some essential concepts that our API have to provide include:
1. A *topology* is an expression of *layers*.
1. A layer could be any kind of computation, including *cost*.
1. Some layers have parameters, some don't. Most costs don't have
parameters.
1. In some topologies, layers share parameters. For
example,
[the network for training a ranking model](https://github.com/PaddlePaddle/Paddle/issues/1311#issuecomment-279121850).
1. At programming time, users specify topologies and possible sharing
of parameters. PaddlePaddle can figure out and create parameters
required (and possibly shared) by one or more topologies.
## Starting from Examples
As a summarization
of
[our disucssion](https://github.com/PaddlePaddle/Paddle/issues/1315),
let us present two examples here:
### Example 1. Sharing Parameters between Layers
We use
the
[3-branch ranking](https://github.com/PaddlePaddle/Paddle/issues/1311#issuecomment-279121850) model
in this example. For your convenience, I copy-a-paste the model's
topology as follows:
```
A -> f -\
Q -> f --> cost
B -> f -/
```
The following program trains the topology including the cost, and then
use the sub-network in the trained topology in inference:
```python
def f(in):
e = paddle.layer.embedding(in, parameter_name="embedding")
o = paddle.layer.softmax(e, parameter_name="semantic")
return o
# Create 3 topologies (subnets), they share parameters because all
# correspoinding layers have the same parameter names.
fA = f(paddle.layer.data(input_name="A"))
fB = f(paddle.layer.data(input_name="B"))
fQ = f(paddle.layer.data(input_name="Q"))
topology = paddle.layer.less_than(
paddle.layer.cross_entropy(fA, fQ),
paddle.layer.corss_entropy(fB, fQ))
# Derive parameters required in topology and create them in model.
parameters = paddle.parameters.create(topology)
# Estimate parameters used in topology from data.
paddle.train(topology, parameters, reader=read_ranking_model_data)
# Inference using fA (or fB or fC, as they share their parameters).
[testA, testB, testQ] = read_ranking_model_data()
print "The sematic-vector of testA: ", paddle.infer(fA, parameters, testA)
```
### Example 2. Sharing Parameters between "Models"
We use [GAN](https://github.com/PaddlePaddle/book/tree/develop/gan) in
this example. In the following example program, `d0` and `d1`
correspond to the two networks in the following figure:
<img src="https://github.com/wangyang59/book/raw/00036f4b0da5225041a6824587c1a01cf20159b1/gan/image/gan_ig.png" width=400 />
```python
def G(in):
# over-simplified example as G has only one layers:
return paddle.layer.fc(in, parameter_name="G")
def D(in);
# again, over-simplified:
return paddle.layer.fc(in, parameter_name="D")
# Construct the first topology, which contains both D and G.
# By learning this topology, we update parameters of G.
d0 = paddle.layer.should_be_false(D(G(paddle.layer.data())))
# Construct a second topology d1, which contains only D. By
# training this topology, we update parameters of D. Note
# that d1 share parameters with d0.
d1 = paddle.layer.should_be_true(D(paddle.layer.data()))
# Create parameters from a list of multiple topologies (models) for
# the chance to share parameters between these topologies.
parameters = paddle.parameters.create([d0, d1])
# Iterative training of GAN.
for ...:
train(d0, parameters, reader=read_from_rng, immutable_parameters={"D"})
train(d1, parameters, reader=read_from_realistic_images)
# Use d1 for inference:
print "D thinks a batch of images are realistic ", infer(d1, parameters, read_mnist_images)
```
### Summarization
Above two programs reveal some important design concerns:
1. Users describe a topology as an expression of layers. Every layer
has a *parameter name*. If the users don't specify it explicitly, it's automatically generated as a unique name. By
specifying the parameter name, users can specify the sharing of
parameters between layers and even between topologies.
1. `paddle.parameters.create` figures out parameters required by one
or more topologies from parameter names of layers. It creates these
parameters and returns a `ParameterSet` object, which is in essence
a map from *parameter names* to *parameters*.
1. At training and inference time, `paddle.train` and `paddle.infer`
requires both a topology and the parameter set that holds the parameters of that topology. There are some reasons:
1. This prevents users from forgetting to call
`paddle.parameters.create`.
1. `paddle.train` needs to know which parameter set to update.
1. Users could load another (pre-trained) parameter set and use it
with a topology in `train.infer`.
1. By specifying the `immutable_parameters` parameter of
`paddle.train`, we can forbid the update of these parameters.
## Reader
Not all programming frameworks allow users to define I/O functions.
An example is Google MapReduce, which can only read from text,
SSTable, and RecordIO files. Hadoop MapReduce allows users to define
readers and writers by deriving from base classes `Reader` and
`Writer`. The former is less flexible but also less error-prone. We
decide to provide the flexibility to users to define their readers.
There are some open questions here:
1. **Should a reader return a Python dictionary?**
1. **How to map multiple outputs from a reader to multiple data layers?**
1. **How to easily compose some existing readers to read more data and
feed a topology with more data layers?**
## Training
The recommended way to training a model is to call `paddle.train`,
which simply calls `paddle.trainer.Default`, a global variable of
type `paddle.trainer.SGD`. Equivalently, we can do
```python
opt = paddle.trainer.SGD(..., paddle.updater.Adam(...))
opt.train(topology, parameters, reader=read, ...)
```
### Updater
Please be aware that a trainer can accept an updater as its data
member, where an updater is a class derived from
`paddle.trainer.Updater`. This is to make it easier to customize
trainers, as discussed
[here](https://github.com/PaddlePaddle/Paddle/issues/1319).
### Event Handler
`paddle.train` and `paddle.trainer.XXX.train` take an optional
parameter `event_handler`, which should be either `None` or a function
that handle some events:
1. BeginTraining
1. EndTraining
1. BeginIteration
1. EndIteration
1. BeginPass
1. EndPass
where EndPass is sent if and only if the reader yields
`end_pass=True`.
An example as follows:
```python
def event_handler(event):
if ininstance(event, paddle.event.EndIteration):
print paddle.test(...)
paddle.train(topology, parameters, reader, event_handler)
```
If we are writing a PaddlePaddle program in and for iPython/Jypyter,
we can use metaplotlib in the event handler to plot a curve of
cost/error versus iterations, as shown
[here](https://blog.dominodatalab.com/interactive-dashboards-in-jupyter/).
### Distributed Training
If users want to do distributed training on a cluster, s/he should
call `paddle.dist_train` and provides access tokens to the cluster as
a parameter.
For example, if the user has a TLS certificate that allows him to
access a Kubernetes cluster, s/he should be able to call
```python
paddle.dist_train(model,
trainer=paddle.trainer.SGD(...,
paddle.updater.Adam(...)),
reader=read,
k8s_user="yi",
k8s_token="kube_cluster_tls.pem",
k8s_job="hello",
num_parameter_servers=15)
```
The pseudo code if `paddle.dist_train` is as follows:
```python
def dist_train(topology, parameters, trainer, reader, ...):
if os.getenv("KUBERNETES_SERVICE_HOST") == None:
image_name = k8s_user + '/' + k8s_job
docker_build(image_name)
docker_push()
kube_ctrl_start_job(image_name, k8s_user, k8s_token)
else:
rank = kube_list_containers_in_job_and_return_current_containers_rank()
if rank == 0:
master()
elif rank < 15:
parameter_server()
else:
trainer.train(model, reader=read)
```
Please be aware that if a process is running on the Kubernetes
cluster, it will have some environment variables pre-defined.
If `dist_train` doesn't see these environment variables, it knows
that it's running on users' personal computer, and it should work as a
*launcher*. Otherwise, it knows that it's running on the cluster and
need to figure out its role as either the master, or a trainer, or a
parameter server.
# Python Data Reader Design Doc
At training and testing time, PaddlePaddle programs need to read data. To ease the users' work to write data reading code, we define that
- A *reader* is a function that reads data (from file, network, random number generator, etc) and yields data items.
- A *reader creator* is a function that returns a reader function.
- A *reader* decorator is a function, which accepts one or more readers, and returns a reader.
and provide frequently used reader creators and reader decorators.
## Data Reader Interface
Indeed, *data reader* doesn't have to be a function that reads and yields data items. It can be any function with no parameter that creates a iterable (anything can be used in `for x in iterable`):
```
iterable = data_reader()
```
Element produced from the iterable should be a **single** entry of data, **not** a mini batch. That entry of data could be a single item, or a tuple of items. Item should be of [supported type](http://www.paddlepaddle.org/doc/ui/data_provider/pydataprovider2.html?highlight=dense_vector#input-types) (e.g., numpy 1d array of float32, int, list of int)
An example implementation for single item data reader creator:
```python
def reader_creator_random_image(width, height):
def reader():
while True:
yield numpy.random.uniform(-1, 1, size=width*height)
return reader
```
An example implementation for multiple item data reader creator:
```python
def reader_creator_random_imageand_label(widht, height, label):
def reader():
while True:
yield numpy.random.uniform(-1, 1, size=width*height), label
return reader
```
## Usage
data reader, mapping from item(s) read to data layer, batch size and number of total pass will be passed into `paddle.train`:
```python
# two data layer is created:
image_layer = paddle.layer.data("image", ...)
label_layer = paddle.layer.data("label", ...)
# ...
paddle.train(paddle.dataset.mnist, {"image":0, "label":1}, 128, 10, ...)
```
## Data Reader Decorator
*Data reader decorator* takes a single or multiple data reader, returns a new data reader. It is similar to a [python decorator](https://wiki.python.org/moin/PythonDecorators), but it does not use `@` syntax.
Since we have a strict interface for data readers (no parameter, return a single data item). Data reader can be used flexiable via data reader decorators. Following are a few examples:
### Prefetch Data
Since reading data may take time and training can not proceed without data. It is generally a good idea to prefetch data.
Use `paddle.reader.buffered` to prefetch data:
```python
buffered_reader = paddle.reader.buffered(paddle.dataset.mnist, 100)
```
`buffered_reader` will try to buffer (prefetch) `100` data entries.
### Compose Multiple Data Readers
For example, we want to use a source of real images (reusing mnist dataset), and a source of random images as input for [Generative Adversarial Networks](https://arxiv.org/abs/1406.2661).
We can do:
```python
def reader_creator_random_image(width, height):
def reader():
while True:
yield numpy.random.uniform(-1, 1, size=width*height)
return reader
def reader_creator_bool(t):
def reader:
while True:
yield t
return reader
true_reader = reader_creator_bool(True)
false_reader = reader_creator_bool(False)
reader = paddle.reader.compose(paddle.dataset.mnist, data_reader_creator_random_image(20, 20), true_reader, false_reader)
# Skipped 1 because paddle.dataset.mnist produces two items per data entry.
# And we don't care second item at this time.
paddle.train(reader, {"true_image":0, "fake_image": 2, "true_label": 3, "false_label": 4}, ...)
```
### Shuffle
Given shuffle buffer size `n`, `paddle.reader.shuffle` will return a data reader that buffers `n` data entries and shuffle them before a data entry is read.
Example:
```python
reader = paddle.reader.shuffle(paddle.dataset.mnist, 512)
```
## Q & A
### Why return only a single entry, but not a mini batch?
If a mini batch is returned, data reader need to take care of batch size. But batch size is a concept for training, it makes more sense for user to specify batch size as a parameter for `train`.
Practically, always return a single entry make reusing existing data readers much easier (e.g., if existing reader return not a single entry but 3 entries, training code will be more complex because it need to handle cases like batch size 2).
### Why use a dictionary but not a list to provide mapping?
We decided to use dictionary (`{"image":0, "label":1}`) instead of list (`["image", "label"]`) is because that user can easily resue item (e.g., using `{"image_a":0, "image_b":0, "label":1}`) or skip item (e.g., using `{"image_a":0, "label":2}`).
### How to create custom data reader creator
```python
def image_reader_creator(image_path, label_path, n):
def reader():
f = open(image_path)
l = open(label_path)
images = numpy.fromfile(
f, 'ubyte', count=n * 28 * 28).reshape((n, 28 * 28)).astype('float32')
images = images / 255.0 * 2.0 - 1.0
labels = numpy.fromfile(l, 'ubyte', count=n).astype("int")
for i in xrange(n):
yield images[i, :], labels[i] # a single entry of data is created each time
f.close()
l.close()
return reader
# images_reader_creator creates a reader
reader = image_reader_creator("/path/to/image_file", "/path/to/label_file", 1024)
paddle.train(reader, {"image":0, "label":1}, ...)
```
### How is `paddle.train` implemented
An example implementation of paddle.train could be:
```python
def make_minibatch(reader, minibatch_size):
def ret():
r = reader()
buf = [r.next() for x in xrange(minibatch_size)]
while len(buf) > 0:
yield buf
buf = [r.next() for x in xrange(minibatch_size)]
return ret
def train(reader, mapping, batch_size, total_pass):
for pass_idx in range(total_pass):
for mini_batch in make_minibatch(reader): # this loop will never end in online learning.
do_forward_backward(mini_batch, mapping)
```
...@@ -188,48 +188,6 @@ extern void hl_param_relu_backward_diff(real* grad_o, ...@@ -188,48 +188,6 @@ extern void hl_param_relu_backward_diff(real* grad_o,
int width, int width,
int height, int height,
int partial_sum); int partial_sum);
/**
* @brief cos sim forward
*
* @param[out] output output data
* @param[in] input1 input1 data(matrix)
* @param[in] input2 input2 data(matrix or vector)
* @param[in] width matrix width
* @param[in] input1_height input1_height
* @param[in] input2_height input2_height
* @param[in] scale scale factor
*/
extern void hl_cossim(real* output,
real* input1,
real* input2,
int width,
int input1_height,
int input2_height,
real scale);
/**
* @brief cos sim derivate
*
* @param[in] grad output grad
* @param[in] output output data
* @param[in] prevOutX input1 data
* @param[in] prevOutY input2 data
* @param[out] prevGradX input1 grad
* @param[out] prevGradY input2 grad
* @param[in] width matrix width
* @param[in] input1_height input1 height
* @param[in] input2_height input2 height
* @param[in] scale scale factor
*/
extern void hl_cossim_derivative(real* grad,
real* output,
real* prevOutX,
real* prevOutY,
real* prevGradX,
real* prevGradY,
int width,
int input1_height,
int input2_height,
real scale);
/** /**
* @brief Matrix addition: A_d[i][j] += scale * B_d[j/channel]. * @brief Matrix addition: A_d[i][j] += scale * B_d[j/channel].
......
...@@ -74,25 +74,6 @@ inline void hl_param_relu_backward_diff(real* grad_o, ...@@ -74,25 +74,6 @@ inline void hl_param_relu_backward_diff(real* grad_o,
int height, int height,
int partial_sum) {} int partial_sum) {}
inline void hl_cossim(real* output,
real* input1,
real* input2,
int width,
int input1_height,
int input2_height,
real scale) {}
inline void hl_cossim_derivative(real* grad,
real* output,
real* prevOutX,
real* prevOutY,
real* prevGradX,
real* prevGradY,
int width,
int input1_height,
int input2_height,
real scale) {}
inline void hl_matrix_add_shared_bias(real* A_d, inline void hl_matrix_add_shared_bias(real* A_d,
real* B_d, real* B_d,
const int channel, const int channel,
......
...@@ -584,177 +584,6 @@ void hl_param_relu_backward_diff(real* grad_o, ...@@ -584,177 +584,6 @@ void hl_param_relu_backward_diff(real* grad_o,
CHECK_SYNC("hl_param_relu_backward_diff failed"); CHECK_SYNC("hl_param_relu_backward_diff failed");
} }
template<int blockSize>
__global__ void KeCosSim(real* output,
real* input1,
real* input2,
int width,
int input1_height,
int input2_height,
real scale) {
const int ty = blockIdx.y;
int tid = threadIdx.x;
__shared__ real xx[blockSize];
__shared__ real yy[blockSize];
__shared__ real xy[blockSize];
xx[tid] = 0.0;
yy[tid] = 0.0;
xy[tid] = 0.0;
__syncthreads();
input1 += ty * width;
if (input2_height > 1) {
input2 += ty * width;
}
for (int index = tid; index < width; index += blockSize) {
real x = input1[index];
real y = input2[index];
xx[tid] += x * x;
yy[tid] += y * y;
xy[tid] += x * y;
}
__syncthreads();
for (int s = blockSize / 2; s > 0; s >>= 1) {
if (tid < s) {
xx[tid] += xx[tid + s];
yy[tid] += yy[tid + s];
xy[tid] += xy[tid + s];
}
__syncthreads();
}
if (tid == 0) {
output[ty] = scale * xy[0] / (sqrt(xx[0]) * sqrt(yy[0]));
}
}
void hl_cossim(real* output,
real* input1,
real* input2,
int width,
int input1_height,
int input2_height,
real scale) {
CHECK_NOTNULL(output);
CHECK_NOTNULL(input1);
CHECK_NOTNULL(input2);
const int blockSize = 256;
dim3 threads(blockSize, 1);
dim3 grid(1, input1_height);
KeCosSim<blockSize><<<grid, threads, 0, STREAM_DEFAULT>>>
(output, input1, input2, width, input1_height, input2_height, scale);
CHECK_SYNC("hl_cossim failed");
}
template<int blockSize>
__global__ void KeCosSimDerivative(real* grad,
real* output,
real* prevOutX,
real* prevOutY,
real* prevGradX,
real* prevGradY,
int width,
int input1_height,
int input2_height,
real scale) {
const int ty = blockIdx.y;
int tid = threadIdx.x;
__shared__ real xx[blockSize];
__shared__ real yy[blockSize];
__shared__ real xy[blockSize];
xx[tid] = 0.0;
yy[tid] = 0.0;
xy[tid] = 0.0;
__syncthreads();
prevOutX += ty * width;
prevGradX += ty * width;
if (input2_height > 1) {
prevOutY += ty * width;
prevGradY += ty * width;
}
for (int index = tid; index < width; index += blockSize) {
real x = prevOutX[index];
real y = prevOutY[index];
xx[tid] += x * x;
yy[tid] += y * y;
xy[tid] += x * y;
}
__syncthreads();
for (int s = blockSize / 2; s > 0; s >>= 1) {
if (tid < s) {
xx[tid] += xx[tid + s];
yy[tid] += yy[tid + s];
xy[tid] += xy[tid + s];
}
__syncthreads();
}
if (xy[0] == 0) {
real reciprocal = 1.0 / (sqrt(xx[0]) * sqrt(yy[0]));
for (int index = tid; index < width; index += blockSize) {
prevGradX[index] +=
scale * grad[ty] * prevOutY[index] * reciprocal;
if (input2_height > 1) {
prevGradY[index] +=
scale * grad[ty] * prevOutX[index] * reciprocal;
} else {
paddle::paddleAtomicAdd(prevGradY + index,
scale * grad[ty] * prevOutX[index] * reciprocal);
}
}
} else {
real reciprocalXY = 1.0 / xy[0];
real reciprocalSquareSumX = 1.0 / xx[0];
real reciprocalSquareSumY = 1.0 / yy[0];
for (int index = tid; index < width; index += blockSize) {
prevGradX[index] += output[ty] * grad[ty] *
(prevOutY[index] * reciprocalXY -
prevOutX[index] * reciprocalSquareSumX);
if (input2_height > 1) {
prevGradY[index] += output[ty] * grad[ty] *
(prevOutX[index] * reciprocalXY -
prevOutY[index] * reciprocalSquareSumY);
} else {
paddle::paddleAtomicAdd(prevGradY + index, output[ty] * grad[ty] *
(prevOutX[index] * reciprocalXY -
prevOutY[index] * reciprocalSquareSumY));
}
}
}
}
void hl_cossim_derivative(real* grad,
real* output,
real* prevOutX,
real* prevOutY,
real* prevGradX,
real* prevGradY,
int width,
int input1_height,
int input2_height,
real scale) {
CHECK_NOTNULL(grad);
CHECK_NOTNULL(output);
CHECK_NOTNULL(prevOutX);
CHECK_NOTNULL(prevOutY);
CHECK_NOTNULL(prevGradX);
CHECK_NOTNULL(prevGradY);
const int blockSize = 256;
dim3 threads(blockSize, 1);
dim3 grid(1, input1_height);
KeCosSimDerivative<blockSize><<<grid, threads, 0, STREAM_DEFAULT>>>
(grad, output, prevOutX, prevOutY, prevGradX, prevGradY, width,
input1_height, input2_height, scale);
CHECK_SYNC("hl_cossim_derivate failed");
}
__global__ void KeMatrixAddSharedBias(real* A, __global__ void KeMatrixAddSharedBias(real* A,
real* B, real* B,
const int channel, const int channel,
......
...@@ -190,7 +190,7 @@ public: ...@@ -190,7 +190,7 @@ public:
: BufferArg(VALUE_TYPE_INT32, shape, argType) { : BufferArg(VALUE_TYPE_INT32, shape, argType) {
bufferType_ = TENSOR_SEQUENCE_ID; bufferType_ = TENSOR_SEQUENCE_ID;
CHECK_EQ(shape_.ndims(), 1UL); CHECK_EQ(shape_.ndims(), 1UL);
CHECK_GT(shape_[0], 1UL); CHECK_GE(shape_[0], 1UL);
numSeqs_ = shape_[0] - 1; numSeqs_ = shape_[0] - 1;
} }
...@@ -226,7 +226,8 @@ public: ...@@ -226,7 +226,8 @@ public:
SequenceArg(ValueType valueType, SequenceArg(ValueType valueType,
const TensorShape& shape, const TensorShape& shape,
ArgType argType = UNSPECIFIED) ArgType argType = UNSPECIFIED)
: BufferArg(valueType, shape, argType), startPositions_(TensorShape()) { : BufferArg(valueType, shape, argType),
startPositions_(TensorShape({shape[0]})) {
bufferType_ = TENSOR_SEQUENCE_DATA; bufferType_ = TENSOR_SEQUENCE_DATA;
} }
......
...@@ -27,6 +27,7 @@ if(WITH_TESTING) ...@@ -27,6 +27,7 @@ if(WITH_TESTING)
add_simple_unittest(ContextProjectionOpTest) add_simple_unittest(ContextProjectionOpTest)
add_simple_unittest(PadOpTest) add_simple_unittest(PadOpTest)
add_simple_unittest(MulOpTest) add_simple_unittest(MulOpTest)
add_simple_unittest(CosSimOpTest)
endif() endif()
endif() endif()
......
...@@ -108,26 +108,23 @@ public: ...@@ -108,26 +108,23 @@ public:
} }
void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
CHECK(1 == inputs.size() || 2 == inputs.size()); CHECK(1UL == inputs.size() || 2UL == inputs.size());
CHECK_EQ((size_t)1, outputs.size()); CHECK_EQ(1UL, outputs.size());
CHECK(inputs[0].isSequenceArg() && outputs[0].isSequenceArg()) CHECK(inputs[0].isSequenceArg() && outputs[0].isSequenceArg())
<< "SequenceArg required here"; << "SequenceArg required here";
const auto val_seqs = dynamic_cast<const SequenceArg&>(inputs[0]); const auto val_seqs = dynamic_cast<const SequenceArg&>(inputs[0]);
auto out_seq = dynamic_cast<const SequenceArg&>(outputs[0]); auto out_seq = dynamic_cast<const SequenceArg&>(outputs[0]);
CHECK(out_seq.data() && val_seqs.data() && val_seqs.getSequenceId().data()); CHECK(out_seq.data() && val_seqs.data() && val_seqs.getSequenceId().data());
CHECK_EQ(out_seq.shape().ndims(), (size_t)2); CHECK_EQ(out_seq.shape().ndims(), 2UL);
CHECK_EQ(val_seqs.shape().ndims(), (size_t)2); CHECK_EQ(val_seqs.shape().ndims(), 2UL);
CHECK_EQ(val_seqs.getSequenceId().shape().ndims(), (size_t)1);
if (2 == inputs.size()) {
CHECK_EQ(inputs[1].shape().ndims(), (size_t)2);
}
/// dim of output = dim of input * context_length /// dim of output = dim of input * context_length
CHECK_EQ(out_seq.shape()[1], val_seqs.shape()[1] * context_length_); CHECK_EQ(out_seq.shape()[1], val_seqs.shape()[1] * context_length_);
/// input and output has the same batch_size /// input and output has the same batch_size
CHECK_EQ(val_seqs.shape()[0], out_seq.shape()[0]); CHECK_EQ(val_seqs.shape()[0], out_seq.shape()[0]);
/// dim of input == dim of weight if (2UL == inputs.size()) {
if (2 == inputs.size()) { CHECK_EQ(inputs[1].shape().ndims(), 2UL);
/// dim of input == dim of weight
CHECK_EQ(val_seqs.shape()[1], inputs[1].shape()[1]); CHECK_EQ(val_seqs.shape()[1], inputs[1].shape()[1]);
} }
...@@ -135,10 +132,11 @@ public: ...@@ -135,10 +132,11 @@ public:
auto out_mat = out_seq.matrix<Device>(); auto out_mat = out_seq.matrix<Device>();
const auto in_mat = val_seqs.matrix<Device>(); const auto in_mat = val_seqs.matrix<Device>();
const auto w_mat = const auto w_mat =
(2 == inputs.size()) (2UL == inputs.size() && inputs[1].data())
? inputs[1].matrix<Device>() ? inputs[1].matrix<Device>()
: typename Tensor<real, Device>::Matrix(nullptr, 0, 0); : typename Tensor<real, Device>::Matrix(nullptr, 0, 0);
const auto seq_vec = val_seqs.getSequenceId().vector<int, Device>(); const auto seq_vec = val_seqs.getSequenceId().vector<int, Device>();
ContextProjectionForward<Device>(out_mat, ContextProjectionForward<Device>(out_mat,
in_mat, in_mat,
w_mat, w_mat,
...@@ -235,36 +233,40 @@ public: ...@@ -235,36 +233,40 @@ public:
} }
void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
CHECK_EQ((size_t)1, inputs.size()); CHECK_EQ(1UL, inputs.size());
CHECK_EQ((size_t)2, outputs.size()); CHECK(1UL == outputs.size() || 2UL == outputs.size());
CHECK(inputs[0].isSequenceArg() && outputs[0].isSequenceArg()) CHECK(inputs[0].isSequenceArg() && outputs[0].isSequenceArg())
<< "SequenceArg required here"; << "SequenceArg required here";
const auto in_seq = dynamic_cast<const SequenceArg&>(inputs[0]); const auto in_seq = dynamic_cast<const SequenceArg&>(inputs[0]);
auto out_seq = dynamic_cast<const SequenceArg&>(outputs[0]); auto out_seq = dynamic_cast<const SequenceArg&>(outputs[0]);
CHECK(in_seq.data() && in_seq.getSequenceId().data()); CHECK(in_seq.data() && in_seq.getSequenceId().data());
CHECK_EQ(in_seq.shape().ndims(), (size_t)2); CHECK_EQ(in_seq.shape().ndims(), 2UL);
CHECK_EQ(in_seq.getSequenceId().shape().ndims(), (size_t)1); CHECK_EQ(out_seq.shape().ndims(), 2UL);
CHECK_EQ(out_seq.shape().ndims(), (size_t)2); CHECK_EQ(out_seq.getSequenceId().shape().ndims(), 1UL);
CHECK_EQ(out_seq.getSequenceId().shape().ndims(), (size_t)1);
CHECK_EQ(outputs[1].shape().ndims(), (size_t)2);
/// dim of input grad == dim of weight
CHECK_EQ(out_seq.shape()[1], outputs[1].shape()[1]);
/// input and output grad has the same batch_size /// input and output grad has the same batch_size
CHECK_EQ(out_seq.shape()[0], in_seq.shape()[0]); CHECK_EQ(out_seq.shape()[0], in_seq.shape()[0]);
/// dim of output grad = dim of input grad * context_length /// dim of output grad = dim of input grad * context_length
CHECK_EQ(in_seq.shape()[1], out_seq.shape()[1] * context_length_); CHECK_EQ(in_seq.shape()[1], out_seq.shape()[1] * context_length_);
CHECK_EQ(out_seq.getArgType(), ADD_TO); CHECK_EQ(out_seq.getArgType(), ADD_TO);
CHECK_EQ(outputs[1].getArgType(), ADD_TO);
if (2UL == outputs.size()) {
CHECK_EQ(outputs[1].shape().ndims(), 2UL);
/// dim of input grad == dim of weight
CHECK_EQ(out_seq.shape()[1], outputs[1].shape()[1]);
CHECK_EQ(outputs[1].getArgType(), ADD_TO);
}
const auto seq_vec = in_seq.getSequenceId().vector<int, Device>(); const auto seq_vec = in_seq.getSequenceId().vector<int, Device>();
const auto out_grad_mat = in_seq.matrix<Device>(); const auto out_grad_mat = in_seq.matrix<Device>();
auto in_grad_mat = auto in_grad_mat =
!out_seq.data() ? typename Tensor<real, Device>::Matrix(nullptr, 0, 0) !out_seq.data() ? typename Tensor<real, Device>::Matrix(nullptr, 0, 0)
: out_seq.matrix<Device>(); : out_seq.matrix<Device>();
auto w_grad_mat = !outputs[1].data() auto w_grad_mat =
? typename Tensor<real, Device>::Matrix(nullptr, 0, 0) (2UL == outputs.size() && outputs[1].data())
: outputs[1].matrix<Device>(); ? outputs[1].matrix<Device>()
: typename Tensor<real, Device>::Matrix(nullptr, 0, 0);
ContextProjectionBackward<Device>(out_grad_mat, ContextProjectionBackward<Device>(out_grad_mat,
in_grad_mat, in_grad_mat,
w_grad_mat, w_grad_mat,
...@@ -304,17 +306,17 @@ public: ...@@ -304,17 +306,17 @@ public:
} }
void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
CHECK_EQ(1, static_cast<int>(inputs.size())); CHECK_EQ(1UL, inputs.size());
CHECK_EQ(1, static_cast<int>(outputs.size())); CHECK_EQ(1UL, outputs.size());
CHECK(inputs[0].isSequenceArg() && outputs[0].isSequenceArg()) CHECK(inputs[0].isSequenceArg() && outputs[0].isSequenceArg())
<< "SequenceArg required here"; << "SequenceArg required here";
const auto in_seq = dynamic_cast<const SequenceArg&>(inputs[0]); const auto in_seq = dynamic_cast<const SequenceArg&>(inputs[0]);
const auto out_seq = dynamic_cast<const SequenceArg&>(outputs[0]); const auto out_seq = dynamic_cast<const SequenceArg&>(outputs[0]);
CHECK(in_seq.data() && out_seq.data() && in_seq.getSequenceId().data()); CHECK(in_seq.data() && out_seq.data() && in_seq.getSequenceId().data());
CHECK_EQ(static_cast<int>(out_seq.shape().ndims()), 2); CHECK_EQ(out_seq.shape().ndims(), 2UL);
CHECK_EQ(static_cast<int>(in_seq.shape().ndims()), 2); CHECK_EQ(in_seq.shape().ndims(), 2UL);
CHECK_EQ(static_cast<int>(in_seq.getSequenceId().shape().ndims()), 1); CHECK_EQ(in_seq.getSequenceId().shape().ndims(), 1UL);
/// output layer grad dim == input layer grad dim * context_length_ /// output layer grad dim == input layer grad dim * context_length_
CHECK_EQ(in_seq.shape().ndims(), out_seq.shape().ndims() * context_length_); CHECK_EQ(in_seq.shape().ndims(), out_seq.shape().ndims() * context_length_);
/// input and output has the same batch_size /// input and output has the same batch_size
...@@ -355,14 +357,14 @@ public: ...@@ -355,14 +357,14 @@ public:
} }
void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
CHECK_EQ(1, static_cast<int>(inputs.size())); CHECK_EQ(1UL, inputs.size());
CHECK_EQ(1, static_cast<int>(outputs.size())); CHECK_EQ(1UL, outputs.size());
CHECK(inputs[0].isSequenceArg()) << "SequenceArg required here"; CHECK(inputs[0].isSequenceArg()) << "SequenceArg required here";
const auto in_seq = dynamic_cast<const SequenceArg&>(inputs[0]); const auto in_seq = dynamic_cast<const SequenceArg&>(inputs[0]);
CHECK(in_seq.data() && in_seq.getSequenceId().data() && outputs[0].data()); CHECK(in_seq.data() && in_seq.getSequenceId().data() && outputs[0].data());
CHECK_EQ(static_cast<int>(outputs[0].shape().ndims()), 2); CHECK_EQ(outputs[0].shape().ndims(), 2UL);
CHECK_EQ(static_cast<int>(in_seq.shape().ndims()), 2); CHECK_EQ(in_seq.shape().ndims(), 2UL);
CHECK_EQ(static_cast<int>(in_seq.getSequenceId().shape().ndims()), 1); CHECK_EQ(in_seq.getSequenceId().shape().ndims(), 1UL);
CHECK_EQ(in_seq.shape()[0], outputs[0].shape()[0]); CHECK_EQ(in_seq.shape()[0], outputs[0].shape()[0]);
/// output layer grad dim == weight dim * context_length_ /// output layer grad dim == weight dim * context_length_
CHECK_EQ(in_seq.shape()[1], outputs[0].shape()[1] * context_length_); CHECK_EQ(in_seq.shape()[1], outputs[0].shape()[1] * context_length_);
......
...@@ -13,7 +13,6 @@ See the License for the specific language governing permissions and ...@@ -13,7 +13,6 @@ See the License for the specific language governing permissions and
limitations under the License. */ limitations under the License. */
#pragma once #pragma once
#include "Function.h" #include "Function.h"
namespace paddle { namespace paddle {
......
...@@ -28,55 +28,26 @@ void testMatrixProjectionForward(int context_start, ...@@ -28,55 +28,26 @@ void testMatrixProjectionForward(int context_start,
std::max(0, (int)(context_start + context_length - 1)); std::max(0, (int)(context_start + context_length - 1));
if (pad == 0) is_padding = false; if (pad == 0) is_padding = false;
FunctionCompare compare("ContextProjectionForward", FunctionCompare test("ContextProjectionForward",
FuncConfig() FuncConfig()
.set("context_length", context_length) .set("context_length", context_length)
.set("context_start", context_start) .set("context_start", context_start)
.set("begin_pad", std::max(0, -context_start))); .set("begin_pad", std::max(0, -context_start)));
CpuMatrix cpu_in(batch_size, input_dim); // prepare input arguments
cpu_in.randomizeUniform(); test.addSequence(SequenceIdArg(TensorShape{batch_size}));
GpuMatrix gpu_in(batch_size, input_dim); test.addInputs(
gpu_in.copyFrom(cpu_in); SequenceArg(VALUE_TYPE_FLOAT, TensorShape{batch_size, input_dim}));
auto cpu_weight = if (is_padding) { // weight
is_padding ? std::make_shared<CpuMatrix>(pad, input_dim) : nullptr; test.addInputs(SequenceArg(VALUE_TYPE_FLOAT, TensorShape{pad, input_dim}));
auto gpu_weight =
is_padding ? std::make_shared<GpuMatrix>(pad, input_dim) : nullptr;
if (is_padding) {
cpu_weight->randomizeUniform();
gpu_weight->copyFrom(*cpu_weight);
} }
IVectorPtr cpu_seq; test.addOutputs(
generateSequenceStartPositions(batch_size, cpu_seq); SequenceArg(VALUE_TYPE_FLOAT,
IVectorPtr gpu_seq = IVector::create(cpu_seq->getSize(), true); TensorShape{batch_size, input_dim * context_length}),
gpu_seq->copyFrom(*cpu_seq); ADD_TO);
CpuMatrix cpu_out(batch_size, input_dim * context_length);
GpuMatrix gpu_out(batch_size, input_dim * context_length);
cpu_out.randomizeUniform();
gpu_out.copyFrom(cpu_out);
BufferArgs cpu_inputs;
BufferArgs cpu_outputs;
cpu_inputs.addArg(cpu_in, *cpu_seq);
if (cpu_weight) {
cpu_inputs.addArg(*cpu_weight, *cpu_seq);
}
cpu_outputs.addArg(cpu_out, *cpu_seq, ADD_TO);
compare.getCpuFunction()->calc(cpu_inputs, cpu_outputs);
BufferArgs gpu_inputs; // run Function
BufferArgs gpu_outputs; test.run();
gpu_inputs.addArg(gpu_in, *gpu_seq);
if (gpu_weight) {
gpu_inputs.addArg(*gpu_weight, *gpu_seq);
}
gpu_outputs.addArg(gpu_out, *gpu_seq, ADD_TO);
compare.getGpuFunction()->calc(gpu_inputs, gpu_outputs);
autotest::TensorCheckEqual(cpu_out, gpu_out);
} }
void testMatrixProjectionBackward(int context_start, void testMatrixProjectionBackward(int context_start,
...@@ -88,63 +59,31 @@ void testMatrixProjectionBackward(int context_start, ...@@ -88,63 +59,31 @@ void testMatrixProjectionBackward(int context_start,
std::max(0, (int)(context_start + context_length - 1)); std::max(0, (int)(context_start + context_length - 1));
if (pad == 0) is_padding = false; if (pad == 0) is_padding = false;
FunctionCompare compare("ContextProjectionBackward", FunctionCompare test("ContextProjectionBackward",
FuncConfig() FuncConfig()
.set("context_length", context_length) .set("context_length", context_length)
.set("context_start", context_start) .set("context_start", context_start)
.set("begin_pad", std::max(0, -context_start)) .set("begin_pad", std::max(0, -context_start))
.set("is_padding", is_padding) .set("is_padding", is_padding)
.set("total_pad", pad)); .set("total_pad", pad));
CpuMatrix cpu_in_grad(batch_size, input_dim); // prepare input arguments
cpu_in_grad.randomizeUniform(); test.addSequence(SequenceIdArg(TensorShape{batch_size}));
GpuMatrix gpu_in_grad(batch_size, input_dim); test.addInputs(SequenceArg(
gpu_in_grad.copyFrom(cpu_in_grad); VALUE_TYPE_FLOAT, TensorShape{batch_size, input_dim * context_length}));
test.addOutputs(
CpuMatrix cpu_out_grad(batch_size, input_dim * context_length); SequenceArg(VALUE_TYPE_FLOAT, TensorShape{batch_size, input_dim}),
cpu_out_grad.randomizeUniform(); ADD_TO);
GpuMatrix gpu_out_grad(batch_size, input_dim * context_length); if (is_padding) { // weight
gpu_out_grad.copyFrom(cpu_out_grad); test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{pad, input_dim}),
ADD_TO);
IVectorPtr cpu_seq;
generateSequenceStartPositions(batch_size, cpu_seq);
IVectorPtr gpu_seq = IVector::create(cpu_seq->getSize(), true);
gpu_seq->copyFrom(*cpu_seq);
auto cpu_w_grad =
is_padding ? std::make_shared<CpuMatrix>(pad, input_dim) : nullptr;
auto gpu_w_grad =
is_padding ? std::make_shared<GpuMatrix>(pad, input_dim) : nullptr;
if (is_padding) {
cpu_w_grad->randomizeUniform();
gpu_w_grad->copyFrom(*cpu_w_grad);
} }
BufferArgs cpu_inputs; // run Function
BufferArgs cpu_outputs; test.run();
cpu_inputs.addArg(cpu_out_grad, *cpu_seq);
cpu_outputs.addArg(cpu_in_grad, *cpu_seq, ADD_TO);
cpu_outputs.addArg(
cpu_w_grad ? *cpu_w_grad : CpuMatrix(nullptr, 0, input_dim), ADD_TO);
compare.getCpuFunction()->calc(cpu_inputs, cpu_outputs);
BufferArgs gpu_inputs;
BufferArgs gpu_outputs;
gpu_inputs.addArg(gpu_out_grad, *gpu_seq);
gpu_outputs.addArg(gpu_in_grad, *gpu_seq, ADD_TO);
gpu_outputs.addArg(
gpu_w_grad ? *gpu_w_grad : GpuMatrix(nullptr, 0, input_dim), ADD_TO);
compare.getGpuFunction()->calc(gpu_inputs, gpu_outputs);
autotest::TensorCheckErr(cpu_in_grad, gpu_in_grad);
if (is_padding) {
autotest::TensorCheckErr(*cpu_w_grad, *gpu_w_grad);
}
} }
TEST(ContextProjection, projection) { TEST(ContextProjection, Projection) {
for (auto context_start : {-5, -3, -1, 0, 3}) { for (auto context_start : {-5, -3, -1, 0, 3}) {
for (auto context_length : {1, 2, 5, 7}) { for (auto context_length : {1, 2, 5, 7}) {
for (auto trainable_padding : {false, true}) { for (auto trainable_padding : {false, true}) {
......
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
#include "CosSimOp.h"
#include "paddle/math/Matrix.h"
#include "paddle/math/Vector.h"
namespace paddle {
/**
* Cosine Similarity for CpuMatrix
*
* \param out_mat, output value, size: nSamples * 1.
* \param in1_mat, input value 1, size: nSamples * dim.
* \param in2_mat, input value 2, size: n2 * dim (n2 == 1 or n2 == nSamples).
* \param scale, default 1.0
*
*/
template <>
void CosSimForward<DEVICE_TYPE_CPU>(CpuMatrix& out_mat,
const CpuMatrix& in1_mat,
const CpuMatrix& in2_mat,
real scale) {
CHECK(out_mat.getData() && in1_mat.getData() && in2_mat.getData());
size_t num_samples = out_mat.getHeight();
size_t dim = in1_mat.getWidth();
/// column vector [nSamples, 1]
real* out = out_mat.getData();
const real* x = in1_mat.getData();
const real* y = in2_mat.getData();
/// in2 might only have one row or full rows
CHECK(in2_mat.getHeight() == 1LU || in2_mat.getHeight() == num_samples);
size_t inc = (in2_mat.getHeight() == 1LU) ? 0 : dim;
for (size_t i = 0; i < num_samples; ++i, x += dim, y += inc) {
real square_sum_x = 0;
real square_sum_y = 0;
real xy = 0;
for (size_t j = 0; j < dim; ++j) {
square_sum_x += x[j] * x[j];
square_sum_y += y[j] * y[j];
xy += x[j] * y[j];
}
CHECK(square_sum_x > 0 && square_sum_y > 0);
out[i] = scale * xy / (std::sqrt(square_sum_x) * std::sqrt(square_sum_y));
}
}
/**
* Cosine Similarity
* for each row i,
* out[i] = scale * cos(input1[i], input2[i])
* = scale * <input1[i], input2[i]>/sqrt(|input1[i]|^2 * |input2[i]|^2)
* when input2 only has one row, then for each row i,
* out[i] = cos(input1[i], input2[0])
*
* \param inputs[0] input matrix 1, size: nSamples * dim.
* \param inputs[1] input matrix 2, size: n2 * dim (n2 == 1 or n2 == nSamples).
* \param outputs[0] output matrix, size : nSamples * 1.
*/
template <DeviceType Device>
class CosSimForwardFunc : public FunctionBase {
void init(const FuncConfig& config) override {
scale_ = config.get<real>("scale");
}
void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
CHECK_EQ(inputs.size(), 2UL);
CHECK_EQ(outputs.size(), 1UL);
CHECK_EQ(inputs[0].shape().ndims(), 2UL);
CHECK_EQ(inputs[1].shape().ndims(), 2UL);
CHECK_EQ(outputs[0].shape().ndims(), 2UL);
CHECK_EQ(inputs[0].shape()[0], outputs[0].shape()[0]);
CHECK_EQ(inputs[0].shape()[1], inputs[1].shape()[1]);
CHECK_EQ(outputs[0].shape()[1], 1UL);
CHECK(outputs[0].data() && inputs[0].data() && inputs[1].data());
CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO);
auto out_mat = outputs[0].matrix<Device>();
const auto in1_mat = inputs[0].matrix<Device>();
const auto in2_mat = inputs[1].matrix<Device>();
CosSimForward<Device>(out_mat, in1_mat, in2_mat, scale_);
}
private:
real scale_;
};
/**
* Cosine Similarity Derivative for CpuMatrix
*
* \param in1_grad forward input grad 1, size: nSamples * dim.
* \param in2_grad forward input grad 2,
* size: n2 * dim (n2 == 1 or n2 == nSamples).
*
* \param out_grad backward loss output grad, size : nSamples * 1.
* \param out_val forward output value, size: nSamples * 1.
* \param in1_val forward input value 1, size: nSamples * dim.
* \param in2_val forward input value 2,
* size: n2 * dim (n2 == 1 or n2 == nSamples).
* \param scale, default 1.0
*/
template <>
void CosSimBackward<DEVICE_TYPE_CPU>(const CpuMatrix& out_grad,
const CpuMatrix& out_val,
const CpuMatrix& in1_val,
const CpuMatrix& in2_val,
CpuMatrix& in1_grad,
CpuMatrix& in2_grad,
real scale) {
CHECK(out_grad.getData() && out_val.getData() && in1_val.getData() &&
in2_val.getData() && in1_grad.getData() && in2_grad.getData());
CHECK_EQ(out_val.useGpu_, false) << "Matrix type are GPU, CPU required";
const real* grad = out_grad.getData();
const real* out = out_val.getData();
const real* prev_out_x = in1_val.getData();
const real* prev_out_y = in2_val.getData();
real* prev_grad_x = in1_grad.getData();
real* prev_grad_y = in2_grad.getData();
size_t num_samples = out_grad.getHeight();
size_t dim = in1_val.getWidth();
CHECK_EQ(in2_val.getHeight(), in2_grad.getHeight());
CHECK(in2_val.getHeight() == 1LU || in2_val.getHeight() == num_samples);
size_t inc = (in2_val.getHeight() == 1LU) ? 0 : dim;
for (size_t i = 0; i < num_samples; ++i,
prev_out_x += dim,
prev_out_y += inc,
prev_grad_x += dim,
prev_grad_y += inc) {
real square_sum_x = 0;
real square_sum_y = 0;
real xy = 0;
for (size_t j = 0; j < dim; ++j) {
square_sum_x += prev_out_x[j] * prev_out_x[j];
square_sum_y += prev_out_y[j] * prev_out_y[j];
xy += prev_out_x[j] * prev_out_y[j];
}
CHECK(square_sum_x > 0 && square_sum_y > 0);
if (xy == 0) {
real reciprocal =
1.0f / (std::sqrt(square_sum_x) * std::sqrt(square_sum_y));
for (size_t j = 0; j < dim; ++j) {
prev_grad_x[j] += scale * grad[i] * prev_out_y[j] * reciprocal;
prev_grad_y[j] += scale * grad[i] * prev_out_x[j] * reciprocal;
}
} else {
real reciprocal_xy = 1.0f / xy;
real reciprocal_square_sum_x = 1.0f / square_sum_x;
real reciprocal_square_sum_y = 1.0f / square_sum_y;
for (size_t j = 0; j < dim; ++j) {
prev_grad_x[j] +=
out[i] * grad[i] * (prev_out_y[j] * reciprocal_xy -
prev_out_x[j] * reciprocal_square_sum_x);
prev_grad_y[j] +=
out[i] * grad[i] * (prev_out_x[j] * reciprocal_xy -
prev_out_y[j] * reciprocal_square_sum_y);
}
}
}
}
/**
* Cosine Similarity backward Derivative
*
* \param outputs[0] forward input grad 1, size: nSamples * dim.
* \param outputs[1] forward input grad 2,
* size: n2 * dim (n2 == 1 or n2 == nSamples).
*
* \param inputs[0] backward loss output grad, size : nSamples * 1.
* \param inputs[1] forward output value, size: nSamples * 1.
* \param inputs[2] forward input value 1, size: nSamples * dim.
* \param inputs[3] forward input value 2,
* size: n2 * dim (n2 == 1 or n2 == nSamples).
*/
template <DeviceType Device>
class CosSimBackwardFunc : public FunctionBase {
void init(const FuncConfig& config) override {
scale_ = config.get<real>("scale");
}
void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
CHECK_EQ(inputs.size(), 4UL);
CHECK_EQ(outputs.size(), 2UL);
/// dim of out_grad and out_val == 1, column vector
CHECK_EQ(inputs[0].shape()[1], 1UL);
CHECK_EQ(inputs[1].shape()[1], 1UL);
/// nSamples of out_grad == out_val == in_val1 == in_grad1
CHECK_EQ(inputs[1].shape()[0], inputs[0].shape()[0]);
CHECK_EQ(inputs[0].shape()[0], inputs[0].shape()[0]);
CHECK_EQ(outputs[0].shape()[0], inputs[0].shape()[0]);
/// dim of in1_val1 == in_val2 == in_grad1 == in_grad2
CHECK_EQ(inputs[3].shape()[1], inputs[2].shape()[1]);
CHECK_EQ(outputs[0].shape()[1], inputs[2].shape()[1]);
CHECK_EQ(outputs[1].shape()[1], inputs[2].shape()[1]);
CHECK(inputs[0].data() && inputs[1].data() && inputs[2].data() &&
inputs[3].data() && outputs[0].data() && outputs[1].data());
CHECK_EQ(outputs[0].getArgType(), ADD_TO);
CHECK_EQ(outputs[1].getArgType(), ADD_TO);
const auto out_grad = inputs[0].matrix<Device>();
const auto out_val = inputs[1].matrix<Device>();
const auto in1_val = inputs[2].matrix<Device>();
const auto in2_val = inputs[3].matrix<Device>();
auto in1_grad = outputs[0].matrix<Device>();
auto in2_grad = outputs[1].matrix<Device>();
CosSimBackward<Device>(
out_grad, out_val, in1_val, in2_val, in1_grad, in2_grad, scale_);
}
private:
real scale_;
};
REGISTER_TYPED_FUNC(CosSimForward, CPU, CosSimForwardFunc);
REGISTER_TYPED_FUNC(CosSimBackward, CPU, CosSimBackwardFunc);
#ifndef PADDLE_ONLY_CPU
REGISTER_TYPED_FUNC(CosSimForward, GPU, CosSimForwardFunc);
REGISTER_TYPED_FUNC(CosSimBackward, GPU, CosSimBackwardFunc);
#endif
} // namespace paddle
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
#pragma once
#include "Function.h"
namespace paddle {
/**
* \brief Cosine Similarity Forward.
* for each row i,
* out[i] = scale * cos(in1[i], in2[i])
* = scale * \sum_j (in1[i][j] * in2[i][j]) /
* sqrt(sum_j (in1[i][j]^2) * sum_j (in2[i][j])^2)
*
* \param[out] output output value.
* \param[in] intput1 input value.
* \param[in] intput2 input value.
* \param[in] scale default 1.0.
*
*/
template <DeviceType Device>
void CosSimForward(typename Tensor<real, Device>::Matrix& output,
const typename Tensor<real, Device>::Matrix& input1,
const typename Tensor<real, Device>::Matrix& input2,
real scale);
/**
* \brief Cosine Similarity BackWard for Derivative.
*
* \param[in] output grad backward loss output grad.
* \param[in] output val forward-output value.
* \param[in] input val1 forward input value 1.
* \param[in] input val2 forward input value 2.
* \param[in/out] input grad forward input grad 1.
* \param[in/out] input grad forward input grad 2.
* \param[in] scale default 1.0.
*
*/
template <DeviceType Device>
void CosSimBackward(const typename Tensor<real, Device>::Matrix& out_grad,
const typename Tensor<real, Device>::Matrix& out_value,
const typename Tensor<real, Device>::Matrix& in1_value,
const typename Tensor<real, Device>::Matrix& in2_value,
typename Tensor<real, Device>::Matrix& in1_grad,
typename Tensor<real, Device>::Matrix& in2_grad,
real scale);
} // namespace paddle
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
#include "hl_base.h"
#include "hl_device_functions.cuh"
#include "CosSimOp.h"
namespace paddle {
template<int block_size>
__global__ void KeCosSim(real* output,
const real* input1,
const real* input2,
int width,
int input1_height,
int input2_height,
real scale) {
const int ty = blockIdx.y;
int tid = threadIdx.x;
__shared__ real xx[block_size];
__shared__ real yy[block_size];
__shared__ real xy[block_size];
xx[tid] = 0.0;
yy[tid] = 0.0;
xy[tid] = 0.0;
__syncthreads();
input1 += ty * width;
if (input2_height > 1) {
input2 += ty * width;
}
for (int index = tid; index < width; index += block_size) {
real x = input1[index];
real y = input2[index];
xx[tid] += x * x;
yy[tid] += y * y;
xy[tid] += x * y;
}
__syncthreads();
for (int s = block_size / 2; s > 0; s >>= 1) {
if (tid < s) {
xx[tid] += xx[tid + s];
yy[tid] += yy[tid + s];
xy[tid] += xy[tid + s];
}
__syncthreads();
}
if (tid == 0) {
output[ty] = scale * xy[0] / (sqrt(xx[0]) * sqrt(yy[0]));
}
}
void hlCossim(real* output,
const real* input1,
const real* input2,
size_t width,
size_t input1_height,
size_t input2_height,
real scale) {
CHECK_NOTNULL(output);
CHECK_NOTNULL(input1);
CHECK_NOTNULL(input2);
const int block_size = 256;
dim3 threads(block_size, 1);
dim3 grid(1, input1_height);
KeCosSim<block_size><<<grid, threads, 0, STREAM_DEFAULT>>>
(output, input1, input2, width, input1_height, input2_height, scale);
CHECK_SYNC("hlCossim failed");
}
template <>
void CosSimForward<DEVICE_TYPE_GPU>(GpuMatrix& out_mat,
const GpuMatrix& in1_mat,
const GpuMatrix& in2_mat,
real scale) {
CHECK(out_mat.getData() && in1_mat.getData() && in2_mat.getData());
CHECK(in1_mat.useGpu_ == true && in2_mat.useGpu_ == true)
<< "Matrix type are not GPU";
size_t num_samples = out_mat.getHeight();
size_t dim = in1_mat.getWidth();
real* out = out_mat.getData();
const real* x = in1_mat.getData();
const real* y = in2_mat.getData();
hlCossim(out, x, y, dim, in1_mat.getHeight(), in2_mat.getHeight(), scale);
}
template<int block_size>
__global__ void KeCosSimDerivative(const real* grad,
const real* output,
const real* prev_out_x,
const real* prev_out_y,
real* prev_grad_x,
real* prev_grad_y,
size_t width,
size_t input1_height,
size_t input2_height,
real scale) {
const int ty = blockIdx.y;
int tid = threadIdx.x;
__shared__ real xx[block_size];
__shared__ real yy[block_size];
__shared__ real xy[block_size];
xx[tid] = 0.0;
yy[tid] = 0.0;
xy[tid] = 0.0;
__syncthreads();
prev_out_x += ty * width;
prev_grad_x += ty * width;
if (input2_height > 1) {
prev_out_y += ty * width;
prev_grad_y += ty * width;
}
for (int index = tid; index < width; index += block_size) {
real x = prev_out_x[index];
real y = prev_out_y[index];
xx[tid] += x * x;
yy[tid] += y * y;
xy[tid] += x * y;
}
__syncthreads();
for (int s = block_size / 2; s > 0; s >>= 1) {
if (tid < s) {
xx[tid] += xx[tid + s];
yy[tid] += yy[tid + s];
xy[tid] += xy[tid + s];
}
__syncthreads();
}
if (xy[0] == 0) {
real reciprocal = 1.0 / (sqrt(xx[0]) * sqrt(yy[0]));
for (int index = tid; index < width; index += block_size) {
prev_grad_x[index] +=
scale * grad[ty] * prev_out_y[index] * reciprocal;
if (input2_height > 1) {
prev_grad_y[index] +=
scale * grad[ty] * prev_out_x[index] * reciprocal;
} else {
paddle::paddleAtomicAdd(prev_grad_y + index,
scale * grad[ty] * prev_out_x[index] * reciprocal);
}
}
} else {
real reciprocalXY = 1.0 / xy[0];
real reciprocalSquareSumX = 1.0 / xx[0];
real reciprocalSquareSumY = 1.0 / yy[0];
for (int index = tid; index < width; index += block_size) {
prev_grad_x[index] += output[ty] * grad[ty] *
(prev_out_y[index] * reciprocalXY -
prev_out_x[index] * reciprocalSquareSumX);
if (input2_height > 1) {
prev_grad_y[index] += output[ty] * grad[ty] *
(prev_out_x[index] * reciprocalXY -
prev_out_y[index] * reciprocalSquareSumY);
} else {
paddle::paddleAtomicAdd(prev_grad_y + index, output[ty] * grad[ty] *
(prev_out_x[index] * reciprocalXY -
prev_out_y[index] * reciprocalSquareSumY));
}
}
}
}
void hlCossimDerivative(const real* grad,
const real* output,
const real* prev_out_x,
const real* prev_out_y,
real* prev_grad_x,
real* prev_grad_y,
size_t width,
size_t input1_height,
size_t input2_height,
real scale) {
CHECK_NOTNULL(grad);
CHECK_NOTNULL(output);
CHECK_NOTNULL(prev_out_x);
CHECK_NOTNULL(prev_out_y);
CHECK_NOTNULL(prev_grad_x);
CHECK_NOTNULL(prev_grad_y);
const int block_size = 256;
dim3 threads(block_size, 1);
dim3 grid(1, input1_height);
KeCosSimDerivative<block_size><<<grid, threads, 0, STREAM_DEFAULT>>>
(grad, output, prev_out_x, prev_out_y, prev_grad_x, prev_grad_y, width,
input1_height, input2_height, scale);
CHECK_SYNC("hlCossimDerivate failed");
}
template <>
void CosSimBackward<DEVICE_TYPE_GPU>(const GpuMatrix& out_grad,
const GpuMatrix& out_val,
const GpuMatrix& in1_val,
const GpuMatrix& in2_val,
GpuMatrix& in1_grad,
GpuMatrix& in2_grad,
real scale) {
CHECK(out_grad.getData() && out_val.getData() && in1_val.getData() &&
in2_val.getData() && in1_grad.getData() && in2_grad.getData());
CHECK(out_grad.useGpu_ && out_val.useGpu_ && in1_val.useGpu_
&& in2_val.useGpu_ && in1_grad.useGpu_ && in2_grad.useGpu_)
<< "Matrix types are not equally GPU";
size_t dim = in1_val.getWidth();
const real* grad = out_grad.getData();
const real* out = out_val.getData();
const real* prev_out_x = in1_val.getData();
const real* prev_out_y = in2_val.getData();
real* prev_grad_x = in1_grad.getData();
real* prev_grad_y = in2_grad.getData();
hlCossimDerivative(grad,
out,
prev_out_x,
prev_out_y,
prev_grad_x,
prev_grad_y,
dim,
in1_val.getHeight(),
in2_val.getHeight(),
scale);
}
} // namespace paddle
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
#include <gtest/gtest.h>
#include "FunctionTest.h"
#include "paddle/math/Matrix.h"
using namespace paddle; // NOLINT
void testCosSimForward(size_t height_x,
size_t height_y,
size_t width,
real scale) {
FunctionCompare test("CosSimForward", FuncConfig().set("scale", scale));
// prepare input arguments
test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{height_x, width}));
test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{height_y, width}));
test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{height_x, 1}),
ASSIGN_TO);
// run Function
test.run();
}
void testCosSimBackward(size_t height_x,
size_t height_y,
size_t width,
real scale) {
FunctionCompare test("CosSimBackward", FuncConfig().set("scale", scale));
// prepare input arguments
test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{height_x, 1}));
test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{height_x, 1}));
test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{height_x, width}));
test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{height_y, width}));
test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{height_x, width}),
ADD_TO);
test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{height_y, width}),
ADD_TO);
// run Function
test.run();
}
TEST(Matrix, cosSim) {
for (auto height_x : {10, 100, 1000}) {
for (auto height_y : {1, height_x}) {
for (auto width : {10, 100, 1000}) {
for (auto scale : {1.0, 2.0}) {
testCosSimForward(height_x, height_y, width, scale);
testCosSimBackward(height_x, height_y, width, scale);
}
}
}
}
}
...@@ -69,6 +69,54 @@ public: ...@@ -69,6 +69,54 @@ public:
gpuMemory_.back()->getBuf(), input.valueType(), input.shape())); gpuMemory_.back()->getBuf(), input.valueType(), input.shape()));
} }
// assume one copy of sequence is shared by different SequenceArgs
void addSequence(const SequenceIdArg& input) {
CHECK_EQ(input.shape().ndims(), 1UL);
size_t batchSize = input.shape()[0];
size_t numSeqs = batchSize / 10 + 1;
size_t sizeId = (numSeqs + 1) * sizeOfValuType(VALUE_TYPE_INT32);
cpuMemory_.emplace_back(std::make_shared<CpuMemoryHandle>(sizeId));
gpuMemory_.emplace_back(std::make_shared<GpuMemoryHandle>(sizeId));
cpuSeq_ = std::make_shared<SequenceIdArg>(cpuMemory_.back()->getBuf(),
TensorShape{numSeqs + 1});
gpuSeq_ = std::make_shared<SequenceIdArg>(gpuMemory_.back()->getBuf(),
TensorShape{numSeqs + 1});
/// init sequence Id
initArg(*cpuSeq_, batchSize);
// todo(tianbing), delete it
CHECK_EQ(cpuSeq_->shape().getElements(), cpuSeq_->numSeqs() + 1);
CpuIVector cpuSeq(cpuSeq_->shape().getElements(), (int*)cpuSeq_->data());
GpuIVector gpuSeq(gpuSeq_->shape().getElements(), (int*)gpuSeq_->data());
gpuSeq.copyFrom(cpuSeq);
}
void addInputs(const SequenceArg& input) {
CHECK_EQ(input.shape().ndims(), 2UL);
size_t batchSize = input.shape()[0];
if (!cpuSeq_ || !gpuSeq_) { // sequence not exist
addSequence(SequenceIdArg(TensorShape{batchSize}));
}
size_t size =
input.shape().getElements() * sizeOfValuType(input.valueType());
cpuMemory_.emplace_back(std::make_shared<CpuMemoryHandle>(size));
gpuMemory_.emplace_back(std::make_shared<GpuMemoryHandle>(size));
/// SequenceArg
cpuInputs_.emplace_back(
std::make_shared<SequenceArg>(cpuMemory_.back()->getBuf(),
input.valueType(),
input.shape(),
*cpuSeq_));
gpuInputs_.emplace_back(
std::make_shared<SequenceArg>(gpuMemory_.back()->getBuf(),
input.valueType(),
input.shape(),
*gpuSeq_));
}
// output need only contains shape, do not contains data. // output need only contains shape, do not contains data.
void addOutputs(const BufferArg& output, ArgType argType = ASSIGN_TO) { void addOutputs(const BufferArg& output, ArgType argType = ASSIGN_TO) {
size_t size = size_t size =
...@@ -116,24 +164,31 @@ public: ...@@ -116,24 +164,31 @@ public:
std::make_shared<SparseMatrixArg>(*gpuSparse_, argType)); std::make_shared<SparseMatrixArg>(*gpuSparse_, argType));
} }
void addInputs(const SequenceArg& input) { void addOutputs(const SequenceArg& output, ArgType argType = ASSIGN_TO) {
size_t batchSize = input.shape()[0]; CHECK_EQ(output.shape().ndims(), 2UL);
size_t numSeqs = batchSize / 10 + 1; size_t batchSize = output.shape()[0];
size_t sizeId = (numSeqs + 1) * sizeOfValuType(VALUE_TYPE_INT32);
cpuMemory_.emplace_back(std::make_shared<CpuMemoryHandle>(sizeId));
gpuMemory_.emplace_back(std::make_shared<GpuMemoryHandle>(sizeId));
TensorShape seqsId({numSeqs + 1});
// void* cpuBuffer = cpuMemory_.back()->getBuf();
// void* gpuBuffer = gpuMemory_.back()->getBuf();
if (!cpuSeq_ || !gpuSeq_) { // sequence not exist
addSequence(SequenceIdArg(TensorShape{batchSize}));
}
size_t size = size_t size =
input.shape().getElements() * sizeOfValuType(input.valueType()); output.shape().getElements() * sizeOfValuType(output.valueType());
cpuMemory_.emplace_back(std::make_shared<CpuMemoryHandle>(size)); cpuMemory_.emplace_back(std::make_shared<CpuMemoryHandle>(size));
gpuMemory_.emplace_back(std::make_shared<GpuMemoryHandle>(size)); gpuMemory_.emplace_back(std::make_shared<GpuMemoryHandle>(size));
// TODO: need be implemented. /// SequenceArg
cpuOutputs_.emplace_back(
std::make_shared<SequenceArg>(cpuMemory_.back()->getBuf(),
output.valueType(),
output.shape(),
*cpuSeq_,
argType));
gpuOutputs_.emplace_back(
std::make_shared<SequenceArg>(gpuMemory_.back()->getBuf(),
output.valueType(),
output.shape(),
*gpuSeq_,
argType));
} }
void addInputs(const SparseMatrixArg& input) { void addInputs(const SparseMatrixArg& input) {
...@@ -193,14 +248,44 @@ public: ...@@ -193,14 +248,44 @@ public:
std::shared_ptr<FunctionBase> getGpuFunction() const { return gpuFunc_; } std::shared_ptr<FunctionBase> getGpuFunction() const { return gpuFunc_; }
protected: protected:
// only init cpu argument, gpu argument copy from cpu argument.
void initArg(BufferArg& arg) {
CpuVector vector(arg.shape().getElements(), (real*)arg.data());
vector.uniform(0.001, 1);
}
void initArg(SequenceArg& arg) {
/// init only matrix
CpuVector vector(arg.shape().getElements(), (real*)arg.data());
vector.uniform(0.001, 1);
}
void initArg(SequenceIdArg& arg, size_t batchSize) {
size_t numSeqs = arg.numSeqs();
int* buf = reinterpret_cast<int*>(arg.data());
int pos = 0;
size_t maxLen = 2 * batchSize / numSeqs;
for (int i = 0; i < (int)numSeqs; ++i) {
int len = 1 + uniformRandom(std::min<int64_t>(
maxLen, batchSize - pos - numSeqs + i));
buf[i] = pos;
pos += len;
VLOG(1) << " len=" << len;
}
buf[numSeqs] = batchSize;
}
void initInputs() { void initInputs() {
for (size_t i = 0; i < cpuInputs_.size(); i++) { for (size_t i = 0; i < cpuInputs_.size(); i++) {
if (cpuInputs_[i]->isSparseArg()) { if (cpuInputs_[i]->isSparseArg()) {
continue; /// sparse matrix already init continue; /// sparse matrix already init
} }
initArg(*cpuInputs_[i]); if (cpuInputs_[i]->isSequenceArg()) {
initArg(dynamic_cast<SequenceArg&>(*cpuInputs_[i]));
} else {
initArg(*cpuInputs_[i]);
}
// TODO: Need a BufferCopy used to copy from one BufferArg to another. // TODO: Need a BufferCopy used to copy from one BufferArg to another.
CpuVector cpuVector(cpuInputs_[i]->shape().getElements(), CpuVector cpuVector(cpuInputs_[i]->shape().getElements(),
(real*)cpuInputs_[i]->data()); (real*)cpuInputs_[i]->data());
...@@ -217,7 +302,11 @@ protected: ...@@ -217,7 +302,11 @@ protected:
continue; /// sparse matrix already init continue; /// sparse matrix already init
} }
initArg(*cpuOutputs_[i]); if (cpuOutputs_[i]->isSequenceArg()) {
initArg(dynamic_cast<SequenceArg&>(*cpuOutputs_[i]));
} else {
initArg(*cpuOutputs_[i]);
}
// TODO: Need a BufferCopy used to copy from one BufferArg to another. // TODO: Need a BufferCopy used to copy from one BufferArg to another.
CpuVector cpuVector(cpuOutputs_[i]->shape().getElements(), CpuVector cpuVector(cpuOutputs_[i]->shape().getElements(),
...@@ -241,28 +330,6 @@ protected: ...@@ -241,28 +330,6 @@ protected:
} }
} }
// only init cpu argument, gpu argument copy from cpu argument.
void initArg(BufferArg& arg) {
CpuVector vector(arg.shape().getElements(), (real*)arg.data());
vector.uniform(0.001, 1);
}
void initArg(SequenceIdArg& arg, size_t batchSize) {
size_t numSeqs = arg.numSeqs();
int* buf = reinterpret_cast<int*>(arg.data());
int pos = 0;
size_t maxLen = 2 * batchSize / numSeqs;
for (int i = 0; i < (int)numSeqs; ++i) {
int len = uniformRandom(
std::min<int64_t>(maxLen, batchSize - pos - numSeqs + i)) +
1;
buf[i] = pos;
pos += len;
VLOG(1) << " len=" << len;
}
buf[numSeqs] = batchSize;
}
protected: protected:
std::shared_ptr<FunctionBase> cpuFunc_; std::shared_ptr<FunctionBase> cpuFunc_;
std::shared_ptr<FunctionBase> gpuFunc_; std::shared_ptr<FunctionBase> gpuFunc_;
...@@ -274,6 +341,8 @@ protected: ...@@ -274,6 +341,8 @@ protected:
std::vector<BufferArgPtr> gpuOutputs_; std::vector<BufferArgPtr> gpuOutputs_;
std::shared_ptr<CpuSparseMatrix> cpuSparse_; std::shared_ptr<CpuSparseMatrix> cpuSparse_;
std::shared_ptr<GpuSparseMatrix> gpuSparse_; std::shared_ptr<GpuSparseMatrix> gpuSparse_;
std::shared_ptr<SequenceIdArg> cpuSeq_;
std::shared_ptr<SequenceIdArg> gpuSeq_;
}; };
} // namespace paddle } // namespace paddle
...@@ -60,7 +60,7 @@ TEST(MulOp, DDDMatrixMul) { ...@@ -60,7 +60,7 @@ TEST(MulOp, DDDMatrixMul) {
if (transa && transb) { if (transa && transb) {
continue; continue;
} }
VLOG(3) << setiosflags(std::ios::left) << std::setfill(' ') VLOG(3) << std::setiosflags(std::ios::left) << std::setfill(' ')
<< " transa=" << transa << " transb=" << transb << " transa=" << transa << " transb=" << transb
<< " dimM=" << std::setw(5) << dimM << " dimM=" << std::setw(5) << dimM
<< " dimN=" << std::setw(5) << dimN << " dimN=" << std::setw(5) << dimN
...@@ -104,7 +104,7 @@ TEST(MuLOp, DSparseDMul) { ...@@ -104,7 +104,7 @@ TEST(MuLOp, DSparseDMul) {
for (const auto dimK : {3, 10}) { for (const auto dimK : {3, 10}) {
for (const auto nnz : {3, 10}) { for (const auto nnz : {3, 10}) {
for (const auto FORMAT : {SPARSE_CSR}) { for (const auto FORMAT : {SPARSE_CSR}) {
VLOG(3) << setiosflags(std::ios::left) << std::setfill(' ') VLOG(3) << std::setiosflags(std::ios::left) << std::setfill(' ')
<< " dimM=" << std::setw(5) << dimM << " dimM=" << std::setw(5) << dimM
<< " dimN=" << std::setw(5) << dimN << " dimN=" << std::setw(5) << dimN
<< " dimK=" << std::setw(5) << dimK << " dimK=" << std::setw(5) << dimK
...@@ -150,7 +150,7 @@ TEST(MulOp, DDSparseMul) { ...@@ -150,7 +150,7 @@ TEST(MulOp, DDSparseMul) {
for (const auto dimK : {3, 10}) { for (const auto dimK : {3, 10}) {
for (const auto nnz : {3, 10}) { for (const auto nnz : {3, 10}) {
for (const auto FORMAT : {SPARSE_CSR, SPARSE_CSC}) { for (const auto FORMAT : {SPARSE_CSR, SPARSE_CSC}) {
VLOG(3) << setiosflags(std::ios::left) << std::setfill(' ') VLOG(3) << std::setiosflags(std::ios::left) << std::setfill(' ')
<< " dimM=" << std::setw(5) << dimM << " dimM=" << std::setw(5) << dimM
<< " dimN=" << std::setw(5) << dimN << " dimN=" << std::setw(5) << dimN
<< " dimK=" << std::setw(5) << dimK << " dimK=" << std::setw(5) << dimK
...@@ -197,7 +197,7 @@ TEST(MulOp, SparseDDMul) { ...@@ -197,7 +197,7 @@ TEST(MulOp, SparseDDMul) {
for (const auto dimK : {3, 10}) { for (const auto dimK : {3, 10}) {
for (const auto nnz : {3, 10}) { for (const auto nnz : {3, 10}) {
for (const auto FORMAT : {SPARSE_CSC, SPARSE_CSR}) { for (const auto FORMAT : {SPARSE_CSC, SPARSE_CSR}) {
VLOG(3) << setiosflags(std::ios::left) << std::setfill(' ') VLOG(3) << std::setiosflags(std::ios::left) << std::setfill(' ')
<< " dimM=" << std::setw(5) << dimM << " dimM=" << std::setw(5) << dimM
<< " dimN=" << std::setw(5) << dimN << " dimN=" << std::setw(5) << dimN
<< " dimK=" << std::setw(5) << dimK << " dimK=" << std::setw(5) << dimK
......
...@@ -647,7 +647,7 @@ public: ...@@ -647,7 +647,7 @@ public:
DataBatch& gpuBatch = *batch; DataBatch& gpuBatch = *batch;
std::vector<Argument>& gpuArguments = gpuBatch.getStreams(); std::vector<Argument>& gpuArguments = gpuBatch.getStreams();
gpuArguments.resize(cpuArguments.size()); gpuArguments.resize(cpuArguments.size());
gpuBatch.setSize(size); gpuBatch.setSize(bsize);
for (size_t i = 0; i < headers_.size(); ++i) { for (size_t i = 0; i < headers_.size(); ++i) {
gpuArguments[i].resizeAndCopyFrom( gpuArguments[i].resizeAndCopyFrom(
cpuArguments[i], useGpu_, HPPL_STREAM_1); cpuArguments[i], useGpu_, HPPL_STREAM_1);
......
...@@ -866,21 +866,20 @@ void PnpairEvaluator::calc(std::vector<PredictionResult>& predictArray) { ...@@ -866,21 +866,20 @@ void PnpairEvaluator::calc(std::vector<PredictionResult>& predictArray) {
ClassRegistrar<Evaluator> Evaluator::registrar_; ClassRegistrar<Evaluator> Evaluator::registrar_;
Evaluator* Evaluator::create(const EvaluatorConfig& config) { Evaluator* Evaluator::create(const EvaluatorConfig& config) {
Evaluator* evaluator = nullptr; Evaluator* evaluator = registrar_.createByType(config.type());
if (config.type() == "classification_error") {
evaluator = new ClassificationErrorEvaluator();
} else if (config.type() == "sum") {
evaluator = new SumEvaluator();
} else if (config.type() == "last-column-sum") {
evaluator = new ColumnSumEvaluator(-1);
} else if (config.type() == "last-column-auc") {
evaluator = new AucEvaluator(-1);
} else {
evaluator = registrar_.createByType(config.type());
}
evaluator->init(config); evaluator->init(config);
return evaluator; return evaluator;
} }
REGISTER_EVALUATOR(classification_error, ClassificationErrorEvaluator);
REGISTER_EVALUATOR(sum, SumEvaluator);
static InitFunction __reg_type_auc_sum__([]() {
Evaluator::registrar_.registerClass(
"last-column-sum", [] { return new ColumnSumEvaluator(-1); });
Evaluator::registrar_.registerClass("last-column-auc",
[] { return new AucEvaluator(-1); });
});
/** /**
* @brief print value of each layer. * @brief print value of each layer.
* *
...@@ -888,32 +887,10 @@ Evaluator* Evaluator::create(const EvaluatorConfig& config) { ...@@ -888,32 +887,10 @@ Evaluator* Evaluator::create(const EvaluatorConfig& config) {
*/ */
class ValuePrinter : public Evaluator { class ValuePrinter : public Evaluator {
public: public:
ValuePrinter() {}
virtual void eval(const NeuralNetwork& nn) { virtual void eval(const NeuralNetwork& nn) {
for (const std::string& name : config_.input_layers()) { for (const std::string& name : config_.input_layers()) {
const Argument& argu = nn.getLayer(name)->getOutput(); nn.getLayer(name)->getOutput().printValueString(LOG(INFO),
if (argu.value) { "layer=" + name + " ");
std::ostringstream os;
argu.value->print(os);
LOG(INFO) << "layer=" << name << " value matrix:\n" << os.str();
}
if (argu.ids) {
std::ostringstream os;
argu.ids->print(os, argu.ids->getSize());
LOG(INFO) << "layer=" << name << " ids vector:\n" << os.str();
}
if (auto startPos = argu.sequenceStartPositions) {
std::ostringstream os;
startPos->getVector(false)->print(os, startPos->getSize());
LOG(INFO) << "layer=" << name << " sequence pos vector:\n" << os.str();
}
if (auto subStartPos = argu.subSequenceStartPositions) {
std::ostringstream os;
subStartPos->getVector(false)->print(os, subStartPos->getSize());
LOG(INFO) << "layer=" << name << " sub-sequence pos vector:\n"
<< os.str();
}
} }
} }
...@@ -929,8 +906,6 @@ REGISTER_EVALUATOR(value_printer, ValuePrinter); ...@@ -929,8 +906,6 @@ REGISTER_EVALUATOR(value_printer, ValuePrinter);
*/ */
class GradientPrinter : public Evaluator { class GradientPrinter : public Evaluator {
public: public:
GradientPrinter() {}
virtual void eval(const NeuralNetwork& nn) { virtual void eval(const NeuralNetwork& nn) {
for (const std::string& name : config_.input_layers()) { for (const std::string& name : config_.input_layers()) {
const Argument& argu = nn.getLayer(name)->getOutput(); const Argument& argu = nn.getLayer(name)->getOutput();
...@@ -939,11 +914,6 @@ public: ...@@ -939,11 +914,6 @@ public:
argu.grad->print(os); argu.grad->print(os);
LOG(INFO) << "layer=" << name << " grad matrix:\n" << os.str(); LOG(INFO) << "layer=" << name << " grad matrix:\n" << os.str();
} }
if (auto startPos = argu.sequenceStartPositions) {
std::ostringstream os;
startPos->getVector(false)->print(os, startPos->getSize());
LOG(INFO) << "layer=" << name << " sequence pos vector:\n" << os.str();
}
} }
} }
......
...@@ -155,7 +155,8 @@ protected: ...@@ -155,7 +155,8 @@ protected:
public: public:
explicit BootBiasLayer(const LayerConfig& config) : Layer(config) {} explicit BootBiasLayer(const LayerConfig& config) : Layer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap) { bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override {
if (!Layer::init(layerMap, parameterMap)) return false; if (!Layer::init(layerMap, parameterMap)) return false;
if (biasParameter_) { if (biasParameter_) {
...@@ -174,7 +175,7 @@ public: ...@@ -174,7 +175,7 @@ public:
} }
} }
virtual void forward(PassType passType) { void forward(PassType passType) override {
if (biases_) { if (biases_) {
MatrixPtr outV = getOutputValue(); MatrixPtr outV = getOutputValue();
outV->addBias(*(biases_->getW()), 1); outV->addBias(*(biases_->getW()), 1);
...@@ -182,7 +183,7 @@ public: ...@@ -182,7 +183,7 @@ public:
} }
} }
virtual void backward(const UpdateCallback& callback) { void backward(const UpdateCallback& callback) override {
if (biases_) { if (biases_) {
backwardActivation(); backwardActivation();
biases_->getWGrad()->collectBias(*getOutputGrad(), 1); biases_->getWGrad()->collectBias(*getOutputGrad(), 1);
......
...@@ -44,19 +44,20 @@ public: ...@@ -44,19 +44,20 @@ public:
/** /**
* Intialization of AddtoLayer. * Intialization of AddtoLayer.
*/ */
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
/** /**
* Forward propagation. * Forward propagation.
* @note There is no weight matrix for each input, * @note There is no weight matrix for each input,
* because it just a simple add operation. * because it just a simple add operation.
*/ */
void forward(PassType passType); void forward(PassType passType) override;
/** /**
* Backward propagation. * Backward propagation.
*/ */
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -35,7 +35,8 @@ public: ...@@ -35,7 +35,8 @@ public:
~AgentLayer() {} ~AgentLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
// if *numSamples* set, // if *numSamples* set,
// real layer output will only use first *numSamples* rows // real layer output will only use first *numSamples* rows
...@@ -44,8 +45,8 @@ public: ...@@ -44,8 +45,8 @@ public:
numSamples_ = numSamples; numSamples_ = numSamples;
} }
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr) {} void backward(const UpdateCallback& callback = nullptr) override {}
}; };
/** /**
...@@ -56,8 +57,8 @@ public: ...@@ -56,8 +57,8 @@ public:
explicit SequenceAgentLayer(const LayerConfig& config) : AgentLayer(config) {} explicit SequenceAgentLayer(const LayerConfig& config) : AgentLayer(config) {}
~SequenceAgentLayer() {} ~SequenceAgentLayer() {}
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr) {} void backward(const UpdateCallback& callback = nullptr) override {}
}; };
/** /**
...@@ -78,7 +79,8 @@ public: ...@@ -78,7 +79,8 @@ public:
virtual ~GatherAgentLayer() {} virtual ~GatherAgentLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
// call before addRealLayer // call before addRealLayer
void copyIdAndSequenceInfo(const Argument& input, void copyIdAndSequenceInfo(const Argument& input,
...@@ -88,8 +90,8 @@ public: ...@@ -88,8 +90,8 @@ public:
// add one real layer, can call many times // add one real layer, can call many times
void addRealLayer(LayerPtr layer) { realLayers_.push_back(layer); } void addRealLayer(LayerPtr layer) { realLayers_.push_back(layer); }
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback); void backward(const UpdateCallback& callback) override;
}; };
/** /**
...@@ -133,7 +135,8 @@ public: ...@@ -133,7 +135,8 @@ public:
virtual ~ScatterAgentLayer() {} virtual ~ScatterAgentLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
/** /**
* @brief set real layer in generation * @brief set real layer in generation
...@@ -182,8 +185,8 @@ public: ...@@ -182,8 +185,8 @@ public:
numSequences_ = numSequences; numSequences_ = numSequences;
} }
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback); void backward(const UpdateCallback& callback) override;
}; };
/** /**
......
...@@ -38,12 +38,11 @@ public: ...@@ -38,12 +38,11 @@ public:
explicit AverageLayer(const LayerConfig& config) explicit AverageLayer(const LayerConfig& config)
: SequencePoolLayer(config) {} : SequencePoolLayer(config) {}
~AverageLayer() {} bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr) override;
void forward(PassType passType);
void backward(const UpdateCallback& callback = nullptr);
protected: protected:
MatrixPtr outMtx_; MatrixPtr outMtx_;
......
...@@ -52,7 +52,8 @@ public: ...@@ -52,7 +52,8 @@ public:
*/ */
static Layer* create(const LayerConfig& config); static Layer* create(const LayerConfig& config);
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
/** /**
* @brief Calculate feature map size. Some input uses frameHeight and * @brief Calculate feature map size. Some input uses frameHeight and
......
...@@ -33,9 +33,10 @@ public: ...@@ -33,9 +33,10 @@ public:
~BatchNormalizationLayer() {} ~BatchNormalizationLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
void forward(PassType passType); const ParameterMap& parameterMap) override;
void backward(const UpdateCallback& callback = nullptr); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr) override;
protected: protected:
/// Epsilon value used in the batch normalization formula. /// Epsilon value used in the batch normalization formula.
...@@ -58,7 +59,7 @@ protected: ...@@ -58,7 +59,7 @@ protected:
/// to batch, channels* imagePixels. /// to batch, channels* imagePixels.
void shrinkMat(const MatrixPtr& in, MatrixPtr& out); void shrinkMat(const MatrixPtr& in, MatrixPtr& out);
void onPassEnd() { firstTest_ = true; } void onPassEnd() override { firstTest_ = true; }
MatrixPtr tmpMat_, tmpGrad_; MatrixPtr tmpMat_, tmpGrad_;
MatrixPtr expandedIn_, expandedOut_; MatrixPtr expandedIn_, expandedOut_;
......
...@@ -38,9 +38,10 @@ public: ...@@ -38,9 +38,10 @@ public:
virtual ~BilinearInterpLayer() {} virtual ~BilinearInterpLayer() {}
size_t getSize(); size_t getSize();
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
void forward(PassType passType); const ParameterMap& parameterMap) override;
void backward(const UpdateCallback& callback = nullptr); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -58,10 +58,11 @@ public: ...@@ -58,10 +58,11 @@ public:
~BlockExpandLayer() {} ~BlockExpandLayer() {}
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
virtual void forward(PassType passType); void forward(PassType passType) override;
virtual void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -32,9 +32,10 @@ namespace paddle { ...@@ -32,9 +32,10 @@ namespace paddle {
class CRFDecodingLayer : public CRFLayer { class CRFDecodingLayer : public CRFLayer {
public: public:
explicit CRFDecodingLayer(const LayerConfig& config) : CRFLayer(config) {} explicit CRFDecodingLayer(const LayerConfig& config) : CRFLayer(config) {}
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
virtual void forward(PassType passType); const ParameterMap& parameterMap) override;
virtual void backward(const UpdateCallback& callback); void forward(PassType passType) override;
void backward(const UpdateCallback& callback) override;
protected: protected:
std::unique_ptr<LinearChainCRF> crf_; std::unique_ptr<LinearChainCRF> crf_;
......
...@@ -29,9 +29,10 @@ namespace paddle { ...@@ -29,9 +29,10 @@ namespace paddle {
class CRFLayer : public Layer { class CRFLayer : public Layer {
public: public:
explicit CRFLayer(const LayerConfig& config) : Layer(config) {} explicit CRFLayer(const LayerConfig& config) : Layer(config) {}
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
virtual void forward(PassType passType); const ParameterMap& parameterMap) override;
virtual void backward(const UpdateCallback& callback); void forward(PassType passType) override;
void backward(const UpdateCallback& callback) override;
protected: protected:
size_t numClasses_; size_t numClasses_;
......
...@@ -22,10 +22,11 @@ namespace paddle { ...@@ -22,10 +22,11 @@ namespace paddle {
class CTCLayer : public Layer { class CTCLayer : public Layer {
public: public:
explicit CTCLayer(const LayerConfig& config) : Layer(config) {} explicit CTCLayer(const LayerConfig& config) : Layer(config) {}
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
virtual void forward(PassType passType); const ParameterMap& parameterMap) override;
void forward(PassType passType) override;
void forwardImp(const Argument& softmaxSeqs, const Argument& labelSeqs); void forwardImp(const Argument& softmaxSeqs, const Argument& labelSeqs);
virtual void backward(const UpdateCallback& callback); void backward(const UpdateCallback& callback) override;
void backwardImp(const UpdateCallback& callback, void backwardImp(const UpdateCallback& callback,
const Argument& softmaxSeqs, const Argument& softmaxSeqs,
const Argument& labelSeqs); const Argument& labelSeqs);
......
...@@ -28,10 +28,11 @@ public: ...@@ -28,10 +28,11 @@ public:
~ConcatenateLayer() {} ~ConcatenateLayer() {}
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
virtual void forward(PassType passType); void forward(PassType passType) override;
virtual void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
REGISTER_LAYER(concat, ConcatenateLayer); REGISTER_LAYER(concat, ConcatenateLayer);
...@@ -101,10 +102,11 @@ public: ...@@ -101,10 +102,11 @@ public:
~ConcatenateLayer2() {} ~ConcatenateLayer2() {}
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
virtual void forward(PassType passType); void forward(PassType passType) override;
virtual void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
protected: protected:
std::vector<std::unique_ptr<Projection>> projections_; std::vector<std::unique_ptr<Projection>> projections_;
......
...@@ -80,7 +80,8 @@ protected: ...@@ -80,7 +80,8 @@ protected:
public: public:
explicit ConvBaseLayer(const LayerConfig& config) : Layer(config) {} explicit ConvBaseLayer(const LayerConfig& config) : Layer(config) {}
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
/** /**
* imgSizeH_ and imgSizeW_ will be set according to the previous input layers * imgSizeH_ and imgSizeW_ will be set according to the previous input layers
......
...@@ -47,10 +47,11 @@ public: ...@@ -47,10 +47,11 @@ public:
~ConvShiftLayer() {} ~ConvShiftLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
REGISTER_LAYER(conv_shift, ConvShiftLayer); REGISTER_LAYER(conv_shift, ConvShiftLayer);
......
...@@ -49,10 +49,11 @@ public: ...@@ -49,10 +49,11 @@ public:
~ConvexCombinationLayer() {} ~ConvexCombinationLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
REGISTER_LAYER(convex_comb, ConvexCombinationLayer); REGISTER_LAYER(convex_comb, ConvexCombinationLayer);
......
...@@ -26,15 +26,23 @@ bool CosSimLayer::init(const LayerMap& layerMap, ...@@ -26,15 +26,23 @@ bool CosSimLayer::init(const LayerMap& layerMap,
Layer::init(layerMap, parameterMap); Layer::init(layerMap, parameterMap);
CHECK_EQ(inputLayers_.size(), 2LU); CHECK_EQ(inputLayers_.size(), 2LU);
createFunction(forward_,
"CosSimForward",
FuncConfig().set("scale", (real)config_.cos_scale()));
createFunction(backward_,
"CosSimBackward",
FuncConfig().set("scale", (real)config_.cos_scale()));
return true; return true;
} }
void CosSimLayer::forward(PassType passType) { void CosSimLayer::forward(PassType passType) {
Layer::forward(passType); Layer::forward(passType);
/* malloc memory for the output_ if necessary */ /* malloc memory for the output_ if necessary */
int batchSize = getInputValue(0)->getHeight(); int batchSize = getInputValue(0)->getHeight();
int size = getSize(); int size = getSize();
CHECK_EQ(forward_.size(), 1) << "Only one forward function needed";
{ {
REGISTER_TIMER_INFO("CosFwResetTimer", getName().c_str()); REGISTER_TIMER_INFO("CosFwResetTimer", getName().c_str());
...@@ -42,26 +50,43 @@ void CosSimLayer::forward(PassType passType) { ...@@ -42,26 +50,43 @@ void CosSimLayer::forward(PassType passType) {
} }
MatrixPtr outV = getOutputValue(); MatrixPtr outV = getOutputValue();
/* activation */ { /* activation */ {
REGISTER_TIMER_INFO("CosFwAtvTimer", getName().c_str()); REGISTER_TIMER_INFO("CosFwAtvTimer", getName().c_str());
MatrixPtr prevOut1 = getInputValue(0); MatrixPtr prevOut1 = getInputValue(0);
MatrixPtr prevOut2 = getInputValue(1); MatrixPtr prevOut2 = getInputValue(1);
outV->cosSim(*prevOut1, *prevOut2, config_.cos_scale());
CHECK(outV && prevOut1 && prevOut2);
BufferArgs inputs;
BufferArgs outputs;
inputs.addArg(*prevOut1);
inputs.addArg(*prevOut2);
outputs.addArg(*outV, ASSIGN_TO);
forward_[0]->calc(inputs, outputs);
} }
} }
void CosSimLayer::backward(const UpdateCallback& callback) { void CosSimLayer::backward(const UpdateCallback& callback) {
/* activation */ { /* activation */ {
REGISTER_TIMER_INFO("CosBpAtvTimer", getName().c_str()); REGISTER_TIMER_INFO("CosBpAtvTimer", getName().c_str());
MatrixPtr outG = this->getOutputGrad(); CHECK_EQ(backward_.size(), 1) << "Only one backward function needed";
outG->cosSimDerivative(*this->getOutputValue(), const auto outG = this->getOutputGrad();
*getInputValue(0), const auto outV = this->getOutputValue();
*getInputValue(1), const auto inV1 = this->getInputValue(0);
*getInputGrad(0), const auto inV2 = this->getInputValue(1);
*getInputGrad(1), auto inG1 = this->getInputGrad(0);
config_.cos_scale()); auto inG2 = this->getInputGrad(1);
CHECK(outG && outV && inV1 && inV2 && inG1 && inG2);
BufferArgs inputs;
BufferArgs outputs;
inputs.addArg(*outG);
inputs.addArg(*outV);
inputs.addArg(*inV1);
inputs.addArg(*inV2);
outputs.addArg(*inG1, ADD_TO);
outputs.addArg(*inG2, ADD_TO);
backward_[0]->calc(inputs, outputs);
} }
} }
......
...@@ -28,7 +28,7 @@ namespace paddle { ...@@ -28,7 +28,7 @@ namespace paddle {
* *
* - Input1: A vector (batchSize * dataDim) * * - Input1: A vector (batchSize * dataDim) *
* - Input2: A vector (batchSize * dataDim) or (1 * dataDim) * * - Input2: A vector (batchSize * dataDim) or (1 * dataDim) *
* - Output: A vector (dataDim * 1) * - Output: A vector (batchSize * 1)
* *
* The config file api is cos_sim. * The config file api is cos_sim.
*/ */
...@@ -38,10 +38,11 @@ public: ...@@ -38,10 +38,11 @@ public:
~CosSimLayer() {} ~CosSimLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -18,7 +18,6 @@ limitations under the License. */ ...@@ -18,7 +18,6 @@ limitations under the License. */
#include "paddle/utils/Stat.h" #include "paddle/utils/Stat.h"
namespace paddle { namespace paddle {
/** /**
* @brief A layer for computing cosine similarity between a vector * @brief A layer for computing cosine similarity between a vector
* and each row of a matrix * and each row of a matrix
...@@ -46,10 +45,11 @@ public: ...@@ -46,10 +45,11 @@ public:
~CosSimVecMatLayer() {} ~CosSimVecMatLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
REGISTER_LAYER(cos_vm, CosSimVecMatLayer); REGISTER_LAYER(cos_vm, CosSimVecMatLayer);
...@@ -97,11 +97,22 @@ bool CosSimVecMatLayer::init(const LayerMap& layerMap, ...@@ -97,11 +97,22 @@ bool CosSimVecMatLayer::init(const LayerMap& layerMap,
dataDim, dataDim,
/* trans= */ false, /* trans= */ false,
useGpu_); useGpu_);
CHECK(tmpRow0 && tmpRow1 && tmpRow2 && tmpRow3 && tmpMtx0 && tmpMtx1);
createFunction(forward_,
"CosSimForward",
FuncConfig().set("scale", (real)config_.cos_scale()));
createFunction(backward_,
"CosSimBackward",
FuncConfig().set("scale", (real)config_.cos_scale()));
return true; return true;
} }
void CosSimVecMatLayer::forward(PassType passType) { void CosSimVecMatLayer::forward(PassType passType) {
Layer::forward(passType); Layer::forward(passType);
CHECK_EQ(forward_.size(), 1) << "Only one forward function needed";
MatrixPtr inV0 = getInputValue(0); MatrixPtr inV0 = getInputValue(0);
MatrixPtr inV1 = getInputValue(1); MatrixPtr inV1 = getInputValue(1);
...@@ -117,17 +128,25 @@ void CosSimVecMatLayer::forward(PassType passType) { ...@@ -117,17 +128,25 @@ void CosSimVecMatLayer::forward(PassType passType) {
} }
MatrixPtr outV = getOutputValue(); MatrixPtr outV = getOutputValue();
CHECK(outV && inV0 && inV1);
REGISTER_TIMER_INFO("FwCosVMTimer", getName().c_str()); REGISTER_TIMER_INFO("FwCosVMTimer", getName().c_str());
for (size_t i = 0; i < batchSize; i++) { for (size_t i = 0; i < batchSize; i++) {
tmpRow0->setData(inV0->rowBuf(i)); tmpRow0->setData(inV0->rowBuf(i));
tmpMtx0->setData(inV1->rowBuf(i)); tmpMtx0->setData(inV1->rowBuf(i));
tmpRow2->setData(outV->rowBuf(i)); tmpRow2->setData(outV->rowBuf(i));
tmpRow2->cosSim(*(tmpMtx0), *(tmpRow0), config_.cos_scale());
BufferArgs inputs;
BufferArgs outputs;
inputs.addArg(*tmpMtx0);
inputs.addArg(*tmpRow0);
outputs.addArg(*tmpRow2, ASSIGN_TO);
forward_[0]->calc(inputs, outputs);
} }
} }
void CosSimVecMatLayer::backward(const UpdateCallback& callback) { void CosSimVecMatLayer::backward(const UpdateCallback& callback) {
CHECK_EQ(backward_.size(), 1) << "Only one forward function needed";
MatrixPtr inV0 = getInputValue(0); MatrixPtr inV0 = getInputValue(0);
MatrixPtr inV1 = getInputValue(1); MatrixPtr inV1 = getInputValue(1);
MatrixPtr inG0 = getInputGrad(0); MatrixPtr inG0 = getInputGrad(0);
...@@ -136,27 +155,27 @@ void CosSimVecMatLayer::backward(const UpdateCallback& callback) { ...@@ -136,27 +155,27 @@ void CosSimVecMatLayer::backward(const UpdateCallback& callback) {
MatrixPtr outG = getOutputGrad(); MatrixPtr outG = getOutputGrad();
size_t batchSize = inV0->getHeight(); size_t batchSize = inV0->getHeight();
CHECK(inV0 && inV1 && inG0 && inG1 && outV && outG);
REGISTER_TIMER_INFO("BwCosVMTimer", getName().c_str()); REGISTER_TIMER_INFO("BwCosVMTimer", getName().c_str());
if (inG0 && inG1) { for (size_t i = 0; i < batchSize; i++) {
for (size_t i = 0; i < batchSize; i++) { tmpRow0->setData(inV0->rowBuf(i));
tmpRow0->setData(inV0->rowBuf(i)); tmpRow1->setData(inG0->rowBuf(i));
tmpRow1->setData(inG0->rowBuf(i)); tmpMtx0->setData(inV1->rowBuf(i));
tmpMtx0->setData(inV1->rowBuf(i)); tmpMtx1->setData(inG1->rowBuf(i));
tmpMtx1->setData(inG1->rowBuf(i)); tmpRow2->setData(outV->rowBuf(i));
tmpRow2->setData(outV->rowBuf(i)); tmpRow3->setData(outG->rowBuf(i));
tmpRow3->setData(outG->rowBuf(i));
BufferArgs inputs;
tmpRow3->cosSimDerivative(*(tmpRow2), BufferArgs outputs;
*(tmpMtx0), inputs.addArg(*tmpRow3);
*(tmpRow0), inputs.addArg(*tmpRow2);
*(tmpMtx1), inputs.addArg(*tmpMtx0);
*(tmpRow1), inputs.addArg(*tmpRow0);
config_.cos_scale()); outputs.addArg(*tmpMtx1, ADD_TO);
} outputs.addArg(*tmpRow1, ADD_TO);
} else {
CHECK(!inG0 || !inG1) << "Not supported"; backward_[0]->calc(inputs, outputs);
} }
} }
......
...@@ -367,8 +367,6 @@ void LambdaCost::backward(const UpdateCallback& callback) { ...@@ -367,8 +367,6 @@ void LambdaCost::backward(const UpdateCallback& callback) {
getInputGrad(0)->add(*marginGrad_); getInputGrad(0)->add(*marginGrad_);
} }
void LambdaCost::onPassEnd() {}
void LambdaCost::calcGrad(const real* outputScore, void LambdaCost::calcGrad(const real* outputScore,
const real* score, const real* score,
real* gradData, real* gradData,
...@@ -611,14 +609,15 @@ class SumCostLayer : public Layer { ...@@ -611,14 +609,15 @@ class SumCostLayer : public Layer {
public: public:
explicit SumCostLayer(const LayerConfig& config) : Layer(config) {} explicit SumCostLayer(const LayerConfig& config) : Layer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap) { bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override {
bool ret = Layer::init(layerMap, parameterMap); bool ret = Layer::init(layerMap, parameterMap);
if (!ret) return ret; if (!ret) return ret;
CHECK_EQ(inputLayers_.size(), 1UL); CHECK_EQ(inputLayers_.size(), 1UL);
return true; return true;
} }
virtual void forward(PassType passType) { void forward(PassType passType) override {
Layer::forward(passType); Layer::forward(passType);
const MatrixPtr& input = getInputValue(0); const MatrixPtr& input = getInputValue(0);
...@@ -629,7 +628,7 @@ public: ...@@ -629,7 +628,7 @@ public:
output_.value->sumRows(*input, /* scaleSum= */ 1, /* scaleDest= */ 0); output_.value->sumRows(*input, /* scaleSum= */ 1, /* scaleDest= */ 0);
} }
virtual void backward(const UpdateCallback& callback = nullptr) { void backward(const UpdateCallback& callback = nullptr) override {
getInputGrad(0)->add((real)1); getInputGrad(0)->add((real)1);
} }
}; };
......
...@@ -32,15 +32,16 @@ class CostLayer : public Layer { ...@@ -32,15 +32,16 @@ class CostLayer : public Layer {
public: public:
explicit CostLayer(const LayerConfig& config) : Layer(config) {} explicit CostLayer(const LayerConfig& config) : Layer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
LayerPtr getOutputLayer() { return inputLayers_[0]; } LayerPtr getOutputLayer() { return inputLayers_[0]; }
LayerPtr getLabelLayer() { return inputLayers_[1]; } LayerPtr getLabelLayer() { return inputLayers_[1]; }
virtual void forward(PassType passType); void forward(PassType passType) override;
virtual void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
virtual void forwardImp(Matrix& outputValue, virtual void forwardImp(Matrix& outputValue,
Argument& label, Argument& label,
...@@ -68,11 +69,14 @@ public: ...@@ -68,11 +69,14 @@ public:
explicit MultiClassCrossEntropy(const LayerConfig& config) explicit MultiClassCrossEntropy(const LayerConfig& config)
: CostLayer(config) {} : CostLayer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forwardImp(Matrix& output, Argument& label, Matrix& cost); void forwardImp(Matrix& output, Argument& label, Matrix& cost) override;
void backwardImp(Matrix& outputValue, Argument& label, Matrix& outputGrad); void backwardImp(Matrix& outputValue,
Argument& label,
Matrix& outputGrad) override;
}; };
/** /**
...@@ -95,11 +99,14 @@ public: ...@@ -95,11 +99,14 @@ public:
explicit MultiClassCrossEntropyWithSelfNorm(const LayerConfig& config) explicit MultiClassCrossEntropyWithSelfNorm(const LayerConfig& config)
: CostLayer(config) {} : CostLayer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forwardImp(Matrix& output, Argument& label, Matrix& cost); void forwardImp(Matrix& output, Argument& label, Matrix& cost) override;
void backwardImp(Matrix& outputValue, Argument& label, Matrix& outputGrad); void backwardImp(Matrix& outputValue,
Argument& label,
Matrix& outputGrad) override;
protected: protected:
MatrixPtr sftMaxSum_; MatrixPtr sftMaxSum_;
...@@ -117,11 +124,14 @@ public: ...@@ -117,11 +124,14 @@ public:
explicit SoftBinaryClassCrossEntropy(const LayerConfig& config) explicit SoftBinaryClassCrossEntropy(const LayerConfig& config)
: CostLayer(config) {} : CostLayer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forwardImp(Matrix& output, Argument& label, Matrix& cost); void forwardImp(Matrix& output, Argument& label, Matrix& cost) override;
void backwardImp(Matrix& outputValue, Argument& label, Matrix& outputGrad); void backwardImp(Matrix& outputValue,
Argument& label,
Matrix& outputGrad) override;
protected: protected:
MatrixPtr targetPerDim_; MatrixPtr targetPerDim_;
...@@ -139,11 +149,14 @@ public: ...@@ -139,11 +149,14 @@ public:
explicit SumOfSquaresCostLayer(const LayerConfig& config) explicit SumOfSquaresCostLayer(const LayerConfig& config)
: CostLayer(config) {} : CostLayer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forwardImp(Matrix& output, Argument& label, Matrix& cost); void forwardImp(Matrix& output, Argument& label, Matrix& cost) override;
void backwardImp(Matrix& outputValue, Argument& label, Matrix& outputGrad); void backwardImp(Matrix& outputValue,
Argument& label,
Matrix& outputGrad) override;
}; };
/** /**
...@@ -162,17 +175,18 @@ class RankingCost : public Layer { ...@@ -162,17 +175,18 @@ class RankingCost : public Layer {
public: public:
explicit RankingCost(const LayerConfig& config) : Layer(config) {} explicit RankingCost(const LayerConfig& config) : Layer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
LayerPtr getOutputLayer(size_t i) { return inputLayers_[i]; } LayerPtr getOutputLayer(size_t i) { return inputLayers_[i]; }
LayerPtr getLabelLayer() { return inputLayers_[2]; } LayerPtr getLabelLayer() { return inputLayers_[2]; }
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
void onPassEnd(); void onPassEnd() override;
void forwardImp(Matrix& output, Argument& label, Matrix& cost) { void forwardImp(Matrix& output, Argument& label, Matrix& cost) {
(void)output; (void)output;
...@@ -214,17 +228,16 @@ class LambdaCost : public Layer { ...@@ -214,17 +228,16 @@ class LambdaCost : public Layer {
public: public:
explicit LambdaCost(const LayerConfig& config) : Layer(config) {} explicit LambdaCost(const LayerConfig& config) : Layer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
LayerPtr getOutputLayer() { return inputLayers_[0]; } LayerPtr getOutputLayer() { return inputLayers_[0]; }
LayerPtr getScoreLayer() { return inputLayers_[1]; } LayerPtr getScoreLayer() { return inputLayers_[1]; }
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
void onPassEnd();
real calcNDCG(const real* outputScore, const real* score, int size); real calcNDCG(const real* outputScore, const real* score, int size);
void calcGrad(const real* outputScore, void calcGrad(const real* outputScore,
...@@ -256,11 +269,14 @@ public: ...@@ -256,11 +269,14 @@ public:
explicit MultiBinaryLabelCrossEntropy(const LayerConfig& config) explicit MultiBinaryLabelCrossEntropy(const LayerConfig& config)
: CostLayer(config) {} : CostLayer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forwardImp(Matrix& output, Argument& label, Matrix& cost); void forwardImp(Matrix& output, Argument& label, Matrix& cost) override;
void backwardImp(Matrix& outputValue, Argument& label, Matrix& outputGrad); void backwardImp(Matrix& outputValue,
Argument& label,
Matrix& outputGrad) override;
}; };
/** /**
...@@ -282,13 +298,16 @@ class HuberTwoClass : public CostLayer { ...@@ -282,13 +298,16 @@ class HuberTwoClass : public CostLayer {
public: public:
explicit HuberTwoClass(const LayerConfig& config) : CostLayer(config) {} explicit HuberTwoClass(const LayerConfig& config) : CostLayer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forwardImp(Matrix& output, Argument& label, Matrix& cost); void forwardImp(Matrix& output, Argument& label, Matrix& cost) override;
void forwardImpIn(Matrix& output, Argument& label, Matrix& cost); void forwardImpIn(Matrix& output, Argument& label, Matrix& cost);
void backwardImp(Matrix& outputValue, Argument& label, Matrix& outputGrad); void backwardImp(Matrix& outputValue,
Argument& label,
Matrix& outputGrad) override;
void backwardImpIn(Matrix& outputValue, Argument& label, Matrix& outputGrad); void backwardImpIn(Matrix& outputValue, Argument& label, Matrix& outputGrad);
}; };
......
...@@ -35,14 +35,15 @@ public: ...@@ -35,14 +35,15 @@ public:
~CudnnBatchNormLayer(); ~CudnnBatchNormLayer();
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
/** /**
* reshape tensor of ioDesc_. * reshape tensor of ioDesc_.
*/ */
void reshape(int batchSize); void reshape(int batchSize);
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
protected: protected:
/** /**
......
...@@ -45,9 +45,10 @@ public: ...@@ -45,9 +45,10 @@ public:
~CudnnConvLayer(); ~CudnnConvLayer();
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
void forward(PassType passType); const ParameterMap& parameterMap) override;
void backward(const UpdateCallback& callback); void forward(PassType passType) override;
void backward(const UpdateCallback& callback) override;
void addBiases(); void addBiases();
void bpropBiases(); void bpropBiases();
}; };
......
...@@ -45,7 +45,8 @@ public: ...@@ -45,7 +45,8 @@ public:
hl_pooling_mode_t* mode = nullptr); hl_pooling_mode_t* mode = nullptr);
explicit CudnnPoolLayer(const LayerConfig& config); explicit CudnnPoolLayer(const LayerConfig& config);
~CudnnPoolLayer(); ~CudnnPoolLayer();
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
/** /**
* Reshape input and output tensor descriptor. * Reshape input and output tensor descriptor.
...@@ -53,8 +54,8 @@ public: ...@@ -53,8 +54,8 @@ public:
* So reshaping is needed. * So reshaping is needed.
*/ */
void reshape(int batchSize); void reshape(int batchSize);
virtual void forward(PassType passType); void forward(PassType passType) override;
virtual void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -33,13 +33,13 @@ public: ...@@ -33,13 +33,13 @@ public:
/** /**
* Prefetch sparse matrix/ids only. * Prefetch sparse matrix/ids only.
*/ */
void prefetch() { output_ = data_; } void prefetch() override { output_ = data_; }
/** /**
* Forward propagation. Copy data_ (value, in, grad, ids, cpuSequenceDims, * Forward propagation. Copy data_ (value, in, grad, ids, cpuSequenceDims,
* sequenceStartPositions, subSequenceStartPositions, strs) to output_. * sequenceStartPositions, subSequenceStartPositions, strs) to output_.
*/ */
virtual void forward(PassType passType) { void forward(PassType passType) override {
Layer::forward(passType); Layer::forward(passType);
copyDataToOutput(output_); copyDataToOutput(output_);
if (FLAGS_show_layer_stat) { if (FLAGS_show_layer_stat) {
...@@ -50,9 +50,9 @@ public: ...@@ -50,9 +50,9 @@ public:
/** /**
* Data layer's backward propagation do nothing. * Data layer's backward propagation do nothing.
*/ */
virtual void backward(const UpdateCallback& callback) { (void)callback; } void backward(const UpdateCallback& callback) override { (void)callback; }
virtual void copyOutputToOtherDevice() { void copyOutputToOtherDevice() override {
for (size_t i = 0; i != outputOtherDevice_.size(); i++) { for (size_t i = 0; i != outputOtherDevice_.size(); i++) {
copyDataToOutput(outputOtherDevice_[i]); copyDataToOutput(outputOtherDevice_[i]);
} }
......
...@@ -44,10 +44,11 @@ public: ...@@ -44,10 +44,11 @@ public:
~DataNormLayer() {} ~DataNormLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
protected: protected:
int mode_; int mode_;
......
...@@ -27,14 +27,14 @@ class EosIdCheckLayer : public Layer { ...@@ -27,14 +27,14 @@ class EosIdCheckLayer : public Layer {
public: public:
explicit EosIdCheckLayer(const LayerConfig& config) : Layer(config) {} explicit EosIdCheckLayer(const LayerConfig& config) : Layer(config) {}
virtual bool init(const LayerMap& layerMap, bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) { const ParameterMap& parameterMap) override {
bool ret = Layer::init(layerMap, parameterMap); bool ret = Layer::init(layerMap, parameterMap);
CHECK_EQ(1UL, inputLayers_.size()); CHECK_EQ(1UL, inputLayers_.size());
return ret; return ret;
} }
virtual void forward(PassType passType) { void forward(PassType passType) override {
Layer::forward(passType); Layer::forward(passType);
const Argument& input = getInput(0); const Argument& input = getInput(0);
...@@ -42,7 +42,7 @@ public: ...@@ -42,7 +42,7 @@ public:
output_.ids->isEqualTo(*input.ids, config_.eos_id()); output_.ids->isEqualTo(*input.ids, config_.eos_id());
} }
virtual void backward(const UpdateCallback& callback) {} void backward(const UpdateCallback& callback) override {}
}; };
REGISTER_LAYER(eos_id, EosIdCheckLayer); REGISTER_LAYER(eos_id, EosIdCheckLayer);
......
...@@ -48,7 +48,8 @@ public: ...@@ -48,7 +48,8 @@ public:
~ExpandConvBaseLayer() {} ~ExpandConvBaseLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
size_t getOutputSize(); size_t getOutputSize();
/** /**
......
...@@ -35,10 +35,11 @@ public: ...@@ -35,10 +35,11 @@ public:
~ExpandConvLayer() {} ~ExpandConvLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback); void backward(const UpdateCallback& callback) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -34,10 +34,11 @@ public: ...@@ -34,10 +34,11 @@ public:
~ExpandConvTransLayer() {} ~ExpandConvTransLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback); void backward(const UpdateCallback& callback) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -53,10 +53,11 @@ public: ...@@ -53,10 +53,11 @@ public:
~ExpandLayer() {} ~ExpandLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -46,10 +46,11 @@ public: ...@@ -46,10 +46,11 @@ public:
~FeatureMapExpandLayer() {} ~FeatureMapExpandLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
REGISTER_LAYER(featmap_expand, FeatureMapExpandLayer); REGISTER_LAYER(featmap_expand, FeatureMapExpandLayer);
......
...@@ -36,13 +36,14 @@ public: ...@@ -36,13 +36,14 @@ public:
explicit FullyConnectedLayer(const LayerConfig& config) : Layer(config) {} explicit FullyConnectedLayer(const LayerConfig& config) : Layer(config) {}
~FullyConnectedLayer() {} ~FullyConnectedLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
Weight& getWeight(int idx) { return *weights_[idx]; } Weight& getWeight(int idx) { return *weights_[idx]; }
void prefetch(); void prefetch() override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -50,17 +50,18 @@ class GatedRecurrentLayer : public Layer, public GruCompute { ...@@ -50,17 +50,18 @@ class GatedRecurrentLayer : public Layer, public GruCompute {
public: public:
explicit GatedRecurrentLayer(const LayerConfig& config) : Layer(config) {} explicit GatedRecurrentLayer(const LayerConfig& config) : Layer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback); void backward(const UpdateCallback& callback) override;
void resetState(); void resetState() override;
void setState(LayerStatePtr state); void setState(LayerStatePtr state) override;
LayerStatePtr getState(); LayerStatePtr getState() override;
protected: protected:
void forwardSequence(int batchSize, void forwardSequence(int batchSize,
......
...@@ -22,17 +22,18 @@ public: ...@@ -22,17 +22,18 @@ public:
~GetOutputLayer() {} ~GetOutputLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap) { bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override {
if (!Layer::init(layerMap, parameterMap)) return false; if (!Layer::init(layerMap, parameterMap)) return false;
CHECK_EQ(1U, inputLayers_.size()); CHECK_EQ(1U, inputLayers_.size());
CHECK_NE(inputArgument_[0], ""); CHECK_NE(inputArgument_[0], "");
return true; return true;
} }
void forward(PassType passType) { void forward(PassType passType) override {
output_ = getPrev(0)->getOutput(inputArgument_[0]); output_ = getPrev(0)->getOutput(inputArgument_[0]);
} }
void backward(const UpdateCallback& callback = nullptr) {} void backward(const UpdateCallback& callback = nullptr) override {}
}; };
REGISTER_LAYER(get_output, GetOutputLayer); REGISTER_LAYER(get_output, GetOutputLayer);
......
...@@ -55,10 +55,11 @@ public: ...@@ -55,10 +55,11 @@ public:
~GruStepLayer() {} ~GruStepLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
REGISTER_LAYER(gru_step, GruStepLayer); REGISTER_LAYER(gru_step, GruStepLayer);
......
...@@ -61,9 +61,10 @@ class HierarchicalSigmoidLayer : public Layer { ...@@ -61,9 +61,10 @@ class HierarchicalSigmoidLayer : public Layer {
public: public:
explicit HierarchicalSigmoidLayer(const LayerConfig& config) explicit HierarchicalSigmoidLayer(const LayerConfig& config)
: Layer(config) {} : Layer(config) {}
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
virtual void forward(PassType passType); const ParameterMap& parameterMap) override;
virtual void backward(const UpdateCallback& callback); void forward(PassType passType) override;
void backward(const UpdateCallback& callback) override;
protected: protected:
/** /**
......
...@@ -43,10 +43,11 @@ public: ...@@ -43,10 +43,11 @@ public:
~InterpolationLayer() {} ~InterpolationLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
REGISTER_LAYER(interpolation, InterpolationLayer); REGISTER_LAYER(interpolation, InterpolationLayer);
......
...@@ -74,17 +74,18 @@ class LstmLayer : public Layer, public LstmCompute { ...@@ -74,17 +74,18 @@ class LstmLayer : public Layer, public LstmCompute {
public: public:
explicit LstmLayer(const LayerConfig &config) : Layer(config) {} explicit LstmLayer(const LayerConfig &config) : Layer(config) {}
bool init(const LayerMap &layerMap, const ParameterMap &parameterMap); bool init(const LayerMap &layerMap,
const ParameterMap &parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback &callback); void backward(const UpdateCallback &callback) override;
void resetState(); void resetState() override;
void setState(LayerStatePtr state); void setState(LayerStatePtr state) override;
LayerStatePtr getState(); LayerStatePtr getState() override;
protected: protected:
/** /**
......
...@@ -35,10 +35,11 @@ public: ...@@ -35,10 +35,11 @@ public:
~LstmStepLayer() {} ~LstmStepLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
REGISTER_LAYER(lstm_step, LstmStepLayer); REGISTER_LAYER(lstm_step, LstmStepLayer);
......
...@@ -181,11 +181,12 @@ class MDLstmLayer : public LstmLayer { ...@@ -181,11 +181,12 @@ class MDLstmLayer : public LstmLayer {
public: public:
explicit MDLstmLayer(const LayerConfig& config) : LstmLayer(config) {} explicit MDLstmLayer(const LayerConfig& config) : LstmLayer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback); void backward(const UpdateCallback& callback) override;
protected: protected:
void forwardOneSequence(int start, CoordIterator& coordIter); void forwardOneSequence(int start, CoordIterator& coordIter);
......
...@@ -30,8 +30,8 @@ private: ...@@ -30,8 +30,8 @@ private:
public: public:
explicit MaxIdLayer(const LayerConfig& config) : Layer(config) {} explicit MaxIdLayer(const LayerConfig& config) : Layer(config) {}
virtual bool init(const LayerMap& layerMap, bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) { const ParameterMap& parameterMap) override {
bool ret = Layer::init(layerMap, parameterMap); bool ret = Layer::init(layerMap, parameterMap);
CHECK_EQ(1UL, inputLayers_.size()); CHECK_EQ(1UL, inputLayers_.size());
...@@ -40,7 +40,7 @@ public: ...@@ -40,7 +40,7 @@ public:
return ret; return ret;
} }
virtual void forward(PassType passType) { void forward(PassType passType) override {
Layer::forward(passType); Layer::forward(passType);
const Argument& input = getInput(0); const Argument& input = getInput(0);
size_t batchSize = input.getBatchSize(); size_t batchSize = input.getBatchSize();
...@@ -54,7 +54,7 @@ public: ...@@ -54,7 +54,7 @@ public:
input.value->rowMax(*output_.ids, *output_.in); input.value->rowMax(*output_.ids, *output_.in);
} }
virtual void backward(const UpdateCallback& callback) {} void backward(const UpdateCallback& callback) override {}
}; };
REGISTER_LAYER(maxid, MaxIdLayer); REGISTER_LAYER(maxid, MaxIdLayer);
......
...@@ -42,14 +42,13 @@ protected: ...@@ -42,14 +42,13 @@ protected:
public: public:
explicit MaxLayer(const LayerConfig& config) : SequencePoolLayer(config) {} explicit MaxLayer(const LayerConfig& config) : SequencePoolLayer(config) {}
~MaxLayer() {} bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override {
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap) {
return SequencePoolLayer::init(layerMap, parameterMap); return SequencePoolLayer::init(layerMap, parameterMap);
} }
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -45,10 +45,11 @@ public: ...@@ -45,10 +45,11 @@ public:
explicit MaxOutLayer(const LayerConfig& config) : Layer(config) {} explicit MaxOutLayer(const LayerConfig& config) : Layer(config) {}
virtual ~MaxOutLayer() {} virtual ~MaxOutLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -35,21 +35,22 @@ public: ...@@ -35,21 +35,22 @@ public:
~MixedLayer() {} ~MixedLayer() {}
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
virtual void prefetch(); void prefetch() override;
virtual void forward(PassType passType); void forward(PassType passType) override;
virtual void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
virtual void resetState(); void resetState() override;
/** /**
* setState() should be called after getState(). * setState() should be called after getState().
* Argument state consists of all projections states. * Argument state consists of all projections states.
*/ */
virtual void setState(LayerStatePtr state); void setState(LayerStatePtr state) override;
/** /**
* Return state which consists of all projections states. * Return state which consists of all projections states.
*/ */
virtual LayerStatePtr getState(); LayerStatePtr getState() override;
protected: protected:
std::vector<std::unique_ptr<Projection>> projections_; std::vector<std::unique_ptr<Projection>> projections_;
......
...@@ -69,10 +69,11 @@ public: ...@@ -69,10 +69,11 @@ public:
~MultiplexLayer() {} ~MultiplexLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
private: private:
/** /**
......
...@@ -61,7 +61,8 @@ public: ...@@ -61,7 +61,8 @@ public:
rand_(0, config.num_classes() - 1), rand_(0, config.num_classes() - 1),
prepared_(false) {} prepared_(false) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap) { bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override {
/* Initialize the basic parent class */ /* Initialize the basic parent class */
Layer::init(layerMap, parameterMap); Layer::init(layerMap, parameterMap);
...@@ -146,7 +147,7 @@ public: ...@@ -146,7 +147,7 @@ public:
prepared_ = true; prepared_ = true;
} }
void prefetch() { void prefetch() override {
prepareSamples(); prepareSamples();
IVector::resizeOrCreate(labelIds_, samples_.size(), useGpu_); IVector::resizeOrCreate(labelIds_, samples_.size(), useGpu_);
int* ids = labelIds_->getData(); int* ids = labelIds_->getData();
...@@ -163,7 +164,7 @@ public: ...@@ -163,7 +164,7 @@ public:
} }
} }
void forward(PassType passType) { void forward(PassType passType) override {
Layer::forward(passType); Layer::forward(passType);
CHECK(!useGpu_) << "GPU is not supported"; CHECK(!useGpu_) << "GPU is not supported";
...@@ -199,7 +200,7 @@ public: ...@@ -199,7 +200,7 @@ public:
forwardCost(); forwardCost();
} }
void backward(const UpdateCallback& callback) { void backward(const UpdateCallback& callback) override {
Matrix::resizeOrCreate(sampleOut_.grad, Matrix::resizeOrCreate(sampleOut_.grad,
1, 1,
samples_.size(), samples_.size(),
......
...@@ -30,7 +30,8 @@ class NormLayer : public Layer { ...@@ -30,7 +30,8 @@ class NormLayer : public Layer {
public: public:
explicit NormLayer(const LayerConfig& config) : Layer(config) {} explicit NormLayer(const LayerConfig& config) : Layer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap) { bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override {
Layer::init(layerMap, parameterMap); Layer::init(layerMap, parameterMap);
return true; return true;
} }
...@@ -56,9 +57,10 @@ protected: ...@@ -56,9 +57,10 @@ protected:
public: public:
explicit ResponseNormLayer(const LayerConfig& config) : NormLayer(config) {} explicit ResponseNormLayer(const LayerConfig& config) : NormLayer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
void forward(PassType passType) { LOG(FATAL) << "Not implemented"; } const ParameterMap& parameterMap) override;
void backward(const UpdateCallback& callback = nullptr) { void forward(PassType passType) override { LOG(FATAL) << "Not implemented"; }
void backward(const UpdateCallback& callback = nullptr) override {
LOG(FATAL) << "Not implemented"; LOG(FATAL) << "Not implemented";
} }
}; };
......
...@@ -36,9 +36,10 @@ public: ...@@ -36,9 +36,10 @@ public:
size_t getSize(); size_t getSize();
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
void forward(PassType passType); const ParameterMap& parameterMap) override;
void backward(const UpdateCallback& callback = nullptr); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr) override;
protected: protected:
TensorShape shape_; TensorShape shape_;
......
...@@ -38,10 +38,11 @@ public: ...@@ -38,10 +38,11 @@ public:
~OuterProdLayer() {} ~OuterProdLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
REGISTER_LAYER(out_prod, OuterProdLayer); REGISTER_LAYER(out_prod, OuterProdLayer);
......
...@@ -29,9 +29,10 @@ public: ...@@ -29,9 +29,10 @@ public:
~PadLayer() {} ~PadLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
void forward(PassType passType); const ParameterMap& parameterMap) override;
void backward(const UpdateCallback& callback = nullptr); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr) override;
protected: protected:
void setOutDims(const size_t batchSize); void setOutDims(const size_t batchSize);
......
...@@ -56,9 +56,10 @@ public: ...@@ -56,9 +56,10 @@ public:
~ParameterReluLayer() {} ~ParameterReluLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -46,7 +46,8 @@ public: ...@@ -46,7 +46,8 @@ public:
*/ */
static Layer* create(const LayerConfig& config); static Layer* create(const LayerConfig& config);
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -40,7 +40,7 @@ public: ...@@ -40,7 +40,7 @@ public:
size_t getSize(); size_t getSize();
virtual void forward(PassType passType); void forward(PassType passType) override;
virtual void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -40,10 +40,11 @@ public: ...@@ -40,10 +40,11 @@ public:
~PowerLayer() {} ~PowerLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
REGISTER_LAYER(power, PowerLayer); REGISTER_LAYER(power, PowerLayer);
......
...@@ -19,38 +19,17 @@ namespace paddle { ...@@ -19,38 +19,17 @@ namespace paddle {
class PrintLayer : public Layer { class PrintLayer : public Layer {
public: public:
explicit PrintLayer(const LayerConfig& config) : Layer(config) {} explicit PrintLayer(const LayerConfig& config) : Layer(config) {}
void forward(PassType passType);
void backward(const UpdateCallback& callback) {}
};
void PrintLayer::forward(PassType passType) { void forward(PassType passType) override {
Layer::forward(passType); Layer::forward(passType);
for (size_t i = 0; i != inputLayers_.size(); ++i) { for (size_t i = 0; i != inputLayers_.size(); ++i) {
const auto& argu = getInput(i); getInput(i).printValueString(LOG(INFO),
const std::string& name = inputLayers_[i]->getName(); "layer=" + inputLayers_[i]->getName() + " ");
if (argu.value) {
std::ostringstream os;
argu.value->print(os);
LOG(INFO) << "layer=" << name << " value matrix:\n" << os.str();
}
if (argu.ids) {
std::ostringstream os;
argu.ids->print(os, argu.ids->getSize());
LOG(INFO) << "layer=" << name << " ids vector:\n" << os.str();
}
if (auto startPos = argu.sequenceStartPositions) {
std::ostringstream os;
startPos->getVector(false)->print(os, startPos->getSize());
LOG(INFO) << "layer=" << name << " sequence pos vector:\n" << os.str();
}
if (auto subStartPos = argu.subSequenceStartPositions) {
std::ostringstream os;
subStartPos->getVector(false)->print(os, subStartPos->getSize());
LOG(INFO) << "layer=" << name << " sub-sequence pos vector:\n"
<< os.str();
} }
} }
}
void backward(const UpdateCallback& callback) override {}
};
REGISTER_LAYER(print, PrintLayer); REGISTER_LAYER(print, PrintLayer);
......
...@@ -30,10 +30,11 @@ namespace paddle { ...@@ -30,10 +30,11 @@ namespace paddle {
class PriorBoxLayer : public Layer { class PriorBoxLayer : public Layer {
public: public:
explicit PriorBoxLayer(const LayerConfig& config) : Layer(config) {} explicit PriorBoxLayer(const LayerConfig& config) : Layer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback) {} void backward(const UpdateCallback& callback) override {}
protected: protected:
int numPriors_; int numPriors_;
......
...@@ -45,17 +45,18 @@ class RecurrentLayer : public Layer { ...@@ -45,17 +45,18 @@ class RecurrentLayer : public Layer {
public: public:
explicit RecurrentLayer(const LayerConfig& config) : Layer(config) {} explicit RecurrentLayer(const LayerConfig& config) : Layer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback); void backward(const UpdateCallback& callback) override;
void resetState(); void resetState() override;
void setState(LayerStatePtr state); void setState(LayerStatePtr state) override;
LayerStatePtr getState(); LayerStatePtr getState() override;
protected: protected:
/** /**
......
...@@ -33,15 +33,15 @@ public: ...@@ -33,15 +33,15 @@ public:
void initSubNetwork(NeuralNetwork* rootNetwork, void initSubNetwork(NeuralNetwork* rootNetwork,
const ModelConfig& config, const ModelConfig& config,
const std::vector<ParameterType>& parameterTypes, const std::vector<ParameterType>& parameterTypes,
bool useGpu); bool useGpu) override;
void forward(PassType passType) { void forward(PassType passType) override {
REGISTER_TIMER_INFO("RecurrentGroupFwTime", getName().c_str()); REGISTER_TIMER_INFO("RecurrentGroupFwTime", getName().c_str());
const std::vector<Argument> inArgs; const std::vector<Argument> inArgs;
std::vector<Argument> outArgs; std::vector<Argument> outArgs;
network_->forward(inArgs, &outArgs, passType); network_->forward(inArgs, &outArgs, passType);
} }
void backward(const UpdateCallback& callback) { void backward(const UpdateCallback& callback) override {
REGISTER_TIMER_INFO("RecurrentGroupBwTime", getName().c_str()); REGISTER_TIMER_INFO("RecurrentGroupBwTime", getName().c_str());
network_->backward(nullptr); network_->backward(nullptr);
...@@ -53,7 +53,8 @@ public: ...@@ -53,7 +53,8 @@ public:
/** /**
* @see Layer.accessSubNetwork * @see Layer.accessSubNetwork
*/ */
void accessSubNetwork(const std::function<void(NeuralNetwork&)>& callback) { void accessSubNetwork(
const std::function<void(NeuralNetwork&)>& callback) override {
callback(*network_); callback(*network_);
} }
......
...@@ -20,18 +20,19 @@ namespace paddle { ...@@ -20,18 +20,19 @@ namespace paddle {
/** /**
* @brief A layer for resizing a minibatch matrix h*w to h'*w' * @brief A layer for resizing a minibatch matrix h*w to h'*w'
* @note * @note
* origin matrix height * witdth) * origin matrix height * width)
* resize matrix: (height * width / size) * size * resize matrix: (height * width / size) * size
*/ */
class ResizeLayer : public Layer { class ResizeLayer : public Layer {
public: public:
explicit ResizeLayer(const LayerConfig& config) : Layer(config) {} explicit ResizeLayer(const LayerConfig& config) : Layer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback); void backward(const UpdateCallback& callback) override;
}; };
REGISTER_LAYER(resize, ResizeLayer); REGISTER_LAYER(resize, ResizeLayer);
......
...@@ -35,8 +35,8 @@ public: ...@@ -35,8 +35,8 @@ public:
explicit SamplingIdLayer(const LayerConfig& config) explicit SamplingIdLayer(const LayerConfig& config)
: Layer(config), rand1_(0, 1) {} : Layer(config), rand1_(0, 1) {}
virtual bool init(const LayerMap& layerMap, bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) { const ParameterMap& parameterMap) override {
bool ret = Layer::init(layerMap, parameterMap); bool ret = Layer::init(layerMap, parameterMap);
CHECK_EQ(1UL, inputLayers_.size()); CHECK_EQ(1UL, inputLayers_.size());
if (useGpu_) { if (useGpu_) {
...@@ -48,7 +48,7 @@ public: ...@@ -48,7 +48,7 @@ public:
return ret; return ret;
} }
void forward(PassType passType) { void forward(PassType passType) override {
Layer::forward(passType); Layer::forward(passType);
if (useGpu_) { if (useGpu_) {
for (size_t i = 0; i < inputLayers_.size(); i++) { for (size_t i = 0; i < inputLayers_.size(); i++) {
...@@ -83,7 +83,7 @@ public: ...@@ -83,7 +83,7 @@ public:
output_.ids->copyFrom(ids.data(), batchSize); output_.ids->copyFrom(ids.data(), batchSize);
} }
virtual void backward(const UpdateCallback& callback) {} void backward(const UpdateCallback& callback) override {}
}; };
REGISTER_LAYER(sampling_id, SamplingIdLayer); REGISTER_LAYER(sampling_id, SamplingIdLayer);
......
...@@ -37,10 +37,11 @@ public: ...@@ -37,10 +37,11 @@ public:
~ScalingLayer() {} ~ScalingLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
REGISTER_LAYER(scaling, ScalingLayer); REGISTER_LAYER(scaling, ScalingLayer);
......
...@@ -65,9 +65,10 @@ public: ...@@ -65,9 +65,10 @@ public:
: Layer(config), selCols_(nullptr) {} : Layer(config), selCols_(nullptr) {}
~SelectiveFullyConnectedLayer() {} ~SelectiveFullyConnectedLayer() {}
void prefetch(); void prefetch() override;
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
Weight& getWeight(int idx) { return *weights_[idx]; } Weight& getWeight(int idx) { return *weights_[idx]; }
...@@ -90,8 +91,8 @@ public: ...@@ -90,8 +91,8 @@ public:
void fillSelectiveData( void fillSelectiveData(
const std::shared_ptr<std::vector<std::pair<int*, size_t>>>& candidates); const std::shared_ptr<std::vector<std::pair<int*, size_t>>>& candidates);
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
private: private:
/** /**
......
...@@ -21,9 +21,11 @@ namespace paddle { ...@@ -21,9 +21,11 @@ namespace paddle {
/** /**
* A layer for concatenating the first sequence with the second sequence * A layer for concatenating the first sequence with the second sequence
* following the first * Input: two sequences each containing the same number of instances
* Input: two sequences each containing some instances * seq1 = [a1, a2, ..., an]
* seq2 = [b1, b2, ..., bn]
* Output: a concatenated sequence of the two input sequences * Output: a concatenated sequence of the two input sequences
* out = [a1, b1, a2, b2, ..., an, bn]
*/ */
class SequenceConcatLayer : public Layer { class SequenceConcatLayer : public Layer {
...@@ -35,10 +37,11 @@ public: ...@@ -35,10 +37,11 @@ public:
~SequenceConcatLayer() {} ~SequenceConcatLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
REGISTER_LAYER(seqconcat, SequenceConcatLayer); REGISTER_LAYER(seqconcat, SequenceConcatLayer);
...@@ -167,13 +170,17 @@ void SequenceConcatLayer::backward(const UpdateCallback& callback) { ...@@ -167,13 +170,17 @@ void SequenceConcatLayer::backward(const UpdateCallback& callback) {
size_t rightNumIns = 0; size_t rightNumIns = 0;
for (size_t seqId = 0; seqId < numSequences1; ++seqId) { for (size_t seqId = 0; seqId < numSequences1; ++seqId) {
leftNumIns = starts1[seqId + 1] - starts1[seqId]; leftNumIns = starts1[seqId + 1] - starts1[seqId];
inputGrad1->subMatrix(starts1[seqId], leftNumIns) if (inputGrad1) {
->add(*(outputGrad->subMatrix(offset, leftNumIns))); inputGrad1->subMatrix(starts1[seqId], leftNumIns)
->add(*(outputGrad->subMatrix(offset, leftNumIns)));
}
offset += leftNumIns; offset += leftNumIns;
rightNumIns = starts2[seqId + 1] - starts2[seqId]; rightNumIns = starts2[seqId + 1] - starts2[seqId];
inputGrad2->subMatrix(starts2[seqId], rightNumIns) if (inputGrad2) {
->add(*(outputGrad->subMatrix(offset, rightNumIns))); inputGrad2->subMatrix(starts2[seqId], rightNumIns)
->add(*(outputGrad->subMatrix(offset, rightNumIns)));
}
offset += rightNumIns; offset += rightNumIns;
} }
} }
......
...@@ -42,12 +42,11 @@ public: ...@@ -42,12 +42,11 @@ public:
explicit SequenceLastInstanceLayer(const LayerConfig& config) explicit SequenceLastInstanceLayer(const LayerConfig& config)
: SequencePoolLayer(config) {} : SequencePoolLayer(config) {}
~SequenceLastInstanceLayer() {} bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr) override;
void forward(PassType passType);
void backward(const UpdateCallback& callback = nullptr);
}; };
REGISTER_LAYER(seqlastins, SequenceLastInstanceLayer); REGISTER_LAYER(seqlastins, SequenceLastInstanceLayer);
......
...@@ -46,12 +46,11 @@ protected: ...@@ -46,12 +46,11 @@ protected:
public: public:
explicit SequencePoolLayer(const LayerConfig& config) : Layer(config) {} explicit SequencePoolLayer(const LayerConfig& config) : Layer(config) {}
virtual ~SequencePoolLayer() {} bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr) override;
void forward(PassType passType);
void backward(const UpdateCallback& callback = nullptr);
}; };
} // namespace paddle } // namespace paddle
...@@ -20,9 +20,12 @@ limitations under the License. */ ...@@ -20,9 +20,12 @@ limitations under the License. */
namespace paddle { namespace paddle {
/** /**
* A layer for reshaping the sequence * A layer for reshaping the sequence. Assume the input sequence has
* Input: a sequence * T instances, the dimension of each instance is M, and the input
* Output: a sequence * reshape_dim is N, then the output sequence has T*M/N instances,
* the dimension of each instance is N.
*
* Note that T*M/N must be an integer.
*/ */
class SequenceReshapeLayer : public Layer { class SequenceReshapeLayer : public Layer {
...@@ -34,12 +37,11 @@ protected: ...@@ -34,12 +37,11 @@ protected:
public: public:
explicit SequenceReshapeLayer(const LayerConfig& config) : Layer(config) {} explicit SequenceReshapeLayer(const LayerConfig& config) : Layer(config) {}
~SequenceReshapeLayer() {} bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr) override;
void forward(PassType passType);
void backward(const UpdateCallback& callback = nullptr);
}; };
REGISTER_LAYER(seqreshape, SequenceReshapeLayer); REGISTER_LAYER(seqreshape, SequenceReshapeLayer);
......
...@@ -39,12 +39,11 @@ class SlopeInterceptLayer : public Layer { ...@@ -39,12 +39,11 @@ class SlopeInterceptLayer : public Layer {
public: public:
explicit SlopeInterceptLayer(const LayerConfig& config) : Layer(config) {} explicit SlopeInterceptLayer(const LayerConfig& config) : Layer(config) {}
~SlopeInterceptLayer() {} bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr) override;
void forward(PassType passType);
void backward(const UpdateCallback& callback = nullptr);
}; };
REGISTER_LAYER(slope_intercept, SlopeInterceptLayer); REGISTER_LAYER(slope_intercept, SlopeInterceptLayer);
......
...@@ -43,9 +43,8 @@ protected: ...@@ -43,9 +43,8 @@ protected:
public: public:
explicit SpatialPyramidPoolLayer(const LayerConfig& config) : Layer(config) {} explicit SpatialPyramidPoolLayer(const LayerConfig& config) : Layer(config) {}
~SpatialPyramidPoolLayer() {} bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap);
ProjectionConfig getConfig(size_t sizeX_, ProjectionConfig getConfig(size_t sizeX_,
size_t sizeY_, size_t sizeY_,
...@@ -54,7 +53,7 @@ public: ...@@ -54,7 +53,7 @@ public:
std::string& poolType_); std::string& poolType_);
size_t getSize(); size_t getSize();
virtual void forward(PassType passType); void forward(PassType passType) override;
virtual void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -35,12 +35,11 @@ protected: ...@@ -35,12 +35,11 @@ protected:
public: public:
explicit SubSequenceLayer(const LayerConfig& config) : Layer(config) {} explicit SubSequenceLayer(const LayerConfig& config) : Layer(config) {}
~SubSequenceLayer() {} bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr) override;
void forward(PassType passType);
void backward(const UpdateCallback& callback = nullptr);
}; };
REGISTER_LAYER(subseq, SubSequenceLayer); REGISTER_LAYER(subseq, SubSequenceLayer);
......
...@@ -41,12 +41,11 @@ protected: ...@@ -41,12 +41,11 @@ protected:
public: public:
explicit SumToOneNormLayer(const LayerConfig& config) : Layer(config) {} explicit SumToOneNormLayer(const LayerConfig& config) : Layer(config) {}
~SumToOneNormLayer() {} bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr) override;
void forward(PassType passType);
void backward(const UpdateCallback& callback = nullptr);
}; };
REGISTER_LAYER(sum_to_one_norm, SumToOneNormLayer); REGISTER_LAYER(sum_to_one_norm, SumToOneNormLayer);
......
...@@ -44,13 +44,12 @@ protected: ...@@ -44,13 +44,12 @@ protected:
public: public:
explicit TensorLayer(const LayerConfig& config) : Layer(config) {} explicit TensorLayer(const LayerConfig& config) : Layer(config) {}
~TensorLayer() {} bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap);
Weight& getWeight(int idx) { return *weights_[idx]; } Weight& getWeight(int idx) { return *weights_[idx]; }
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -32,9 +32,10 @@ class TransLayer : public Layer { ...@@ -32,9 +32,10 @@ class TransLayer : public Layer {
public: public:
explicit TransLayer(const LayerConfig& config) : Layer(config) {} explicit TransLayer(const LayerConfig& config) : Layer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType); void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
}; };
} // namespace paddle } // namespace paddle
...@@ -26,7 +26,8 @@ class ValidationLayer : public Layer { ...@@ -26,7 +26,8 @@ class ValidationLayer : public Layer {
public: public:
explicit ValidationLayer(const LayerConfig& config) : Layer(config) {} explicit ValidationLayer(const LayerConfig& config) : Layer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
LayerPtr getOutputLayer() { return inputLayers_[0]; } LayerPtr getOutputLayer() { return inputLayers_[0]; }
...@@ -37,13 +38,13 @@ public: ...@@ -37,13 +38,13 @@ public:
return inputLayers_[2]; return inputLayers_[2];
} }
virtual void forward(PassType passType); void forward(PassType passType) override;
virtual void backward(const UpdateCallback& callback = nullptr); void backward(const UpdateCallback& callback = nullptr) override;
virtual void validationImp(MatrixPtr outputValue, IVectorPtr label) = 0; virtual void validationImp(MatrixPtr outputValue, IVectorPtr label) = 0;
virtual void onPassEnd() = 0; void onPassEnd() override = 0;
}; };
/* /*
...@@ -57,11 +58,12 @@ public: ...@@ -57,11 +58,12 @@ public:
cpuLabel_(nullptr), cpuLabel_(nullptr),
cpuWeight_(nullptr) {} cpuWeight_(nullptr) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void validationImp(MatrixPtr outputValue, IVectorPtr label); void validationImp(MatrixPtr outputValue, IVectorPtr label) override;
void onPassEnd(); void onPassEnd() override;
struct PredictionResult { struct PredictionResult {
PredictionResult(real __out, int __label) : out(__out), label(__label) {} PredictionResult(real __out, int __label) : out(__out), label(__label) {}
...@@ -86,11 +88,12 @@ public: ...@@ -86,11 +88,12 @@ public:
explicit PnpairValidation(const LayerConfig& config) explicit PnpairValidation(const LayerConfig& config)
: ValidationLayer(config) {} : ValidationLayer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void validationImp(MatrixPtr outputValue, IVectorPtr label); void validationImp(MatrixPtr outputValue, IVectorPtr label) override;
void onPassEnd(); void onPassEnd() override;
private: private:
bool passBegin_; bool passBegin_;
......
...@@ -30,9 +30,10 @@ public: ...@@ -30,9 +30,10 @@ public:
explicit WarpCTCLayer(const LayerConfig& config) : Layer(config) {} explicit WarpCTCLayer(const LayerConfig& config) : Layer(config) {}
~WarpCTCLayer() {} ~WarpCTCLayer() {}
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); bool init(const LayerMap& layerMap,
virtual void forward(PassType passType); const ParameterMap& parameterMap) override;
virtual void backward(const UpdateCallback& callback); void forward(PassType passType) override;
void backward(const UpdateCallback& callback) override;
protected: protected:
/** /**
......
...@@ -941,59 +941,6 @@ void GpuMatrix::softreluDerivative(Matrix& output) { ...@@ -941,59 +941,6 @@ void GpuMatrix::softreluDerivative(Matrix& output) {
void GpuMatrix::scaledTanh(Matrix& output, real p1, real p2) { void GpuMatrix::scaledTanh(Matrix& output, real p1, real p2) {
BaseMatrix::scaledTanh(output, p1, p2); BaseMatrix::scaledTanh(output, p1, p2);
} }
void GpuMatrix::cosSim(Matrix& output1, Matrix& output2, real scale) {
CHECK(output1.useGpu_ == true && output2.useGpu_ == true)
<< "Matrix type are not equal";
size_t numSamples = getHeight();
size_t dim = output1.getWidth();
CHECK_EQ(getWidth(), 1UL);
CHECK_EQ(output1.getHeight(), numSamples);
CHECK_EQ(output1.getWidth(), output2.getWidth());
real* out = getData();
real* x = output1.getData();
real* y = output2.getData();
hl_cossim(out, x, y, dim, output1.getHeight(), output2.getHeight(), scale);
}
void GpuMatrix::cosSimDerivative(Matrix& output,
Matrix& prevOut1,
Matrix& prevOut2,
Matrix& prevGrad1,
Matrix& prevGrad2,
real scale) {
CHECK(output.useGpu_ == true && prevOut1.useGpu_ == true &&
prevOut2.useGpu_ == true && prevGrad1.useGpu_ == true &&
prevGrad2.useGpu_ == true)
<< "Matrix type are not equal";
CHECK_EQ(getWidth(), 1UL);
CHECK_EQ(output.getWidth(), 1UL);
size_t numSamples = getHeight();
CHECK_EQ(output.getHeight(), numSamples);
CHECK_EQ(prevOut1.getHeight(), numSamples);
CHECK_EQ(prevGrad1.getHeight(), numSamples);
size_t dim = prevOut1.getWidth();
CHECK_EQ(prevOut2.getWidth(), dim);
CHECK_EQ(prevGrad1.getWidth(), dim);
CHECK_EQ(prevGrad2.getWidth(), dim);
real* grad = getData();
real* out = output.getData();
real* prevOutX = prevOut1.getData();
real* prevOutY = prevOut2.getData();
real* prevGradX = prevGrad1.getData();
real* prevGradY = prevGrad2.getData();
hl_cossim_derivative(grad,
out,
prevOutX,
prevOutY,
prevGradX,
prevGradY,
dim,
prevOut1.getHeight(),
prevOut2.getHeight(),
scale);
}
void GpuMatrix::randomizeUniform() { void GpuMatrix::randomizeUniform() {
CHECK(isContiguous()); CHECK(isContiguous());
...@@ -3470,105 +3417,6 @@ void CpuMatrix::softmaxDerivative(Matrix& output, Matrix& sftmaxSum) { ...@@ -3470,105 +3417,6 @@ void CpuMatrix::softmaxDerivative(Matrix& output, Matrix& sftmaxSum) {
} }
} }
void CpuMatrix::cosSim(Matrix& output1, Matrix& output2, real scale) {
size_t numSamples = getHeight();
size_t dim = output1.getWidth();
CHECK_EQ(getWidth(), 1UL);
CHECK_EQ(output1.getHeight(), numSamples);
CHECK_EQ(output1.getWidth(), output2.getWidth());
real* out = getData();
const real* x = output1.getData();
const real* y = output2.getData();
size_t yInc = dim;
if (output2.getHeight() == 1LU) {
yInc = 0;
} else {
CHECK_EQ(output2.getHeight(), numSamples);
}
for (size_t i = 0; i < numSamples; ++i, x += dim, y += yInc) {
real squareSumX = 0;
real squareSumY = 0;
real xy = 0;
for (size_t j = 0; j < dim; ++j) {
squareSumX += _square(x[j]);
squareSumY += _square(y[j]);
xy += x[j] * y[j];
}
CHECK(squareSumX > 0 && squareSumY > 0);
out[i] = scale * xy / (std::sqrt(squareSumX) * std::sqrt(squareSumY));
}
}
void CpuMatrix::cosSimDerivative(Matrix& output,
Matrix& prevOut1,
Matrix& prevOut2,
Matrix& prevGrad1,
Matrix& prevGrad2,
real scale) {
CHECK(output.useGpu_ == false) << "Matrix type are not equal";
CHECK_EQ(getWidth(), 1UL);
CHECK_EQ(output.getWidth(), 1UL);
size_t numSamples = getHeight();
CHECK_EQ(output.getHeight(), numSamples);
CHECK_EQ(prevOut1.getHeight(), numSamples);
CHECK_EQ(prevGrad1.getHeight(), numSamples);
size_t dim = prevOut1.getWidth();
CHECK_EQ(prevOut2.getWidth(), dim);
CHECK_EQ(prevGrad1.getWidth(), dim);
CHECK_EQ(prevGrad2.getWidth(), dim);
const real* grad = getData();
const real* out = output.getData();
const real* prevOutX = prevOut1.getData();
const real* prevOutY = prevOut2.getData();
real* prevGradX = prevGrad1.getData();
real* prevGradY = prevGrad2.getData();
size_t yInc = dim;
if (prevOut2.getHeight() == 1LU) {
yInc = 0;
CHECK_EQ(prevGrad2.getHeight(), 1LU);
} else {
CHECK_EQ(prevOut2.getHeight(), numSamples);
CHECK_EQ(prevGrad2.getHeight(), numSamples);
}
for (size_t i = 0; i < numSamples; ++i,
prevOutX += dim,
prevOutY += yInc,
prevGradX += dim,
prevGradY += yInc) {
real squareSumX = 0;
real squareSumY = 0;
real xy = 0;
for (size_t j = 0; j < dim; ++j) {
squareSumX += _square(prevOutX[j]);
squareSumY += _square(prevOutY[j]);
xy += prevOutX[j] * prevOutY[j];
}
CHECK(squareSumX > 0 && squareSumY > 0);
if (xy == 0) {
real reciprocal = 1.0f / (std::sqrt(squareSumX) * std::sqrt(squareSumY));
for (size_t j = 0; j < dim; ++j) {
prevGradX[j] += scale * grad[i] * prevOutY[j] * reciprocal;
prevGradY[j] += scale * grad[i] * prevOutX[j] * reciprocal;
}
} else {
real reciprocalXY = 1.0f / xy;
real reciprocalSquareSumX = 1.0f / squareSumX;
real reciprocalSquareSumY = 1.0f / squareSumY;
for (size_t j = 0; j < dim; ++j) {
prevGradX[j] += out[i] * grad[i] * (prevOutY[j] * reciprocalXY -
prevOutX[j] * reciprocalSquareSumX);
prevGradY[j] += out[i] * grad[i] * (prevOutX[j] * reciprocalXY -
prevOutY[j] * reciprocalSquareSumY);
}
}
}
}
void CpuMatrix::sumOfSquares(Matrix& output, Matrix& label) { void CpuMatrix::sumOfSquares(Matrix& output, Matrix& label) {
CHECK(output.useGpu_ == false && label.useGpu_ == false) CHECK(output.useGpu_ == false && label.useGpu_ == false)
<< "Matrix type are not equal"; << "Matrix type are not equal";
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册