From a3043989a4d2fb082e19173e430809c8025afba2 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 13 Dec 2016 16:57:09 +0800 Subject: [PATCH 001/370] Extract RowBuffer class for SparseRowMatrix. * The original SparseRowMatrix use two fields to store each rows, which let code very confusing. Try to extract a RowBuffer class, for SparseRowMatrix data storage, and manage auto-growth logic. --- paddle/gserver/tests/test_PyDataProvider2.cpp | 2 +- paddle/math/SparseRowMatrix.h | 107 ++++++++++++++---- 2 files changed, 83 insertions(+), 26 deletions(-) diff --git a/paddle/gserver/tests/test_PyDataProvider2.cpp b/paddle/gserver/tests/test_PyDataProvider2.cpp index 436318d35634f4..7a3b51da8b27f7 100644 --- a/paddle/gserver/tests/test_PyDataProvider2.cpp +++ b/paddle/gserver/tests/test_PyDataProvider2.cpp @@ -293,7 +293,7 @@ TEST(PyDataProvider2, can_over_batch_size) { while (true) { int64_t realBatchSize = provider->getNextBatchInternal(batchSize, &batch); if (realBatchSize) { - CHECK_LE(realBatchSize, batchSize); + CHECK_LE((size_t)realBatchSize, batchSize); } else { break; } diff --git a/paddle/math/SparseRowMatrix.h b/paddle/math/SparseRowMatrix.h index badb4b9c1cce4d..db1530f7cfd529 100644 --- a/paddle/math/SparseRowMatrix.h +++ b/paddle/math/SparseRowMatrix.h @@ -24,6 +24,73 @@ P_DECLARE_bool(allow_inefficient_sparse_update); namespace paddle { +/** + * @brief The RowBuffer class + * Represent the SparseRow Matrix Data. + * + * If not set memory handler, then the data could be auto growth. + */ +class RowBuffer { +public: + explicit RowBuffer(size_t width) : width_(width) {} + RowBuffer(const CpuMemHandlePtr& mem, size_t width) + : preallocatedBuf_(mem), width_(width) {} + + inline void reserve(int rowCnt) { + if (preallocatedBuf_) { + CHECK(preallocatedBuf_->getSize() < rowCnt * width_ * sizeof(real)); + } else { + rowStore_.reserve(rowCnt * width_); + } + } + + inline const real* get(int row) const { + if (preallocatedBuf_) { + CHECK_LE((row + 1) * width_ * sizeof(real), preallocatedBuf_->getSize()); + return reinterpret_cast(preallocatedBuf_->getBuf()) + row * width_; + } else { + CHECK_LE((row + 1) * width_, rowStore_.size()); + return rowStore_.data() + row * width_; + } + } + + inline const real* getWithAutoGrowth(int row) { + if (preallocatedBuf_) { + return get(row); + } else { + if ((rowStore_.size() <= row * width_)) { + rowStore_.resize((row + 1) * width_); + } + return rowStore_.data() + row * width_; + } + } + + inline real* data() { + if (preallocatedBuf_) { + return reinterpret_cast(preallocatedBuf_->getBuf()); + } else { + return rowStore_.data(); + } + } + + inline void clear() { rowStore_.clear(); } + + inline size_t getRowCount() const { + if (preallocatedBuf_) { + return preallocatedBuf_->getSize() / sizeof(float) / width_; + } else { + return rowStore_.size() / width_; + } + } + + inline bool canAutoGrowth() const { return preallocatedBuf_ == nullptr; } + +private: + CpuMemHandlePtr preallocatedBuf_; + std::vector> rowStore_; + size_t width_; +}; + /** * Sparse Row */ @@ -45,12 +112,9 @@ class SparseRowCpuMatrix : public CpuMatrix { IndexDictPtr indexDictHandle = nullptr, bool trans = false) : CpuMatrix(nullptr, height, width, trans), - storeMat_(dataHandle, - dataHandle ? dataHandle->getSize() / sizeof(real) / width : 0, - width, - trans), indexDictHandle_(indexDictHandle) { init(height, width); + buf_.reset(new RowBuffer(dataHandle, width)); } virtual ~SparseRowCpuMatrix() {} @@ -72,24 +136,17 @@ class SparseRowCpuMatrix : public CpuMatrix { * @param row row id in local storage */ real* getLocalRow(size_t row) { - if (storeMat_.getData()) return storeMat_.rowBuf(row); - if (rowStore_.size() <= row * width_) { - rowStore_.resize((row + 1) * width_); - } - return rowStore_.data() + row * width_; + return const_cast(buf_->getWithAutoGrowth(row)); } /** - * reserve the storage for rows according to current size of indexDictHandle. + * reserve the storage for rows according to current size of + * indexDictHandle. * * This is only used when SparseRowCpuMatrix is constructed with * indexDictHandle. */ - void reserveStore() { - if (!storeMat_.getData() && !localIndices_->empty()) { - rowStore_.resize(localIndices_->size() * width_); - } - } + void reserveStore() { buf_->reserve(localIndices_->size()); } // row is the row id in the original matrix virtual real* getRowBuf(size_t row) { return getRow(row); } @@ -117,7 +174,8 @@ class SparseRowCpuMatrix : public CpuMatrix { * * If L1 decay set use L1, else if L2 set use L2, otherwise no decay atall. * - * t0 is a int vector used by L1/L2 decay, size = height of parameter matrix, + * t0 is a int vector used by L1/L2 decay, size = height of parameter + * matrix, * store the time that each weight row last updated. * * Time is batchId, currentTime is current batchId. @@ -176,8 +234,7 @@ class SparseRowCpuMatrix : public CpuMatrix { protected: template void apply(Func f) { - real* data = storeMat_.getData() ? storeMat_.getData() : rowStore_.data(); - f(data, localIndices_->size() * width_); + f(buf_->data(), localIndices_->size() * width_); } void init(size_t height, size_t width); @@ -188,25 +245,25 @@ class SparseRowCpuMatrix : public CpuMatrix { globalIndices_[id] = kUnusedId_; } localIndices_->clear(); - rowStore_.clear(); + buf_->clear(); } inline void checkStoreSize() { - if (storeMat_.getData()) { - CHECK_LE(localIndices_->size(), storeMat_.getHeight()); - } else if (!FLAGS_allow_inefficient_sparse_update) { - if (localIndices_->size() > 0.5 * height_) { + if (buf_->canAutoGrowth()) { + if (buf_->getRowCount() > 0.5 * height_) { LOG(WARNING) << "There are more than 0.5*height (" << localIndices_->size() << ") rows are used for sparse " << "update, which is not efficient. Considering not use " << "sparse_update or set --allow_inefficient_sparse_update=true"; + + } else { + CHECK_LE(localIndices_->size(), buf_->getRowCount()); } } } - CpuMatrix storeMat_; - std::vector> rowStore_; + std::unique_ptr buf_; IndexDictPtr indexDictHandle_; std::vector* localIndices_; // =&indexDictHandle_->localIndices unsigned int* globalIndices_; // =indexDictHandle_->globalIndices.data(); From fa2c06fb053769f1c82e4d5c98b2bcdee376d6d0 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 13 Dec 2016 17:25:38 +0800 Subject: [PATCH 002/370] Add comments --- paddle/math/RowBuffer.h | 127 ++++++++++++++++++++++++++++++++++ paddle/math/SparseRowMatrix.h | 72 +------------------ 2 files changed, 130 insertions(+), 69 deletions(-) create mode 100644 paddle/math/RowBuffer.h diff --git a/paddle/math/RowBuffer.h b/paddle/math/RowBuffer.h new file mode 100644 index 00000000000000..e35820461214aa --- /dev/null +++ b/paddle/math/RowBuffer.h @@ -0,0 +1,127 @@ +/* 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 +#include "MemoryHandle.h" +#include "paddle/utils/Util.h" + +namespace paddle { + +/** + * @brief The RowBuffer class + * Represent the SparseRow Matrix Data. + * + * If not set memory handler, then the data could be auto growth. + */ +class RowBuffer { +public: + /** + * @brief RowBuffer create a auto-growth row buffer. The row length is width. + * @param width the length of each row, a.k.a matrix width. + */ + explicit RowBuffer(size_t width) : width_(width) {} + + /** + * @brief RowBuffer create a row buffer, which cannot be auto-growth. + * @param mem the pre-allocated memory. + * @param width the length of each row, a.k.a matrix width. + */ + RowBuffer(const CpuMemHandlePtr& mem, size_t width) + : preallocatedBuf_(mem), width_(width) {} + + /** + * @brief resize resize the buffer with rowCount + * @param rowCnt number of row. matrix height. + */ + inline void resize(int rowCnt) { + if (preallocatedBuf_) { + CHECK(preallocatedBuf_->getSize() < rowCnt * width_ * sizeof(real)); + } else { + rowStore_.resize(rowCnt * width_); + } + } + + /** + * @brief get a row buffer with row index. + * @param row the index of row. + * @return row buffer. + */ + inline const real* get(int row) const { + if (preallocatedBuf_) { + CHECK_LE((row + 1) * width_ * sizeof(real), preallocatedBuf_->getSize()); + return reinterpret_cast(preallocatedBuf_->getBuf()) + row * width_; + } else { + CHECK_LE((row + 1) * width_, rowStore_.size()); + return rowStore_.data() + row * width_; + } + } + + /** + * @brief get a row buffer with row index. If row index is larger than local + * buffer, the size of local buffer will grow. + * @param row the index of row. + * @return row buffer. + */ + inline const real* getWithAutoGrowth(int row) { + if (preallocatedBuf_) { + return get(row); + } else { + if ((rowStore_.size() <= row * width_)) { + rowStore_.resize((row + 1) * width_); + } + return rowStore_.data() + row * width_; + } + } + + /** + * @return raw data buffer. + */ + inline real* data() { + if (preallocatedBuf_) { + return reinterpret_cast(preallocatedBuf_->getBuf()); + } else { + return rowStore_.data(); + } + } + + /** + * @brief clear local buffer. It only affect auto-growth buffer. + */ + inline void clear() { rowStore_.clear(); } + + /** + * @brief get current number of rows. + * @return number of rows. + */ + inline size_t getRowCount() const { + if (preallocatedBuf_) { + return preallocatedBuf_->getSize() / sizeof(float) / width_; + } else { + return rowStore_.size() / width_; + } + } + + /** + * @brief get is this buffer can automatically grow or not. + * @return ture if can automacitally grow. + */ + inline bool isAutoGrowth() const { return preallocatedBuf_ == nullptr; } + +private: + CpuMemHandlePtr preallocatedBuf_; + std::vector> rowStore_; + size_t width_; +}; +} // namespace paddle diff --git a/paddle/math/SparseRowMatrix.h b/paddle/math/SparseRowMatrix.h index db1530f7cfd529..d77d8c3ed13b14 100644 --- a/paddle/math/SparseRowMatrix.h +++ b/paddle/math/SparseRowMatrix.h @@ -17,6 +17,7 @@ limitations under the License. */ #include #include #include "Matrix.h" +#include "RowBuffer.h" #include "paddle/utils/CommandLineParser.h" #include "paddle/utils/Util.h" @@ -24,73 +25,6 @@ P_DECLARE_bool(allow_inefficient_sparse_update); namespace paddle { -/** - * @brief The RowBuffer class - * Represent the SparseRow Matrix Data. - * - * If not set memory handler, then the data could be auto growth. - */ -class RowBuffer { -public: - explicit RowBuffer(size_t width) : width_(width) {} - RowBuffer(const CpuMemHandlePtr& mem, size_t width) - : preallocatedBuf_(mem), width_(width) {} - - inline void reserve(int rowCnt) { - if (preallocatedBuf_) { - CHECK(preallocatedBuf_->getSize() < rowCnt * width_ * sizeof(real)); - } else { - rowStore_.reserve(rowCnt * width_); - } - } - - inline const real* get(int row) const { - if (preallocatedBuf_) { - CHECK_LE((row + 1) * width_ * sizeof(real), preallocatedBuf_->getSize()); - return reinterpret_cast(preallocatedBuf_->getBuf()) + row * width_; - } else { - CHECK_LE((row + 1) * width_, rowStore_.size()); - return rowStore_.data() + row * width_; - } - } - - inline const real* getWithAutoGrowth(int row) { - if (preallocatedBuf_) { - return get(row); - } else { - if ((rowStore_.size() <= row * width_)) { - rowStore_.resize((row + 1) * width_); - } - return rowStore_.data() + row * width_; - } - } - - inline real* data() { - if (preallocatedBuf_) { - return reinterpret_cast(preallocatedBuf_->getBuf()); - } else { - return rowStore_.data(); - } - } - - inline void clear() { rowStore_.clear(); } - - inline size_t getRowCount() const { - if (preallocatedBuf_) { - return preallocatedBuf_->getSize() / sizeof(float) / width_; - } else { - return rowStore_.size() / width_; - } - } - - inline bool canAutoGrowth() const { return preallocatedBuf_ == nullptr; } - -private: - CpuMemHandlePtr preallocatedBuf_; - std::vector> rowStore_; - size_t width_; -}; - /** * Sparse Row */ @@ -146,7 +80,7 @@ class SparseRowCpuMatrix : public CpuMatrix { * This is only used when SparseRowCpuMatrix is constructed with * indexDictHandle. */ - void reserveStore() { buf_->reserve(localIndices_->size()); } + void reserveStore() { buf_->resize(localIndices_->size()); } // row is the row id in the original matrix virtual real* getRowBuf(size_t row) { return getRow(row); } @@ -249,7 +183,7 @@ class SparseRowCpuMatrix : public CpuMatrix { } inline void checkStoreSize() { - if (buf_->canAutoGrowth()) { + if (buf_->isAutoGrowth()) { if (buf_->getRowCount() > 0.5 * height_) { LOG(WARNING) << "There are more than 0.5*height (" << localIndices_->size() From f63fbcdd2981b2bd9f478e784097b8ec5c6e463c Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 13 Dec 2016 21:34:39 +0800 Subject: [PATCH 003/370] Add unit test for row buffer. --- paddle/math/RowBuffer.h | 12 +++-- paddle/math/SparseRowMatrix.h | 4 +- paddle/math/tests/CMakeLists.txt | 1 + paddle/math/tests/test_RowBuffer.cpp | 65 ++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 paddle/math/tests/test_RowBuffer.cpp diff --git a/paddle/math/RowBuffer.h b/paddle/math/RowBuffer.h index e35820461214aa..bb55ca5f9f0d24 100644 --- a/paddle/math/RowBuffer.h +++ b/paddle/math/RowBuffer.h @@ -58,13 +58,13 @@ class RowBuffer { * @param row the index of row. * @return row buffer. */ - inline const real* get(int row) const { + inline real* get(int row) const { if (preallocatedBuf_) { CHECK_LE((row + 1) * width_ * sizeof(real), preallocatedBuf_->getSize()); return reinterpret_cast(preallocatedBuf_->getBuf()) + row * width_; } else { CHECK_LE((row + 1) * width_, rowStore_.size()); - return rowStore_.data() + row * width_; + return const_cast(rowStore_.data() + row * width_); } } @@ -74,7 +74,7 @@ class RowBuffer { * @param row the index of row. * @return row buffer. */ - inline const real* getWithAutoGrowth(int row) { + inline real* getWithAutoGrowth(int row) { if (preallocatedBuf_) { return get(row); } else { @@ -119,6 +119,12 @@ class RowBuffer { */ inline bool isAutoGrowth() const { return preallocatedBuf_ == nullptr; } + /** + * @brief return the width of matrix. a.k.a length of row. + * @return width of matrix + */ + inline size_t getWidth() const { return width_; } + private: CpuMemHandlePtr preallocatedBuf_; std::vector> rowStore_; diff --git a/paddle/math/SparseRowMatrix.h b/paddle/math/SparseRowMatrix.h index d77d8c3ed13b14..8532bca879dfda 100644 --- a/paddle/math/SparseRowMatrix.h +++ b/paddle/math/SparseRowMatrix.h @@ -69,9 +69,7 @@ class SparseRowCpuMatrix : public CpuMatrix { * * @param row row id in local storage */ - real* getLocalRow(size_t row) { - return const_cast(buf_->getWithAutoGrowth(row)); - } + real* getLocalRow(size_t row) { return buf_->getWithAutoGrowth(row); } /** * reserve the storage for rows according to current size of diff --git a/paddle/math/tests/CMakeLists.txt b/paddle/math/tests/CMakeLists.txt index fe5177291c21c3..9403bb073a273a 100644 --- a/paddle/math/tests/CMakeLists.txt +++ b/paddle/math/tests/CMakeLists.txt @@ -4,6 +4,7 @@ add_simple_unittest(test_ExecViaCpu) add_simple_unittest(test_SIMDFunctions) add_simple_unittest(test_TrainingAlgorithm) add_simple_unittest(test_SparseMatrix) +add_simple_unittest(test_RowBuffer) # TODO(yuyang18): Refactor TestUtil.cpp. Remove this cross module reference. add_unittest(test_matrixCompare diff --git a/paddle/math/tests/test_RowBuffer.cpp b/paddle/math/tests/test_RowBuffer.cpp new file mode 100644 index 00000000000000..5f66f22ef73dcf --- /dev/null +++ b/paddle/math/tests/test_RowBuffer.cpp @@ -0,0 +1,65 @@ +/* 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 +#include "paddle/math/RowBuffer.h" + +TEST(RowBuffer, testAutoGrow) { + paddle::RowBuffer buf(128); + ASSERT_EQ(128, buf.getWidth()); + ASSERT_TRUE(buf.isAutoGrowth()); + buf.resize(2); + ASSERT_EQ(2, buf.getRowCount()); + for (size_t i = 0; i < buf.getWidth() * 2; ++i) { + buf.data()[i] = i; + } + for (size_t i = 0; i < buf.getRowCount(); ++i) { + for (size_t j = 0; j < buf.getWidth(); ++j) { + ASSERT_NEAR(i * buf.getWidth() + j, buf.get(i)[j], 1e-5); + } + } + + auto data = buf.getWithAutoGrowth(2); + for (size_t i = 0; i < buf.getWidth(); ++i) { + data[i] = i; + } + + ASSERT_EQ(3, buf.getRowCount()); + for (size_t i = 0; i < buf.getRowCount() - 1; ++i) { + for (size_t j = 0; j < buf.getWidth(); ++j) { + ASSERT_NEAR(i * buf.getWidth() + j, buf.get(i)[j], 1e-5); + } + } + for (size_t i = 0; i < buf.getWidth(); ++i) { + ASSERT_NEAR(i, buf.get(2)[i], 1e-5); + } +} + +TEST(RowBuffer, testWithMemBuf) { + paddle::CpuMemHandlePtr mem = + std::make_shared(128 * 2 * sizeof(real)); + paddle::RowBuffer buf(mem, 128); + ASSERT_TRUE(!buf.isAutoGrowth()); + ASSERT_EQ(2, buf.getRowCount()); + for (size_t i = 0; i < buf.getWidth() * 2; ++i) { + buf.data()[i] = i; + } + for (size_t i = 0; i < buf.getRowCount(); ++i) { + for (size_t j = 0; j < buf.getWidth(); ++j) { + ASSERT_NEAR(i * buf.getWidth() + j, buf.getWithAutoGrowth(i)[j], 1e-5); + } + } + + ASSERT_DEATH_IF_SUPPORTED(buf.getWithAutoGrowth(3), ".*"); +} From ea7dd7c92590116d69e3244b8718012fd0d6b68d Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 13 Dec 2016 22:48:32 +0800 Subject: [PATCH 004/370] Fix logic error before --- paddle/math/SparseRowMatrix.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/paddle/math/SparseRowMatrix.h b/paddle/math/SparseRowMatrix.h index 8532bca879dfda..dd4d85611d6fca 100644 --- a/paddle/math/SparseRowMatrix.h +++ b/paddle/math/SparseRowMatrix.h @@ -188,10 +188,9 @@ class SparseRowCpuMatrix : public CpuMatrix { << ") rows are used for sparse " << "update, which is not efficient. Considering not use " << "sparse_update or set --allow_inefficient_sparse_update=true"; - - } else { - CHECK_LE(localIndices_->size(), buf_->getRowCount()); } + } else { + CHECK_LE(localIndices_->size(), buf_->getRowCount()); } } From 8b5431d5e1e4f54339594ba6a76ecbccf256080f Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Fri, 6 Jan 2017 19:19:56 +0800 Subject: [PATCH 005/370] padding operation --- paddle/function/CMakeLists.txt | 1 + paddle/function/PadOp.cpp | 185 + paddle/function/PadOp.h | 96 + paddle/function/PadOpGpu.cu | 102 + paddle/function/PadOpTest.cpp | 70 + paddle/gserver/layers/PadLayer.cpp | 115 + paddle/gserver/layers/PadLayer.h | 45 + paddle/gserver/tests/test_LayerGrad.cpp | 3090 +++++++++-------- proto/ModelConfig.proto | 8 + python/paddle/trainer/config_parser.py | 26 + .../paddle/trainer_config_helpers/layers.py | 84 +- .../tests/configs/test_pad.py | 21 + 12 files changed, 2317 insertions(+), 1526 deletions(-) create mode 100644 paddle/function/PadOp.cpp create mode 100644 paddle/function/PadOp.h create mode 100644 paddle/function/PadOpGpu.cu create mode 100644 paddle/function/PadOpTest.cpp create mode 100644 paddle/gserver/layers/PadLayer.cpp create mode 100644 paddle/gserver/layers/PadLayer.h create mode 100644 python/paddle/trainer_config_helpers/tests/configs/test_pad.py diff --git a/paddle/function/CMakeLists.txt b/paddle/function/CMakeLists.txt index 0b3126155d0c08..70b25406a4afda 100644 --- a/paddle/function/CMakeLists.txt +++ b/paddle/function/CMakeLists.txt @@ -17,6 +17,7 @@ if(WITH_TESTING) # file(GLOB test_files . *OpTest.cpp) # add_executable(${test_bin} EXCLUDE_FROM_ALL ${test_files}) add_simple_unittest(CrossMapNormalOpTest) + add_simple_unittest(PadOpTest) add_unittest(ContextProjectionOpTest ContextProjectionOpTest.cpp ../gserver/tests/TestUtil.cpp) diff --git a/paddle/function/PadOp.cpp b/paddle/function/PadOp.cpp new file mode 100644 index 00000000000000..e10011da2a1750 --- /dev/null +++ b/paddle/function/PadOp.cpp @@ -0,0 +1,185 @@ +/* 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 "PadOp.h" +#include "paddle/math/Vector.h" + +namespace paddle { + +template <> +void Pad(real* outputs, + const real* inputs, + const int num, + const int inC, + const int inH, + const int inW, + const int padc0, + const int padc1, + const int padh0, + const int padh1, + const int padw0, + const int padw1) { + int outC = inC + padc0 + padc1; + int outH = inH + padh0 + padh1; + int outW = inW + padw0 + padw1; + for (int i = 0; i < num; i++) { + for (int c = 0; c < inC; c++) { + for (int h = 0; h < inH; h++) { + int inoff = ((i * inC + c) * inH + h) * inW; + int outoff = ((i * outC + c + padc0) * outH + h + padh0) * outW + padw0; + memcpy(outputs + outoff, inputs + inoff, inW * sizeof(real)); + } + } + } +} + +template <> +void PadGrad(real* inGrad, + const real* outGrad, + const int num, + const int inC, + const int inH, + const int inW, + const int padc0, + const int padc1, + const int padh0, + const int padh1, + const int padw0, + const int padw1) { + int outC = inC + padc0 + padc1; + int outH = inH + padh0 + padh1; + int outW = inW + padw0 + padw1; + for (int i = 0; i < num; i++) { + for (int c = 0; c < inC; c++) { + for (int h = 0; h < inH; h++) { + int inoff = ((i * inC + c) * inH + h) * inW; + int outoff = ((i * outC + c + padc0) * outH + h + padh0) * outW + padw0; + CpuVector inG = CpuVector(inW, inGrad + inoff); + CpuVector outG = CpuVector(inW, const_cast(outGrad + outoff)); + inG += outG; + } + } + } +} + +/** + * \param inputs[0] input value. + * \param outputs[0] output value. + */ +template +class PadFunc : public FunctionBase { +public: + void init(const FuncConfig& config) override { + padc0_ = config.get("padc0"); + padc1_ = config.get("padc1"); + padh0_ = config.get("padh0"); + padh1_ = config.get("padh1"); + padw0_ = config.get("padw0"); + padw1_ = config.get("padw1"); + } + + void calc(const Arguments& inputs, + const Arguments& outputs, + const Arguments& inouts) override { + CHECK_EQ(1, inputs.size()); + CHECK_EQ(1, outputs.size()); + CHECK_EQ(0, inouts.size()); + + size_t num = inputs[0].dims_[0]; + size_t inC = inputs[0].dims_[1]; + size_t inH = inputs[0].dims_[2]; + size_t inW = inputs[0].dims_[3]; + + Pad(outputs[0].getData(), + inputs[0].getData(), + num, + inC, + inH, + inW, + padc0_, + padc1_, + padh0_, + padh1_, + padw0_, + padw1_); + } + +private: + int padc0_; + int padc1_; + int padh0_; + int padh1_; + int padw0_; + int padw1_; +}; + +/** + * \param inputs[0] input grad. + * \param outputs[0] output grad. + */ +template +class PadGradFunc : public FunctionBase { +public: + void init(const FuncConfig& config) override { + padc0_ = config.get("padc0"); + padc1_ = config.get("padc1"); + padh0_ = config.get("padh0"); + padh1_ = config.get("padh1"); + padw0_ = config.get("padw0"); + padw1_ = config.get("padw1"); + } + + void calc(const Arguments& inputs, + const Arguments& outputs, + const Arguments& inouts) override { + CHECK_EQ(1, inputs.size()); + CHECK_EQ(0, outputs.size()); + CHECK_EQ(1, inouts.size()); + + size_t n = inouts[0].dims_[0]; + size_t inC = inouts[0].dims_[1]; + size_t inH = inouts[0].dims_[2]; + size_t inW = inouts[0].dims_[3]; + + PadGrad(inouts[0].getData(), + inputs[0].getData(), + n, + inC, + inH, + inW, + padc0_, + padc1_, + padh0_, + padh1_, + padw0_, + padw1_); + } + +private: + int padc0_; + int padc1_; + int padh0_; + int padh1_; + int padw0_; + int padw1_; +}; + +REGISTER_TYPED_FUNC(Pad, CPU, PadFunc); +REGISTER_TYPED_FUNC(PadGrad, CPU, PadGradFunc); +#ifndef PADDLE_ONLY_CPU +REGISTER_TYPED_FUNC(Pad, GPU, PadFunc); +REGISTER_TYPED_FUNC(PadGrad, GPU, PadGradFunc); +#endif + +} // namespace paddle diff --git a/paddle/function/PadOp.h b/paddle/function/PadOp.h new file mode 100644 index 00000000000000..4a5e8fe33857aa --- /dev/null +++ b/paddle/function/PadOp.h @@ -0,0 +1,96 @@ +/* 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 This funtion pads zeros to inputs according to the specify dimension. + * The data structure of image data is NCHW. + * + * \param[out] outputs save results. + * \param[in] inputs input data. + * \param[in] num batch size of input data. + * \param[in] inC channel number of input data. + * \param[in] inH height of input data. + * \param[in] inH with of input data. + * \param[in] padc0 how many values to add before the data in dimension of + * channel. + * \param[in] padc1 how many values to add after the data in dimension of + * channel. + * \param[in] padh0 how many values to add before the data in dimension of + * height. + * \param[in] padh1 how many values to add after the data in dimension of + * height. + * \param[in] padw0 how many values to add before the data in dimension of + * width. + * \param[in] padw1 how many values to add after the data in dimension of + * width. + * + */ +template +void Pad(real* outputs, + const real* inputs, + const int num, + const int inC, + const int inH, + const int inW, + const int padc0, + const int padc1, + const int padh0, + const int padh1, + const int padw0, + const int padw1); + +/** + * \brief Padding operation backward. + * The data structure of image data is NCHW. + * + * \param[out] inGrad gradients of previous layer. + * \param[in] outGrad output gradients. + * \param[in] num batch size of input data. + * \param[in] inC channel number of input data. + * \param[in] inH height of input data. + * \param[in] inH with of input data. + * \param[in] padc0 how many values to add before the data in dimension of + * channel. + * \param[in] padc1 how many values to add after the data in dimension of + * channel. + * \param[in] padh0 how many values to add before the data in dimension of + * height. + * \param[in] padh1 how many values to add after the data in dimension of + * height. + * \param[in] padw0 how many values to add before the data in dimension of + * width. + * \param[in] padw1 how many values to add after the data in dimension of + * width. + * + */ +template +void PadGrad(real* inGrad, + const real* outGrad, + const int num, + const int inC, + const int inH, + const int inW, + const int padc0, + const int padc1, + const int padh0, + const int padh1, + const int padw0, + const int padw1); +} // namespace paddle diff --git a/paddle/function/PadOpGpu.cu b/paddle/function/PadOpGpu.cu new file mode 100644 index 00000000000000..578d6e86d7534e --- /dev/null +++ b/paddle/function/PadOpGpu.cu @@ -0,0 +1,102 @@ +/* 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 "PadOp.h" + +namespace paddle { + +__global__ void KePad(real* outputs, const real* inputs, + int inC, int inH, int inW, + int padc, int padh, int padw, + int outC, int outH, int outW, int nthreads) { + const int idx = threadIdx.x + blockIdx.x * blockDim.x; + if (idx < nthreads) { + const int w = idx % inW; + const int h = (idx / inW) % inH; + const int c = (idx / inW / inH) % inC; + const int n = idx / inW / inH / inC; + + const int off = ((n * outC + c + padc) * outH + h + padh) * outW + padw + w; + outputs[off] = inputs[idx]; + } +} + +template <> +void Pad(real* outputs, + const real* inputs, + const int num, + const int inC, + const int inH, + const int inW, + const int padc0, + const int padc1, + const int padh0, + const int padh1, + const int padw0, + const int padw1) { + size_t nth = num * inC * inH * inW; + int blockSize = 1024; + int gridSize = (nth + 1024 - 1) / 1024; + int outC = inC + padc0 + padc1; + int outH = inH + padh0 + padh1; + int outW = inW + padw0 + padw1; + KePad<<>> + (outputs, inputs, inC, inH, inW, padc0, padh0, padw0, + outC, outH, outW, nth); + CHECK_SYNC("Pad"); +} + +__global__ void KePadDiff(real* inGrad, const real* outGrad, + int inC, int inH, int inW, + int padc, int padh, int padw, + int outC, int outH, int outW, int nthreads) { + const int idx = threadIdx.x + blockIdx.x * blockDim.x; + if (idx < nthreads) { + const int w = idx % inW; + const int h = (idx / inW) % inH; + const int c = (idx / inW / inH) % inC; + const int n = idx / inW / inH / inC; + + const int off = ((n * outC + c + padc) * outH + h + padh) * outW + padw + w; + inGrad[idx] += outGrad[off]; + } +} + +template <> +void PadGrad(real* inGrad, + const real* outGrad, + const int num, + const int inC, + const int inH, + const int inW, + const int padc0, + const int padc1, + const int padh0, + const int padh1, + const int padw0, + const int padw1) { + int nth = num * inC * inH * inW; + int blockSize = 1024; + int gridSize = (nth + 1024 - 1) / 1024; + int outC = inC + padc0 + padc1; + int outH = inH + padh0 + padh1; + int outW = inW + padw0 + padw1; + KePadDiff <<>> + (inGrad, outGrad, inC, inH, inW, padc0, padh0, padw0, + outC, outH, outW, nth); + CHECK_SYNC("PadGrad"); +} + +} // namespace paddle diff --git a/paddle/function/PadOpTest.cpp b/paddle/function/PadOpTest.cpp new file mode 100644 index 00000000000000..ee2834d793d348 --- /dev/null +++ b/paddle/function/PadOpTest.cpp @@ -0,0 +1,70 @@ +/* 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 +#include "FunctionTest.h" + +namespace paddle { + +TEST(Pad, real) { + for (size_t numSamples : {5, 32}) { + for (size_t channels : {1, 5, 32}) { + for (size_t imgSizeH : {5, 33, 100}) { + for (size_t imgSizeW : {5, 32, 96}) { + VLOG(3) << " numSamples=" << numSamples << " channels=" << channels + << " imgSizeH=" << imgSizeH << " imgSizeW=" << imgSizeW; + + FunctionCompare compare("Pad", + FuncConfig() + .set("padc0", 2) + .set("padc1", 3) + .set("padh0", 1) + .set("padh1", 2) + .set("padw0", 3) + .set("padw1", 2)); + Dims inDims{numSamples, channels, imgSizeH, imgSizeW}; + Dims outDims{numSamples, channels + 5, imgSizeH + 3, imgSizeW + 5}; + compare.cmpWithArg( + {Tensor(nullptr, inDims)}, {Tensor(nullptr, outDims)}, {}); + } + } + } + } +} + +// TEST(PadGrad, real) { +// for (size_t numSamples : {5, 32}) { +// for (size_t channels : {1, 5, 32}) { +// for (size_t imgSizeH : {5, 33, 100}) { +// for (size_t imgSizeW : {5, 32, 96}) { +// VLOG(3) << " numSamples=" << numSamples << " channels=" << channels +// << " imgSizeH=" << imgSizeH << " imgSizeW=" << imgSizeW; +// +// FunctionCompare compare("PadGrad", +// FuncConfig() +// .set("padc0", 2).set("padc1", 3) +// .set("padh0", 1).set("padh1", 2) +// .set("padw0", 3).set("padw1", 2)); +// Dims inDims{numSamples, channels, imgSizeH, imgSizeW}; +// Dims outDims{numSamples, channels + 5, imgSizeH + 3, imgSizeW + 5}; +// compare.cmpWithArg({Tensor(nullptr, inDims)}, +// {Tensor(nullptr, outDims)}, +// {}); +// } +// } +// } +// } +//} + +} // namespace paddle diff --git a/paddle/gserver/layers/PadLayer.cpp b/paddle/gserver/layers/PadLayer.cpp new file mode 100644 index 00000000000000..62c50af32dd055 --- /dev/null +++ b/paddle/gserver/layers/PadLayer.cpp @@ -0,0 +1,115 @@ +/* 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 "PadLayer.h" +#include "paddle/utils/Stat.h" + +namespace paddle { + +REGISTER_LAYER(pad, PadLayer); + +bool PadLayer::init(const LayerMap& layerMap, + const ParameterMap& parameterMap) { + /* Initialize the basic parent class */ + Layer::init(layerMap, parameterMap); + + auto& pad_conf = config_.inputs(0).pad_conf(); + auto& img_conf = pad_conf.image_conf(); + CHECK_EQ(config_.inputs_size(), 1); + inDims_.push_back(0); + inDims_.push_back(img_conf.channels()); + inDims_.push_back(img_conf.has_img_size_y() ? img_conf.img_size_y() + : img_conf.img_size()); + inDims_.push_back(img_conf.img_size()); + + CHECK_EQ(2UL, pad_conf.pad_c_size()); + CHECK_EQ(2UL, pad_conf.pad_h_size()); + CHECK_EQ(2UL, pad_conf.pad_w_size()); + padc_.push_back(pad_conf.pad_c(0)); + padc_.push_back(pad_conf.pad_c(1)); + padh_.push_back(pad_conf.pad_h(0)); + padh_.push_back(pad_conf.pad_h(1)); + padw_.push_back(pad_conf.pad_w(0)); + padw_.push_back(pad_conf.pad_w(1)); + + outDims_.resize(4); + setOutDims(0); + + createFunction(forward_, + "Pad", + FuncConfig() + .set("padc0", padc_[0]) + .set("padc1", padc_[1]) + .set("padh0", padh_[0]) + .set("padh1", padh_[1]) + .set("padw0", padw_[0]) + .set("padw1", padw_[1])); + createFunction(backward_, + "PadGrad", + FuncConfig() + .set("padc0", padc_[0]) + .set("padc1", padc_[1]) + .set("padh0", padh_[0]) + .set("padh1", padh_[1]) + .set("padw0", padw_[0]) + .set("padw1", padw_[1])); + + return true; +} + +void PadLayer::setOutDims(int batchSize) { + outDims_[0] = batchSize; + outDims_[1] = inDims_[1] + padc_[0] + padc_[1]; + outDims_[2] = inDims_[2] + padh_[0] + padh_[1]; + outDims_[3] = inDims_[3] + padw_[0] + padw_[1]; +} + +void PadLayer::setTensorDim(int batchSize) { + CHECK_EQ(inputLayers_.size(), 1UL); + inDims_[0] = batchSize; + int h = inputLayers_[0]->getOutput().getFrameHeight(); + if (h != 0) inDims_[2]; + int w = inputLayers_[0]->getOutput().getFrameWidth(); + if (w != 0) inDims_[3]; + setOutDims(batchSize); +} + +void PadLayer::forward(PassType passType) { + Layer::forward(passType); + MatrixPtr input = inputLayers_[0]->getOutputValue(); + size_t batchSize = input->getHeight(); + setTensorDim(batchSize); + int size = outDims_[1] * outDims_[2] * outDims_[3]; + resetOutput(batchSize, size); + MatrixPtr outV = getOutputValue(); + REGISTER_TIMER_INFO("PadForward", getName().c_str()); + forward_[0]->calc({Tensor(input->getData(), inDims_)}, + {Tensor(outV->getData(), outDims_)}, + {}); +} + +void PadLayer::backward(const UpdateCallback& callback) { + (void)callback; + + MatrixPtr preGrad = inputLayers_[0]->getOutputGrad(); + if (NULL == preGrad) { + return; + } + MatrixPtr outGrad = getOutputGrad(); + REGISTER_TIMER_INFO("PadBackward", getName().c_str()); + backward_[0]->calc({Tensor(outGrad->getData(), outDims_)}, + {}, + {Tensor(preGrad->getData(), inDims_)}); +} +} // namespace paddle diff --git a/paddle/gserver/layers/PadLayer.h b/paddle/gserver/layers/PadLayer.h new file mode 100644 index 00000000000000..834622a7af396e --- /dev/null +++ b/paddle/gserver/layers/PadLayer.h @@ -0,0 +1,45 @@ +/* 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 "Layer.h" + +namespace paddle { + +/** + * @brief response normalization across feature maps + * namely normalize in number of size_ channels + */ +class PadLayer : public Layer { +public: + explicit PadLayer(const LayerConfig& config) : Layer(config) {} + + ~PadLayer() {} + + bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + void forward(PassType passType); + void backward(const UpdateCallback& callback = nullptr); + +protected: + void setOutDims(int batchSize); + void setTensorDim(int batchSize); + + std::vector padc_; + std::vector padh_; + std::vector padw_; + Dims inDims_; + Dims outDims_; +}; +} // namespace paddle diff --git a/paddle/gserver/tests/test_LayerGrad.cpp b/paddle/gserver/tests/test_LayerGrad.cpp index 2cc25f6b211e36..3094b3a4a02e3e 100644 --- a/paddle/gserver/tests/test_LayerGrad.cpp +++ b/paddle/gserver/tests/test_LayerGrad.cpp @@ -32,1534 +32,1580 @@ DECLARE_double(checkgrad_eps); DECLARE_bool(thread_local_rand_use_global_seed); DECLARE_bool(prev_batch_state); -TEST(Operator, dot_mul) { +// TEST(Operator, dot_mul) { +// TestConfig config; +// config.layerConfig.set_size(10); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); +// config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// OperatorConfig& operatorConf = *config.layerConfig.add_operator_confs(); +// operatorConf.set_type("dot_mul"); +// operatorConf.set_dotmul_scale(-1); +// +// testOperatorGrad(config, operatorConf, 100, false, false); +// } +// +// TEST(Projection, context) { +// for (auto contextStart : {-5, -3, -1, 0, 3}) { +// for (auto contextLength : {1, 2, 5, 7}) { +// for (auto batchSize : {1, 2, 5, 20, 50}) { +// for (auto trainablePadding : {false, true}) { +// LOG(INFO) << " contextStart=" << contextStart +// << " contextLength=" << contextLength +// << " batchSize=" << batchSize +// << " trainablePadding=" << trainablePadding; +// ProjectionConfig conf; +// conf.set_type("context"); +// conf.set_input_size(10); +// conf.set_context_start(contextStart); +// conf.set_context_length(contextLength); +// conf.set_trainable_padding(trainablePadding); +// conf.set_output_size(conf.context_length() * conf.input_size()); +// int pad = +// std::max(0, -conf.context_start()) + +// std::max(0, conf.context_start() + conf.context_length() - 1); +// for (auto useGpu : {false, true}) { +// testProjectionGrad( +// conf, +// INPUT_SEQUENCE_DATA, +// trainablePadding ? conf.input_size() * pad : 0, +// batchSize, +// useGpu, +// contextStart + contextLength <= 1); // = testState +// } +// } +// } +// } +// } +// } +// +// TEST(Projection, trans_fc) { +// ProjectionConfig conf; +// conf.set_type("trans_fc"); +// conf.set_input_size(50); +// conf.set_output_size(20); +// for (auto useGpu : {false, true}) { +// testProjectionGrad(conf, +// INPUT_DATA, +// /* parameterSize */ 1000, +// /* batchSize */ 100, +// useGpu); +// } +// } +// +// TEST(Projection, fc) { +// ProjectionConfig conf; +// conf.set_type("fc"); +// conf.set_input_size(10); +// conf.set_output_size(20); +// for (auto useGpu : {false, true}) { +// testProjectionGrad(conf, +// INPUT_DATA, +// /* parameterSize */ 200, +// /* batchSize */ 100, +// useGpu); +// } +// } +// +// TEST(Projection, dot_mul) { +// ProjectionConfig conf; +// conf.set_type("dot_mul"); +// conf.set_input_size(20); +// conf.set_output_size(20); +// for (auto useGpu : {false, true}) { +// testProjectionGrad(conf, +// INPUT_DATA, +// /* parameterSize */ 20, +// /* batchSize */ 100, +// useGpu); +// } +// } +// +// TEST(Projection, table) { +// ProjectionConfig conf; +// conf.set_type("table"); +// conf.set_input_size(10); +// conf.set_output_size(20); +// for (auto useGpu : {false, true}) { +// testProjectionGrad(conf, +// INPUT_LABEL, +// /* parameterSize */ 200, +// /* batchSize */ 100, +// useGpu); +// } +// } +// +// TEST(Projection, identity) { +// ProjectionConfig conf; +// conf.set_type("identity"); +// conf.set_input_size(10); +// conf.set_output_size(10); +// for (auto useGpu : {false, true}) { +// testProjectionGrad(conf, +// INPUT_DATA, +// /* parameterSize */ 0, +// /* batchSize */ 100, +// useGpu); +// } +// } +// +// TEST(Projection, scaling) { +// ProjectionConfig conf; +// conf.set_type("scaling"); +// conf.set_input_size(10); +// conf.set_output_size(10); +// for (auto useGpu : {false}) { +// testProjectionGrad(conf, +// INPUT_DATA, +// /* parameterSize */ 1, +// /* batchSize */ 100, +// useGpu); +// } +// } +// +// void testProjectionConv(size_t groups) { +// const int NUM_FILTERS = 18; +// const int FILTER_SIZE = 2; +// const int FILTER_SIZE_Y = 3; +// const int CHANNELS = 3; +// const int IMAGE_SIZE = 16; +// +// ProjectionConfig conf; +// conf.set_type("conv"); +// conf.set_num_filters(NUM_FILTERS); +// +// ConvConfig* conv = conf.mutable_conv_conf(); +// conv->set_filter_size(FILTER_SIZE); +// conv->set_filter_size_y(FILTER_SIZE_Y); +// conv->set_channels(CHANNELS); +// conv->set_padding(0); +// conv->set_padding_y(1); +// conv->set_stride(2); +// conv->set_stride_y(2); +// conv->set_groups(groups); +// conv->set_filter_channels(conv->channels() / conv->groups()); +// conv->set_img_size(IMAGE_SIZE); +// int output_x = outputSize(conv->img_size(), +// conv->filter_size(), +// conv->padding(), +// conv->stride(), +// /* caffeMode */ true); +// int output_y = outputSize(conv->img_size(), +// conv->filter_size_y(), +// conv->padding_y(), +// conv->stride_y(), +// /* caffeMode */ true); +// conv->set_output_x(output_x); +// conf.set_input_size(IMAGE_SIZE * IMAGE_SIZE * CHANNELS); +// conf.set_output_size(output_x * output_y * NUM_FILTERS); +// +// testProjectionGrad(conf, +// INPUT_DATA, +// /* parameterSize */ NUM_FILTERS * CHANNELS * FILTER_SIZE +// * +// FILTER_SIZE_Y / groups, +// /* batchSize */ 100, +// true, +// false, +// NUM_FILTERS, +// true); +// } +// +// #ifndef PADDLE_ONLY_CPU +// TEST(Projection, conv) { +// testProjectionConv(1); +// testProjectionConv(3); +// } +// #endif +// +// TEST(Layer, BilinearInterpLayer) { +// TestConfig config; +// config.layerConfig.set_type("bilinear_interp"); +// config.biasSize = 0; +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 4096, 0}); +// +// LayerInputConfig* input = config.layerConfig.add_inputs(); +// BilinearInterpConfig* bilinear = input->mutable_bilinear_interp_conf(); +// ImageConfig* image = bilinear->mutable_image_conf(); +// image->set_img_size(32); +// image->set_img_size_y(32); +// image->set_channels(4); +// +// for (auto useGpu : {false, true}) { +// for (auto outSize : {32, 64}) { +// bilinear->set_out_size_x(outSize); +// bilinear->set_out_size_y(outSize); +// testLayerGrad(config, "bilinear_interp", 10, false, useGpu); +// } +// } +// } +// +// TEST(Layer, concat) { +// TestConfig config; +// config.biasSize = 0; +// config.layerConfig.set_type("concat"); +// config.layerConfig.set_size(15); +// config.layerConfig.set_active_type("sigmoid"); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 5, 0}); +// config.layerConfig.add_inputs(); +// config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "concat", 100, false, useGpu); +// } +// } +// +// TEST(Layer, AddtoLayer) { +// TestConfig config; +// config.biasSize = 0; +// config.layerConfig.set_type("addto"); +// config.layerConfig.set_size(10); +// config.layerConfig.set_active_type("sigmoid"); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); +// config.layerConfig.add_inputs(); +// config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "addto", 100, false, useGpu); +// } +// } +// +// TEST(Layer, CRFLayer) { +// TestConfig config; +// config.layerConfig.set_type("crf"); +// config.layerConfig.set_size(10); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 10, 120}); +// config.inputDefs.push_back({INPUT_SEQUENCE_LABEL, "layer_1", 10, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// // Not support GPU now +// testLayerGrad(config, +// "crf", +// 100, +// /* trans */ false, +// /* useGpu */ false, +// false /*useWeight*/, +// 0.03 /*epsilon*/); +// } +// +// TEST(Layer, CTCLayer) { +// TestConfig config; +// config.layerConfig.set_type("ctc"); +// config.layerConfig.set_norm_by_times(false); +// config.layerConfig.set_size(10); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 10, 0}); +// config.inputDefs.push_back({INPUT_SEQUENCE_LABEL, "layer_1", 10, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "ctc", 100, /* trans */ false, /* useGpu */ +// useGpu); +// } +// } +// +// TEST(Layer, cosSimLayer) { +// TestConfig config; +// config.layerConfig.set_type("cos"); +// config.layerConfig.set_size(1); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); +// config.inputDefs.push_back({INPUT_DATA, "layer_1", 50, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "cos", 100, false, useGpu); +// } +// } +// +// TEST(Layer, CosSimVecMatLayer) { +// TestConfig config; +// config.layerConfig.set_type("cos_vm"); +// config.layerConfig.set_size(5); // output size +// config.layerConfig.set_cos_scale(2.0); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 20, 0}); +// config.layerConfig.add_inputs(); +// config.inputDefs.push_back({INPUT_DATA, "layer_1", 100, 0}); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "cos_vm", 100, false, useGpu); +// } +// } +// +// void testConvLayer(const string& type, bool trans, bool useGpu) { +// TestConfig config; +// config.biasSize = 16; +// config.layerConfig.set_type(type); +// config.layerConfig.set_num_filters(16); +// config.layerConfig.set_partial_sum(1); +// config.layerConfig.set_shared_biases(true); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 384, 288}); +// LayerInputConfig* input = config.layerConfig.add_inputs(); +// ConvConfig* conv = input->mutable_conv_conf(); +// conv->set_filter_size(2); +// conv->set_filter_size_y(3); +// conv->set_channels(3); +// conv->set_padding(0); +// conv->set_padding_y(1); +// conv->set_stride(2); +// conv->set_stride_y(2); +// conv->set_groups(1); +// conv->set_filter_channels(conv->channels() / conv->groups()); +// conv->set_img_size(16); +// conv->set_img_size_y(8); +// conv->set_output_x(outputSize(conv->img_size(), +// conv->filter_size(), +// conv->padding(), +// conv->stride(), +// /* caffeMode */ true)); +// conv->set_output_y(outputSize(conv->img_size_y(), +// conv->filter_size_y(), +// conv->padding_y(), +// conv->stride_y(), +// /* caffeMode */ true)); +// config.layerConfig.set_size(conv->output_x() * conv->output_y() * +// config.layerConfig.num_filters()); +// +// testLayerGrad(config, "conv", 100, trans, useGpu); +// // Use small batch_size and useWeight=true to test biasGrad +// testLayerGrad(config, "conv", 2, trans, useGpu, true, 0.02); +// } +// +// TEST(Layer, convLayer) { +// testConvLayer("exconv", /* trans= */ false, /* useGpu= */ false); +// #ifndef PADDLE_ONLY_CPU +// testConvLayer("exconv", /* trans= */ false, /* useGpu= */ true); +// testConvLayer("cudnn_conv", /* trans= */ false, /* useGpu= */ true); +// #endif +// } +// +// void testConvTransLayer(const string& type, bool trans, bool useGpu) { +// TestConfig config; +// config.biasSize = 3; +// config.layerConfig.set_type(type); +// config.layerConfig.set_num_filters(3); +// config.layerConfig.set_partial_sum(1); +// config.layerConfig.set_shared_biases(true); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1024, 288}); +// LayerInputConfig* input = config.layerConfig.add_inputs(); +// ConvConfig* conv = input->mutable_conv_conf(); +// conv->set_filter_size(2); +// conv->set_filter_size_y(3); +// conv->set_channels(16); +// conv->set_padding(0); +// conv->set_padding_y(1); +// conv->set_stride(2); +// conv->set_stride_y(2); +// conv->set_groups(1); +// conv->set_filter_channels(3 / conv->groups()); +// conv->set_img_size(16); +// conv->set_output_x(outputSize(conv->img_size(), +// conv->filter_size(), +// conv->padding(), +// conv->stride(), +// /* caffeMode */ true)); +// +// config.layerConfig.set_size(conv->img_size() * conv->img_size() * +// config.layerConfig.num_filters()); +// +// testLayerGrad(config, "convTrans", 100, trans, useGpu); +// // Use small batch_size and useWeight=true to test biasGrad +// testLayerGrad(config, "convTrans", 2, trans, useGpu, true, 0.02); +// } +// +// TEST(Layer, convTransLayer) { +// for (auto useGpu : {false, true}) { +// testConvTransLayer("exconvt", /* trans= */ false, /* useGpu= */ useGpu); +// } +// } +// +// TEST(Layer, blockExpandLayer) { +// TestConfig config; +// config.biasSize = 0; +// config.layerConfig.set_type("blockexpand"); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 6144, 0}); +// LayerInputConfig* input = config.layerConfig.add_inputs(); +// BlockExpandConfig* blockExpand = input->mutable_block_expand_conf(); +// blockExpand->set_img_size_x(64); +// blockExpand->set_img_size_y(32); +// blockExpand->set_channels(3); +// blockExpand->set_padding_x(0); +// blockExpand->set_padding_y(0); +// blockExpand->set_block_x(4); +// blockExpand->set_block_y(32); +// blockExpand->set_stride_x(2); +// blockExpand->set_stride_y(2); +// blockExpand->set_output_x(outputSize(blockExpand->img_size_x(), +// blockExpand->block_x(), +// blockExpand->padding_x(), +// blockExpand->stride_x(), +// /* caffeMode */ false)); +// blockExpand->set_output_y(outputSize(blockExpand->img_size_y(), +// blockExpand->block_y(), +// blockExpand->padding_y(), +// blockExpand->stride_y(), +// /* caffeMode */ false)); +// config.layerConfig.set_size(blockExpand->block_x() * blockExpand->block_y() +// * +// blockExpand->channels()); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "blockexpand", 100, false, useGpu); +// } +// } +// +// TEST(Layer, maxoutLayer) { +// TestConfig config; +// config.biasSize = 0; +// config.layerConfig.set_type("maxout"); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 4096, 0}); +// LayerInputConfig* input = config.layerConfig.add_inputs(); +// MaxOutConfig* maxout = input->mutable_maxout_conf(); +// ImageConfig* image = maxout->mutable_image_conf(); +// +// image->set_img_size(32); +// image->set_img_size_y(32); +// image->set_channels(4); +// maxout->set_groups(2); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "maxout", 10, false, useGpu); +// } +// } +// void testFcLayer(string format, size_t nnz) { +// TestConfig config; +// config.biasSize = 4096; +// config.layerConfig.set_type("fc"); +// config.layerConfig.set_size(4096); +// config.layerConfig.set_active_type("sigmoid"); +// config.layerConfig.set_drop_rate(0.1); +// +// config.inputDefs.push_back( +// {INPUT_DATA, "layer_0", 8192, nnz, ParaSparse(format)}); +// config.layerConfig.add_inputs(); +// +// LOG(INFO) << config.inputDefs[0].sparse.sparse << " " +// << config.inputDefs[0].sparse.format; +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, +// "fc", +// 100, +// /* trans */ false, +// useGpu, +// /* weight */ true); +// } +// } +// +// TEST(Layer, fcLayer) { +// testFcLayer("", 4096 * 4096 * 2); +// testFcLayer("csc", 4096 * 40); +// testFcLayer("csr", 4096 * 40); +// } +// +// TEST(Layer, SelectiveFullyConnectedLayer) { +// TestConfig config; +// size_t nin = 16; +// size_t nout = 256; +// config.layerConfig.set_type("selective_fc"); +// config.layerConfig.set_size(nout); +// config.layerConfig.set_active_type("sigmoid"); +// config.layerConfig.set_has_selected_colums(true); +// config.layerConfig.set_selective_fc_pass_generation(false); +// config.biasSize = nout; +// +// config.inputDefs.push_back({INPUT_DATA, "input0", nin, nin * nout}); +// config.layerConfig.add_inputs(); +// config.inputDefs.push_back( +// {INPUT_SPARSE_NON_VALUE_DATA, "index", nout, 0, ParaSparse("csr", +// true)}); +// config.layerConfig.add_inputs(); +// +// testLayerGrad(config, +// "selective_fc", +// 100, +// /* trans= */ false, +// /* useGup= */ false, +// false); +// #ifndef PADDLE_ONLY_CPU +// testLayerGrad(config, +// "selective_fc", +// 100, +// /* trans= */ false, +// /* useGup= */ true, +// false); +// #endif +// } +// +// TEST(Layer, DataNormLayer) { +// TestConfig config; +// config.layerConfig.set_type("data_norm"); +// config.layerConfig.set_size(20); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 20, 100}); +// config.inputDefs.back().isStatic = true; +// config.layerConfig.add_inputs(); +// +// for (auto strategy : {"z-score", "min-max", "decimal-scaling"}) { +// config.layerConfig.set_data_norm_strategy(strategy); +// // The parameters are static, so not support GPU now +// testLayerGrad(config, +// "data_norm", +// 200, +// /* trans */ false, +// /* useGpu */ false); +// } +// } +// +// TEST(Layer, hsigmoidLayer) { +// TestConfig config; +// config.layerConfig.set_type("hsigmoid"); +// config.layerConfig.set_num_classes(5); +// config.layerConfig.set_size(1); +// config.biasSize = config.layerConfig.num_classes() - 1; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 200}); +// config.inputDefs.push_back({INPUT_LABEL, "layer_1", 5, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// // Not support GPU now +// testLayerGrad(config, "hsigmoid", 100, /* trans */ false, /* useGpu */ +// false); +// } +// +// TEST(Layer, multi_cross) { +// TestConfig config; +// config.layerConfig.set_type("multi-class-cross-entropy"); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); +// config.inputDefs.push_back({INPUT_LABEL, "layer_1", 10, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad( +// config, "multi-class-cross-entropy", 100, /* trans */ false, useGpu); +// } +// } +// +// TEST(Layer, multi_binary_label_sparse_mat) { +// TestConfig config; +// config.layerConfig.set_type("multi_binary_label_cross_entropy"); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); +// config.inputDefs.push_back({INPUT_SPARSE_NON_VALUE_DATA, "layer_1", 50, +// 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, +// "multi_binary_label_cross_entropy", +// 100, +// /* trans */ false, +// useGpu); +// } +// } +// +// TEST(layer, multi_binary_label_id) { +// TestConfig config; +// config.layerConfig.set_type("multi_binary_label_cross_entropy"); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); +// config.inputDefs.push_back({INPUT_LABEL, "layer_1", 10, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, +// "multi_binary_label_cross_entropy", +// 100, +// /* trans */ false, +// useGpu); +// } +// } +// +// TEST(Layer, multi_cross_with_selfnorm) { +// TestConfig config; +// config.layerConfig.set_type("multi_class_cross_entropy_with_selfnorm"); +// config.layerConfig.set_softmax_selfnorm_alpha(0.1); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); +// config.inputDefs.push_back({INPUT_LABEL, "layer_1", 10, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// // Not support GPU now +// testLayerGrad(config, +// "multi_class_cross_entropy_with_selfnorm", +// 100, +// /* trans */ false, +// /* useGpu */ false); +// } +// +// TEST(Layer, multi_cross_soft) { +// TestConfig config; +// config.layerConfig.set_type("soft_binary_class_cross_entropy"); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); +// config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_1", 10, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, +// "soft_binary_class_cross_entropy", +// 100, +// /* trans */ false, +// useGpu); +// } +// } +// +// TEST(Layer, square_error) { +// TestConfig config; +// config.layerConfig.set_type("square_error"); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); +// config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_1", 10, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "square_error", 100, /* trans */ false, useGpu); +// } +// } +// +// TEST(Layer, sparse_square_error) { +// TestConfig config; +// config.layerConfig.set_type("square_error"); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); +// config.inputDefs.push_back({INPUT_SPARSE_NON_VALUE_DATA, "layer_1", 50, +// 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// // "GpuSparseMatrix" as label is not supported +// testLayerGrad(config, +// "square_error", +// 100, +// /* trans */ false, +// /* useGpu */ false); +// } +// +// TEST(Layer, sparse_float_square_error) { +// TestConfig config; +// config.layerConfig.set_type("square_error"); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); +// config.inputDefs.push_back({INPUT_SPARSE_FLOAT_VALUE_DATA, "layer_1", 50, +// 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// // "GpuSparseMatrix" as label is not supported +// testLayerGrad(config, +// "square_error", +// 100, +// /* trans */ false, +// /* useGpu */ false); +// } +// +// TEST(Layer, square_error_weighted) { +// TestConfig config; +// config.layerConfig.set_type("square_error"); +// config.biasSize = 0; +// config.testAccumulate = false; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); +// config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_1", 10, 0}); +// config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_2", 1, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "square_error", 100, /* trans */ false, useGpu); +// } +// } +// +// TEST(Layer, huber_two_class) { +// TestConfig config; +// config.layerConfig.set_type("huber"); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); +// config.inputDefs.push_back({INPUT_LABEL, "layer_1", 2, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "huber", 100, /* trans */ false, useGpu); +// } +// } +// +// void testExpandLayer(string trans_type, bool hasSubseq) { +// TestConfig config; +// config.layerConfig.set_type("expand"); +// +// config.inputDefs.push_back( +// {trans_type == "non-seq" ? INPUT_DENSE_DIM_DATA : INPUT_SEQUENCE_DATA, +// "layer_0", +// 10, +// 0}); +// config.inputDefs.push_back( +// {hasSubseq ? INPUT_HASSUB_SEQUENCE_DATA : INPUT_SEQUENCE_DATA, +// "layer_1", +// 10, +// 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// config.layerConfig.set_trans_type(trans_type); +// LOG(INFO) << " trans_type=" << trans_type << " hasSubseq=" << hasSubseq; +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "expand", 30, false, useGpu); +// } +// } +// +// TEST(Layer, ExpandLayer) { +// testExpandLayer("non-seq", false); // non-seq expand to seq +// testExpandLayer("non-seq", true); // non-seq expand to hasSubseq +// testExpandLayer("seq", true); // seq expand to hasSubseq +// } +// +// void testDegradeLayer(bool hasSubseq, string layer_type, string trans_type) { +// TestConfig config; +// config.layerConfig.set_type(layer_type); +// config.layerConfig.set_size(10); +// config.biasSize = 0; +// +// config.inputDefs.push_back( +// {hasSubseq ? INPUT_HASSUB_SEQUENCE_DATA : INPUT_SEQUENCE_DATA, +// "layer_0", +// 10, +// 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.set_trans_type(trans_type); +// +// auto testDegradeLayerGrad = [](TestConfig& config, string layer_type) { +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, layer_type, 100, false, useGpu); +// } +// }; +// +// if (layer_type == "average") { +// for (auto strategy : {"average", "sum", "squarerootn"}) { +// LOG(INFO) << " hasSubseq=" << hasSubseq << " trans_type=" << trans_type +// << " average_strategy=" << strategy; +// config.layerConfig.set_average_strategy(strategy); +// testDegradeLayerGrad(config, layer_type); +// } +// } else { +// LOG(INFO) << " hasSubseq=" << hasSubseq << " trans_type=" << trans_type; +// testDegradeLayerGrad(config, layer_type); +// } +// } +// +// TEST(Layer, MaxLayer) { +// testDegradeLayer(false, "max", "non-seq"); // seq max to non-seq +// testDegradeLayer(true, "max", "non-seq"); // hasSubseq max to non-seq +// testDegradeLayer(true, "max", "seq"); // hasSubseq max to seq +// } +// +// TEST(Layer, SequenceLastInstanceLayer) { +// testDegradeLayer(false, +// "seqlastins", +// "non-seq"); // seq seqlastins to non-seq +// testDegradeLayer(true, +// "seqlastins", +// "non-seq"); // hasSubseq seqlastins to non-seq +// testDegradeLayer(true, "seqlastins", "seq"); // hasSubseq seqlastins to +// seq +// } +// +// TEST(Layer, AverageLayer) { +// testDegradeLayer(false, "average", "non-seq"); // seq average to non-seq +// testDegradeLayer(true, "average", "non-seq"); // hasSubseq average to +// non-seq +// testDegradeLayer(true, "average", "seq"); // hasSubseq average to seq +// } +// +// TEST(Layer, SequenceConcatLayer) { +// TestConfig config; +// config.layerConfig.set_type("seqconcat"); +// config.layerConfig.set_size(10); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 10, 0}); +// config.layerConfig.add_inputs(); +// config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_1", 10, 0}); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "seqconcat", 100, false, useGpu); +// } +// } +// +// TEST(Layer, SequenceReshapeLayer) { +// TestConfig config; +// config.layerConfig.set_type("seqreshape"); +// config.layerConfig.set_size(10); +// +// config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 100, 0}); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "seqreshape", 100, false, useGpu); +// } +// } +// +// TEST(Layer, ConvShiftLayer) { +// TestConfig config; +// config.layerConfig.set_type("conv_shift"); +// config.layerConfig.set_size(10); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); +// config.inputDefs.push_back({INPUT_DATA, "layer_1", 3, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// // Not support GPU now +// testLayerGrad(config, "conv_shift", 100, false, false); +// } +// +// TEST(Layer, PowerLayer) { +// TestConfig config; +// config.layerConfig.set_type("power"); +// config.layerConfig.set_size(10); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); +// config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "power", 100, false, useGpu); +// } +// } +// +// TEST(Layer, ConvexCombinationLayer) { +// TestConfig config; +// config.layerConfig.set_type("convex_comb"); +// config.layerConfig.set_size(20); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 5, 0}); +// config.inputDefs.push_back({INPUT_DATA, "layer_1", 100, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "convex_comb", 100, false, useGpu); +// } +// } +// +// TEST(Layer, InterpolationLayer) { +// TestConfig config; +// config.layerConfig.set_type("interpolation"); +// config.layerConfig.set_size(10); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); +// config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); +// config.inputDefs.push_back({INPUT_DATA, "layer_2", 10, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "interpolation", 100, false, useGpu); +// } +// } +// +// TEST(Layer, OuterProdLayer) { +// TestConfig config; +// config.layerConfig.set_type("out_prod"); +// config.layerConfig.set_size(100); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); +// config.layerConfig.add_inputs(); +// config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "out_prod", 100, false, useGpu); +// } +// } +// +// TEST(Layer, SlopeInterceptLayer) { +// TestConfig config; +// config.layerConfig.set_type("slope_intercept"); +// config.layerConfig.set_size(10); +// config.layerConfig.set_slope(1.0); +// config.layerConfig.set_intercept(0.1); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "slope_intercept", 100, false, useGpu); +// } +// } +// +// TEST(Layer, ScalingLayer) { +// TestConfig config; +// config.layerConfig.set_type("scaling"); +// config.layerConfig.set_size(10); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); +// config.layerConfig.add_inputs(); +// config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "scaling", 100, false, useGpu); +// } +// } +// +// void testNormLayer(const string& normType, bool trans, bool useGpu) { +// TestConfig config; +// config.layerConfig.set_type("norm"); +// config.layerConfig.set_active_type("relu"); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1568, 0}); +// LayerInputConfig* input = config.layerConfig.add_inputs(); +// NormConfig* norm = input->mutable_norm_conf(); +// norm->set_norm_type(normType); +// norm->set_channels(16); +// norm->set_size(5); +// norm->set_scale(0.001); +// norm->set_pow(0.75); +// norm->set_blocked(0); +// norm->set_img_size(14); +// norm->set_img_size_y(7); +// norm->set_output_x(norm->img_size()); +// norm->set_output_y(norm->img_size_y()); +// if (norm->norm_type() == "cmrnorm" || +// norm->norm_type() == "cmrnorm-projection") { +// norm->set_scale(norm->scale() / norm->size()); +// } else { +// norm->set_scale(norm->scale() / (norm->size() * norm->size())); +// } +// +// config.layerConfig.set_size(norm->output_x() * norm->output_y() * +// norm->channels()); +// config.biasSize = 0; +// +// testLayerGrad(config, "norm", 100, trans, useGpu); +// } +// +// TEST(Layer, NormLayer) { +// testNormLayer("cmrnorm-projection", /* trans= */ false, /* useGpu= */ +// true); +// testNormLayer("cmrnorm-projection", /* trans= */ false, /* useGpu= */ +// false); +// } +// +// void setPoolConfig(TestConfig* config, +// PoolConfig* pool, +// const string& poolType) { +// (*config).biasSize = 0; +// (*config).layerConfig.set_type("pool"); +// (*config).layerConfig.set_num_filters(16); +// +// int kw = 3, kh = 3; +// int pw = 0, ph = 0; +// int sw = 2, sh = 2; +// pool->set_pool_type(poolType); +// pool->set_channels(16); +// pool->set_size_x(kw); +// pool->set_size_y(kh); +// pool->set_start(0); +// pool->set_padding(pw); +// pool->set_padding_y(ph); +// pool->set_stride(sw); +// pool->set_stride_y(sh); +// +// int ow = outputSize(pool->img_size(), kw, pw, sw, /* caffeMode */ false); +// int oh = outputSize(pool->img_size_y(), kh, ph, sh, /* caffeMode */ false); +// pool->set_output_x(ow); +// pool->set_output_y(oh); +// } +// +// void testPoolLayer(const string& poolType, bool trans, bool useGpu) { +// TestConfig config; +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 3136, 0}); +// LayerInputConfig* input = config.layerConfig.add_inputs(); +// PoolConfig* pool = input->mutable_pool_conf(); +// +// pool->set_img_size(14); +// pool->set_img_size_y(14); +// setPoolConfig(&config, pool, poolType); +// config.layerConfig.set_size(pool->output_x() * pool->output_y() * +// pool->channels()); +// +// testLayerGrad(config, "pool", 100, trans, useGpu); +// } +// +// #ifndef PADDLE_ONLY_CPU +// void testPoolLayer2(const string& poolType, bool trans, bool useGpu) { +// TestConfig config; +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 3200, 0}); +// LayerInputConfig* input = config.layerConfig.add_inputs(); +// PoolConfig* pool = input->mutable_pool_conf(); +// +// pool->set_size_y(4); +// pool->set_stride_y(3); +// pool->set_img_size(10); +// pool->set_img_size_y(20); +// setPoolConfig(&config, pool, poolType); +// pool->set_output_y((pool->img_size_y() - pool->start() - pool->size_y()) / +// ((float)pool->stride_y()) + +// 1.5); +// config.layerConfig.set_size(pool->output_x() * pool->output_y() * +// pool->channels()); +// +// testLayerGrad(config, "pool", 100, trans, useGpu); +// } +// #endif +// +// TEST(Layer, PoolLayer) { +// testPoolLayer("avg-projection", /* trans= */ false, /* useGpu= */ false); +// testPoolLayer("max-projection", /* trans= */ false, /* useGpu= */ false); +// +// #ifndef PADDLE_ONLY_CPU +// testPoolLayer("avg-projection", /* trans= */ false, /* useGpu= */ true); +// testPoolLayer("max-projection", /* trans= */ false, /* useGpu= */ true); +// testPoolLayer("cudnn-max-pool", /* trans= */ false, /* useGpu= */ true); +// testPoolLayer("cudnn-avg-pool", /* trans= */ false, /* useGpu= */ true); +// testPoolLayer2("cudnn-max-pool", /* trans= */ false, /* useGpu= */ true); +// testPoolLayer2("cudnn-avg-pool", /* trans= */ false, /* useGpu= */ true); +// #endif +// } +// +// void testSppLayer(const string& poolType, +// const int pyramidHeight, +// bool trans, +// bool useGpu) { +// TestConfig config; +// config.layerConfig.set_type("spp"); +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 3200, 0}); +// LayerInputConfig* input = config.layerConfig.add_inputs(); +// SppConfig* sppConfig = input->mutable_spp_conf(); +// sppConfig->set_pool_type(poolType); +// sppConfig->set_pyramid_height(pyramidHeight); +// ImageConfig* imageConfig = sppConfig->mutable_image_conf(); +// imageConfig->set_channels(16); +// imageConfig->set_img_size(10); +// imageConfig->set_img_size_y(20); +// int outputSize = (std::pow(4, sppConfig->pyramid_height()) - 1) / (4 - 1); +// config.layerConfig.set_size(outputSize * imageConfig->channels()); +// testLayerGrad(config, "spp", 100, trans, useGpu); +// } +// +// TEST(Layer, SpatialPyramidPoolLayer) { +// for (auto useGpu : {false, true}) { +// for (auto pyramidHeight : {1, 2, 3}) { +// testSppLayer("avg-projection", pyramidHeight, false, useGpu); +// testSppLayer("max-projection", pyramidHeight, false, useGpu); +// } +// } +// } +// +// TEST(Layer, rankCostLayer) { +// TestConfig config; +// config.layerConfig.set_type("rank-cost"); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); +// config.inputDefs.push_back({INPUT_DATA, "layer_1", 1, 0}); +// config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_2", 1, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "rank-cost", 100, false, useGpu); +// } +// } +// +// TEST(Layer, sumCostLayer) { +// TestConfig config; +// config.layerConfig.set_type("sum_cost"); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "sum_cost", 100, false, useGpu); +// } +// } +// +// TEST(Layer, weightedRankCostLayer) { +// TestConfig config; +// config.layerConfig.set_type("rank-cost"); +// config.biasSize = 0; +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); +// config.inputDefs.push_back({INPUT_DATA, "layer_1", 1, 0}); +// config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_2", 1, 0}); +// config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_3", 1, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "weighted-rank-cost", 100, false, useGpu); +// } +// } +// +// TEST(Layer, TensorLayer) { +// TestConfig config; +// config.layerConfig.set_type("tensor"); +// config.layerConfig.set_size(10); +// config.layerConfig.set_active_type("sigmoid"); +// config.biasSize = config.layerConfig.size(); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 5, 250}); +// config.inputDefs.push_back({INPUT_DATA, "layer_1", 5, 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "tensor", 100, false, useGpu); +// } +// } +// +// TEST(Layer, RecurrentLayer) { +// TestConfig config; +// config.layerConfig.set_type("recurrent"); +// config.layerConfig.set_size(4); +// config.layerConfig.set_active_type("tanh"); +// config.biasSize = 4; +// +// config.inputDefs.push_back( +// {INPUT_SEQUENCE_DATA, "layer_0", /* dim= */ 4, /* paraSize= */ 16}); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// for (auto reversed : {false, true}) { +// config.layerConfig.set_reversed(reversed); +// config.testState = !reversed; +// testLayerGrad(config, "recurrent", 50, /* trans= */ false, useGpu); +// } +// } +// } +// +// TEST(Layer, LstmLayer) { +// TestConfig config; +// config.layerConfig.set_type("lstmemory"); +// config.layerConfig.set_size(4); +// config.layerConfig.set_active_type("tanh"); +// config.layerConfig.set_active_state_type("sigmoid"); +// config.layerConfig.set_active_gate_type("sigmoid"); +// config.biasSize = 28; +// +// config.inputDefs.push_back( +// {INPUT_SEQUENCE_DATA, "layer_0", /* dim= */ 16, /* paraSize= */ 64}); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// for (auto reversed : {false, true}) { +// config.layerConfig.set_reversed(reversed); +// config.testState = !reversed; +// testLayerGrad(config, "lstmemory", 100, /* trans= */ false, useGpu); +// } +// } +// for (auto useGpu : {true}) { +// config.testBatchState = true; +// config.layerConfig.set_reversed(false); +// testLayerGrad(config, "lstmemory", 10, /* trans= */ false, useGpu); +// } +// } +// +// TEST(Layer, MDLstmLayer) { +// TestConfig config; +// config.layerConfig.set_type("mdlstmemory"); +// config.layerConfig.set_size(4); +// config.layerConfig.set_active_type("sigmoid"); +// config.layerConfig.set_active_state_type("sigmoid"); +// config.layerConfig.set_active_gate_type("sigmoid"); +// config.biasSize = 4 * 9; +// +// config.inputDefs.push_back( +// {INPUT_SEQUENCE_MDIM_DATA, "layer_0", 4 * 5, 4 * 4 * 5}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_directions(true); +// config.layerConfig.add_directions(true); +// +// for (auto useGpu : {false, true}) { +// for (int i = 0; i < 2; i++) { +// for (int j = 0; j < 2; j++) { +// config.layerConfig.set_directions(0, bool(i)); +// config.layerConfig.set_directions(1, bool(j)); +// testLayerGrad(config, "mdlstmemory", 100, false, useGpu); +// } +// } +// } +// } +// +// TEST(Layer, ParameterReluLayer) { +// auto testParameterReluLayer = [&](size_t inputSize, size_t channels) { +// TestConfig config; +// config.layerConfig.set_type("prelu"); +// config.inputDefs.push_back({INPUT_DATA, "layer_0", inputSize, channels}); +// config.layerConfig.add_inputs(); +// config.layerConfig.set_size(inputSize); +// config.layerConfig.set_partial_sum(inputSize / +// channels); // size of feature map +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "prelu", 100, false, useGpu); +// } +// }; +// +// testParameterReluLayer(192, 1); +// testParameterReluLayer(192, 3); +// testParameterReluLayer(192, 192); +// } +// +// TEST(Layer, ResizeLayer) { +// TestConfig config; +// config.biasSize = 0; +// config.layerConfig.set_type("resize"); +// config.layerConfig.set_size(64); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_0", 16, 0}); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "resize", 100, false, useGpu); +// } +// } +// +// TEST(Layer, NCELayer) { +// TestConfig config; +// size_t numClasses = 4; +// config.layerConfig.set_type("nce"); +// config.layerConfig.set_size(1); +// config.layerConfig.set_active_type("sigmoid"); +// config.layerConfig.set_num_classes(numClasses); +// config.biasSize = numClasses; +// +// config.inputDefs.push_back( +// {INPUT_DATA, "layer_0", /* dim= */ 16, /* paraSize= */ 16 * +// numClasses}); +// config.inputDefs.push_back( +// {INPUT_LABEL, "label", /* dim= */ numClasses, /* paraSize= */ 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto withWeight : {false, true}) { +// if (withWeight) { +// config.inputDefs.push_back( +// {INPUT_DATA_TARGET, "weight", /* dim= */ 1, /* paraSize= */ 0}); +// config.layerConfig.add_inputs(); +// } +// +// for (auto isIdLabel : {false, true}) { +// config.inputDefs[1] = { +// isIdLabel ? INPUT_LABEL : INPUT_SPARSE_NON_VALUE_DATA, +// "label", +// /* dim= */ numClasses, +// /* paraSize= */ 0}; +// +// for (auto withDist : {false, true}) { +// config.layerConfig.clear_neg_sampling_dist(); +// if (withDist) { +// double sum = 0; +// for (size_t i = 0; i < numClasses; ++i) { +// real p = rand(); // NOLINT use rand_r +// config.layerConfig.add_neg_sampling_dist(p); +// sum += p; +// } +// for (size_t i = 0; i < numClasses; ++i) { +// real p = config.layerConfig.neg_sampling_dist(i) / sum; +// config.layerConfig.set_neg_sampling_dist(i, p); +// } +// } +// LOG(INFO) << "NCELayer " +// << " isIdLabel=" << isIdLabel << " withWeight=" << +// withWeight +// << " withDist=" << withDist; +// // Not support GPU now +// testLayerGrad(config, +// "nce", +// 100, +// /* trans= */ false, +// /* useGpu */ false); +// } +// } +// } +// } +// +// TEST(Layer, GatedRecurrentLayer) { +// TestConfig config; +// config.layerConfig.set_type("gated_recurrent"); +// config.layerConfig.set_size(4); +// config.layerConfig.set_active_type("sigmoid"); +// config.layerConfig.set_active_gate_type("sigmoid"); +// config.biasSize = 12; +// +// config.inputDefs.push_back( +// {INPUT_SEQUENCE_DATA, "layer_0", /* dim= */ 12, /* paraSize= */ 48}); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// for (auto reversed : {false, true}) { +// config.layerConfig.set_reversed(reversed); +// config.testState = !reversed; +// testLayerGrad(config, "gated_recurrent", 100, /* trans= */ false, +// useGpu); +// } +// } +// } +// +// TEST(Layer, GruStepLayer) { +// TestConfig config; +// config.layerConfig.set_type("gru_step"); +// config.layerConfig.set_size(4); +// config.layerConfig.set_active_type("sigmoid"); +// config.layerConfig.set_active_gate_type("sigmoid"); +// config.biasSize = 12; +// +// config.inputDefs.push_back( +// {INPUT_DATA, "layer_0", /* dim= */ 12, /* paraSize= */ 48}); +// config.inputDefs.push_back( +// {INPUT_DATA, "layer_1", /* dim= */ 4, /* paraSize= */ 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "gruStep", 100, /* trans= */ false, useGpu); +// } +// } +// +// TEST(Layer, LstmStepLayer) { +// TestConfig config; +// config.layerConfig.set_type("lstm_step"); +// config.layerConfig.set_size(4); +// config.layerConfig.set_active_type("sigmoid"); +// config.layerConfig.set_active_state_type("sigmoid"); +// config.layerConfig.set_active_gate_type("sigmoid"); +// config.biasSize = 12; +// config.testAccumulate = false; +// +// config.inputDefs.push_back( +// {INPUT_DATA, "layer_0", /* dim= */ 16, /* paraSize= */ 0}); +// config.inputDefs.push_back( +// {INPUT_DATA, "layer_1", /* dim= */ 4, /* paraSize= */ 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "lstmStep", 100, /* trans= */ false, useGpu); +// } +// } +// +// void testBatchNormLayer(const string& type, bool trans, bool useGpu) { +// TestConfig config; +// const int CHANNELS = 10; +// const int IMG_SIZE = 16; +// const int IMG_SIZE_Y = 8; +// size_t size = CHANNELS * IMG_SIZE * IMG_SIZE_Y; +// config.layerConfig.set_type(type); +// config.layerConfig.set_size(size); +// config.layerConfig.set_active_type("sigmoid"); +// config.biasSize = CHANNELS; +// config.inputDefs.push_back({INPUT_DATA, +// "layer_0", +// /* dim= */ size, +// /* paraSize= */ CHANNELS}); +// +// config.inputDefs.push_back({INPUT_DATA, "layer_1_running_mean", 1, +// CHANNELS}); +// config.inputDefs.back().isStatic = true; +// config.inputDefs.push_back({INPUT_DATA, "layer_2_running_var", 1, +// CHANNELS}); +// config.inputDefs.back().isStatic = true; +// +// LayerInputConfig* input = config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// ImageConfig* img_conf = input->mutable_image_conf(); +// img_conf->set_channels(CHANNELS); +// img_conf->set_img_size(IMG_SIZE); +// img_conf->set_img_size_y(IMG_SIZE_Y); +// +// testLayerGrad(config, +// "batch_norm", +// 64, +// /* trans= */ trans, +// useGpu, +// /* useWeight */ true); +// } +// +// TEST(Layer, BatchNormalizationLayer) { +// testBatchNormLayer("batch_norm", false, false); +// #ifndef PADDLE_ONLY_CPU +// testBatchNormLayer("batch_norm", false, true); +// if (hl_get_cudnn_lib_version() >= int(4000)) { +// testBatchNormLayer("cudnn_batch_norm", false, true); +// } +// #endif +// } +// +// TEST(Operator, conv) { +// TestConfig config; +// const int NUM_FILTERS = 16; +// const int FILTER_SIZE = 2; +// const int FILTER_SIZE_Y = 3; +// const int CHANNELS = 3; +// const int IMAGE_SIZE = 16; +// const int IMAGE_SIZE_Y = 8; +// OperatorConfig& operatorConf = *config.layerConfig.add_operator_confs(); +// operatorConf.set_type("conv"); +// ConvConfig* conv = operatorConf.mutable_conv_conf(); +// operatorConf.set_num_filters(NUM_FILTERS); +// conv->set_filter_size(FILTER_SIZE); +// conv->set_filter_size_y(FILTER_SIZE_Y); +// conv->set_channels(CHANNELS); +// conv->set_padding(0); +// conv->set_padding_y(1); +// conv->set_stride(2); +// conv->set_stride_y(2); +// conv->set_groups(1); +// conv->set_filter_channels(conv->channels() / conv->groups()); +// conv->set_img_size(IMAGE_SIZE); +// conv->set_img_size_y(IMAGE_SIZE_Y); +// conv->set_output_x(outputSize(conv->img_size(), +// conv->filter_size(), +// conv->padding(), +// conv->stride(), +// /* caffeMode */ true)); +// conv->set_output_y(outputSize(conv->img_size_y(), +// conv->filter_size_y(), +// conv->padding_y(), +// conv->stride_y(), +// /* caffeMode */ true)); +// config.layerConfig.set_size(conv->output_x() * conv->output_y() * +// NUM_FILTERS); +// +// config.inputDefs.push_back( +// {INPUT_DATA, "layer_0", IMAGE_SIZE * IMAGE_SIZE_Y * CHANNELS, 0}); +// config.inputDefs.push_back( +// {INPUT_DATA, +// "layer_1", +// FILTER_SIZE * FILTER_SIZE_Y * CHANNELS * NUM_FILTERS, +// 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// testOperatorGrad(config, operatorConf, 100, /*useGpu*/ true, false); +// } +// +// TEST(Layer, FeatureMapExpandLayer) { +// TestConfig config; +// config.layerConfig.set_type("featmap_expand"); +// const int CHANNELS = 10; +// const int INPUT_SIZE = 100; +// config.layerConfig.set_size(INPUT_SIZE * CHANNELS); +// config.layerConfig.set_num_filters(CHANNELS); +// config.inputDefs.push_back({INPUT_SEQUENCE_DATA, +// "layer_0", +// /* dim= */ INPUT_SIZE, +// /* paraSize= */ 0}); +// config.layerConfig.add_inputs(); +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, +// "featmap_expand", +// /*batch_size*/ 100, +// /* trans= */ false, +// useGpu, +// /* useWeight */ true); +// } +// } +// +// TEST(Layer, MultiplexLayer) { +// TestConfig config; +// const int LAYER_SIZE = 100; +// config.layerConfig.set_type("multiplex"); +// config.layerConfig.set_size(LAYER_SIZE); +// +// config.inputDefs.push_back({INPUT_LABEL, "layer_0", 2, 0}); +// config.inputDefs.push_back( +// {INPUT_DATA, "layer_1", /* dim= */ LAYER_SIZE, /* paraSize= */ 0}); +// config.inputDefs.push_back( +// {INPUT_DATA, "layer_2", /* dim= */ LAYER_SIZE, /* paraSize= */ 0}); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// config.layerConfig.add_inputs(); +// +// for (auto useGpu : {false, true}) { +// testLayerGrad(config, "multiplex", 512, /* trans= */ false, useGpu); +// } +// } +// +TEST(Layer, PadLayer) { TestConfig config; - config.layerConfig.set_size(10); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); - config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - OperatorConfig& operatorConf = *config.layerConfig.add_operator_confs(); - operatorConf.set_type("dot_mul"); - operatorConf.set_dotmul_scale(-1); - - testOperatorGrad(config, operatorConf, 100, false, false); -} - -TEST(Projection, context) { - for (auto contextStart : {-5, -3, -1, 0, 3}) { - for (auto contextLength : {1, 2, 5, 7}) { - for (auto batchSize : {1, 2, 5, 20, 50}) { - for (auto trainablePadding : {false, true}) { - LOG(INFO) << " contextStart=" << contextStart - << " contextLength=" << contextLength - << " batchSize=" << batchSize - << " trainablePadding=" << trainablePadding; - ProjectionConfig conf; - conf.set_type("context"); - conf.set_input_size(10); - conf.set_context_start(contextStart); - conf.set_context_length(contextLength); - conf.set_trainable_padding(trainablePadding); - conf.set_output_size(conf.context_length() * conf.input_size()); - int pad = - std::max(0, -conf.context_start()) + - std::max(0, conf.context_start() + conf.context_length() - 1); - for (auto useGpu : {false, true}) { - testProjectionGrad( - conf, - INPUT_SEQUENCE_DATA, - trainablePadding ? conf.input_size() * pad : 0, - batchSize, - useGpu, - contextStart + contextLength <= 1); // = testState - } - } - } - } - } -} - -TEST(Projection, trans_fc) { - ProjectionConfig conf; - conf.set_type("trans_fc"); - conf.set_input_size(50); - conf.set_output_size(20); - for (auto useGpu : {false, true}) { - testProjectionGrad(conf, - INPUT_DATA, - /* parameterSize */ 1000, - /* batchSize */ 100, - useGpu); - } -} - -TEST(Projection, fc) { - ProjectionConfig conf; - conf.set_type("fc"); - conf.set_input_size(10); - conf.set_output_size(20); - for (auto useGpu : {false, true}) { - testProjectionGrad(conf, - INPUT_DATA, - /* parameterSize */ 200, - /* batchSize */ 100, - useGpu); - } -} - -TEST(Projection, dot_mul) { - ProjectionConfig conf; - conf.set_type("dot_mul"); - conf.set_input_size(20); - conf.set_output_size(20); - for (auto useGpu : {false, true}) { - testProjectionGrad(conf, - INPUT_DATA, - /* parameterSize */ 20, - /* batchSize */ 100, - useGpu); - } -} - -TEST(Projection, table) { - ProjectionConfig conf; - conf.set_type("table"); - conf.set_input_size(10); - conf.set_output_size(20); - for (auto useGpu : {false, true}) { - testProjectionGrad(conf, - INPUT_LABEL, - /* parameterSize */ 200, - /* batchSize */ 100, - useGpu); - } -} - -TEST(Projection, identity) { - ProjectionConfig conf; - conf.set_type("identity"); - conf.set_input_size(10); - conf.set_output_size(10); - for (auto useGpu : {false, true}) { - testProjectionGrad(conf, - INPUT_DATA, - /* parameterSize */ 0, - /* batchSize */ 100, - useGpu); - } -} - -TEST(Projection, scaling) { - ProjectionConfig conf; - conf.set_type("scaling"); - conf.set_input_size(10); - conf.set_output_size(10); - for (auto useGpu : {false}) { - testProjectionGrad(conf, - INPUT_DATA, - /* parameterSize */ 1, - /* batchSize */ 100, - useGpu); - } -} - -void testProjectionConv(size_t groups) { - const int NUM_FILTERS = 18; - const int FILTER_SIZE = 2; - const int FILTER_SIZE_Y = 3; - const int CHANNELS = 3; - const int IMAGE_SIZE = 16; - - ProjectionConfig conf; - conf.set_type("conv"); - conf.set_num_filters(NUM_FILTERS); - - ConvConfig* conv = conf.mutable_conv_conf(); - conv->set_filter_size(FILTER_SIZE); - conv->set_filter_size_y(FILTER_SIZE_Y); - conv->set_channels(CHANNELS); - conv->set_padding(0); - conv->set_padding_y(1); - conv->set_stride(2); - conv->set_stride_y(2); - conv->set_groups(groups); - conv->set_filter_channels(conv->channels() / conv->groups()); - conv->set_img_size(IMAGE_SIZE); - int output_x = outputSize(conv->img_size(), - conv->filter_size(), - conv->padding(), - conv->stride(), - /* caffeMode */ true); - int output_y = outputSize(conv->img_size(), - conv->filter_size_y(), - conv->padding_y(), - conv->stride_y(), - /* caffeMode */ true); - conv->set_output_x(output_x); - conf.set_input_size(IMAGE_SIZE * IMAGE_SIZE * CHANNELS); - conf.set_output_size(output_x * output_y * NUM_FILTERS); - - testProjectionGrad(conf, - INPUT_DATA, - /* parameterSize */ NUM_FILTERS * CHANNELS * FILTER_SIZE * - FILTER_SIZE_Y / groups, - /* batchSize */ 100, - true, - false, - NUM_FILTERS, - true); -} - -#ifndef PADDLE_ONLY_CPU -TEST(Projection, conv) { - testProjectionConv(1); - testProjectionConv(3); -} -#endif - -TEST(Layer, BilinearInterpLayer) { - TestConfig config; - config.layerConfig.set_type("bilinear_interp"); - config.biasSize = 0; - config.inputDefs.push_back({INPUT_DATA, "layer_0", 4096, 0}); - - LayerInputConfig* input = config.layerConfig.add_inputs(); - BilinearInterpConfig* bilinear = input->mutable_bilinear_interp_conf(); - ImageConfig* image = bilinear->mutable_image_conf(); - image->set_img_size(32); - image->set_img_size_y(32); - image->set_channels(4); - - for (auto useGpu : {false, true}) { - for (auto outSize : {32, 64}) { - bilinear->set_out_size_x(outSize); - bilinear->set_out_size_y(outSize); - testLayerGrad(config, "bilinear_interp", 10, false, useGpu); - } - } -} - -TEST(Layer, concat) { - TestConfig config; - config.biasSize = 0; - config.layerConfig.set_type("concat"); - config.layerConfig.set_size(15); - config.layerConfig.set_active_type("sigmoid"); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 5, 0}); - config.layerConfig.add_inputs(); - config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "concat", 100, false, useGpu); - } -} - -TEST(Layer, AddtoLayer) { - TestConfig config; - config.biasSize = 0; - config.layerConfig.set_type("addto"); - config.layerConfig.set_size(10); - config.layerConfig.set_active_type("sigmoid"); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); - config.layerConfig.add_inputs(); - config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "addto", 100, false, useGpu); - } -} - -TEST(Layer, CRFLayer) { - TestConfig config; - config.layerConfig.set_type("crf"); - config.layerConfig.set_size(10); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 10, 120}); - config.inputDefs.push_back({INPUT_SEQUENCE_LABEL, "layer_1", 10, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - // Not support GPU now - testLayerGrad(config, - "crf", - 100, - /* trans */ false, - /* useGpu */ false, - false /*useWeight*/, - 0.03 /*epsilon*/); -} - -TEST(Layer, CTCLayer) { - TestConfig config; - config.layerConfig.set_type("ctc"); - config.layerConfig.set_norm_by_times(false); - config.layerConfig.set_size(10); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 10, 0}); - config.inputDefs.push_back({INPUT_SEQUENCE_LABEL, "layer_1", 10, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "ctc", 100, /* trans */ false, /* useGpu */ useGpu); - } -} - -TEST(Layer, cosSimLayer) { - TestConfig config; - config.layerConfig.set_type("cos"); - config.layerConfig.set_size(1); config.biasSize = 0; + config.layerConfig.set_type("pad"); - config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); - config.inputDefs.push_back({INPUT_DATA, "layer_1", 50, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "cos", 100, false, useGpu); - } -} - -TEST(Layer, CosSimVecMatLayer) { - TestConfig config; - config.layerConfig.set_type("cos_vm"); - config.layerConfig.set_size(5); // output size - config.layerConfig.set_cos_scale(2.0); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 20, 0}); - config.layerConfig.add_inputs(); - config.inputDefs.push_back({INPUT_DATA, "layer_1", 100, 0}); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "cos_vm", 100, false, useGpu); - } -} - -void testConvLayer(const string& type, bool trans, bool useGpu) { - TestConfig config; - config.biasSize = 16; - config.layerConfig.set_type(type); - config.layerConfig.set_num_filters(16); - config.layerConfig.set_partial_sum(1); - config.layerConfig.set_shared_biases(true); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 384, 288}); + int c = 4; + int h = 31; + int w = 36; + size_t size = c * h * w; + config.inputDefs.push_back({INPUT_DATA, "layer_0", size, 0}); LayerInputConfig* input = config.layerConfig.add_inputs(); - ConvConfig* conv = input->mutable_conv_conf(); - conv->set_filter_size(2); - conv->set_filter_size_y(3); - conv->set_channels(3); - conv->set_padding(0); - conv->set_padding_y(1); - conv->set_stride(2); - conv->set_stride_y(2); - conv->set_groups(1); - conv->set_filter_channels(conv->channels() / conv->groups()); - conv->set_img_size(16); - conv->set_img_size_y(8); - conv->set_output_x(outputSize(conv->img_size(), - conv->filter_size(), - conv->padding(), - conv->stride(), - /* caffeMode */ true)); - conv->set_output_y(outputSize(conv->img_size_y(), - conv->filter_size_y(), - conv->padding_y(), - conv->stride_y(), - /* caffeMode */ true)); - config.layerConfig.set_size(conv->output_x() * conv->output_y() * - config.layerConfig.num_filters()); - - testLayerGrad(config, "conv", 100, trans, useGpu); - // Use small batch_size and useWeight=true to test biasGrad - testLayerGrad(config, "conv", 2, trans, useGpu, true, 0.02); -} - -TEST(Layer, convLayer) { - testConvLayer("exconv", /* trans= */ false, /* useGpu= */ false); -#ifndef PADDLE_ONLY_CPU - testConvLayer("exconv", /* trans= */ false, /* useGpu= */ true); - testConvLayer("cudnn_conv", /* trans= */ false, /* useGpu= */ true); -#endif -} - -void testConvTransLayer(const string& type, bool trans, bool useGpu) { - TestConfig config; - config.biasSize = 3; - config.layerConfig.set_type(type); - config.layerConfig.set_num_filters(3); - config.layerConfig.set_partial_sum(1); - config.layerConfig.set_shared_biases(true); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 1024, 288}); - LayerInputConfig* input = config.layerConfig.add_inputs(); - ConvConfig* conv = input->mutable_conv_conf(); - conv->set_filter_size(2); - conv->set_filter_size_y(3); - conv->set_channels(16); - conv->set_padding(0); - conv->set_padding_y(1); - conv->set_stride(2); - conv->set_stride_y(2); - conv->set_groups(1); - conv->set_filter_channels(3 / conv->groups()); - conv->set_img_size(16); - conv->set_output_x(outputSize(conv->img_size(), - conv->filter_size(), - conv->padding(), - conv->stride(), - /* caffeMode */ true)); - - config.layerConfig.set_size(conv->img_size() * conv->img_size() * - config.layerConfig.num_filters()); - - testLayerGrad(config, "convTrans", 100, trans, useGpu); - // Use small batch_size and useWeight=true to test biasGrad - testLayerGrad(config, "convTrans", 2, trans, useGpu, true, 0.02); -} - -TEST(Layer, convTransLayer) { - for (auto useGpu : {false, true}) { - testConvTransLayer("exconvt", /* trans= */ false, /* useGpu= */ useGpu); - } -} - -TEST(Layer, blockExpandLayer) { - TestConfig config; - config.biasSize = 0; - config.layerConfig.set_type("blockexpand"); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 6144, 0}); - LayerInputConfig* input = config.layerConfig.add_inputs(); - BlockExpandConfig* blockExpand = input->mutable_block_expand_conf(); - blockExpand->set_img_size_x(64); - blockExpand->set_img_size_y(32); - blockExpand->set_channels(3); - blockExpand->set_padding_x(0); - blockExpand->set_padding_y(0); - blockExpand->set_block_x(4); - blockExpand->set_block_y(32); - blockExpand->set_stride_x(2); - blockExpand->set_stride_y(2); - blockExpand->set_output_x(outputSize(blockExpand->img_size_x(), - blockExpand->block_x(), - blockExpand->padding_x(), - blockExpand->stride_x(), - /* caffeMode */ false)); - blockExpand->set_output_y(outputSize(blockExpand->img_size_y(), - blockExpand->block_y(), - blockExpand->padding_y(), - blockExpand->stride_y(), - /* caffeMode */ false)); - config.layerConfig.set_size(blockExpand->block_x() * blockExpand->block_y() * - blockExpand->channels()); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "blockexpand", 100, false, useGpu); - } -} - -TEST(Layer, maxoutLayer) { - TestConfig config; - config.biasSize = 0; - config.layerConfig.set_type("maxout"); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 4096, 0}); - LayerInputConfig* input = config.layerConfig.add_inputs(); - MaxOutConfig* maxout = input->mutable_maxout_conf(); - ImageConfig* image = maxout->mutable_image_conf(); - - image->set_img_size(32); - image->set_img_size_y(32); - image->set_channels(4); - maxout->set_groups(2); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "maxout", 10, false, useGpu); - } -} -void testFcLayer(string format, size_t nnz) { - TestConfig config; - config.biasSize = 4096; - config.layerConfig.set_type("fc"); - config.layerConfig.set_size(4096); - config.layerConfig.set_active_type("sigmoid"); - config.layerConfig.set_drop_rate(0.1); - - config.inputDefs.push_back( - {INPUT_DATA, "layer_0", 8192, nnz, ParaSparse(format)}); - config.layerConfig.add_inputs(); - - LOG(INFO) << config.inputDefs[0].sparse.sparse << " " - << config.inputDefs[0].sparse.format; - - for (auto useGpu : {false, true}) { - testLayerGrad(config, - "fc", - 100, - /* trans */ false, - useGpu, - /* weight */ true); - } -} - -TEST(Layer, fcLayer) { - testFcLayer("", 4096 * 4096 * 2); - testFcLayer("csc", 4096 * 40); - testFcLayer("csr", 4096 * 40); -} - -TEST(Layer, SelectiveFullyConnectedLayer) { - TestConfig config; - size_t nin = 16; - size_t nout = 256; - config.layerConfig.set_type("selective_fc"); - config.layerConfig.set_size(nout); - config.layerConfig.set_active_type("sigmoid"); - config.layerConfig.set_has_selected_colums(true); - config.layerConfig.set_selective_fc_pass_generation(false); - config.biasSize = nout; - - config.inputDefs.push_back({INPUT_DATA, "input0", nin, nin * nout}); - config.layerConfig.add_inputs(); - config.inputDefs.push_back( - {INPUT_SPARSE_NON_VALUE_DATA, "index", nout, 0, ParaSparse("csr", true)}); - config.layerConfig.add_inputs(); - - testLayerGrad(config, - "selective_fc", - 100, - /* trans= */ false, - /* useGup= */ false, - false); -#ifndef PADDLE_ONLY_CPU - testLayerGrad(config, - "selective_fc", - 100, - /* trans= */ false, - /* useGup= */ true, - false); -#endif -} - -TEST(Layer, DataNormLayer) { - TestConfig config; - config.layerConfig.set_type("data_norm"); - config.layerConfig.set_size(20); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 20, 100}); - config.inputDefs.back().isStatic = true; - config.layerConfig.add_inputs(); - - for (auto strategy : {"z-score", "min-max", "decimal-scaling"}) { - config.layerConfig.set_data_norm_strategy(strategy); - // The parameters are static, so not support GPU now - testLayerGrad(config, - "data_norm", - 200, - /* trans */ false, - /* useGpu */ false); - } -} - -TEST(Layer, hsigmoidLayer) { - TestConfig config; - config.layerConfig.set_type("hsigmoid"); - config.layerConfig.set_num_classes(5); - config.layerConfig.set_size(1); - config.biasSize = config.layerConfig.num_classes() - 1; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 200}); - config.inputDefs.push_back({INPUT_LABEL, "layer_1", 5, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - // Not support GPU now - testLayerGrad(config, "hsigmoid", 100, /* trans */ false, /* useGpu */ false); -} - -TEST(Layer, multi_cross) { - TestConfig config; - config.layerConfig.set_type("multi-class-cross-entropy"); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); - config.inputDefs.push_back({INPUT_LABEL, "layer_1", 10, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad( - config, "multi-class-cross-entropy", 100, /* trans */ false, useGpu); - } -} - -TEST(Layer, multi_binary_label_sparse_mat) { - TestConfig config; - config.layerConfig.set_type("multi_binary_label_cross_entropy"); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); - config.inputDefs.push_back({INPUT_SPARSE_NON_VALUE_DATA, "layer_1", 50, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, - "multi_binary_label_cross_entropy", - 100, - /* trans */ false, - useGpu); - } -} - -TEST(layer, multi_binary_label_id) { - TestConfig config; - config.layerConfig.set_type("multi_binary_label_cross_entropy"); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); - config.inputDefs.push_back({INPUT_LABEL, "layer_1", 10, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, - "multi_binary_label_cross_entropy", - 100, - /* trans */ false, - useGpu); - } -} - -TEST(Layer, multi_cross_with_selfnorm) { - TestConfig config; - config.layerConfig.set_type("multi_class_cross_entropy_with_selfnorm"); - config.layerConfig.set_softmax_selfnorm_alpha(0.1); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); - config.inputDefs.push_back({INPUT_LABEL, "layer_1", 10, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - // Not support GPU now - testLayerGrad(config, - "multi_class_cross_entropy_with_selfnorm", - 100, - /* trans */ false, - /* useGpu */ false); -} - -TEST(Layer, multi_cross_soft) { - TestConfig config; - config.layerConfig.set_type("soft_binary_class_cross_entropy"); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); - config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_1", 10, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, - "soft_binary_class_cross_entropy", - 100, - /* trans */ false, - useGpu); - } -} - -TEST(Layer, square_error) { - TestConfig config; - config.layerConfig.set_type("square_error"); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); - config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_1", 10, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "square_error", 100, /* trans */ false, useGpu); - } -} - -TEST(Layer, sparse_square_error) { - TestConfig config; - config.layerConfig.set_type("square_error"); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); - config.inputDefs.push_back({INPUT_SPARSE_NON_VALUE_DATA, "layer_1", 50, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - // "GpuSparseMatrix" as label is not supported - testLayerGrad(config, - "square_error", - 100, - /* trans */ false, - /* useGpu */ false); -} - -TEST(Layer, sparse_float_square_error) { - TestConfig config; - config.layerConfig.set_type("square_error"); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); - config.inputDefs.push_back({INPUT_SPARSE_FLOAT_VALUE_DATA, "layer_1", 50, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - // "GpuSparseMatrix" as label is not supported - testLayerGrad(config, - "square_error", - 100, - /* trans */ false, - /* useGpu */ false); -} - -TEST(Layer, square_error_weighted) { - TestConfig config; - config.layerConfig.set_type("square_error"); - config.biasSize = 0; - config.testAccumulate = false; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); - config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_1", 10, 0}); - config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_2", 1, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "square_error", 100, /* trans */ false, useGpu); - } -} - -TEST(Layer, huber_two_class) { - TestConfig config; - config.layerConfig.set_type("huber"); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); - config.inputDefs.push_back({INPUT_LABEL, "layer_1", 2, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "huber", 100, /* trans */ false, useGpu); - } -} - -void testExpandLayer(string trans_type, bool hasSubseq) { - TestConfig config; - config.layerConfig.set_type("expand"); - - config.inputDefs.push_back( - {trans_type == "non-seq" ? INPUT_DENSE_DIM_DATA : INPUT_SEQUENCE_DATA, - "layer_0", - 10, - 0}); - config.inputDefs.push_back( - {hasSubseq ? INPUT_HASSUB_SEQUENCE_DATA : INPUT_SEQUENCE_DATA, - "layer_1", - 10, - 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - config.layerConfig.set_trans_type(trans_type); - LOG(INFO) << " trans_type=" << trans_type << " hasSubseq=" << hasSubseq; - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "expand", 30, false, useGpu); - } -} - -TEST(Layer, ExpandLayer) { - testExpandLayer("non-seq", false); // non-seq expand to seq - testExpandLayer("non-seq", true); // non-seq expand to hasSubseq - testExpandLayer("seq", true); // seq expand to hasSubseq -} - -void testDegradeLayer(bool hasSubseq, string layer_type, string trans_type) { - TestConfig config; - config.layerConfig.set_type(layer_type); - config.layerConfig.set_size(10); - config.biasSize = 0; - - config.inputDefs.push_back( - {hasSubseq ? INPUT_HASSUB_SEQUENCE_DATA : INPUT_SEQUENCE_DATA, - "layer_0", - 10, - 0}); - config.layerConfig.add_inputs(); - config.layerConfig.set_trans_type(trans_type); - - auto testDegradeLayerGrad = [](TestConfig& config, string layer_type) { - for (auto useGpu : {false, true}) { - testLayerGrad(config, layer_type, 100, false, useGpu); - } - }; - - if (layer_type == "average") { - for (auto strategy : {"average", "sum", "squarerootn"}) { - LOG(INFO) << " hasSubseq=" << hasSubseq << " trans_type=" << trans_type - << " average_strategy=" << strategy; - config.layerConfig.set_average_strategy(strategy); - testDegradeLayerGrad(config, layer_type); - } - } else { - LOG(INFO) << " hasSubseq=" << hasSubseq << " trans_type=" << trans_type; - testDegradeLayerGrad(config, layer_type); - } -} - -TEST(Layer, MaxLayer) { - testDegradeLayer(false, "max", "non-seq"); // seq max to non-seq - testDegradeLayer(true, "max", "non-seq"); // hasSubseq max to non-seq - testDegradeLayer(true, "max", "seq"); // hasSubseq max to seq -} - -TEST(Layer, SequenceLastInstanceLayer) { - testDegradeLayer(false, - "seqlastins", - "non-seq"); // seq seqlastins to non-seq - testDegradeLayer(true, - "seqlastins", - "non-seq"); // hasSubseq seqlastins to non-seq - testDegradeLayer(true, "seqlastins", "seq"); // hasSubseq seqlastins to seq -} - -TEST(Layer, AverageLayer) { - testDegradeLayer(false, "average", "non-seq"); // seq average to non-seq - testDegradeLayer(true, "average", "non-seq"); // hasSubseq average to non-seq - testDegradeLayer(true, "average", "seq"); // hasSubseq average to seq -} - -TEST(Layer, SequenceConcatLayer) { - TestConfig config; - config.layerConfig.set_type("seqconcat"); - config.layerConfig.set_size(10); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 10, 0}); - config.layerConfig.add_inputs(); - config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_1", 10, 0}); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "seqconcat", 100, false, useGpu); - } -} - -TEST(Layer, SequenceReshapeLayer) { - TestConfig config; - config.layerConfig.set_type("seqreshape"); - config.layerConfig.set_size(10); - - config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 100, 0}); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "seqreshape", 100, false, useGpu); - } -} - -TEST(Layer, ConvShiftLayer) { - TestConfig config; - config.layerConfig.set_type("conv_shift"); - config.layerConfig.set_size(10); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); - config.inputDefs.push_back({INPUT_DATA, "layer_1", 3, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - // Not support GPU now - testLayerGrad(config, "conv_shift", 100, false, false); -} - -TEST(Layer, PowerLayer) { - TestConfig config; - config.layerConfig.set_type("power"); - config.layerConfig.set_size(10); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); - config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "power", 100, false, useGpu); - } -} - -TEST(Layer, ConvexCombinationLayer) { - TestConfig config; - config.layerConfig.set_type("convex_comb"); - config.layerConfig.set_size(20); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 5, 0}); - config.inputDefs.push_back({INPUT_DATA, "layer_1", 100, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "convex_comb", 100, false, useGpu); - } -} - -TEST(Layer, InterpolationLayer) { - TestConfig config; - config.layerConfig.set_type("interpolation"); - config.layerConfig.set_size(10); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); - config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); - config.inputDefs.push_back({INPUT_DATA, "layer_2", 10, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "interpolation", 100, false, useGpu); - } -} - -TEST(Layer, OuterProdLayer) { - TestConfig config; - config.layerConfig.set_type("out_prod"); - config.layerConfig.set_size(100); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); - config.layerConfig.add_inputs(); - config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "out_prod", 100, false, useGpu); - } -} - -TEST(Layer, SlopeInterceptLayer) { - TestConfig config; - config.layerConfig.set_type("slope_intercept"); - config.layerConfig.set_size(10); - config.layerConfig.set_slope(1.0); - config.layerConfig.set_intercept(0.1); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "slope_intercept", 100, false, useGpu); - } -} - -TEST(Layer, ScalingLayer) { - TestConfig config; - config.layerConfig.set_type("scaling"); - config.layerConfig.set_size(10); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); - config.layerConfig.add_inputs(); - config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "scaling", 100, false, useGpu); - } -} - -void testNormLayer(const string& normType, bool trans, bool useGpu) { - TestConfig config; - config.layerConfig.set_type("norm"); - config.layerConfig.set_active_type("relu"); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 1568, 0}); - LayerInputConfig* input = config.layerConfig.add_inputs(); - NormConfig* norm = input->mutable_norm_conf(); - norm->set_norm_type(normType); - norm->set_channels(16); - norm->set_size(5); - norm->set_scale(0.001); - norm->set_pow(0.75); - norm->set_blocked(0); - norm->set_img_size(14); - norm->set_img_size_y(7); - norm->set_output_x(norm->img_size()); - norm->set_output_y(norm->img_size_y()); - if (norm->norm_type() == "cmrnorm" || - norm->norm_type() == "cmrnorm-projection") { - norm->set_scale(norm->scale() / norm->size()); - } else { - norm->set_scale(norm->scale() / (norm->size() * norm->size())); - } - - config.layerConfig.set_size(norm->output_x() * norm->output_y() * - norm->channels()); - config.biasSize = 0; - - testLayerGrad(config, "norm", 100, trans, useGpu); -} - -TEST(Layer, NormLayer) { - testNormLayer("cmrnorm-projection", /* trans= */ false, /* useGpu= */ true); - testNormLayer("cmrnorm-projection", /* trans= */ false, /* useGpu= */ false); -} - -void setPoolConfig(TestConfig* config, - PoolConfig* pool, - const string& poolType) { - (*config).biasSize = 0; - (*config).layerConfig.set_type("pool"); - (*config).layerConfig.set_num_filters(16); - - int kw = 3, kh = 3; - int pw = 0, ph = 0; - int sw = 2, sh = 2; - pool->set_pool_type(poolType); - pool->set_channels(16); - pool->set_size_x(kw); - pool->set_size_y(kh); - pool->set_start(0); - pool->set_padding(pw); - pool->set_padding_y(ph); - pool->set_stride(sw); - pool->set_stride_y(sh); - - int ow = outputSize(pool->img_size(), kw, pw, sw, /* caffeMode */ false); - int oh = outputSize(pool->img_size_y(), kh, ph, sh, /* caffeMode */ false); - pool->set_output_x(ow); - pool->set_output_y(oh); -} - -void testPoolLayer(const string& poolType, bool trans, bool useGpu) { - TestConfig config; - config.inputDefs.push_back({INPUT_DATA, "layer_0", 3136, 0}); - LayerInputConfig* input = config.layerConfig.add_inputs(); - PoolConfig* pool = input->mutable_pool_conf(); - - pool->set_img_size(14); - pool->set_img_size_y(14); - setPoolConfig(&config, pool, poolType); - config.layerConfig.set_size(pool->output_x() * pool->output_y() * - pool->channels()); - - testLayerGrad(config, "pool", 100, trans, useGpu); -} - -#ifndef PADDLE_ONLY_CPU -void testPoolLayer2(const string& poolType, bool trans, bool useGpu) { - TestConfig config; - config.inputDefs.push_back({INPUT_DATA, "layer_0", 3200, 0}); - LayerInputConfig* input = config.layerConfig.add_inputs(); - PoolConfig* pool = input->mutable_pool_conf(); - - pool->set_size_y(4); - pool->set_stride_y(3); - pool->set_img_size(10); - pool->set_img_size_y(20); - setPoolConfig(&config, pool, poolType); - pool->set_output_y((pool->img_size_y() - pool->start() - pool->size_y()) / - ((float)pool->stride_y()) + - 1.5); - config.layerConfig.set_size(pool->output_x() * pool->output_y() * - pool->channels()); - - testLayerGrad(config, "pool", 100, trans, useGpu); -} -#endif - -TEST(Layer, PoolLayer) { - testPoolLayer("avg-projection", /* trans= */ false, /* useGpu= */ false); - testPoolLayer("max-projection", /* trans= */ false, /* useGpu= */ false); - -#ifndef PADDLE_ONLY_CPU - testPoolLayer("avg-projection", /* trans= */ false, /* useGpu= */ true); - testPoolLayer("max-projection", /* trans= */ false, /* useGpu= */ true); - testPoolLayer("cudnn-max-pool", /* trans= */ false, /* useGpu= */ true); - testPoolLayer("cudnn-avg-pool", /* trans= */ false, /* useGpu= */ true); - testPoolLayer2("cudnn-max-pool", /* trans= */ false, /* useGpu= */ true); - testPoolLayer2("cudnn-avg-pool", /* trans= */ false, /* useGpu= */ true); -#endif -} - -void testSppLayer(const string& poolType, - const int pyramidHeight, - bool trans, - bool useGpu) { - TestConfig config; - config.layerConfig.set_type("spp"); - config.inputDefs.push_back({INPUT_DATA, "layer_0", 3200, 0}); - LayerInputConfig* input = config.layerConfig.add_inputs(); - SppConfig* sppConfig = input->mutable_spp_conf(); - sppConfig->set_pool_type(poolType); - sppConfig->set_pyramid_height(pyramidHeight); - ImageConfig* imageConfig = sppConfig->mutable_image_conf(); - imageConfig->set_channels(16); - imageConfig->set_img_size(10); - imageConfig->set_img_size_y(20); - int outputSize = (std::pow(4, sppConfig->pyramid_height()) - 1) / (4 - 1); - config.layerConfig.set_size(outputSize * imageConfig->channels()); - testLayerGrad(config, "spp", 100, trans, useGpu); -} - -TEST(Layer, SpatialPyramidPoolLayer) { - for (auto useGpu : {false, true}) { - for (auto pyramidHeight : {1, 2, 3}) { - testSppLayer("avg-projection", pyramidHeight, false, useGpu); - testSppLayer("max-projection", pyramidHeight, false, useGpu); - } - } -} - -TEST(Layer, rankCostLayer) { - TestConfig config; - config.layerConfig.set_type("rank-cost"); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); - config.inputDefs.push_back({INPUT_DATA, "layer_1", 1, 0}); - config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_2", 1, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "rank-cost", 100, false, useGpu); - } -} - -TEST(Layer, sumCostLayer) { - TestConfig config; - config.layerConfig.set_type("sum_cost"); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "sum_cost", 100, false, useGpu); - } -} - -TEST(Layer, weightedRankCostLayer) { - TestConfig config; - config.layerConfig.set_type("rank-cost"); - config.biasSize = 0; - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); - config.inputDefs.push_back({INPUT_DATA, "layer_1", 1, 0}); - config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_2", 1, 0}); - config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_3", 1, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "weighted-rank-cost", 100, false, useGpu); - } -} - -TEST(Layer, TensorLayer) { - TestConfig config; - config.layerConfig.set_type("tensor"); - config.layerConfig.set_size(10); - config.layerConfig.set_active_type("sigmoid"); - config.biasSize = config.layerConfig.size(); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 5, 250}); - config.inputDefs.push_back({INPUT_DATA, "layer_1", 5, 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "tensor", 100, false, useGpu); - } -} - -TEST(Layer, RecurrentLayer) { - TestConfig config; - config.layerConfig.set_type("recurrent"); - config.layerConfig.set_size(4); - config.layerConfig.set_active_type("tanh"); - config.biasSize = 4; - - config.inputDefs.push_back( - {INPUT_SEQUENCE_DATA, "layer_0", /* dim= */ 4, /* paraSize= */ 16}); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - for (auto reversed : {false, true}) { - config.layerConfig.set_reversed(reversed); - config.testState = !reversed; - testLayerGrad(config, "recurrent", 50, /* trans= */ false, useGpu); - } - } -} - -TEST(Layer, LstmLayer) { - TestConfig config; - config.layerConfig.set_type("lstmemory"); - config.layerConfig.set_size(4); - config.layerConfig.set_active_type("tanh"); - config.layerConfig.set_active_state_type("sigmoid"); - config.layerConfig.set_active_gate_type("sigmoid"); - config.biasSize = 28; - - config.inputDefs.push_back( - {INPUT_SEQUENCE_DATA, "layer_0", /* dim= */ 16, /* paraSize= */ 64}); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - for (auto reversed : {false, true}) { - config.layerConfig.set_reversed(reversed); - config.testState = !reversed; - testLayerGrad(config, "lstmemory", 100, /* trans= */ false, useGpu); - } - } - for (auto useGpu : {true}) { - config.testBatchState = true; - config.layerConfig.set_reversed(false); - testLayerGrad(config, "lstmemory", 10, /* trans= */ false, useGpu); - } -} - -TEST(Layer, MDLstmLayer) { - TestConfig config; - config.layerConfig.set_type("mdlstmemory"); - config.layerConfig.set_size(4); - config.layerConfig.set_active_type("sigmoid"); - config.layerConfig.set_active_state_type("sigmoid"); - config.layerConfig.set_active_gate_type("sigmoid"); - config.biasSize = 4 * 9; - - config.inputDefs.push_back( - {INPUT_SEQUENCE_MDIM_DATA, "layer_0", 4 * 5, 4 * 4 * 5}); - config.layerConfig.add_inputs(); - config.layerConfig.add_directions(true); - config.layerConfig.add_directions(true); - - for (auto useGpu : {false, true}) { - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 2; j++) { - config.layerConfig.set_directions(0, bool(i)); - config.layerConfig.set_directions(1, bool(j)); - testLayerGrad(config, "mdlstmemory", 100, false, useGpu); - } - } - } -} - -TEST(Layer, ParameterReluLayer) { - auto testParameterReluLayer = [&](size_t inputSize, size_t channels) { - TestConfig config; - config.layerConfig.set_type("prelu"); - config.inputDefs.push_back({INPUT_DATA, "layer_0", inputSize, channels}); - config.layerConfig.add_inputs(); - config.layerConfig.set_size(inputSize); - config.layerConfig.set_partial_sum(inputSize / - channels); // size of feature map - for (auto useGpu : {false, true}) { - testLayerGrad(config, "prelu", 100, false, useGpu); - } - }; - - testParameterReluLayer(192, 1); - testParameterReluLayer(192, 3); - testParameterReluLayer(192, 192); -} - -TEST(Layer, ResizeLayer) { - TestConfig config; - config.biasSize = 0; - config.layerConfig.set_type("resize"); - config.layerConfig.set_size(64); - - config.inputDefs.push_back({INPUT_DATA, "layer_0", 16, 0}); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "resize", 100, false, useGpu); - } -} - -TEST(Layer, NCELayer) { - TestConfig config; - size_t numClasses = 4; - config.layerConfig.set_type("nce"); - config.layerConfig.set_size(1); - config.layerConfig.set_active_type("sigmoid"); - config.layerConfig.set_num_classes(numClasses); - config.biasSize = numClasses; - - config.inputDefs.push_back( - {INPUT_DATA, "layer_0", /* dim= */ 16, /* paraSize= */ 16 * numClasses}); - config.inputDefs.push_back( - {INPUT_LABEL, "label", /* dim= */ numClasses, /* paraSize= */ 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto withWeight : {false, true}) { - if (withWeight) { - config.inputDefs.push_back( - {INPUT_DATA_TARGET, "weight", /* dim= */ 1, /* paraSize= */ 0}); - config.layerConfig.add_inputs(); - } - - for (auto isIdLabel : {false, true}) { - config.inputDefs[1] = { - isIdLabel ? INPUT_LABEL : INPUT_SPARSE_NON_VALUE_DATA, - "label", - /* dim= */ numClasses, - /* paraSize= */ 0}; - - for (auto withDist : {false, true}) { - config.layerConfig.clear_neg_sampling_dist(); - if (withDist) { - double sum = 0; - for (size_t i = 0; i < numClasses; ++i) { - real p = rand(); // NOLINT use rand_r - config.layerConfig.add_neg_sampling_dist(p); - sum += p; - } - for (size_t i = 0; i < numClasses; ++i) { - real p = config.layerConfig.neg_sampling_dist(i) / sum; - config.layerConfig.set_neg_sampling_dist(i, p); - } - } - LOG(INFO) << "NCELayer " - << " isIdLabel=" << isIdLabel << " withWeight=" << withWeight - << " withDist=" << withDist; - // Not support GPU now - testLayerGrad(config, - "nce", - 100, - /* trans= */ false, - /* useGpu */ false); - } - } - } -} - -TEST(Layer, GatedRecurrentLayer) { - TestConfig config; - config.layerConfig.set_type("gated_recurrent"); - config.layerConfig.set_size(4); - config.layerConfig.set_active_type("sigmoid"); - config.layerConfig.set_active_gate_type("sigmoid"); - config.biasSize = 12; - - config.inputDefs.push_back( - {INPUT_SEQUENCE_DATA, "layer_0", /* dim= */ 12, /* paraSize= */ 48}); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - for (auto reversed : {false, true}) { - config.layerConfig.set_reversed(reversed); - config.testState = !reversed; - testLayerGrad(config, "gated_recurrent", 100, /* trans= */ false, useGpu); - } - } -} - -TEST(Layer, GruStepLayer) { - TestConfig config; - config.layerConfig.set_type("gru_step"); - config.layerConfig.set_size(4); - config.layerConfig.set_active_type("sigmoid"); - config.layerConfig.set_active_gate_type("sigmoid"); - config.biasSize = 12; - - config.inputDefs.push_back( - {INPUT_DATA, "layer_0", /* dim= */ 12, /* paraSize= */ 48}); - config.inputDefs.push_back( - {INPUT_DATA, "layer_1", /* dim= */ 4, /* paraSize= */ 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "gruStep", 100, /* trans= */ false, useGpu); - } -} - -TEST(Layer, LstmStepLayer) { - TestConfig config; - config.layerConfig.set_type("lstm_step"); - config.layerConfig.set_size(4); - config.layerConfig.set_active_type("sigmoid"); - config.layerConfig.set_active_state_type("sigmoid"); - config.layerConfig.set_active_gate_type("sigmoid"); - config.biasSize = 12; - config.testAccumulate = false; - - config.inputDefs.push_back( - {INPUT_DATA, "layer_0", /* dim= */ 16, /* paraSize= */ 0}); - config.inputDefs.push_back( - {INPUT_DATA, "layer_1", /* dim= */ 4, /* paraSize= */ 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - for (auto useGpu : {false, true}) { - testLayerGrad(config, "lstmStep", 100, /* trans= */ false, useGpu); - } -} - -void testBatchNormLayer(const string& type, bool trans, bool useGpu) { - TestConfig config; - const int CHANNELS = 10; - const int IMG_SIZE = 16; - const int IMG_SIZE_Y = 8; - size_t size = CHANNELS * IMG_SIZE * IMG_SIZE_Y; - config.layerConfig.set_type(type); - config.layerConfig.set_size(size); - config.layerConfig.set_active_type("sigmoid"); - config.biasSize = CHANNELS; - config.inputDefs.push_back({INPUT_DATA, - "layer_0", - /* dim= */ size, - /* paraSize= */ CHANNELS}); - - config.inputDefs.push_back({INPUT_DATA, "layer_1_running_mean", 1, CHANNELS}); - config.inputDefs.back().isStatic = true; - config.inputDefs.push_back({INPUT_DATA, "layer_2_running_var", 1, CHANNELS}); - config.inputDefs.back().isStatic = true; - - LayerInputConfig* input = config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - ImageConfig* img_conf = input->mutable_image_conf(); - img_conf->set_channels(CHANNELS); - img_conf->set_img_size(IMG_SIZE); - img_conf->set_img_size_y(IMG_SIZE_Y); - - testLayerGrad(config, - "batch_norm", - 64, - /* trans= */ trans, - useGpu, - /* useWeight */ true); -} - -TEST(Layer, BatchNormalizationLayer) { - testBatchNormLayer("batch_norm", false, false); -#ifndef PADDLE_ONLY_CPU - testBatchNormLayer("batch_norm", false, true); - if (hl_get_cudnn_lib_version() >= int(4000)) { - testBatchNormLayer("cudnn_batch_norm", false, true); - } -#endif -} - -TEST(Operator, conv) { - TestConfig config; - const int NUM_FILTERS = 16; - const int FILTER_SIZE = 2; - const int FILTER_SIZE_Y = 3; - const int CHANNELS = 3; - const int IMAGE_SIZE = 16; - const int IMAGE_SIZE_Y = 8; - OperatorConfig& operatorConf = *config.layerConfig.add_operator_confs(); - operatorConf.set_type("conv"); - ConvConfig* conv = operatorConf.mutable_conv_conf(); - operatorConf.set_num_filters(NUM_FILTERS); - conv->set_filter_size(FILTER_SIZE); - conv->set_filter_size_y(FILTER_SIZE_Y); - conv->set_channels(CHANNELS); - conv->set_padding(0); - conv->set_padding_y(1); - conv->set_stride(2); - conv->set_stride_y(2); - conv->set_groups(1); - conv->set_filter_channels(conv->channels() / conv->groups()); - conv->set_img_size(IMAGE_SIZE); - conv->set_img_size_y(IMAGE_SIZE_Y); - conv->set_output_x(outputSize(conv->img_size(), - conv->filter_size(), - conv->padding(), - conv->stride(), - /* caffeMode */ true)); - conv->set_output_y(outputSize(conv->img_size_y(), - conv->filter_size_y(), - conv->padding_y(), - conv->stride_y(), - /* caffeMode */ true)); - config.layerConfig.set_size(conv->output_x() * conv->output_y() * - NUM_FILTERS); - - config.inputDefs.push_back( - {INPUT_DATA, "layer_0", IMAGE_SIZE * IMAGE_SIZE_Y * CHANNELS, 0}); - config.inputDefs.push_back( - {INPUT_DATA, - "layer_1", - FILTER_SIZE * FILTER_SIZE_Y * CHANNELS * NUM_FILTERS, - 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - - testOperatorGrad(config, operatorConf, 100, /*useGpu*/ true, false); -} - -TEST(Layer, FeatureMapExpandLayer) { - TestConfig config; - config.layerConfig.set_type("featmap_expand"); - const int CHANNELS = 10; - const int INPUT_SIZE = 100; - config.layerConfig.set_size(INPUT_SIZE * CHANNELS); - config.layerConfig.set_num_filters(CHANNELS); - config.inputDefs.push_back({INPUT_SEQUENCE_DATA, - "layer_0", - /* dim= */ INPUT_SIZE, - /* paraSize= */ 0}); - config.layerConfig.add_inputs(); - for (auto useGpu : {false, true}) { - testLayerGrad(config, - "featmap_expand", - /*batch_size*/ 100, - /* trans= */ false, - useGpu, - /* useWeight */ true); - } -} - -TEST(Layer, MultiplexLayer) { - TestConfig config; - const int LAYER_SIZE = 100; - config.layerConfig.set_type("multiplex"); - config.layerConfig.set_size(LAYER_SIZE); - - config.inputDefs.push_back({INPUT_LABEL, "layer_0", 2, 0}); - config.inputDefs.push_back( - {INPUT_DATA, "layer_1", /* dim= */ LAYER_SIZE, /* paraSize= */ 0}); - config.inputDefs.push_back( - {INPUT_DATA, "layer_2", /* dim= */ LAYER_SIZE, /* paraSize= */ 0}); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); - config.layerConfig.add_inputs(); + PadConfig* pad = input->mutable_pad_conf(); + ImageConfig* image = pad->mutable_image_conf(); + + image->set_channels(c); + image->set_img_size(h); + image->set_img_size_y(w); + pad->add_pad_c(1); + pad->add_pad_c(2); + pad->add_pad_h(2); + pad->add_pad_h(3); + pad->add_pad_w(3); + pad->add_pad_w(5); for (auto useGpu : {false, true}) { - testLayerGrad(config, "multiplex", 512, /* trans= */ false, useGpu); + testLayerGrad(config, "pad", 10, false, useGpu); } } diff --git a/proto/ModelConfig.proto b/proto/ModelConfig.proto index 3a9d339976fff9..0456404832c301 100644 --- a/proto/ModelConfig.proto +++ b/proto/ModelConfig.proto @@ -255,6 +255,13 @@ message PriorBoxConfig { repeated float variance = 4; } +message PadConfig { + required ImageConfig image_conf = 1; + repeated uint32 pad_c = 2; + repeated uint32 pad_h = 3; + repeated uint32 pad_w = 4; +} + message LayerInputConfig { required string input_layer_name = 1; optional string input_parameter_name = 2; @@ -271,6 +278,7 @@ message LayerInputConfig { optional MaxOutConfig maxout_conf = 11; optional SppConfig spp_conf = 12; optional PriorBoxConfig priorbox_conf = 13; + optional PadConfig pad_conf = 14; } message LayerConfig { diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index 674b5ac58b6feb..6e5922166da1b1 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -493,6 +493,7 @@ def __init__( block_expand=None, maxout=None, spp=None, + pad=None, format=None, nnz=None, is_static=None, @@ -844,6 +845,12 @@ def __init__(self, pool_type, pyramid_height, channels): self.add_keys(locals()) +@config_class +class Pad(Cfg): + def __init__(self, channels, pad_c, pad_h, pad_w): + self.add_keys(locals()) + + @config_class class Norm(Cfg): def __init__(self, @@ -1842,6 +1849,25 @@ def __init__(self, name, inputs, device=None): self.set_cnn_layer(name, 1, output_x, spp_conf.image_conf.channels) +@config_layer('pad') +class PadLayer(LayerBase): + def __init__(self, name, inputs, **xargs): + super(PadLayer, self).__init__(name, 'pad', 0, inputs=inputs, **xargs) + pad = self.inputs[0].pad + self.config.inputs[0].pad_conf.pad_c.extend(pad.pad_c) + self.config.inputs[0].pad_conf.pad_h.extend(pad.pad_h) + self.config.inputs[0].pad_conf.pad_w.extend(pad.pad_w) + + input_layer = self.get_input_layer(0) + image_conf = self.config.inputs[0].pad_conf.image_conf + parse_image(pad, input_layer.name, image_conf) + out_ch = pad.channels + pad.pad_c[0] + pad.pad_c[1] + out_h = image_conf.img_size_y + pad.pad_h[0] + pad.pad_h[1] + out_w = image_conf.img_size + pad.pad_w[0] + pad.pad_w[1] + self.set_cnn_layer(name, out_h, out_w, out_ch) + self.config.size = out_ch * out_h * out_w + + @config_layer('batch_norm') class BatchNormLayer(LayerBase): layer_type = 'batch_norm' diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 9b6e5774bc82dc..56c335a0504d04 100644 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -170,6 +170,7 @@ class LayerType(object): BLOCK_EXPAND = "blockexpand" MAXOUT = "maxout" SPP_LAYER = "spp" + PAD_LAYER = "pad" PRINT_LAYER = "print" PRIORBOX_LAYER = "priorbox" @@ -3488,9 +3489,6 @@ def conv_projection(input, groups=1, param_attr=None): """ - ConvProjection with a layer as input. - It performs element-wise multiplication with weight. - Different from img_conv_layer and conv_op, conv_projection is an Projection, which can be used in mixed_layer and conat_layer. It use cudnn to implement conv and only support GPU mode. @@ -3499,7 +3497,7 @@ def conv_projection(input, .. code-block:: python - proj = conv_projection(img=input1, + proj = conv_projection(input=input1, filter_size=3, num_filters=64, num_channels=64) @@ -3582,6 +3580,84 @@ def conv_projection(input, return proj +@wrap_name_default("pad") +@layer_support() +def pad_layer(input, + pad_c=None, + pad_h=None, + pad_w=None, + name=None, + layer_attr=None): + """ + This operation pads zeros to the input data according to pad_c,pad_h + and pad_w. pad_c, pad_h, pad_w specifies the which dimension and size + of padding. And the input data shape is NCHW. + + For example, pad_c=[2,3] means padding 2 zeros before the + input data and 3 zeros after the input data in channel dimension. + pad_h means padding zeros in height dimension. pad_w means padding zeros + in width dimension. + + .. code-block:: python + + pad = pad_layer(input=ipt, + pad_c=[4,4], + pad_h=[0,0], + pad_w=[2,2]) + + :param input: layer's input. + :type input: LayerOutput + :param pad_c: padding size in channel dimension. + :type pad_c: list|None + :param pad_h: padding size in height dimension. + :type pad_h: list|None + :param pad_w: padding size in width dimension. + :type pad_w: list|None + :param layer_attr: Extra Layer Attribute. + :type layer_attr: ExtraLayerAttribute + :param name: layer name. + :type name: basestring + :return: LayerOutput object. + :rtype: LayerOutput + """ + if pad_c is not None: + assert isinstance(pad_c, collections.Sequence) and len(pad_c) == 2 + else: + pad_c = [0, 0] + + if pad_h is not None: + assert isinstance(pad_h, collections.Sequence) and len(pad_h) == 2 + else: + pad_h = [0, 0] + + if pad_w is not None: + assert isinstance(pad_w, collections.Sequence) and len(pad_w) == 2 + else: + pad_w = [0, 0] + + assert input.num_filters is not None + in_ch = input.num_filters + out_ch = in_ch + pad_c[0] + pad_c[1] + + l = Layer( + name=name, + type=LayerType.PAD_LAYER, + inputs=Input( + input.name, + pad=Pad( + channels=in_ch, + pad_c=pad_c, + pad_h=pad_h, + pad_w=pad_w, )), + **ExtraLayerAttribute.to_kwargs(layer_attr)) + return LayerOutput( + name, + layer_type=LayerType.PAD_LAYER, + parents=[input], + num_filters=out_ch, + size=l.config.size) + + @wrap_name_default() @layer_support() def conv_shift_layer(a, b, name=None, layer_attr=None): diff --git a/python/paddle/trainer_config_helpers/tests/configs/test_pad.py b/python/paddle/trainer_config_helpers/tests/configs/test_pad.py new file mode 100644 index 00000000000000..bb5f13410dbbba --- /dev/null +++ b/python/paddle/trainer_config_helpers/tests/configs/test_pad.py @@ -0,0 +1,21 @@ +from paddle.trainer_config_helpers import * + +settings(batch_size=1000, learning_rate=1e-5) + +data = data_layer(name='data', size=2304, height=48, width=42) + +conv = img_conv_layer( + input=data, + filter_size=3, + num_channels=1, + num_filters=16, + padding=1, + act=LinearActivation(), + bias_attr=True) + +pool = img_pool_layer( + input=conv, num_channels=8, pool_size=2, stride=2, pool_type=MaxPooling()) + +pad = pad_layer(input=pool, pad_c=[2, 3], pad_h=[1, 2], pad_w=[3, 1]) + +outputs(pad) From 6b61a096e13d04e1927c0760e96f2474df0085c7 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Sat, 7 Jan 2017 16:01:44 +0800 Subject: [PATCH 006/370] Optional padding mode, namely ceil or floor, ceil by default. --- paddle/function/PadOp.cpp | 16 +- paddle/function/PadOpTest.cpp | 48 +- paddle/gserver/tests/test_LayerGrad.cpp | 3093 ++++++++--------- python/paddle/trainer/config_parser.py | 36 +- .../paddle/trainer_config_helpers/layers.py | 21 +- 5 files changed, 1614 insertions(+), 1600 deletions(-) diff --git a/paddle/function/PadOp.cpp b/paddle/function/PadOp.cpp index e10011da2a1750..2dfe03dcf61ce3 100644 --- a/paddle/function/PadOp.cpp +++ b/paddle/function/PadOp.cpp @@ -73,10 +73,6 @@ void PadGrad(real* inGrad, } } -/** - * \param inputs[0] input value. - * \param outputs[0] output value. - */ template class PadFunc : public FunctionBase { public: @@ -89,6 +85,10 @@ class PadFunc : public FunctionBase { padw1_ = config.get("padw1"); } + /** + * \param inputs[0] input value. + * \param outputs[0] output value. + */ void calc(const Arguments& inputs, const Arguments& outputs, const Arguments& inouts) override { @@ -124,10 +124,6 @@ class PadFunc : public FunctionBase { int padw1_; }; -/** - * \param inputs[0] input grad. - * \param outputs[0] output grad. - */ template class PadGradFunc : public FunctionBase { public: @@ -140,6 +136,10 @@ class PadGradFunc : public FunctionBase { padw1_ = config.get("padw1"); } + /** + * \param inputs[0] output grad. + * \param inouts[0] input grad. + */ void calc(const Arguments& inputs, const Arguments& outputs, const Arguments& inouts) override { diff --git a/paddle/function/PadOpTest.cpp b/paddle/function/PadOpTest.cpp index ee2834d793d348..c6d573c1d94537 100644 --- a/paddle/function/PadOpTest.cpp +++ b/paddle/function/PadOpTest.cpp @@ -43,28 +43,30 @@ TEST(Pad, real) { } } -// TEST(PadGrad, real) { -// for (size_t numSamples : {5, 32}) { -// for (size_t channels : {1, 5, 32}) { -// for (size_t imgSizeH : {5, 33, 100}) { -// for (size_t imgSizeW : {5, 32, 96}) { -// VLOG(3) << " numSamples=" << numSamples << " channels=" << channels -// << " imgSizeH=" << imgSizeH << " imgSizeW=" << imgSizeW; -// -// FunctionCompare compare("PadGrad", -// FuncConfig() -// .set("padc0", 2).set("padc1", 3) -// .set("padh0", 1).set("padh1", 2) -// .set("padw0", 3).set("padw1", 2)); -// Dims inDims{numSamples, channels, imgSizeH, imgSizeW}; -// Dims outDims{numSamples, channels + 5, imgSizeH + 3, imgSizeW + 5}; -// compare.cmpWithArg({Tensor(nullptr, inDims)}, -// {Tensor(nullptr, outDims)}, -// {}); -// } -// } -// } -// } -//} +TEST(PadGrad, real) { + for (size_t numSamples : {5, 32}) { + for (size_t channels : {1, 5, 32}) { + for (size_t imgSizeH : {5, 33, 100}) { + for (size_t imgSizeW : {5, 32, 96}) { + VLOG(3) << " numSamples=" << numSamples << " channels=" << channels + << " imgSizeH=" << imgSizeH << " imgSizeW=" << imgSizeW; + + FunctionCompare compare("PadGrad", + FuncConfig() + .set("padc0", 2) + .set("padc1", 3) + .set("padh0", 1) + .set("padh1", 2) + .set("padw0", 3) + .set("padw1", 2)); + Dims inDims{numSamples, channels, imgSizeH, imgSizeW}; + Dims outDims{numSamples, channels + 5, imgSizeH + 3, imgSizeW + 5}; + compare.cmpWithArg( + {Tensor(nullptr, inDims)}, {}, {Tensor(nullptr, outDims)}); + } + } + } + } +} } // namespace paddle diff --git a/paddle/gserver/tests/test_LayerGrad.cpp b/paddle/gserver/tests/test_LayerGrad.cpp index 2be52c17addc41..0560bb3ed91d36 100644 --- a/paddle/gserver/tests/test_LayerGrad.cpp +++ b/paddle/gserver/tests/test_LayerGrad.cpp @@ -32,1554 +32,1551 @@ DECLARE_double(checkgrad_eps); DECLARE_bool(thread_local_rand_use_global_seed); DECLARE_bool(prev_batch_state); -// TEST(Operator, dot_mul) { -// TestConfig config; -// config.layerConfig.set_size(10); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); -// config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// OperatorConfig& operatorConf = *config.layerConfig.add_operator_confs(); -// operatorConf.set_type("dot_mul"); -// operatorConf.set_dotmul_scale(-1); -// -// testOperatorGrad(config, operatorConf, 100, false, false); -// } -// -// TEST(Projection, context) { -// for (auto contextStart : {-5, -3, -1, 0, 3}) { -// for (auto contextLength : {1, 2, 5, 7}) { -// for (auto batchSize : {1, 2, 5, 20, 50}) { -// for (auto trainablePadding : {false, true}) { -// LOG(INFO) << " contextStart=" << contextStart -// << " contextLength=" << contextLength -// << " batchSize=" << batchSize -// << " trainablePadding=" << trainablePadding; -// ProjectionConfig conf; -// conf.set_type("context"); -// conf.set_input_size(10); -// conf.set_context_start(contextStart); -// conf.set_context_length(contextLength); -// conf.set_trainable_padding(trainablePadding); -// conf.set_output_size(conf.context_length() * conf.input_size()); -// int pad = -// std::max(0, -conf.context_start()) + -// std::max(0, conf.context_start() + conf.context_length() - 1); -// for (auto useGpu : {false, true}) { -// testProjectionGrad( -// conf, -// INPUT_SEQUENCE_DATA, -// trainablePadding ? conf.input_size() * pad : 0, -// batchSize, -// useGpu, -// contextStart + contextLength <= 1); // = testState -// } -// } -// } -// } -// } -// } -// -// TEST(Projection, trans_fc) { -// ProjectionConfig conf; -// conf.set_type("trans_fc"); -// conf.set_input_size(50); -// conf.set_output_size(20); -// for (auto useGpu : {false, true}) { -// testProjectionGrad(conf, -// INPUT_DATA, -// /* parameterSize */ 1000, -// /* batchSize */ 100, -// useGpu); -// } -// } -// -// TEST(Projection, fc) { -// ProjectionConfig conf; -// conf.set_type("fc"); -// conf.set_input_size(10); -// conf.set_output_size(20); -// for (auto useGpu : {false, true}) { -// testProjectionGrad(conf, -// INPUT_DATA, -// /* parameterSize */ 200, -// /* batchSize */ 100, -// useGpu); -// } -// } -// -// TEST(Projection, dot_mul) { -// ProjectionConfig conf; -// conf.set_type("dot_mul"); -// conf.set_input_size(20); -// conf.set_output_size(20); -// for (auto useGpu : {false, true}) { -// testProjectionGrad(conf, -// INPUT_DATA, -// /* parameterSize */ 20, -// /* batchSize */ 100, -// useGpu); -// } -// } -// -// TEST(Projection, table) { -// ProjectionConfig conf; -// conf.set_type("table"); -// conf.set_input_size(10); -// conf.set_output_size(20); -// for (auto useGpu : {false, true}) { -// testProjectionGrad(conf, -// INPUT_LABEL, -// /* parameterSize */ 200, -// /* batchSize */ 100, -// useGpu); -// } -// } -// -// TEST(Projection, identity) { -// ProjectionConfig conf; -// conf.set_type("identity"); -// conf.set_input_size(10); -// conf.set_output_size(10); -// for (auto useGpu : {false, true}) { -// testProjectionGrad(conf, -// INPUT_DATA, -// /* parameterSize */ 0, -// /* batchSize */ 100, -// useGpu); -// } -// } -// -// TEST(Projection, scaling) { -// ProjectionConfig conf; -// conf.set_type("scaling"); -// conf.set_input_size(10); -// conf.set_output_size(10); -// for (auto useGpu : {false}) { -// testProjectionGrad(conf, -// INPUT_DATA, -// /* parameterSize */ 1, -// /* batchSize */ 100, -// useGpu); -// } -// } -// -// void testProjectionConv(size_t groups) { -// const int NUM_FILTERS = 18; -// const int FILTER_SIZE = 2; -// const int FILTER_SIZE_Y = 3; -// const int CHANNELS = 3; -// const int IMAGE_SIZE = 16; -// -// ProjectionConfig conf; -// conf.set_type("conv"); -// conf.set_num_filters(NUM_FILTERS); -// -// ConvConfig* conv = conf.mutable_conv_conf(); -// conv->set_filter_size(FILTER_SIZE); -// conv->set_filter_size_y(FILTER_SIZE_Y); -// conv->set_channels(CHANNELS); -// conv->set_padding(0); -// conv->set_padding_y(1); -// conv->set_stride(2); -// conv->set_stride_y(2); -// conv->set_groups(groups); -// conv->set_filter_channels(conv->channels() / conv->groups()); -// conv->set_img_size(IMAGE_SIZE); -// int output_x = outputSize(conv->img_size(), -// conv->filter_size(), -// conv->padding(), -// conv->stride(), -// /* caffeMode */ true); -// int output_y = outputSize(conv->img_size(), -// conv->filter_size_y(), -// conv->padding_y(), -// conv->stride_y(), -// /* caffeMode */ true); -// conv->set_output_x(output_x); -// conf.set_input_size(IMAGE_SIZE * IMAGE_SIZE * CHANNELS); -// conf.set_output_size(output_x * output_y * NUM_FILTERS); -// -// testProjectionGrad(conf, -// INPUT_DATA, -// /* parameterSize */ NUM_FILTERS * CHANNELS * FILTER_SIZE -// * -// FILTER_SIZE_Y / groups, -// /* batchSize */ 100, -// true, -// false, -// NUM_FILTERS, -// true); -// } -// -// #ifndef PADDLE_ONLY_CPU -// TEST(Projection, conv) { -// testProjectionConv(1); -// testProjectionConv(3); -// } -// #endif -// -// TEST(Layer, BilinearInterpLayer) { -// TestConfig config; -// config.layerConfig.set_type("bilinear_interp"); -// config.biasSize = 0; -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 4096, 0}); -// -// LayerInputConfig* input = config.layerConfig.add_inputs(); -// BilinearInterpConfig* bilinear = input->mutable_bilinear_interp_conf(); -// ImageConfig* image = bilinear->mutable_image_conf(); -// image->set_img_size(32); -// image->set_img_size_y(32); -// image->set_channels(4); -// -// for (auto useGpu : {false, true}) { -// for (auto outSize : {32, 64}) { -// bilinear->set_out_size_x(outSize); -// bilinear->set_out_size_y(outSize); -// testLayerGrad(config, "bilinear_interp", 10, false, useGpu); -// } -// } -// } -// -// TEST(Layer, concat) { -// TestConfig config; -// config.biasSize = 0; -// config.layerConfig.set_type("concat"); -// config.layerConfig.set_size(15); -// config.layerConfig.set_active_type("sigmoid"); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 5, 0}); -// config.layerConfig.add_inputs(); -// config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "concat", 100, false, useGpu); -// } -// } -// -// TEST(Layer, AddtoLayer) { -// TestConfig config; -// config.biasSize = 0; -// config.layerConfig.set_type("addto"); -// config.layerConfig.set_size(10); -// config.layerConfig.set_active_type("sigmoid"); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); -// config.layerConfig.add_inputs(); -// config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "addto", 100, false, useGpu); -// } -// } -// -// TEST(Layer, CRFLayer) { -// TestConfig config; -// config.layerConfig.set_type("crf"); -// config.layerConfig.set_size(10); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 10, 120}); -// config.inputDefs.push_back({INPUT_SEQUENCE_LABEL, "layer_1", 10, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// // Not support GPU now -// testLayerGrad(config, -// "crf", -// 100, -// /* trans */ false, -// /* useGpu */ false, -// false /*useWeight*/, -// 0.03 /*epsilon*/); -// } -// -// TEST(Layer, CTCLayer) { -// TestConfig config; -// config.layerConfig.set_type("ctc"); -// config.layerConfig.set_norm_by_times(false); -// config.layerConfig.set_size(10); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 10, 0}); -// config.inputDefs.push_back({INPUT_SEQUENCE_LABEL, "layer_1", 10, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "ctc", 100, /* trans */ false, /* useGpu */ -// useGpu); -// } -// } -// -// TEST(Layer, cosSimLayer) { -// TestConfig config; -// config.layerConfig.set_type("cos"); -// config.layerConfig.set_size(1); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); -// config.inputDefs.push_back({INPUT_DATA, "layer_1", 50, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "cos", 100, false, useGpu); -// } -// } -// -// TEST(Layer, CosSimVecMatLayer) { -// TestConfig config; -// config.layerConfig.set_type("cos_vm"); -// config.layerConfig.set_size(5); // output size -// config.layerConfig.set_cos_scale(2.0); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 20, 0}); -// config.layerConfig.add_inputs(); -// config.inputDefs.push_back({INPUT_DATA, "layer_1", 100, 0}); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "cos_vm", 100, false, useGpu); -// } -// } -// -// void testConvLayer(const string& type, bool trans, bool useGpu) { -// TestConfig config; -// config.biasSize = 16; -// config.layerConfig.set_type(type); -// config.layerConfig.set_num_filters(16); -// config.layerConfig.set_partial_sum(1); -// config.layerConfig.set_shared_biases(true); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 384, 288}); -// LayerInputConfig* input = config.layerConfig.add_inputs(); -// ConvConfig* conv = input->mutable_conv_conf(); -// conv->set_filter_size(2); -// conv->set_filter_size_y(3); -// conv->set_channels(3); -// conv->set_padding(0); -// conv->set_padding_y(1); -// conv->set_stride(2); -// conv->set_stride_y(2); -// conv->set_groups(1); -// conv->set_filter_channels(conv->channels() / conv->groups()); -// conv->set_img_size(16); -// conv->set_img_size_y(8); -// conv->set_output_x(outputSize(conv->img_size(), -// conv->filter_size(), -// conv->padding(), -// conv->stride(), -// /* caffeMode */ true)); -// conv->set_output_y(outputSize(conv->img_size_y(), -// conv->filter_size_y(), -// conv->padding_y(), -// conv->stride_y(), -// /* caffeMode */ true)); -// config.layerConfig.set_size(conv->output_x() * conv->output_y() * -// config.layerConfig.num_filters()); -// -// testLayerGrad(config, "conv", 100, trans, useGpu); -// // Use small batch_size and useWeight=true to test biasGrad -// testLayerGrad(config, "conv", 2, trans, useGpu, true, 0.02); -// } -// -// TEST(Layer, convLayer) { -// testConvLayer("exconv", /* trans= */ false, /* useGpu= */ false); -// #ifndef PADDLE_ONLY_CPU -// testConvLayer("exconv", /* trans= */ false, /* useGpu= */ true); -// testConvLayer("cudnn_conv", /* trans= */ false, /* useGpu= */ true); -// #endif -// } -// -// void testConvTransLayer(const string& type, bool trans, bool useGpu) { -// TestConfig config; -// config.biasSize = 3; -// config.layerConfig.set_type(type); -// config.layerConfig.set_num_filters(3); -// config.layerConfig.set_partial_sum(1); -// config.layerConfig.set_shared_biases(true); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1024, 288}); -// LayerInputConfig* input = config.layerConfig.add_inputs(); -// ConvConfig* conv = input->mutable_conv_conf(); -// conv->set_filter_size(2); -// conv->set_filter_size_y(3); -// conv->set_channels(16); -// conv->set_padding(0); -// conv->set_padding_y(1); -// conv->set_stride(2); -// conv->set_stride_y(2); -// conv->set_groups(1); -// conv->set_filter_channels(3 / conv->groups()); -// conv->set_img_size(16); -// conv->set_output_x(outputSize(conv->img_size(), -// conv->filter_size(), -// conv->padding(), -// conv->stride(), -// /* caffeMode */ true)); -// -// config.layerConfig.set_size(conv->img_size() * conv->img_size() * -// config.layerConfig.num_filters()); -// -// testLayerGrad(config, "convTrans", 100, trans, useGpu); -// // Use small batch_size and useWeight=true to test biasGrad -// testLayerGrad(config, "convTrans", 2, trans, useGpu, true, 0.02); -// } -// -// TEST(Layer, convTransLayer) { -// for (auto useGpu : {false, true}) { -// testConvTransLayer("exconvt", /* trans= */ false, /* useGpu= */ useGpu); -// } -// } -// -// TEST(Layer, blockExpandLayer) { -// TestConfig config; -// config.biasSize = 0; -// config.layerConfig.set_type("blockexpand"); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 6144, 0}); -// LayerInputConfig* input = config.layerConfig.add_inputs(); -// BlockExpandConfig* blockExpand = input->mutable_block_expand_conf(); -// blockExpand->set_img_size_x(64); -// blockExpand->set_img_size_y(32); -// blockExpand->set_channels(3); -// blockExpand->set_padding_x(0); -// blockExpand->set_padding_y(0); -// blockExpand->set_block_x(4); -// blockExpand->set_block_y(32); -// blockExpand->set_stride_x(2); -// blockExpand->set_stride_y(2); -// blockExpand->set_output_x(outputSize(blockExpand->img_size_x(), -// blockExpand->block_x(), -// blockExpand->padding_x(), -// blockExpand->stride_x(), -// /* caffeMode */ false)); -// blockExpand->set_output_y(outputSize(blockExpand->img_size_y(), -// blockExpand->block_y(), -// blockExpand->padding_y(), -// blockExpand->stride_y(), -// /* caffeMode */ false)); -// config.layerConfig.set_size(blockExpand->block_x() * blockExpand->block_y() -// * -// blockExpand->channels()); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "blockexpand", 100, false, useGpu); -// } -// } -// -// TEST(Layer, maxoutLayer) { -// TestConfig config; -// config.biasSize = 0; -// config.layerConfig.set_type("maxout"); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 4096, 0}); -// LayerInputConfig* input = config.layerConfig.add_inputs(); -// MaxOutConfig* maxout = input->mutable_maxout_conf(); -// ImageConfig* image = maxout->mutable_image_conf(); -// -// image->set_img_size(32); -// image->set_img_size_y(32); -// image->set_channels(4); -// maxout->set_groups(2); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "maxout", 10, false, useGpu); -// } -// } -// void testFcLayer(string format, size_t nnz) { -// TestConfig config; -// config.biasSize = 4096; -// config.layerConfig.set_type("fc"); -// config.layerConfig.set_size(4096); -// config.layerConfig.set_active_type("sigmoid"); -// config.layerConfig.set_drop_rate(0.1); -// -// config.inputDefs.push_back( -// {INPUT_DATA, "layer_0", 8192, nnz, ParaSparse(format)}); -// config.layerConfig.add_inputs(); -// -// LOG(INFO) << config.inputDefs[0].sparse.sparse << " " -// << config.inputDefs[0].sparse.format; -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, -// "fc", -// 100, -// /* trans */ false, -// useGpu, -// /* weight */ true); -// } -// } -// -// TEST(Layer, fcLayer) { -// testFcLayer("", 4096 * 4096 * 2); -// testFcLayer("csc", 4096 * 40); -// testFcLayer("csr", 4096 * 40); -// } -// -// TEST(Layer, SelectiveFullyConnectedLayer) { -// TestConfig config; -// size_t nin = 16; -// size_t nout = 256; -// config.layerConfig.set_type("selective_fc"); -// config.layerConfig.set_size(nout); -// config.layerConfig.set_active_type("sigmoid"); -// config.layerConfig.set_has_selected_colums(true); -// config.layerConfig.set_selective_fc_pass_generation(false); -// config.biasSize = nout; -// -// config.inputDefs.push_back({INPUT_DATA, "input0", nin, nin * nout}); -// config.layerConfig.add_inputs(); -// config.inputDefs.push_back( -// {INPUT_SPARSE_NON_VALUE_DATA, "index", nout, 0, ParaSparse("csr", -// true)}); -// config.layerConfig.add_inputs(); -// -// testLayerGrad(config, -// "selective_fc", -// 100, -// /* trans= */ false, -// /* useGup= */ false, -// false); -// #ifndef PADDLE_ONLY_CPU -// testLayerGrad(config, -// "selective_fc", -// 100, -// /* trans= */ false, -// /* useGup= */ true, -// false); -// #endif -// } -// -// TEST(Layer, DataNormLayer) { -// TestConfig config; -// config.layerConfig.set_type("data_norm"); -// config.layerConfig.set_size(20); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 20, 100}); -// config.inputDefs.back().isStatic = true; -// config.layerConfig.add_inputs(); -// -// for (auto strategy : {"z-score", "min-max", "decimal-scaling"}) { -// config.layerConfig.set_data_norm_strategy(strategy); -// // The parameters are static, so not support GPU now -// testLayerGrad(config, -// "data_norm", -// 200, -// /* trans */ false, -// /* useGpu */ false); -// } -// } -// -// TEST(Layer, hsigmoidLayer) { -// TestConfig config; -// config.layerConfig.set_type("hsigmoid"); -// config.layerConfig.set_num_classes(5); -// config.layerConfig.set_size(1); -// config.biasSize = config.layerConfig.num_classes() - 1; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 200}); -// config.inputDefs.push_back({INPUT_LABEL, "layer_1", 5, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// // Not support GPU now -// testLayerGrad(config, "hsigmoid", 100, /* trans */ false, /* useGpu */ -// false); -// } -// -// TEST(Layer, multi_cross) { -// TestConfig config; -// config.layerConfig.set_type("multi-class-cross-entropy"); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); -// config.inputDefs.push_back({INPUT_LABEL, "layer_1", 10, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad( -// config, "multi-class-cross-entropy", 100, /* trans */ false, useGpu); -// } -// } -// -// TEST(Layer, multi_binary_label_sparse_mat) { -// TestConfig config; -// config.layerConfig.set_type("multi_binary_label_cross_entropy"); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); -// config.inputDefs.push_back({INPUT_SPARSE_NON_VALUE_DATA, "layer_1", 50, -// 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, -// "multi_binary_label_cross_entropy", -// 100, -// /* trans */ false, -// useGpu); -// } -// } -// -// TEST(layer, multi_binary_label_id) { -// TestConfig config; -// config.layerConfig.set_type("multi_binary_label_cross_entropy"); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); -// config.inputDefs.push_back({INPUT_LABEL, "layer_1", 10, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, -// "multi_binary_label_cross_entropy", -// 100, -// /* trans */ false, -// useGpu); -// } -// } -// -// TEST(Layer, multi_cross_with_selfnorm) { -// TestConfig config; -// config.layerConfig.set_type("multi_class_cross_entropy_with_selfnorm"); -// config.layerConfig.set_softmax_selfnorm_alpha(0.1); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); -// config.inputDefs.push_back({INPUT_LABEL, "layer_1", 10, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// // Not support GPU now -// testLayerGrad(config, -// "multi_class_cross_entropy_with_selfnorm", -// 100, -// /* trans */ false, -// /* useGpu */ false); -// } -// -// TEST(Layer, multi_cross_soft) { -// TestConfig config; -// config.layerConfig.set_type("soft_binary_class_cross_entropy"); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); -// config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_1", 10, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, -// "soft_binary_class_cross_entropy", -// 100, -// /* trans */ false, -// useGpu); -// } -// } -// -// TEST(Layer, square_error) { -// TestConfig config; -// config.layerConfig.set_type("square_error"); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); -// config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_1", 10, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "square_error", 100, /* trans */ false, useGpu); -// } -// } -// -// TEST(Layer, sparse_square_error) { -// TestConfig config; -// config.layerConfig.set_type("square_error"); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); -// config.inputDefs.push_back({INPUT_SPARSE_NON_VALUE_DATA, "layer_1", 50, -// 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// // "GpuSparseMatrix" as label is not supported -// testLayerGrad(config, -// "square_error", -// 100, -// /* trans */ false, -// /* useGpu */ false); -// } -// -// TEST(Layer, sparse_float_square_error) { -// TestConfig config; -// config.layerConfig.set_type("square_error"); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); -// config.inputDefs.push_back({INPUT_SPARSE_FLOAT_VALUE_DATA, "layer_1", 50, -// 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// // "GpuSparseMatrix" as label is not supported -// testLayerGrad(config, -// "square_error", -// 100, -// /* trans */ false, -// /* useGpu */ false); -// } -// -// TEST(Layer, square_error_weighted) { -// TestConfig config; -// config.layerConfig.set_type("square_error"); -// config.biasSize = 0; -// config.testAccumulate = false; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); -// config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_1", 10, 0}); -// config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_2", 1, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "square_error", 100, /* trans */ false, useGpu); -// } -// } -// -// TEST(Layer, huber_two_class) { -// TestConfig config; -// config.layerConfig.set_type("huber"); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); -// config.inputDefs.push_back({INPUT_LABEL, "layer_1", 2, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "huber", 100, /* trans */ false, useGpu); -// } -// } -// -// void testExpandLayer(string trans_type, bool hasSubseq) { -// TestConfig config; -// config.layerConfig.set_type("expand"); -// -// config.inputDefs.push_back( -// {trans_type == "non-seq" ? INPUT_DENSE_DIM_DATA : INPUT_SEQUENCE_DATA, -// "layer_0", -// 10, -// 0}); -// config.inputDefs.push_back( -// {hasSubseq ? INPUT_HASSUB_SEQUENCE_DATA : INPUT_SEQUENCE_DATA, -// "layer_1", -// 10, -// 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// config.layerConfig.set_trans_type(trans_type); -// LOG(INFO) << " trans_type=" << trans_type << " hasSubseq=" << hasSubseq; -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "expand", 30, false, useGpu); -// } -// } -// -// TEST(Layer, ExpandLayer) { -// testExpandLayer("non-seq", false); // non-seq expand to seq -// testExpandLayer("non-seq", true); // non-seq expand to hasSubseq -// testExpandLayer("seq", true); // seq expand to hasSubseq -// } -// -// void testDegradeLayer(bool hasSubseq, string layer_type, string trans_type) { -// TestConfig config; -// config.layerConfig.set_type(layer_type); -// config.layerConfig.set_size(10); -// config.biasSize = 0; -// -// config.inputDefs.push_back( -// {hasSubseq ? INPUT_HASSUB_SEQUENCE_DATA : INPUT_SEQUENCE_DATA, -// "layer_0", -// 10, -// 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.set_trans_type(trans_type); -// -// auto testDegradeLayerGrad = [](TestConfig& config, string layer_type) { -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, layer_type, 100, false, useGpu); -// } -// }; -// -// if (layer_type == "average") { -// for (auto strategy : {"average", "sum", "squarerootn"}) { -// LOG(INFO) << " hasSubseq=" << hasSubseq << " trans_type=" << trans_type -// << " average_strategy=" << strategy; -// config.layerConfig.set_average_strategy(strategy); -// testDegradeLayerGrad(config, layer_type); -// } -// } else { -// LOG(INFO) << " hasSubseq=" << hasSubseq << " trans_type=" << trans_type; -// testDegradeLayerGrad(config, layer_type); -// } -// } -// -// TEST(Layer, MaxLayer) { -// testDegradeLayer(false, "max", "non-seq"); // seq max to non-seq -// testDegradeLayer(true, "max", "non-seq"); // hasSubseq max to non-seq -// testDegradeLayer(true, "max", "seq"); // hasSubseq max to seq -// } -// -// TEST(Layer, SequenceLastInstanceLayer) { -// testDegradeLayer(false, -// "seqlastins", -// "non-seq"); // seq seqlastins to non-seq -// testDegradeLayer(true, -// "seqlastins", -// "non-seq"); // hasSubseq seqlastins to non-seq -// testDegradeLayer(true, "seqlastins", "seq"); // hasSubseq seqlastins to -// seq -// } -// -// TEST(Layer, AverageLayer) { -// testDegradeLayer(false, "average", "non-seq"); // seq average to non-seq -// testDegradeLayer(true, "average", "non-seq"); // hasSubseq average to -// non-seq -// testDegradeLayer(true, "average", "seq"); // hasSubseq average to seq -// } -// -// TEST(Layer, SequenceConcatLayer) { -// TestConfig config; -// config.layerConfig.set_type("seqconcat"); -// config.layerConfig.set_size(10); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 10, 0}); -// config.layerConfig.add_inputs(); -// config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_1", 10, 0}); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "seqconcat", 100, false, useGpu); -// } -// } -// -// TEST(Layer, SequenceReshapeLayer) { -// TestConfig config; -// config.layerConfig.set_type("seqreshape"); -// config.layerConfig.set_size(10); -// -// config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 100, 0}); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "seqreshape", 100, false, useGpu); -// } -// } -// -// TEST(Layer, ConvShiftLayer) { -// TestConfig config; -// config.layerConfig.set_type("conv_shift"); -// config.layerConfig.set_size(10); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); -// config.inputDefs.push_back({INPUT_DATA, "layer_1", 3, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// // Not support GPU now -// testLayerGrad(config, "conv_shift", 100, false, false); -// } -// -// TEST(Layer, PowerLayer) { -// TestConfig config; -// config.layerConfig.set_type("power"); -// config.layerConfig.set_size(10); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); -// config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "power", 100, false, useGpu); -// } -// } -// -// TEST(Layer, ConvexCombinationLayer) { -// TestConfig config; -// config.layerConfig.set_type("convex_comb"); -// config.layerConfig.set_size(20); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 5, 0}); -// config.inputDefs.push_back({INPUT_DATA, "layer_1", 100, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "convex_comb", 100, false, useGpu); -// } -// } -// -// TEST(Layer, InterpolationLayer) { -// TestConfig config; -// config.layerConfig.set_type("interpolation"); -// config.layerConfig.set_size(10); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); -// config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); -// config.inputDefs.push_back({INPUT_DATA, "layer_2", 10, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "interpolation", 100, false, useGpu); -// } -// } -// -// TEST(Layer, OuterProdLayer) { -// TestConfig config; -// config.layerConfig.set_type("out_prod"); -// config.layerConfig.set_size(100); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); -// config.layerConfig.add_inputs(); -// config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "out_prod", 100, false, useGpu); -// } -// } -// -// TEST(Layer, SlopeInterceptLayer) { -// TestConfig config; -// config.layerConfig.set_type("slope_intercept"); -// config.layerConfig.set_size(10); -// config.layerConfig.set_slope(1.0); -// config.layerConfig.set_intercept(0.1); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "slope_intercept", 100, false, useGpu); -// } -// } -// -// TEST(Layer, ScalingLayer) { -// TestConfig config; -// config.layerConfig.set_type("scaling"); -// config.layerConfig.set_size(10); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); -// config.layerConfig.add_inputs(); -// config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "scaling", 100, false, useGpu); -// } -// } -// -// void testNormLayer(const string& normType, bool trans, bool useGpu) { -// TestConfig config; -// config.layerConfig.set_type("norm"); -// config.layerConfig.set_active_type("relu"); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1568, 0}); -// LayerInputConfig* input = config.layerConfig.add_inputs(); -// NormConfig* norm = input->mutable_norm_conf(); -// norm->set_norm_type(normType); -// norm->set_channels(16); -// norm->set_size(5); -// norm->set_scale(0.001); -// norm->set_pow(0.75); -// norm->set_blocked(0); -// norm->set_img_size(14); -// norm->set_img_size_y(7); -// norm->set_output_x(norm->img_size()); -// norm->set_output_y(norm->img_size_y()); -// if (norm->norm_type() == "cmrnorm" || -// norm->norm_type() == "cmrnorm-projection") { -// norm->set_scale(norm->scale() / norm->size()); -// } else { -// norm->set_scale(norm->scale() / (norm->size() * norm->size())); -// } -// -// config.layerConfig.set_size(norm->output_x() * norm->output_y() * -// norm->channels()); -// config.biasSize = 0; -// -// testLayerGrad(config, "norm", 100, trans, useGpu); -// } -// -// TEST(Layer, NormLayer) { -// testNormLayer("cmrnorm-projection", /* trans= */ false, /* useGpu= */ -// true); -// testNormLayer("cmrnorm-projection", /* trans= */ false, /* useGpu= */ -// false); -// } -// -// void setPoolConfig(TestConfig* config, -// PoolConfig* pool, -// const string& poolType) { -// (*config).biasSize = 0; -// (*config).layerConfig.set_type("pool"); -// (*config).layerConfig.set_num_filters(16); -// -// int kw = 3, kh = 3; -// int pw = 0, ph = 0; -// int sw = 2, sh = 2; -// pool->set_pool_type(poolType); -// pool->set_channels(16); -// pool->set_size_x(kw); -// pool->set_size_y(kh); -// pool->set_start(0); -// pool->set_padding(pw); -// pool->set_padding_y(ph); -// pool->set_stride(sw); -// pool->set_stride_y(sh); -// -// int ow = outputSize(pool->img_size(), kw, pw, sw, /* caffeMode */ false); -// int oh = outputSize(pool->img_size_y(), kh, ph, sh, /* caffeMode */ false); -// pool->set_output_x(ow); -// pool->set_output_y(oh); -// } -// -// void testPoolLayer(const string& poolType, bool trans, bool useGpu) { -// TestConfig config; -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 3136, 0}); -// LayerInputConfig* input = config.layerConfig.add_inputs(); -// PoolConfig* pool = input->mutable_pool_conf(); -// -// pool->set_img_size(14); -// pool->set_img_size_y(14); -// setPoolConfig(&config, pool, poolType); -// config.layerConfig.set_size(pool->output_x() * pool->output_y() * -// pool->channels()); -// -// testLayerGrad(config, "pool", 100, trans, useGpu); -// } -// -// #ifndef PADDLE_ONLY_CPU -// void testPoolLayer2(const string& poolType, bool trans, bool useGpu) { -// TestConfig config; -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 3200, 0}); -// LayerInputConfig* input = config.layerConfig.add_inputs(); -// PoolConfig* pool = input->mutable_pool_conf(); -// -// pool->set_size_y(4); -// pool->set_stride_y(3); -// pool->set_img_size(10); -// pool->set_img_size_y(20); -// setPoolConfig(&config, pool, poolType); -// pool->set_output_y((pool->img_size_y() - pool->start() - pool->size_y()) / -// ((float)pool->stride_y()) + -// 1.5); -// config.layerConfig.set_size(pool->output_x() * pool->output_y() * -// pool->channels()); -// -// testLayerGrad(config, "pool", 100, trans, useGpu); -// } -// #endif -// -// TEST(Layer, PoolLayer) { -// testPoolLayer("avg-projection", /* trans= */ false, /* useGpu= */ false); -// testPoolLayer("max-projection", /* trans= */ false, /* useGpu= */ false); -// -// #ifndef PADDLE_ONLY_CPU -// testPoolLayer("avg-projection", /* trans= */ false, /* useGpu= */ true); -// testPoolLayer("max-projection", /* trans= */ false, /* useGpu= */ true); -// testPoolLayer("cudnn-max-pool", /* trans= */ false, /* useGpu= */ true); -// testPoolLayer("cudnn-avg-pool", /* trans= */ false, /* useGpu= */ true); -// testPoolLayer2("cudnn-max-pool", /* trans= */ false, /* useGpu= */ true); -// testPoolLayer2("cudnn-avg-pool", /* trans= */ false, /* useGpu= */ true); -// #endif -// } -// -// void testSppLayer(const string& poolType, -// const int pyramidHeight, -// bool trans, -// bool useGpu) { -// TestConfig config; -// config.layerConfig.set_type("spp"); -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 3200, 0}); -// LayerInputConfig* input = config.layerConfig.add_inputs(); -// SppConfig* sppConfig = input->mutable_spp_conf(); -// sppConfig->set_pool_type(poolType); -// sppConfig->set_pyramid_height(pyramidHeight); -// ImageConfig* imageConfig = sppConfig->mutable_image_conf(); -// imageConfig->set_channels(16); -// imageConfig->set_img_size(10); -// imageConfig->set_img_size_y(20); -// int outputSize = (std::pow(4, sppConfig->pyramid_height()) - 1) / (4 - 1); -// config.layerConfig.set_size(outputSize * imageConfig->channels()); -// testLayerGrad(config, "spp", 100, trans, useGpu); -// } -// -// TEST(Layer, SpatialPyramidPoolLayer) { -// for (auto useGpu : {false, true}) { -// for (auto pyramidHeight : {1, 2, 3}) { -// testSppLayer("avg-projection", pyramidHeight, false, useGpu); -// testSppLayer("max-projection", pyramidHeight, false, useGpu); -// } -// } -// } -// -// TEST(Layer, rankCostLayer) { -// TestConfig config; -// config.layerConfig.set_type("rank-cost"); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); -// config.inputDefs.push_back({INPUT_DATA, "layer_1", 1, 0}); -// config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_2", 1, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "rank-cost", 100, false, useGpu); -// } -// } -// -// TEST(Layer, sumCostLayer) { -// TestConfig config; -// config.layerConfig.set_type("sum_cost"); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "sum_cost", 100, false, useGpu); -// } -// } -// -// TEST(Layer, weightedRankCostLayer) { -// TestConfig config; -// config.layerConfig.set_type("rank-cost"); -// config.biasSize = 0; -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); -// config.inputDefs.push_back({INPUT_DATA, "layer_1", 1, 0}); -// config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_2", 1, 0}); -// config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_3", 1, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "weighted-rank-cost", 100, false, useGpu); -// } -// } -// -// TEST(Layer, TensorLayer) { -// TestConfig config; -// config.layerConfig.set_type("tensor"); -// config.layerConfig.set_size(10); -// config.layerConfig.set_active_type("sigmoid"); -// config.biasSize = config.layerConfig.size(); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 5, 250}); -// config.inputDefs.push_back({INPUT_DATA, "layer_1", 5, 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "tensor", 100, false, useGpu); -// } -// } -// -// TEST(Layer, RecurrentLayer) { -// TestConfig config; -// config.layerConfig.set_type("recurrent"); -// config.layerConfig.set_size(4); -// config.layerConfig.set_active_type("tanh"); -// config.biasSize = 4; -// -// config.inputDefs.push_back( -// {INPUT_SEQUENCE_DATA, "layer_0", /* dim= */ 4, /* paraSize= */ 16}); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// for (auto reversed : {false, true}) { -// config.layerConfig.set_reversed(reversed); -// config.testState = !reversed; -// testLayerGrad(config, "recurrent", 50, /* trans= */ false, useGpu); -// } -// } -// } -// -// TEST(Layer, LstmLayer) { -// TestConfig config; -// config.layerConfig.set_type("lstmemory"); -// config.layerConfig.set_size(4); -// config.layerConfig.set_active_type("tanh"); -// config.layerConfig.set_active_state_type("sigmoid"); -// config.layerConfig.set_active_gate_type("sigmoid"); -// config.biasSize = 28; -// -// config.inputDefs.push_back( -// {INPUT_SEQUENCE_DATA, "layer_0", /* dim= */ 16, /* paraSize= */ 64}); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// for (auto reversed : {false, true}) { -// config.layerConfig.set_reversed(reversed); -// config.testState = !reversed; -// testLayerGrad(config, "lstmemory", 100, /* trans= */ false, useGpu); -// } -// } -// for (auto useGpu : {true}) { -// config.testBatchState = true; -// config.layerConfig.set_reversed(false); -// testLayerGrad(config, "lstmemory", 10, /* trans= */ false, useGpu); -// } -// } -// -// TEST(Layer, MDLstmLayer) { -// TestConfig config; -// config.layerConfig.set_type("mdlstmemory"); -// config.layerConfig.set_size(4); -// config.layerConfig.set_active_type("sigmoid"); -// config.layerConfig.set_active_state_type("sigmoid"); -// config.layerConfig.set_active_gate_type("sigmoid"); -// config.biasSize = 4 * 9; -// -// config.inputDefs.push_back( -// {INPUT_SEQUENCE_MDIM_DATA, "layer_0", 4 * 5, 4 * 4 * 5}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_directions(true); -// config.layerConfig.add_directions(true); -// -// for (auto useGpu : {false, true}) { -// for (int i = 0; i < 2; i++) { -// for (int j = 0; j < 2; j++) { -// config.layerConfig.set_directions(0, bool(i)); -// config.layerConfig.set_directions(1, bool(j)); -// testLayerGrad(config, "mdlstmemory", 100, false, useGpu); -// } -// } -// } -// } -// -// TEST(Layer, ParameterReluLayer) { -// auto testParameterReluLayer = [&](size_t inputSize, size_t channels) { -// TestConfig config; -// config.layerConfig.set_type("prelu"); -// config.inputDefs.push_back({INPUT_DATA, "layer_0", inputSize, channels}); -// config.layerConfig.add_inputs(); -// config.layerConfig.set_size(inputSize); -// config.layerConfig.set_partial_sum(inputSize / -// channels); // size of feature map -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "prelu", 100, false, useGpu); -// } -// }; -// -// testParameterReluLayer(192, 1); -// testParameterReluLayer(192, 3); -// testParameterReluLayer(192, 192); -// } -// -// TEST(Layer, ResizeLayer) { -// TestConfig config; -// config.biasSize = 0; -// config.layerConfig.set_type("resize"); -// config.layerConfig.set_size(64); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_0", 16, 0}); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "resize", 100, false, useGpu); -// } -// } -// -// TEST(Layer, NCELayer) { -// TestConfig config; -// size_t numClasses = 4; -// config.layerConfig.set_type("nce"); -// config.layerConfig.set_size(1); -// config.layerConfig.set_active_type("sigmoid"); -// config.layerConfig.set_num_classes(numClasses); -// config.biasSize = numClasses; -// -// config.inputDefs.push_back( -// {INPUT_DATA, "layer_0", /* dim= */ 16, /* paraSize= */ 16 * -// numClasses}); -// config.inputDefs.push_back( -// {INPUT_LABEL, "label", /* dim= */ numClasses, /* paraSize= */ 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto withWeight : {false, true}) { -// if (withWeight) { -// config.inputDefs.push_back( -// {INPUT_DATA_TARGET, "weight", /* dim= */ 1, /* paraSize= */ 0}); -// config.layerConfig.add_inputs(); -// } -// -// for (auto isIdLabel : {false, true}) { -// config.inputDefs[1] = { -// isIdLabel ? INPUT_LABEL : INPUT_SPARSE_NON_VALUE_DATA, -// "label", -// /* dim= */ numClasses, -// /* paraSize= */ 0}; -// -// for (auto withDist : {false, true}) { -// config.layerConfig.clear_neg_sampling_dist(); -// if (withDist) { -// double sum = 0; -// for (size_t i = 0; i < numClasses; ++i) { -// real p = rand(); // NOLINT use rand_r -// config.layerConfig.add_neg_sampling_dist(p); -// sum += p; -// } -// for (size_t i = 0; i < numClasses; ++i) { -// real p = config.layerConfig.neg_sampling_dist(i) / sum; -// config.layerConfig.set_neg_sampling_dist(i, p); -// } -// } -// LOG(INFO) << "NCELayer " -// << " isIdLabel=" << isIdLabel << " withWeight=" << -// withWeight -// << " withDist=" << withDist; -// // Not support GPU now -// testLayerGrad(config, -// "nce", -// 100, -// /* trans= */ false, -// /* useGpu */ false); -// } -// } -// } -// } -// -// TEST(Layer, GatedRecurrentLayer) { -// TestConfig config; -// config.layerConfig.set_type("gated_recurrent"); -// config.layerConfig.set_size(4); -// config.layerConfig.set_active_type("sigmoid"); -// config.layerConfig.set_active_gate_type("sigmoid"); -// config.biasSize = 12; -// -// config.inputDefs.push_back( -// {INPUT_SEQUENCE_DATA, "layer_0", /* dim= */ 12, /* paraSize= */ 48}); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// for (auto reversed : {false, true}) { -// config.layerConfig.set_reversed(reversed); -// config.testState = !reversed; -// testLayerGrad(config, "gated_recurrent", 100, /* trans= */ false, -// useGpu); -// } -// } -// } -// -// TEST(Layer, GruStepLayer) { -// TestConfig config; -// config.layerConfig.set_type("gru_step"); -// config.layerConfig.set_size(4); -// config.layerConfig.set_active_type("sigmoid"); -// config.layerConfig.set_active_gate_type("sigmoid"); -// config.biasSize = 12; -// -// config.inputDefs.push_back( -// {INPUT_DATA, "layer_0", /* dim= */ 12, /* paraSize= */ 48}); -// config.inputDefs.push_back( -// {INPUT_DATA, "layer_1", /* dim= */ 4, /* paraSize= */ 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "gruStep", 100, /* trans= */ false, useGpu); -// } -// } -// -// TEST(Layer, LstmStepLayer) { -// TestConfig config; -// config.layerConfig.set_type("lstm_step"); -// config.layerConfig.set_size(4); -// config.layerConfig.set_active_type("sigmoid"); -// config.layerConfig.set_active_state_type("sigmoid"); -// config.layerConfig.set_active_gate_type("sigmoid"); -// config.biasSize = 12; -// config.testAccumulate = false; -// -// config.inputDefs.push_back( -// {INPUT_DATA, "layer_0", /* dim= */ 16, /* paraSize= */ 0}); -// config.inputDefs.push_back( -// {INPUT_DATA, "layer_1", /* dim= */ 4, /* paraSize= */ 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "lstmStep", 100, /* trans= */ false, useGpu); -// } -// } -// -// void testBatchNormLayer(const string& type, bool trans, bool useGpu) { -// TestConfig config; -// const int CHANNELS = 10; -// const int IMG_SIZE = 16; -// const int IMG_SIZE_Y = 8; -// size_t size = CHANNELS * IMG_SIZE * IMG_SIZE_Y; -// config.layerConfig.set_type(type); -// config.layerConfig.set_size(size); -// config.layerConfig.set_active_type("sigmoid"); -// config.biasSize = CHANNELS; -// config.inputDefs.push_back({INPUT_DATA, -// "layer_0", -// /* dim= */ size, -// /* paraSize= */ CHANNELS}); -// -// config.inputDefs.push_back({INPUT_DATA, "layer_1_running_mean", 1, -// CHANNELS}); -// config.inputDefs.back().isStatic = true; -// config.inputDefs.push_back({INPUT_DATA, "layer_2_running_var", 1, -// CHANNELS}); -// config.inputDefs.back().isStatic = true; -// -// LayerInputConfig* input = config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// ImageConfig* img_conf = input->mutable_image_conf(); -// img_conf->set_channels(CHANNELS); -// img_conf->set_img_size(IMG_SIZE); -// img_conf->set_img_size_y(IMG_SIZE_Y); -// -// testLayerGrad(config, -// "batch_norm", -// 64, -// /* trans= */ trans, -// useGpu, -// /* useWeight */ true); -// } -// -// TEST(Layer, BatchNormalizationLayer) { -// testBatchNormLayer("batch_norm", false, false); -// #ifndef PADDLE_ONLY_CPU -// testBatchNormLayer("batch_norm", false, true); -// if (hl_get_cudnn_lib_version() >= int(4000)) { -// testBatchNormLayer("cudnn_batch_norm", false, true); -// } -// #endif -// } -// -// TEST(Operator, conv) { -// TestConfig config; -// const int NUM_FILTERS = 16; -// const int FILTER_SIZE = 2; -// const int FILTER_SIZE_Y = 3; -// const int CHANNELS = 3; -// const int IMAGE_SIZE = 16; -// const int IMAGE_SIZE_Y = 8; -// OperatorConfig& operatorConf = *config.layerConfig.add_operator_confs(); -// operatorConf.set_type("conv"); -// ConvConfig* conv = operatorConf.mutable_conv_conf(); -// operatorConf.set_num_filters(NUM_FILTERS); -// conv->set_filter_size(FILTER_SIZE); -// conv->set_filter_size_y(FILTER_SIZE_Y); -// conv->set_channels(CHANNELS); -// conv->set_padding(0); -// conv->set_padding_y(1); -// conv->set_stride(2); -// conv->set_stride_y(2); -// conv->set_groups(1); -// conv->set_filter_channels(conv->channels() / conv->groups()); -// conv->set_img_size(IMAGE_SIZE); -// conv->set_img_size_y(IMAGE_SIZE_Y); -// conv->set_output_x(outputSize(conv->img_size(), -// conv->filter_size(), -// conv->padding(), -// conv->stride(), -// /* caffeMode */ true)); -// conv->set_output_y(outputSize(conv->img_size_y(), -// conv->filter_size_y(), -// conv->padding_y(), -// conv->stride_y(), -// /* caffeMode */ true)); -// config.layerConfig.set_size(conv->output_x() * conv->output_y() * -// NUM_FILTERS); -// -// config.inputDefs.push_back( -// {INPUT_DATA, "layer_0", IMAGE_SIZE * IMAGE_SIZE_Y * CHANNELS, 0}); -// config.inputDefs.push_back( -// {INPUT_DATA, -// "layer_1", -// FILTER_SIZE * FILTER_SIZE_Y * CHANNELS * NUM_FILTERS, -// 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// testOperatorGrad(config, operatorConf, 100, /*useGpu*/ true, false); -// } -// -// TEST(Layer, FeatureMapExpandLayer) { -// TestConfig config; -// config.layerConfig.set_type("featmap_expand"); -// const int CHANNELS = 10; -// const int INPUT_SIZE = 100; -// config.layerConfig.set_size(INPUT_SIZE * CHANNELS); -// config.layerConfig.set_num_filters(CHANNELS); -// config.inputDefs.push_back({INPUT_SEQUENCE_DATA, -// "layer_0", -// /* dim= */ INPUT_SIZE, -// /* paraSize= */ 0}); -// config.layerConfig.add_inputs(); -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, -// "featmap_expand", -// /*batch_size*/ 100, -// /* trans= */ false, -// useGpu, -// /* useWeight */ true); -// } -// } -// -// TEST(Layer, MultiplexLayer) { -// TestConfig config; -// const int LAYER_SIZE = 100; -// config.layerConfig.set_type("multiplex"); -// config.layerConfig.set_size(LAYER_SIZE); -// -// config.inputDefs.push_back({INPUT_LABEL, "layer_0", 2, 0}); -// config.inputDefs.push_back( -// {INPUT_DATA, "layer_1", /* dim= */ LAYER_SIZE, /* paraSize= */ 0}); -// config.inputDefs.push_back( -// {INPUT_DATA, "layer_2", /* dim= */ LAYER_SIZE, /* paraSize= */ 0}); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// config.layerConfig.add_inputs(); -// -// for (auto useGpu : {false, true}) { -// testLayerGrad(config, "multiplex", 512, /* trans= */ false, useGpu); -// } -// } -// +TEST(Operator, dot_mul) { + TestConfig config; + config.layerConfig.set_size(10); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); + config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + OperatorConfig& operatorConf = *config.layerConfig.add_operator_confs(); + operatorConf.set_type("dot_mul"); + operatorConf.set_dotmul_scale(-1); + + testOperatorGrad(config, operatorConf, 100, false, false); +} + +TEST(Projection, context) { + for (auto contextStart : {-5, -3, -1, 0, 3}) { + for (auto contextLength : {1, 2, 5, 7}) { + for (auto batchSize : {1, 2, 5, 20, 50}) { + for (auto trainablePadding : {false, true}) { + LOG(INFO) << " contextStart=" << contextStart + << " contextLength=" << contextLength + << " batchSize=" << batchSize + << " trainablePadding=" << trainablePadding; + ProjectionConfig conf; + conf.set_type("context"); + conf.set_input_size(10); + conf.set_context_start(contextStart); + conf.set_context_length(contextLength); + conf.set_trainable_padding(trainablePadding); + conf.set_output_size(conf.context_length() * conf.input_size()); + int pad = + std::max(0, -conf.context_start()) + + std::max(0, conf.context_start() + conf.context_length() - 1); + for (auto useGpu : {false, true}) { + testProjectionGrad( + conf, + INPUT_SEQUENCE_DATA, + trainablePadding ? conf.input_size() * pad : 0, + batchSize, + useGpu, + contextStart + contextLength <= 1); // = testState + } + } + } + } + } +} + +TEST(Projection, trans_fc) { + ProjectionConfig conf; + conf.set_type("trans_fc"); + conf.set_input_size(50); + conf.set_output_size(20); + for (auto useGpu : {false, true}) { + testProjectionGrad(conf, + INPUT_DATA, + /* parameterSize */ 1000, + /* batchSize */ 100, + useGpu); + } +} + +TEST(Projection, fc) { + ProjectionConfig conf; + conf.set_type("fc"); + conf.set_input_size(10); + conf.set_output_size(20); + for (auto useGpu : {false, true}) { + testProjectionGrad(conf, + INPUT_DATA, + /* parameterSize */ 200, + /* batchSize */ 100, + useGpu); + } +} + +TEST(Projection, dot_mul) { + ProjectionConfig conf; + conf.set_type("dot_mul"); + conf.set_input_size(20); + conf.set_output_size(20); + for (auto useGpu : {false, true}) { + testProjectionGrad(conf, + INPUT_DATA, + /* parameterSize */ 20, + /* batchSize */ 100, + useGpu); + } +} + +TEST(Projection, table) { + ProjectionConfig conf; + conf.set_type("table"); + conf.set_input_size(10); + conf.set_output_size(20); + for (auto useGpu : {false, true}) { + testProjectionGrad(conf, + INPUT_LABEL, + /* parameterSize */ 200, + /* batchSize */ 100, + useGpu); + } +} + +TEST(Projection, identity) { + ProjectionConfig conf; + conf.set_type("identity"); + conf.set_input_size(10); + conf.set_output_size(10); + for (auto useGpu : {false, true}) { + testProjectionGrad(conf, + INPUT_DATA, + /* parameterSize */ 0, + /* batchSize */ 100, + useGpu); + } +} + +TEST(Projection, scaling) { + ProjectionConfig conf; + conf.set_type("scaling"); + conf.set_input_size(10); + conf.set_output_size(10); + for (auto useGpu : {false}) { + testProjectionGrad(conf, + INPUT_DATA, + /* parameterSize */ 1, + /* batchSize */ 100, + useGpu); + } +} + +void testProjectionConv(size_t groups) { + const int NUM_FILTERS = 18; + const int FILTER_SIZE = 2; + const int FILTER_SIZE_Y = 3; + const int CHANNELS = 3; + const int IMAGE_SIZE = 16; + + ProjectionConfig conf; + conf.set_type("conv"); + conf.set_num_filters(NUM_FILTERS); + + ConvConfig* conv = conf.mutable_conv_conf(); + conv->set_filter_size(FILTER_SIZE); + conv->set_filter_size_y(FILTER_SIZE_Y); + conv->set_channels(CHANNELS); + conv->set_padding(0); + conv->set_padding_y(1); + conv->set_stride(2); + conv->set_stride_y(2); + conv->set_groups(groups); + conv->set_filter_channels(conv->channels() / conv->groups()); + conv->set_img_size(IMAGE_SIZE); + int output_x = outputSize(conv->img_size(), + conv->filter_size(), + conv->padding(), + conv->stride(), + /* caffeMode */ true); + int output_y = outputSize(conv->img_size(), + conv->filter_size_y(), + conv->padding_y(), + conv->stride_y(), + /* caffeMode */ true); + conv->set_output_x(output_x); + conf.set_input_size(IMAGE_SIZE * IMAGE_SIZE * CHANNELS); + conf.set_output_size(output_x * output_y * NUM_FILTERS); + + testProjectionGrad(conf, + INPUT_DATA, + /* parameterSize */ NUM_FILTERS * CHANNELS * FILTER_SIZE * + FILTER_SIZE_Y / groups, + /* batchSize */ 100, + true, + false, + NUM_FILTERS, + true); +} + +#ifndef PADDLE_ONLY_CPU +TEST(Projection, conv) { + testProjectionConv(1); + testProjectionConv(3); +} +#endif + +TEST(Layer, BilinearInterpLayer) { + TestConfig config; + config.layerConfig.set_type("bilinear_interp"); + config.biasSize = 0; + config.inputDefs.push_back({INPUT_DATA, "layer_0", 4096, 0}); + + LayerInputConfig* input = config.layerConfig.add_inputs(); + BilinearInterpConfig* bilinear = input->mutable_bilinear_interp_conf(); + ImageConfig* image = bilinear->mutable_image_conf(); + image->set_img_size(32); + image->set_img_size_y(32); + image->set_channels(4); + + for (auto useGpu : {false, true}) { + for (auto outSize : {32, 64}) { + bilinear->set_out_size_x(outSize); + bilinear->set_out_size_y(outSize); + testLayerGrad(config, "bilinear_interp", 10, false, useGpu); + } + } +} + +TEST(Layer, concat) { + TestConfig config; + config.biasSize = 0; + config.layerConfig.set_type("concat"); + config.layerConfig.set_size(15); + config.layerConfig.set_active_type("sigmoid"); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 5, 0}); + config.layerConfig.add_inputs(); + config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "concat", 100, false, useGpu); + } +} + +TEST(Layer, AddtoLayer) { + TestConfig config; + config.biasSize = 0; + config.layerConfig.set_type("addto"); + config.layerConfig.set_size(10); + config.layerConfig.set_active_type("sigmoid"); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); + config.layerConfig.add_inputs(); + config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "addto", 100, false, useGpu); + } +} + +TEST(Layer, CRFLayer) { + TestConfig config; + config.layerConfig.set_type("crf"); + config.layerConfig.set_size(10); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 10, 120}); + config.inputDefs.push_back({INPUT_SEQUENCE_LABEL, "layer_1", 10, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + // Not support GPU now + testLayerGrad(config, + "crf", + 100, + /* trans */ false, + /* useGpu */ false, + false /*useWeight*/, + 0.03 /*epsilon*/); +} + +TEST(Layer, CTCLayer) { + TestConfig config; + config.layerConfig.set_type("ctc"); + config.layerConfig.set_norm_by_times(false); + config.layerConfig.set_size(10); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 10, 0}); + config.inputDefs.push_back({INPUT_SEQUENCE_LABEL, "layer_1", 10, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, + "ctc", + 100, + /* trans */ false, /* useGpu */ + useGpu); + } +} + +TEST(Layer, cosSimLayer) { + TestConfig config; + config.layerConfig.set_type("cos"); + config.layerConfig.set_size(1); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); + config.inputDefs.push_back({INPUT_DATA, "layer_1", 50, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "cos", 100, false, useGpu); + } +} + +TEST(Layer, CosSimVecMatLayer) { + TestConfig config; + config.layerConfig.set_type("cos_vm"); + config.layerConfig.set_size(5); // output size + config.layerConfig.set_cos_scale(2.0); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 20, 0}); + config.layerConfig.add_inputs(); + config.inputDefs.push_back({INPUT_DATA, "layer_1", 100, 0}); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "cos_vm", 100, false, useGpu); + } +} + +void testConvLayer(const string& type, bool trans, bool useGpu) { + TestConfig config; + config.biasSize = 16; + config.layerConfig.set_type(type); + config.layerConfig.set_num_filters(16); + config.layerConfig.set_partial_sum(1); + config.layerConfig.set_shared_biases(true); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 384, 288}); + LayerInputConfig* input = config.layerConfig.add_inputs(); + ConvConfig* conv = input->mutable_conv_conf(); + conv->set_filter_size(2); + conv->set_filter_size_y(3); + conv->set_channels(3); + conv->set_padding(0); + conv->set_padding_y(1); + conv->set_stride(2); + conv->set_stride_y(2); + conv->set_groups(1); + conv->set_filter_channels(conv->channels() / conv->groups()); + conv->set_img_size(16); + conv->set_img_size_y(8); + conv->set_output_x(outputSize(conv->img_size(), + conv->filter_size(), + conv->padding(), + conv->stride(), + /* caffeMode */ true)); + conv->set_output_y(outputSize(conv->img_size_y(), + conv->filter_size_y(), + conv->padding_y(), + conv->stride_y(), + /* caffeMode */ true)); + config.layerConfig.set_size(conv->output_x() * conv->output_y() * + config.layerConfig.num_filters()); + + testLayerGrad(config, "conv", 100, trans, useGpu); + // Use small batch_size and useWeight=true to test biasGrad + testLayerGrad(config, "conv", 2, trans, useGpu, true, 0.02); +} + +TEST(Layer, convLayer) { + testConvLayer("exconv", /* trans= */ false, /* useGpu= */ false); +#ifndef PADDLE_ONLY_CPU + testConvLayer("exconv", /* trans= */ false, /* useGpu= */ true); + testConvLayer("cudnn_conv", /* trans= */ false, /* useGpu= */ true); +#endif +} + +void testConvTransLayer(const string& type, bool trans, bool useGpu) { + TestConfig config; + config.biasSize = 3; + config.layerConfig.set_type(type); + config.layerConfig.set_num_filters(3); + config.layerConfig.set_partial_sum(1); + config.layerConfig.set_shared_biases(true); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 1024, 288}); + LayerInputConfig* input = config.layerConfig.add_inputs(); + ConvConfig* conv = input->mutable_conv_conf(); + conv->set_filter_size(2); + conv->set_filter_size_y(3); + conv->set_channels(16); + conv->set_padding(0); + conv->set_padding_y(1); + conv->set_stride(2); + conv->set_stride_y(2); + conv->set_groups(1); + conv->set_filter_channels(3 / conv->groups()); + conv->set_img_size(16); + conv->set_output_x(outputSize(conv->img_size(), + conv->filter_size(), + conv->padding(), + conv->stride(), + /* caffeMode */ true)); + + config.layerConfig.set_size(conv->img_size() * conv->img_size() * + config.layerConfig.num_filters()); + + testLayerGrad(config, "convTrans", 100, trans, useGpu); + // Use small batch_size and useWeight=true to test biasGrad + testLayerGrad(config, "convTrans", 2, trans, useGpu, true, 0.02); +} + +TEST(Layer, convTransLayer) { + for (auto useGpu : {false, true}) { + testConvTransLayer("exconvt", /* trans= */ false, /* useGpu= */ useGpu); + } +} + +TEST(Layer, blockExpandLayer) { + TestConfig config; + config.biasSize = 0; + config.layerConfig.set_type("blockexpand"); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 6144, 0}); + LayerInputConfig* input = config.layerConfig.add_inputs(); + BlockExpandConfig* blockExpand = input->mutable_block_expand_conf(); + blockExpand->set_img_size_x(64); + blockExpand->set_img_size_y(32); + blockExpand->set_channels(3); + blockExpand->set_padding_x(0); + blockExpand->set_padding_y(0); + blockExpand->set_block_x(4); + blockExpand->set_block_y(32); + blockExpand->set_stride_x(2); + blockExpand->set_stride_y(2); + blockExpand->set_output_x(outputSize(blockExpand->img_size_x(), + blockExpand->block_x(), + blockExpand->padding_x(), + blockExpand->stride_x(), + /* caffeMode */ false)); + blockExpand->set_output_y(outputSize(blockExpand->img_size_y(), + blockExpand->block_y(), + blockExpand->padding_y(), + blockExpand->stride_y(), + /* caffeMode */ false)); + config.layerConfig.set_size(blockExpand->block_x() * blockExpand->block_y() * + blockExpand->channels()); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "blockexpand", 100, false, useGpu); + } +} + +TEST(Layer, maxoutLayer) { + TestConfig config; + config.biasSize = 0; + config.layerConfig.set_type("maxout"); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 4096, 0}); + LayerInputConfig* input = config.layerConfig.add_inputs(); + MaxOutConfig* maxout = input->mutable_maxout_conf(); + ImageConfig* image = maxout->mutable_image_conf(); + + image->set_img_size(32); + image->set_img_size_y(32); + image->set_channels(4); + maxout->set_groups(2); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "maxout", 10, false, useGpu); + } +} +void testFcLayer(string format, size_t nnz) { + TestConfig config; + config.biasSize = 4096; + config.layerConfig.set_type("fc"); + config.layerConfig.set_size(4096); + config.layerConfig.set_active_type("sigmoid"); + config.layerConfig.set_drop_rate(0.1); + + config.inputDefs.push_back( + {INPUT_DATA, "layer_0", 8192, nnz, ParaSparse(format)}); + config.layerConfig.add_inputs(); + + LOG(INFO) << config.inputDefs[0].sparse.sparse << " " + << config.inputDefs[0].sparse.format; + + for (auto useGpu : {false, true}) { + testLayerGrad(config, + "fc", + 100, + /* trans */ false, + useGpu, + /* weight */ true); + } +} + +TEST(Layer, fcLayer) { + testFcLayer("", 4096 * 4096 * 2); + testFcLayer("csc", 4096 * 40); + testFcLayer("csr", 4096 * 40); +} + +TEST(Layer, SelectiveFullyConnectedLayer) { + TestConfig config; + size_t nin = 16; + size_t nout = 256; + config.layerConfig.set_type("selective_fc"); + config.layerConfig.set_size(nout); + config.layerConfig.set_active_type("sigmoid"); + config.layerConfig.set_has_selected_colums(true); + config.layerConfig.set_selective_fc_pass_generation(false); + config.biasSize = nout; + + config.inputDefs.push_back({INPUT_DATA, "input0", nin, nin * nout}); + config.layerConfig.add_inputs(); + config.inputDefs.push_back( + {INPUT_SPARSE_NON_VALUE_DATA, "index", nout, 0, ParaSparse("csr", true)}); + config.layerConfig.add_inputs(); + + testLayerGrad(config, + "selective_fc", + 100, + /* trans= */ false, + /* useGup= */ false, + false); +#ifndef PADDLE_ONLY_CPU + testLayerGrad(config, + "selective_fc", + 100, + /* trans= */ false, + /* useGup= */ true, + false); +#endif +} + +TEST(Layer, DataNormLayer) { + TestConfig config; + config.layerConfig.set_type("data_norm"); + config.layerConfig.set_size(20); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 20, 100}); + config.inputDefs.back().isStatic = true; + config.layerConfig.add_inputs(); + + for (auto strategy : {"z-score", "min-max", "decimal-scaling"}) { + config.layerConfig.set_data_norm_strategy(strategy); + // The parameters are static, so not support GPU now + testLayerGrad(config, + "data_norm", + 200, + /* trans */ false, + /* useGpu */ false); + } +} + +TEST(Layer, hsigmoidLayer) { + TestConfig config; + config.layerConfig.set_type("hsigmoid"); + config.layerConfig.set_num_classes(5); + config.layerConfig.set_size(1); + config.biasSize = config.layerConfig.num_classes() - 1; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 200}); + config.inputDefs.push_back({INPUT_LABEL, "layer_1", 5, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + // Not support GPU now + testLayerGrad(config, + "hsigmoid", + 100, + /* trans */ false, /* useGpu */ + false); +} + +TEST(Layer, multi_cross) { + TestConfig config; + config.layerConfig.set_type("multi-class-cross-entropy"); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); + config.inputDefs.push_back({INPUT_LABEL, "layer_1", 10, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad( + config, "multi-class-cross-entropy", 100, /* trans */ false, useGpu); + } +} + +TEST(Layer, multi_binary_label_sparse_mat) { + TestConfig config; + config.layerConfig.set_type("multi_binary_label_cross_entropy"); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); + config.inputDefs.push_back({INPUT_SPARSE_NON_VALUE_DATA, "layer_1", 50, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, + "multi_binary_label_cross_entropy", + 100, + /* trans */ false, + useGpu); + } +} + +TEST(layer, multi_binary_label_id) { + TestConfig config; + config.layerConfig.set_type("multi_binary_label_cross_entropy"); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); + config.inputDefs.push_back({INPUT_LABEL, "layer_1", 10, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, + "multi_binary_label_cross_entropy", + 100, + /* trans */ false, + useGpu); + } +} + +TEST(Layer, multi_cross_with_selfnorm) { + TestConfig config; + config.layerConfig.set_type("multi_class_cross_entropy_with_selfnorm"); + config.layerConfig.set_softmax_selfnorm_alpha(0.1); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); + config.inputDefs.push_back({INPUT_LABEL, "layer_1", 10, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + // Not support GPU now + testLayerGrad(config, + "multi_class_cross_entropy_with_selfnorm", + 100, + /* trans */ false, + /* useGpu */ false); +} + +TEST(Layer, multi_cross_soft) { + TestConfig config; + config.layerConfig.set_type("soft_binary_class_cross_entropy"); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); + config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_1", 10, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, + "soft_binary_class_cross_entropy", + 100, + /* trans */ false, + useGpu); + } +} + +TEST(Layer, square_error) { + TestConfig config; + config.layerConfig.set_type("square_error"); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); + config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_1", 10, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "square_error", 100, /* trans */ false, useGpu); + } +} + +TEST(Layer, sparse_square_error) { + TestConfig config; + config.layerConfig.set_type("square_error"); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); + config.inputDefs.push_back({INPUT_SPARSE_NON_VALUE_DATA, "layer_1", 50, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + // "GpuSparseMatrix" as label is not supported + testLayerGrad(config, + "square_error", + 100, + /* trans */ false, + /* useGpu */ false); +} + +TEST(Layer, sparse_float_square_error) { + TestConfig config; + config.layerConfig.set_type("square_error"); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 50, 0}); + config.inputDefs.push_back({INPUT_SPARSE_FLOAT_VALUE_DATA, "layer_1", 50, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + // "GpuSparseMatrix" as label is not supported + testLayerGrad(config, + "square_error", + 100, + /* trans */ false, + /* useGpu */ false); +} + +TEST(Layer, square_error_weighted) { + TestConfig config; + config.layerConfig.set_type("square_error"); + config.biasSize = 0; + config.testAccumulate = false; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); + config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_1", 10, 0}); + config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_2", 1, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "square_error", 100, /* trans */ false, useGpu); + } +} + +TEST(Layer, huber_two_class) { + TestConfig config; + config.layerConfig.set_type("huber"); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); + config.inputDefs.push_back({INPUT_LABEL, "layer_1", 2, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "huber", 100, /* trans */ false, useGpu); + } +} + +void testExpandLayer(string trans_type, bool hasSubseq) { + TestConfig config; + config.layerConfig.set_type("expand"); + + config.inputDefs.push_back( + {trans_type == "non-seq" ? INPUT_DENSE_DIM_DATA : INPUT_SEQUENCE_DATA, + "layer_0", + 10, + 0}); + config.inputDefs.push_back( + {hasSubseq ? INPUT_HASSUB_SEQUENCE_DATA : INPUT_SEQUENCE_DATA, + "layer_1", + 10, + 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + config.layerConfig.set_trans_type(trans_type); + LOG(INFO) << " trans_type=" << trans_type << " hasSubseq=" << hasSubseq; + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "expand", 30, false, useGpu); + } +} + +TEST(Layer, ExpandLayer) { + testExpandLayer("non-seq", false); // non-seq expand to seq + testExpandLayer("non-seq", true); // non-seq expand to hasSubseq + testExpandLayer("seq", true); // seq expand to hasSubseq +} + +void testDegradeLayer(bool hasSubseq, string layer_type, string trans_type) { + TestConfig config; + config.layerConfig.set_type(layer_type); + config.layerConfig.set_size(10); + config.biasSize = 0; + + config.inputDefs.push_back( + {hasSubseq ? INPUT_HASSUB_SEQUENCE_DATA : INPUT_SEQUENCE_DATA, + "layer_0", + 10, + 0}); + config.layerConfig.add_inputs(); + config.layerConfig.set_trans_type(trans_type); + + auto testDegradeLayerGrad = [](TestConfig& config, string layer_type) { + for (auto useGpu : {false, true}) { + testLayerGrad(config, layer_type, 100, false, useGpu); + } + }; + + if (layer_type == "average") { + for (auto strategy : {"average", "sum", "squarerootn"}) { + LOG(INFO) << " hasSubseq=" << hasSubseq << " trans_type=" << trans_type + << " average_strategy=" << strategy; + config.layerConfig.set_average_strategy(strategy); + testDegradeLayerGrad(config, layer_type); + } + } else { + LOG(INFO) << " hasSubseq=" << hasSubseq << " trans_type=" << trans_type; + testDegradeLayerGrad(config, layer_type); + } +} + +TEST(Layer, MaxLayer) { + testDegradeLayer(false, "max", "non-seq"); // seq max to non-seq + testDegradeLayer(true, "max", "non-seq"); // hasSubseq max to non-seq + testDegradeLayer(true, "max", "seq"); // hasSubseq max to seq +} + +TEST(Layer, SequenceLastInstanceLayer) { + testDegradeLayer(false, + "seqlastins", + "non-seq"); // seq seqlastins to non-seq + testDegradeLayer(true, + "seqlastins", + "non-seq"); // hasSubseq seqlastins to non-seq + testDegradeLayer(true, "seqlastins", "seq"); // hasSubseq seqlastins to + seq +} + +TEST(Layer, AverageLayer) { + testDegradeLayer(false, "average", "non-seq"); // seq average to non-seq + testDegradeLayer(true, "average", "non-seq"); // hasSubseq average to + non - + seq testDegradeLayer(true, "average", "seq"); // hasSubseq average to seq +} + +TEST(Layer, SequenceConcatLayer) { + TestConfig config; + config.layerConfig.set_type("seqconcat"); + config.layerConfig.set_size(10); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 10, 0}); + config.layerConfig.add_inputs(); + config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_1", 10, 0}); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "seqconcat", 100, false, useGpu); + } +} + +TEST(Layer, SequenceReshapeLayer) { + TestConfig config; + config.layerConfig.set_type("seqreshape"); + config.layerConfig.set_size(10); + + config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "layer_0", 100, 0}); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "seqreshape", 100, false, useGpu); + } +} + +TEST(Layer, ConvShiftLayer) { + TestConfig config; + config.layerConfig.set_type("conv_shift"); + config.layerConfig.set_size(10); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); + config.inputDefs.push_back({INPUT_DATA, "layer_1", 3, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + // Not support GPU now + testLayerGrad(config, "conv_shift", 100, false, false); +} + +TEST(Layer, PowerLayer) { + TestConfig config; + config.layerConfig.set_type("power"); + config.layerConfig.set_size(10); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); + config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "power", 100, false, useGpu); + } +} + +TEST(Layer, ConvexCombinationLayer) { + TestConfig config; + config.layerConfig.set_type("convex_comb"); + config.layerConfig.set_size(20); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 5, 0}); + config.inputDefs.push_back({INPUT_DATA, "layer_1", 100, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "convex_comb", 100, false, useGpu); + } +} + +TEST(Layer, InterpolationLayer) { + TestConfig config; + config.layerConfig.set_type("interpolation"); + config.layerConfig.set_size(10); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); + config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); + config.inputDefs.push_back({INPUT_DATA, "layer_2", 10, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "interpolation", 100, false, useGpu); + } +} + +TEST(Layer, OuterProdLayer) { + TestConfig config; + config.layerConfig.set_type("out_prod"); + config.layerConfig.set_size(100); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); + config.layerConfig.add_inputs(); + config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "out_prod", 100, false, useGpu); + } +} + +TEST(Layer, SlopeInterceptLayer) { + TestConfig config; + config.layerConfig.set_type("slope_intercept"); + config.layerConfig.set_size(10); + config.layerConfig.set_slope(1.0); + config.layerConfig.set_intercept(0.1); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 10, 0}); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "slope_intercept", 100, false, useGpu); + } +} + +TEST(Layer, ScalingLayer) { + TestConfig config; + config.layerConfig.set_type("scaling"); + config.layerConfig.set_size(10); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); + config.layerConfig.add_inputs(); + config.inputDefs.push_back({INPUT_DATA, "layer_1", 10, 0}); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "scaling", 100, false, useGpu); + } +} + +void testNormLayer(const string& normType, bool trans, bool useGpu) { + TestConfig config; + config.layerConfig.set_type("norm"); + config.layerConfig.set_active_type("relu"); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 1568, 0}); + LayerInputConfig* input = config.layerConfig.add_inputs(); + NormConfig* norm = input->mutable_norm_conf(); + norm->set_norm_type(normType); + norm->set_channels(16); + norm->set_size(5); + norm->set_scale(0.001); + norm->set_pow(0.75); + norm->set_blocked(0); + norm->set_img_size(14); + norm->set_img_size_y(7); + norm->set_output_x(norm->img_size()); + norm->set_output_y(norm->img_size_y()); + if (norm->norm_type() == "cmrnorm" || + norm->norm_type() == "cmrnorm-projection") { + norm->set_scale(norm->scale() / norm->size()); + } else { + norm->set_scale(norm->scale() / (norm->size() * norm->size())); + } + + config.layerConfig.set_size(norm->output_x() * norm->output_y() * + norm->channels()); + config.biasSize = 0; + + testLayerGrad(config, "norm", 100, trans, useGpu); +} + +TEST(Layer, NormLayer) { + testNormLayer("cmrnorm-projection", + /* trans= */ false, /* useGpu= */ + true); + testNormLayer("cmrnorm-projection", + /* trans= */ false, /* useGpu= */ + false); +} + +void setPoolConfig(TestConfig* config, + PoolConfig* pool, + const string& poolType) { + (*config).biasSize = 0; + (*config).layerConfig.set_type("pool"); + (*config).layerConfig.set_num_filters(16); + + int kw = 3, kh = 3; + int pw = 0, ph = 0; + int sw = 2, sh = 2; + pool->set_pool_type(poolType); + pool->set_channels(16); + pool->set_size_x(kw); + pool->set_size_y(kh); + pool->set_start(0); + pool->set_padding(pw); + pool->set_padding_y(ph); + pool->set_stride(sw); + pool->set_stride_y(sh); + + int ow = outputSize(pool->img_size(), kw, pw, sw, /* caffeMode */ false); + int oh = outputSize(pool->img_size_y(), kh, ph, sh, /* caffeMode */ false); + pool->set_output_x(ow); + pool->set_output_y(oh); +} + +void testPoolLayer(const string& poolType, bool trans, bool useGpu) { + TestConfig config; + config.inputDefs.push_back({INPUT_DATA, "layer_0", 3136, 0}); + LayerInputConfig* input = config.layerConfig.add_inputs(); + PoolConfig* pool = input->mutable_pool_conf(); + + pool->set_img_size(14); + pool->set_img_size_y(14); + setPoolConfig(&config, pool, poolType); + config.layerConfig.set_size(pool->output_x() * pool->output_y() * + pool->channels()); + + testLayerGrad(config, "pool", 100, trans, useGpu); +} + +#ifndef PADDLE_ONLY_CPU +void testPoolLayer2(const string& poolType, bool trans, bool useGpu) { + TestConfig config; + config.inputDefs.push_back({INPUT_DATA, "layer_0", 3200, 0}); + LayerInputConfig* input = config.layerConfig.add_inputs(); + PoolConfig* pool = input->mutable_pool_conf(); + + pool->set_size_y(4); + pool->set_stride_y(3); + pool->set_img_size(10); + pool->set_img_size_y(20); + setPoolConfig(&config, pool, poolType); + pool->set_output_y((pool->img_size_y() - pool->start() - pool->size_y()) / + ((float)pool->stride_y()) + + 1.5); + config.layerConfig.set_size(pool->output_x() * pool->output_y() * + pool->channels()); + + testLayerGrad(config, "pool", 100, trans, useGpu); +} +#endif + +TEST(Layer, PoolLayer) { + testPoolLayer("avg-projection", /* trans= */ false, /* useGpu= */ false); + testPoolLayer("max-projection", /* trans= */ false, /* useGpu= */ false); + +#ifndef PADDLE_ONLY_CPU + testPoolLayer("avg-projection", /* trans= */ false, /* useGpu= */ true); + testPoolLayer("max-projection", /* trans= */ false, /* useGpu= */ true); + testPoolLayer("cudnn-max-pool", /* trans= */ false, /* useGpu= */ true); + testPoolLayer("cudnn-avg-pool", /* trans= */ false, /* useGpu= */ true); + testPoolLayer2("cudnn-max-pool", /* trans= */ false, /* useGpu= */ true); + testPoolLayer2("cudnn-avg-pool", /* trans= */ false, /* useGpu= */ true); +#endif +} + +void testSppLayer(const string& poolType, + const int pyramidHeight, + bool trans, + bool useGpu) { + TestConfig config; + config.layerConfig.set_type("spp"); + config.inputDefs.push_back({INPUT_DATA, "layer_0", 3200, 0}); + LayerInputConfig* input = config.layerConfig.add_inputs(); + SppConfig* sppConfig = input->mutable_spp_conf(); + sppConfig->set_pool_type(poolType); + sppConfig->set_pyramid_height(pyramidHeight); + ImageConfig* imageConfig = sppConfig->mutable_image_conf(); + imageConfig->set_channels(16); + imageConfig->set_img_size(10); + imageConfig->set_img_size_y(20); + int outputSize = (std::pow(4, sppConfig->pyramid_height()) - 1) / (4 - 1); + config.layerConfig.set_size(outputSize * imageConfig->channels()); + testLayerGrad(config, "spp", 100, trans, useGpu); +} + +TEST(Layer, SpatialPyramidPoolLayer) { + for (auto useGpu : {false, true}) { + for (auto pyramidHeight : {1, 2, 3}) { + testSppLayer("avg-projection", pyramidHeight, false, useGpu); + testSppLayer("max-projection", pyramidHeight, false, useGpu); + } + } +} + +TEST(Layer, rankCostLayer) { + TestConfig config; + config.layerConfig.set_type("rank-cost"); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); + config.inputDefs.push_back({INPUT_DATA, "layer_1", 1, 0}); + config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_2", 1, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "rank-cost", 100, false, useGpu); + } +} + +TEST(Layer, sumCostLayer) { + TestConfig config; + config.layerConfig.set_type("sum_cost"); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "sum_cost", 100, false, useGpu); + } +} + +TEST(Layer, weightedRankCostLayer) { + TestConfig config; + config.layerConfig.set_type("rank-cost"); + config.biasSize = 0; + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0}); + config.inputDefs.push_back({INPUT_DATA, "layer_1", 1, 0}); + config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_2", 1, 0}); + config.inputDefs.push_back({INPUT_DATA_TARGET, "layer_3", 1, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "weighted-rank-cost", 100, false, useGpu); + } +} + +TEST(Layer, TensorLayer) { + TestConfig config; + config.layerConfig.set_type("tensor"); + config.layerConfig.set_size(10); + config.layerConfig.set_active_type("sigmoid"); + config.biasSize = config.layerConfig.size(); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 5, 250}); + config.inputDefs.push_back({INPUT_DATA, "layer_1", 5, 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "tensor", 100, false, useGpu); + } +} + +TEST(Layer, RecurrentLayer) { + TestConfig config; + config.layerConfig.set_type("recurrent"); + config.layerConfig.set_size(4); + config.layerConfig.set_active_type("tanh"); + config.biasSize = 4; + + config.inputDefs.push_back( + {INPUT_SEQUENCE_DATA, "layer_0", /* dim= */ 4, /* paraSize= */ 16}); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + for (auto reversed : {false, true}) { + config.layerConfig.set_reversed(reversed); + config.testState = !reversed; + testLayerGrad(config, "recurrent", 50, /* trans= */ false, useGpu); + } + } +} + +TEST(Layer, LstmLayer) { + TestConfig config; + config.layerConfig.set_type("lstmemory"); + config.layerConfig.set_size(4); + config.layerConfig.set_active_type("tanh"); + config.layerConfig.set_active_state_type("sigmoid"); + config.layerConfig.set_active_gate_type("sigmoid"); + config.biasSize = 28; + + config.inputDefs.push_back( + {INPUT_SEQUENCE_DATA, "layer_0", /* dim= */ 16, /* paraSize= */ 64}); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + for (auto reversed : {false, true}) { + config.layerConfig.set_reversed(reversed); + config.testState = !reversed; + testLayerGrad(config, "lstmemory", 100, /* trans= */ false, useGpu); + } + } + for (auto useGpu : {true}) { + config.testBatchState = true; + config.layerConfig.set_reversed(false); + testLayerGrad(config, "lstmemory", 10, /* trans= */ false, useGpu); + } +} + +TEST(Layer, MDLstmLayer) { + TestConfig config; + config.layerConfig.set_type("mdlstmemory"); + config.layerConfig.set_size(4); + config.layerConfig.set_active_type("sigmoid"); + config.layerConfig.set_active_state_type("sigmoid"); + config.layerConfig.set_active_gate_type("sigmoid"); + config.biasSize = 4 * 9; + + config.inputDefs.push_back( + {INPUT_SEQUENCE_MDIM_DATA, "layer_0", 4 * 5, 4 * 4 * 5}); + config.layerConfig.add_inputs(); + config.layerConfig.add_directions(true); + config.layerConfig.add_directions(true); + + for (auto useGpu : {false, true}) { + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + config.layerConfig.set_directions(0, bool(i)); + config.layerConfig.set_directions(1, bool(j)); + testLayerGrad(config, "mdlstmemory", 100, false, useGpu); + } + } + } +} + +TEST(Layer, ParameterReluLayer) { + auto testParameterReluLayer = [&](size_t inputSize, size_t channels) { + TestConfig config; + config.layerConfig.set_type("prelu"); + config.inputDefs.push_back({INPUT_DATA, "layer_0", inputSize, channels}); + config.layerConfig.add_inputs(); + config.layerConfig.set_size(inputSize); + config.layerConfig.set_partial_sum(inputSize / + channels); // size of feature map + for (auto useGpu : {false, true}) { + testLayerGrad(config, "prelu", 100, false, useGpu); + } + }; + + testParameterReluLayer(192, 1); + testParameterReluLayer(192, 3); + testParameterReluLayer(192, 192); +} + +TEST(Layer, ResizeLayer) { + TestConfig config; + config.biasSize = 0; + config.layerConfig.set_type("resize"); + config.layerConfig.set_size(64); + + config.inputDefs.push_back({INPUT_DATA, "layer_0", 16, 0}); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "resize", 100, false, useGpu); + } +} + +TEST(Layer, NCELayer) { + TestConfig config; + size_t numClasses = 4; + config.layerConfig.set_type("nce"); + config.layerConfig.set_size(1); + config.layerConfig.set_active_type("sigmoid"); + config.layerConfig.set_num_classes(numClasses); + config.biasSize = numClasses; + + config.inputDefs.push_back( + {INPUT_DATA, "layer_0", /* dim= */ 16, /* paraSize= */ 16 * numClasses}); + config.inputDefs.push_back( + {INPUT_LABEL, "label", /* dim= */ numClasses, /* paraSize= */ 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto withWeight : {false, true}) { + if (withWeight) { + config.inputDefs.push_back( + {INPUT_DATA_TARGET, "weight", /* dim= */ 1, /* paraSize= */ 0}); + config.layerConfig.add_inputs(); + } + + for (auto isIdLabel : {false, true}) { + config.inputDefs[1] = { + isIdLabel ? INPUT_LABEL : INPUT_SPARSE_NON_VALUE_DATA, + "label", + /* dim= */ numClasses, + /* paraSize= */ 0}; + + for (auto withDist : {false, true}) { + config.layerConfig.clear_neg_sampling_dist(); + if (withDist) { + double sum = 0; + for (size_t i = 0; i < numClasses; ++i) { + real p = rand(); // NOLINT use rand_r + config.layerConfig.add_neg_sampling_dist(p); + sum += p; + } + for (size_t i = 0; i < numClasses; ++i) { + real p = config.layerConfig.neg_sampling_dist(i) / sum; + config.layerConfig.set_neg_sampling_dist(i, p); + } + } + LOG(INFO) << "NCELayer " + << " isIdLabel=" << isIdLabel << " withWeight=" << withWeight + << " withDist=" << withDist; + // Not support GPU now + testLayerGrad(config, + "nce", + 100, + /* trans= */ false, + /* useGpu */ false); + } + } + } +} + +TEST(Layer, GatedRecurrentLayer) { + TestConfig config; + config.layerConfig.set_type("gated_recurrent"); + config.layerConfig.set_size(4); + config.layerConfig.set_active_type("sigmoid"); + config.layerConfig.set_active_gate_type("sigmoid"); + config.biasSize = 12; + + config.inputDefs.push_back( + {INPUT_SEQUENCE_DATA, "layer_0", /* dim= */ 12, /* paraSize= */ 48}); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + for (auto reversed : {false, true}) { + config.layerConfig.set_reversed(reversed); + config.testState = !reversed; + testLayerGrad(config, "gated_recurrent", 100, /* trans= */ false, useGpu); + } + } +} + +TEST(Layer, GruStepLayer) { + TestConfig config; + config.layerConfig.set_type("gru_step"); + config.layerConfig.set_size(4); + config.layerConfig.set_active_type("sigmoid"); + config.layerConfig.set_active_gate_type("sigmoid"); + config.biasSize = 12; + + config.inputDefs.push_back( + {INPUT_DATA, "layer_0", /* dim= */ 12, /* paraSize= */ 48}); + config.inputDefs.push_back( + {INPUT_DATA, "layer_1", /* dim= */ 4, /* paraSize= */ 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "gruStep", 100, /* trans= */ false, useGpu); + } +} + +TEST(Layer, LstmStepLayer) { + TestConfig config; + config.layerConfig.set_type("lstm_step"); + config.layerConfig.set_size(4); + config.layerConfig.set_active_type("sigmoid"); + config.layerConfig.set_active_state_type("sigmoid"); + config.layerConfig.set_active_gate_type("sigmoid"); + config.biasSize = 12; + config.testAccumulate = false; + + config.inputDefs.push_back( + {INPUT_DATA, "layer_0", /* dim= */ 16, /* paraSize= */ 0}); + config.inputDefs.push_back( + {INPUT_DATA, "layer_1", /* dim= */ 4, /* paraSize= */ 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "lstmStep", 100, /* trans= */ false, useGpu); + } +} + +void testBatchNormLayer(const string& type, bool trans, bool useGpu) { + TestConfig config; + const int CHANNELS = 10; + const int IMG_SIZE = 16; + const int IMG_SIZE_Y = 8; + size_t size = CHANNELS * IMG_SIZE * IMG_SIZE_Y; + config.layerConfig.set_type(type); + config.layerConfig.set_size(size); + config.layerConfig.set_active_type("sigmoid"); + config.biasSize = CHANNELS; + config.inputDefs.push_back({INPUT_DATA, + "layer_0", + /* dim= */ size, + /* paraSize= */ CHANNELS}); + + config.inputDefs.push_back({INPUT_DATA, "layer_1_running_mean", 1, CHANNELS}); + config.inputDefs.back().isStatic = true; + config.inputDefs.push_back({INPUT_DATA, "layer_2_running_var", 1, CHANNELS}); + config.inputDefs.back().isStatic = true; + + LayerInputConfig* input = config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + ImageConfig* img_conf = input->mutable_image_conf(); + img_conf->set_channels(CHANNELS); + img_conf->set_img_size(IMG_SIZE); + img_conf->set_img_size_y(IMG_SIZE_Y); + + testLayerGrad(config, + "batch_norm", + 64, + /* trans= */ trans, + useGpu, + /* useWeight */ true); +} + +TEST(Layer, BatchNormalizationLayer) { + testBatchNormLayer("batch_norm", false, false); +#ifndef PADDLE_ONLY_CPU + testBatchNormLayer("batch_norm", false, true); + if (hl_get_cudnn_lib_version() >= int(4000)) { + testBatchNormLayer("cudnn_batch_norm", false, true); + } +#endif +} + +TEST(Operator, conv) { + TestConfig config; + const int NUM_FILTERS = 16; + const int FILTER_SIZE = 2; + const int FILTER_SIZE_Y = 3; + const int CHANNELS = 3; + const int IMAGE_SIZE = 16; + const int IMAGE_SIZE_Y = 8; + OperatorConfig& operatorConf = *config.layerConfig.add_operator_confs(); + operatorConf.set_type("conv"); + ConvConfig* conv = operatorConf.mutable_conv_conf(); + operatorConf.set_num_filters(NUM_FILTERS); + conv->set_filter_size(FILTER_SIZE); + conv->set_filter_size_y(FILTER_SIZE_Y); + conv->set_channels(CHANNELS); + conv->set_padding(0); + conv->set_padding_y(1); + conv->set_stride(2); + conv->set_stride_y(2); + conv->set_groups(1); + conv->set_filter_channels(conv->channels() / conv->groups()); + conv->set_img_size(IMAGE_SIZE); + conv->set_img_size_y(IMAGE_SIZE_Y); + conv->set_output_x(outputSize(conv->img_size(), + conv->filter_size(), + conv->padding(), + conv->stride(), + /* caffeMode */ true)); + conv->set_output_y(outputSize(conv->img_size_y(), + conv->filter_size_y(), + conv->padding_y(), + conv->stride_y(), + /* caffeMode */ true)); + config.layerConfig.set_size(conv->output_x() * conv->output_y() * + NUM_FILTERS); + + config.inputDefs.push_back( + {INPUT_DATA, "layer_0", IMAGE_SIZE * IMAGE_SIZE_Y * CHANNELS, 0}); + config.inputDefs.push_back( + {INPUT_DATA, + "layer_1", + FILTER_SIZE * FILTER_SIZE_Y * CHANNELS * NUM_FILTERS, + 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + testOperatorGrad(config, operatorConf, 100, /*useGpu*/ true, false); +} + +TEST(Layer, FeatureMapExpandLayer) { + TestConfig config; + config.layerConfig.set_type("featmap_expand"); + const int CHANNELS = 10; + const int INPUT_SIZE = 100; + config.layerConfig.set_size(INPUT_SIZE * CHANNELS); + config.layerConfig.set_num_filters(CHANNELS); + config.inputDefs.push_back({INPUT_SEQUENCE_DATA, + "layer_0", + /* dim= */ INPUT_SIZE, + /* paraSize= */ 0}); + config.layerConfig.add_inputs(); + for (auto useGpu : {false, true}) { + testLayerGrad(config, + "featmap_expand", + /*batch_size*/ 100, + /* trans= */ false, + useGpu, + /* useWeight */ true); + } +} + +TEST(Layer, MultiplexLayer) { + TestConfig config; + const int LAYER_SIZE = 100; + config.layerConfig.set_type("multiplex"); + config.layerConfig.set_size(LAYER_SIZE); + + config.inputDefs.push_back({INPUT_LABEL, "layer_0", 2, 0}); + config.inputDefs.push_back( + {INPUT_DATA, "layer_1", /* dim= */ LAYER_SIZE, /* paraSize= */ 0}); + config.inputDefs.push_back( + {INPUT_DATA, "layer_2", /* dim= */ LAYER_SIZE, /* paraSize= */ 0}); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "multiplex", 512, /* trans= */ false, useGpu); + } +} + TEST(Layer, PadLayer) { TestConfig config; config.biasSize = 0; diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index 6e5922166da1b1..c80ed0274461da 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -1109,7 +1109,7 @@ def parse_bilinear(bilinear, input_layer_name, bilinear_conf): bilinear_conf.out_size_y = bilinear.out_size_y -def parse_pool(pool, input_layer_name, pool_conf): +def parse_pool(pool, input_layer_name, pool_conf, ceil_mode): pool_conf.pool_type = pool.pool_type config_assert(pool.pool_type in [ 'max-projection', 'avg-projection', 'cudnn-max-pool', 'cudnn-avg-pool' @@ -1134,10 +1134,10 @@ def parse_pool(pool, input_layer_name, pool_conf): pool_conf.padding_y = default(pool.padding_y, pool_conf.padding) pool_conf.output_x = cnn_output_size(pool_conf.img_size, pool_conf.size_x, pool_conf.padding, pool_conf.stride, - False) + not ceil_mode) pool_conf.output_y = cnn_output_size(pool_conf.img_size_y, pool_conf.size_y, pool_conf.padding_y, - pool_conf.stride_y, False) + pool_conf.stride_y, not ceil_mode) def parse_spp(spp, input_layer_name, spp_conf): @@ -1810,9 +1810,8 @@ class ConvTransLayer(ConvTransLayerBase): @config_layer('norm') class NormLayer(LayerBase): - def __init__(self, name, inputs, device=None): - super(NormLayer, self).__init__( - name, 'norm', 0, inputs=inputs, device=device) + def __init__(self, name, inputs, **xargs): + super(NormLayer, self).__init__(name, 'norm', 0, inputs=inputs, **xargs) for input_index in xrange(len(self.inputs)): input_layer = self.get_input_layer(input_index) norm_conf = self.config.inputs[input_index].norm_conf @@ -1824,23 +1823,22 @@ def __init__(self, name, inputs, device=None): @config_layer('pool') class PoolLayer(LayerBase): - def __init__(self, name, inputs, device=None): - super(PoolLayer, self).__init__( - name, 'pool', 0, inputs=inputs, device=device) + def __init__(self, name, inputs, ceil_mode=True, **xargs): + super(PoolLayer, self).__init__(name, 'pool', 0, inputs=inputs, **xargs) for input_index in xrange(len(self.inputs)): input_layer = self.get_input_layer(input_index) pool_conf = self.config.inputs[input_index].pool_conf parse_pool(self.inputs[input_index].pool, input_layer.name, - pool_conf) + pool_conf, ceil_mode) self.set_cnn_layer(name, pool_conf.output_y, pool_conf.output_x, pool_conf.channels) @config_layer('spp') class SpatialPyramidPoolLayer(LayerBase): - def __init__(self, name, inputs, device=None): + def __init__(self, name, inputs, **xargs): super(SpatialPyramidPoolLayer, self).__init__( - name, 'spp', 0, inputs=inputs, device=device) + name, 'spp', 0, inputs=inputs, **xargs) for input_index in xrange(len(self.inputs)): input_layer = self.get_input_layer(input_index) spp_conf = self.config.inputs[input_index].spp_conf @@ -1877,7 +1875,6 @@ def __init__(self, inputs, active_type="linear", bias=True, - device=None, use_global_stats=True, moving_average_fraction=0.9, batch_norm_type=None, @@ -1919,7 +1916,6 @@ def __init__(self, 0, active_type=active_type, inputs=inputs, - device=device, **xargs) if use_global_stats is not None: @@ -1953,9 +1949,9 @@ def calc_parameter_size(self, image_conf): @config_layer('trans') class TransLayer(LayerBase): - def __init__(self, name, inputs, device=None): + def __init__(self, name, inputs, **xargs): super(TransLayer, self).__init__( - name, 'trans', 0, inputs=inputs, device=device) + name, 'trans', 0, inputs=inputs, **xargs) config_assert( len(self.inputs) == 1, 'TransLayer must have one and only one input') @@ -1964,9 +1960,9 @@ def __init__(self, name, inputs, device=None): @config_layer('resize') class ResizeLayer(LayerBase): - def __init__(self, name, size, inputs, device=None): + def __init__(self, name, size, inputs, **xargs): super(ResizeLayer, self).__init__( - name, 'resize', size=size, inputs=inputs, device=device) + name, 'resize', size=size, inputs=inputs, **xargs) config_assert( len(self.inputs) == 1, 'ResizeLayer must have one and only one input') @@ -1974,9 +1970,9 @@ def __init__(self, name, size, inputs, device=None): @config_layer('blockexpand') class BlockExpandLayer(LayerBase): - def __init__(self, name, inputs, device=None): + def __init__(self, name, inputs, **xargs): super(BlockExpandLayer, self).__init__( - name, 'blockexpand', 0, inputs=inputs, device=device) + name, 'blockexpand', 0, inputs=inputs, **xargs) for input_index in xrange(len(self.inputs)): input_layer = self.get_input_layer(input_index) parse_block_expand( diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 56c335a0504d04..3f88727b63066f 100644 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -1980,7 +1980,8 @@ def img_pool_layer(input, layer_attr=None, pool_size_y=None, stride_y=None, - padding_y=None): + padding_y=None, + ceil_mode=True): """ Image pooling Layer. @@ -2011,6 +2012,23 @@ def img_pool_layer(input, :type stride_y: int|None :param layer_attr: Extra Layer attribute. :type layer_attr: ExtraLayerAttribute + :param ceil_mode: Wether to use ceil mode to calculate output height and with. + Defalut is True. If set false, Otherwise use floor. + + - ceil_mode=True: + + .. math:: + + w = 1 + int(ceil(input_width + 2 * padding - pool_size) / float(stride)) + h = 1 + int(ceil(input_height + 2 * padding_y - pool_size_y) / float(stride_y)) + + - ceil_mode=False: + + .. math:: + + w = 1 + int(floor(input_width + 2 * padding - pool_size) / float(stride)) + h = 1 + int(floor(input_height + 2 * padding_y - pool_size_y) / float(stride_y)) + :type ceil_mode: bool :return: LayerOutput object. :rtype: LayerOutput """ @@ -2048,6 +2066,7 @@ def img_pool_layer(input, stride_y=stride_y, padding_y=padding_y)) ], + ceil_mode=ceil_mode, **ExtraLayerAttribute.to_kwargs(layer_attr)) return LayerOutput( name, From 74f76e61d885dcc0478086c54ad330875b92bbd4 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Mon, 9 Jan 2017 10:30:39 +0800 Subject: [PATCH 007/370] update code and fix bug --- paddle/function/PadOp.cpp | 12 ++++++------ paddle/function/PadOpTest.cpp | 2 +- paddle/gserver/tests/test_LayerGrad.cpp | 8 +++----- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/paddle/function/PadOp.cpp b/paddle/function/PadOp.cpp index 2dfe03dcf61ce3..ff13f27e94217b 100644 --- a/paddle/function/PadOp.cpp +++ b/paddle/function/PadOp.cpp @@ -92,9 +92,9 @@ class PadFunc : public FunctionBase { void calc(const Arguments& inputs, const Arguments& outputs, const Arguments& inouts) override { - CHECK_EQ(1, inputs.size()); - CHECK_EQ(1, outputs.size()); - CHECK_EQ(0, inouts.size()); + CHECK_EQ(1UL, inputs.size()); + CHECK_EQ(1UL, outputs.size()); + CHECK_EQ(0UL, inouts.size()); size_t num = inputs[0].dims_[0]; size_t inC = inputs[0].dims_[1]; @@ -143,9 +143,9 @@ class PadGradFunc : public FunctionBase { void calc(const Arguments& inputs, const Arguments& outputs, const Arguments& inouts) override { - CHECK_EQ(1, inputs.size()); - CHECK_EQ(0, outputs.size()); - CHECK_EQ(1, inouts.size()); + CHECK_EQ(1UL, inputs.size()); + CHECK_EQ(0UL, outputs.size()); + CHECK_EQ(1UL, inouts.size()); size_t n = inouts[0].dims_[0]; size_t inC = inouts[0].dims_[1]; diff --git a/paddle/function/PadOpTest.cpp b/paddle/function/PadOpTest.cpp index c6d573c1d94537..be989807d13688 100644 --- a/paddle/function/PadOpTest.cpp +++ b/paddle/function/PadOpTest.cpp @@ -62,7 +62,7 @@ TEST(PadGrad, real) { Dims inDims{numSamples, channels, imgSizeH, imgSizeW}; Dims outDims{numSamples, channels + 5, imgSizeH + 3, imgSizeW + 5}; compare.cmpWithArg( - {Tensor(nullptr, inDims)}, {}, {Tensor(nullptr, outDims)}); + {Tensor(nullptr, outDims)}, {}, {Tensor(nullptr, inDims)}); } } } diff --git a/paddle/gserver/tests/test_LayerGrad.cpp b/paddle/gserver/tests/test_LayerGrad.cpp index 0560bb3ed91d36..8c8e876bd64fb9 100644 --- a/paddle/gserver/tests/test_LayerGrad.cpp +++ b/paddle/gserver/tests/test_LayerGrad.cpp @@ -850,15 +850,13 @@ TEST(Layer, SequenceLastInstanceLayer) { testDegradeLayer(true, "seqlastins", "non-seq"); // hasSubseq seqlastins to non-seq - testDegradeLayer(true, "seqlastins", "seq"); // hasSubseq seqlastins to - seq + testDegradeLayer(true, "seqlastins", "seq"); // hasSubseq seqlastins to seq } TEST(Layer, AverageLayer) { testDegradeLayer(false, "average", "non-seq"); // seq average to non-seq - testDegradeLayer(true, "average", "non-seq"); // hasSubseq average to - non - - seq testDegradeLayer(true, "average", "seq"); // hasSubseq average to seq + testDegradeLayer(true, "average", "non-seq"); // hasSubseq average to non-seq + testDegradeLayer(true, "average", "seq"); // hasSubseq average to seq } TEST(Layer, SequenceConcatLayer) { From 93fef79e1f5936fbe45a4474cf20cf2298c5c49d Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Mon, 9 Jan 2017 12:40:49 +0800 Subject: [PATCH 008/370] fix build --- paddle/gserver/layers/PadLayer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/paddle/gserver/layers/PadLayer.cpp b/paddle/gserver/layers/PadLayer.cpp index 62c50af32dd055..9069d382ef9273 100644 --- a/paddle/gserver/layers/PadLayer.cpp +++ b/paddle/gserver/layers/PadLayer.cpp @@ -33,9 +33,9 @@ bool PadLayer::init(const LayerMap& layerMap, : img_conf.img_size()); inDims_.push_back(img_conf.img_size()); - CHECK_EQ(2UL, pad_conf.pad_c_size()); - CHECK_EQ(2UL, pad_conf.pad_h_size()); - CHECK_EQ(2UL, pad_conf.pad_w_size()); + CHECK_EQ(2, pad_conf.pad_c_size()); + CHECK_EQ(2, pad_conf.pad_h_size()); + CHECK_EQ(2, pad_conf.pad_w_size()); padc_.push_back(pad_conf.pad_c(0)); padc_.push_back(pad_conf.pad_c(1)); padh_.push_back(pad_conf.pad_h(0)); @@ -76,7 +76,7 @@ void PadLayer::setOutDims(int batchSize) { } void PadLayer::setTensorDim(int batchSize) { - CHECK_EQ(inputLayers_.size(), 1UL); + CHECK_EQ(static_cast(inputLayers_.size()), 1); inDims_[0] = batchSize; int h = inputLayers_[0]->getOutput().getFrameHeight(); if (h != 0) inDims_[2]; From 2e47c9d828ea48b775572384260cc806674663aa Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 11 Jan 2017 17:44:18 +0800 Subject: [PATCH 009/370] Fix bug in DenseScanner of DataProviderConverter. --- paddle/py_paddle/dataprovider_converter.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/paddle/py_paddle/dataprovider_converter.py b/paddle/py_paddle/dataprovider_converter.py index 981d10afda2671..21d1cb75f4d40e 100644 --- a/paddle/py_paddle/dataprovider_converter.py +++ b/paddle/py_paddle/dataprovider_converter.py @@ -34,6 +34,10 @@ def finish_scan(self, argument): class DenseScanner(IScanner): + """ + :type __mat__: numpy.ndarray + """ + def __init__(self, input_type, pos): IScanner.__init__(self, input_type, pos) self.__mat__ = None @@ -47,6 +51,8 @@ def scan(self, dat): def finish_scan(self, argument): assert isinstance(argument, swig_paddle.Arguments) assert isinstance(self.input_type, dp2.InputType) + if self.__mat__.dtype != numpy.float32: + self.__mat__ = self.__mat__.astype(numpy.float32) m = swig_paddle.Matrix.createDenseFromNumpy(self.__mat__, True, False) argument.setSlotValue(self.pos, m) From 2629d43ff7c798f1b3cd3be3883449a4b2877c35 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Thu, 12 Jan 2017 14:49:19 +0800 Subject: [PATCH 010/370] New FunctionTest --- paddle/function/FunctionTest.h | 138 ++++++++++++++++++++++++++++++--- 1 file changed, 126 insertions(+), 12 deletions(-) diff --git a/paddle/function/FunctionTest.h b/paddle/function/FunctionTest.h index 32131037f6de4a..2847188fd67989 100644 --- a/paddle/function/FunctionTest.h +++ b/paddle/function/FunctionTest.h @@ -15,9 +15,33 @@ limitations under the License. */ #include "Function.h" #include "paddle/math/Vector.h" #include "paddle/math/tests/TensorCheck.h" +#include "paddle/testing/TestUtil.h" namespace paddle { +/** + * \brief A class for comparing CPU and GPU implementations of Function. + * + * + * Use case: + * // Initializes a test object, the corresponding cpu and gpu Function + * // are constructed according to FunctionName and FuncConfig. + * FunctionCompare test(FunctionName, FuncConfig); + * // Prepare inputs and outputs arguments. + * // Here the input and output can not contain real data, + * // only contains the argument type and shape. + * test.addInputs(input1); + * test.addInputs(input2); + * test.addOutputs(output1); + * test.addOutputs(output2); + * // Run. + * // Will according to the type and shape of arguments(inputs_/outputs_), + * // automatic initialization cpu and gpu function required arguments + * // (cpuInputs_/cpuOutputs_/gpuInputs_/gpuOutputs_). + * // Call the CPU and GPU Function calculation results. + * // Compares CPU and GPU calculation results for consistency. + * test.run(); + */ class FunctionCompare { public: FunctionCompare(const std::string& name, const FuncConfig& config) @@ -27,6 +51,32 @@ class FunctionCompare { gpu->init(config); } + void addInputs(const BufferArg& input) { inputs.push_back(input); } + + void addOutputs(const BufferArg& output) { outputs.push_back(output); } + + void run() { + // prepare cpu/gpu arguments + prepareArgs(); + + // function calculate + cpu->calc(cpuInputs, cpuOutputs); + gpu->calc(gpuInputs, gpuOutputs); + + // check outputs and inouts + auto checkArgs = [=](const BufferArgs& cpuArgs, const BufferArgs& gpuArgs) { + for (size_t i = 0; i < cpuArgs.size(); i++) { + auto cpu = cpuArgs[i]; + auto gpu = gpuArgs[i]; + CpuVector cpuVector(cpu.shape().getElements(), (real*)cpu.getData()); + GpuVector gpuVector(cpu.shape().getElements(), (real*)gpu.getData()); + + autotest::TensorCheckErr(cpuVector, gpuVector); + } + }; + checkArgs(cpuOutputs, gpuOutputs); + } +#if 0 void cmpWithArg(const Arguments& inputs, const Arguments& outputs, const Arguments& inouts) { @@ -64,11 +114,10 @@ class FunctionCompare { }; initArgs(cpuInputs, gpuInputs, inputs); initArgs(cpuOutputs, gpuOutputs, outputs); - initArgs(cpuInouts, gpuInouts, inouts); // function calculate - cpu->calc(cpuInputs, cpuOutputs, cpuInouts); - gpu->calc(gpuInputs, gpuOutputs, gpuInouts); + cpu->calc(cpuInputs, cpuOutputs); + gpu->calc(gpuInputs, gpuOutputs); // check outputs and inouts auto checkArgs = [=](const Arguments& cpuArgs, const Arguments& gpuArgs) { @@ -86,24 +135,89 @@ class FunctionCompare { } }; checkArgs(cpuOutputs, gpuOutputs); - checkArgs(cpuInouts, gpuInouts); } +#endif std::shared_ptr getCpuFunction() const { return cpu; } std::shared_ptr getGpuFunction() const { return gpu; } +protected: + void prepareArgs() { + // TODO, if inputs has data + } + + void createArg(BufferArgs& cpuArgs, BufferArgs& gpuArgs, BufferArg& arg) { + size_t size = arg.shape().getElements() * sizeOfValuType(arg.valueType()); + cpuMemory_.emplace_back(std::make_shared(size)); + gpuMemory_.emplace_back(std::make_shared(size)); + + cpuArgs.emplace_back( + BufferArg(cpuMemory_.back()->getBuf()), arg.valueType(), arg.shape()); + gpuArgs.emplace_back( + BufferArg(gpuMemory_.back()->getBuf()), arg.valueType(), arg.shape()); + } + + void createArg(BufferArgs& cpuArgs, BufferArgs& gpuArgs, SequenceArg& arg) { + size_t batchSize = arg.shape()[0]; + size_t numSeqs = batchSize / 10 + 1; + + size_t sizeId = (numSeqs + 1) * sizeOfValuType(VALUE_TYPE_INT32); + cpuMemory_.emplace_back(std::make_shared(size)); + gpuMemory_.emplace_back(std::make_shared(size)); + + TensorShape seqsId({numSeqs + 1}); + void* cpuBuffer = cpuMemory_.back()->getBuf(); + void* gpuBuffer = gpuMemory_.back()->getBuf(); + + size_t size = arg.shape().getElements() * sizeOfValuType(arg.valueType()); + cpuMemory_.emplace_back(std::make_shared(size)); + gpuMemory_.emplace_back(std::make_shared(size)); + + cpuArgs.emplace_back(SequenceArg(cpuMemory_.back()->getBuf(), + arg.valueType(), + arg.shape(), + SequenceIdArg(cpuBuffer, seqsId))); + gpuArgs.emplace_back(SequenceArg(gpuMemory_.back()->getBuf(), + arg.valueType(), + arg.shape(), + SequenceIdArg(gpuBuffer, seqsId))); + } + + // 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 = arg.data(); + int pos = 0; + size_t maxLen = 2 * batchSize / numSeqs; + for (int i = 0; i < numSeqs; ++i) { + int len = uniformRandom( + std::min(maxLen, batchSize - pos - numSeqs + i)) + + 1; + buf[i] = pos; + pos += len; + VLOG(1) << " len=" << len; + } + buf[numSeqs] = batchSize; + } + protected: std::shared_ptr cpu; std::shared_ptr gpu; - std::vector cpuMemory; - std::vector gpuMemory; - Arguments cpuInputs; - Arguments cpuOutputs; - Arguments cpuInouts; - Arguments gpuInputs; - Arguments gpuOutputs; - Arguments gpuInouts; + std::vector cpuMemory_; + std::vector gpuMemory_; + // inputs and outputs + BufferArgs inputs; + BufferArgs outputs; + BufferArgs cpuInputs_; + BufferArgs cpuOutputs_; + BufferArgs gpuInputs_; + BufferArgs gpuOutputs_; }; } // namespace paddle From fdf194aeaf6df02fde1165737def451a5fec8e73 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Thu, 12 Jan 2017 18:03:18 +0800 Subject: [PATCH 011/370] move a test case from BufferArgTest.cpp to FunctionTest.cpp --- paddle/function/BufferArgTest.cpp | 53 ------------------------------- paddle/function/FunctionTest.cpp | 52 ++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 53 deletions(-) diff --git a/paddle/function/BufferArgTest.cpp b/paddle/function/BufferArgTest.cpp index b345597435c991..1744f377808f13 100644 --- a/paddle/function/BufferArgTest.cpp +++ b/paddle/function/BufferArgTest.cpp @@ -14,9 +14,7 @@ limitations under the License. */ #include "BufferArg.h" #include -#include "Function.h" #include "paddle/math/MemoryHandle.h" -#include "paddle/math/SparseMatrix.h" namespace paddle { @@ -37,55 +35,4 @@ TEST(BufferTest, SequenceIdArg) { EXPECT_EQ(buffer.numSeqs(), 9); } -TEST(BufferTest, asArgument) { - MatrixPtr matrix = Matrix::create(100, 200); - VectorPtr vector = Vector::create(100, false); - CpuSparseMatrix sparse(200, 300, 50); - - // prepare arguments - BufferArgs argments; - argments.addArg(*matrix); - argments.addArg(*vector); - argments.addArg(sparse); - - // function - auto function = [=](const BufferArgs& inputs) { - EXPECT_EQ(inputs.size(), 3); - - // check inputs[0] - EXPECT_EQ(inputs[0].shape().ndims(), 2); - EXPECT_EQ(inputs[0].shape()[0], 100); - EXPECT_EQ(inputs[0].shape()[1], 200); - EXPECT_EQ(inputs[0].data(), matrix->getData()); - - EXPECT_EQ(inputs[0].matrix().getHeight(), - matrix->getHeight()); - EXPECT_EQ(inputs[0].matrix().getWidth(), - matrix->getWidth()); - EXPECT_EQ(inputs[0].matrix().getData(), matrix->getData()); - - // check inputs[1] - EXPECT_EQ(inputs[1].shape().ndims(), 1); - EXPECT_EQ(inputs[1].shape()[0], 100); - EXPECT_EQ(inputs[1].data(), vector->getData()); - CpuVector inVector = inputs[1].vector(); - EXPECT_EQ(inVector.getSize(), vector->getSize()); - EXPECT_EQ(inVector.getData(), vector->getData()); - - // check inputs[2] - EXPECT_EQ(inputs[2].shape().ndims(), 2); - EXPECT_EQ(inputs[2].shape()[0], 200); - EXPECT_EQ(inputs[2].shape()[1], 300); - EXPECT_EQ(inputs[2].data(), sparse.getData()); - // CHECK_EQ(inputs[2].sparse().nnz(), 50); - // CHECK_EQ(inputs[2].sparse().dataFormat(), SPARSE_CSR_FORMAT); - // CHECK_EQ(inputs[2].sparse().dataType(), SPARSE_FLOAT_VALUE); - EXPECT_EQ(inputs[2].sparse().getRowBuf(), sparse.getRows()); - EXPECT_EQ(inputs[2].sparse().getColBuf(), sparse.getCols()); - }; - - // call function - function(argments); -} - } // namespace paddle diff --git a/paddle/function/FunctionTest.cpp b/paddle/function/FunctionTest.cpp index 7ce908320a6f6f..6e44c2f5dbf347 100644 --- a/paddle/function/FunctionTest.cpp +++ b/paddle/function/FunctionTest.cpp @@ -14,6 +14,7 @@ limitations under the License. */ #include "Function.h" #include +#include "paddle/math/SparseMatrix.h" namespace paddle { @@ -56,4 +57,55 @@ TEST(Function, BufferArgs) { Function(gpuArgments); } +TEST(BufferArgs, asArgument) { + MatrixPtr matrix = Matrix::create(100, 200); + VectorPtr vector = Vector::create(100, false); + CpuSparseMatrix sparse(200, 300, 50); + + // prepare arguments + BufferArgs argments; + argments.addArg(*matrix); + argments.addArg(*vector); + argments.addArg(sparse); + + // function + auto function = [=](const BufferArgs& inputs) { + EXPECT_EQ(inputs.size(), 3); + + // check inputs[0] + EXPECT_EQ(inputs[0].shape().ndims(), 2); + EXPECT_EQ(inputs[0].shape()[0], 100); + EXPECT_EQ(inputs[0].shape()[1], 200); + EXPECT_EQ(inputs[0].data(), matrix->getData()); + + EXPECT_EQ(inputs[0].matrix().getHeight(), + matrix->getHeight()); + EXPECT_EQ(inputs[0].matrix().getWidth(), + matrix->getWidth()); + EXPECT_EQ(inputs[0].matrix().getData(), matrix->getData()); + + // check inputs[1] + EXPECT_EQ(inputs[1].shape().ndims(), 1); + EXPECT_EQ(inputs[1].shape()[0], 100); + EXPECT_EQ(inputs[1].data(), vector->getData()); + CpuVector inVector = inputs[1].vector(); + EXPECT_EQ(inVector.getSize(), vector->getSize()); + EXPECT_EQ(inVector.getData(), vector->getData()); + + // check inputs[2] + EXPECT_EQ(inputs[2].shape().ndims(), 2); + EXPECT_EQ(inputs[2].shape()[0], 200); + EXPECT_EQ(inputs[2].shape()[1], 300); + EXPECT_EQ(inputs[2].data(), sparse.getData()); + // CHECK_EQ(inputs[2].sparse().nnz(), 50); + // CHECK_EQ(inputs[2].sparse().dataFormat(), SPARSE_CSR_FORMAT); + // CHECK_EQ(inputs[2].sparse().dataType(), SPARSE_FLOAT_VALUE); + EXPECT_EQ(inputs[2].sparse().getRowBuf(), sparse.getRows()); + EXPECT_EQ(inputs[2].sparse().getColBuf(), sparse.getCols()); + }; + + // call function + function(argments); +} + } // namespace paddle From bff19f57d193f00240ff52419b2c43a7df662453 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Thu, 12 Jan 2017 20:15:59 +0800 Subject: [PATCH 012/370] Add a CheckBufferArg. It is used to check the consistency between the BufferArg type argument received by Function and the original type argument. --- paddle/function/FunctionTest.cpp | 114 ++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 39 deletions(-) diff --git a/paddle/function/FunctionTest.cpp b/paddle/function/FunctionTest.cpp index 6e44c2f5dbf347..eb05ca9a2190d5 100644 --- a/paddle/function/FunctionTest.cpp +++ b/paddle/function/FunctionTest.cpp @@ -57,55 +57,91 @@ TEST(Function, BufferArgs) { Function(gpuArgments); } -TEST(BufferArgs, asArgument) { +/** + * Some tests case are used to check the consistency between the BufferArg type + * argument received by Function and the original type argument. + * + * Use Case: + * TEST() { + * Matrix matrix(...); + * CheckBufferArg lambda = [=](const BufferArg& arg) { + * // check matrix and arg are equivalent + * EXPECT_EQ(matrix, arg); + * } + * + * BufferArgs argments{matrix...}; + * std::vector checkFunc{lambda...}; + * testBufferArgs(argments, checkFunc); + * } + */ +typedef std::function CheckBufferArg; + +void testBufferArgs(const BufferArgs& inputs, + const std::vector& check) { + EXPECT_EQ(inputs.size(), check.size()); + for (size_t i = 0; i < inputs.size(); i++) { + check[i](inputs[i]); + } +} + +TEST(Arguments, Matrix) { MatrixPtr matrix = Matrix::create(100, 200); - VectorPtr vector = Vector::create(100, false); - CpuSparseMatrix sparse(200, 300, 50); + CheckBufferArg check = [=](const BufferArg& arg) { + EXPECT_EQ(arg.shape().ndims(), 2); + EXPECT_EQ(arg.shape()[0], 100); + EXPECT_EQ(arg.shape()[1], 200); + EXPECT_EQ(arg.data(), matrix->getData()); + + EXPECT_EQ(arg.matrix().getHeight(), matrix->getHeight()); + EXPECT_EQ(arg.matrix().getWidth(), matrix->getWidth()); + EXPECT_EQ(arg.matrix().getData(), matrix->getData()); + }; - // prepare arguments BufferArgs argments; argments.addArg(*matrix); - argments.addArg(*vector); - argments.addArg(sparse); + std::vector checkFunc; + checkFunc.push_back(check); + testBufferArgs(argments, checkFunc); +} + +TEST(Arguments, Vector) { + VectorPtr vector = Vector::create(100, false); + CheckBufferArg check = [=](const BufferArg& arg) { + EXPECT_EQ(arg.shape().ndims(), 1); + EXPECT_EQ(arg.shape()[0], 100); + EXPECT_EQ(arg.data(), vector->getData()); - // function - auto function = [=](const BufferArgs& inputs) { - EXPECT_EQ(inputs.size(), 3); - - // check inputs[0] - EXPECT_EQ(inputs[0].shape().ndims(), 2); - EXPECT_EQ(inputs[0].shape()[0], 100); - EXPECT_EQ(inputs[0].shape()[1], 200); - EXPECT_EQ(inputs[0].data(), matrix->getData()); - - EXPECT_EQ(inputs[0].matrix().getHeight(), - matrix->getHeight()); - EXPECT_EQ(inputs[0].matrix().getWidth(), - matrix->getWidth()); - EXPECT_EQ(inputs[0].matrix().getData(), matrix->getData()); - - // check inputs[1] - EXPECT_EQ(inputs[1].shape().ndims(), 1); - EXPECT_EQ(inputs[1].shape()[0], 100); - EXPECT_EQ(inputs[1].data(), vector->getData()); - CpuVector inVector = inputs[1].vector(); + CpuVector inVector = arg.vector(); EXPECT_EQ(inVector.getSize(), vector->getSize()); EXPECT_EQ(inVector.getData(), vector->getData()); + }; - // check inputs[2] - EXPECT_EQ(inputs[2].shape().ndims(), 2); - EXPECT_EQ(inputs[2].shape()[0], 200); - EXPECT_EQ(inputs[2].shape()[1], 300); - EXPECT_EQ(inputs[2].data(), sparse.getData()); - // CHECK_EQ(inputs[2].sparse().nnz(), 50); - // CHECK_EQ(inputs[2].sparse().dataFormat(), SPARSE_CSR_FORMAT); - // CHECK_EQ(inputs[2].sparse().dataType(), SPARSE_FLOAT_VALUE); - EXPECT_EQ(inputs[2].sparse().getRowBuf(), sparse.getRows()); - EXPECT_EQ(inputs[2].sparse().getColBuf(), sparse.getCols()); + BufferArgs argments; + argments.addArg(*vector); + std::vector checkFunc; + checkFunc.push_back(check); + testBufferArgs(argments, checkFunc); +} + +TEST(Arguments, CpuSparseMatrix) { + CpuSparseMatrix sparse(200, 300, 50); + CheckBufferArg check = [=](const BufferArg& arg) { + EXPECT_EQ(arg.shape().ndims(), 2); + EXPECT_EQ(arg.shape()[0], 200); + EXPECT_EQ(arg.shape()[1], 300); + EXPECT_EQ(arg.data(), sparse.getData()); + // CHECK_EQ(arg.sparse().nnz(), 50); + // CHECK_EQ(arg.sparse().dataFormat(), SPARSE_CSR_FORMAT); + // CHECK_EQ(arg.sparse().dataType(), SPARSE_FLOAT_VALUE); + EXPECT_EQ(arg.sparse().getRowBuf(), sparse.getRows()); + EXPECT_EQ(arg.sparse().getColBuf(), sparse.getCols()); }; - // call function - function(argments); + BufferArgs argments; + argments.addArg(sparse); + std::vector checkFunc; + checkFunc.push_back(check); + testBufferArgs(argments, checkFunc); } } // namespace paddle From edad8a6913a10ab83fd9463c6dce92f93cb5e315 Mon Sep 17 00:00:00 2001 From: zhanghaichao Date: Thu, 12 Jan 2017 11:02:17 -0800 Subject: [PATCH 013/370] bug fix in hierarchical layer doc --- doc/howto/deep_model/rnn/hierarchical_layer_cn.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/howto/deep_model/rnn/hierarchical_layer_cn.rst b/doc/howto/deep_model/rnn/hierarchical_layer_cn.rst index 943b1d4bb84646..4b328fc9d38bc5 100644 --- a/doc/howto/deep_model/rnn/hierarchical_layer_cn.rst +++ b/doc/howto/deep_model/rnn/hierarchical_layer_cn.rst @@ -32,7 +32,7 @@ pooling_layer 的使用示例如下,详细见 :ref:`api_trainer_config_helpers - `pooling_type` 目前支持两种,分别是:MaxPooling()和AvgPooling()。 -- `agg_level=AggregateLevel.TIMESTEP` 时(默认值): +- `agg_level=AggregateLevel.EACH_TIMESTEP` 时(默认值): - 作用:双层序列经过运算变成一个0层序列,或单层序列经过运算变成一个0层序列 - 输入:一个双层序列,或一个单层序列 @@ -54,7 +54,7 @@ last_seq 的使用示例如下( :ref:`api_trainer_config_helpers_layers_first_ last = last_seq(input=layer, agg_level=AggregateLevel.EACH_SEQUENCE) -- `agg_level=AggregateLevel.TIMESTEP` 时(默认值): +- `agg_level=AggregateLevel.EACH_TIMESTEP` 时(默认值): - 作用:一个双层序列经过运算变成一个0层序列,或一个单层序列经过运算变成一个0层序列 - 输入:一个双层序列或一个单层序列 From 86fa8c05280e18c6fc4a569931d9f50fd9467546 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Thu, 5 Jan 2017 11:05:18 -0800 Subject: [PATCH 014/370] Wei Xu's comments, set up right inouts. --- paddle/function/ContextProjectionOp.cpp | 124 +++++++++++++------- paddle/function/ContextProjectionOp.h | 20 ++-- paddle/function/ContextProjectionOpGpu.cu | 25 ++-- paddle/function/ContextProjectionOpTest.cpp | 34 +++--- 4 files changed, 124 insertions(+), 79 deletions(-) diff --git a/paddle/function/ContextProjectionOp.cpp b/paddle/function/ContextProjectionOp.cpp index cb448562ebb370..8803ea78963a00 100644 --- a/paddle/function/ContextProjectionOp.cpp +++ b/paddle/function/ContextProjectionOp.cpp @@ -70,10 +70,11 @@ void ContextProjectionForward(CpuMatrix& out_mat, } /** + * \param outputs[0] output value. + * * \param inputs[0] input value. * \param inputs[1] input weight. * \param inputs[2] input sequence. - * \param outputs[0] output value. */ template class ContextProjectionForwardFunc : public FunctionBase { @@ -123,7 +124,8 @@ class ContextProjectionForwardFunc : public FunctionBase { }; template <> -void ContextProjectionBackward(CpuMatrix& out_grad_mat, +<<<<<<< HEAD +void ContextProjectionBackward(const CpuMatrix& out_grad_mat, CpuMatrix& in_grad_mat, CpuMatrix& w_grad_mat, const CpuIVector& seq_vec, @@ -176,10 +178,10 @@ void ContextProjectionBackward(CpuMatrix& out_grad_mat, } /** - * \param inputs[0] input grad. - * \param inputs[1] weight grad. - * \param inputs[2] input sequence. - * \param outputs[0] output value. + * \param inputs[0] input sequence. + * \param inputs[1] output grad. + * \param inouts[0] input grad. + * \param inouts[1] weight grad. */ template class ContextProjectionBackwardFunc : public FunctionBase { @@ -192,6 +194,7 @@ class ContextProjectionBackwardFunc : public FunctionBase { total_pad_ = config.get("total_pad"); } +<<<<<<< HEAD void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { CHECK_EQ((size_t)3, inputs.size()); CHECK_EQ((size_t)1, outputs.size()); @@ -210,6 +213,42 @@ class ContextProjectionBackwardFunc : public FunctionBase { CHECK_EQ(outputs[0].shape()[1], inputs[0].shape()[1] * context_length_); CHECK_EQ(outputs[0].getArgType(), ADD_TO); +======= + void calc(const Arguments& inputs, + const Arguments& outputs, + const Arguments& inouts) override { + CHECK_EQ(2, inputs.size()); + CHECK_EQ(0, outputs.size()); + CHECK_EQ(2, inouts.size()); + + CHECK(inputs[0].getData() && inputs[1].getData()); + CHECK_EQ(inputs[0].dims_.size(), 1); + CHECK_EQ(inputs[1].dims_.size(), 2); + CHECK_EQ(inouts[0].dims_.size(), 2); + CHECK_EQ(inouts[1].dims_.size(), 2); + + /// dim of input grad == dim of weight grad + CHECK_EQ(inouts[0].dims_[1], inouts[1].dims_[1]); + /// input grad and output grad have the same batch_size + CHECK_EQ(inouts[0].dims_[0], inputs[1].dims_[0]); + /// dim of output = dim of input * context_length + CHECK_EQ(inputs[1].dims_[1], inputs[0].dims_[1] * context_length_); + + typename SequenceT::type seq_vec( + inputs[0].dims_[0], reinterpret_cast(inputs[0].getData())); + const auto out_grad_mat = std::make_shared::type>( + inputs[1].getData(), inputs[1].dims_[0], inputs[1].dims_[1]); + auto in_grad_mat = + !inouts[0].getData() + ? nullptr + : std::make_shared::type>( + inouts[0].getData(), inouts[0].dims_[0], inouts[0].dims_[1]); + auto w_grad_mat = + !inouts[1].getData() + ? nullptr + : std::make_shared::type>( + inouts[1].getData(), inouts[1].dims_[0], inouts[1].dims_[1]); +>>>>>>> Wei Xu's comments, set up right inouts. auto out_grad_mat = outputs[0].matrix(); auto in_grad_mat = @@ -240,9 +279,9 @@ class ContextProjectionBackwardFunc : public FunctionBase { #if 0 /** - * \param inputs[0] input grad. - * \param inputs[1] input sequence. - * \param outputs[0] output grad. + * \param inouts[0] input grad. + * \param inputs[0] input sequence. + * \param inputs[1] output grad. */ template class ContextProjectionBackwardDataFunc : public FunctionBase { @@ -255,23 +294,24 @@ class ContextProjectionBackwardDataFunc : public FunctionBase { void calc(const Arguments& inputs, const Arguments& outputs, const Arguments& inouts) override { - CHECK_EQ(2, static_cast(inputs.size())); - CHECK_EQ(1, static_cast(outputs.size())); - CHECK_EQ(0, static_cast(inouts.size())); - CHECK(inputs[0].getData() && outputs[0].getData() && inputs[1].getData()); - CHECK_EQ(static_cast(outputs[0].dims_.size()), 2); - CHECK_EQ(static_cast(inputs[0].dims_.size()), 2); - CHECK_EQ(static_cast(inputs[1].dims_.size()), 1); - CHECK_EQ(outputs[0].dims_[1], inputs[0].dims_[1] * context_length_); - /// input and output has the same batch_size - CHECK_EQ(inputs[0].dims_[0], outputs[0].dims_[0]); + CHECK_EQ(2, inputs.size()); + CHECK_EQ(0, outputs.size()); + CHECK_EQ(1, inouts.size()); + + CHECK(inouts[0].getData() && inputs[0].getData() && inputs[1].getData()); + CHECK_EQ(inputs[0].dims_.size(), 1); + CHECK_EQ(inputs[1].dims_.size(), 2); + CHECK_EQ(inouts[0].dims_.size(), 2); + CHECK_EQ(inputs[1].dims_[1], inouts[0].dims_[1] * context_length_); + /// input and output grad have the same batch_size + CHECK_EQ(inouts[0].dims_[0], inputs[1].dims_[0]); - auto out_grad_mat = std::make_shared::type>( - outputs[0].getData(), outputs[0].dims_[0], outputs[0].dims_[1]); - const auto in_grad_mat = std::make_shared::type>( - inputs[0].getData(), inputs[0].dims_[0], inputs[0].dims_[1]); typename SequenceT::type seq_vec( - inputs[1].dims_[0], reinterpret_cast(inputs[1].getData())); + inputs[0].dims_[0], reinterpret_cast(inputs[0].getData())); + const auto out_grad_mat = std::make_shared::type>( + inputs[1].getData(), inputs[1].dims_[0], inputs[1].dims_[1]); + auto in_grad_mat = std::make_shared::type>( + inouts[0].getData(), inouts[0].dims_[0], inouts[0].dims_[1]); ContextProjectionBackwardData(out_grad_mat.get(), in_grad_mat.get(), @@ -286,9 +326,9 @@ class ContextProjectionBackwardDataFunc : public FunctionBase { }; /** - * \param inputs[0] weight grad. - * \param inputs[1] input sequence. - * \param outputs[0] output grad. + * \param inouts[0] weight grad. + * \param inputs[0] input sequence. + * \param inputs[1] output grad. */ template class ContextProjectionBackwardWeightFunc : public FunctionBase { @@ -303,22 +343,22 @@ class ContextProjectionBackwardWeightFunc : public FunctionBase { void calc(const Arguments& inputs, const Arguments& outputs, const Arguments& inouts) override { - CHECK_EQ(2, static_cast(inputs.size())); - CHECK_EQ(1, static_cast(outputs.size())); - CHECK_EQ(0, static_cast(inouts.size())); - - CHECK(inputs[0].getData() && outputs[0].getData() && inputs[1].getData()); - CHECK_EQ(static_cast(outputs[0].dims_.size()), 2); - CHECK_EQ(static_cast(inputs[0].dims_.size()), 2); - CHECK_EQ(static_cast(inputs[1].dims_.size()), 1); - CHECK_EQ(outputs[0].dims_[1], inputs[0].dims_[1] * context_length_); - - auto out_grad_mat = std::make_shared::type>( - outputs[0].getData(), outputs[0].dims_[0], outputs[0].dims_[1]); - auto w_grad_mat = std::make_shared::type>( - inputs[0].getData(), inputs[0].dims_[0], inputs[0].dims_[1]); + CHECK_EQ(2, inputs.size()); + CHECK_EQ(0, outputs.size()); + CHECK_EQ(1, inouts.size()); + + CHECK(inouts[0].getData() && inputs[0].getData() && inputs[1].getData()); + CHECK_EQ(inputs[0].dims_.size(), 1); + CHECK_EQ(inputs[1].dims_.size(), 2); + CHECK_EQ(inouts[0].dims_.size(), 2); + CHECK_EQ(inputs[1].dims_[1], inouts[0].dims_[1] * context_length_); + typename SequenceT::type seq_vec( - inputs[1].dims_[0], reinterpret_cast(inputs[1].getData())); + inputs[0].dims_[0], reinterpret_cast(inputs[0].getData())); + const auto out_grad_mat = std::make_shared::type>( + inputs[1].getData(), inputs[1].dims_[0], inputs[1].dims_[1]); + auto w_grad_mat = std::make_shared::type>( + inouts[0].getData(), inouts[0].dims_[0], inouts[0].dims_[1]); ContextProjectionBackwardWeight(out_grad_mat.get(), w_grad_mat.get(), diff --git a/paddle/function/ContextProjectionOp.h b/paddle/function/ContextProjectionOp.h index a558df5e072f2f..8e956c6c6fd4c5 100644 --- a/paddle/function/ContextProjectionOp.h +++ b/paddle/function/ContextProjectionOp.h @@ -21,14 +21,14 @@ namespace paddle { /** * \brief Context Projection Forward. * - * \param[out] outputs output data. - * \param[in] input input data. - * \param[in] weight input weight. - * \param[in] sequence input data. - * \param[in] context_length consecutive rows for concatenation. - * \param[in] context_start context start position. - * \param[in] begin_pad begining pad position. - * \param[in] is_padding whether padding 0 or not. + * \param[in/out] outputs output data. + * \param[in] input input data. + * \param[in] weight input weight. + * \param[in] sequence input data. + * \param[in] context_length consecutive rows for concatenation. + * \param[in] context_start context start position. + * \param[in] begin_pad begining pad position. + * \param[in] is_padding whether padding 0 or not. * */ template @@ -68,7 +68,7 @@ void ContextProjectionBackward( template void ContextProjectionBackwardData( - typename Tensor::Matrix& out_grad, + const typename Tensor::Matrix& out_grad, typename Tensor::Matrix& in_grad, const typename Tensor::Vector& sequence, size_t context_length, @@ -76,7 +76,7 @@ void ContextProjectionBackwardData( template void ContextProjectionBackwardWeight( - typename Tensor::Matrix& out_grad, + const typename Tensor::Matrix& out_grad, typename Tensor::Matrix& w_grad, const typename Tensor::Vector& seq_vec, size_t context_length, diff --git a/paddle/function/ContextProjectionOpGpu.cu b/paddle/function/ContextProjectionOpGpu.cu index 6a4a01a6510416..6194ad8e74a37e 100644 --- a/paddle/function/ContextProjectionOpGpu.cu +++ b/paddle/function/ContextProjectionOpGpu.cu @@ -138,10 +138,10 @@ void ContextProjectionForward(GpuMatrix& output, begin_pad); } -__global__ void KeContextProjectionBackwardData(real* out_grad, +__global__ void KeContextProjectionBackwardData(const real* out_grad, const int* sequence, real* in_grad, - int input_dim, + size_t input_dim, int context_length, int context_start) { int idx = threadIdx.x; @@ -152,7 +152,8 @@ __global__ void KeContextProjectionBackwardData(real* out_grad, real value = 0; int instances = seq_end - seq_start + context_length - 1; - out_grad += seq_start * input_dim * context_length; + auto out = const_cast(out_grad); + out += seq_start * input_dim * context_length; in_grad += seq_start * input_dim; for (int k = 0; k <= input_dim / block_size; k++) { if (idx < input_dim) { @@ -169,7 +170,7 @@ __global__ void KeContextProjectionBackwardData(real* out_grad, int outx = (i - context_length) < 0 ? i : (context_length - 1); int outy = (i - context_length) < 0 ? 0 : (i - (context_length - 1)); real* output_r = - out_grad + outy * input_dim * context_length + outx * input_dim; + out + outy * input_dim * context_length + outx * input_dim; for (int j = outy; j < seq_end - seq_start; j++) { value += output_r[idx]; if (j - outy == outx) break; @@ -194,7 +195,7 @@ __global__ void KeContextProjectionBackwardData(real* out_grad, * @param[in] context_start context start. * */ -void hl_context_projection_backward_data(real* out_grad, +void hl_context_projection_backward_data(const real* out_grad, const int* sequence, real* input_grad, size_t num_sequences, @@ -216,7 +217,8 @@ void hl_context_projection_backward_data(real* out_grad, } template <> -void ContextProjectionBackwardData(GpuMatrix& out_grad, +<<<<<<< HEAD +void ContextProjectionBackwardData(const GpuMatrix& out_grad, GpuMatrix& in_grad, const GpuIVector& sequence, size_t context_length, @@ -231,7 +233,7 @@ void ContextProjectionBackwardData(GpuMatrix& out_grad, } template -__global__ void KeContextProjectionBackwardWeight(real* out_grad, +__global__ void KeContextProjectionBackwardWeight(const real* out_grad, const int* sequence, real* w_grad, int num_sequences, @@ -254,7 +256,8 @@ __global__ void KeContextProjectionBackwardWeight(real* out_grad, for (int seqId = idy; seqId < num_sequences; seqId += THREADS_Y) { int seq_start = sequence[seqId]; int seq_end = sequence[seqId+1]; - output_r = out_grad + seq_start * w_dim * context_length; + output_r = const_cast(out_grad) + + seq_start * w_dim * context_length; if (context_start < 0) { if (padId + context_start < 0) { @@ -318,7 +321,7 @@ __global__ void KeContextProjectionBackwardWeight(real* out_grad, * beginning. * */ -void hl_context_projection_backward_weight(real* out_grad, +void hl_context_projection_backward_weight(const real* out_grad, const int* sequence, real* w_grad, size_t num_sequences, @@ -346,7 +349,7 @@ void hl_context_projection_backward_weight(real* out_grad, template <> void ContextProjectionBackwardWeight( - GpuMatrix& out_grad, + const GpuMatrix& out_grad, GpuMatrix& w_grad, const GpuIVector& seq_vec, size_t context_length, @@ -365,7 +368,7 @@ void ContextProjectionBackwardWeight( } template <> -void ContextProjectionBackward(GpuMatrix& out_grad, +void ContextProjectionBackward(const GpuMatrix& out_grad, GpuMatrix& in_grad, GpuMatrix& w_grad, const GpuIVector& sequence, diff --git a/paddle/function/ContextProjectionOpTest.cpp b/paddle/function/ContextProjectionOpTest.cpp index 6223d2fd23ac3b..169c1dd505a0ba 100644 --- a/paddle/function/ContextProjectionOpTest.cpp +++ b/paddle/function/ContextProjectionOpTest.cpp @@ -62,16 +62,18 @@ void testMatrixProjectionForward(int context_start, Dims{pad, input_dim}), Tensor(reinterpret_cast(cpu_seq->getData()), Dims{cpu_seq->getSize()})}, - {Tensor(cpu_out.getData(), Dims{batch_size, input_dim * context_length})}, - {}); + {}, + {Tensor(cpu_out.getData(), + Dims{batch_size, input_dim * context_length})}); compare.getGpuFunction()->calc( {Tensor(gpu_in.getData(), Dims{batch_size, input_dim}), Tensor(gpu_weight ? gpu_weight->getData() : nullptr, Dims{pad, input_dim}), Tensor(reinterpret_cast(gpu_seq->getData()), Dims{gpu_seq->getSize()})}, - {Tensor(gpu_out.getData(), Dims{batch_size, input_dim * context_length})}, - {}); + {}, + {Tensor(gpu_out.getData(), + Dims{batch_size, input_dim * context_length})}); autotest::TensorCheckEqual(cpu_out, gpu_out); } @@ -118,24 +120,24 @@ void testMatrixProjectionBackward(int context_start, } compare.getCpuFunction()->calc( + {Tensor(reinterpret_cast(cpu_seq->getData()), + Dims{cpu_seq->getSize()}), + Tensor(cpu_out_grad.getData(), + Dims{batch_size, input_dim * context_length})}, + {}, {Tensor(cpu_in_grad.getData(), Dims{batch_size, input_dim}), Tensor(cpu_w_grad ? cpu_w_grad->getData() : nullptr, - Dims{pad, input_dim}), - Tensor(reinterpret_cast(cpu_seq->getData()), - Dims{cpu_seq->getSize()})}, - {Tensor(cpu_out_grad.getData(), - Dims{batch_size, input_dim * context_length})}, - {}); + Dims{pad, input_dim})}); compare.getGpuFunction()->calc( + {Tensor(reinterpret_cast(gpu_seq->getData()), + Dims{gpu_seq->getSize()}), + Tensor(gpu_out_grad.getData(), + Dims{batch_size, input_dim * context_length})}, + {}, {Tensor(gpu_in_grad.getData(), Dims{batch_size, input_dim}), Tensor(gpu_w_grad ? gpu_w_grad->getData() : nullptr, - Dims{pad, input_dim}), - Tensor(reinterpret_cast(gpu_seq->getData()), - Dims{gpu_seq->getSize()})}, - {Tensor(gpu_out_grad.getData(), - Dims{batch_size, input_dim * context_length})}, - {}); + Dims{pad, input_dim})}); autotest::TensorCheckErr(cpu_in_grad, gpu_in_grad); if (is_padding) { From df66957ec32f38b45b3e7274ef8f99699391854f Mon Sep 17 00:00:00 2001 From: xutianbing Date: Thu, 5 Jan 2017 11:14:51 -0800 Subject: [PATCH 015/370] clean a little bit code. --- paddle/function/ContextProjectionOp.cpp | 2 +- paddle/function/ContextProjectionOpGpu.cu | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/paddle/function/ContextProjectionOp.cpp b/paddle/function/ContextProjectionOp.cpp index 8803ea78963a00..f1e42cad7259e3 100644 --- a/paddle/function/ContextProjectionOp.cpp +++ b/paddle/function/ContextProjectionOp.cpp @@ -232,7 +232,7 @@ class ContextProjectionBackwardFunc : public FunctionBase { /// input grad and output grad have the same batch_size CHECK_EQ(inouts[0].dims_[0], inputs[1].dims_[0]); /// dim of output = dim of input * context_length - CHECK_EQ(inputs[1].dims_[1], inputs[0].dims_[1] * context_length_); + CHECK_EQ(inputs[1].dims_[1], inouts[0].dims_[1] * context_length_); typename SequenceT::type seq_vec( inputs[0].dims_[0], reinterpret_cast(inputs[0].getData())); diff --git a/paddle/function/ContextProjectionOpGpu.cu b/paddle/function/ContextProjectionOpGpu.cu index 6194ad8e74a37e..c5a636dce8ea31 100644 --- a/paddle/function/ContextProjectionOpGpu.cu +++ b/paddle/function/ContextProjectionOpGpu.cu @@ -256,7 +256,7 @@ __global__ void KeContextProjectionBackwardWeight(const real* out_grad, for (int seqId = idy; seqId < num_sequences; seqId += THREADS_Y) { int seq_start = sequence[seqId]; int seq_end = sequence[seqId+1]; - output_r = const_cast(out_grad) + output_r = const_cast(out_grad) + seq_start * w_dim * context_length; if (context_start < 0) { From 1482ec430a918cc5f9b44c3acf9d60d895c05b26 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Sat, 7 Jan 2017 13:57:31 -0800 Subject: [PATCH 016/370] some comments. --- paddle/function/ContextProjectionOp.cpp | 88 ++++++++++++------------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/paddle/function/ContextProjectionOp.cpp b/paddle/function/ContextProjectionOp.cpp index f1e42cad7259e3..75c09108b1bb8d 100644 --- a/paddle/function/ContextProjectionOp.cpp +++ b/paddle/function/ContextProjectionOp.cpp @@ -18,6 +18,10 @@ limitations under the License. */ namespace paddle { +/** + * Context Projection Forward with CPU Matrix Device. + * + */ template <> void ContextProjectionForward(CpuMatrix& out_mat, const CpuMatrix& input_mat, @@ -70,11 +74,29 @@ void ContextProjectionForward(CpuMatrix& out_mat, } /** - * \param outputs[0] output value. + * Paddle Function for Context Projection Forward. + * Calculate the value for the output layer with context projection. + * + * What is Context Projection? + * For example, assumed input (x) has 4 words and the dimension of each word + * representation is 2. If we use zero to pad instead of learned weight to pad, + * and the context_lenth is 3, the output (y) is: * - * \param inputs[0] input value. - * \param inputs[1] input weight. - * \param inputs[2] input sequence. + * @code + * x = [a1, a2; + * b1, b2; + * c1, c2; + * d1, d2] + * y = [0, 0, a1, a2, b1, b2; + * a1, a2, b1, b2, c1, c2; + * b1, b2, c1, c2, d1, d2; + * c1, c2, d1, d2, 0, 0] + * @endcode + * + * \param outputs[0] output value. + * \param inputs[0] input value. + * \param inputs[1] input weight. + * \param inputs[2] input sequence. */ template class ContextProjectionForwardFunc : public FunctionBase { @@ -123,6 +145,10 @@ class ContextProjectionForwardFunc : public FunctionBase { size_t begin_pad_; }; +/** + * Context Projection Backward with CPU Matrix Device. + * + */ template <> <<<<<<< HEAD void ContextProjectionBackward(const CpuMatrix& out_grad_mat, @@ -178,10 +204,13 @@ void ContextProjectionBackward(const CpuMatrix& out_grad_mat, } /** - * \param inputs[0] input sequence. - * \param inputs[1] output grad. - * \param inouts[0] input grad. - * \param inouts[1] weight grad. + * Context Projection Backward Function. + * Update the weight gradient and input layer gradient with backprop + * + * \param inputs[0] input sequence. + * \param inputs[1] output grad. + * \param inouts[0] input grad. + * \param inouts[1] weight grad. */ template class ContextProjectionBackwardFunc : public FunctionBase { @@ -194,7 +223,6 @@ class ContextProjectionBackwardFunc : public FunctionBase { total_pad_ = config.get("total_pad"); } -<<<<<<< HEAD void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { CHECK_EQ((size_t)3, inputs.size()); CHECK_EQ((size_t)1, outputs.size()); @@ -213,42 +241,6 @@ class ContextProjectionBackwardFunc : public FunctionBase { CHECK_EQ(outputs[0].shape()[1], inputs[0].shape()[1] * context_length_); CHECK_EQ(outputs[0].getArgType(), ADD_TO); -======= - void calc(const Arguments& inputs, - const Arguments& outputs, - const Arguments& inouts) override { - CHECK_EQ(2, inputs.size()); - CHECK_EQ(0, outputs.size()); - CHECK_EQ(2, inouts.size()); - - CHECK(inputs[0].getData() && inputs[1].getData()); - CHECK_EQ(inputs[0].dims_.size(), 1); - CHECK_EQ(inputs[1].dims_.size(), 2); - CHECK_EQ(inouts[0].dims_.size(), 2); - CHECK_EQ(inouts[1].dims_.size(), 2); - - /// dim of input grad == dim of weight grad - CHECK_EQ(inouts[0].dims_[1], inouts[1].dims_[1]); - /// input grad and output grad have the same batch_size - CHECK_EQ(inouts[0].dims_[0], inputs[1].dims_[0]); - /// dim of output = dim of input * context_length - CHECK_EQ(inputs[1].dims_[1], inouts[0].dims_[1] * context_length_); - - typename SequenceT::type seq_vec( - inputs[0].dims_[0], reinterpret_cast(inputs[0].getData())); - const auto out_grad_mat = std::make_shared::type>( - inputs[1].getData(), inputs[1].dims_[0], inputs[1].dims_[1]); - auto in_grad_mat = - !inouts[0].getData() - ? nullptr - : std::make_shared::type>( - inouts[0].getData(), inouts[0].dims_[0], inouts[0].dims_[1]); - auto w_grad_mat = - !inouts[1].getData() - ? nullptr - : std::make_shared::type>( - inouts[1].getData(), inouts[1].dims_[0], inouts[1].dims_[1]); ->>>>>>> Wei Xu's comments, set up right inouts. auto out_grad_mat = outputs[0].matrix(); auto in_grad_mat = @@ -279,6 +271,9 @@ class ContextProjectionBackwardFunc : public FunctionBase { #if 0 /** + * Context Projection Backward Data Function. + * Update gradient of the input layer with backprop. + * * \param inouts[0] input grad. * \param inputs[0] input sequence. * \param inputs[1] output grad. @@ -326,6 +321,9 @@ class ContextProjectionBackwardDataFunc : public FunctionBase { }; /** + * Context Projection Backward Weight Function. + * Update weight gradient with backprop. + * * \param inouts[0] weight grad. * \param inputs[0] input sequence. * \param inputs[1] output grad. From 23ac0b78cb472e2f5007531427e142d553831e91 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Tue, 10 Jan 2017 16:13:41 -0800 Subject: [PATCH 017/370] merge Daoyuan's FuncArgs, pass the ContextProjection test. --- paddle/function/CMakeLists.txt | 2 +- paddle/function/ContextProjectionOp.cpp | 181 ++++---------------- paddle/function/ContextProjectionOp.h | 2 +- paddle/function/ContextProjectionOpGpu.cu | 1 - paddle/function/ContextProjectionOpTest.cpp | 75 ++++---- paddle/function/FunctionTest.h | 72 ++------ paddle/gserver/layers/ContextProjection.cpp | 15 +- 7 files changed, 101 insertions(+), 247 deletions(-) diff --git a/paddle/function/CMakeLists.txt b/paddle/function/CMakeLists.txt index 75a2acc55ec3d3..39733479cc55d8 100644 --- a/paddle/function/CMakeLists.txt +++ b/paddle/function/CMakeLists.txt @@ -24,7 +24,7 @@ if(WITH_TESTING) add_simple_unittest(TensorTypeTest) add_simple_unittest(BufferArgTest) add_simple_unittest(FunctionTest) - # add_simple_unittest(ContextProjectionOpTest) + add_simple_unittest(ContextProjectionOpTest) endif() endif() diff --git a/paddle/function/ContextProjectionOp.cpp b/paddle/function/ContextProjectionOp.cpp index 75c09108b1bb8d..42b78eacfd59d1 100644 --- a/paddle/function/ContextProjectionOp.cpp +++ b/paddle/function/ContextProjectionOp.cpp @@ -125,11 +125,11 @@ class ContextProjectionForwardFunc : public FunctionBase { CHECK_EQ(outputs[0].getArgType(), ADD_TO); auto out_mat = outputs[0].matrix(); - auto in_mat = inputs[0].matrix(); - auto w_mat = !inputs[1].data() - ? typename Tensor::Matrix(nullptr, 0, 0) - : inputs[1].matrix(); - auto seq_vec = inputs[2].vector(); + const auto in_mat = inputs[0].matrix(); + const auto w_mat = + !inputs[1].data() ? typename Tensor::Matrix(nullptr, 0, 0) + : inputs[1].matrix(); + const auto seq_vec = inputs[2].vector(); ContextProjectionForward(out_mat, in_mat, w_mat, @@ -150,7 +150,6 @@ class ContextProjectionForwardFunc : public FunctionBase { * */ template <> -<<<<<<< HEAD void ContextProjectionBackward(const CpuMatrix& out_grad_mat, CpuMatrix& in_grad_mat, CpuMatrix& w_grad_mat, @@ -174,7 +173,8 @@ void ContextProjectionBackward(const CpuMatrix& out_grad_mat, int64_t pad_size = std::min(starts[i] - begin, starts[i + 1] - starts[i]); if (is_padding && w_grad_mat) { - MatrixPtr mat = out_grad_mat.subMatrix(starts[i], pad_size); + MatrixPtr mat = const_cast(out_grad_mat) + .subMatrix(starts[i], pad_size); MatrixPtr sub = w_grad_mat.subMatrix(j, pad_size); sub->addAtOffset(*mat, j * input_dim); } @@ -185,8 +185,8 @@ void ContextProjectionBackward(const CpuMatrix& out_grad_mat, int64_t pad_size = std::min(end - starts[i + 1], starts[i + 1] - starts[i]); if (is_padding && w_grad_mat) { - MatrixPtr mat = - out_grad_mat.subMatrix(starts[i + 1] - pad_size, pad_size); + MatrixPtr mat = const_cast(out_grad_mat) + .subMatrix(starts[i + 1] - pad_size, pad_size); MatrixPtr sub = w_grad_mat.subMatrix( begin_pad + context_start + j - pad_size, pad_size); sub->addAtOffset(*mat, j * input_dim); @@ -197,7 +197,8 @@ void ContextProjectionBackward(const CpuMatrix& out_grad_mat, if (end <= begin) continue; if (!in_grad_mat) continue; MatrixPtr src = in_grad_mat.subMatrix(begin, end - begin); - MatrixPtr dst = out_grad_mat.subMatrix(dst_begin, dst_end - dst_begin); + MatrixPtr dst = const_cast(out_grad_mat) + .subMatrix(dst_begin, dst_end - dst_begin); src->addAtOffset(*dst, j * input_dim); } } @@ -207,10 +208,10 @@ void ContextProjectionBackward(const CpuMatrix& out_grad_mat, * Context Projection Backward Function. * Update the weight gradient and input layer gradient with backprop * - * \param inputs[0] input sequence. - * \param inputs[1] output grad. - * \param inouts[0] input grad. - * \param inouts[1] weight grad. + * \param inputs[0] input sequence. + * \param inputs[1] output layer grad. + * \param outputs[0] input layer grad. + * \param outputs[1] weight grad. */ template class ContextProjectionBackwardFunc : public FunctionBase { @@ -224,32 +225,34 @@ class ContextProjectionBackwardFunc : public FunctionBase { } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK_EQ((size_t)3, inputs.size()); - CHECK_EQ((size_t)1, outputs.size()); + CHECK_EQ((size_t)2, inputs.size()); + CHECK_EQ((size_t)2, outputs.size()); - CHECK(outputs[0].data() && inputs[2].data()); - CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); - CHECK_EQ(inputs[0].shape().ndims(), (size_t)2); + CHECK(inputs[0].data() && inputs[1].data()); + CHECK_EQ(inputs[0].shape().ndims(), (size_t)1); CHECK_EQ(inputs[1].shape().ndims(), (size_t)2); - CHECK_EQ(inputs[2].shape().ndims(), (size_t)1); + CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); + CHECK_EQ(outputs[1].shape().ndims(), (size_t)2); - /// dim of input == dim of weight - CHECK_EQ(inputs[0].shape()[1], inputs[1].shape()[1]); - /// input and output has the same batch_size - CHECK_EQ(inputs[0].shape()[0], outputs[0].shape()[0]); - /// dim of output = dim of input * context_length - CHECK_EQ(outputs[0].shape()[1], inputs[0].shape()[1] * context_length_); + /// dim of input grad == dim of weight + CHECK_EQ(outputs[0].shape()[1], outputs[1].shape()[1]); + /// input and output grad has the same batch_size + CHECK_EQ(outputs[0].shape()[0], inputs[1].shape()[0]); + /// dim of output val = dim of input grad * context_length + CHECK_EQ(inputs[1].shape()[1], outputs[0].shape()[1] * context_length_); CHECK_EQ(outputs[0].getArgType(), ADD_TO); + CHECK_EQ(outputs[1].getArgType(), ADD_TO); - auto out_grad_mat = outputs[0].matrix(); + const auto seq_vec = inputs[0].vector(); + const auto out_grad_mat = inputs[1].matrix(); auto in_grad_mat = - !inputs[0].data() ? typename Tensor::Matrix(nullptr, 0, 0) - : inputs[0].matrix(); - auto w_grad_mat = !inputs[1].data() + !outputs[0].data() + ? typename Tensor::Matrix(nullptr, 0, 0) + : outputs[0].matrix(); + auto w_grad_mat = !outputs[1].data() ? typename Tensor::Matrix(nullptr, 0, 0) - : inputs[1].matrix(); - auto seq_vec = inputs[2].vector(); + : outputs[1].matrix(); ContextProjectionBackward(out_grad_mat, in_grad_mat, w_grad_mat, @@ -269,112 +272,6 @@ class ContextProjectionBackwardFunc : public FunctionBase { size_t total_pad_; }; -#if 0 -/** - * Context Projection Backward Data Function. - * Update gradient of the input layer with backprop. - * - * \param inouts[0] input grad. - * \param inputs[0] input sequence. - * \param inputs[1] output grad. - */ -template -class ContextProjectionBackwardDataFunc : public FunctionBase { -public: - void init(const FuncConfig& config) override { - context_length_ = config.get("context_length"); - context_start_ = config.get("context_start"); - } - - void calc(const Arguments& inputs, - const Arguments& outputs, - const Arguments& inouts) override { - CHECK_EQ(2, inputs.size()); - CHECK_EQ(0, outputs.size()); - CHECK_EQ(1, inouts.size()); - - CHECK(inouts[0].getData() && inputs[0].getData() && inputs[1].getData()); - CHECK_EQ(inputs[0].dims_.size(), 1); - CHECK_EQ(inputs[1].dims_.size(), 2); - CHECK_EQ(inouts[0].dims_.size(), 2); - CHECK_EQ(inputs[1].dims_[1], inouts[0].dims_[1] * context_length_); - /// input and output grad have the same batch_size - CHECK_EQ(inouts[0].dims_[0], inputs[1].dims_[0]); - - typename SequenceT::type seq_vec( - inputs[0].dims_[0], reinterpret_cast(inputs[0].getData())); - const auto out_grad_mat = std::make_shared::type>( - inputs[1].getData(), inputs[1].dims_[0], inputs[1].dims_[1]); - auto in_grad_mat = std::make_shared::type>( - inouts[0].getData(), inouts[0].dims_[0], inouts[0].dims_[1]); - - ContextProjectionBackwardData(out_grad_mat.get(), - in_grad_mat.get(), - seq_vec, - context_length_, - context_start_); - } - -private: - size_t context_length_; - int context_start_; -}; - -/** - * Context Projection Backward Weight Function. - * Update weight gradient with backprop. - * - * \param inouts[0] weight grad. - * \param inputs[0] input sequence. - * \param inputs[1] output grad. - */ -template -class ContextProjectionBackwardWeightFunc : public FunctionBase { -public: - void init(const FuncConfig& config) override { - context_length_ = config.get("context_length"); - context_start_ = config.get("context_start"); - begin_pad_ = config.get("begin_pad"); - total_pad_ = config.get("total_pad"); - } - - void calc(const Arguments& inputs, - const Arguments& outputs, - const Arguments& inouts) override { - CHECK_EQ(2, inputs.size()); - CHECK_EQ(0, outputs.size()); - CHECK_EQ(1, inouts.size()); - - CHECK(inouts[0].getData() && inputs[0].getData() && inputs[1].getData()); - CHECK_EQ(inputs[0].dims_.size(), 1); - CHECK_EQ(inputs[1].dims_.size(), 2); - CHECK_EQ(inouts[0].dims_.size(), 2); - CHECK_EQ(inputs[1].dims_[1], inouts[0].dims_[1] * context_length_); - - typename SequenceT::type seq_vec( - inputs[0].dims_[0], reinterpret_cast(inputs[0].getData())); - const auto out_grad_mat = std::make_shared::type>( - inputs[1].getData(), inputs[1].dims_[0], inputs[1].dims_[1]); - auto w_grad_mat = std::make_shared::type>( - inouts[0].getData(), inouts[0].dims_[0], inouts[0].dims_[1]); - - ContextProjectionBackwardWeight(out_grad_mat.get(), - w_grad_mat.get(), - seq_vec, - context_length_, - context_start_, - total_pad_, - begin_pad_); - } - -private: - size_t context_length_; - int context_start_; - size_t begin_pad_; - size_t total_pad_; -}; -#endif - REGISTER_TYPED_FUNC(ContextProjectionForward, CPU, ContextProjectionForwardFunc); @@ -388,13 +285,5 @@ REGISTER_TYPED_FUNC(ContextProjectionForward, REGISTER_TYPED_FUNC(ContextProjectionBackward, GPU, ContextProjectionBackwardFunc); -#if 0 -REGISTER_TYPED_FUNC(ContextProjectionBackwardData, - GPU, - ContextProjectionBackwardDataFunc); -REGISTER_TYPED_FUNC(ContextProjectionBackwardWeight, - GPU, - ContextProjectionBackwardWeightFunc); -#endif #endif } // namespace paddle diff --git a/paddle/function/ContextProjectionOp.h b/paddle/function/ContextProjectionOp.h index 8e956c6c6fd4c5..2bdd47e4e9b024 100644 --- a/paddle/function/ContextProjectionOp.h +++ b/paddle/function/ContextProjectionOp.h @@ -56,7 +56,7 @@ void ContextProjectionForward( */ template void ContextProjectionBackward( - typename Tensor::Matrix& out_grad, + const typename Tensor::Matrix& out_grad, typename Tensor::Matrix& in_grad, typename Tensor::Matrix& w_grad, const typename Tensor::Vector& seq_vec, diff --git a/paddle/function/ContextProjectionOpGpu.cu b/paddle/function/ContextProjectionOpGpu.cu index c5a636dce8ea31..1a5b4042402df3 100644 --- a/paddle/function/ContextProjectionOpGpu.cu +++ b/paddle/function/ContextProjectionOpGpu.cu @@ -217,7 +217,6 @@ void hl_context_projection_backward_data(const real* out_grad, } template <> -<<<<<<< HEAD void ContextProjectionBackwardData(const GpuMatrix& out_grad, GpuMatrix& in_grad, const GpuIVector& sequence, diff --git a/paddle/function/ContextProjectionOpTest.cpp b/paddle/function/ContextProjectionOpTest.cpp index 169c1dd505a0ba..c8d5b4f2786f76 100644 --- a/paddle/function/ContextProjectionOpTest.cpp +++ b/paddle/function/ContextProjectionOpTest.cpp @@ -56,24 +56,25 @@ void testMatrixProjectionForward(int context_start, cpu_out.randomizeUniform(); gpu_out.copyFrom(cpu_out); - compare.getCpuFunction()->calc( - {Tensor(cpu_in.getData(), Dims{batch_size, input_dim}), - Tensor(cpu_weight ? cpu_weight->getData() : nullptr, - Dims{pad, input_dim}), - Tensor(reinterpret_cast(cpu_seq->getData()), - Dims{cpu_seq->getSize()})}, - {}, - {Tensor(cpu_out.getData(), - Dims{batch_size, input_dim * context_length})}); - compare.getGpuFunction()->calc( - {Tensor(gpu_in.getData(), Dims{batch_size, input_dim}), - Tensor(gpu_weight ? gpu_weight->getData() : nullptr, - Dims{pad, input_dim}), - Tensor(reinterpret_cast(gpu_seq->getData()), - Dims{gpu_seq->getSize()})}, - {}, - {Tensor(gpu_out.getData(), - Dims{batch_size, input_dim * context_length})}); + BufferArgs cpu_inputs; + BufferArgs cpu_outputs; + cpu_inputs.addArg(cpu_in); + cpu_inputs.addArg(cpu_weight ? *cpu_weight + : CpuMatrix(nullptr, 0, input_dim)); + cpu_inputs.addArg(*cpu_seq); + cpu_outputs.addArg(cpu_out, ADD_TO); + + compare.getCpuFunction()->calc(cpu_inputs, cpu_outputs); + + BufferArgs gpu_inputs; + BufferArgs gpu_outputs; + gpu_inputs.addArg(gpu_in); + gpu_inputs.addArg(gpu_weight ? *gpu_weight + : GpuMatrix(nullptr, 0, input_dim)); + gpu_inputs.addArg(*gpu_seq); + gpu_outputs.addArg(gpu_out, ADD_TO); + + compare.getGpuFunction()->calc(gpu_inputs, gpu_outputs); autotest::TensorCheckEqual(cpu_out, gpu_out); } @@ -119,25 +120,25 @@ void testMatrixProjectionBackward(int context_start, gpu_w_grad->copyFrom(*cpu_w_grad); } - compare.getCpuFunction()->calc( - {Tensor(reinterpret_cast(cpu_seq->getData()), - Dims{cpu_seq->getSize()}), - Tensor(cpu_out_grad.getData(), - Dims{batch_size, input_dim * context_length})}, - {}, - {Tensor(cpu_in_grad.getData(), Dims{batch_size, input_dim}), - Tensor(cpu_w_grad ? cpu_w_grad->getData() : nullptr, - Dims{pad, input_dim})}); - - compare.getGpuFunction()->calc( - {Tensor(reinterpret_cast(gpu_seq->getData()), - Dims{gpu_seq->getSize()}), - Tensor(gpu_out_grad.getData(), - Dims{batch_size, input_dim * context_length})}, - {}, - {Tensor(gpu_in_grad.getData(), Dims{batch_size, input_dim}), - Tensor(gpu_w_grad ? gpu_w_grad->getData() : nullptr, - Dims{pad, input_dim})}); + BufferArgs cpu_inputs; + BufferArgs cpu_outputs; + cpu_inputs.addArg(*cpu_seq); + cpu_inputs.addArg(cpu_out_grad); + cpu_outputs.addArg(cpu_in_grad, 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_seq); + gpu_inputs.addArg(gpu_out_grad); + gpu_outputs.addArg(gpu_in_grad, 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) { diff --git a/paddle/function/FunctionTest.h b/paddle/function/FunctionTest.h index 32131037f6de4a..da4c0f4f077b8d 100644 --- a/paddle/function/FunctionTest.h +++ b/paddle/function/FunctionTest.h @@ -27,66 +27,28 @@ class FunctionCompare { gpu->init(config); } - void cmpWithArg(const Arguments& inputs, - const Arguments& outputs, - const Arguments& inouts) { + void cmpWithArg(const BufferArgs& inputs, + const BufferArgs& outputs, + const BufferArgs& inouts) { // init cpu and gpu arguments auto initArgs = [=]( - Arguments& cpuArgs, Arguments& gpuArgs, const Arguments& inArgs) { - for (const auto arg : inArgs) { - size_t size = sizeof(real); - for (const auto dim : arg.dims_) { - size *= dim; - } - if (arg.getData()) { - // todo(tianbing), waste unnecessary mem here - cpuMemory.emplace_back(std::make_shared(size)); - gpuMemory.emplace_back(std::make_shared(size)); - cpuArgs.emplace_back(Tensor((real*)arg.getData(), arg.dims_)); - gpuArgs.emplace_back(Tensor((real*)arg.getData(), arg.dims_)); - // already init outside - } else { - cpuMemory.emplace_back(std::make_shared(size)); - gpuMemory.emplace_back(std::make_shared(size)); - cpuArgs.emplace_back( - Tensor((real*)cpuMemory.back()->getBuf(), arg.dims_)); - gpuArgs.emplace_back( - Tensor((real*)gpuMemory.back()->getBuf(), arg.dims_)); - // will use an api to refactor this code. - CpuVector cpuVector(size / sizeof(real), - (real*)cpuArgs.back().getData()); - GpuVector gpuVector(size / sizeof(real), - (real*)gpuArgs.back().getData()); - cpuVector.uniform(0.001, 1); - gpuVector.copyFrom(cpuVector); - } - } + BufferArgs& cpuArgs, BufferArgs& gpuArgs, const BufferArgs& inArgs) { + /// leave it empty to pass the compile of ContextProjectionTest + /// Daoyuan is working on FunctionTest + /// and I will further merge with it }; initArgs(cpuInputs, gpuInputs, inputs); initArgs(cpuOutputs, gpuOutputs, outputs); - initArgs(cpuInouts, gpuInouts, inouts); // function calculate - cpu->calc(cpuInputs, cpuOutputs, cpuInouts); - gpu->calc(gpuInputs, gpuOutputs, gpuInouts); + cpu->calc(cpuInputs, cpuOutputs); + gpu->calc(gpuInputs, gpuOutputs); // check outputs and inouts - auto checkArgs = [=](const Arguments& cpuArgs, const Arguments& gpuArgs) { - for (size_t i = 0; i < cpuArgs.size(); i++) { - auto cpu = cpuArgs[i]; - auto gpu = gpuArgs[i]; - size_t size = 1; - for (auto dim : cpu.dims_) { - size *= dim; - } - CpuVector cpuVector(size, (real*)cpu.getData()); - GpuVector gpuVector(size, (real*)gpu.getData()); - - autotest::TensorCheckErr(cpuVector, gpuVector); - } + auto checkArgs = [=](const BufferArgs& cpuArgs, const BufferArgs& gpuArgs) { + /// leave it open }; checkArgs(cpuOutputs, gpuOutputs); - checkArgs(cpuInouts, gpuInouts); } std::shared_ptr getCpuFunction() const { return cpu; } @@ -98,12 +60,12 @@ class FunctionCompare { std::shared_ptr gpu; std::vector cpuMemory; std::vector gpuMemory; - Arguments cpuInputs; - Arguments cpuOutputs; - Arguments cpuInouts; - Arguments gpuInputs; - Arguments gpuOutputs; - Arguments gpuInouts; + BufferArgs cpuInputs; + BufferArgs cpuOutputs; + BufferArgs cpuInouts; + BufferArgs gpuInputs; + BufferArgs gpuOutputs; + BufferArgs gpuInouts; }; } // namespace paddle diff --git a/paddle/gserver/layers/ContextProjection.cpp b/paddle/gserver/layers/ContextProjection.cpp index ebcc87cbf48a3c..def7c15ca82756 100644 --- a/paddle/gserver/layers/ContextProjection.cpp +++ b/paddle/gserver/layers/ContextProjection.cpp @@ -166,13 +166,16 @@ void ContextProjection::backward(const UpdateCallback& callback) { BufferArgs inputs; BufferArgs outputs; - inputs.addArg(CpuMatrix( - in_->grad ? in_->grad->getData() : nullptr, batch_size, input_dim)); - inputs.addArg(CpuMatrix(w_ptr ? w_ptr->getData() : nullptr, - w_ptr ? w_ptr->getHeight() : 0, - input_dim)); inputs.addArg(*in_->sequenceStartPositions->getVector(useGpu_)); - outputs.addArg(*out_->grad, ADD_TO); + inputs.addArg(*out_->grad); + outputs.addArg( + CpuMatrix( + in_->grad ? in_->grad->getData() : nullptr, batch_size, input_dim), + ADD_TO); + outputs.addArg(CpuMatrix(w_ptr ? w_ptr->getData() : nullptr, + w_ptr ? w_ptr->getHeight() : 0, + input_dim), + ADD_TO); backward_[0]->calc(inputs, outputs); if (config_.trainable_padding()) { From 9edfd2003153dd122b01300c3973249be1abd8c1 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Tue, 10 Jan 2017 20:10:16 -0800 Subject: [PATCH 018/370] use Daoyuan's SequenceArg. --- paddle/function/BufferArg.h | 3 ++- paddle/function/ContextProjectionOp.cpp | 26 ++++++++++----------- paddle/function/ContextProjectionOpTest.cpp | 6 ++--- paddle/function/Function.cpp | 6 +++++ paddle/function/Function.h | 4 ++++ paddle/gserver/layers/ContextProjection.cpp | 3 +-- 6 files changed, 28 insertions(+), 20 deletions(-) diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index 12352ba29e3392..f3a4350e12df34 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -190,7 +190,7 @@ class SequenceIdArg : public BufferArg { size_t numSeqs_; }; -// sequence data +// sequence data {seqId(vec), buf(matrix)} class SequenceArg : public BufferArg { public: SequenceArg(void* buf, @@ -210,6 +210,7 @@ class SequenceArg : public BufferArg { void* getIdBuf() const { return startPositions_.data(); } size_t numSeqs() const { return startPositions_.numSeqs(); } + const SequenceIdArg& getSequenceIds() const { return startPositions_; } private: SequenceIdArg startPositions_; diff --git a/paddle/function/ContextProjectionOp.cpp b/paddle/function/ContextProjectionOp.cpp index 42b78eacfd59d1..177708d00f83c7 100644 --- a/paddle/function/ContextProjectionOp.cpp +++ b/paddle/function/ContextProjectionOp.cpp @@ -17,7 +17,6 @@ limitations under the License. */ #include "paddle/math/Vector.h" namespace paddle { - /** * Context Projection Forward with CPU Matrix Device. * @@ -208,10 +207,10 @@ void ContextProjectionBackward(const CpuMatrix& out_grad_mat, * Context Projection Backward Function. * Update the weight gradient and input layer gradient with backprop * - * \param inputs[0] input sequence. - * \param inputs[1] output layer grad. - * \param outputs[0] input layer grad. - * \param outputs[1] weight grad. + * \param inputs[0].seq input sequence. + * \param inputs[0].matrix output layer grad. + * \param outputs[0] input layer grad. + * \param outputs[1] weight grad. */ template class ContextProjectionBackwardFunc : public FunctionBase { @@ -225,27 +224,28 @@ class ContextProjectionBackwardFunc : public FunctionBase { } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK_EQ((size_t)2, inputs.size()); + CHECK_EQ((size_t)1, inputs.size()); CHECK_EQ((size_t)2, outputs.size()); - CHECK(inputs[0].data() && inputs[1].data()); - CHECK_EQ(inputs[0].shape().ndims(), (size_t)1); - CHECK_EQ(inputs[1].shape().ndims(), (size_t)2); + const auto seqArg = dynamic_cast(inputs[0]); + CHECK(seqArg.data() && inputs[0].data()); + CHECK_EQ(seqArg.shape().ndims(), (size_t)2); + CHECK_EQ(seqArg.getSequenceIds().shape().ndims(), (size_t)1); CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); CHECK_EQ(outputs[1].shape().ndims(), (size_t)2); /// dim of input grad == dim of weight CHECK_EQ(outputs[0].shape()[1], outputs[1].shape()[1]); /// input and output grad has the same batch_size - CHECK_EQ(outputs[0].shape()[0], inputs[1].shape()[0]); + CHECK_EQ(outputs[0].shape()[0], seqArg.shape()[0]); /// dim of output val = dim of input grad * context_length - CHECK_EQ(inputs[1].shape()[1], outputs[0].shape()[1] * context_length_); + CHECK_EQ(seqArg.shape()[1], outputs[0].shape()[1] * context_length_); CHECK_EQ(outputs[0].getArgType(), ADD_TO); CHECK_EQ(outputs[1].getArgType(), ADD_TO); - const auto seq_vec = inputs[0].vector(); - const auto out_grad_mat = inputs[1].matrix(); + const auto seq_vec = seqArg.getSequenceIds().vector(); + const auto out_grad_mat = seqArg.matrix(); auto in_grad_mat = !outputs[0].data() ? typename Tensor::Matrix(nullptr, 0, 0) diff --git a/paddle/function/ContextProjectionOpTest.cpp b/paddle/function/ContextProjectionOpTest.cpp index c8d5b4f2786f76..50ca2040050cad 100644 --- a/paddle/function/ContextProjectionOpTest.cpp +++ b/paddle/function/ContextProjectionOpTest.cpp @@ -122,8 +122,7 @@ void testMatrixProjectionBackward(int context_start, BufferArgs cpu_inputs; BufferArgs cpu_outputs; - cpu_inputs.addArg(*cpu_seq); - cpu_inputs.addArg(cpu_out_grad); + cpu_inputs.addArg(cpu_out_grad, *cpu_seq); cpu_outputs.addArg(cpu_in_grad, ADD_TO); cpu_outputs.addArg( cpu_w_grad ? *cpu_w_grad : CpuMatrix(nullptr, 0, input_dim), ADD_TO); @@ -132,8 +131,7 @@ void testMatrixProjectionBackward(int context_start, BufferArgs gpu_inputs; BufferArgs gpu_outputs; - gpu_inputs.addArg(*gpu_seq); - gpu_inputs.addArg(gpu_out_grad); + gpu_inputs.addArg(gpu_out_grad, *gpu_seq); gpu_outputs.addArg(gpu_in_grad, ADD_TO); gpu_outputs.addArg( gpu_w_grad ? *gpu_w_grad : GpuMatrix(nullptr, 0, input_dim), ADD_TO); diff --git a/paddle/function/Function.cpp b/paddle/function/Function.cpp index dbe3a4e9f608df..3b6590846532d8 100644 --- a/paddle/function/Function.cpp +++ b/paddle/function/Function.cpp @@ -90,6 +90,12 @@ void BufferArgs::addArg(const GpuSparseMatrix& arg, ArgType argType) { args_.push_back(std::make_shared(arg, argType)); } +void BufferArgs::addArg(const Matrix& matrix, + const IVector& vector, + ArgType argType) { + args_.push_back(std::make_shared(matrix, vector, argType)); +} + ClassRegistrar FunctionBase::funcRegistrar_; } // namespace paddle diff --git a/paddle/function/Function.h b/paddle/function/Function.h index 249f8f9cfad58b..c15045143bb673 100644 --- a/paddle/function/Function.h +++ b/paddle/function/Function.h @@ -77,6 +77,10 @@ class BufferArgs { void addArg(const CpuSparseMatrix& arg, ArgType argType = UNSPECIFIED); void addArg(const GpuSparseMatrix& arg, ArgType argType = UNSPECIFIED); + void addArg(const Matrix& matrix, + const IVector& vector, + ArgType argType = UNSPECIFIED); + // get argument const BufferArg& operator[](size_t num) const { CHECK_LT(num, args_.size()); diff --git a/paddle/gserver/layers/ContextProjection.cpp b/paddle/gserver/layers/ContextProjection.cpp index def7c15ca82756..17fd36ef563c1b 100644 --- a/paddle/gserver/layers/ContextProjection.cpp +++ b/paddle/gserver/layers/ContextProjection.cpp @@ -166,8 +166,7 @@ void ContextProjection::backward(const UpdateCallback& callback) { BufferArgs inputs; BufferArgs outputs; - inputs.addArg(*in_->sequenceStartPositions->getVector(useGpu_)); - inputs.addArg(*out_->grad); + inputs.addArg(*out_->grad, *in_->sequenceStartPositions->getVector(useGpu_)); outputs.addArg( CpuMatrix( in_->grad ? in_->grad->getData() : nullptr, batch_size, input_dim), From 8560ce69ff8ed6d201e0c31d561aaa6aab7cb5b2 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Wed, 11 Jan 2017 16:55:32 -0800 Subject: [PATCH 019/370] Daoyuan's comments about SequenceArg. --- paddle/function/ContextProjectionOp.cpp | 163 ++++++++++++++++---- paddle/function/ContextProjectionOpTest.cpp | 20 +-- paddle/gserver/layers/ContextProjection.cpp | 15 +- 3 files changed, 151 insertions(+), 47 deletions(-) diff --git a/paddle/function/ContextProjectionOp.cpp b/paddle/function/ContextProjectionOp.cpp index 177708d00f83c7..ec697a381f97fa 100644 --- a/paddle/function/ContextProjectionOp.cpp +++ b/paddle/function/ContextProjectionOp.cpp @@ -74,7 +74,7 @@ void ContextProjectionForward(CpuMatrix& out_mat, /** * Paddle Function for Context Projection Forward. - * Calculate the value for the output layer with context projection. + * Calculate the output sequence after context projection. * * What is Context Projection? * For example, assumed input (x) has 4 words and the dimension of each word @@ -92,10 +92,12 @@ void ContextProjectionForward(CpuMatrix& out_mat, * c1, c2, d1, d2, 0, 0] * @endcode * - * \param outputs[0] output value. - * \param inputs[0] input value. - * \param inputs[1] input weight. - * \param inputs[2] input sequence. + * \param outputs[0].matrix output value, n * (d * l) + * \param outputs[0].vector input sequence, n * 1 + * \param inputs[0].matrix input value, n * d + * \param inputs[0].vector input sequence, n * 1 + * \param inputs[1].matrix input weight, pad * d + * \param inputs[1].vector input sequence, n * 1 */ template class ContextProjectionForwardFunc : public FunctionBase { @@ -107,28 +109,40 @@ class ContextProjectionForwardFunc : public FunctionBase { } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK_EQ((size_t)3, inputs.size()); + CHECK(1 == inputs.size() || 2 == inputs.size()); CHECK_EQ((size_t)1, outputs.size()); - CHECK(outputs[0].data() && inputs[0].data() && inputs[2].data()); - CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); - CHECK_EQ(inputs[0].shape().ndims(), (size_t)2); - CHECK_EQ(inputs[1].shape().ndims(), (size_t)2); - CHECK_EQ(inputs[2].shape().ndims(), (size_t)1); + const auto val_seqs = dynamic_cast(inputs[0]); + const auto w_seqs = inputs.size() <= 1 + ? nullptr + : dynamic_cast(&inputs[1]); + auto out_seqs = dynamic_cast(outputs[0]); + + CHECK(out_seqs.data() && val_seqs.data() && + val_seqs.getSequenceIds().data()); + CHECK_EQ(out_seqs.shape().ndims(), (size_t)2); + CHECK_EQ(val_seqs.shape().ndims(), (size_t)2); + CHECK_EQ(val_seqs.getSequenceIds().shape().ndims(), (size_t)1); + if (w_seqs) { + CHECK_EQ(w_seqs->shape().ndims(), (size_t)2); + CHECK_EQ(w_seqs->getSequenceIds().shape().ndims(), (size_t)1); + } /// dim of output = dim of input * context_length - CHECK_EQ(outputs[0].shape()[1], inputs[0].shape()[1] * context_length_); - /// dim of input == dim of weight - CHECK_EQ(inputs[0].shape()[1], inputs[1].shape()[1]); + CHECK_EQ(out_seqs.shape()[1], val_seqs.shape()[1] * context_length_); /// input and output has the same batch_size - CHECK_EQ(inputs[0].shape()[0], outputs[0].shape()[0]); + CHECK_EQ(val_seqs.shape()[0], out_seqs.shape()[0]); + /// dim of input == dim of weight + if (w_seqs) { + CHECK_EQ(val_seqs.shape()[1], w_seqs->shape()[1]); + } - CHECK_EQ(outputs[0].getArgType(), ADD_TO); - auto out_mat = outputs[0].matrix(); - const auto in_mat = inputs[0].matrix(); + CHECK_EQ(out_seqs.getArgType(), ADD_TO); + auto out_mat = out_seqs.matrix(); + const auto in_mat = val_seqs.matrix(); const auto w_mat = - !inputs[1].data() ? typename Tensor::Matrix(nullptr, 0, 0) - : inputs[1].matrix(); - const auto seq_vec = inputs[2].vector(); + w_seqs ? w_seqs->matrix() + : typename Tensor::Matrix(nullptr, 0, 0); + const auto seq_vec = val_seqs.getSequenceIds().vector(); ContextProjectionForward(out_mat, in_mat, w_mat, @@ -227,25 +241,25 @@ class ContextProjectionBackwardFunc : public FunctionBase { CHECK_EQ((size_t)1, inputs.size()); CHECK_EQ((size_t)2, outputs.size()); - const auto seqArg = dynamic_cast(inputs[0]); - CHECK(seqArg.data() && inputs[0].data()); - CHECK_EQ(seqArg.shape().ndims(), (size_t)2); - CHECK_EQ(seqArg.getSequenceIds().shape().ndims(), (size_t)1); + const auto seq_arg = dynamic_cast(inputs[0]); + CHECK(seq_arg.data() && inputs[0].data()); + CHECK_EQ(seq_arg.shape().ndims(), (size_t)2); + CHECK_EQ(seq_arg.getSequenceIds().shape().ndims(), (size_t)1); CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); CHECK_EQ(outputs[1].shape().ndims(), (size_t)2); /// dim of input grad == dim of weight CHECK_EQ(outputs[0].shape()[1], outputs[1].shape()[1]); /// input and output grad has the same batch_size - CHECK_EQ(outputs[0].shape()[0], seqArg.shape()[0]); + CHECK_EQ(outputs[0].shape()[0], seq_arg.shape()[0]); /// dim of output val = dim of input grad * context_length - CHECK_EQ(seqArg.shape()[1], outputs[0].shape()[1] * context_length_); + CHECK_EQ(seq_arg.shape()[1], outputs[0].shape()[1] * context_length_); CHECK_EQ(outputs[0].getArgType(), ADD_TO); CHECK_EQ(outputs[1].getArgType(), ADD_TO); - const auto seq_vec = seqArg.getSequenceIds().vector(); - const auto out_grad_mat = seqArg.matrix(); + const auto seq_vec = seq_arg.getSequenceIds().vector(); + const auto out_grad_mat = seq_arg.matrix(); auto in_grad_mat = !outputs[0].data() ? typename Tensor::Matrix(nullptr, 0, 0) @@ -272,6 +286,91 @@ class ContextProjectionBackwardFunc : public FunctionBase { size_t total_pad_; }; +/** + * \param inputs[0].matrix input grad, n*d + * \param inputs[0].vector input sequence, n*1 + * \param outputs[0] output grad, n*(d*l) + */ +template +class ContextProjectionBackwardDataFunc : public FunctionBase { +public: + void init(const FuncConfig& config) override { + context_length_ = config.get("context_length"); + context_start_ = config.get("context_start"); + } + + void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { + CHECK_EQ(1, static_cast(inputs.size())); + CHECK_EQ(1, static_cast(outputs.size())); + const auto in_seqs = dynamic_cast(inputs[0]); + CHECK(in_seqs.data() && outputs[0].data() && + in_seqs.getSequenceIds().data()); + CHECK_EQ(static_cast(outputs[0].shape().ndims()), 2); + CHECK_EQ(static_cast(in_seqs.shape().ndims()), 2); + CHECK_EQ(static_cast(in_seqs.getSequenceIds().shape().ndims()), 1); + CHECK_EQ(outputs[0].shape().ndims(), + in_seqs.shape().ndims() * context_length_); + /// input and output has the same batch_size + CHECK_EQ(in_seqs.shape()[0], outputs[0].shape()[0]); + const auto out_grad_mat = outputs[0].matrix(); + auto in_grad_mat = in_seqs.matrix(); + const auto seq_vec = in_seqs.getSequenceIds().vector(); + + ContextProjectionBackwardData( + out_grad_mat, in_grad_mat, seq_vec, context_length_, context_start_); + } + +private: + size_t context_length_; + int context_start_; +}; + +/** + * \param inputs[0].matrix weight grad, pad * d + * \param inputs[0].vecotr input sequence, n * 1 + * \param outputs[0] output grad, n * (d * l) + */ +template +class ContextProjectionBackwardWeightFunc : public FunctionBase { +public: + void init(const FuncConfig& config) override { + context_length_ = config.get("context_length"); + context_start_ = config.get("context_start"); + begin_pad_ = config.get("begin_pad"); + total_pad_ = config.get("total_pad"); + } + + void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { + CHECK_EQ(1, static_cast(inputs.size())); + CHECK_EQ(1, static_cast(outputs.size())); + + const auto in_seqs = dynamic_cast(inputs[0]); + CHECK(in_seqs.data() && in_seqs.getSequenceIds().data() && + outputs[0].data()); + CHECK_EQ(static_cast(outputs[0].shape().ndims()), 2); + CHECK_EQ(static_cast(in_seqs.shape().ndims()), 2); + CHECK_EQ(static_cast(in_seqs.getSequenceIds().shape().ndims()), 1); + CHECK_EQ(in_seqs.shape()[0], outputs[0].shape()[0]); + CHECK_EQ(outputs[0].shape()[1], in_seqs.shape()[1] * context_length_); + const auto out_grad_mat = outputs[0].matrix(); + auto w_grad_mat = inputs[0].matrix(); + const auto seq_vec = in_seqs.getSequenceIds().vector(); + ContextProjectionBackwardWeight(out_grad_mat, + w_grad_mat, + seq_vec, + context_length_, + context_start_, + total_pad_, + begin_pad_); + } + +private: + size_t context_length_; + int context_start_; + size_t begin_pad_; + size_t total_pad_; +}; + REGISTER_TYPED_FUNC(ContextProjectionForward, CPU, ContextProjectionForwardFunc); @@ -285,5 +384,11 @@ REGISTER_TYPED_FUNC(ContextProjectionForward, REGISTER_TYPED_FUNC(ContextProjectionBackward, GPU, ContextProjectionBackwardFunc); +REGISTER_TYPED_FUNC(ContextProjectionBackwardData, + GPU, + ContextProjectionBackwardDataFunc); +REGISTER_TYPED_FUNC(ContextProjectionBackwardWeight, + GPU, + ContextProjectionBackwardWeightFunc); #endif } // namespace paddle diff --git a/paddle/function/ContextProjectionOpTest.cpp b/paddle/function/ContextProjectionOpTest.cpp index 50ca2040050cad..bd0c06c5f64a88 100644 --- a/paddle/function/ContextProjectionOpTest.cpp +++ b/paddle/function/ContextProjectionOpTest.cpp @@ -58,21 +58,21 @@ void testMatrixProjectionForward(int context_start, BufferArgs cpu_inputs; BufferArgs cpu_outputs; - cpu_inputs.addArg(cpu_in); - cpu_inputs.addArg(cpu_weight ? *cpu_weight - : CpuMatrix(nullptr, 0, input_dim)); - cpu_inputs.addArg(*cpu_seq); - cpu_outputs.addArg(cpu_out, ADD_TO); + 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; BufferArgs gpu_outputs; - gpu_inputs.addArg(gpu_in); - gpu_inputs.addArg(gpu_weight ? *gpu_weight - : GpuMatrix(nullptr, 0, input_dim)); - gpu_inputs.addArg(*gpu_seq); - gpu_outputs.addArg(gpu_out, ADD_TO); + 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); diff --git a/paddle/gserver/layers/ContextProjection.cpp b/paddle/gserver/layers/ContextProjection.cpp index 17fd36ef563c1b..edcef17ad4705f 100644 --- a/paddle/gserver/layers/ContextProjection.cpp +++ b/paddle/gserver/layers/ContextProjection.cpp @@ -118,16 +118,15 @@ void ContextProjection::forward() { /// first use state_, otherwise use weight_(padding false === w nullptr) auto w_ptr = state_ ? state_.get() : is_padding ? weight_->getW().get() : nullptr; - auto start_pos = in_->sequenceStartPositions; - + const auto start_pos = in_->sequenceStartPositions->getVector(useGpu_); BufferArgs inputs; BufferArgs outputs; - inputs.addArg(*in_->value); - inputs.addArg(CpuMatrix(w_ptr ? w_ptr->getData() : nullptr, - w_ptr ? w_ptr->getHeight() : 0, - input_dim)); - inputs.addArg(*in_->sequenceStartPositions->getVector(useGpu_)); - outputs.addArg(*out_->value, ADD_TO); + inputs.addArg(*in_->value, *start_pos); + if (w_ptr) { + inputs.addArg(CpuMatrix(w_ptr->getData(), w_ptr->getHeight(), input_dim), + *start_pos); + } + outputs.addArg(*out_->value, *start_pos, ADD_TO); forward_[0]->calc(inputs, outputs); if (state_ && config_.context_start() < 0) { From e9794214cbca438b1b467d614c6398ec09ab1d0b Mon Sep 17 00:00:00 2001 From: xutianbing Date: Thu, 12 Jan 2017 13:26:10 -0800 Subject: [PATCH 020/370] Address further comments. --- paddle/function/BufferArg.cpp | 12 +- paddle/function/BufferArg.h | 30 +++- paddle/function/ContextProjectionOp.cpp | 169 +++++++++++--------- paddle/function/ContextProjectionOpTest.cpp | 4 +- paddle/gserver/layers/ContextProjection.cpp | 1 + 5 files changed, 126 insertions(+), 90 deletions(-) diff --git a/paddle/function/BufferArg.cpp b/paddle/function/BufferArg.cpp index fde48a73b61c31..5d595deb12c6c8 100644 --- a/paddle/function/BufferArg.cpp +++ b/paddle/function/BufferArg.cpp @@ -20,23 +20,27 @@ limitations under the License. */ namespace paddle { const SequenceArg& BufferArg::sequence() const { - // CHECK_EQ(bufferType_, TENSOR_SEQUENCE_DATA); + CHECK_EQ(bufferType_, TENSOR_SEQUENCE_DATA); return dynamic_cast(*this); } const SparseMatrixArg& BufferArg::sparse() const { - // CHECK_EQ(bufferType_, TENSOR_SPARSE); + CHECK_EQ(bufferType_, TENSOR_SPARSE); return dynamic_cast(*this); } SparseMatrixArg::SparseMatrixArg(const CpuSparseMatrix& sparse, ArgType argType) : BufferArg(sparse, argType), row_(reinterpret_cast(sparse.getRows()), VALUE_TYPE_INT32), - col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32) {} + col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32) { + bufferType_ = TENSOR_SPARSE; +} SparseMatrixArg::SparseMatrixArg(const GpuSparseMatrix& sparse, ArgType argType) : BufferArg(sparse, argType), row_(reinterpret_cast(sparse.getRows()), VALUE_TYPE_INT32), - col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32) {} + col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32) { + bufferType_ = TENSOR_SPARSE; +} } // namespace paddle diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index f3a4350e12df34..440a924a7a63d8 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -23,10 +23,11 @@ limitations under the License. */ namespace paddle { enum BufferType { - TENSOR_NORMAL = 0, - TENSOR_SEQUENCE_ID = 1, - TENSOR_SEQUENCE_DATA = 2, - TENSOR_SPARSE = 3 + TENSOR_UNKNOWN = 0, + TENSOR_NORMAL = 1, + TENSOR_SEQUENCE_ID = 2, + TENSOR_SEQUENCE_DATA = 3, + TENSOR_SPARSE = 4 }; enum SparseDataType { @@ -86,6 +87,7 @@ class BufferArg { valueType_(DataType::value), shape_(2), argType_(argType) { + bufferType_ = TENSOR_NORMAL; shape_.setDim(0, matrix.getHeight()); shape_.setDim(1, matrix.getWidth()); } @@ -98,6 +100,7 @@ class BufferArg { valueType_(DataType::value), shape_(shape), argType_(argType) { + bufferType_ = TENSOR_NORMAL; CHECK_EQ(matrix.getElementCnt(), shape.getElements()); } @@ -107,6 +110,7 @@ class BufferArg { valueType_(DataType::value), shape_(1), argType_(argType) { + bufferType_ = TENSOR_NORMAL; shape_.setDim(0, vector.getSize()); } @@ -116,6 +120,7 @@ class BufferArg { valueType_(VALUE_TYPE_INT32), shape_(1), argType_(argType) { + bufferType_ = TENSOR_NORMAL; shape_.setDim(0, vector.getSize()); } @@ -150,6 +155,8 @@ class BufferArg { ValueType valueType() const { return valueType_; } BufferType bufferType() const { return bufferType_; } const TensorShape& shape() const { return shape_; } + bool isSparse() const { return (TENSOR_SPARSE == bufferType_); } + bool isSequenceArg() const { return TENSOR_SEQUENCE_DATA == bufferType_; } const SequenceArg& sequence() const; const SparseMatrixArg& sparse() const; @@ -158,8 +165,8 @@ class BufferArg { void* buf_; ValueType valueType_; TensorShape shape_; - BufferType bufferType_; - ArgType argType_ = UNSPECIFIED; + BufferType bufferType_{TENSOR_UNKNOWN}; + ArgType argType_{UNSPECIFIED}; // leading dimensions. The size is dims_.size() // Dims lds_; }; @@ -174,11 +181,13 @@ class SequenceIdArg : public BufferArg { const TensorShape& shape, ArgType argType = UNSPECIFIED) : BufferArg(buf, VALUE_TYPE_INT32, shape, argType) { + bufferType_ = TENSOR_SEQUENCE_ID; CHECK_EQ(shape_.ndims(), (size_t)1); numSeqs_ = shape_[0] - 1; } SequenceIdArg(const IVector& vector) : BufferArg(vector) { + bufferType_ = TENSOR_SEQUENCE_ID; numSeqs_ = shape_[0] - 1; } @@ -199,12 +208,16 @@ class SequenceArg : public BufferArg { const SequenceIdArg& startPositions, ArgType argType = UNSPECIFIED) : BufferArg(buf, valueType, shape, argType), - startPositions_(startPositions) {} + startPositions_(startPositions) { + bufferType_ = TENSOR_SEQUENCE_DATA; + } SequenceArg(const Matrix& matrix, const IVector& vector, ArgType argType = UNSPECIFIED) - : BufferArg(matrix, argType), startPositions_(vector) {} + : BufferArg(matrix, argType), startPositions_(vector) { + bufferType_ = TENSOR_SEQUENCE_DATA; + } ~SequenceArg() {} @@ -236,6 +249,7 @@ class SparseMatrixArg : public BufferArg { nnz_(nnz), format_(format), type_(type) { + bufferType_ = TENSOR_SPARSE; CHECK((valueType == VALUE_TYPE_FLOAT) || (valueType == VALUE_TYPE_DOUBLE)); CHECK_EQ(shape_.ndims(), (size_t)2); CHECK_EQ(row_.shape().ndims(), (size_t)1); diff --git a/paddle/function/ContextProjectionOp.cpp b/paddle/function/ContextProjectionOp.cpp index ec697a381f97fa..2ef53cd6d9deda 100644 --- a/paddle/function/ContextProjectionOp.cpp +++ b/paddle/function/ContextProjectionOp.cpp @@ -74,9 +74,9 @@ void ContextProjectionForward(CpuMatrix& out_mat, /** * Paddle Function for Context Projection Forward. - * Calculate the output sequence after context projection. + * Calculate the output layer value sequence after context projection. * - * What is Context Projection? + * What is Context Projection for a sequence? * For example, assumed input (x) has 4 words and the dimension of each word * representation is 2. If we use zero to pad instead of learned weight to pad, * and the context_lenth is 3, the output (y) is: @@ -92,12 +92,11 @@ void ContextProjectionForward(CpuMatrix& out_mat, * c1, c2, d1, d2, 0, 0] * @endcode * - * \param outputs[0].matrix output value, n * (d * l) - * \param outputs[0].vector input sequence, n * 1 - * \param inputs[0].matrix input value, n * d - * \param inputs[0].vector input sequence, n * 1 - * \param inputs[1].matrix input weight, pad * d - * \param inputs[1].vector input sequence, n * 1 + * \param outputs[0].matrix output layer value, n * (d * l) + * \param outputs[0].vector start position sequence, n * 1 + * \param inputs[0].matrix input layer value, n * d + * \param inputs[0].vector start position sequence, n * 1 + * \param inputs[1].matrix input layer weight, pad * d */ template class ContextProjectionForwardFunc : public FunctionBase { @@ -111,37 +110,35 @@ class ContextProjectionForwardFunc : public FunctionBase { void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { CHECK(1 == inputs.size() || 2 == inputs.size()); CHECK_EQ((size_t)1, outputs.size()); - + CHECK(inputs[0].isSequenceArg() && outputs[0].isSequenceArg()) + << "SequenceArg required here"; const auto val_seqs = dynamic_cast(inputs[0]); - const auto w_seqs = inputs.size() <= 1 - ? nullptr - : dynamic_cast(&inputs[1]); - auto out_seqs = dynamic_cast(outputs[0]); + auto out_seq = dynamic_cast(outputs[0]); - CHECK(out_seqs.data() && val_seqs.data() && + CHECK(out_seq.data() && val_seqs.data() && val_seqs.getSequenceIds().data()); - CHECK_EQ(out_seqs.shape().ndims(), (size_t)2); + CHECK_EQ(out_seq.shape().ndims(), (size_t)2); CHECK_EQ(val_seqs.shape().ndims(), (size_t)2); CHECK_EQ(val_seqs.getSequenceIds().shape().ndims(), (size_t)1); - if (w_seqs) { - CHECK_EQ(w_seqs->shape().ndims(), (size_t)2); - CHECK_EQ(w_seqs->getSequenceIds().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 - CHECK_EQ(out_seqs.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 - CHECK_EQ(val_seqs.shape()[0], out_seqs.shape()[0]); + CHECK_EQ(val_seqs.shape()[0], out_seq.shape()[0]); /// dim of input == dim of weight - if (w_seqs) { - CHECK_EQ(val_seqs.shape()[1], w_seqs->shape()[1]); + if (2 == inputs.size()) { + CHECK_EQ(val_seqs.shape()[1], inputs[1].shape()[1]); } - CHECK_EQ(out_seqs.getArgType(), ADD_TO); - auto out_mat = out_seqs.matrix(); + CHECK_EQ(out_seq.getArgType(), ADD_TO); + auto out_mat = out_seq.matrix(); const auto in_mat = val_seqs.matrix(); const auto w_mat = - w_seqs ? w_seqs->matrix() - : typename Tensor::Matrix(nullptr, 0, 0); + (2 == inputs.size()) + ? inputs[1].matrix() + : typename Tensor::Matrix(nullptr, 0, 0); const auto seq_vec = val_seqs.getSequenceIds().vector(); ContextProjectionForward(out_mat, in_mat, @@ -221,10 +218,11 @@ void ContextProjectionBackward(const CpuMatrix& out_grad_mat, * Context Projection Backward Function. * Update the weight gradient and input layer gradient with backprop * - * \param inputs[0].seq input sequence. - * \param inputs[0].matrix output layer grad. - * \param outputs[0] input layer grad. - * \param outputs[1] weight grad. + * \param inputs[0].matrix output layer grad, n * (d * l) + * \param inputs[0].vector start position sequence, n * 1 + * \param outputs[0].matrix input layer grad, n * d + * \param outputs[0].vector start position sequence, n * 1 + * \param outputs[1] weight grad, pad * d */ template class ContextProjectionBackwardFunc : public FunctionBase { @@ -240,30 +238,31 @@ class ContextProjectionBackwardFunc : public FunctionBase { void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { CHECK_EQ((size_t)1, inputs.size()); CHECK_EQ((size_t)2, outputs.size()); - - const auto seq_arg = dynamic_cast(inputs[0]); - CHECK(seq_arg.data() && inputs[0].data()); - CHECK_EQ(seq_arg.shape().ndims(), (size_t)2); - CHECK_EQ(seq_arg.getSequenceIds().shape().ndims(), (size_t)1); - CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); + CHECK(inputs[0].isSequenceArg() && outputs[0].isSequenceArg()) + << "SequenceArg required here"; + const auto in_seq = dynamic_cast(inputs[0]); + auto out_seq = dynamic_cast(outputs[0]); + CHECK(in_seq.data() && in_seq.getSequenceIds().data()); + CHECK_EQ(in_seq.shape().ndims(), (size_t)2); + CHECK_EQ(in_seq.getSequenceIds().shape().ndims(), (size_t)1); + CHECK_EQ(out_seq.shape().ndims(), (size_t)2); + CHECK_EQ(out_seq.getSequenceIds().shape().ndims(), (size_t)1); CHECK_EQ(outputs[1].shape().ndims(), (size_t)2); /// dim of input grad == dim of weight - CHECK_EQ(outputs[0].shape()[1], outputs[1].shape()[1]); + CHECK_EQ(out_seq.shape()[1], outputs[1].shape()[1]); /// input and output grad has the same batch_size - CHECK_EQ(outputs[0].shape()[0], seq_arg.shape()[0]); - /// dim of output val = dim of input grad * context_length - CHECK_EQ(seq_arg.shape()[1], outputs[0].shape()[1] * context_length_); - - CHECK_EQ(outputs[0].getArgType(), ADD_TO); + CHECK_EQ(out_seq.shape()[0], in_seq.shape()[0]); + /// dim of output grad = dim of input grad * context_length + CHECK_EQ(in_seq.shape()[1], out_seq.shape()[1] * context_length_); + CHECK_EQ(out_seq.getArgType(), ADD_TO); CHECK_EQ(outputs[1].getArgType(), ADD_TO); - const auto seq_vec = seq_arg.getSequenceIds().vector(); - const auto out_grad_mat = seq_arg.matrix(); + const auto seq_vec = in_seq.getSequenceIds().vector(); + const auto out_grad_mat = in_seq.matrix(); auto in_grad_mat = - !outputs[0].data() - ? typename Tensor::Matrix(nullptr, 0, 0) - : outputs[0].matrix(); + !out_seq.data() ? typename Tensor::Matrix(nullptr, 0, 0) + : out_seq.matrix(); auto w_grad_mat = !outputs[1].data() ? typename Tensor::Matrix(nullptr, 0, 0) : outputs[1].matrix(); @@ -287,9 +286,15 @@ class ContextProjectionBackwardFunc : public FunctionBase { }; /** - * \param inputs[0].matrix input grad, n*d - * \param inputs[0].vector input sequence, n*1 - * \param outputs[0] output grad, n*(d*l) + * Context Projection Backward Data Function + * Update input layer grad + * input: sequence of output layer grad + * output: sequence of input layer grad + * + * \param outputs[0].matrix input layer grad, n * d + * \param outputs[0].vector start position sequence, n * 1 + * \param inputs[0].matrix output layer grad, n * (d * l) + * \param inputs[0].vector start positon sequence, n * 1 */ template class ContextProjectionBackwardDataFunc : public FunctionBase { @@ -302,19 +307,24 @@ class ContextProjectionBackwardDataFunc : public FunctionBase { void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { CHECK_EQ(1, static_cast(inputs.size())); CHECK_EQ(1, static_cast(outputs.size())); - const auto in_seqs = dynamic_cast(inputs[0]); - CHECK(in_seqs.data() && outputs[0].data() && - in_seqs.getSequenceIds().data()); - CHECK_EQ(static_cast(outputs[0].shape().ndims()), 2); - CHECK_EQ(static_cast(in_seqs.shape().ndims()), 2); - CHECK_EQ(static_cast(in_seqs.getSequenceIds().shape().ndims()), 1); - CHECK_EQ(outputs[0].shape().ndims(), - in_seqs.shape().ndims() * context_length_); + CHECK(inputs[0].isSequenceArg() && outputs[0].isSequenceArg()) + << "SequenceArg required here"; + const auto in_seq = dynamic_cast(inputs[0]); + const auto out_seq = dynamic_cast(outputs[0]); + + CHECK(in_seq.data() && out_seq.data() && in_seq.getSequenceIds().data()); + CHECK_EQ(static_cast(out_seq.shape().ndims()), 2); + CHECK_EQ(static_cast(in_seq.shape().ndims()), 2); + CHECK_EQ(static_cast(in_seq.getSequenceIds().shape().ndims()), 1); + /// output layer grad dim == input layer grad dim * context_length_ + CHECK_EQ(in_seq.shape().ndims(), out_seq.shape().ndims() * context_length_); /// input and output has the same batch_size - CHECK_EQ(in_seqs.shape()[0], outputs[0].shape()[0]); - const auto out_grad_mat = outputs[0].matrix(); - auto in_grad_mat = in_seqs.matrix(); - const auto seq_vec = in_seqs.getSequenceIds().vector(); + CHECK_EQ(in_seq.shape()[0], out_seq.shape()[0]); + CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO); + + const auto out_grad_mat = in_seq.matrix(); + const auto seq_vec = in_seq.getSequenceIds().vector(); + auto in_grad_mat = out_seq.matrix(); ContextProjectionBackwardData( out_grad_mat, in_grad_mat, seq_vec, context_length_, context_start_); @@ -326,9 +336,14 @@ class ContextProjectionBackwardDataFunc : public FunctionBase { }; /** - * \param inputs[0].matrix weight grad, pad * d - * \param inputs[0].vecotr input sequence, n * 1 - * \param outputs[0] output grad, n * (d * l) + * Context Projection Backward Weight Function + * Update weight grad by backprop + * input: sequence of output layer grad + * output: weight grad + * + * \param outputs[0] weight grad, pad * d + * \param inputs[0].matrix output layer grad, n * (d * l) + * \param inputs[0].vecotr start positon sequence, n * 1 */ template class ContextProjectionBackwardWeightFunc : public FunctionBase { @@ -343,18 +358,20 @@ class ContextProjectionBackwardWeightFunc : public FunctionBase { void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { CHECK_EQ(1, static_cast(inputs.size())); CHECK_EQ(1, static_cast(outputs.size())); - - const auto in_seqs = dynamic_cast(inputs[0]); - CHECK(in_seqs.data() && in_seqs.getSequenceIds().data() && - outputs[0].data()); + CHECK(inputs[0].isSequenceArg()) << "SequenceArg required here"; + const auto in_seq = dynamic_cast(inputs[0]); + CHECK(in_seq.data() && in_seq.getSequenceIds().data() && outputs[0].data()); CHECK_EQ(static_cast(outputs[0].shape().ndims()), 2); - CHECK_EQ(static_cast(in_seqs.shape().ndims()), 2); - CHECK_EQ(static_cast(in_seqs.getSequenceIds().shape().ndims()), 1); - CHECK_EQ(in_seqs.shape()[0], outputs[0].shape()[0]); - CHECK_EQ(outputs[0].shape()[1], in_seqs.shape()[1] * context_length_); - const auto out_grad_mat = outputs[0].matrix(); - auto w_grad_mat = inputs[0].matrix(); - const auto seq_vec = in_seqs.getSequenceIds().vector(); + CHECK_EQ(static_cast(in_seq.shape().ndims()), 2); + CHECK_EQ(static_cast(in_seq.getSequenceIds().shape().ndims()), 1); + CHECK_EQ(in_seq.shape()[0], outputs[0].shape()[0]); + /// output layer grad dim == weight dim * context_length_ + CHECK_EQ(in_seq.shape()[1], outputs[0].shape()[1] * context_length_); + CHECK_EQ(outputs[0].getArgType(), ADD_TO); + + const auto seq_vec = in_seq.getSequenceIds().vector(); + const auto out_grad_mat = in_seq.matrix(); + auto w_grad_mat = outputs[0].matrix(); ContextProjectionBackwardWeight(out_grad_mat, w_grad_mat, seq_vec, diff --git a/paddle/function/ContextProjectionOpTest.cpp b/paddle/function/ContextProjectionOpTest.cpp index bd0c06c5f64a88..c9db2ff8008e0b 100644 --- a/paddle/function/ContextProjectionOpTest.cpp +++ b/paddle/function/ContextProjectionOpTest.cpp @@ -123,7 +123,7 @@ void testMatrixProjectionBackward(int context_start, BufferArgs cpu_inputs; BufferArgs cpu_outputs; cpu_inputs.addArg(cpu_out_grad, *cpu_seq); - cpu_outputs.addArg(cpu_in_grad, ADD_TO); + 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); @@ -132,7 +132,7 @@ void testMatrixProjectionBackward(int context_start, BufferArgs gpu_inputs; BufferArgs gpu_outputs; gpu_inputs.addArg(gpu_out_grad, *gpu_seq); - gpu_outputs.addArg(gpu_in_grad, ADD_TO); + 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); diff --git a/paddle/gserver/layers/ContextProjection.cpp b/paddle/gserver/layers/ContextProjection.cpp index edcef17ad4705f..d7042af1c25e74 100644 --- a/paddle/gserver/layers/ContextProjection.cpp +++ b/paddle/gserver/layers/ContextProjection.cpp @@ -169,6 +169,7 @@ void ContextProjection::backward(const UpdateCallback& callback) { outputs.addArg( CpuMatrix( in_->grad ? in_->grad->getData() : nullptr, batch_size, input_dim), + *in_->sequenceStartPositions->getVector(useGpu_), ADD_TO); outputs.addArg(CpuMatrix(w_ptr ? w_ptr->getData() : nullptr, w_ptr ? w_ptr->getHeight() : 0, From 143ff015c66fb70db0c89de77bbd8cb60bb082ce Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Thu, 5 Jan 2017 14:14:51 -0800 Subject: [PATCH 021/370] add permission AWSKeyManagementServicePowerUser for aws kms key creation Without the permission command `aws kms --region=us-west-1 create-key --description="kube-aws assets"` will fail with: An error occurred (AccessDeniedException) when calling the CreateKey operation: --- doc/howto/usage/k8s/k8s_aws_en.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/howto/usage/k8s/k8s_aws_en.md b/doc/howto/usage/k8s/k8s_aws_en.md index b04bfba590de42..a82243995a3b42 100644 --- a/doc/howto/usage/k8s/k8s_aws_en.md +++ b/doc/howto/usage/k8s/k8s_aws_en.md @@ -31,6 +31,7 @@ the user group: - IAMUserSSHKeys - IAMFullAccess - NetworkAdministrator +- AWSKeyManagementServicePowerUser By the time we write this tutorial, we noticed that Chinese AWS users From 2778a65b0ff9aa825d1ccaf6907c7364427058f1 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Thu, 12 Jan 2017 17:19:05 -0800 Subject: [PATCH 022/370] first pass change for k8s aws en tutorial --- doc/howto/usage/k8s/k8s_aws_en.md | 108 +++++++++++++++--------------- 1 file changed, 55 insertions(+), 53 deletions(-) diff --git a/doc/howto/usage/k8s/k8s_aws_en.md b/doc/howto/usage/k8s/k8s_aws_en.md index a82243995a3b42..c776ba9eb97a8c 100644 --- a/doc/howto/usage/k8s/k8s_aws_en.md +++ b/doc/howto/usage/k8s/k8s_aws_en.md @@ -2,15 +2,9 @@ ## Create AWS Account and IAM Account -To use AWS, we need to sign up an AWS account on Amazon's Web site. -An AWS account allows us to login to the AWS Console Web interface to -create IAM users and user groups. Usually, we create a user group with -privileges required to run PaddlePaddle, and we create users for -those who are going to run PaddlePaddle and add these users into the -group. IAM users can identify themselves using password and tokens, -where passwords allows users to log in to the AWS Console, and tokens -make it easy for users to submit and inspect jobs from the command -line. +AWS account allow us to manage AWS from Web Console. Amazon AMI enable us to manage AWS from command line interface. + +We need to create an AMI user with sufficient privilege to create kubernetes cluster on AWS. To sign up an AWS account, please follow @@ -19,8 +13,7 @@ To create users and user groups under an AWS account, please follow [this guide](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html). -Please be aware that this tutorial needs the following privileges in -the user group: +Please be aware that this tutorial needs the following privileges for the user in AMI: - AmazonEC2FullAccess - AmazonS3FullAccess @@ -47,9 +40,11 @@ it. Here we will show you step by step on how to run PaddlePaddle training on AWS cluster. -###Download kube-aws and kubectl +### Download kube-aws and kubectl + +#### kube-aws -####kube-aws +[kube-aws](https://github.com/coreos/kube-aws) is a CLI tool to automate cluster deployment to AWS. Import the CoreOS Application Signing Public Key: @@ -89,24 +84,22 @@ mv ${PLATFORM}/kube-aws /usr/local/bin ``` -####kubectl +#### kubectl + +[kubectl](https://kubernetes.io/docs/user-guide/kubectl-overview/) is a command line interface for running commands against Kubernetes clusters. Go to the [releases](https://github.com/kubernetes/kubernetes/releases) and download the latest release tarball. Extract the tarball and then concate the kubernetes binaries directory into PATH: ``` -export PATH=/platforms/linux/amd64:$PATH - +export PATH=/platforms/linux/amd64:$PATH # The exact path depend on your platform ``` -User credentials and security tokens will be generated later in user directory, not in `~/.kube/config`, they will be necessary to use the CLI or the HTTP Basic Auth. - - -###Configure AWS Credentials -First check out [this](http://docs.aws.amazon.com/cli/latest/userguide/installing.html) for installing the AWS command line interface, if you use ec2 instance with default amazon AMI, the cli tool has already been installed on your machine. +### Configure AWS Credentials +First check out [this](http://docs.aws.amazon.com/cli/latest/userguide/installing.html) for installing the AWS command line interface. And then configure your AWS account information: @@ -127,33 +120,35 @@ Default output format: json ``` -Test that your credentials work by describing any instances you may already have running on your account: +Verify that your credentials work by describing any instances you may already have running on your account: ``` aws ec2 describe-instances ``` -###Define Cluster Parameters +### Define Cluster Parameters -####EC2 key pair +#### EC2 key pair The keypair that will authenticate SSH access to your EC2 instances. The public half of this key pair will be configured on each CoreOS node. -After creating a key pair, you will use the name you gave the keys to configure the cluster. Key pairs are only available to EC2 instances in the same region. More info in the [EC2 Keypair docs](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html). +Follow [EC2 Keypair docs](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) to create a EC2 key pair -####KMS key +After creating a key pair, you will use the name you gave the keys to configure the cluster. Key pairs are only available to EC2 instances in the same region. + +#### KMS key Amazon KMS keys are used to encrypt and decrypt cluster TLS assets. If you already have a KMS Key that you would like to use, you can skip creating a new key and provide the Arn string for your existing key. You can create a KMS key in the AWS console, or with the aws command line tool: ``` -$ aws kms --region=us-west-2 create-key --description="kube-aws assets" +$ aws kms --region=us-west-1 create-key --description="kube-aws assets" { "KeyMetadata": { "CreationDate": 1458235139.724, "KeyState": "Enabled", - "Arn": "arn:aws:kms:us-west-2:xxxxxxxxx:key/xxxxxxxxxxxxxxxxxxx", + "Arn": "arn:aws:kms:us-west-1:xxxxxxxxx:key/xxxxxxxxxxxxxxxxxxx", "AWSAccountId": "xxxxxxxxxxxxx", "Enabled": true, "KeyUsage": "ENCRYPT_DECRYPT", @@ -167,7 +162,9 @@ You will use the `KeyMetadata.Arn` string to identify your KMS key in the init s And then you need to add several inline policies in your user permission. -kms inline policy: +Go to AMI user page, click on `Add inline policy` button, and then select `Custom Policy` + +paste into following inline policies: ``` { @@ -183,16 +180,8 @@ kms inline policy: "Resource": [ "arn:aws:kms:*:xxxxxxxxx:key/*" ] - } - ] -} -``` -cloudformation inline policy: - -``` -"Version": "2012-10-17", - "Statement": [ - { + }, + { "Sid": "Stmt1482205746000", "Effect": "Allow", "Action": [ @@ -201,10 +190,11 @@ cloudformation inline policy: "cloudformation:DeleteStack", "cloudformation:DescribeStacks", "cloudformation:DescribeStackResource", - "cloudformation:GetTemplate" + "cloudformation:GetTemplate", + "cloudformation:DescribeStackEvents" ], "Resource": [ - "arn:aws:cloudformation:us-west-2:xxxxxxxxx:stack/YOUR_CLUSTER_NAME/*" + "arn:aws:cloudformation:us-west-1:xxxxxxxxx:stack/YOUR_CLUSTER_NAME/*" ] } ] @@ -212,15 +202,23 @@ cloudformation inline policy: ``` -####External DNS name +#### External DNS name When the cluster is created, the controller will expose the TLS-secured API on a public IP address. You will need to create an A record for the external DNS hostname you want to point to this IP address. You can find the API external IP address after the cluster is created by invoking kube-aws status. -####S3 bucket +#### S3 bucket You need to create an S3 bucket before startup the Kubernetes cluster. -####Initialize an asset directory +command (need to have a global unique name): + +``` +paddle aws s3api --region=us-west-1 create-bucket --bucket bucket-name +``` + +If you get an error message, try a different bucket name. The bucket name needs to be globally unique. + +#### Initialize an asset directory Create a directory on your local machine to hold the generated assets: @@ -238,12 +236,16 @@ $ kube-aws init \ --region=us-west-1 \ --availability-zone=us-west-1c \ --key-name=key-pair-name \ ---kms-key-arn="arn:aws:kms:us-west-2:xxxxxxxxxx:key/xxxxxxxxxxxxxxxxxxx" +--kms-key-arn="arn:aws:kms:us-west-1:xxxxxxxxxx:key/xxxxxxxxxxxxxxxxxxx" ``` +Here `us-west-1c` is used for parameter `--availability-zone`, but supported availability zone varies among AWS accounts. + +Please check if `us-west-1c` is supported by `aws ec2 --region us-west-1 describe-availability-zones`, if not switch to other supported availability zone. (e.g., `us-west-1a`, or `us-west-1b`) + There will now be a cluster.yaml file in the asset directory. This is the main configuration file for your cluster. -####Render contents of the asset directory +#### Render contents of the asset directory In the simplest case, you can have kube-aws generate both your TLS identities and certificate authority for you. @@ -286,21 +288,21 @@ $ tree These assets (templates and credentials) are used to create, update and interact with your Kubernetes cluster. -###Kubernetes Cluster Start Up +### Kubernetes Cluster Start Up -####Create the instances defined in the CloudFormation template +#### Create the instances defined in the CloudFormation template -Now for the exciting part, creating your cluster: +Now for the exciting part, creating your cluster (choose any ``): ``` $ kube-aws up --s3-uri s3:/// ``` -####Configure DNS +#### Configure DNS -You can invoke `kube-aws status` to get the cluster API endpoint after cluster creation, if necessary. This command can take a while. And then dig the load balancer hostname to get the ip address, use this ip to setup an A record for your external dns name. +You can invoke `kube-aws status` to get the cluster API endpoint after cluster creation, if necessary. This command can take a while. And use command `dig` to check the load balancer hostname to get the ip address, use this ip to setup an A record for your external dns name. -####Access the cluster +#### Access the cluster Once the API server is running, you should see: @@ -313,7 +315,7 @@ ip-10-0-0-xx.us-west-1.compute.internal Ready,SchedulingDisabled 5m ``` -###Setup PaddlePaddle Environment on AWS +### Setup PaddlePaddle Environment on AWS Now, we've created a cluster with following network capability: From 2a20fdc14bce87ce3d092ab9bff8349be5194b05 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Fri, 13 Jan 2017 14:35:56 +0800 Subject: [PATCH 023/370] Change BufferArgPtr to BufferArg* --- paddle/function/Function.cpp | 9 ++++++--- paddle/function/Function.h | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/paddle/function/Function.cpp b/paddle/function/Function.cpp index dbe3a4e9f608df..3fdc37b9689559 100644 --- a/paddle/function/Function.cpp +++ b/paddle/function/Function.cpp @@ -79,15 +79,18 @@ FuncConfig& FuncConfig::set(const std::string& key, bool v) { void BufferArgs::addArg(const Matrix& arg, const TensorShape& shape, ArgType argType) { - args_.push_back(std::make_shared(arg, shape, argType)); + _args_.push_back(new BufferArg(arg, shape, argType)); + addArg(*_args_.back()); } void BufferArgs::addArg(const CpuSparseMatrix& arg, ArgType argType) { - args_.push_back(std::make_shared(arg, argType)); + _args_.push_back(new SparseMatrixArg(arg, argType)); + addArg(*_args_.back()); } void BufferArgs::addArg(const GpuSparseMatrix& arg, ArgType argType) { - args_.push_back(std::make_shared(arg, argType)); + _args_.push_back(new SparseMatrixArg(arg, argType)); + addArg(*_args_.back()); } ClassRegistrar FunctionBase::funcRegistrar_; diff --git a/paddle/function/Function.h b/paddle/function/Function.h index 249f8f9cfad58b..afbd4911b0a2b9 100644 --- a/paddle/function/Function.h +++ b/paddle/function/Function.h @@ -50,10 +50,25 @@ class FuncConfig { * Argument type for Function::calc(). * A BufferArgs contains a set of BufferArg, * because Function can have multiple inputs and outputs. + * + * addArg() with Matix object used to adapt Layer Argument. + * Will create a BufferArg object in addArg(), + * and free in destructor of BufferArgs. + * + * addArg() with BufferArg object, just save BufferArg object address, + * and the caller needs to guarantee the validity of the BufferArg object + * in the BufferArgs life time. */ class BufferArgs { public: BufferArgs() {} + + ~BufferArgs() { + for (auto arg : _args_) { + delete arg; + } + } + size_t size() const { return args_.size(); } // add argument into BufferArgs @@ -62,7 +77,8 @@ class BufferArgs { // For outputs, the argType needs to be specified as ASSIGN_TO or ADD_TO. template void addArg(const Tensor& arg, ArgType argType = UNSPECIFIED) { - args_.push_back(std::make_shared(arg, argType)); + _args_.push_back(new BufferArg(arg, argType)); + addArg(*_args_.back()); } // Add arg into BufferArgs and reshape the arg. @@ -83,14 +99,27 @@ class BufferArgs { return *args_[num]; } + void addArg(BufferArg& arg) { args_.push_back(&arg); } + + void addArg(SequenceIdArg& arg) { args_.push_back(&arg); } + + void addArg(SequenceArg& arg) { args_.push_back(&arg); } + + void addArg(SparseMatrixArg& arg) { args_.push_back(&arg); } + private: - std::vector args_; + std::vector args_; + // The BufferArg object is constructed and freed by BufferArgs. + std::vector _args_; }; /** * \brief Base class for Function. * The basic Function implementation requires override init and calc interfaces. * + * The caller needs to ensure the validity of the arguments + * during Function execution. + * * Function inputs are readonly, Function outputs have two modes: ASSIGN_TO * and ADD_TO. * If output.getArgType() == ASSIGN_TO, this is assign mode, and the calculation From 039c0bf22384607446fcd38a4ba6c349ce073213 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Fri, 13 Jan 2017 15:05:22 +0800 Subject: [PATCH 024/370] Add some constructors for generating object that only contains shape (do not contains data). --- paddle/function/BufferArg.h | 33 ++++++++++++++++++++++++++++++-- paddle/function/FunctionTest.cpp | 18 +++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index 12352ba29e3392..28542a86574812 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -39,7 +39,6 @@ enum SparseDataFormat { SPARSE_CSR_FORMAT = 0, SPARSE_CSC_FORMAT = 1 }; class BufferArg; class SequenceArg; class SparseMatrixArg; -typedef std::shared_ptr BufferArgPtr; /** * \brief BufferArg used as the argument type of Function. @@ -50,6 +49,11 @@ typedef std::shared_ptr BufferArgPtr; * 3. SequenceArg for a Buffer of sequence data. * 4. SparseMatrixArg for a Buffer of sparse matrix. * + * Buffer shape + * For most buffers, the first dimension `shape()[0]` represents + * the size of the mini-batch. + * + * Buffer argType * There is an ArgType property for the BufferArg used as Function Output. * Whether the result of the Function calculation is assigned to the * output Buffer or added to the output Buffer is determined by the @@ -71,6 +75,14 @@ class BufferArg { ArgType getArgType() const { return argType_; } public: + BufferArg(ValueType valueType, + const TensorShape& shape, + ArgType argType = UNSPECIFIED) + : buf_(nullptr), + valueType_(valueType), + shape_(shape), + argType_(argType) {} + BufferArg(void* buf, ValueType valueType, const TensorShape& shape, @@ -170,6 +182,12 @@ class BufferArg { // if a < b then value_.buf_[a] < value_.buf_[b] class SequenceIdArg : public BufferArg { public: + SequenceIdArg(const TensorShape& shape, ArgType argType = UNSPECIFIED) + : BufferArg(VALUE_TYPE_INT32, shape, argType) { + CHECK_EQ(shape_.ndims(), (size_t)1); + numSeqs_ = shape_[0] - 1; + } + SequenceIdArg(void* buf, const TensorShape& shape, ArgType argType = UNSPECIFIED) @@ -190,9 +208,18 @@ class SequenceIdArg : public BufferArg { size_t numSeqs_; }; -// sequence data +// sequences data +// For mini-batch calculate, +// one batch can contain more than one sequence of data. +// SequenceArg can be used to represent sequences that contain multiple +// unequal lengths. class SequenceArg : public BufferArg { public: + SequenceArg(ValueType valueType, + const TensorShape& shape, + ArgType argType = UNSPECIFIED) + : BufferArg(valueType, shape, argType), startPositions_(TensorShape()) {} + SequenceArg(void* buf, ValueType valueType, const TensorShape& shape, @@ -210,6 +237,8 @@ class SequenceArg : public BufferArg { void* getIdBuf() const { return startPositions_.data(); } size_t numSeqs() const { return startPositions_.numSeqs(); } + SequenceIdArg& getSequenceId() { return startPositions_; } + const SequenceIdArg& getSequenceId() const { return startPositions_; } private: SequenceIdArg startPositions_; diff --git a/paddle/function/FunctionTest.cpp b/paddle/function/FunctionTest.cpp index eb05ca9a2190d5..03c609b5242777 100644 --- a/paddle/function/FunctionTest.cpp +++ b/paddle/function/FunctionTest.cpp @@ -84,6 +84,10 @@ void testBufferArgs(const BufferArgs& inputs, } } +void testBufferArgs(const BufferArgs& inputs, const CheckBufferArg& check) { + check(inputs[0]); +} + TEST(Arguments, Matrix) { MatrixPtr matrix = Matrix::create(100, 200); CheckBufferArg check = [=](const BufferArg& arg) { @@ -144,4 +148,18 @@ TEST(Arguments, CpuSparseMatrix) { testBufferArgs(argments, checkFunc); } +TEST(Arguments, BufferArg) { + BufferArg arg(nullptr, VALUE_TYPE_FLOAT, {1, 2, 3}); + CheckBufferArg check = [=](const BufferArg& arg) { + EXPECT_EQ(arg.shape().ndims(), 3); + EXPECT_EQ(arg.shape()[0], 1); + EXPECT_EQ(arg.shape()[1], 2); + EXPECT_EQ(arg.shape()[2], 3); + }; + + BufferArgs argments; + argments.addArg(arg); + testBufferArgs(argments, check); +} + } // namespace paddle From 678174339fcc1aeb953684f795e1bf8cf1d631a5 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Fri, 13 Jan 2017 17:46:05 +0800 Subject: [PATCH 025/370] Implement the FunctionTest --- paddle/function/Function.h | 13 +- paddle/function/FunctionTest.h | 225 +++++++++++++++------------------ 2 files changed, 112 insertions(+), 126 deletions(-) diff --git a/paddle/function/Function.h b/paddle/function/Function.h index afbd4911b0a2b9..b0c6ba0facc7f8 100644 --- a/paddle/function/Function.h +++ b/paddle/function/Function.h @@ -75,8 +75,17 @@ class BufferArgs { // Tensor can be Matrix, Vector, IVector. // For inputs, do not need argType. // For outputs, the argType needs to be specified as ASSIGN_TO or ADD_TO. - template - void addArg(const Tensor& arg, ArgType argType = UNSPECIFIED) { + void addArg(const Matrix& arg, ArgType argType = UNSPECIFIED) { + _args_.push_back(new BufferArg(arg, argType)); + addArg(*_args_.back()); + } + + void addArg(const Vector& arg, ArgType argType = UNSPECIFIED) { + _args_.push_back(new BufferArg(arg, argType)); + addArg(*_args_.back()); + } + + void addArg(const IVector& arg, ArgType argType = UNSPECIFIED) { _args_.push_back(new BufferArg(arg, argType)); addArg(*_args_.back()); } diff --git a/paddle/function/FunctionTest.h b/paddle/function/FunctionTest.h index 2847188fd67989..412e3a7d1b30a7 100644 --- a/paddle/function/FunctionTest.h +++ b/paddle/function/FunctionTest.h @@ -19,6 +19,8 @@ limitations under the License. */ namespace paddle { +typedef std::shared_ptr BufferArgPtr; + /** * \brief A class for comparing CPU and GPU implementations of Function. * @@ -45,143 +47,121 @@ namespace paddle { class FunctionCompare { public: FunctionCompare(const std::string& name, const FuncConfig& config) - : cpu(FunctionBase::funcRegistrar_.createByType(name + "-CPU")), - gpu(FunctionBase::funcRegistrar_.createByType(name + "-GPU")) { - cpu->init(config); - gpu->init(config); + : cpuFunc_(FunctionBase::funcRegistrar_.createByType(name + "-CPU")), + gpuFunc_(FunctionBase::funcRegistrar_.createByType(name + "-GPU")) { + cpuFunc_->init(config); + gpuFunc_->init(config); + } + + ~FunctionCompare() {} + + // input need only contains shape, do not contains data. + void addInputs(const BufferArg& input) { + size_t size = + input.shape().getElements() * sizeOfValuType(input.valueType()); + cpuMemory_.emplace_back(std::make_shared(size)); + gpuMemory_.emplace_back(std::make_shared(size)); + + cpuInputs_.emplace_back(std::make_shared( + cpuMemory_.back()->getBuf(), input.valueType(), input.shape())); + gpuInputs_.emplace_back(std::make_shared( + gpuMemory_.back()->getBuf(), input.valueType(), input.shape())); + } + + // output need only contains shape, do not contains data. + void addOutputs(const BufferArg& output) { + size_t size = + output.shape().getElements() * sizeOfValuType(output.valueType()); + cpuMemory_.emplace_back(std::make_shared(size)); + gpuMemory_.emplace_back(std::make_shared(size)); + + cpuOutputs_.emplace_back( + std::make_shared(cpuMemory_.back()->getBuf(), + output.valueType(), + output.shape(), + ASSIGN_TO)); + gpuOutputs_.emplace_back( + std::make_shared(gpuMemory_.back()->getBuf(), + output.valueType(), + output.shape(), + ASSIGN_TO)); } - void addInputs(const BufferArg& input) { inputs.push_back(input); } + void addInputs(const SequenceArg& input) { + 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(sizeId)); + gpuMemory_.emplace_back(std::make_shared(sizeId)); - void addOutputs(const BufferArg& output) { outputs.push_back(output); } + TensorShape seqsId({numSeqs + 1}); + // void* cpuBuffer = cpuMemory_.back()->getBuf(); + // void* gpuBuffer = gpuMemory_.back()->getBuf(); + + size_t size = + input.shape().getElements() * sizeOfValuType(input.valueType()); + cpuMemory_.emplace_back(std::make_shared(size)); + gpuMemory_.emplace_back(std::make_shared(size)); + + // TODO: need be implemented. + } void run() { // prepare cpu/gpu arguments - prepareArgs(); + initInputs(); // function calculate - cpu->calc(cpuInputs, cpuOutputs); - gpu->calc(gpuInputs, gpuOutputs); - - // check outputs and inouts - auto checkArgs = [=](const BufferArgs& cpuArgs, const BufferArgs& gpuArgs) { - for (size_t i = 0; i < cpuArgs.size(); i++) { - auto cpu = cpuArgs[i]; - auto gpu = gpuArgs[i]; - CpuVector cpuVector(cpu.shape().getElements(), (real*)cpu.getData()); - GpuVector gpuVector(cpu.shape().getElements(), (real*)gpu.getData()); - - autotest::TensorCheckErr(cpuVector, gpuVector); + auto callFunction = [](FunctionBase* function, + std::vector& inputs, + std::vector& outputs) { + BufferArgs inArgs; + BufferArgs outArgs; + for (auto arg : inputs) { + inArgs.addArg(*arg); } - }; - checkArgs(cpuOutputs, gpuOutputs); - } -#if 0 - void cmpWithArg(const Arguments& inputs, - const Arguments& outputs, - const Arguments& inouts) { - // init cpu and gpu arguments - auto initArgs = [=]( - Arguments& cpuArgs, Arguments& gpuArgs, const Arguments& inArgs) { - for (const auto arg : inArgs) { - size_t size = sizeof(real); - for (const auto dim : arg.dims_) { - size *= dim; - } - if (arg.getData()) { - // todo(tianbing), waste unnecessary mem here - cpuMemory.emplace_back(std::make_shared(size)); - gpuMemory.emplace_back(std::make_shared(size)); - cpuArgs.emplace_back(Tensor((real*)arg.getData(), arg.dims_)); - gpuArgs.emplace_back(Tensor((real*)arg.getData(), arg.dims_)); - // already init outside - } else { - cpuMemory.emplace_back(std::make_shared(size)); - gpuMemory.emplace_back(std::make_shared(size)); - cpuArgs.emplace_back( - Tensor((real*)cpuMemory.back()->getBuf(), arg.dims_)); - gpuArgs.emplace_back( - Tensor((real*)gpuMemory.back()->getBuf(), arg.dims_)); - // will use an api to refactor this code. - CpuVector cpuVector(size / sizeof(real), - (real*)cpuArgs.back().getData()); - GpuVector gpuVector(size / sizeof(real), - (real*)gpuArgs.back().getData()); - cpuVector.uniform(0.001, 1); - gpuVector.copyFrom(cpuVector); - } + for (auto arg : outputs) { + outArgs.addArg(*arg); } + function->calc(inArgs, outArgs); }; - initArgs(cpuInputs, gpuInputs, inputs); - initArgs(cpuOutputs, gpuOutputs, outputs); - // function calculate - cpu->calc(cpuInputs, cpuOutputs); - gpu->calc(gpuInputs, gpuOutputs); + callFunction(cpuFunc_.get(), cpuInputs_, cpuOutputs_); + callFunction(gpuFunc_.get(), gpuInputs_, gpuOutputs_); // check outputs and inouts - auto checkArgs = [=](const Arguments& cpuArgs, const Arguments& gpuArgs) { - for (size_t i = 0; i < cpuArgs.size(); i++) { - auto cpu = cpuArgs[i]; - auto gpu = gpuArgs[i]; - size_t size = 1; - for (auto dim : cpu.dims_) { - size *= dim; - } - CpuVector cpuVector(size, (real*)cpu.getData()); - GpuVector gpuVector(size, (real*)gpu.getData()); - - autotest::TensorCheckErr(cpuVector, gpuVector); - } - }; - checkArgs(cpuOutputs, gpuOutputs); + compareOutputs(); } -#endif - std::shared_ptr getCpuFunction() const { return cpu; } + std::shared_ptr getCpuFunction() const { return cpuFunc_; } - std::shared_ptr getGpuFunction() const { return gpu; } + std::shared_ptr getGpuFunction() const { return gpuFunc_; } protected: - void prepareArgs() { - // TODO, if inputs has data - } + void initInputs() { + for (size_t i = 0; i < cpuInputs_.size(); i++) { + initArg(*cpuInputs_[i]); - void createArg(BufferArgs& cpuArgs, BufferArgs& gpuArgs, BufferArg& arg) { - size_t size = arg.shape().getElements() * sizeOfValuType(arg.valueType()); - cpuMemory_.emplace_back(std::make_shared(size)); - gpuMemory_.emplace_back(std::make_shared(size)); + // TODO: Need a BufferCopy used to copy from one BufferArg to another. + CpuVector cpuVector(cpuInputs_[i]->shape().getElements(), + (real*)cpuInputs_[i]->data()); + GpuVector gpuVector(gpuInputs_[i]->shape().getElements(), + (real*)gpuInputs_[i]->data()); - cpuArgs.emplace_back( - BufferArg(cpuMemory_.back()->getBuf()), arg.valueType(), arg.shape()); - gpuArgs.emplace_back( - BufferArg(gpuMemory_.back()->getBuf()), arg.valueType(), arg.shape()); + gpuVector.copyFrom(cpuVector); + } } - void createArg(BufferArgs& cpuArgs, BufferArgs& gpuArgs, SequenceArg& arg) { - size_t batchSize = arg.shape()[0]; - size_t numSeqs = batchSize / 10 + 1; + void compareOutputs() { + for (size_t i = 0; i < cpuOutputs_.size(); i++) { + // TODO, Need a BufferCheck used to compare the two buffers. + auto cpu = cpuOutputs_[i]; + auto gpu = gpuOutputs_[i]; + CpuVector cpuVector(cpu->shape().getElements(), (real*)cpu->data()); + GpuVector gpuVector(cpu->shape().getElements(), (real*)gpu->data()); - size_t sizeId = (numSeqs + 1) * sizeOfValuType(VALUE_TYPE_INT32); - cpuMemory_.emplace_back(std::make_shared(size)); - gpuMemory_.emplace_back(std::make_shared(size)); - - TensorShape seqsId({numSeqs + 1}); - void* cpuBuffer = cpuMemory_.back()->getBuf(); - void* gpuBuffer = gpuMemory_.back()->getBuf(); - - size_t size = arg.shape().getElements() * sizeOfValuType(arg.valueType()); - cpuMemory_.emplace_back(std::make_shared(size)); - gpuMemory_.emplace_back(std::make_shared(size)); - - cpuArgs.emplace_back(SequenceArg(cpuMemory_.back()->getBuf(), - arg.valueType(), - arg.shape(), - SequenceIdArg(cpuBuffer, seqsId))); - gpuArgs.emplace_back(SequenceArg(gpuMemory_.back()->getBuf(), - arg.valueType(), - arg.shape(), - SequenceIdArg(gpuBuffer, seqsId))); + autotest::TensorCheckErr(cpuVector, gpuVector); + } } // only init cpu argument, gpu argument copy from cpu argument. @@ -192,10 +172,10 @@ class FunctionCompare { void initArg(SequenceIdArg& arg, size_t batchSize) { size_t numSeqs = arg.numSeqs(); - int* buf = arg.data(); + int* buf = (int*)arg.data(); int pos = 0; size_t maxLen = 2 * batchSize / numSeqs; - for (int i = 0; i < numSeqs; ++i) { + for (int i = 0; i < (int)numSeqs; ++i) { int len = uniformRandom( std::min(maxLen, batchSize - pos - numSeqs + i)) + 1; @@ -207,17 +187,14 @@ class FunctionCompare { } protected: - std::shared_ptr cpu; - std::shared_ptr gpu; + std::shared_ptr cpuFunc_; + std::shared_ptr gpuFunc_; std::vector cpuMemory_; std::vector gpuMemory_; - // inputs and outputs - BufferArgs inputs; - BufferArgs outputs; - BufferArgs cpuInputs_; - BufferArgs cpuOutputs_; - BufferArgs gpuInputs_; - BufferArgs gpuOutputs_; + std::vector cpuInputs_; + std::vector cpuOutputs_; + std::vector gpuInputs_; + std::vector gpuOutputs_; }; } // namespace paddle From b791dcddcc0d83c7397cbd075ccce08b60dfcb27 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Fri, 13 Jan 2017 17:56:44 +0800 Subject: [PATCH 026/370] Fix CrossMapNormal Test --- paddle/function/CMakeLists.txt | 2 +- paddle/function/CrossMapNormalOpTest.cpp | 51 ++++++++++++++---------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/paddle/function/CMakeLists.txt b/paddle/function/CMakeLists.txt index 75a2acc55ec3d3..566fe53b14d85d 100644 --- a/paddle/function/CMakeLists.txt +++ b/paddle/function/CMakeLists.txt @@ -19,7 +19,7 @@ if(WITH_TESTING) # TODO: # file(GLOB test_files . *OpTest.cpp) # add_executable(${test_bin} EXCLUDE_FROM_ALL ${test_files}) - # add_simple_unittest(CrossMapNormalOpTest) + add_simple_unittest(CrossMapNormalOpTest) add_simple_unittest(TensorShapeTest) add_simple_unittest(TensorTypeTest) add_simple_unittest(BufferArgTest) diff --git a/paddle/function/CrossMapNormalOpTest.cpp b/paddle/function/CrossMapNormalOpTest.cpp index d65d9310affd7c..da196a699cc32b 100644 --- a/paddle/function/CrossMapNormalOpTest.cpp +++ b/paddle/function/CrossMapNormalOpTest.cpp @@ -27,15 +27,19 @@ TEST(CrossMapNormal, real) { << " imgSizeH=" << imgSizeH << " imgSizeW=" << imgSizeW << " size=" << size; - FunctionCompare compare("CrossMapNormal", - FuncConfig() - .set("size", size) - .set("scale", (real)1.5) - .set("pow", (real)0.5)); - Dims dims{numSamples, channels, imgSizeH, imgSizeW}; - compare.cmpWithArg({Tensor(nullptr, dims)}, - {Tensor(nullptr, dims), Tensor(nullptr, dims)}, - {}); + // init Test object + FunctionCompare test("CrossMapNormal", + FuncConfig() + .set("size", size) + .set("scale", (real)1.5) + .set("pow", (real)0.5)); + // prepare input arguments + TensorShape shape{numSamples, channels, imgSizeH, imgSizeW}; + test.addInputs(BufferArg(VALUE_TYPE_FLOAT, shape)); + test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, shape)); + test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, shape)); + // run Function + test.run(); } } } @@ -43,6 +47,9 @@ TEST(CrossMapNormal, real) { } } +#if 0 +// TODO(hedaoyuan): Now CrossMapNormalGrad not support ASSIGN_TO mode. +// Maybe all Function need support ASSIGN_TO mode. TEST(CrossMapNormalGrad, real) { for (size_t numSamples : {5, 32}) { for (size_t channels : {1, 5, 32}) { @@ -53,23 +60,25 @@ TEST(CrossMapNormalGrad, real) { << " imgSizeH=" << imgSizeH << " imgSizeW=" << imgSizeW << " size=" << size; - FunctionCompare compare("CrossMapNormalGrad", - FuncConfig() - .set("size", size) - .set("scale", (real)1.5) - .set("pow", (real)0.5)); - Dims dims{numSamples, channels, imgSizeH, imgSizeW}; - compare.cmpWithArg({Tensor(nullptr, dims), - Tensor(nullptr, dims), - Tensor(nullptr, dims), - Tensor(nullptr, dims)}, - {Tensor(nullptr, dims)}, - {}); + FunctionCompare test("CrossMapNormalGrad", + FuncConfig() + .set("size", size) + .set("scale", (real)1.5) + .set("pow", (real)0.5)); + TensorShape shape{numSamples, channels, imgSizeH, imgSizeW}; + test.addInputs(BufferArg(VALUE_TYPE_FLOAT, shape)); + test.addInputs(BufferArg(VALUE_TYPE_FLOAT, shape)); + test.addInputs(BufferArg(VALUE_TYPE_FLOAT, shape)); + test.addInputs(BufferArg(VALUE_TYPE_FLOAT, shape)); + test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, shape)); + // run Function + test.run(); } } } } } } +#endif } // namespace paddle From 2efdd460dac2ff0ed15a9b8ba079bc83e10e6d0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=9B=8A?= Date: Fri, 13 Jan 2017 13:48:47 -0800 Subject: [PATCH 027/370] Add Dockerfile.dev for building a standard develop environment --- paddle/scripts/docker/Dockerfile.dev | 47 ++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 paddle/scripts/docker/Dockerfile.dev diff --git a/paddle/scripts/docker/Dockerfile.dev b/paddle/scripts/docker/Dockerfile.dev new file mode 100644 index 00000000000000..e60b9e30732583 --- /dev/null +++ b/paddle/scripts/docker/Dockerfile.dev @@ -0,0 +1,47 @@ +FROM ubuntu:16.04 +MAINTAINER PaddlePaddle Authors + +ARG DEBIAN_FRONTEND=noninteractive +ARG UBUNTU_MIRROR +RUN /bin/bash -c 'if [[ -n ${UBUNTU_MIRROR} ]]; then sed -i 's#http://archive.ubuntu.com#${UBUNTU_MIRROR}#g' /etc/apt/sources.list; fi' + +RUN apt-get update \ + && apt-get install -y cmake libprotobuf-dev protobuf-compiler git \ + libgoogle-glog-dev libgflags-dev libgtest-dev \ + libatlas-dev libatlas3-base g++ m4 python-pip \ + python-protobuf python-numpy python-dev swig openssh-server \ + wget unzip python-matplotlib tar xz-utils bzip2 gzip coreutils \ + sed grep graphviz libjpeg-dev zlib1g-dev doxygen \ + clang-3.8 llvm-3.8 libclang-3.8-dev clang-format-3.8 clang-tidy-3.8 \ + && apt-get clean -y +RUN cd /usr/src/gtest && cmake . && make && cp *.a /usr/lib +RUN pip install -U BeautifulSoup docopt PyYAML pillow \ + sphinx sphinx_rtd_theme recommonmark jupyter + +ARG WITH_AVX +ARG WITH_DOC +ARG WITH_SWIG_PY +ARG WITH_STYLE_CHECK + +ENV WITH_GPU=OFF +ENV WITH_AVX=${WITH_AVX:-ON} +ENV WITH_DOC=${WITH_DOC:-ON} +ENV WITH_SWIG_PY=${WITH_SWIG_PY:-ON} +ENV WITH_STYLE_CHECK=${WITH_STYLE_CHECK:-OFF} + +RUN echo 'export LD_LIBRARY_PATH=/usr/lib64:${LD_LIBRARY_PATH}' >> /etc/profile + +# Configure OpenSSH server. c.f. https://docs.docker.com/engine/examples/running_ssh_service +RUN mkdir /var/run/sshd +RUN echo 'root:root' | chpasswd +RUN sed -ri 's/^PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config +RUN sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config +EXPOSE 22 + +# Jupyter Notebook directory. +RUN mkdir /notes/ +WORKDIR "/notes" +EXPOSE 8888 + +RUN mkdir -p /opt/bin +COPY ./paddle/scripts/docker/entrypoint /opt/bin/ From 02480316016bd04c10676d8cb859c473f07a819f Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 12 Jan 2017 17:18:39 +0800 Subject: [PATCH 028/370] Add Status --- paddle/utils/Status.h | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 paddle/utils/Status.h diff --git a/paddle/utils/Status.h b/paddle/utils/Status.h new file mode 100644 index 00000000000000..398ae182ab053e --- /dev/null +++ b/paddle/utils/Status.h @@ -0,0 +1,39 @@ +/* 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 +#include + +namespace paddle { + +class Status final : public std::exception { +public: + Status() noexcept {} + + Status(const std::string& msg) : errMsg_(new std::string(msg)) {} + + virtual const char* what() const noexcept override { + if (errMsg_) { + return errMsg_->data(); + } else { + return nullptr; + } + } + + inline bool isOK() const noexcept { return errMsg_ == nullptr; } + +private: + std::unique_ptr errMsg_; +}; + +} // namespace paddle From 6c20e08b042e1351a4ea8c97a74129d211b1d636 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 12 Jan 2017 17:55:36 +0800 Subject: [PATCH 029/370] Try using status to handle Paddle Error --- .../activations/ActivationFunction.cpp | 126 ++++++++++++++---- .../gserver/activations/ActivationFunction.h | 5 +- paddle/gserver/layers/Layer.cpp | 7 +- paddle/utils/Status.h | 36 ++++- paddle/utils/tests/CMakeLists.txt | 1 + paddle/utils/tests/test_Status.cpp | 29 ++++ 6 files changed, 169 insertions(+), 35 deletions(-) create mode 100644 paddle/utils/tests/test_Status.cpp diff --git a/paddle/gserver/activations/ActivationFunction.cpp b/paddle/gserver/activations/ActivationFunction.cpp index f8c4bcac2f8eb4..8a938cf7e9d730 100644 --- a/paddle/gserver/activations/ActivationFunction.cpp +++ b/paddle/gserver/activations/ActivationFunction.cpp @@ -69,8 +69,14 @@ static ClassRegistrar gActivationRegistrar; class IdentityActivation : public ActivationFunction { public: static const std::string name; - void forward(Argument& act) { (void)act; } - void backward(Argument& act) { (void)act; } + Status forward(Argument& act) { + (void)act; + return Status(); + } + Status backward(Argument& act) { + (void)act; + return Status(); + } const std::string& getName() const { return name; } }; const std::string IdentityActivation::name = ""; @@ -86,8 +92,14 @@ static InitFunction __reg_activation__identity([] { * \f] */ BEGIN_DEFINE_ACTIVATION(sigmoid) -void forward(Argument& act) { act.value->sigmoid(*act.value); } -void backward(Argument& act) { act.grad->sigmoidDerivative(*act.value); } +Status forward(Argument& act) { + act.value->sigmoid(*act.value); + return Status(); +} +Status backward(Argument& act) { + act.grad->sigmoidDerivative(*act.value); + return Status(); +} END_DEFINE_ACTIVATION(sigmoid) /** @@ -103,9 +115,12 @@ MatrixPtr sftMaxDot_; MatrixPtr one_; public: -void forward(Argument& act) { act.value->softmax(*act.value); } +Status forward(Argument& act) { + act.value->softmax(*act.value); + return Status(); +} -void backward(Argument& act) { +Status backward(Argument& act) { MatrixPtr outputV = act.value; MatrixPtr outputG = act.grad; @@ -137,6 +152,7 @@ void backward(Argument& act) { act.grad->softmaxDerivative(*act.value, *sftMaxSum_); } + return Status(); } END_DEFINE_ACTIVATION(softmax) @@ -151,8 +167,11 @@ ACTIVATION_CLASS_NAME(softmax) softmax_; Argument argument_; public: -void forward(Argument& act) { - CHECK_EQ(act.value->getWidth(), 1UL); +Status forward(Argument& act) { + if (act.value->getWidth() != 1UL) { + return Status( + "Input width for each timestep of sequence softmax should be 1"); + } if (!argument_.value) { argument_.value = Matrix::create(nullptr, @@ -169,10 +188,14 @@ void forward(Argument& act) { auto starts = act.sequenceStartPositions->getVector(useGpu(act.deviceId)); act.value->sequenceSoftmax(*act.value, *starts); + return Status(); } -void backward(Argument& act) { - CHECK_EQ(act.grad->getWidth(), 1UL); +Status backward(Argument& act) { + if (act.value->getWidth() != 1UL) { + return Status( + "Input width for each timestep of sequence softmax should be 1"); + } size_t numSequences = act.getNumSequences(); const int* starts = act.sequenceStartPositions->getData(false); @@ -186,6 +209,7 @@ void backward(Argument& act) { softmax_.backward(argument_); } + return Status(); } END_DEFINE_ACTIVATION(sequence_softmax) @@ -200,9 +224,15 @@ END_DEFINE_ACTIVATION(sequence_softmax) * 0 otherwise. */ BEGIN_DEFINE_ACTIVATION(relu) -void forward(Argument& act) { act.value->relu(*act.value); } +Status forward(Argument& act) { + act.value->relu(*act.value); + return Status(); +} -void backward(Argument& act) { act.grad->reluDerivative(*act.value); } +Status backward(Argument& act) { + act.grad->reluDerivative(*act.value); + return Status(); +} END_DEFINE_ACTIVATION(relu) /** @@ -219,9 +249,15 @@ END_DEFINE_ACTIVATION(relu) * TODO(yuyang18): Remove magic number 24 or make it configuable. */ BEGIN_DEFINE_ACTIVATION(brelu) -void forward(Argument& act) { act.value->brelu(*act.value); } +Status forward(Argument& act) { + act.value->brelu(*act.value); + return Status(); +} -void backward(Argument& act) { act.grad->breluDerivative(*act.value); } +Status backward(Argument& act) { + act.grad->breluDerivative(*act.value); + return Status(); +} END_DEFINE_ACTIVATION(brelu) /** @@ -231,9 +267,15 @@ END_DEFINE_ACTIVATION(brelu) * \f] */ BEGIN_DEFINE_ACTIVATION(tanh) -void forward(Argument& act) { act.value->tanh(*act.value); } +Status forward(Argument& act) { + act.value->tanh(*act.value); + return Status(); +} -void backward(Argument& act) { act.grad->tanhDerivative(*act.value); } +Status backward(Argument& act) { + act.grad->tanhDerivative(*act.value); + return Status(); +} END_DEFINE_ACTIVATION(tanh) /** @@ -248,10 +290,14 @@ real a, b; public: ACTIVATION_CLASS_NAME(stanh)() : a(1.7159), b(2. / 3.) {} -void forward(Argument& act) { act.value->scaledTanh(*act.value, a, b); } +Status forward(Argument& act) { + act.value->scaledTanh(*act.value, a, b); + return Status(); +} -void backward(Argument& act) { +Status backward(Argument& act) { act.grad->scaledTanhDerivative(*act.value, a, b); + return Status(); } END_DEFINE_ACTIVATION(stanh) @@ -262,9 +308,15 @@ END_DEFINE_ACTIVATION(stanh) * \f] */ BEGIN_DEFINE_ACTIVATION(softrelu) -void forward(Argument& act) { act.value->softrelu(*act.value); } +Status forward(Argument& act) { + act.value->softrelu(*act.value); + return Status(); +} -void backward(Argument& act) { act.grad->softreluDerivative(*act.value); } +Status backward(Argument& act) { + act.grad->softreluDerivative(*act.value); + return Status(); +} END_DEFINE_ACTIVATION(softrelu) /** @@ -280,7 +332,7 @@ END_DEFINE_ACTIVATION(softrelu) * 0 if z=0 */ BEGIN_DEFINE_ACTIVATION(abs) -void forward(Argument& act) { +Status forward(Argument& act) { SetDevice device(act.deviceId); Matrix::resizeOrCreate(act.in, act.value->getHeight(), @@ -290,9 +342,13 @@ void forward(Argument& act) { act.in->copyFrom(*act.value); act.value->abs2(*act.value); + return Status(); } -void backward(Argument& act) { act.grad->absDerivative(*act.in); } +Status backward(Argument& act) { + act.grad->absDerivative(*act.in); + return Status(); +} END_DEFINE_ACTIVATION(abs) /** @@ -302,7 +358,7 @@ END_DEFINE_ACTIVATION(abs) * \f] */ BEGIN_DEFINE_ACTIVATION(square) -void forward(Argument& act) { +Status forward(Argument& act) { SetDevice device(act.deviceId); Matrix::resizeOrCreate(act.in, act.value->getHeight(), @@ -312,9 +368,13 @@ void forward(Argument& act) { act.in->copyFrom(*act.value); act.value->square2(*act.value); + return Status(); } -void backward(Argument& act) { act.grad->squareDerivative(*act.in); } +Status backward(Argument& act) { + act.grad->squareDerivative(*act.in); + return Status(); +} END_DEFINE_ACTIVATION(square) /** @@ -324,9 +384,15 @@ END_DEFINE_ACTIVATION(square) * \f] */ BEGIN_DEFINE_ACTIVATION(exponential) -void forward(Argument& act) { act.value->exp2(*act.value); } +Status forward(Argument& act) { + act.value->exp2(*act.value); + return Status(); +} -void backward(Argument& act) { act.grad->expDerivative(*act.value); } +Status backward(Argument& act) { + act.grad->expDerivative(*act.value); + return Status(); +} END_DEFINE_ACTIVATION(exponential) /** @@ -336,7 +402,7 @@ END_DEFINE_ACTIVATION(exponential) * \f] */ BEGIN_DEFINE_ACTIVATION(log) -void forward(Argument& act) { +Status forward(Argument& act) { SetDevice device(act.deviceId); Matrix::resizeOrCreate(act.in, act.value->getHeight(), @@ -346,9 +412,13 @@ void forward(Argument& act) { act.in->copyFrom(*act.value); act.value->log2(*act.value); + return Status(); } -void backward(Argument& act) { act.grad->dotDiv(*act.grad, *act.in); } +Status backward(Argument& act) { + act.grad->dotDiv(*act.grad, *act.in); + return Status(); +} END_DEFINE_ACTIVATION(log) ActivationFunction* ActivationFunction::create(const std::string& type) { diff --git a/paddle/gserver/activations/ActivationFunction.h b/paddle/gserver/activations/ActivationFunction.h index 601e3b6c0cd401..ad395ac28da7d9 100644 --- a/paddle/gserver/activations/ActivationFunction.h +++ b/paddle/gserver/activations/ActivationFunction.h @@ -15,6 +15,7 @@ limitations under the License. */ #pragma once #include #include +#include "paddle/utils/Status.h" namespace paddle { @@ -48,7 +49,7 @@ class ActivationFunction { * * Usually, act is Layer::output_ */ - virtual void forward(Argument& act) = 0; + virtual Status forward(Argument& act) = 0; /** * @brief Backward propagaion @@ -57,7 +58,7 @@ class ActivationFunction { * - Before calling backward(), act.grad = dE / dy, where E is the error/cost * - After backward() returns, act.grad = dE / dx = (dE/dy) * (dy/dx) */ - virtual void backward(Argument& act) = 0; + virtual Status backward(Argument& act) = 0; virtual const std::string& getName() const = 0; }; diff --git a/paddle/gserver/layers/Layer.cpp b/paddle/gserver/layers/Layer.cpp index c47943f81c0158..06c936c3aec670 100644 --- a/paddle/gserver/layers/Layer.cpp +++ b/paddle/gserver/layers/Layer.cpp @@ -16,6 +16,7 @@ limitations under the License. */ #include "paddle/math/SparseMatrix.h" #include "paddle/utils/Logging.h" +#include "paddle/utils/Status.h" #include "AddtoLayer.h" #include "CRFLayer.h" @@ -334,7 +335,8 @@ void Layer::showOutputStats() { void Layer::forwardActivation() { /* activation */ - activation_->forward(output_); + auto status = activation_->forward(output_); + CHECK(status.isOK()) << status.what(); /* dropout */ if (config_.drop_rate() > 0) { @@ -372,7 +374,8 @@ void Layer::backwardActivation() { oGrad->dotMul(*oGrad, *dropOutMask_); } - activation_->backward(output_); + auto status = activation_->backward(output_); + CHECK(status.isOK()) << status.what(); } void Layer::forwardDropOut() { diff --git a/paddle/utils/Status.h b/paddle/utils/Status.h index 398ae182ab053e..3456d7b686f0d9 100644 --- a/paddle/utils/Status.h +++ b/paddle/utils/Status.h @@ -11,18 +11,44 @@ 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 #include namespace paddle { +/** + * Status is Paddle error code. It only contain a std::string as error message. + * Although Status inherits the std::exception, but do not throw it except you + * know what you are doing. + */ class Status final : public std::exception { public: + /** + * Default Status. OK + */ Status() noexcept {} - Status(const std::string& msg) : errMsg_(new std::string(msg)) {} + /** + * @brief Create Status with error message + * @param msg + */ + explicit Status(const std::string& msg) : errMsg_(new std::string(msg)) {} + + /** + * @brief set a error message for status. + * @param msg + */ + inline void set(const std::string& msg) noexcept { + errMsg_.reset(new std::string(msg)); + } - virtual const char* what() const noexcept override { + /** + * @brief what will return the error message. If status is OK, return nullptr. + */ + const char* what() const noexcept override { if (errMsg_) { return errMsg_->data(); } else { @@ -30,10 +56,14 @@ class Status final : public std::exception { } } + /** + * @brief isOK + * @return true if OK. + */ inline bool isOK() const noexcept { return errMsg_ == nullptr; } private: - std::unique_ptr errMsg_; + std::shared_ptr errMsg_; }; } // namespace paddle diff --git a/paddle/utils/tests/CMakeLists.txt b/paddle/utils/tests/CMakeLists.txt index 26fafbd1ab3f29..a1cc32668d5100 100644 --- a/paddle/utils/tests/CMakeLists.txt +++ b/paddle/utils/tests/CMakeLists.txt @@ -4,6 +4,7 @@ add_simple_unittest(test_CustomStackTrace) add_simple_unittest(test_ThreadBarrier) add_simple_unittest(test_SpinLock) add_simple_unittest(test_SIMDFlags) +add_simple_unittest(test_Status) add_executable( test_CustomStackTracePrint diff --git a/paddle/utils/tests/test_Status.cpp b/paddle/utils/tests/test_Status.cpp new file mode 100644 index 00000000000000..e2c2ae537d8b62 --- /dev/null +++ b/paddle/utils/tests/test_Status.cpp @@ -0,0 +1,29 @@ +/* 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 "paddle/utils/Status.h" + +#include + +TEST(Status, testAll) { + paddle::Status status; + ASSERT_TRUE(status.isOK()); + status.set("I'm the error"); + ASSERT_FALSE(status.isOK()); + ASSERT_STREQ("I'm the error", status.what()); + + paddle::Status status2("error2"); + ASSERT_FALSE(status2.isOK()); + ASSERT_STREQ("error2", status2.what()); +} From df62df7e6726b502d34ed5805ba26f44b7cfdd92 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sat, 14 Jan 2017 16:30:24 +0800 Subject: [PATCH 030/370] Partially follow comments --- paddle/math/RowBuffer.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/paddle/math/RowBuffer.h b/paddle/math/RowBuffer.h index bb55ca5f9f0d24..0edcefd7562460 100644 --- a/paddle/math/RowBuffer.h +++ b/paddle/math/RowBuffer.h @@ -47,7 +47,7 @@ class RowBuffer { */ inline void resize(int rowCnt) { if (preallocatedBuf_) { - CHECK(preallocatedBuf_->getSize() < rowCnt * width_ * sizeof(real)); + CHECK(preallocatedBuf_->getSize() >= rowCnt * width_ * sizeof(real)); } else { rowStore_.resize(rowCnt * width_); } @@ -107,7 +107,7 @@ class RowBuffer { */ inline size_t getRowCount() const { if (preallocatedBuf_) { - return preallocatedBuf_->getSize() / sizeof(float) / width_; + return preallocatedBuf_->getSize() / sizeof(real) / width_; } else { return rowStore_.size() / width_; } @@ -117,7 +117,7 @@ class RowBuffer { * @brief get is this buffer can automatically grow or not. * @return ture if can automacitally grow. */ - inline bool isAutoGrowth() const { return preallocatedBuf_ == nullptr; } + inline bool isAutoGrowth() const { return !preallocatedBuf_; } /** * @brief return the width of matrix. a.k.a length of row. From cdf6af64a87c46da070da139925c32cc4064e6d3 Mon Sep 17 00:00:00 2001 From: liaogang Date: Sat, 14 Jan 2017 21:42:04 +0800 Subject: [PATCH 031/370] Add external openblas --- .travis.yml | 2 +- cmake/external/openblas.cmake | 32 +++++++++++++++---- cmake/system.cmake | 4 +-- .../build_and_install/build_from_source_en.md | 5 +-- paddle/scripts/travis/before_install.osx.sh | 4 +-- paddle/scripts/travis/build_and_test.sh | 2 +- paddle/scripts/travis/docs.sh | 2 +- 7 files changed, 34 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0705baa1aca8b4..162bebba091d84 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,9 +25,9 @@ addons: packages: - gcc-4.8 - g++-4.8 + - gfortran-4.8 - git - build-essential - - libatlas-base-dev - python - python-pip - python2.7-dev diff --git a/cmake/external/openblas.cmake b/cmake/external/openblas.cmake index 0e8c29c831c823..43ebb39cd6f3aa 100644 --- a/cmake/external/openblas.cmake +++ b/cmake/external/openblas.cmake @@ -15,7 +15,6 @@ INCLUDE(cblas) IF(NOT ${CBLAS_FOUND}) - MESSAGE(FATAL_ERROR "Please install OpenBlas, MKL or ATLAS.") INCLUDE(ExternalProject) SET(CBLAS_SOURCES_DIR ${THIRD_PARTY_PATH}/openblas) @@ -28,20 +27,39 @@ IF(NOT ${CBLAS_FOUND}) SET(CBLAS_LIBRARIES "${CBLAS_INSTALL_DIR}/lib/libopenblas.a" CACHE FILEPATH "openblas library" FORCE) ENDIF(WIN32) + IF(CMAKE_COMPILER_IS_GNUCC) + ENABLE_LANGUAGE(Fortran) + LIST(APPEND CBLAS_LIBRARIES gfortran pthread) + ENDIF(CMAKE_COMPILER_IS_GNUCC) + + IF(NOT CMAKE_Fortran_COMPILER) + MESSAGE(FATAL_ERROR "To build lapack in libopenblas, " + "you need to set gfortran compiler: cmake .. -DCMAKE_Fortran_COMPILER=...") + ENDIF(NOT CMAKE_Fortran_COMPILER) + ExternalProject_Add( openblas - ${EXTERNAL_PROJECT_LOG_ARGS} - URL "https://github.com/xianyi/OpenBLAS/archive/v0.2.19.tar.gz" + GIT_REPOSITORY https://github.com/xianyi/OpenBLAS.git + GIT_TAG v0.2.19 PREFIX ${CBLAS_SOURCES_DIR} INSTALL_DIR ${CBLAS_INSTALL_DIR} BUILD_IN_SOURCE 1 - CONFIGURE_COMMAND "" - BUILD_COMMAND make CC=${CMAKE_C_COMPILER} FC=${CMAKE_Fortran_COMPILER} - INSTALL_COMMAND make install PREFIX= + BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} FC=${CMAKE_Fortran_COMPILER} CC=${CMAKE_C_COMPILER} HOSTCC=${CMAKE_C_COMPILER} NO_SHARED=1 libs netlib + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} install NO_SHARED=1 PREFIX= UPDATE_COMMAND "" + CONFIGURE_COMMAND "" + ) + + ExternalProject_Add_Step( + openblas lapacke_install + COMMAND ${CMAKE_COMMAND} -E copy "${CBLAS_SOURCES_DIR}/src/openblas/lapack-netlib/LAPACKE/include/lapacke_mangling_with_flags.h" "${CBLAS_INSTALL_DIR}/include/lapacke_mangling.h" + COMMAND ${CMAKE_COMMAND} -E copy "${CBLAS_SOURCES_DIR}/src/openblas/lapack-netlib/LAPACKE/include/lapacke.h" "${CBLAS_INSTALL_DIR}/include/lapacke.h" + COMMAND ${CMAKE_COMMAND} -E copy "${CBLAS_SOURCES_DIR}/src/openblas/lapack-netlib/LAPACKE/include/lapacke_config.h" "${CBLAS_INSTALL_DIR}/include/lapacke_config.h" + COMMAND ${CMAKE_COMMAND} -E copy "${CBLAS_SOURCES_DIR}/src/openblas/lapack-netlib/LAPACKE/include/lapacke_utils.h" "${CBLAS_INSTALL_DIR}/include/lapacke_utils.h" + DEPENDEES install ) LIST(APPEND external_project_dependencies openblas) -ENDIF() +ENDIF(NOT ${CBLAS_FOUND}) INCLUDE_DIRECTORIES(${CBLAS_INC_DIR}) diff --git a/cmake/system.cmake b/cmake/system.cmake index 788db404ebfb6f..1e9f79496441c8 100644 --- a/cmake/system.cmake +++ b/cmake/system.cmake @@ -47,7 +47,7 @@ SET(EXTERNAL_PROJECT_LOG_ARGS LOG_DOWNLOAD 0 # Wrap download in script to log output LOG_UPDATE 1 # Wrap update in script to log output LOG_CONFIGURE 1 # Wrap configure in script to log output - LOG_BUILD 1 # Wrap build in script to log output + LOG_BUILD 0 # Wrap build in script to log output LOG_TEST 1 # Wrap test in script to log output - LOG_INSTALL 1 # Wrap install in script to log output + LOG_INSTALL 0 # Wrap install in script to log output ) diff --git a/doc/getstarted/build_and_install/build_from_source_en.md b/doc/getstarted/build_and_install/build_from_source_en.md index 6954be3b2bb956..1abd7b698bc09c 100644 --- a/doc/getstarted/build_and_install/build_from_source_en.md +++ b/doc/getstarted/build_and_install/build_from_source_en.md @@ -64,7 +64,8 @@ As a simple example, consider the following: 1. **BLAS Dependencies(optional)** - Paddle will find BLAS from system's default path. But you can specify MKL, OpenBLAS or ATLAS via `MKL_ROOT`, `OPENBLAS_ROOT` or `ATLAS_ROOT`. + CMake will search BLAS libraries from system. If not found, OpenBLAS will be downloaded, built and installed automatically. + To utilize preinstalled BLAS, you can simply specify MKL, OpenBLAS or ATLAS via `MKL_ROOT`, `OPENBLAS_ROOT` or `ATLAS_ROOT`. ```bash # specify MKL @@ -99,7 +100,7 @@ As a simple example, consider the following: ```bash # necessary sudo apt-get update - sudo apt-get install -y g++ make cmake build-essential libatlas-base-dev python python-pip libpython-dev git + sudo apt-get install -y g++ make cmake build-essential python python-pip libpython-dev git sudo pip install wheel numpy sudo pip install 'protobuf>=3.0.0' ``` diff --git a/paddle/scripts/travis/before_install.osx.sh b/paddle/scripts/travis/before_install.osx.sh index 7036f971fdd7ba..80f031a74e7052 100755 --- a/paddle/scripts/travis/before_install.osx.sh +++ b/paddle/scripts/travis/before_install.osx.sh @@ -1,6 +1,4 @@ #!/bin/bash brew update brew tap homebrew/science -brew install python -sudo pip install --upgrade protobuf -brew install swig openblas md5sha1sum protobuf +brew install openblas swig md5sha1sum diff --git a/paddle/scripts/travis/build_and_test.sh b/paddle/scripts/travis/build_and_test.sh index fd3aeb02b21d65..5e6350b5745859 100755 --- a/paddle/scripts/travis/build_and_test.sh +++ b/paddle/scripts/travis/build_and_test.sh @@ -6,7 +6,7 @@ if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export PYTHONPATH=/opt/python/2.7.12/lib/python2.7/site-packages export PYTHONHOME=/opt/python/2.7.12 export PATH=/opt/python/2.7.12/bin:${PATH} - cmake .. -DON_TRAVIS=ON -DON_COVERALLS=ON -DCOVERALLS_UPLOAD=ON ${EXTRA_CMAKE_OPTS} + cmake .. -DCMAKE_Fortran_COMPILER=/usr/bin/gfortran-4.8 -DON_TRAVIS=ON -DON_COVERALLS=ON -DCOVERALLS_UPLOAD=ON ${EXTRA_CMAKE_OPTS} NRPOC=`nproc` make -j $NPROC make coveralls diff --git a/paddle/scripts/travis/docs.sh b/paddle/scripts/travis/docs.sh index bdafb145bcd4e5..6b43cad20b76e9 100755 --- a/paddle/scripts/travis/docs.sh +++ b/paddle/scripts/travis/docs.sh @@ -4,7 +4,7 @@ source ./common.sh # Compile Documentation only. -cmake .. -DCMAKE_BUILD_TYPE=Debug -DWITH_GPU=OFF -DWITH_DOC=ON ${EXTRA_CMAKE_OPTS} +cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_Fortran_COMPILER=/usr/bin/gfortran-4.8 -DWITH_GPU=OFF -DWITH_DOC=ON ${EXTRA_CMAKE_OPTS} make paddle_docs paddle_docs_cn # check websites for broken links From 589bb84241baca1f53cee290b55ced88c331fc02 Mon Sep 17 00:00:00 2001 From: liaogang Date: Sat, 14 Jan 2017 21:53:52 +0800 Subject: [PATCH 032/370] Add openblas log configuration --- cmake/external/openblas.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/external/openblas.cmake b/cmake/external/openblas.cmake index 43ebb39cd6f3aa..29d17691db9f45 100644 --- a/cmake/external/openblas.cmake +++ b/cmake/external/openblas.cmake @@ -39,6 +39,7 @@ IF(NOT ${CBLAS_FOUND}) ExternalProject_Add( openblas + ${EXTERNAL_PROJECT_LOG_ARGS} GIT_REPOSITORY https://github.com/xianyi/OpenBLAS.git GIT_TAG v0.2.19 PREFIX ${CBLAS_SOURCES_DIR} From 35d7b17f79342431c7e392e4644140326d37feca Mon Sep 17 00:00:00 2001 From: liaogang Date: Sun, 15 Jan 2017 00:02:57 +0800 Subject: [PATCH 033/370] Disable externel python --- cmake/external/python.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/external/python.cmake b/cmake/external/python.cmake index 29247d5c3d474a..209e679f2cb217 100644 --- a/cmake/external/python.cmake +++ b/cmake/external/python.cmake @@ -31,6 +31,7 @@ IF(PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) "please use pip to upgrade protobuf.") ENDIF(${PY_GOOGLE.PROTOBUF_VERSION} VERSION_LESS "3.0.0") ELSE(PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) + MESSAGE(FATAL_ERROR "Please install python 2.7 before building PaddlePaddle.") ##################################### PYTHON ######################################## SET(PYTHON_SOURCES_DIR ${THIRD_PARTY_PATH}/python) SET(PYTHON_INSTALL_DIR ${THIRD_PARTY_PATH}/install/python) From 94618d8776229254d52075f9aabd998d7ed6be8d Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 16 Jan 2017 10:20:26 +0800 Subject: [PATCH 034/370] Fix merge error. --- paddle/math/SparseRowMatrix.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddle/math/SparseRowMatrix.h b/paddle/math/SparseRowMatrix.h index d7dfb2fe579950..c05fc98ff9fe73 100644 --- a/paddle/math/SparseRowMatrix.h +++ b/paddle/math/SparseRowMatrix.h @@ -19,8 +19,8 @@ limitations under the License. */ #include #include "Matrix.h" #include "RowBuffer.h" -#include "paddle/utils/CommandLineParser.h" #include "paddle/utils/Util.h" + DECLARE_bool(allow_inefficient_sparse_update); namespace paddle { From 66851af107c9eb3e6cea8485db467daf9b6cc078 Mon Sep 17 00:00:00 2001 From: liaogang Date: Mon, 16 Jan 2017 10:44:51 +0800 Subject: [PATCH 035/370] Detect CentOS 7 in CMake --- cmake/system.cmake | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cmake/system.cmake b/cmake/system.cmake index 788db404ebfb6f..d40499c39da736 100644 --- a/cmake/system.cmake +++ b/cmake/system.cmake @@ -21,6 +21,7 @@ ELSE(WIN32) SET(MACOS_VERSION ${VERSION}) SET(HOST_SYSTEM "macosx") ELSE(APPLE) + IF(EXISTS "/etc/issue") FILE(READ "/etc/issue" LINUX_ISSUE) IF(LINUX_ISSUE MATCHES "CentOS") @@ -31,6 +32,14 @@ ELSE(WIN32) SET(HOST_SYSTEM "ubuntu") ENDIF() ENDIF(EXISTS "/etc/issue") + + IF(EXISTS "/etc/redhat-release") + FILE(READ "/etc/redhat-release" LINUX_ISSUE) + IF(LINUX_ISSUE MATCHES "CentOS") + SET(HOST_SYSTEM "centos") + ENDIF() + ENDIF(EXISTS "/etc/redhat-release") + ENDIF(APPLE) ENDIF(WIN32) From 014a72713009b52a6e6642adf2c360b2e1097ff7 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 16 Jan 2017 12:04:15 +0800 Subject: [PATCH 036/370] Add todos --- paddle/math/RowBuffer.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/paddle/math/RowBuffer.h b/paddle/math/RowBuffer.h index 0edcefd7562460..dbb829c4e24a65 100644 --- a/paddle/math/RowBuffer.h +++ b/paddle/math/RowBuffer.h @@ -126,6 +126,8 @@ class RowBuffer { inline size_t getWidth() const { return width_; } private: + //! TODO(yuyang18): Add resize method to CpuMemHandlePtr, then we can get rid + //! of std::vector here. CpuMemHandlePtr preallocatedBuf_; std::vector> rowStore_; size_t width_; From 741637eba41f66b51bd1764900e75cc7d5bd9ce6 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 16 Jan 2017 16:14:29 +0800 Subject: [PATCH 037/370] Add printf method to Status. --- paddle/utils/Status.h | 23 +++++++++++++++++++++++ paddle/utils/tests/test_Status.cpp | 5 +++++ 2 files changed, 28 insertions(+) diff --git a/paddle/utils/Status.h b/paddle/utils/Status.h index 3456d7b686f0d9..db1edfb7c735fc 100644 --- a/paddle/utils/Status.h +++ b/paddle/utils/Status.h @@ -14,6 +14,7 @@ limitations under the License. */ #pragma once +#include #include #include @@ -45,6 +46,28 @@ class Status final : public std::exception { errMsg_.reset(new std::string(msg)); } + /** + * @brief set a error message for status. Use C style printf + * @param fmt + */ + template + inline void setByPrintf(const char* fmt, ARGS... args) noexcept { + constexpr size_t bufferSize = 4096; + char buffer[bufferSize]; + snprintf(buffer, bufferSize, fmt, args...); + errMsg_.reset(new std::string(buffer)); + } + + /** + * create a error status by C style printf. + */ + template + inline static Status printf(const char* fmt, ARGS... args) noexcept { + Status s; + s.setByPrintf(fmt, args...); + return s; + } + /** * @brief what will return the error message. If status is OK, return nullptr. */ diff --git a/paddle/utils/tests/test_Status.cpp b/paddle/utils/tests/test_Status.cpp index e2c2ae537d8b62..04cef095792c73 100644 --- a/paddle/utils/tests/test_Status.cpp +++ b/paddle/utils/tests/test_Status.cpp @@ -26,4 +26,9 @@ TEST(Status, testAll) { paddle::Status status2("error2"); ASSERT_FALSE(status2.isOK()); ASSERT_STREQ("error2", status2.what()); + + int i = 3; + auto status3 = paddle::Status::printf("error%d", i); + ASSERT_FALSE(status3.isOK()); + ASSERT_STREQ("error3", status3.what()); } From 1e233171ff59decc3d179e30ab29e65735583747 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Mon, 16 Jan 2017 17:18:24 +0800 Subject: [PATCH 038/370] Fix merge error --- paddle/function/Function.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/paddle/function/Function.cpp b/paddle/function/Function.cpp index 2632c17e3ac61a..f47d55a4ade97d 100644 --- a/paddle/function/Function.cpp +++ b/paddle/function/Function.cpp @@ -96,7 +96,8 @@ void BufferArgs::addArg(const GpuSparseMatrix& arg, ArgType argType) { void BufferArgs::addArg(const Matrix& matrix, const IVector& vector, ArgType argType) { - args_.push_back(std::make_shared(matrix, vector, argType)); + _args_.push_back(new SequenceArg(matrix, vector, argType)); + addArg(*_args_.back()); } ClassRegistrar FunctionBase::funcRegistrar_; From 19cb2a7fb3e750eb2a81337bed063782977d7195 Mon Sep 17 00:00:00 2001 From: zhangruiqing01 Date: Mon, 16 Jan 2017 11:26:29 +0800 Subject: [PATCH 039/370] fix default value of cos_sim scale --- python/paddle/trainer/config_parser.py | 2 +- python/paddle/trainer_config_helpers/layers.py | 2 +- .../tests/configs/protostr/test_ntm_layers.protostr | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index 674b5ac58b6feb..8e9c40877bac59 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -2628,7 +2628,7 @@ def __init__(self, @config_layer('cos') class CosSimLayer(LayerBase): - def __init__(self, name, inputs, cos_scale=5, device=None): + def __init__(self, name, inputs, cos_scale=1, device=None): super(CosSimLayer, self).__init__( name, 'cos', 1, inputs=inputs, device=device) config_assert(len(self.inputs) == 2, 'CosSimLayer must have 2 inputs') diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 9b6e5774bc82dc..23c0e9174ff958 100644 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -1673,7 +1673,7 @@ def trans_layer(input, name=None, layer_attr=None): @wrap_name_default() @layer_support() -def cos_sim(a, b, scale=5, size=1, name=None, layer_attr=None): +def cos_sim(a, b, scale=1, size=1, name=None, layer_attr=None): """ Cosine Similarity Layer. The cosine similarity equation is here. diff --git a/python/paddle/trainer_config_helpers/tests/configs/protostr/test_ntm_layers.protostr b/python/paddle/trainer_config_helpers/tests/configs/protostr/test_ntm_layers.protostr index b30bbb2a4e24d7..c1bfdf1b19c61d 100644 --- a/python/paddle/trainer_config_helpers/tests/configs/protostr/test_ntm_layers.protostr +++ b/python/paddle/trainer_config_helpers/tests/configs/protostr/test_ntm_layers.protostr @@ -79,7 +79,7 @@ layers { inputs { input_layer_name: "b" } - cos_scale: 5 + cos_scale: 1 } layers { name: "__cos_sim_1__" @@ -92,7 +92,7 @@ layers { inputs { input_layer_name: "c" } - cos_scale: 5 + cos_scale: 1 } layers { name: "__sum_to_one_norm_layer_0__" From f8c9c889c34dd3530b899fc12523579802d4f582 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Mon, 16 Jan 2017 21:30:44 +0800 Subject: [PATCH 040/370] Fix CrossMapNormalTest --- paddle/function/CrossMapNormalOp.cpp | 9 +++++++-- paddle/function/CrossMapNormalOpTest.cpp | 4 ---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/paddle/function/CrossMapNormalOp.cpp b/paddle/function/CrossMapNormalOp.cpp index 92980c503fdaaa..8e7dc72524a768 100644 --- a/paddle/function/CrossMapNormalOp.cpp +++ b/paddle/function/CrossMapNormalOp.cpp @@ -188,8 +188,13 @@ class CrossMapNormalGradFunc : public FunctionBase { CHECK(inputs[0].shape() == inputs[3].shape()); CHECK(inputs[0].shape() == outputs[0].shape()); - // TODO(hedaoyuan): need support ASSIGN_TO mode. - CHECK_EQ(outputs[0].getArgType(), ADD_TO); + if (outputs[0].getArgType() != ADD_TO) { + // Currently, some algorithm implementations are ASSIGN_TO mode, + // if need to support the ADD_TO calculation, need to clear the output. + typename Tensor::Vector tmp( + outputs[0].shape().getElements(), outputs[0].data()); + tmp.zero(); + } size_t samples = inputs[0].shape()[0]; size_t channels = inputs[0].shape()[1]; diff --git a/paddle/function/CrossMapNormalOpTest.cpp b/paddle/function/CrossMapNormalOpTest.cpp index da196a699cc32b..51f5da81bfc9ae 100644 --- a/paddle/function/CrossMapNormalOpTest.cpp +++ b/paddle/function/CrossMapNormalOpTest.cpp @@ -47,9 +47,6 @@ TEST(CrossMapNormal, real) { } } -#if 0 -// TODO(hedaoyuan): Now CrossMapNormalGrad not support ASSIGN_TO mode. -// Maybe all Function need support ASSIGN_TO mode. TEST(CrossMapNormalGrad, real) { for (size_t numSamples : {5, 32}) { for (size_t channels : {1, 5, 32}) { @@ -79,6 +76,5 @@ TEST(CrossMapNormalGrad, real) { } } } -#endif } // namespace paddle From 07787f72ba69dd0bbca4ee01f84c59fb34dc02c9 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Mon, 16 Jan 2017 09:19:05 -0800 Subject: [PATCH 041/370] clarify and fix problems in paddle on aws k8s (create cluster part) --- doc/howto/usage/k8s/k8s_aws_en.md | 138 ++++++++++++++++++++---------- 1 file changed, 93 insertions(+), 45 deletions(-) diff --git a/doc/howto/usage/k8s/k8s_aws_en.md b/doc/howto/usage/k8s/k8s_aws_en.md index c776ba9eb97a8c..bd9eee72963932 100644 --- a/doc/howto/usage/k8s/k8s_aws_en.md +++ b/doc/howto/usage/k8s/k8s_aws_en.md @@ -2,18 +2,18 @@ ## Create AWS Account and IAM Account -AWS account allow us to manage AWS from Web Console. Amazon AMI enable us to manage AWS from command line interface. +AWS account allow us to manage AWS from Web Console. Amazon IAM enable us to manage AWS from command line interface. -We need to create an AMI user with sufficient privilege to create kubernetes cluster on AWS. +We need to create an IAM user with sufficient privilege to create kubernetes cluster on AWS. To sign up an AWS account, please follow [this guide](http://docs.aws.amazon.com/lambda/latest/dg/setting-up.html). -To create users and user groups under an AWS account, please +To create IAM users and user groups under an AWS account, please follow [this guide](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html). -Please be aware that this tutorial needs the following privileges for the user in AMI: +Please be aware that this tutorial needs the following privileges for the user in IAM: - AmazonEC2FullAccess - AmazonS3FullAccess @@ -27,14 +27,6 @@ Please be aware that this tutorial needs the following privileges for the user i - AWSKeyManagementServicePowerUser -By the time we write this tutorial, we noticed that Chinese AWS users -might suffer from authentication problems when running this tutorial. -Our solution is that we create a VM instance with the default Amazon -AMI and in the same zone as our cluster runs, so we can SSH to this VM -instance as a tunneling server and control our cluster and jobs from -it. - - ## PaddlePaddle on AWS Here we will show you step by step on how to run PaddlePaddle training on AWS cluster. @@ -59,7 +51,7 @@ gpg2 --fingerprint FC8A365E ``` The correct key fingerprint is `18AD 5014 C99E F7E3 BA5F 6CE9 50BD D3E0 FC8A 365E` -Go to the [releases](https://github.com/coreos/kube-aws/releases) and download the latest release tarball and detached signature (.sig) for your architecture. +Go to the [releases](https://github.com/coreos/kube-aws/releases) and download release tarball (this tutorial is using v0.9.1) and detached signature (.sig) for your architecture. Validate the tarball's GPG signature: @@ -88,14 +80,22 @@ mv ${PLATFORM}/kube-aws /usr/local/bin [kubectl](https://kubernetes.io/docs/user-guide/kubectl-overview/) is a command line interface for running commands against Kubernetes clusters. -Go to the [releases](https://github.com/kubernetes/kubernetes/releases) and download the latest release tarball. - -Extract the tarball and then concate the kubernetes binaries directory into PATH: +Download `kubectl` from the Kubernetes release artifact site with the `curl` tool. ``` -export PATH=/platforms/linux/amd64:$PATH # The exact path depend on your platform +# OS X +curl -O https://storage.googleapis.com/kubernetes-release/release/"$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)"/bin/darwin/amd64/kubectl + +# Linux +curl -O https://storage.googleapis.com/kubernetes-release/release/"$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)"/bin/linux/amd64/kubectl ``` +Make the kubectl binary executable and move it to your PATH (e.g. `/usr/local/bin`): + +``` +chmod +x ./kubectl +sudo mv ./kubectl /usr/local/bin/kubectl +``` ### Configure AWS Credentials @@ -109,17 +109,18 @@ aws configure ``` -Fill in the required fields (You can get your AWS aceess key id and AWS secrete access key by following [this](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html) instruction): +Fill in the required fields: ``` AWS Access Key ID: YOUR_ACCESS_KEY_ID AWS Secrete Access Key: YOUR_SECRETE_ACCESS_KEY -Default region name: us-west-2 +Default region name: us-west-1 Default output format: json - ``` +`YOUR_ACCESS_KEY_ID`, and `YOUR_SECRETE_ACCESS_KEY` is the IAM key and secret from [Create AWS Account and IAM Account](#create-aws-account-and-iam-account) + Verify that your credentials work by describing any instances you may already have running on your account: ``` @@ -134,7 +135,9 @@ The keypair that will authenticate SSH access to your EC2 instances. The public Follow [EC2 Keypair docs](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) to create a EC2 key pair -After creating a key pair, you will use the name you gave the keys to configure the cluster. Key pairs are only available to EC2 instances in the same region. +After creating a key pair, you will use the key pair name to configure the cluster. + +Key pairs are only available to EC2 instances in the same region. We are using us-west-1 in our tutorial, so make sure to creat key pairs in that region (N. California). #### KMS key @@ -143,12 +146,12 @@ Amazon KMS keys are used to encrypt and decrypt cluster TLS assets. If you alrea You can create a KMS key in the AWS console, or with the aws command line tool: ``` -$ aws kms --region=us-west-1 create-key --description="kube-aws assets" +aws kms --region=us-west-1 create-key --description="kube-aws assets" { "KeyMetadata": { "CreationDate": 1458235139.724, "KeyState": "Enabled", - "Arn": "arn:aws:kms:us-west-1:xxxxxxxxx:key/xxxxxxxxxxxxxxxxxxx", + "Arn": "arn:aws:kms:us-west-1:aaaaaaaaaaaaa:key/xxxxxxxxxxxxxxxxxxx", "AWSAccountId": "xxxxxxxxxxxxx", "Enabled": true, "KeyUsage": "ENCRYPT_DECRYPT", @@ -158,11 +161,11 @@ $ aws kms --region=us-west-1 create-key --description="kube-aws assets" } ``` -You will use the `KeyMetadata.Arn` string to identify your KMS key in the init step. +We will need to use the value of `Arn` later. And then you need to add several inline policies in your user permission. -Go to AMI user page, click on `Add inline policy` button, and then select `Custom Policy` +Go to IAM user page, click on `Add inline policy` button, and then select `Custom Policy` paste into following inline policies: @@ -178,7 +181,7 @@ paste into following inline policies: "kms:Encrypt" ], "Resource": [ - "arn:aws:kms:*:xxxxxxxxx:key/*" + "arn:aws:kms:*:AWS_ACCOUNT_ID:key/*" ] }, { @@ -194,29 +197,37 @@ paste into following inline policies: "cloudformation:DescribeStackEvents" ], "Resource": [ - "arn:aws:cloudformation:us-west-1:xxxxxxxxx:stack/YOUR_CLUSTER_NAME/*" + "arn:aws:cloudformation:us-west-1:AWS_ACCOUNT_ID:stack/MY_CLUSTER_NAME/*" ] } ] } ``` +`AWS_ACCOUNT_ID`: You can get it from following command line: + +``` +aws sts get-caller-identity --output text --query Account +``` + +`MY_CLUSTER_NAME`: Pick a MY_CLUSTER_NAME that you like, you will use it later as well. #### External DNS name -When the cluster is created, the controller will expose the TLS-secured API on a public IP address. You will need to create an A record for the external DNS hostname you want to point to this IP address. You can find the API external IP address after the cluster is created by invoking kube-aws status. +When the cluster is created, the controller will expose the TLS-secured API on a DNS name. + +The A record of that DNS name needs to be point to the cluster ip address. + +We will need to use DNS name later in tutorial. If you don't already own one, you can choose any DNS name (e.g., `paddle`) and modify `/etc/hosts` to associate cluster ip with that DNS name. #### S3 bucket You need to create an S3 bucket before startup the Kubernetes cluster. -command (need to have a global unique name): +There are some bug in aws cli in creating S3 bucket, so let's use [web console](https://console.aws.amazon.com/s3/home?region=us-west-1). -``` -paddle aws s3api --region=us-west-1 create-bucket --bucket bucket-name -``` +Click on `Create Bucket`, fill in a unique BUCKET_NAME, and make sure region is us-west-1 (Northern California). -If you get an error message, try a different bucket name. The bucket name needs to be globally unique. #### Initialize an asset directory @@ -230,33 +241,44 @@ $ cd my-cluster Initialize the cluster CloudFormation stack with the KMS Arn, key pair name, and DNS name from the previous step: ``` -$ kube-aws init \ ---cluster-name=my-cluster-name \ ---external-dns-name=my-cluster-endpoint \ +kube-aws init \ +--cluster-name=MY_CLUSTER_NAME \ +--external-dns-name=MY_EXTERNAL_DNS_NAME \ --region=us-west-1 \ ---availability-zone=us-west-1c \ ---key-name=key-pair-name \ +--availability-zone=us-west-1a \ +--key-name=KEY_PAIR_NAME \ --kms-key-arn="arn:aws:kms:us-west-1:xxxxxxxxxx:key/xxxxxxxxxxxxxxxxxxx" ``` -Here `us-west-1c` is used for parameter `--availability-zone`, but supported availability zone varies among AWS accounts. +`MY_CLUSTER_NAME`: the one you picked in [KMS key](#kms-key) + +`MY_EXTERNAL_DNS_NAME`: see [External DNS name](#external-dns-name) -Please check if `us-west-1c` is supported by `aws ec2 --region us-west-1 describe-availability-zones`, if not switch to other supported availability zone. (e.g., `us-west-1a`, or `us-west-1b`) +`KEY_PAIR_NAME`: see [EC2 key pair](#ec2-key-pair) + +`--kms-key-arn`: the "Arn" in [KMS key](#kms-key) + +Here `us-west-1a` is used for parameter `--availability-zone`, but supported availability zone varies among AWS accounts. + +Please check if `us-west-1a` is supported by `aws ec2 --region us-west-1 describe-availability-zones`, if not switch to other supported availability zone. (e.g., `us-west-1a`, or `us-west-1b`) + +Note: please don't use `us-west-1c`. Subnets can currently only be created in the following availability zones: us-west-1b, us-west-1a. There will now be a cluster.yaml file in the asset directory. This is the main configuration file for your cluster. + #### Render contents of the asset directory In the simplest case, you can have kube-aws generate both your TLS identities and certificate authority for you. ``` -$ kube-aws render credentials --generate-ca +kube-aws render credentials --generate-ca ``` The next command generates the default set of cluster assets in your asset directory. ``` -sh $ kube-aws render stack +kube-aws render stack ``` Here's what the directory structure looks like: @@ -292,15 +314,41 @@ These assets (templates and credentials) are used to create, update and interact #### Create the instances defined in the CloudFormation template -Now for the exciting part, creating your cluster (choose any ``): +Now let's create your cluster (choose any PREFIX for the command below): ``` -$ kube-aws up --s3-uri s3:/// +kube-aws up --s3-uri s3://BUCKET_NAME/PREFIX ``` +`BUCKET_NAME`: the bucket name that you used in [S3 bucket](#s3-bucket) + + #### Configure DNS -You can invoke `kube-aws status` to get the cluster API endpoint after cluster creation, if necessary. This command can take a while. And use command `dig` to check the load balancer hostname to get the ip address, use this ip to setup an A record for your external dns name. +You can invoke `kube-aws status` to get the cluster API endpoint after cluster creation. + +``` +$ kube-aws status +Cluster Name: paddle-cluster +Controller DNS Name: paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-1.elb.amazonaws.com +``` + +Use command `dig` to check the load balancer hostname to get the ip address. + +``` +$ dig paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-1.elb.amazonaws.com + +;; QUESTION SECTION: +;paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-1.elb.amazonaws.com. IN A + +;; ANSWER SECTION: +paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-1.elb.amazonaws.com. 59 IN A 54.241.164.52 +paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-1.elb.amazonaws.com. 59 IN A 54.67.102.112 +``` + +In the above output, both ip `54.241.164.52`, `54.67.102.112` will work. + +If you own a DNS name, set the A record to any of the above ip. Otherwise you can edit `/etc/hosts` to associate ip with the DNS name. #### Access the cluster From 50afa35a59de9e9c2a31e873ab650eb181de801d Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Mon, 16 Jan 2017 14:29:52 -0800 Subject: [PATCH 042/370] fixes according to comment --- doc/howto/usage/k8s/k8s_aws_en.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/howto/usage/k8s/k8s_aws_en.md b/doc/howto/usage/k8s/k8s_aws_en.md index bd9eee72963932..00bc41e5c3e2e9 100644 --- a/doc/howto/usage/k8s/k8s_aws_en.md +++ b/doc/howto/usage/k8s/k8s_aws_en.md @@ -2,9 +2,7 @@ ## Create AWS Account and IAM Account -AWS account allow us to manage AWS from Web Console. Amazon IAM enable us to manage AWS from command line interface. - -We need to create an IAM user with sufficient privilege to create kubernetes cluster on AWS. +Under each AWS account, we can create multiple [IAM](http://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html) users. This allows us to grant some privileges to each IAM user and to create/operate AWS clusters as an IAM user. To sign up an AWS account, please follow @@ -51,7 +49,7 @@ gpg2 --fingerprint FC8A365E ``` The correct key fingerprint is `18AD 5014 C99E F7E3 BA5F 6CE9 50BD D3E0 FC8A 365E` -Go to the [releases](https://github.com/coreos/kube-aws/releases) and download release tarball (this tutorial is using v0.9.1) and detached signature (.sig) for your architecture. +We can download `kube-aws` from its [release page](https://github.com/coreos/kube-aws/releases). In this tutorial, we use version 0.9.1 Validate the tarball's GPG signature: @@ -224,7 +222,7 @@ We will need to use DNS name later in tutorial. If you don't already own one, yo You need to create an S3 bucket before startup the Kubernetes cluster. -There are some bug in aws cli in creating S3 bucket, so let's use [web console](https://console.aws.amazon.com/s3/home?region=us-west-1). +There are some bugs in aws cli in creating S3 bucket, so let's use the [Web console](https://console.aws.amazon.com/s3/home?region=us-west-1). Click on `Create Bucket`, fill in a unique BUCKET_NAME, and make sure region is us-west-1 (Northern California). From 8aefc30499e09729b5755fe8edfd32ba72a9baed Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 17 Jan 2017 10:59:27 +0800 Subject: [PATCH 043/370] Fix compile error. --- paddle/utils/Status.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/paddle/utils/Status.h b/paddle/utils/Status.h index db1edfb7c735fc..52f312378eedaa 100644 --- a/paddle/utils/Status.h +++ b/paddle/utils/Status.h @@ -52,9 +52,9 @@ class Status final : public std::exception { */ template inline void setByPrintf(const char* fmt, ARGS... args) noexcept { - constexpr size_t bufferSize = 4096; - char buffer[bufferSize]; - snprintf(buffer, bufferSize, fmt, args...); + constexpr size_t kBufferSize = 4096; + char buffer[kBufferSize]; + snprintf(buffer, kBufferSize, fmt, args...); errMsg_.reset(new std::string(buffer)); } From ae0f953eb03f021e5892bdea2009d7088a346e46 Mon Sep 17 00:00:00 2001 From: qijun Date: Tue, 17 Jan 2017 03:10:53 +0000 Subject: [PATCH 044/370] add centos build doc --- .../build_and_install/build_from_source_en.md | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/doc/getstarted/build_and_install/build_from_source_en.md b/doc/getstarted/build_and_install/build_from_source_en.md index 1abd7b698bc09c..924ccf01169234 100644 --- a/doc/getstarted/build_and_install/build_from_source_en.md +++ b/doc/getstarted/build_and_install/build_from_source_en.md @@ -4,6 +4,8 @@ Installing from Sources * [1. Download and Setup](#download) * [2. Requirements](#requirements) * [3. Build on Ubuntu](#ubuntu) +* [4. Build on Centos](#centos) + ## Download and Setup You can download PaddlePaddle from the [github source](https://github.com/PaddlePaddle/Paddle). @@ -151,3 +153,64 @@ export PATH=/bin:$PATH # install PaddlePaddle Python modules. sudo pip install /opt/paddle/share/wheels/*.whl ``` +## Build on Centos 7 + +### Install Dependencies + +- **CPU Dependencies** + + ```bash + # necessary + sudo yum update + sudo yum install -y epel-release + sudo yum install -y make cmake3 python-devel python-pip gcc-gfortran swig git + sudo pip install wheel numpy + sudo pip install 'protobuf>=3.0.0' + ``` + +- **GPU Dependencies (optional)** + + To build GPU version, you will need the following installed: + + 1. a CUDA-capable GPU + 2. A supported version of Linux with a gcc compiler and toolchain + 3. NVIDIA CUDA Toolkit (available at http://developer.nvidia.com/cuda-downloads) + 4. NVIDIA cuDNN Library (availabel at https://developer.nvidia.com/cudnn) + + The CUDA development environment relies on tight integration with the host development environment, + including the host compiler and C runtime libraries, and is therefore only supported on + distribution versions that have been qualified for this CUDA Toolkit release. + + After downloading cuDNN library, issue the following commands: + + ```bash + sudo tar -xzf cudnn-7.5-linux-x64-v5.1.tgz -C /usr/local + sudo chmod a+r /usr/local/cuda/include/cudnn.h /usr/local/cuda/lib64/libcudnn* + ``` + Then you need to set LD\_LIBRARY\_PATH, PATH environment variables in ~/.bashrc. + + ```bash + export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH + export PATH=/usr/local/cuda/bin:$PATH + ``` + +### Build and Install + +As usual, the best option is to create build folder under paddle project directory. + +```bash +mkdir build && cd build +``` + +Finally, you can build and install PaddlePaddle: + +```bash +# you can add build option here, such as: +cmake3 .. -DCMAKE_INSTALL_PREFIX= +# please use sudo make install, if you want to install PaddlePaddle into the system +make -j `nproc` && make install +# set PaddlePaddle installation path in ~/.bashrc +export PATH=/bin:$PATH +# install PaddlePaddle Python modules. +sudo pip install /opt/paddle/share/wheels/*.whl +``` From ceb2d39799fa600ff77fdbe019191f846829e916 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 17 Jan 2017 12:49:05 +0800 Subject: [PATCH 045/370] Fix bugs in config_helpers unittest. * It gets wrong command line arguments before. --- .../tests/configs/run_tests.sh | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/python/paddle/trainer_config_helpers/tests/configs/run_tests.sh b/python/paddle/trainer_config_helpers/tests/configs/run_tests.sh index a37eb6439e6d28..c8a3b190b19148 100755 --- a/python/paddle/trainer_config_helpers/tests/configs/run_tests.sh +++ b/python/paddle/trainer_config_helpers/tests/configs/run_tests.sh @@ -2,16 +2,18 @@ cd `dirname $0` set -e +PYTHON_EXEC=$1 +COMPARE_PROTO_UTIL=$2 protostr=`dirname $0`/protostr files=`ls $protostr | grep -v "unittest"` -./generate_protostr.sh $1 +./generate_protostr.sh ${PYTHON_EXEC} . ./file_list.sh -if [ -z $1 ]; then +if [ -z ${COMPARE_PROTO_UTIL} ]; then for file in $files do base_protostr=$protostr/$file @@ -22,20 +24,20 @@ if [ -z $1 ]; then else for file in ${configs[*]} do - if ! $1 $protostr/$file.protostr $protostr/$file.protostr.unittest; then + if ! ${COMPARE_PROTO_UTIL} $protostr/$file.protostr $protostr/$file.protostr.unittest; then diff $protostr/$file.protostr $protostr/$file.protostr.unittest -u fi - if ! $1 $protostr/$file.protostr $protostr/$file.protostr.non_file_config.unittest; then + if ! ${COMPARE_PROTO_UTIL} $protostr/$file.protostr $protostr/$file.protostr.non_file_config.unittest; then diff $protostr/$file.protostr $protostr/$file.protostr.non_file_config.unittest -u fi done for file in ${whole_configs[*]} do - if ! $1 $protostr/$file.protostr $protostr/$file.protostr.unittest --whole; then + if ! ${COMPARE_PROTO_UTIL} $protostr/$file.protostr $protostr/$file.protostr.unittest --whole; then diff $protostr/$file.protostr $protostr/$file.protostr.unittest -u fi - if ! $1 $protostr/$file.protostr $protostr/$file.protostr.non_file_config.unittest --whole; then + if ! ${COMPARE_PROTO_UTIL} $protostr/$file.protostr $protostr/$file.protostr.non_file_config.unittest --whole; then diff $protostr/$file.protostr $protostr/$file.protostr.non_file_config.unittest -u fi done From 4837665d227f0357e3aac51712e6bac7a595cb72 Mon Sep 17 00:00:00 2001 From: liaogang Date: Tue, 17 Jan 2017 17:01:44 +0800 Subject: [PATCH 046/370] Update dockerfiles for develop branch --- .../build_and_install/build_from_source_en.md | 3 +- paddle/scripts/docker/Dockerfile | 31 ++++++++++--------- paddle/scripts/docker/Dockerfile.gpu | 31 ++++++++++--------- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/doc/getstarted/build_and_install/build_from_source_en.md b/doc/getstarted/build_and_install/build_from_source_en.md index 1abd7b698bc09c..7d963a5a6df3cf 100644 --- a/doc/getstarted/build_and_install/build_from_source_en.md +++ b/doc/getstarted/build_and_install/build_from_source_en.md @@ -17,8 +17,9 @@ cd paddle To compile the source code, your computer must be equipped with the following dependencies. - **Compiler**: GCC >= 4.8 or Clang >= 3.3 (AppleClang >= 5.1) -- **CMake**: version >= 3.0 (at least CMake 3.4 on Mac OS X) +- **CMake**: CMake >= 3.0 (at least CMake 3.4 on Mac OS X) - **BLAS**: MKL, OpenBlas or ATLAS +- **Python**: only support Python 2.7 **Note:** For CUDA 7.0 and CUDA 7.5, GCC 5.0 and up are not supported! For CUDA 8.0, GCC versions later than 5.3 are not supported! diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile index 1522be023f6de3..13a5758f7b66a1 100644 --- a/paddle/scripts/docker/Dockerfile +++ b/paddle/scripts/docker/Dockerfile @@ -4,28 +4,31 @@ MAINTAINER PaddlePaddle Authors ARG DEBIAN_FRONTEND=noninteractive ARG UBUNTU_MIRROR RUN /bin/bash -c 'if [[ -n ${UBUNTU_MIRROR} ]]; then sed -i 's#http://archive.ubuntu.com#${UBUNTU_MIRROR}#g' /etc/apt/sources.list; fi' -RUN apt-get update \ - && apt-get install -y cmake libprotobuf-dev protobuf-compiler git \ - libgoogle-glog-dev libgflags-dev libgtest-dev \ - libatlas-dev libatlas3-base g++ m4 python-pip \ - python-protobuf python-numpy python-dev swig openssh-server \ - wget unzip python-matplotlib tar xz-utils bzip2 gzip coreutils \ - sed grep graphviz libjpeg-dev zlib1g-dev doxygen \ - clang-3.8 llvm-3.8 libclang-3.8-dev \ - && apt-get clean -y -RUN cd /usr/src/gtest && cmake . && make && cp *.a /usr/lib -RUN pip install -U BeautifulSoup docopt PyYAML pillow \ - sphinx sphinx_rtd_theme recommonmark jupyter + +RUN apt-get update && \ + apt-get install -y git python-pip python-dev openssh-server && \ + apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ + apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ + apt-get install -y g++ clang-3.8 llvm-3.8 libclang-3.8-dev && \ + apt-get clean -y + +RUN pip install --upgrade pip && \ + pip install 'protobuf==3.1.0.post1' && \ + pip install -U numpy wheel matplotlib pillow && \ + pip install -U BeautifulSoup docopt PyYAML sphinx && \ + pip install -U sphinx_rtd_theme recommonmark jupyter + +RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \ + cd cmake-3.4.1 && ./bootstrap && make -j4 && make install && \ + cd .. && rm -rf cmake-3.4.1 ARG WITH_AVX ARG WITH_DOC -ARG WITH_SWIG_PY ARG WITH_STYLE_CHECK ENV WITH_GPU=OFF ENV WITH_AVX=${WITH_AVX:-ON} ENV WITH_DOC=${WITH_DOC:-ON} -ENV WITH_SWIG_PY=${WITH_SWIG_PY:-ON} ENV WITH_STYLE_CHECK=${WITH_STYLE_CHECK:-OFF} RUN mkdir /paddle diff --git a/paddle/scripts/docker/Dockerfile.gpu b/paddle/scripts/docker/Dockerfile.gpu index 09f07043e21723..bab86114feaf99 100644 --- a/paddle/scripts/docker/Dockerfile.gpu +++ b/paddle/scripts/docker/Dockerfile.gpu @@ -4,28 +4,31 @@ MAINTAINER PaddlePaddle Authors ARG DEBIAN_FRONTEND=noninteractive ARG UBUNTU_MIRROR RUN /bin/bash -c 'if [[ -n ${UBUNTU_MIRROR} ]]; then sed -i 's#http://archive.ubuntu.com#${UBUNTU_MIRROR}#g' /etc/apt/sources.list; fi' -RUN apt-get update \ - && apt-get install -y cmake libprotobuf-dev protobuf-compiler git \ - libgoogle-glog-dev libgflags-dev libgtest-dev \ - libatlas-dev libatlas3-base g++ m4 python-pip \ - python-protobuf python-numpy python-dev swig openssh-server \ - wget unzip python-matplotlib tar xz-utils bzip2 gzip coreutils \ - sed grep graphviz libjpeg-dev zlib1g-dev doxygen \ - clang-3.8 llvm-3.8 libclang-3.8-dev \ - && apt-get clean -y -RUN cd /usr/src/gtest && cmake . && make && cp *.a /usr/lib -RUN pip install -U BeautifulSoup docopt PyYAML pillow \ - sphinx sphinx_rtd_theme recommonmark jupyter + +RUN apt-get update && \ + apt-get install -y git python-pip python-dev openssh-server && \ + apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ + apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ + apt-get install -y g++ clang-3.8 llvm-3.8 libclang-3.8-dev && \ + apt-get clean -y + +RUN pip install --upgrade pip && \ + pip install 'protobuf==3.1.0.post1' && \ + pip install -U numpy wheel matplotlib pillow && \ + pip install -U BeautifulSoup docopt PyYAML sphinx && \ + pip install -U sphinx_rtd_theme recommonmark jupyter + +RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \ + cd cmake-3.4.1 && ./bootstrap && make -j4 && make install && \ + cd .. && rm -rf cmake-3.4.1 ARG WITH_AVX ARG WITH_DOC -ARG WITH_SWIG_PY ARG WITH_STYLE_CHECK ENV WITH_GPU=ON ENV WITH_AVX=${WITH_AVX:-ON} ENV WITH_DOC=${WITH_DOC:-ON} -ENV WITH_SWIG_PY=${WITH_SWIG_PY:-ON} ENV WITH_STYLE_CHECK=${WITH_STYLE_CHECK:-OFF} RUN mkdir /paddle From a5c1658d455008bbe4e4a5a3075bbd6eced30f28 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 17 Jan 2017 17:20:13 +0800 Subject: [PATCH 047/370] Always create protobuf_equal * Because currently Paddle only use protobuf 3. --- .../tests/CMakeLists.txt | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/python/paddle/trainer_config_helpers/tests/CMakeLists.txt b/python/paddle/trainer_config_helpers/tests/CMakeLists.txt index 403aafabe91434..93dd7796c246ae 100644 --- a/python/paddle/trainer_config_helpers/tests/CMakeLists.txt +++ b/python/paddle/trainer_config_helpers/tests/CMakeLists.txt @@ -9,17 +9,10 @@ add_test(NAME test_reset_hook ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/trainer_config_helpers/tests/test_reset_hook.py WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) -if (PROTOBUF_3) - add_paddle_exe(protobuf_equal - ProtobufEqualMain.cpp) - add_test(NAME test_layerHelpers - COMMAND - ${PROJ_ROOT}/python/paddle/trainer_config_helpers/tests/configs/run_tests.sh ${PYTHON_EXECUTABLE} - ${CMAKE_CURRENT_BINARY_DIR}/protobuf_equal - ) -else() - add_test(NAME test_layerHelpers - COMMAND - ${PROJ_ROOT}/python/paddle/trainer_config_helpers/tests/configs/run_tests.sh ${PYTHON_EXECUTABLE} - ) -endif() +add_paddle_exe(protobuf_equal + ProtobufEqualMain.cpp) +add_test(NAME test_layerHelpers + COMMAND + ${PROJ_ROOT}/python/paddle/trainer_config_helpers/tests/configs/run_tests.sh ${PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_BINARY_DIR}/protobuf_equal +) From 1c5a7c431690ba6a981ac9f72aacf556da1bc1db Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Tue, 17 Jan 2017 17:33:15 +0800 Subject: [PATCH 048/370] follow comments --- paddle/function/BufferArg.h | 1 + paddle/function/FunctionTest.cpp | 1 + paddle/function/FunctionTest.h | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index 9c792c6bb72aa2..84209265ce7634 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -192,6 +192,7 @@ class SequenceIdArg : public BufferArg { SequenceIdArg(const TensorShape& shape, ArgType argType = UNSPECIFIED) : BufferArg(VALUE_TYPE_INT32, shape, argType) { CHECK_EQ(shape_.ndims(), (size_t)1); + CHECK_GT(shape_[0], 1); numSeqs_ = shape_[0] - 1; } diff --git a/paddle/function/FunctionTest.cpp b/paddle/function/FunctionTest.cpp index 03c609b5242777..fdf7e631e5ab8c 100644 --- a/paddle/function/FunctionTest.cpp +++ b/paddle/function/FunctionTest.cpp @@ -85,6 +85,7 @@ void testBufferArgs(const BufferArgs& inputs, } void testBufferArgs(const BufferArgs& inputs, const CheckBufferArg& check) { + EXPECT_EQ(inputs.size(), 1); check(inputs[0]); } diff --git a/paddle/function/FunctionTest.h b/paddle/function/FunctionTest.h index 412e3a7d1b30a7..24e7a36a43cfa8 100644 --- a/paddle/function/FunctionTest.h +++ b/paddle/function/FunctionTest.h @@ -172,7 +172,7 @@ class FunctionCompare { void initArg(SequenceIdArg& arg, size_t batchSize) { size_t numSeqs = arg.numSeqs(); - int* buf = (int*)arg.data(); + int* buf = reinterpret_cast(arg.data()); int pos = 0; size_t maxLen = 2 * batchSize / numSeqs; for (int i = 0; i < (int)numSeqs; ++i) { From c21595d6d9ac964763638531687080477e6c75ca Mon Sep 17 00:00:00 2001 From: cxysteven Date: Tue, 17 Jan 2017 17:33:24 +0800 Subject: [PATCH 049/370] bug fixed --- demo/traffic_prediction/predict.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/traffic_prediction/predict.sh b/demo/traffic_prediction/predict.sh index cec35dce11d1c1..2dbd5e8805dd97 100755 --- a/demo/traffic_prediction/predict.sh +++ b/demo/traffic_prediction/predict.sh @@ -25,6 +25,6 @@ paddle train \ --config_args=is_predict=1 \ --predict_output_dir=. -python gen_result.py > result.txt +python gen_result.py > result.csv rm -rf rank-00000 From d79cac158d5436b987c07e398b029e26210f2c96 Mon Sep 17 00:00:00 2001 From: liaogang Date: Tue, 17 Jan 2017 17:45:50 +0800 Subject: [PATCH 050/370] Update python-matplotlib in Dockerfile --- paddle/scripts/docker/Dockerfile | 4 ++-- paddle/scripts/docker/Dockerfile.gpu | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile index 13a5758f7b66a1..01261d7a2df468 100644 --- a/paddle/scripts/docker/Dockerfile +++ b/paddle/scripts/docker/Dockerfile @@ -9,12 +9,12 @@ RUN apt-get update && \ apt-get install -y git python-pip python-dev openssh-server && \ apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ - apt-get install -y g++ clang-3.8 llvm-3.8 libclang-3.8-dev && \ + apt-get install -y python-matplotlib g++ && \ apt-get clean -y RUN pip install --upgrade pip && \ pip install 'protobuf==3.1.0.post1' && \ - pip install -U numpy wheel matplotlib pillow && \ + pip install -U numpy wheel pillow && \ pip install -U BeautifulSoup docopt PyYAML sphinx && \ pip install -U sphinx_rtd_theme recommonmark jupyter diff --git a/paddle/scripts/docker/Dockerfile.gpu b/paddle/scripts/docker/Dockerfile.gpu index bab86114feaf99..108cfd9c9eb9ff 100644 --- a/paddle/scripts/docker/Dockerfile.gpu +++ b/paddle/scripts/docker/Dockerfile.gpu @@ -9,12 +9,12 @@ RUN apt-get update && \ apt-get install -y git python-pip python-dev openssh-server && \ apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ - apt-get install -y g++ clang-3.8 llvm-3.8 libclang-3.8-dev && \ + apt-get install -y python-matplotlib g++ && \ apt-get clean -y RUN pip install --upgrade pip && \ pip install 'protobuf==3.1.0.post1' && \ - pip install -U numpy wheel matplotlib pillow && \ + pip install -U numpy wheel pillow && \ pip install -U BeautifulSoup docopt PyYAML sphinx && \ pip install -U sphinx_rtd_theme recommonmark jupyter From 832bb6a745975c8327da396a48303f407649337c Mon Sep 17 00:00:00 2001 From: liaogang Date: Tue, 17 Jan 2017 17:57:38 +0800 Subject: [PATCH 051/370] Update docs --- doc/getstarted/build_and_install/build_from_source_en.md | 4 ++-- paddle/scripts/docker/Dockerfile | 6 +++--- paddle/scripts/docker/Dockerfile.gpu | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/getstarted/build_and_install/build_from_source_en.md b/doc/getstarted/build_and_install/build_from_source_en.md index 7d963a5a6df3cf..6cd2183f489881 100644 --- a/doc/getstarted/build_and_install/build_from_source_en.md +++ b/doc/getstarted/build_and_install/build_from_source_en.md @@ -101,8 +101,8 @@ As a simple example, consider the following: ```bash # necessary sudo apt-get update - sudo apt-get install -y g++ make cmake build-essential python python-pip libpython-dev git - sudo pip install wheel numpy + sudo apt-get install -y g++ make cmake build-essential python python-pip python-numpy libpython-dev git + sudo pip install wheel sudo pip install 'protobuf>=3.0.0' ``` diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile index 01261d7a2df468..28d7696c8cfcc2 100644 --- a/paddle/scripts/docker/Dockerfile +++ b/paddle/scripts/docker/Dockerfile @@ -9,13 +9,13 @@ RUN apt-get update && \ apt-get install -y git python-pip python-dev openssh-server && \ apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ - apt-get install -y python-matplotlib g++ && \ + apt-get install -y python-numpy python-matplotlib g++ && \ apt-get clean -y RUN pip install --upgrade pip && \ pip install 'protobuf==3.1.0.post1' && \ - pip install -U numpy wheel pillow && \ - pip install -U BeautifulSoup docopt PyYAML sphinx && \ + pip install -U wheel pillow BeautifulSoup && \ + pip install -U docopt PyYAML sphinx && \ pip install -U sphinx_rtd_theme recommonmark jupyter RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \ diff --git a/paddle/scripts/docker/Dockerfile.gpu b/paddle/scripts/docker/Dockerfile.gpu index 108cfd9c9eb9ff..b1344f275b61c8 100644 --- a/paddle/scripts/docker/Dockerfile.gpu +++ b/paddle/scripts/docker/Dockerfile.gpu @@ -9,13 +9,13 @@ RUN apt-get update && \ apt-get install -y git python-pip python-dev openssh-server && \ apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ - apt-get install -y python-matplotlib g++ && \ + apt-get install -y python-numpy python-matplotlib g++ && \ apt-get clean -y RUN pip install --upgrade pip && \ pip install 'protobuf==3.1.0.post1' && \ - pip install -U numpy wheel pillow && \ - pip install -U BeautifulSoup docopt PyYAML sphinx && \ + pip install -U wheel pillow BeautifulSoup && \ + pip install -U docopt PyYAML sphinx && \ pip install -U sphinx_rtd_theme recommonmark jupyter RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \ From 3d01c60e25c1b5874e6854ac565646d6ad9432d7 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 17 Jan 2017 15:44:09 +0800 Subject: [PATCH 052/370] Stash --- paddle/utils/Compiler.h | 0 paddle/utils/Status.h | 9 ++++++++- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 paddle/utils/Compiler.h diff --git a/paddle/utils/Compiler.h b/paddle/utils/Compiler.h new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/paddle/utils/Status.h b/paddle/utils/Status.h index 52f312378eedaa..cb66e4b225e92c 100644 --- a/paddle/utils/Status.h +++ b/paddle/utils/Status.h @@ -24,6 +24,13 @@ namespace paddle { * Status is Paddle error code. It only contain a std::string as error message. * Although Status inherits the std::exception, but do not throw it except you * know what you are doing. + * + * + * There are two styles to return status in Paddle. + * + * 1. Return Status + * + * */ class Status final : public std::exception { public: @@ -52,7 +59,7 @@ class Status final : public std::exception { */ template inline void setByPrintf(const char* fmt, ARGS... args) noexcept { - constexpr size_t kBufferSize = 4096; + constexpr size_t kBufferSize = 1024; // 1KB buffer char buffer[kBufferSize]; snprintf(buffer, kBufferSize, fmt, args...); errMsg_.reset(new std::string(buffer)); From ee59d109373e1417460e10227692548698bbcac7 Mon Sep 17 00:00:00 2001 From: liaogang Date: Tue, 17 Jan 2017 21:08:02 +0800 Subject: [PATCH 053/370] Add gfortran in docker --- .../build_and_install/build_from_source_en.md | 17 +++++++++++------ paddle/scripts/docker/Dockerfile | 2 +- paddle/scripts/docker/Dockerfile.gpu | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/doc/getstarted/build_and_install/build_from_source_en.md b/doc/getstarted/build_and_install/build_from_source_en.md index 6cd2183f489881..fbca407030e682 100644 --- a/doc/getstarted/build_and_install/build_from_source_en.md +++ b/doc/getstarted/build_and_install/build_from_source_en.md @@ -16,7 +16,7 @@ cd paddle To compile the source code, your computer must be equipped with the following dependencies. -- **Compiler**: GCC >= 4.8 or Clang >= 3.3 (AppleClang >= 5.1) +- **Compiler**: GCC >= 4.8 or Clang >= 3.3 (AppleClang >= 5.1) and gfortran compiler - **CMake**: CMake >= 3.0 (at least CMake 3.4 on Mac OS X) - **BLAS**: MKL, OpenBlas or ATLAS - **Python**: only support Python 2.7 @@ -96,16 +96,21 @@ As a simple example, consider the following: ### Install Dependencies -- **CPU Dependencies** +- **Paddle Dependencies** ```bash # necessary sudo apt-get update - sudo apt-get install -y g++ make cmake build-essential python python-pip python-numpy libpython-dev git - sudo pip install wheel - sudo pip install 'protobuf>=3.0.0' + sudo apt-get install -y git curl gcc g++ gfortran make build-essential + sudo apt-get install -y python python-pip python-numpy libpython-dev + sudo pip install 'protobuf==3.1.0.post1' + + # install cmake 3.4 + curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \ + cd cmake-3.4.1 && ./bootstrap && make -j4 && sudo make install && \ + cd .. && rm -rf cmake-3.4.1 ``` - + - **GPU Dependencies (optional)** To build GPU version, you will need the following installed: diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile index 28d7696c8cfcc2..127ebf26c23730 100644 --- a/paddle/scripts/docker/Dockerfile +++ b/paddle/scripts/docker/Dockerfile @@ -9,7 +9,7 @@ RUN apt-get update && \ apt-get install -y git python-pip python-dev openssh-server && \ apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ - apt-get install -y python-numpy python-matplotlib g++ && \ + apt-get install -y python-numpy python-matplotlib gcc g++ gfortran && \ apt-get clean -y RUN pip install --upgrade pip && \ diff --git a/paddle/scripts/docker/Dockerfile.gpu b/paddle/scripts/docker/Dockerfile.gpu index b1344f275b61c8..a729e33d468cd3 100644 --- a/paddle/scripts/docker/Dockerfile.gpu +++ b/paddle/scripts/docker/Dockerfile.gpu @@ -9,7 +9,7 @@ RUN apt-get update && \ apt-get install -y git python-pip python-dev openssh-server && \ apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ - apt-get install -y python-numpy python-matplotlib g++ && \ + apt-get install -y python-numpy python-matplotlib gcc g++ gfortran && \ apt-get clean -y RUN pip install --upgrade pip && \ From 70dfd7f13732ab10452809ce68d394b0b300382f Mon Sep 17 00:00:00 2001 From: liaogang Date: Tue, 17 Jan 2017 21:37:30 +0800 Subject: [PATCH 054/370] Add automake in dockerfile --- doc/getstarted/build_and_install/build_from_source_en.md | 4 ++-- paddle/scripts/docker/Dockerfile | 1 + paddle/scripts/docker/Dockerfile.gpu | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/getstarted/build_and_install/build_from_source_en.md b/doc/getstarted/build_and_install/build_from_source_en.md index fbca407030e682..27b478a0fdd9ab 100644 --- a/doc/getstarted/build_and_install/build_from_source_en.md +++ b/doc/getstarted/build_and_install/build_from_source_en.md @@ -101,8 +101,8 @@ As a simple example, consider the following: ```bash # necessary sudo apt-get update - sudo apt-get install -y git curl gcc g++ gfortran make build-essential - sudo apt-get install -y python python-pip python-numpy libpython-dev + sudo apt-get install -y git curl gcc g++ gfortran make build-essential autotools-dev + sudo apt-get install -y python python-pip python-numpy libpython-dev automake sudo pip install 'protobuf==3.1.0.post1' # install cmake 3.4 diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile index 127ebf26c23730..d46dd48f744b33 100644 --- a/paddle/scripts/docker/Dockerfile +++ b/paddle/scripts/docker/Dockerfile @@ -10,6 +10,7 @@ RUN apt-get update && \ apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ apt-get install -y python-numpy python-matplotlib gcc g++ gfortran && \ + apt-get install -y autotools-dev automake && \ apt-get clean -y RUN pip install --upgrade pip && \ diff --git a/paddle/scripts/docker/Dockerfile.gpu b/paddle/scripts/docker/Dockerfile.gpu index a729e33d468cd3..58070b2ad9c862 100644 --- a/paddle/scripts/docker/Dockerfile.gpu +++ b/paddle/scripts/docker/Dockerfile.gpu @@ -10,6 +10,7 @@ RUN apt-get update && \ apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ apt-get install -y python-numpy python-matplotlib gcc g++ gfortran && \ + apt-get install -y autotools-dev automake && \ apt-get clean -y RUN pip install --upgrade pip && \ From 878b321a128bd405e0cb66efc00e800ea03d0fad Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Tue, 17 Jan 2017 11:59:26 -0800 Subject: [PATCH 055/370] changes wording for paddle on k8s tutorial --- doc/howto/usage/k8s/k8s_aws_en.md | 92 ++++++++---------- .../usage/k8s/src/pserver_and_trainer.png | Bin 0 -> 71688 bytes 2 files changed, 41 insertions(+), 51 deletions(-) create mode 100644 doc/howto/usage/k8s/src/pserver_and_trainer.png diff --git a/doc/howto/usage/k8s/k8s_aws_en.md b/doc/howto/usage/k8s/k8s_aws_en.md index 00bc41e5c3e2e9..10f5a2ef2fcaf9 100644 --- a/doc/howto/usage/k8s/k8s_aws_en.md +++ b/doc/howto/usage/k8s/k8s_aws_en.md @@ -361,20 +361,9 @@ ip-10-0-0-xx.us-west-1.compute.internal Ready,SchedulingDisabled 5m ``` -### Setup PaddlePaddle Environment on AWS +### Setup Elastic File System for Cluster -Now, we've created a cluster with following network capability: - -1. All Kubernetes nodes can communicate with each other. - -1. All Docker containers on Kubernetes nodes can communicate with each other. - -1. All Kubernetes nodes can communicate with all Docker containers on Kubernetes nodes. - -1. All other traffic loads from outside of Kubernetes nodes cannot reach to the Docker containers on Kubernetes nodes except for creating the services for containers. - - -For sharing the training data across all the Kubernetes nodes, we use EFS (Elastic File System) in AWS. Ceph might be a better solution, but it requires high version of Linux kernel that might not be stable enough at this moment. We haven't automated the EFS setup at this moment, so please do the following steps: +Training data is usually served on a distributed filesystem, we use Elastic File System (EFS) on AWS. Ceph might be a better solution, but it requires high version of Linux kernel that might not be stable enough at this moment. We haven't automated the EFS setup at this moment, so please do the following steps: 1. Make sure you added AmazonElasticFileSystemFullAccess policy in your group. @@ -391,57 +380,71 @@ For sharing the training data across all the Kubernetes nodes, we use EFS (Elast
![](src/efs_mount.png)
-Before starting the training, you should place your user config and divided training data onto EFS. When the training start, each task will copy related files from EFS into container, and it will also write the training results back onto EFS, we will show you how to place the data later in this article. +We will place user config and divided training data onto EFS. Training task will cache related files by copying them from EFS into container. It will also write the training results back onto EFS. We will show you how to place the data later in this article. + + + +### Core Concepts of PaddlePaddle Training on AWS +Now we've already setup a 3 nodes distributed Kubernetes cluster, and on each node we've attached the EFS volume. In this training demo, we will create three Kubernetes pods and schedule them on three nodes. Each pod contains a PaddlePaddle container. When container gets created, it will start parameter server (pserver) and trainer process, load the training data from EFS volume and start the distributed training task. +#### Distributed Training Job -###Core Concept of PaddlePaddle Training on AWS +Distributed training job is represented by a [kubernetes job](https://kubernetes.io/docs/user-guide/jobs/#what-is-a-job). -Now we've already setup a 3 nodes distributed Kubernetes cluster, and on each node we've attached the EFS volume, in this training demo, we will create three Kubernetes pod and scheduling them on 3 node. Each pod contains a PaddlePaddle container. When container gets created, it will start pserver and trainer process, load the training data from EFS volume and start the distributed training task. +Kubernetes job is described by a job config file. The file contains lots of configuration information. For example, PaddlePaddle's node number, `paddle pserver` open port number, the network card info etc. These information are passed into container for `pserver` and `trainer` to use as environment variables. -####Use Kubernetes Job +In one distributed training job, we will: -We use Kubernetes job to represent one time of distributed training. After the job get finished, Kubernetes will destroy job container and release all related resources. +1. Upload the pre-divided training data and configuration file onto EFS volume. +1. Create and submit the Kubernetes job config to the Kubernetes cluster to start the training job. -We can write a yaml file to describe the Kubernetes job. The file contains lots of configuration information, for example PaddlePaddle's node number, `paddle pserver` open port number, the network card info etc., these information are passed into container for processes to use as environment variables. +#### Parameter Server and Trainer -In one time of distributed training, user will confirm the PaddlePaddle node number first. And then upload the pre-divided training data and configuration file onth EFS volume. And then create the Kubernetes job yaml file; submit to the Kubernetes cluster to start the training job. +There are two roles in a PaddlePaddle cluster: `parameter server` and `trainer`. Each parameter server process maintains a shard of the global model. Each trainer has its local copy of the model, and uses its local data to update the model. During the training process, trainers send model updates to parameter servers, parameter servers are responsible for aggregating these updates, so that trainers can synchronize their local copy with the global model. -####Create PaddlePaddle Node +
![Model is partitioned into two shards. Managed by two parameter servers respectively.](src/pserver_and_trainer.png)
-After Kubernetes master gets the request, it will parse the yaml file and create several pods (defined by PaddlePaddle's node number), Kubernetes will allocate these pods onto cluster's node. A pod represents a PaddlePaddle node, when pod is successfully allocated onto one physical/virtual machine, Kubernetes will startup the container in the pod, and this container will use the environment variables in yaml file and start up `paddle pserver` and `paddle trainer` processes. +In order to communicate with pserver, trainer needs to know the ip address of each pserver. In kubernetes it's better to use a service discovery mechanism (e.g., DNS hostname) rather than static ip address, since any pserver's pod may be killed and a new pod could be schduled onto another node of different ip address. We will improve paddlepaddle's service discovery ability. For now we will use static ip. +Parameter server and trainer are packaged into a same docker image. They will run once pod is scheduled by kubernetes job. -####Start up Training +#### Trainer ID -After container gets started, it starts up the distributed training by using scripts. We know `paddle train` process need to know other node's ip address and it's own trainer_id, since PaddlePaddle currently don't have the ability to do the service discovery, so in the start up script, each node will use job pod's name to query all to pod info from Kubernetes apiserver (apiserver's endpoint is an environment variable in container by default). +Trainer id is the index of trainer within all trainers of a job. Trainer needs this information to do things like reading the correct shared of data. -With pod information, we can assign each pod a unique trainer_id. Here we sort all the pods by pod's ip, and assign the index to each PaddlePaddle node as it's trainer_id. The workflow of starting up the script is as follows: +#### Training -1. Query the api server to get pod information, and assign the trainer_id by sorting the ip. +After container gets started, it starts up the distributed training by using scripts. Each node will use job pod's name to query Kubernetes apiserver for information of all pods in current job. + +From pods information, script knows static ip addresses of pservers. And assign trainer it's own `trainer_id`. The workflow of the script is as follows: + +1. Query the api server to get pod information, and assign the `trainer_id` by sorting the ip. 1. Copy the training data from EFS sharing volume into container. -1. Parse the `paddle pserver` and 'paddle trainer' startup parameters from environment variables, and then start up the processes. -1. PaddlePaddle will automatically write the result onto the PaddlePaddle node with trainer_id:0, we set the output path to be the EFS volume to save the result data. +1. Parse the `paddle pserver` and `paddle trainer` startup parameters from environment variables, and then start up the processes. +1. Trainer with `train_id` 0 will automatically write results onto EFS volume. -###Start PaddlePaddle Training Demo on AWS +### Start PaddlePaddle Training Demo on AWS Now we'll start a PaddlePaddle training demo on AWS, steps are as follows: 1. Build PaddlePaddle Docker image. 1. Divide the training data file and upload it onto the EFS sharing volume. -1. Create the training job yaml file, and start up the job. +1. Create the training job config file, and start up the job. 1. Check the result after training. -####Build PaddlePaddle Docker Image +#### Build PaddlePaddle Docker Image -PaddlePaddle docker image need to provide the runtime environment for `paddle pserver` and `paddle train`, so the container use this image should have two main function: +PaddlePaddle docker image need to provide the runtime environment for `pserver` and `trainer`, so the container use this image should have two main function: 1. Copy the training data into container. -1. Generate the startup parameter for `paddle pserver` and `paddle train` process, and startup the training. +1. Generate the startup parameter for `pserver` and `trainer` process, and startup the training. + +We need to create a new image since official `paddledev/paddle:cpu-latest` only have PaddlePaddle binary, but lack of the above functionalities. -Since official `paddledev/paddle:cpu-latest` have already included the PaddlePaddle binary, but lack of the above functionalities, so we will create the startup script based on this image, to achieve the work above. the detailed Dockerfile is as follows: +Dockerfile for creating the new image is as follows: ``` FROM paddledev/paddle:cpu-latest @@ -530,7 +533,7 @@ And then push the built image onto docker registry. docker push your_repo/paddle:mypaddle ``` -####Upload Training Data File +#### Upload Training Data File Here we will use PaddlePaddle's official recommendation demo as the content for this training, we put the training data file into a directory named by job name, which located in EFS sharing volume, the tree structure for the directory looks like: @@ -550,7 +553,7 @@ efs The `paddle-cluster-job` directory is the job name for this training, this training includes 3 PaddlePaddle node, we store the pre-divided data under `paddle-cluster-job/data` directory, directory 0, 1, 2 each represent 3 nodes' trainer_id. the training data in in recommendation directory, the training results and logs will be in the output directory. -####Create Kubernetes Job +#### Create Kubernetes Job Kubernetes use yaml file to describe job details, and then use command line tool to create the job in Kubernetes cluster. @@ -632,7 +635,7 @@ After we execute the above command, Kubernetes will create 3 pods and then pull -####Check Training Results +#### Check Training Results During the training, we can see the logs and models on EFS sharing volume, the output directory contains the training results. (Caution: node_0, node_1, node_2 directories represents PaddlePaddle node and train_id, not the Kubernetes node) @@ -689,7 +692,7 @@ I1116 09:10:18.019836 50 ParameterClient2.cpp:122] pserver 5 192.168.129.71:7 It'll take around 8 hours to finish this PaddlePaddle recommendation training demo on three 2 core 8 GB EC2 machine (m3.large). -###Kubernetes Cluster Tear Down +### Kubernetes Cluster Tear Down If you want to tear down the whole Kubernetes cluster, make sure to *delete* the EFS volume first (otherwise, you will get stucked on following steps), and then use the following command: @@ -700,16 +703,3 @@ kube-aws destroy It's an async call, it might take 5 min to tear down the whole cluster. If you created any Kubernetes Services of type LoadBalancer, you must delete these first, as the CloudFormation cannot be fully destroyed if any externally-managed resources still exist. - - - -## For Experts with Kubernetes and AWS - -Sometimes we might need to create or manage the cluster on AWS manually with limited privileges, so here we will explain more on what’s going on with the Kubernetes setup script. - -### Some Presumptions - -* Instances run on CoreOS, the official IAM. -* Kubernetes node use instance storage, no EBS get mounted. Etcd is running on additional node. -* For networking, we use Flannel network at this moment, we will use Calico solution later on. -* When you create a service with Type=LoadBalancer, Kubernetes will create and ELB, and create a security group for the ELB. diff --git a/doc/howto/usage/k8s/src/pserver_and_trainer.png b/doc/howto/usage/k8s/src/pserver_and_trainer.png new file mode 100644 index 0000000000000000000000000000000000000000..f41fe48920590333ad332bb51eb18e03dc251541 GIT binary patch literal 71688 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

f~#`&?YC< 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\xJ`@_XHst`L=vVQ^ZMhA4vOZMjd*|7Q44^NQ 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 aRF+60qV`#@@0$zYkJ>{mrE&%9=l=tnkqu@5 literal 0 HcmV?d00001 From 20b851c10f91e884b5174d7c6b2870e615a6cbbf Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Tue, 17 Jan 2017 13:40:58 -0800 Subject: [PATCH 056/370] fix according to comments --- doc/howto/usage/k8s/k8s_aws_en.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/howto/usage/k8s/k8s_aws_en.md b/doc/howto/usage/k8s/k8s_aws_en.md index 10f5a2ef2fcaf9..c144bab649f31b 100644 --- a/doc/howto/usage/k8s/k8s_aws_en.md +++ b/doc/howto/usage/k8s/k8s_aws_en.md @@ -392,14 +392,14 @@ Now we've already setup a 3 nodes distributed Kubernetes cluster, and on each no Distributed training job is represented by a [kubernetes job](https://kubernetes.io/docs/user-guide/jobs/#what-is-a-job). -Kubernetes job is described by a job config file. The file contains lots of configuration information. For example, PaddlePaddle's node number, `paddle pserver` open port number, the network card info etc. These information are passed into container for `pserver` and `trainer` to use as environment variables. +Each Kuberentes job is described by a job config file, which specifies the information like the number of pods in the job and environment variables. -In one distributed training job, we will: +In a distributed training job, we would: -1. Upload the pre-divided training data and configuration file onto EFS volume. -1. Create and submit the Kubernetes job config to the Kubernetes cluster to start the training job. +1. upload the partitioned training data and configuration file onto EFS volume, and +1. create and submit the Kubernetes job config to the Kubernetes cluster to start the training job. -#### Parameter Server and Trainer +#### Parameter Servers and Trainers There are two roles in a PaddlePaddle cluster: `parameter server` and `trainer`. Each parameter server process maintains a shard of the global model. Each trainer has its local copy of the model, and uses its local data to update the model. During the training process, trainers send model updates to parameter servers, parameter servers are responsible for aggregating these updates, so that trainers can synchronize their local copy with the global model. @@ -411,13 +411,13 @@ Parameter server and trainer are packaged into a same docker image. They will ru #### Trainer ID -Trainer id is the index of trainer within all trainers of a job. Trainer needs this information to do things like reading the correct shared of data. +Each trainer process requires a trainer ID, a zero-based index value, passed in as a command-line parameter. The trainer process thus reads the data partition indexed by this ID. #### Training -After container gets started, it starts up the distributed training by using scripts. Each node will use job pod's name to query Kubernetes apiserver for information of all pods in current job. +The entry-point of a container is a Python script. As it runs in a pod, it can see some environment variables pre-defined by Kubernetes. This includes one that gives the job's identity, which can be used in a remote call to the Kubernetes apiserver that lists all pods in the job. -From pods information, script knows static ip addresses of pservers. And assign trainer it's own `trainer_id`. The workflow of the script is as follows: +We rank each pod by sorting them by their ips. The rank of each pod could be the "pod ID". Because we run one trainer and one parameter server in each pod, we can use this "pod ID" as the trainer ID. A detailed workflow of the entry-point script is as follows: 1. Query the api server to get pod information, and assign the `trainer_id` by sorting the ip. 1. Copy the training data from EFS sharing volume into container. @@ -550,7 +550,7 @@ efs └── recommendation ``` -The `paddle-cluster-job` directory is the job name for this training, this training includes 3 PaddlePaddle node, we store the pre-divided data under `paddle-cluster-job/data` directory, directory 0, 1, 2 each represent 3 nodes' trainer_id. the training data in in recommendation directory, the training results and logs will be in the output directory. +The `paddle-cluster-job` directory is the job name for this training, this training includes 3 PaddlePaddle node, we store the partitioned data under `paddle-cluster-job/data` directory, directory 0, 1, 2 each represent 3 nodes' trainer_id. the training data in in recommendation directory, the training results and logs will be in the output directory. #### Create Kubernetes Job From f4ff8d26d6cb50b6749264f8db460732fda1e37b Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Tue, 17 Jan 2017 13:41:45 -0800 Subject: [PATCH 057/370] fix according to comments --- doc/howto/usage/k8s/k8s_aws_en.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/howto/usage/k8s/k8s_aws_en.md b/doc/howto/usage/k8s/k8s_aws_en.md index c144bab649f31b..a6422b9be00e21 100644 --- a/doc/howto/usage/k8s/k8s_aws_en.md +++ b/doc/howto/usage/k8s/k8s_aws_en.md @@ -390,7 +390,7 @@ Now we've already setup a 3 nodes distributed Kubernetes cluster, and on each no #### Distributed Training Job -Distributed training job is represented by a [kubernetes job](https://kubernetes.io/docs/user-guide/jobs/#what-is-a-job). +A distributed training job is represented by a [kubernetes job](https://kubernetes.io/docs/user-guide/jobs/#what-is-a-job). Each Kuberentes job is described by a job config file, which specifies the information like the number of pods in the job and environment variables. From b89f2f2f0c97e3f5328bb17061c4c551b8af91cd Mon Sep 17 00:00:00 2001 From: liaogang Date: Wed, 18 Jan 2017 09:35:01 +0800 Subject: [PATCH 058/370] Update build doc and dockerfile --- cmake/external/swig.cmake | 23 ++++--------------- .../build_and_install/build_from_source_en.md | 4 ++-- paddle/scripts/docker/Dockerfile | 4 ++-- paddle/scripts/docker/Dockerfile.gpu | 4 ++-- 4 files changed, 11 insertions(+), 24 deletions(-) diff --git a/cmake/external/swig.cmake b/cmake/external/swig.cmake index 63e8bd25462e50..744c766ee7b067 100644 --- a/cmake/external/swig.cmake +++ b/cmake/external/swig.cmake @@ -38,14 +38,6 @@ IF(NOT SWIG_FOUND) SET(SWIG_DIR ${SWIG_SOURCES_DIR} CACHE FILEPATH "SWIG Directory" FORCE) SET(SWIG_EXECUTABLE ${SWIG_SOURCES_DIR}/swig.exe CACHE FILEPATH "SWIG Executable" FORCE) ELSE(WIN32) - # From PCRE configure - ExternalProject_Add(pcre - ${EXTERNAL_PROJECT_LOG_ARGS} - GIT_REPOSITORY https://github.com/svn2github/pcre.git - PREFIX ${SWIG_SOURCES_DIR}/pcre - CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${SWIG_INSTALL_DIR}/pcre - ) - # swig uses bison find it by cmake and pass it down FIND_PACKAGE(BISON) @@ -54,16 +46,11 @@ IF(NOT SWIG_FOUND) GIT_REPOSITORY https://github.com/swig/swig.git GIT_TAG rel-3.0.10 PREFIX ${SWIG_SOURCES_DIR} - CONFIGURE_COMMAND cd ${SWIG_SOURCES_DIR}/src/swig && ./autogen.sh - CONFIGURE_COMMAND cd ${SWIG_SOURCES_DIR}/src/swig && - env "PCRE_LIBS=${SWIG_INSTALL_DIR}/pcre/lib/libpcre.a ${SWIG_INSTALL_DIR}/pcre/lib/libpcrecpp.a ${SWIG_INSTALL_DIR}/pcre/lib/libpcreposix.a" - ./configure - --prefix=${SWIG_INSTALL_DIR} - --with-pcre-prefix=${SWIG_INSTALL_DIR}/pcre - BUILD_COMMAND cd ${SWIG_SOURCES_DIR}/src/swig && make - INSTALL_COMMAND cd ${SWIG_SOURCES_DIR}/src/swig && make install - UPDATE_COMMAND "" - DEPENDS pcre + CONFIGURE_COMMAND cd && ./autogen.sh && ./configure + --prefix=${SWIG_INSTALL_DIR} --without-pcre + BUILD_COMMAND cd && make + INSTALL_COMMAND cd && make install + UPDATE_COMMAND "" ) SET(SWIG_DIR ${SWIG_INSTALL_DIR}/share/swig/${SWIG_TARGET_VERSION}) diff --git a/doc/getstarted/build_and_install/build_from_source_en.md b/doc/getstarted/build_and_install/build_from_source_en.md index 27b478a0fdd9ab..7e0942b211bb1d 100644 --- a/doc/getstarted/build_and_install/build_from_source_en.md +++ b/doc/getstarted/build_and_install/build_from_source_en.md @@ -101,8 +101,8 @@ As a simple example, consider the following: ```bash # necessary sudo apt-get update - sudo apt-get install -y git curl gcc g++ gfortran make build-essential autotools-dev - sudo apt-get install -y python python-pip python-numpy libpython-dev automake + sudo apt-get install -y git curl gcc g++ gfortran make build-essential automake + sudo apt-get install -y python python-pip python-numpy libpython-dev bison sudo pip install 'protobuf==3.1.0.post1' # install cmake 3.4 diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile index d46dd48f744b33..79c4efbed0b856 100644 --- a/paddle/scripts/docker/Dockerfile +++ b/paddle/scripts/docker/Dockerfile @@ -6,11 +6,11 @@ ARG UBUNTU_MIRROR RUN /bin/bash -c 'if [[ -n ${UBUNTU_MIRROR} ]]; then sed -i 's#http://archive.ubuntu.com#${UBUNTU_MIRROR}#g' /etc/apt/sources.list; fi' RUN apt-get update && \ - apt-get install -y git python-pip python-dev openssh-server && \ + apt-get install -y git python-pip python-dev openssh-server bison && \ apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ apt-get install -y python-numpy python-matplotlib gcc g++ gfortran && \ - apt-get install -y autotools-dev automake && \ + apt-get install -y automake clang-3.8 llvm-3.8 libclang-3.8-dev && \ apt-get clean -y RUN pip install --upgrade pip && \ diff --git a/paddle/scripts/docker/Dockerfile.gpu b/paddle/scripts/docker/Dockerfile.gpu index 58070b2ad9c862..6c1c2225d1a304 100644 --- a/paddle/scripts/docker/Dockerfile.gpu +++ b/paddle/scripts/docker/Dockerfile.gpu @@ -6,11 +6,11 @@ ARG UBUNTU_MIRROR RUN /bin/bash -c 'if [[ -n ${UBUNTU_MIRROR} ]]; then sed -i 's#http://archive.ubuntu.com#${UBUNTU_MIRROR}#g' /etc/apt/sources.list; fi' RUN apt-get update && \ - apt-get install -y git python-pip python-dev openssh-server && \ + apt-get install -y git python-pip python-dev openssh-server bison && \ apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ apt-get install -y python-numpy python-matplotlib gcc g++ gfortran && \ - apt-get install -y autotools-dev automake && \ + apt-get install -y automake clang-3.8 llvm-3.8 libclang-3.8-dev && \ apt-get clean -y RUN pip install --upgrade pip && \ From 9bc12034002d0c0ca5f30bd1f11b30188978e327 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 18 Jan 2017 12:45:00 +0800 Subject: [PATCH 059/370] Add more comments, also add __must_check. --- .../activations/ActivationFunction.cpp | 55 +++++++++--------- .../gserver/activations/ActivationFunction.h | 4 +- paddle/gserver/layers/Layer.cpp | 4 +- paddle/gserver/layers/MDLstmLayer.cpp | 25 +++++---- paddle/gserver/layers/NCELayer.cpp | 6 +- paddle/gserver/layers/RecurrentLayer.cpp | 21 +++---- .../layers/SelectiveFullyConnectedLayer.cpp | 3 +- paddle/gserver/tests/test_WarpCTCLayer.cpp | 4 +- paddle/utils/Compiler.h | 25 +++++++++ paddle/utils/Status.h | 56 +++++++++++++++++++ 10 files changed, 147 insertions(+), 56 deletions(-) diff --git a/paddle/gserver/activations/ActivationFunction.cpp b/paddle/gserver/activations/ActivationFunction.cpp index 8a938cf7e9d730..666c2e01c8bdaf 100644 --- a/paddle/gserver/activations/ActivationFunction.cpp +++ b/paddle/gserver/activations/ActivationFunction.cpp @@ -69,11 +69,11 @@ static ClassRegistrar gActivationRegistrar; class IdentityActivation : public ActivationFunction { public: static const std::string name; - Status forward(Argument& act) { + Status __must_check forward(Argument& act) { (void)act; return Status(); } - Status backward(Argument& act) { + Status __must_check backward(Argument& act) { (void)act; return Status(); } @@ -92,11 +92,11 @@ static InitFunction __reg_activation__identity([] { * \f] */ BEGIN_DEFINE_ACTIVATION(sigmoid) -Status forward(Argument& act) { +Status __must_check forward(Argument& act) { act.value->sigmoid(*act.value); return Status(); } -Status backward(Argument& act) { +Status __must_check backward(Argument& act) { act.grad->sigmoidDerivative(*act.value); return Status(); } @@ -115,12 +115,12 @@ MatrixPtr sftMaxDot_; MatrixPtr one_; public: -Status forward(Argument& act) { +Status __must_check forward(Argument& act) { act.value->softmax(*act.value); return Status(); } -Status backward(Argument& act) { +Status __must_check backward(Argument& act) { MatrixPtr outputV = act.value; MatrixPtr outputG = act.grad; @@ -167,7 +167,7 @@ ACTIVATION_CLASS_NAME(softmax) softmax_; Argument argument_; public: -Status forward(Argument& act) { +Status __must_check forward(Argument& act) { if (act.value->getWidth() != 1UL) { return Status( "Input width for each timestep of sequence softmax should be 1"); @@ -191,7 +191,7 @@ Status forward(Argument& act) { return Status(); } -Status backward(Argument& act) { +Status __must_check backward(Argument& act) { if (act.value->getWidth() != 1UL) { return Status( "Input width for each timestep of sequence softmax should be 1"); @@ -207,7 +207,8 @@ Status backward(Argument& act) { argument_.value->setData(act.value->getData() + offset, 1UL, size); argument_.grad->setData(act.grad->getData() + offset, 1UL, size); - softmax_.backward(argument_); + Status status = softmax_.backward(argument_); + if (!status.isOK()) return status; } return Status(); } @@ -224,12 +225,12 @@ END_DEFINE_ACTIVATION(sequence_softmax) * 0 otherwise. */ BEGIN_DEFINE_ACTIVATION(relu) -Status forward(Argument& act) { +Status __must_check forward(Argument& act) { act.value->relu(*act.value); return Status(); } -Status backward(Argument& act) { +Status __must_check backward(Argument& act) { act.grad->reluDerivative(*act.value); return Status(); } @@ -249,12 +250,12 @@ END_DEFINE_ACTIVATION(relu) * TODO(yuyang18): Remove magic number 24 or make it configuable. */ BEGIN_DEFINE_ACTIVATION(brelu) -Status forward(Argument& act) { +Status __must_check forward(Argument& act) { act.value->brelu(*act.value); return Status(); } -Status backward(Argument& act) { +Status __must_check backward(Argument& act) { act.grad->breluDerivative(*act.value); return Status(); } @@ -267,12 +268,12 @@ END_DEFINE_ACTIVATION(brelu) * \f] */ BEGIN_DEFINE_ACTIVATION(tanh) -Status forward(Argument& act) { +Status __must_check forward(Argument& act) { act.value->tanh(*act.value); return Status(); } -Status backward(Argument& act) { +Status __must_check backward(Argument& act) { act.grad->tanhDerivative(*act.value); return Status(); } @@ -290,12 +291,12 @@ real a, b; public: ACTIVATION_CLASS_NAME(stanh)() : a(1.7159), b(2. / 3.) {} -Status forward(Argument& act) { +Status __must_check forward(Argument& act) { act.value->scaledTanh(*act.value, a, b); return Status(); } -Status backward(Argument& act) { +Status __must_check backward(Argument& act) { act.grad->scaledTanhDerivative(*act.value, a, b); return Status(); } @@ -308,12 +309,12 @@ END_DEFINE_ACTIVATION(stanh) * \f] */ BEGIN_DEFINE_ACTIVATION(softrelu) -Status forward(Argument& act) { +Status __must_check forward(Argument& act) { act.value->softrelu(*act.value); return Status(); } -Status backward(Argument& act) { +Status __must_check backward(Argument& act) { act.grad->softreluDerivative(*act.value); return Status(); } @@ -332,7 +333,7 @@ END_DEFINE_ACTIVATION(softrelu) * 0 if z=0 */ BEGIN_DEFINE_ACTIVATION(abs) -Status forward(Argument& act) { +Status __must_check forward(Argument& act) { SetDevice device(act.deviceId); Matrix::resizeOrCreate(act.in, act.value->getHeight(), @@ -345,7 +346,7 @@ Status forward(Argument& act) { return Status(); } -Status backward(Argument& act) { +Status __must_check backward(Argument& act) { act.grad->absDerivative(*act.in); return Status(); } @@ -358,7 +359,7 @@ END_DEFINE_ACTIVATION(abs) * \f] */ BEGIN_DEFINE_ACTIVATION(square) -Status forward(Argument& act) { +Status __must_check forward(Argument& act) { SetDevice device(act.deviceId); Matrix::resizeOrCreate(act.in, act.value->getHeight(), @@ -371,7 +372,7 @@ Status forward(Argument& act) { return Status(); } -Status backward(Argument& act) { +Status __must_check backward(Argument& act) { act.grad->squareDerivative(*act.in); return Status(); } @@ -384,12 +385,12 @@ END_DEFINE_ACTIVATION(square) * \f] */ BEGIN_DEFINE_ACTIVATION(exponential) -Status forward(Argument& act) { +Status __must_check forward(Argument& act) { act.value->exp2(*act.value); return Status(); } -Status backward(Argument& act) { +Status __must_check backward(Argument& act) { act.grad->expDerivative(*act.value); return Status(); } @@ -402,7 +403,7 @@ END_DEFINE_ACTIVATION(exponential) * \f] */ BEGIN_DEFINE_ACTIVATION(log) -Status forward(Argument& act) { +Status __must_check forward(Argument& act) { SetDevice device(act.deviceId); Matrix::resizeOrCreate(act.in, act.value->getHeight(), @@ -415,7 +416,7 @@ Status forward(Argument& act) { return Status(); } -Status backward(Argument& act) { +Status __must_check backward(Argument& act) { act.grad->dotDiv(*act.grad, *act.in); return Status(); } diff --git a/paddle/gserver/activations/ActivationFunction.h b/paddle/gserver/activations/ActivationFunction.h index ad395ac28da7d9..737df2219dd36f 100644 --- a/paddle/gserver/activations/ActivationFunction.h +++ b/paddle/gserver/activations/ActivationFunction.h @@ -49,7 +49,7 @@ class ActivationFunction { * * Usually, act is Layer::output_ */ - virtual Status forward(Argument& act) = 0; + virtual Status __must_check forward(Argument& act) = 0; /** * @brief Backward propagaion @@ -58,7 +58,7 @@ class ActivationFunction { * - Before calling backward(), act.grad = dE / dy, where E is the error/cost * - After backward() returns, act.grad = dE / dx = (dE/dy) * (dy/dx) */ - virtual Status backward(Argument& act) = 0; + virtual Status __must_check backward(Argument& act) = 0; virtual const std::string& getName() const = 0; }; diff --git a/paddle/gserver/layers/Layer.cpp b/paddle/gserver/layers/Layer.cpp index 06c936c3aec670..f96070fe6e269b 100644 --- a/paddle/gserver/layers/Layer.cpp +++ b/paddle/gserver/layers/Layer.cpp @@ -336,7 +336,7 @@ void Layer::showOutputStats() { void Layer::forwardActivation() { /* activation */ auto status = activation_->forward(output_); - CHECK(status.isOK()) << status.what(); + status.check(); /* dropout */ if (config_.drop_rate() > 0) { @@ -375,7 +375,7 @@ void Layer::backwardActivation() { } auto status = activation_->backward(output_); - CHECK(status.isOK()) << status.what(); + status.check(); } void Layer::forwardDropOut() { diff --git a/paddle/gserver/layers/MDLstmLayer.cpp b/paddle/gserver/layers/MDLstmLayer.cpp index fb41af56319549..88d934d782b549 100644 --- a/paddle/gserver/layers/MDLstmLayer.cpp +++ b/paddle/gserver/layers/MDLstmLayer.cpp @@ -506,9 +506,12 @@ void MDLstmLayer::forwardGate2OutputSequence(int start, *frameState_[start + preOffsetV[i]].value, *checkFgOneDim, 1.0, 1.0); } } - activationGate_->forward(frameInputGate_[idxCurr]); - activationGate_->forward(frameForgetGate_[idxCurr]); - activation_->forward(frameInputNode_[idxCurr]); + auto status = activationGate_->forward(frameInputGate_[idxCurr]); + status.check(); + status = activationGate_->forward(frameForgetGate_[idxCurr]); + status.check(); + status = activation_->forward(frameInputNode_[idxCurr]); + status.check(); frameState_[idxCurr].value->zeroMem(); for (int i = 0; i < numDims_; i++) { @@ -530,10 +533,12 @@ void MDLstmLayer::forwardGate2OutputSequence(int start, frameOutputGate_[idxCurr].value->addDotMul( *frameState_[idxCurr].value, *checkOg_, 1.0, 1.0); - activationGate_->forward(frameOutputGate_[idxCurr]); + status = activationGate_->forward(frameOutputGate_[idxCurr]); + status.check(); framePreOutput_[idxCurr].value->copyFrom(*(frameState_[idxCurr].value)); - activationState_->forward(framePreOutput_[idxCurr]); + status = activationState_->forward(framePreOutput_[idxCurr]); + status.check(); frameOutput_[idxCurr].value->dotMul(*framePreOutput_[idxCurr].value, *frameOutputGate_[idxCurr].value); @@ -640,12 +645,12 @@ void MDLstmLayer::backwardGate2OutputSequence(int start, framePreOutput_[idxCurr].grad->dotMul(*frameOutput_[idxCurr].grad, *frameOutputGate_[idxCurr].value); - activationState_->backward(framePreOutput_[idxCurr]); + activationState_->backward(framePreOutput_[idxCurr]).check(); frameState_[idxCurr].grad->copyFrom(*(framePreOutput_[idxCurr].grad)); frameOutputGate_[idxCurr].grad->dotMul(*frameOutput_[idxCurr].grad, *framePreOutput_[idxCurr].value); - activationGate_->backward(frameOutputGate_[idxCurr]); + activationGate_->backward(frameOutputGate_[idxCurr]).check(); frameState_[idxCurr].grad->addDotMul( *frameOutputGate_[idxCurr].grad, *checkOg_, 1.0, 1.0); @@ -702,9 +707,9 @@ void MDLstmLayer::backwardGate2OutputSequence(int start, } } - activationGate_->backward(frameInputGate_[idxCurr]); - activationGate_->backward(frameForgetGate_[idxCurr]); - activation_->backward(frameInputNode_[idxCurr]); + activationGate_->backward(frameInputGate_[idxCurr]).check(); + activationGate_->backward(frameForgetGate_[idxCurr]).check(); + activation_->backward(frameInputNode_[idxCurr]).check(); if (bias_->getWGrad()) { for (int i = 0; i < numDims_; i++) { diff --git a/paddle/gserver/layers/NCELayer.cpp b/paddle/gserver/layers/NCELayer.cpp index 5ab765247f63df..3542e739df8d03 100644 --- a/paddle/gserver/layers/NCELayer.cpp +++ b/paddle/gserver/layers/NCELayer.cpp @@ -193,7 +193,8 @@ class NCELayer : public Layer { forwardOneInput(l); } - activation_->forward(sampleOut_); + auto status = activation_->forward(sampleOut_); + status.check(); forwardCost(); } @@ -207,7 +208,8 @@ class NCELayer : public Layer { backwardCost(); - activation_->backward(sampleOut_); + auto status = activation_->backward(sampleOut_); + status.check(); if (biases_->getWGrad()) { backwardBias(callback); diff --git a/paddle/gserver/layers/RecurrentLayer.cpp b/paddle/gserver/layers/RecurrentLayer.cpp index 55e0fdfb9048c0..b843fa1265cf3c 100644 --- a/paddle/gserver/layers/RecurrentLayer.cpp +++ b/paddle/gserver/layers/RecurrentLayer.cpp @@ -217,21 +217,22 @@ void RecurrentLayer::forwardOneSequence(int start, int length) { if (prevOutput_) { frameOutput_[start].value->mul(*prevOutput_, *weight_->getW(), 1, 1); } - activation_->forward(frameOutput_[start]); + activation_->forward(frameOutput_[start]).check(); + for (int i = 1; i < length; ++i) { frameOutput_[start + i].value->mul( *frameOutput_[start + i - 1].value, *weight_->getW(), 1, 1); - activation_->forward(frameOutput_[start + i]); + activation_->forward(frameOutput_[start + i]).check(); } if (prevOutput_) { prevOutput_->assign(*frameOutput_[start + length - 1].value); } } else { - activation_->forward(frameOutput_[start + length - 1]); + activation_->forward(frameOutput_[start + length - 1]).check(); for (int i = length - 2; i >= 0; --i) { frameOutput_[start + i].value->mul( *frameOutput_[start + i + 1].value, *weight_->getW(), 1, 1); - activation_->forward(frameOutput_[start + i]); + activation_->forward(frameOutput_[start + i]).check(); } } } @@ -280,11 +281,11 @@ void RecurrentLayer::backwardOneSequence(int start, int length) { MatrixPtr weightT = weight_->getW()->getTranspose(); if (!reversed_) { for (int i = length - 1; i > 0; --i) { - activation_->backward(frameOutput_[start + i]); + activation_->backward(frameOutput_[start + i]).check(); frameOutput_[start + i - 1].grad->mul( *frameOutput_[start + i].grad, *weightT, 1, 1); } - activation_->backward(frameOutput_[start]); + activation_->backward(frameOutput_[start]).check(); if (weight_->getWGrad()) { weight_->getWGrad()->mul( *output_.value->subMatrix(start, length - 1)->getTranspose(), @@ -294,11 +295,11 @@ void RecurrentLayer::backwardOneSequence(int start, int length) { } } else { for (int i = 0; i < length - 1; ++i) { - activation_->backward(frameOutput_[start + i]); + activation_->backward(frameOutput_[start + i]).check(); frameOutput_[start + i + 1].grad->mul( *frameOutput_[start + i].grad, *weightT, 1, 1); } - activation_->backward(frameOutput_[start + length - 1]); + activation_->backward(frameOutput_[start + length - 1]).check(); if (weight_->getWGrad()) { weight_->getWGrad()->mul( *output_.value->subMatrix(start + 1, length - 1)->getTranspose(), @@ -333,7 +334,7 @@ void RecurrentLayer::forwardBatch(int batchSize, } Argument arg; arg.value = batch2; - activation_->forward(arg); + activation_->forward(arg).check(); } } batchValue_->copyBackSeq(*output_.value); @@ -363,7 +364,7 @@ void RecurrentLayer::backwardBatch(int batchSize, Argument arg; arg.value = batch1; arg.grad = batch2; - activation_->backward(arg); + activation_->backward(arg).check(); if (n != 0) { batch1 = batchGrad_->getBatchValue(n - 1, batch2->getHeight()); diff --git a/paddle/gserver/layers/SelectiveFullyConnectedLayer.cpp b/paddle/gserver/layers/SelectiveFullyConnectedLayer.cpp index 5eacff6b714399..d9a91de8a6f4da 100644 --- a/paddle/gserver/layers/SelectiveFullyConnectedLayer.cpp +++ b/paddle/gserver/layers/SelectiveFullyConnectedLayer.cpp @@ -192,7 +192,8 @@ void SelectiveFullyConnectedLayer::forward(PassType passType) { nnz, /*trans=*/false, /*useGpu=*/useGpu_); - activation_->forward(arg); + //! TODO(yuyang18): Why we cannot invoke forwardActivation here? + activation_->forward(arg).check(); } else /* train and test in train, not generating */ { // during training, this layer output value is *Matrix*, which is input of // eg. multi-class-cross-entropy diff --git a/paddle/gserver/tests/test_WarpCTCLayer.cpp b/paddle/gserver/tests/test_WarpCTCLayer.cpp index 23ae95852e8421..55427e2f12fd7b 100644 --- a/paddle/gserver/tests/test_WarpCTCLayer.cpp +++ b/paddle/gserver/tests/test_WarpCTCLayer.cpp @@ -148,11 +148,11 @@ LayerPtr createCTCLayer(string name, ActivationFunction* softmaxActivation = ActivationFunction::create("softmax"); - softmaxActivation->forward(dataLayer->getOutput()); + softmaxActivation->forward(dataLayer->getOutput()).check(); layer->forward(PASS_GC); layer->backward(); - softmaxActivation->backward(dataLayer->getOutput()); + softmaxActivation->backward(dataLayer->getOutput()).check(); return layer; } diff --git a/paddle/utils/Compiler.h b/paddle/utils/Compiler.h index e69de29bb2d1d6..22812e83987d8d 100644 --- a/paddle/utils/Compiler.h +++ b/paddle/utils/Compiler.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved. +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 + +#ifdef __GNUC__ +#define GCC_VERSION \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#else +#define GCC_VERSION +#endif + +#if GCC_VERSION >= 30400 +#define __must_check __attribute__((warn_unused_result)) +#else +#define __must_check +#endif diff --git a/paddle/utils/Status.h b/paddle/utils/Status.h index cb66e4b225e92c..26329f8d19bae6 100644 --- a/paddle/utils/Status.h +++ b/paddle/utils/Status.h @@ -14,9 +14,11 @@ limitations under the License. */ #pragma once +#include #include #include #include +#include "Compiler.h" namespace paddle { @@ -29,8 +31,55 @@ namespace paddle { * There are two styles to return status in Paddle. * * 1. Return Status + * When method return a status, the return must use `__must_check` attribute. + * Example as below. + * @code{cpp} + * Status __must_check foo(); * + * Status __must_check bar() { + * // do something. + * Status s = foo(); // invoke other method return status. + * if (!s.isOK()) return s; + * // do something else. + * return Status(); + * } + * @endcode{cpp} * + * 2. Return by parameter. + * It is another way to return a status, by using a pointer parameter. + * Example as below. + * + * @code{cpp} + * Status bar(); + * + * int foo(Status* status) { + * // Do something. + * Status s = bar(); + * if (!s.isOK()) { + * *status = s; + * return 0; + * } + * // Do something else. + * if (someInternalErrorHappend) { + * status->setByPrintf("Some dimension is too large, %d", dimension); + * return 0; + * } + * // End of method. + * return someValue; + * } + * + * Status foobar() { + * Status s; + * // do something. + * foo(&s); + * if (!s.isOK()) return s; + * } + * @endcode{cpp} + * + * + * Currently there is a helper method 'check' in status, because Paddle always + * use log(FATAL) or CHECK to make program exit before. When we clean all + * log(FATAL) and CHECK in Paddle, 'check' method will be removed. */ class Status final : public std::exception { public: @@ -92,6 +141,13 @@ class Status final : public std::exception { */ inline bool isOK() const noexcept { return errMsg_ == nullptr; } + /** + * @brief check this status by glog. + * @note It is a temp method used during cleaning Paddle code. It will be + * removed later. + */ + inline void check() const { CHECK(isOK()) << what(); } + private: std::shared_ptr errMsg_; }; From 8605544c0b0cbc5ad43d86a71402f3f4075b48e3 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 18 Jan 2017 12:49:00 +0800 Subject: [PATCH 060/370] Add some comments to compiler.h --- paddle/utils/Compiler.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/paddle/utils/Compiler.h b/paddle/utils/Compiler.h index 22812e83987d8d..cebca5a2a37661 100644 --- a/paddle/utils/Compiler.h +++ b/paddle/utils/Compiler.h @@ -10,7 +10,10 @@ See the License for the specific language governing permissions and limitations under the License. */ #pragma once - +/** + * This header defines some useful attribute by each compiler. It is the + * abstract layer of compilers. + */ #ifdef __GNUC__ #define GCC_VERSION \ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) @@ -18,6 +21,11 @@ limitations under the License. */ #define GCC_VERSION #endif +/** + * __must_check macro. It make the function's return value must be used, + * otherwise it will raise a compile warning. And also Paddle treat all compile + * warnings as errors. + */ #if GCC_VERSION >= 30400 #define __must_check __attribute__((warn_unused_result)) #else From ec790e1050b52b09a182eed95fc030c7879e5012 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 18 Jan 2017 13:24:02 +0800 Subject: [PATCH 061/370] Rename Status => Error. * Also make ErrorF as a global method. --- .../activations/ActivationFunction.cpp | 110 +++++++++--------- .../gserver/activations/ActivationFunction.h | 6 +- paddle/gserver/layers/Layer.cpp | 2 +- paddle/utils/{Status.h => Error.h} | 92 ++++++++------- paddle/utils/tests/CMakeLists.txt | 2 +- .../tests/{test_Status.cpp => test_Error.cpp} | 14 +-- 6 files changed, 114 insertions(+), 112 deletions(-) rename paddle/utils/{Status.h => Error.h} (70%) rename paddle/utils/tests/{test_Status.cpp => test_Error.cpp} (76%) diff --git a/paddle/gserver/activations/ActivationFunction.cpp b/paddle/gserver/activations/ActivationFunction.cpp index 666c2e01c8bdaf..f1f96fc67d04f4 100644 --- a/paddle/gserver/activations/ActivationFunction.cpp +++ b/paddle/gserver/activations/ActivationFunction.cpp @@ -69,13 +69,13 @@ static ClassRegistrar gActivationRegistrar; class IdentityActivation : public ActivationFunction { public: static const std::string name; - Status __must_check forward(Argument& act) { + Error __must_check forward(Argument& act) { (void)act; - return Status(); + return Error(); } - Status __must_check backward(Argument& act) { + Error __must_check backward(Argument& act) { (void)act; - return Status(); + return Error(); } const std::string& getName() const { return name; } }; @@ -92,13 +92,13 @@ static InitFunction __reg_activation__identity([] { * \f] */ BEGIN_DEFINE_ACTIVATION(sigmoid) -Status __must_check forward(Argument& act) { +Error __must_check forward(Argument& act) { act.value->sigmoid(*act.value); - return Status(); + return Error(); } -Status __must_check backward(Argument& act) { +Error __must_check backward(Argument& act) { act.grad->sigmoidDerivative(*act.value); - return Status(); + return Error(); } END_DEFINE_ACTIVATION(sigmoid) @@ -115,12 +115,12 @@ MatrixPtr sftMaxDot_; MatrixPtr one_; public: -Status __must_check forward(Argument& act) { +Error __must_check forward(Argument& act) { act.value->softmax(*act.value); - return Status(); + return Error(); } -Status __must_check backward(Argument& act) { +Error __must_check backward(Argument& act) { MatrixPtr outputV = act.value; MatrixPtr outputG = act.grad; @@ -152,7 +152,7 @@ Status __must_check backward(Argument& act) { act.grad->softmaxDerivative(*act.value, *sftMaxSum_); } - return Status(); + return Error(); } END_DEFINE_ACTIVATION(softmax) @@ -167,9 +167,9 @@ ACTIVATION_CLASS_NAME(softmax) softmax_; Argument argument_; public: -Status __must_check forward(Argument& act) { +Error __must_check forward(Argument& act) { if (act.value->getWidth() != 1UL) { - return Status( + return ErrorF( "Input width for each timestep of sequence softmax should be 1"); } @@ -188,12 +188,12 @@ Status __must_check forward(Argument& act) { auto starts = act.sequenceStartPositions->getVector(useGpu(act.deviceId)); act.value->sequenceSoftmax(*act.value, *starts); - return Status(); + return Error(); } -Status __must_check backward(Argument& act) { +Error __must_check backward(Argument& act) { if (act.value->getWidth() != 1UL) { - return Status( + return ErrorF( "Input width for each timestep of sequence softmax should be 1"); } @@ -207,10 +207,10 @@ Status __must_check backward(Argument& act) { argument_.value->setData(act.value->getData() + offset, 1UL, size); argument_.grad->setData(act.grad->getData() + offset, 1UL, size); - Status status = softmax_.backward(argument_); + Error status = softmax_.backward(argument_); if (!status.isOK()) return status; } - return Status(); + return Error(); } END_DEFINE_ACTIVATION(sequence_softmax) @@ -225,14 +225,14 @@ END_DEFINE_ACTIVATION(sequence_softmax) * 0 otherwise. */ BEGIN_DEFINE_ACTIVATION(relu) -Status __must_check forward(Argument& act) { +Error __must_check forward(Argument& act) { act.value->relu(*act.value); - return Status(); + return Error(); } -Status __must_check backward(Argument& act) { +Error __must_check backward(Argument& act) { act.grad->reluDerivative(*act.value); - return Status(); + return Error(); } END_DEFINE_ACTIVATION(relu) @@ -250,14 +250,14 @@ END_DEFINE_ACTIVATION(relu) * TODO(yuyang18): Remove magic number 24 or make it configuable. */ BEGIN_DEFINE_ACTIVATION(brelu) -Status __must_check forward(Argument& act) { +Error __must_check forward(Argument& act) { act.value->brelu(*act.value); - return Status(); + return Error(); } -Status __must_check backward(Argument& act) { +Error __must_check backward(Argument& act) { act.grad->breluDerivative(*act.value); - return Status(); + return Error(); } END_DEFINE_ACTIVATION(brelu) @@ -268,14 +268,14 @@ END_DEFINE_ACTIVATION(brelu) * \f] */ BEGIN_DEFINE_ACTIVATION(tanh) -Status __must_check forward(Argument& act) { +Error __must_check forward(Argument& act) { act.value->tanh(*act.value); - return Status(); + return Error(); } -Status __must_check backward(Argument& act) { +Error __must_check backward(Argument& act) { act.grad->tanhDerivative(*act.value); - return Status(); + return Error(); } END_DEFINE_ACTIVATION(tanh) @@ -291,14 +291,14 @@ real a, b; public: ACTIVATION_CLASS_NAME(stanh)() : a(1.7159), b(2. / 3.) {} -Status __must_check forward(Argument& act) { +Error __must_check forward(Argument& act) { act.value->scaledTanh(*act.value, a, b); - return Status(); + return Error(); } -Status __must_check backward(Argument& act) { +Error __must_check backward(Argument& act) { act.grad->scaledTanhDerivative(*act.value, a, b); - return Status(); + return Error(); } END_DEFINE_ACTIVATION(stanh) @@ -309,14 +309,14 @@ END_DEFINE_ACTIVATION(stanh) * \f] */ BEGIN_DEFINE_ACTIVATION(softrelu) -Status __must_check forward(Argument& act) { +Error __must_check forward(Argument& act) { act.value->softrelu(*act.value); - return Status(); + return Error(); } -Status __must_check backward(Argument& act) { +Error __must_check backward(Argument& act) { act.grad->softreluDerivative(*act.value); - return Status(); + return Error(); } END_DEFINE_ACTIVATION(softrelu) @@ -333,7 +333,7 @@ END_DEFINE_ACTIVATION(softrelu) * 0 if z=0 */ BEGIN_DEFINE_ACTIVATION(abs) -Status __must_check forward(Argument& act) { +Error __must_check forward(Argument& act) { SetDevice device(act.deviceId); Matrix::resizeOrCreate(act.in, act.value->getHeight(), @@ -343,12 +343,12 @@ Status __must_check forward(Argument& act) { act.in->copyFrom(*act.value); act.value->abs2(*act.value); - return Status(); + return Error(); } -Status __must_check backward(Argument& act) { +Error __must_check backward(Argument& act) { act.grad->absDerivative(*act.in); - return Status(); + return Error(); } END_DEFINE_ACTIVATION(abs) @@ -359,7 +359,7 @@ END_DEFINE_ACTIVATION(abs) * \f] */ BEGIN_DEFINE_ACTIVATION(square) -Status __must_check forward(Argument& act) { +Error __must_check forward(Argument& act) { SetDevice device(act.deviceId); Matrix::resizeOrCreate(act.in, act.value->getHeight(), @@ -369,12 +369,12 @@ Status __must_check forward(Argument& act) { act.in->copyFrom(*act.value); act.value->square2(*act.value); - return Status(); + return Error(); } -Status __must_check backward(Argument& act) { +Error __must_check backward(Argument& act) { act.grad->squareDerivative(*act.in); - return Status(); + return Error(); } END_DEFINE_ACTIVATION(square) @@ -385,14 +385,14 @@ END_DEFINE_ACTIVATION(square) * \f] */ BEGIN_DEFINE_ACTIVATION(exponential) -Status __must_check forward(Argument& act) { +Error __must_check forward(Argument& act) { act.value->exp2(*act.value); - return Status(); + return Error(); } -Status __must_check backward(Argument& act) { +Error __must_check backward(Argument& act) { act.grad->expDerivative(*act.value); - return Status(); + return Error(); } END_DEFINE_ACTIVATION(exponential) @@ -403,7 +403,7 @@ END_DEFINE_ACTIVATION(exponential) * \f] */ BEGIN_DEFINE_ACTIVATION(log) -Status __must_check forward(Argument& act) { +Error __must_check forward(Argument& act) { SetDevice device(act.deviceId); Matrix::resizeOrCreate(act.in, act.value->getHeight(), @@ -413,12 +413,12 @@ Status __must_check forward(Argument& act) { act.in->copyFrom(*act.value); act.value->log2(*act.value); - return Status(); + return Error(); } -Status __must_check backward(Argument& act) { +Error __must_check backward(Argument& act) { act.grad->dotDiv(*act.grad, *act.in); - return Status(); + return Error(); } END_DEFINE_ACTIVATION(log) diff --git a/paddle/gserver/activations/ActivationFunction.h b/paddle/gserver/activations/ActivationFunction.h index 737df2219dd36f..f208224e304a79 100644 --- a/paddle/gserver/activations/ActivationFunction.h +++ b/paddle/gserver/activations/ActivationFunction.h @@ -15,7 +15,7 @@ limitations under the License. */ #pragma once #include #include -#include "paddle/utils/Status.h" +#include "paddle/utils/Error.h" namespace paddle { @@ -49,7 +49,7 @@ class ActivationFunction { * * Usually, act is Layer::output_ */ - virtual Status __must_check forward(Argument& act) = 0; + virtual Error __must_check forward(Argument& act) = 0; /** * @brief Backward propagaion @@ -58,7 +58,7 @@ class ActivationFunction { * - Before calling backward(), act.grad = dE / dy, where E is the error/cost * - After backward() returns, act.grad = dE / dx = (dE/dy) * (dy/dx) */ - virtual Status __must_check backward(Argument& act) = 0; + virtual Error __must_check backward(Argument& act) = 0; virtual const std::string& getName() const = 0; }; diff --git a/paddle/gserver/layers/Layer.cpp b/paddle/gserver/layers/Layer.cpp index f96070fe6e269b..f76d41ad3e8a3b 100644 --- a/paddle/gserver/layers/Layer.cpp +++ b/paddle/gserver/layers/Layer.cpp @@ -15,8 +15,8 @@ limitations under the License. */ #include "paddle/utils/Util.h" #include "paddle/math/SparseMatrix.h" +#include "paddle/utils/Error.h" #include "paddle/utils/Logging.h" -#include "paddle/utils/Status.h" #include "AddtoLayer.h" #include "CRFLayer.h" diff --git a/paddle/utils/Status.h b/paddle/utils/Error.h similarity index 70% rename from paddle/utils/Status.h rename to paddle/utils/Error.h index 26329f8d19bae6..f1597f93d2579a 100644 --- a/paddle/utils/Status.h +++ b/paddle/utils/Error.h @@ -34,9 +34,9 @@ namespace paddle { * When method return a status, the return must use `__must_check` attribute. * Example as below. * @code{cpp} - * Status __must_check foo(); + * Error __must_check foo(); * - * Status __must_check bar() { + * Error __must_check bar() { * // do something. * Status s = foo(); // invoke other method return status. * if (!s.isOK()) return s; @@ -50,9 +50,9 @@ namespace paddle { * Example as below. * * @code{cpp} - * Status bar(); + * Error bar(); * - * int foo(Status* status) { + * int foo(Error* status) { * // Do something. * Status s = bar(); * if (!s.isOK()) { @@ -61,15 +61,15 @@ namespace paddle { * } * // Do something else. * if (someInternalErrorHappend) { - * status->setByPrintf("Some dimension is too large, %d", dimension); + * *status = ErrorF("Some dimension is too large, %d", dimension); * return 0; * } * // End of method. * return someValue; * } * - * Status foobar() { - * Status s; + * Error foobar() { + * Error s; * // do something. * foo(&s); * if (!s.isOK()) return s; @@ -81,48 +81,12 @@ namespace paddle { * use log(FATAL) or CHECK to make program exit before. When we clean all * log(FATAL) and CHECK in Paddle, 'check' method will be removed. */ -class Status final : public std::exception { +class Error final : public std::exception { public: /** * Default Status. OK */ - Status() noexcept {} - - /** - * @brief Create Status with error message - * @param msg - */ - explicit Status(const std::string& msg) : errMsg_(new std::string(msg)) {} - - /** - * @brief set a error message for status. - * @param msg - */ - inline void set(const std::string& msg) noexcept { - errMsg_.reset(new std::string(msg)); - } - - /** - * @brief set a error message for status. Use C style printf - * @param fmt - */ - template - inline void setByPrintf(const char* fmt, ARGS... args) noexcept { - constexpr size_t kBufferSize = 1024; // 1KB buffer - char buffer[kBufferSize]; - snprintf(buffer, kBufferSize, fmt, args...); - errMsg_.reset(new std::string(buffer)); - } - - /** - * create a error status by C style printf. - */ - template - inline static Status printf(const char* fmt, ARGS... args) noexcept { - Status s; - s.setByPrintf(fmt, args...); - return s; - } + Error() noexcept {} /** * @brief what will return the error message. If status is OK, return nullptr. @@ -148,8 +112,46 @@ class Status final : public std::exception { */ inline void check() const { CHECK(isOK()) << what(); } + /** + * friend method to create Error. + */ + template + friend Error __must_check ErrorF(const char* fmt, ARGS... args); + private: std::shared_ptr errMsg_; }; +/** + * ErrorF will create an Error by printf syntax. + * + * Specialize this method because clang will give a warning when use printf(fmt) + * without arguments. + */ +template <> +inline Error __must_check ErrorF(const char* msg) { + Error e; + e.errMsg_.reset(new std::string(msg)); + return e; +} + +/** + * ErrorF will create an Error by printf syntax. + * + * Examples: + * @code{cpp} + * auto err = ErrorF("SomeError"); + * auto err2 = ErrorF("SomeErrorWithParameter %f %d", real_val, int_val); + * @endcode{cpp} + */ +template +inline Error __must_check ErrorF(const char* fmt, ARGS... args) { + constexpr size_t kBufferSize = 1024; + char buffer[kBufferSize]; + snprintf(buffer, kBufferSize, fmt, args...); + Error e; + e.errMsg_.reset(new std::string(buffer)); + return e; +} + } // namespace paddle diff --git a/paddle/utils/tests/CMakeLists.txt b/paddle/utils/tests/CMakeLists.txt index a1cc32668d5100..aa923b35537775 100644 --- a/paddle/utils/tests/CMakeLists.txt +++ b/paddle/utils/tests/CMakeLists.txt @@ -4,7 +4,7 @@ add_simple_unittest(test_CustomStackTrace) add_simple_unittest(test_ThreadBarrier) add_simple_unittest(test_SpinLock) add_simple_unittest(test_SIMDFlags) -add_simple_unittest(test_Status) +add_simple_unittest(test_Error) add_executable( test_CustomStackTracePrint diff --git a/paddle/utils/tests/test_Status.cpp b/paddle/utils/tests/test_Error.cpp similarity index 76% rename from paddle/utils/tests/test_Status.cpp rename to paddle/utils/tests/test_Error.cpp index 04cef095792c73..96115f7053aec5 100644 --- a/paddle/utils/tests/test_Status.cpp +++ b/paddle/utils/tests/test_Error.cpp @@ -12,23 +12,23 @@ 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 "paddle/utils/Status.h" +#include "paddle/utils/Error.h" #include TEST(Status, testAll) { - paddle::Status status; + paddle::Error status; ASSERT_TRUE(status.isOK()); - status.set("I'm the error"); + status = paddle::ErrorF("I'm the error"); ASSERT_FALSE(status.isOK()); ASSERT_STREQ("I'm the error", status.what()); - paddle::Status status2("error2"); - ASSERT_FALSE(status2.isOK()); - ASSERT_STREQ("error2", status2.what()); + status = paddle::ErrorF("error2"); + ASSERT_FALSE(status.isOK()); + ASSERT_STREQ("error2", status.what()); int i = 3; - auto status3 = paddle::Status::printf("error%d", i); + auto status3 = paddle::ErrorF("error%d", i); ASSERT_FALSE(status3.isOK()); ASSERT_STREQ("error3", status3.what()); } From 699d18f11701aae1efe72c8bf6edc50723445050 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 18 Jan 2017 13:34:20 +0800 Subject: [PATCH 062/370] Change unittest variable name --- paddle/utils/tests/test_Error.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/paddle/utils/tests/test_Error.cpp b/paddle/utils/tests/test_Error.cpp index 96115f7053aec5..e8643de9d2dccf 100644 --- a/paddle/utils/tests/test_Error.cpp +++ b/paddle/utils/tests/test_Error.cpp @@ -16,19 +16,19 @@ limitations under the License. */ #include -TEST(Status, testAll) { - paddle::Error status; - ASSERT_TRUE(status.isOK()); - status = paddle::ErrorF("I'm the error"); - ASSERT_FALSE(status.isOK()); - ASSERT_STREQ("I'm the error", status.what()); +TEST(Error, testAll) { + paddle::Error error; + ASSERT_TRUE(error.isOK()); + error = paddle::ErrorF("I'm the error"); + ASSERT_FALSE(error.isOK()); + ASSERT_STREQ("I'm the error", error.what()); - status = paddle::ErrorF("error2"); - ASSERT_FALSE(status.isOK()); - ASSERT_STREQ("error2", status.what()); + error = paddle::ErrorF("error2"); + ASSERT_FALSE(error.isOK()); + ASSERT_STREQ("error2", error.what()); int i = 3; - auto status3 = paddle::ErrorF("error%d", i); - ASSERT_FALSE(status3.isOK()); - ASSERT_STREQ("error3", status3.what()); + auto error3 = paddle::ErrorF("error%d", i); + ASSERT_FALSE(error3.isOK()); + ASSERT_STREQ("error3", error3.what()); } From b6dfd2891bd658e1212f5e38bf764cf0f901574f Mon Sep 17 00:00:00 2001 From: backyes Date: Wed, 18 Jan 2017 18:14:41 +0800 Subject: [PATCH 063/370] fix bug: * update function can not be inherited since updateImpl exsits * remove update implementation in one inherited updater --- paddle/parameter/ParameterUpdaterBase.h | 2 +- paddle/trainer/ParameterUpdater.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/paddle/parameter/ParameterUpdaterBase.h b/paddle/parameter/ParameterUpdaterBase.h index b230e170c15f1b..6265c828a1a254 100644 --- a/paddle/parameter/ParameterUpdaterBase.h +++ b/paddle/parameter/ParameterUpdaterBase.h @@ -55,7 +55,7 @@ class ParameterUpdater { // between startBatch() and finishBatch(), update() will be called // by the trainer multiple times, each time for updating one Parameter // with its gradient in PARAMETER_GRADIENT - virtual void update(Parameter* para) { + void update(Parameter* para) { SetDevice setDevice(para->getDeviceId()); para->updateHook(); this->updateImpl(para); diff --git a/paddle/trainer/ParameterUpdater.h b/paddle/trainer/ParameterUpdater.h index c3207e63ce72b7..9e9e948b8856d2 100644 --- a/paddle/trainer/ParameterUpdater.h +++ b/paddle/trainer/ParameterUpdater.h @@ -184,7 +184,6 @@ class SgdCpuUpdater : public SgdLocalUpdater, public Deprecated { * @param para */ virtual void updateImpl(Parameter* para) {} - virtual void update(Parameter* para) {} }; /** From 5a15c70e167a83e6b06686e3152ca9b30ed7800e Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 18 Jan 2017 20:27:52 +0800 Subject: [PATCH 064/370] Make Error interface cleaner --- .../activations/ActivationFunction.cpp | 6 +- paddle/utils/Error.h | 92 +++++++------------ paddle/utils/tests/test_Error.cpp | 20 ++-- 3 files changed, 45 insertions(+), 73 deletions(-) diff --git a/paddle/gserver/activations/ActivationFunction.cpp b/paddle/gserver/activations/ActivationFunction.cpp index f1f96fc67d04f4..c541b72e104bf2 100644 --- a/paddle/gserver/activations/ActivationFunction.cpp +++ b/paddle/gserver/activations/ActivationFunction.cpp @@ -169,7 +169,7 @@ Argument argument_; public: Error __must_check forward(Argument& act) { if (act.value->getWidth() != 1UL) { - return ErrorF( + return Error( "Input width for each timestep of sequence softmax should be 1"); } @@ -193,7 +193,7 @@ Error __must_check forward(Argument& act) { Error __must_check backward(Argument& act) { if (act.value->getWidth() != 1UL) { - return ErrorF( + return Error( "Input width for each timestep of sequence softmax should be 1"); } @@ -208,7 +208,7 @@ Error __must_check backward(Argument& act) { argument_.grad->setData(act.grad->getData() + offset, 1UL, size); Error status = softmax_.backward(argument_); - if (!status.isOK()) return status; + if (!status) return status; } return Error(); } diff --git a/paddle/utils/Error.h b/paddle/utils/Error.h index f1597f93d2579a..a8de56b9808b81 100644 --- a/paddle/utils/Error.h +++ b/paddle/utils/Error.h @@ -23,14 +23,12 @@ limitations under the License. */ namespace paddle { /** - * Status is Paddle error code. It only contain a std::string as error message. - * Although Status inherits the std::exception, but do not throw it except you - * know what you are doing. + * Error is Paddle error code. It only contain a std::string as error message. * * - * There are two styles to return status in Paddle. + * There are two styles to return error in Paddle. * - * 1. Return Status + * 1. Return Error * When method return a status, the return must use `__must_check` attribute. * Example as below. * @code{cpp} @@ -39,29 +37,29 @@ namespace paddle { * Error __must_check bar() { * // do something. * Status s = foo(); // invoke other method return status. - * if (!s.isOK()) return s; + * if (!s) return s; * // do something else. * return Status(); * } * @endcode{cpp} * * 2. Return by parameter. - * It is another way to return a status, by using a pointer parameter. + * It is another way to return an error, by using a pointer parameter. * Example as below. * * @code{cpp} * Error bar(); * - * int foo(Error* status) { + * int foo(Error* error) { * // Do something. - * Status s = bar(); - * if (!s.isOK()) { - * *status = s; + * Error s = bar(); + * if (!s) { + * *error = s; * return 0; * } * // Do something else. * if (someInternalErrorHappend) { - * *status = ErrorF("Some dimension is too large, %d", dimension); + * *error = Error("Some dimension is too large, %d", dimension); * return 0; * } * // End of method. @@ -72,7 +70,7 @@ namespace paddle { * Error s; * // do something. * foo(&s); - * if (!s.isOK()) return s; + * if (!s) return s; * } * @endcode{cpp} * @@ -81,17 +79,31 @@ namespace paddle { * use log(FATAL) or CHECK to make program exit before. When we clean all * log(FATAL) and CHECK in Paddle, 'check' method will be removed. */ -class Error final : public std::exception { +class Error final { public: /** * Default Status. OK */ - Error() noexcept {} + inline Error() {} /** - * @brief what will return the error message. If status is OK, return nullptr. + * @brief Create an Error use printf syntax. */ - const char* what() const noexcept override { + inline explicit Error(const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + constexpr size_t kBufferSize = 1024; + this->errMsg_.reset(new std::string(kBufferSize, 0)); + auto sz = vsnprintf(&(*errMsg_)[0], kBufferSize, fmt, ap); + this->errMsg_->resize(sz); + this->errMsg_->shrink_to_fit(); + va_end(ap); + } + + /** + * @brief what will return the error message. If no error, return nullptr. + */ + inline const char* msg() const { if (errMsg_) { return errMsg_->data(); } else { @@ -100,58 +112,18 @@ class Error final : public std::exception { } /** - * @brief isOK - * @return true if OK. + * @brief operator bool, return True if there is no error. */ - inline bool isOK() const noexcept { return errMsg_ == nullptr; } - + inline operator bool() const { return !errMsg_; } /** * @brief check this status by glog. * @note It is a temp method used during cleaning Paddle code. It will be * removed later. */ - inline void check() const { CHECK(isOK()) << what(); } - - /** - * friend method to create Error. - */ - template - friend Error __must_check ErrorF(const char* fmt, ARGS... args); + inline void check() const { CHECK(*this) << msg(); } private: std::shared_ptr errMsg_; }; -/** - * ErrorF will create an Error by printf syntax. - * - * Specialize this method because clang will give a warning when use printf(fmt) - * without arguments. - */ -template <> -inline Error __must_check ErrorF(const char* msg) { - Error e; - e.errMsg_.reset(new std::string(msg)); - return e; -} - -/** - * ErrorF will create an Error by printf syntax. - * - * Examples: - * @code{cpp} - * auto err = ErrorF("SomeError"); - * auto err2 = ErrorF("SomeErrorWithParameter %f %d", real_val, int_val); - * @endcode{cpp} - */ -template -inline Error __must_check ErrorF(const char* fmt, ARGS... args) { - constexpr size_t kBufferSize = 1024; - char buffer[kBufferSize]; - snprintf(buffer, kBufferSize, fmt, args...); - Error e; - e.errMsg_.reset(new std::string(buffer)); - return e; -} - } // namespace paddle diff --git a/paddle/utils/tests/test_Error.cpp b/paddle/utils/tests/test_Error.cpp index e8643de9d2dccf..85156466e2cafd 100644 --- a/paddle/utils/tests/test_Error.cpp +++ b/paddle/utils/tests/test_Error.cpp @@ -18,17 +18,17 @@ limitations under the License. */ TEST(Error, testAll) { paddle::Error error; - ASSERT_TRUE(error.isOK()); - error = paddle::ErrorF("I'm the error"); - ASSERT_FALSE(error.isOK()); - ASSERT_STREQ("I'm the error", error.what()); + ASSERT_TRUE(error); + error = paddle::Error("I'm the error"); + ASSERT_FALSE(error); + ASSERT_STREQ("I'm the error", error.msg()); - error = paddle::ErrorF("error2"); - ASSERT_FALSE(error.isOK()); - ASSERT_STREQ("error2", error.what()); + error = paddle::Error("error2"); + ASSERT_FALSE(error); + ASSERT_STREQ("error2", error.msg()); int i = 3; - auto error3 = paddle::ErrorF("error%d", i); - ASSERT_FALSE(error3.isOK()); - ASSERT_STREQ("error3", error3.what()); + auto error3 = paddle::Error("error%d", i); + ASSERT_FALSE(error3); + ASSERT_STREQ("error3", error3.msg()); } From 312326899e779d96811b7dfab3cfe5817b1b6fdb Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Wed, 18 Jan 2017 21:18:33 +0800 Subject: [PATCH 065/370] add api to doc --- doc/api/trainer_config_helpers/layers.rst | 9 +++++++++ python/paddle/trainer_config_helpers/layers.py | 1 + 2 files changed, 10 insertions(+) diff --git a/doc/api/trainer_config_helpers/layers.rst b/doc/api/trainer_config_helpers/layers.rst index 4e429650e54517..8b0e553eacc932 100644 --- a/doc/api/trainer_config_helpers/layers.rst +++ b/doc/api/trainer_config_helpers/layers.rst @@ -382,6 +382,15 @@ sampling_id_layer :members: sampling_id_layer :noindex: +Slicing and Joining Layers +========================== + +pad_layer +----------- +.. automodule:: paddle.trainer_config_helpers.layers + :members: pad_layer + :noindex: + .. _api_trainer_config_helpers_layers_cost_layers: Cost Layers diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 4e4744b518d859..66817fc93be43b 100644 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -108,6 +108,7 @@ 'print_layer', 'priorbox_layer', 'spp_layer', + 'pad_layer', ] From 9200b955c3312ffa3cbb103ca65dbc214f9d3f16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=9B=8A?= Date: Wed, 18 Jan 2017 16:13:06 -0800 Subject: [PATCH 066/370] Update Dockerfile.dev --- paddle/scripts/docker/Dockerfile.dev | 45 ++++++++++++++++++---------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/paddle/scripts/docker/Dockerfile.dev b/paddle/scripts/docker/Dockerfile.dev index e60b9e30732583..2f245e2580f486 100644 --- a/paddle/scripts/docker/Dockerfile.dev +++ b/paddle/scripts/docker/Dockerfile.dev @@ -5,16 +5,37 @@ ARG DEBIAN_FRONTEND=noninteractive ARG UBUNTU_MIRROR RUN /bin/bash -c 'if [[ -n ${UBUNTU_MIRROR} ]]; then sed -i 's#http://archive.ubuntu.com#${UBUNTU_MIRROR}#g' /etc/apt/sources.list; fi' -RUN apt-get update \ - && apt-get install -y cmake libprotobuf-dev protobuf-compiler git \ +RUN apt-get update + +# Paddle development tools. +RUN apt-get install -y coreutils git cmake g++ m4 python-pip swig + +# Paddle data tools. +RUN apt-get install -y wget unzip tar xz-utils bzip2 gzip sed grep graphviz + +# Paddle documentation tools. +RUN apt-get install -y doxygen + +# Paddle code auto-reformat tools. +RUN apt-get install -y clang-3.8 llvm-3.8 libclang-3.8-dev clang-format-3.8 clang-tidy-3.8 + +# Paddle prerequisites. +RUN apt-get install -y \ + libprotobuf-dev protobuf-compiler \ libgoogle-glog-dev libgflags-dev libgtest-dev \ - libatlas-dev libatlas3-base g++ m4 python-pip \ - python-protobuf python-numpy python-dev swig openssh-server \ - wget unzip python-matplotlib tar xz-utils bzip2 gzip coreutils \ - sed grep graphviz libjpeg-dev zlib1g-dev doxygen \ - clang-3.8 llvm-3.8 libclang-3.8-dev clang-format-3.8 clang-tidy-3.8 \ - && apt-get clean -y + libatlas-dev libatlas3-base \ + python-protobuf python-numpy python-dev python-matplotlib \ + libjpeg-dev zlib1g-dev + +# Development environment: +RUN apt-get install -y openssh-server + +RUN apt-get clean -y + +# Build Google test RUN cd /usr/src/gtest && cmake . && make && cp *.a /usr/lib + +# Python dependencies. RUN pip install -U BeautifulSoup docopt PyYAML pillow \ sphinx sphinx_rtd_theme recommonmark jupyter @@ -38,10 +59,4 @@ RUN sed -ri 's/^PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config RUN sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config EXPOSE 22 -# Jupyter Notebook directory. -RUN mkdir /notes/ -WORKDIR "/notes" -EXPOSE 8888 - -RUN mkdir -p /opt/bin -COPY ./paddle/scripts/docker/entrypoint /opt/bin/ +CMD ["/usr/sbin/sshd", "-D"] From a6d4a31deae38f78e24ecaf198e9250927416041 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 19 Jan 2017 10:01:47 +0800 Subject: [PATCH 067/370] Follow comments --- paddle/utils/Error.h | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/paddle/utils/Error.h b/paddle/utils/Error.h index a8de56b9808b81..ff11541bbd781f 100644 --- a/paddle/utils/Error.h +++ b/paddle/utils/Error.h @@ -79,33 +79,32 @@ namespace paddle { * use log(FATAL) or CHECK to make program exit before. When we clean all * log(FATAL) and CHECK in Paddle, 'check' method will be removed. */ -class Error final { +class Error { public: /** - * Default Status. OK + * Construct an no-error value. */ - inline Error() {} + Error() {} /** * @brief Create an Error use printf syntax. */ - inline explicit Error(const char* fmt, ...) { + explicit Error(const char* fmt, ...) { va_list ap; va_start(ap, fmt); constexpr size_t kBufferSize = 1024; - this->errMsg_.reset(new std::string(kBufferSize, 0)); - auto sz = vsnprintf(&(*errMsg_)[0], kBufferSize, fmt, ap); - this->errMsg_->resize(sz); - this->errMsg_->shrink_to_fit(); + char buffer[kBufferSize]; + vsnprintf(buffer, kBufferSize, fmt, ap); + this->msg_.reset(new std::string(buffer)); va_end(ap); } /** * @brief what will return the error message. If no error, return nullptr. */ - inline const char* msg() const { - if (errMsg_) { - return errMsg_->data(); + const char* msg() const { + if (msg_) { + return msg_->c_str(); } else { return nullptr; } @@ -114,16 +113,16 @@ class Error final { /** * @brief operator bool, return True if there is no error. */ - inline operator bool() const { return !errMsg_; } + operator bool() const { return !msg_; } /** * @brief check this status by glog. * @note It is a temp method used during cleaning Paddle code. It will be * removed later. */ - inline void check() const { CHECK(*this) << msg(); } + void check() const { CHECK(*this) << msg(); } private: - std::shared_ptr errMsg_; + std::shared_ptr msg_; }; } // namespace paddle From c88dec209f367cb3ac1bd3fe6964e63f7274d975 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 19 Jan 2017 10:08:33 +0800 Subject: [PATCH 068/370] Fix typo --- paddle/utils/Error.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/paddle/utils/Error.h b/paddle/utils/Error.h index ff11541bbd781f..6fe7b6ea8884ec 100644 --- a/paddle/utils/Error.h +++ b/paddle/utils/Error.h @@ -82,7 +82,7 @@ namespace paddle { class Error { public: /** - * Construct an no-error value. + * Construct a no-error value. */ Error() {} @@ -100,7 +100,7 @@ class Error { } /** - * @brief what will return the error message. If no error, return nullptr. + * @brief msg will return the error message. If no error, return nullptr. */ const char* msg() const { if (msg_) { @@ -114,6 +114,7 @@ class Error { * @brief operator bool, return True if there is no error. */ operator bool() const { return !msg_; } + /** * @brief check this status by glog. * @note It is a temp method used during cleaning Paddle code. It will be From 42ea1376e25f7ed02ea55e11cb6114983c0d1e4c Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Thu, 19 Jan 2017 10:11:06 +0800 Subject: [PATCH 069/370] bug fix in GatedRecurrentLayer which only occurs in predicting or job=test mode. --- paddle/gserver/layers/GatedRecurrentLayer.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/paddle/gserver/layers/GatedRecurrentLayer.cpp b/paddle/gserver/layers/GatedRecurrentLayer.cpp index 930d9a056164e7..d3aeea921801da 100644 --- a/paddle/gserver/layers/GatedRecurrentLayer.cpp +++ b/paddle/gserver/layers/GatedRecurrentLayer.cpp @@ -314,13 +314,13 @@ void GatedRecurrentLayer::forwardBatch(int batchSize, batchValue_->resizeOrCreate(*output_.value); batchValue_->copy(*inputValue, *gate_.value, /* seq2batch */ true); - if (bias_ && bias_->getWGrad()) { + if (bias_) { gate_.value->addBias(*(bias_->getW()), 1); } { int numBatch = batchValue_->getNumBatch(); - int batchSize = 0; + int curBatchSize = 0; AsyncGpuBlock asyncGpuBlock; for (int n = 0; n < numBatch; n++) { MatrixPtr outputValueTmp = batchValue_->getBatchValue(n); @@ -330,16 +330,17 @@ void GatedRecurrentLayer::forwardBatch(int batchSize, gruValue.resetOutputValue = (batchValue_->getBatchValue(*resetOutput_.value, n))->getData(); - batchSize = outputValueTmp->getHeight(); + curBatchSize = outputValueTmp->getHeight(); gruValue.prevOutValue = - (n == 0 ? nullptr - : (batchValue_->getBatchValue(n - 1, batchSize))->getData()); + (n == 0 + ? nullptr + : (batchValue_->getBatchValue(n - 1, curBatchSize))->getData()); { if (useGpu_) { - GruCompute::forward<1>(gruValue, getSize(), batchSize); + GruCompute::forward<1>(gruValue, getSize(), curBatchSize); } else { - GruCompute::forward<0>(gruValue, getSize(), batchSize); + GruCompute::forward<0>(gruValue, getSize(), curBatchSize); } } } From 843fb2ea32d4f0b2d1f3667545487c8084229819 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 19 Jan 2017 15:12:42 +0800 Subject: [PATCH 070/370] Make code more readable --- paddle/utils/Error.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/paddle/utils/Error.h b/paddle/utils/Error.h index 6fe7b6ea8884ec..2b4fbef4e015e7 100644 --- a/paddle/utils/Error.h +++ b/paddle/utils/Error.h @@ -15,6 +15,7 @@ limitations under the License. */ #pragma once #include +#include #include #include #include @@ -113,7 +114,7 @@ class Error { /** * @brief operator bool, return True if there is no error. */ - operator bool() const { return !msg_; } + operator bool() const { return msg_ == nullptr; } /** * @brief check this status by glog. From 7ff8c8eec3f44497816ae4fe66516f3ca3ba7cb7 Mon Sep 17 00:00:00 2001 From: xuwei06 Date: Thu, 19 Jan 2017 01:33:28 -0800 Subject: [PATCH 071/370] Compile glog with WITH_GFLAGS=ON Also initialize glog after gflags in Util.cpp initMain() Change-Id: I09ff062b462aa76d9f7b5f97e883b92939e6dcb2 --- cmake/external/glog.cmake | 9 +++++---- paddle/utils/Util.cpp | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cmake/external/glog.cmake b/cmake/external/glog.cmake index 71e20c85276b01..e1eade601ea007 100644 --- a/cmake/external/glog.cmake +++ b/cmake/external/glog.cmake @@ -1,11 +1,11 @@ # 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. @@ -29,12 +29,13 @@ INCLUDE_DIRECTORIES(${GLOG_INCLUDE_DIR}) ExternalProject_Add( glog ${EXTERNAL_PROJECT_LOG_ARGS} + DEPENDS gflags GIT_REPOSITORY "https://github.com/google/glog.git" PREFIX ${GLOG_SOURCES_DIR} UPDATE_COMMAND "" CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${GLOG_INSTALL_DIR} CMAKE_ARGS -DCMAKE_POSITION_INDEPENDENT_CODE=ON - CMAKE_ARGS -DWITH_GFLAGS=OFF + CMAKE_ARGS -DWITH_GFLAGS=ON CMAKE_ARGS -DBUILD_TESTING=OFF ) diff --git a/paddle/utils/Util.cpp b/paddle/utils/Util.cpp index 411a64aa8d0737..220aac1ff11e0f 100644 --- a/paddle/utils/Util.cpp +++ b/paddle/utils/Util.cpp @@ -144,20 +144,20 @@ void runInitFunctions() { } void initMain(int argc, char** argv) { - initializeLogging(argc, argv); installLayerStackTracer(); std::string line; for (int i = 0; i < argc; ++i) { line += argv[i]; line += ' '; } - LOG(INFO) << "commandline: " << line; #ifndef GFLAGS_GFLAGS_H_ namespace gflags = google; #endif gflags::ParseCommandLineFlags(&argc, &argv, true); + initializeLogging(argc, argv); + LOG(INFO) << "commandline: " << line; CHECK_EQ(argc, 1) << "Unknown commandline argument: " << argv[1]; installProfilerSwitch(); From 63118767bf0ede148a7404604ea966d6f0bf35c7 Mon Sep 17 00:00:00 2001 From: liaogang Date: Thu, 19 Jan 2017 17:36:00 +0800 Subject: [PATCH 072/370] Add detect redhat and unknown in CMake --- cmake/system.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmake/system.cmake b/cmake/system.cmake index ab124a89dcdc1c..485cf0eea1c2e7 100644 --- a/cmake/system.cmake +++ b/cmake/system.cmake @@ -30,6 +30,10 @@ ELSE(WIN32) SET(HOST_SYSTEM "debian") ELSEIF(LINUX_ISSUE MATCHES "Ubuntu") SET(HOST_SYSTEM "ubuntu") + ELSEIF(LINUX_ISSUE MATCHES "Red Hat") + SET(HOST_SYSTEM "redhat") + ELSEIF(LINUX_ISSUE MATCHES "Fedora") + SET(HOST_SYSTEM "fedora") ENDIF() ENDIF(EXISTS "/etc/issue") @@ -40,6 +44,10 @@ ELSE(WIN32) ENDIF() ENDIF(EXISTS "/etc/redhat-release") + IF(NOT HOST_SYSTEM) + SET(HOST_SYSTEM "unknown") + ENDIF() + ENDIF(APPLE) ENDIF(WIN32) From febf9a0b070a7c5036f2b32f12167952f1597727 Mon Sep 17 00:00:00 2001 From: liaogang Date: Fri, 20 Jan 2017 00:11:08 +0800 Subject: [PATCH 073/370] Add comments and CMAKE_SYSTEM_NAME --- cmake/system.cmake | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cmake/system.cmake b/cmake/system.cmake index 485cf0eea1c2e7..3e472da7e0bd9c 100644 --- a/cmake/system.cmake +++ b/cmake/system.cmake @@ -12,6 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Detects the OS and sets appropriate variables. +# CMAKE_SYSTEM_NAME only give us a coarse-grained name, +# but the name like centos is necessary in some scenes +# to distinguish system for customization. +# +# for instance, protobuf libs path is /lib64 +# on CentOS, but /lib on other systems. + IF(WIN32) SET(HOST_SYSTEM "win32") ELSE(WIN32) @@ -45,7 +53,7 @@ ELSE(WIN32) ENDIF(EXISTS "/etc/redhat-release") IF(NOT HOST_SYSTEM) - SET(HOST_SYSTEM "unknown") + SET(HOST_SYSTEM ${CMAKE_SYSTEM_NAME}) ENDIF() ENDIF(APPLE) From 0cc3d829024a140a5d388437b021ded4d20d1661 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Fri, 20 Jan 2017 18:41:04 +0800 Subject: [PATCH 074/370] Add some comment of CrossMapNormalFunc --- paddle/function/CrossMapNormalOp.cpp | 54 ++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/paddle/function/CrossMapNormalOp.cpp b/paddle/function/CrossMapNormalOp.cpp index 8e7dc72524a768..568b8faef4566a 100644 --- a/paddle/function/CrossMapNormalOp.cpp +++ b/paddle/function/CrossMapNormalOp.cpp @@ -112,11 +112,31 @@ void CrossMapNormalGrad(real* inputsGrad, } /** - * \brief {o_0, o_1} = calc(i_0) + * \brief Normalization with across maps. * - * \param inputs[0] input value. - * \param outputs[0] output value. - * \param outputs[1] denoms. + * This Function comes from the paper + * "ImageNet Classification with Deep Convolutional Neural Networks". + * + * The original formula is: + * + * Input(x, y) + * Output(x, y) = ------------------------------------------------ + * alpha /min(F, f-[N/2] + N) + * (1 + ----- * | (Input(x, y))^2 ) ^ (beta) + * N /max(0, f-[N/2]) + * + * Argument in the Function: + * \param size_ represent N + * \param scale_ represent alpha / N + * \param pow_ represent beta + * \param inputs[0] represent Input + * \param outputs[0] represent Output + * \param outputs[1] represent The denominator in the formula(except beta) + * + * note: + * Save output[1] is to simplify the backward calculation. + * So, if only consider the forward calculation, we can optimize to + * remove the output[1]. */ template class CrossMapNormalFunc : public FunctionBase { @@ -161,13 +181,27 @@ class CrossMapNormalFunc : public FunctionBase { }; /** - * \brief {o_0} = calc(i_0, i_1, i_2, i_3) + * \brief Backward calculation for normalization with across maps. + * + * The implementation of this Function is derived from the + * CrossMapNormalFunc implementation. + * + * InputGrad = OutputGrad * denoms ^ (-beta) + * / + * + | (OutputGrad * OutputValue * (-2 * alpha * beta) / denoms) * InputValue + * / * - * \param inputs[0] input value. - * \param inputs[1] output value. - * \param inputs[2] output grad. - * \param inputs[3] denoms. - * \param outputs[0] input grad. + * Argument in the Function: + * \param size_ represent N + * \param scale_ represent alpha / N + * \param pow_ represent beta + * \param inputs[0] represent InputValue, inputs[0] of CrossMapNormalFunc + * \param inputs[1] represent OutputValue, outputs[0] of CrossMapNormalFunc + * \param inputs[2] represent OutputGrad + * \param inputs[3] represent denoms, outputs[1] of CrossMapNormalFunc + * This is the intermediate result that is + * preserved in the forward calculation. + * \param outputs[0] represent InputGrad */ template class CrossMapNormalGradFunc : public FunctionBase { From 95dec805aab0ddaef551b367f0c2f4e42a393819 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Fri, 20 Jan 2017 18:48:42 +0800 Subject: [PATCH 075/370] Make external/glog use local gflags. --- cmake/external/glog.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/external/glog.cmake b/cmake/external/glog.cmake index e1eade601ea007..ab105611c812a4 100644 --- a/cmake/external/glog.cmake +++ b/cmake/external/glog.cmake @@ -36,6 +36,7 @@ ExternalProject_Add( CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${GLOG_INSTALL_DIR} CMAKE_ARGS -DCMAKE_POSITION_INDEPENDENT_CODE=ON CMAKE_ARGS -DWITH_GFLAGS=ON + CMAKE_ARGS -Dgflags_DIR=${GFLAGS_INSTALL_DIR}/lib/cmake/gflags CMAKE_ARGS -DBUILD_TESTING=OFF ) From a8583f0ccb230fb0564103a28a034a87156bac78 Mon Sep 17 00:00:00 2001 From: reyoung Date: Fri, 20 Jan 2017 11:39:52 +0000 Subject: [PATCH 076/370] Correct Handle Python Proto2 --- cmake/external/python.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/external/python.cmake b/cmake/external/python.cmake index 209e679f2cb217..6372a9a768e580 100644 --- a/cmake/external/python.cmake +++ b/cmake/external/python.cmake @@ -26,10 +26,10 @@ IF(PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) find_python_module(wheel REQUIRED) find_python_module(google.protobuf REQUIRED) FIND_PACKAGE(NumPy REQUIRED) - IF(${PY_GOOGLE.PROTOBUF_VERSION} VERSION_LESS "3.0.0") + IF(${PY_GOOGLE.PROTOBUF_VERSION} AND ${PY_GOOGLE.PROTOBUF_VERSION} VERSION_LESS "3.0.0") MESSAGE(FATAL_ERROR "Found Python Protobuf ${PY_GOOGLE.PROTOBUF_VERSION} < 3.0.0, " - "please use pip to upgrade protobuf.") - ENDIF(${PY_GOOGLE.PROTOBUF_VERSION} VERSION_LESS "3.0.0") + "please use pip to upgrade protobuf. pip install -U protobuf") + ENDIF() ELSE(PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) MESSAGE(FATAL_ERROR "Please install python 2.7 before building PaddlePaddle.") ##################################### PYTHON ######################################## From 51fa6baebec5c29f4ff0f1c2e72f6feab02bbe5e Mon Sep 17 00:00:00 2001 From: FoREacH Date: Sat, 21 Jan 2017 00:24:38 +0200 Subject: [PATCH 077/370] Fix issue #1186 --- cmake/external/warpctc.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/external/warpctc.cmake b/cmake/external/warpctc.cmake index f5e4b3e1eb39ac..f23a3969e95259 100644 --- a/cmake/external/warpctc.cmake +++ b/cmake/external/warpctc.cmake @@ -54,6 +54,7 @@ ExternalProject_Add( CMAKE_ARGS -DWITH_GPU=${WITH_GPU} CMAKE_ARGS -DWITH_OMP=${USE_OMP} CMAKE_ARGS -DWITH_TORCH=OFF + CMAKE_ARGS -DCMAKE_DISABLE_FIND_PACKAGE_TORCH=TRUE CMAKE_ARGS -DBUILD_SHARED=ON ) From 7709b697ba85a99c9f784e5f2f8267f7a52c61fc Mon Sep 17 00:00:00 2001 From: F0REacH Date: Sat, 21 Jan 2017 00:52:39 +0200 Subject: [PATCH 078/370] Update warpctc.cmake Fix case-sensitiveness --- cmake/external/warpctc.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/external/warpctc.cmake b/cmake/external/warpctc.cmake index f23a3969e95259..172c318b35d611 100644 --- a/cmake/external/warpctc.cmake +++ b/cmake/external/warpctc.cmake @@ -54,7 +54,7 @@ ExternalProject_Add( CMAKE_ARGS -DWITH_GPU=${WITH_GPU} CMAKE_ARGS -DWITH_OMP=${USE_OMP} CMAKE_ARGS -DWITH_TORCH=OFF - CMAKE_ARGS -DCMAKE_DISABLE_FIND_PACKAGE_TORCH=TRUE + CMAKE_ARGS -DCMAKE_DISABLE_FIND_PACKAGE_Torch=TRUE CMAKE_ARGS -DBUILD_SHARED=ON ) From ed5624023549374259c0fc9c4849d5ae46347b1b Mon Sep 17 00:00:00 2001 From: FoREacH Date: Sat, 21 Jan 2017 05:46:07 +0200 Subject: [PATCH 079/370] Set protobuf CMAKE_INSTALL_LIBDIR to fixed value lib --- cmake/external/protobuf.cmake | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/cmake/external/protobuf.cmake b/cmake/external/protobuf.cmake index 613614c0e3d42f..84f459033f06f8 100644 --- a/cmake/external/protobuf.cmake +++ b/cmake/external/protobuf.cmake @@ -29,17 +29,12 @@ IF(WIN32) "${PROTOBUF_INSTALL_DIR}/lib/libprotoc.lib" CACHE FILEPATH "protoc library." FORCE) SET(PROTOBUF_PROTOC_EXECUTABLE "${PROTOBUF_INSTALL_DIR}/bin/protoc.exe" CACHE FILEPATH "protobuf executable." FORCE) ELSE(WIN32) - IF(${HOST_SYSTEM} STREQUAL "centos") - SET(LIB "lib64") - ELSE() - SET(LIB "lib") - ENDIF() SET(PROTOBUF_LITE_LIBRARY - "${PROTOBUF_INSTALL_DIR}/${LIB}/libprotobuf-lite.a" CACHE FILEPATH "protobuf lite library." FORCE) + "${PROTOBUF_INSTALL_DIR}/lib/libprotobuf-lite.a" CACHE FILEPATH "protobuf lite library." FORCE) SET(PROTOBUF_LIBRARY - "${PROTOBUF_INSTALL_DIR}/${LIB}/libprotobuf.a" CACHE FILEPATH "protobuf library." FORCE) + "${PROTOBUF_INSTALL_DIR}/lib/libprotobuf.a" CACHE FILEPATH "protobuf library." FORCE) SET(PROTOBUF_PROTOC_LIBRARY - "${PROTOBUF_INSTALL_DIR}/${LIB}/libprotoc.a" CACHE FILEPATH "protoc library." FORCE) + "${PROTOBUF_INSTALL_DIR}/lib/libprotoc.a" CACHE FILEPATH "protoc library." FORCE) SET(PROTOBUF_PROTOC_EXECUTABLE "${PROTOBUF_INSTALL_DIR}/bin/protoc" CACHE FILEPATH "protobuf executable." FORCE) ENDIF(WIN32) @@ -58,6 +53,7 @@ ExternalProject_Add( -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${PROTOBUF_INSTALL_DIR} + -DCMAKE_INSTALL_LIBDIR=lib ) LIST(APPEND external_project_dependencies protobuf) From fae5d82c367482e7236489bff41c875a230598fd Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sun, 22 Jan 2017 10:29:55 +0800 Subject: [PATCH 080/370] Fix destroy error in test_ProtoServer. --- paddle/pserver/test/test_ProtoServer.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/paddle/pserver/test/test_ProtoServer.cpp b/paddle/pserver/test/test_ProtoServer.cpp index 9f86ee80f4e5cc..e70e1670d31993 100644 --- a/paddle/pserver/test/test_ProtoServer.cpp +++ b/paddle/pserver/test/test_ProtoServer.cpp @@ -12,14 +12,13 @@ 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 "paddle/utils/Util.h" - #include - +#include #include "ParameterService.pb.h" #include "paddle/math/Vector.h" #include "paddle/pserver/ProtoServer.h" #include "paddle/utils/Stat.h" +#include "paddle/utils/Util.h" DEFINE_string(server_addr, "127.0.0.1", "Server address"); DEFINE_int64(dim, 50000000, "Data size"); @@ -163,17 +162,15 @@ int main(int argc, char** argv) { paddle::initMain(argc, argv); testing::InitGoogleTest(&argc, argv); - MyServer* server; + std::unique_ptr server; if (FLAGS_rdma_tcp == "rdma") { - server = new MyServer(FLAGS_port, 0); + server.reset(new MyServer(FLAGS_port, 0)); } else { - server = new MyServer(FLAGS_port); + server.reset(new MyServer(FLAGS_port)); } server->start(); usleep(10000); - int ret = RUN_ALL_TESTS(); - - exit(ret); + return RUN_ALL_TESTS(); } From 7acd669ee291d42492dd9f6d5a9716ab2f5ac314 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Sun, 22 Jan 2017 16:25:19 +0800 Subject: [PATCH 081/370] Supplement the data format specifications for the parameters. --- paddle/function/CrossMapNormalOp.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/paddle/function/CrossMapNormalOp.cpp b/paddle/function/CrossMapNormalOp.cpp index 568b8faef4566a..2d2ff0ca868204 100644 --- a/paddle/function/CrossMapNormalOp.cpp +++ b/paddle/function/CrossMapNormalOp.cpp @@ -126,6 +126,11 @@ void CrossMapNormalGrad(real* inputsGrad, * N /max(0, f-[N/2]) * * Argument in the Function: + * Input is NCHW format, while input.shape.ndims() is equal 4. + * And the meaning of each dimension(0-3) is respectively batch size, + * feature maps, rows and columns. + * The above formula is for each image. + * * \param size_ represent N * \param scale_ represent alpha / N * \param pow_ represent beta @@ -135,7 +140,7 @@ void CrossMapNormalGrad(real* inputsGrad, * * note: * Save output[1] is to simplify the backward calculation. - * So, if only consider the forward calculation, we can optimize to + * TODO, if only consider the forward calculation, we can optimize to * remove the output[1]. */ template @@ -192,6 +197,9 @@ class CrossMapNormalFunc : public FunctionBase { * / * * Argument in the Function: + * The data of inputs/outputs format is the same as the forward interface + * and is NCHW. + * * \param size_ represent N * \param scale_ represent alpha / N * \param pow_ represent beta From 44e3c724f90f6944478de11cb0e0acbd71c6ce74 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Sun, 22 Jan 2017 16:38:35 +0800 Subject: [PATCH 082/370] Refine and comments --- paddle/function/PadOp.cpp | 161 +++++++++++------- paddle/function/PadOp.h | 87 ++++------ paddle/function/PadOpGpu.cu | 36 ++-- paddle/function/PadOpTest.cpp | 24 +-- paddle/gserver/layers/PadLayer.cpp | 24 +-- .../paddle/trainer_config_helpers/layers.py | 25 +++ 6 files changed, 197 insertions(+), 160 deletions(-) diff --git a/paddle/function/PadOp.cpp b/paddle/function/PadOp.cpp index 75e64a8ee41513..df44fd0fa628d8 100644 --- a/paddle/function/PadOp.cpp +++ b/paddle/function/PadOp.cpp @@ -24,20 +24,19 @@ void Pad(real* outputs, const int inC, const int inH, const int inW, - const int padc0, - const int padc1, - const int padh0, - const int padh1, - const int padw0, - const int padw1) { - int outC = inC + padc0 + padc1; - int outH = inH + padh0 + padh1; - int outW = inW + padw0 + padw1; + const PadConf& pad) { + int cstart = pad.channelStart, cend = pad.channelEnd; + int hstart = pad.heightStart, hend = pad.heightEnd; + int wstart = pad.widthStart, wend = pad.widthEnd; + int outC = inC + cstart + cend; + int outH = inH + hstart + hend; + int outW = inW + wstart + wend; for (int i = 0; i < num; i++) { for (int c = 0; c < inC; c++) { for (int h = 0; h < inH; h++) { int inoff = ((i * inC + c) * inH + h) * inW; - int outoff = ((i * outC + c + padc0) * outH + h + padh0) * outW + padw0; + int outoff = + ((i * outC + c + cstart) * outH + h + hstart) * outW + wstart; memcpy(outputs + outoff, inputs + inoff, inW * sizeof(real)); } } @@ -51,20 +50,19 @@ void PadGrad(real* inGrad, const int inC, const int inH, const int inW, - const int padc0, - const int padc1, - const int padh0, - const int padh1, - const int padw0, - const int padw1) { - int outC = inC + padc0 + padc1; - int outH = inH + padh0 + padh1; - int outW = inW + padw0 + padw1; + const PadConf& pad) { + int cstart = pad.channelStart, cend = pad.channelEnd; + int hstart = pad.heightStart, hend = pad.heightEnd; + int wstart = pad.widthStart, wend = pad.widthEnd; + int outC = inC + cstart + cend; + int outH = inH + hstart + hend; + int outW = inW + wstart + wend; for (int i = 0; i < num; i++) { for (int c = 0; c < inC; c++) { for (int h = 0; h < inH; h++) { int inoff = ((i * inC + c) * inH + h) * inW; - int outoff = ((i * outC + c + padc0) * outH + h + padh0) * outW + padw0; + int outoff = + ((i * outC + c + cstart) * outH + h + hstart) * outW + wstart; CpuVector inG = CpuVector(inW, inGrad + inoff); CpuVector outG = CpuVector(inW, const_cast(outGrad + outoff)); inG += outG; @@ -73,22 +71,71 @@ void PadGrad(real* inGrad, } } +/** + * \brief Padding zeros to input according to the specify dimension. + * The struct pad_ contains the padding size in each dimension. + * The input and output is a 4D tensor. In PadFunc, we only + * pad zeros to the 2nd to 4th dimension. + * + * Argument in this Function: + * \param pad_ A struct object contains the padding size in each dimension. + * It has six integers. The channelStart and channelEnd indicates + * how many zeros to add before and after the input in channel + * dimension. And the heightStart and heightEnd indicates padding + * in height dimension. The widthStart and widthEnd indicates the + * padding in width dimension. + * \param inputs A 4D tensor, only one input. + * \param outputs A 4D tensor, the output value after padding. + * + * For example, + * Input(2,2,2,3) = [ + * [ [[1,2,3], [3,4,5]], + * [[2,3,5], [1,6,7]] ], + * [ [[4,3,1], [1,8,7]], + * [[3,8,9], [2,3,5]] ] + * ] # the shape is (1,2,2,3) + * + * pad_: if channelStart = channelEnd = 1, others are 0. + * Output(2,4,2,3) = [ + * [ [[0,0,0], [0,0,0]], + * [[1,2,3], [3,4,5]], + * [[2,3,5], [1,6,7]], + * [[0,0,0], [0,0,0]] ], + * [ [[0,0,0], [0,0,0]], + * [[4,3,1], [1,8,7]], + * [[3,8,9], [2,3,5]], + * [[0,0,0], [0,0,0]] ] + * ] # the shape is (2,4,2,3) + * + * pad_: if widthStart = 1, widthEnd = 2, others are 0. + * Output(2,2,2,6) = [ + * [ [[0,1,2,3,0,0], [0,3,4,5,0,0]], + * [[0,2,3,5,0,0], [0,1,6,7,0,0]] ], + * [ [[0,4,3,1,0,0], [0,1,8,7,0,0]], + * [[0,3,8,9,0,0], [0,2,3,5,0,0]] ], + * ] # the shape is (2,2,2,6) + * + * pad_: if heightStart = 1, heightEnd = 1, others are 0. + * Output(2,2,4,3) = [ + * [ [[0,0,0], [1,2,3], [3,4,5], [0,0,0]], + * [[0,0,0], [2,3,5], [1,6,7], [0,0,0]] ], + * [ [[0,0,0], [4,3,1], [1,8,7], [0,0,0]], + * [[0,0,0], [3,8,9], [2,3,5], [0,0,0]] ], + * ] # the shape is (2,2,4,3) + */ + template class PadFunc : public FunctionBase { public: void init(const FuncConfig& config) override { - padc0_ = config.get("padc0"); - padc1_ = config.get("padc1"); - padh0_ = config.get("padh0"); - padh1_ = config.get("padh1"); - padw0_ = config.get("padw0"); - padw1_ = config.get("padw1"); + pad_.channelStart = config.get("cstart"); + pad_.channelEnd = config.get("cend"); + pad_.heightStart = config.get("hstart"); + pad_.heightEnd = config.get("hend"); + pad_.widthStart = config.get("wstart"); + pad_.widthEnd = config.get("wend"); } - /** - * \param inputs[0] input value. - * \param outputs[0] output value. - */ void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { CHECK_EQ(1UL, inputs.size()); CHECK_EQ(1UL, outputs.size()); @@ -108,39 +155,35 @@ class PadFunc : public FunctionBase { inC, inH, inW, - padc0_, - padc1_, - padh0_, - padh1_, - padw0_, - padw1_); + pad_); } private: - int padc0_; - int padc1_; - int padh0_; - int padh1_; - int padw0_; - int padw1_; + PadConf pad_; }; +/** + * \brief The backward propagation of padding Function. Remove the elements + * in the padding positions of forward. + * + * Argument in this Function: + * \param pad_ The same meaning as it in PadFunc. + * \param inputs The gradient with respect to the output value of PadFunc. + * \param outputs The gradient with respect to the input value of PadFunc. + */ + template class PadGradFunc : public FunctionBase { public: void init(const FuncConfig& config) override { - padc0_ = config.get("padc0"); - padc1_ = config.get("padc1"); - padh0_ = config.get("padh0"); - padh1_ = config.get("padh1"); - padw0_ = config.get("padw0"); - padw1_ = config.get("padw1"); + pad_.channelStart = config.get("cstart"); + pad_.channelEnd = config.get("cend"); + pad_.heightStart = config.get("hstart"); + pad_.heightEnd = config.get("hend"); + pad_.widthStart = config.get("wstart"); + pad_.widthEnd = config.get("wend"); } - /** - * \param inputs[0] output grad. - * \param inouts[0] input grad. - */ void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { CHECK_EQ(1UL, inputs.size()); CHECK_EQ(1UL, outputs.size()); @@ -163,21 +206,11 @@ class PadGradFunc : public FunctionBase { inC, inH, inW, - padc0_, - padc1_, - padh0_, - padh1_, - padw0_, - padw1_); + pad_); } private: - int padc0_; - int padc1_; - int padh0_; - int padh1_; - int padw0_; - int padw1_; + PadConf pad_; }; REGISTER_TYPED_FUNC(Pad, CPU, PadFunc); diff --git a/paddle/function/PadOp.h b/paddle/function/PadOp.h index 4a5e8fe33857aa..7b5c730a6a0fa5 100644 --- a/paddle/function/PadOp.h +++ b/paddle/function/PadOp.h @@ -18,29 +18,34 @@ limitations under the License. */ namespace paddle { +struct PadConf { + /// how many values to add before the data along channel dimension. + int channelStart; + /// how many values to add after the data along channel dimension. + int channelEnd; + /// how many values to add before the data along height dimension. + int heightStart; + /// how many values to add after the data along height dimension. + int heightEnd; + /// how many values to add before the data along width dimension. + int widthStart; + /// how many values to add after the data along width dimension. + int widthEnd; +}; + /** * \brief This funtion pads zeros to inputs according to the specify dimension. - * The data structure of image data is NCHW. - * - * \param[out] outputs save results. - * \param[in] inputs input data. - * \param[in] num batch size of input data. - * \param[in] inC channel number of input data. - * \param[in] inH height of input data. - * \param[in] inH with of input data. - * \param[in] padc0 how many values to add before the data in dimension of - * channel. - * \param[in] padc1 how many values to add after the data in dimension of - * channel. - * \param[in] padh0 how many values to add before the data in dimension of - * height. - * \param[in] padh1 how many values to add after the data in dimension of - * height. - * \param[in] padw0 how many values to add before the data in dimension of - * width. - * \param[in] padw1 how many values to add after the data in dimension of - * width. + * The input and output is a 4D tensor. Padding zeros from the 2nd to + * the 4th dimenstion according argument of pad. * + * \param[out] outputs save results. + * \param[in] inputs input data. + * \param[in] num batch size of input data. + * \param[in] inC channel number of input data. + * \param[in] inH height of input data. + * \param[in] inH with of input data. + * \param[in] pad the padding config, contains the size along the + * specify dimension. */ template void Pad(real* outputs, @@ -49,36 +54,19 @@ void Pad(real* outputs, const int inC, const int inH, const int inW, - const int padc0, - const int padc1, - const int padh0, - const int padh1, - const int padw0, - const int padw1); + const PadConf& pad); /** * \brief Padding operation backward. - * The data structure of image data is NCHW. - * - * \param[out] inGrad gradients of previous layer. - * \param[in] outGrad output gradients. - * \param[in] num batch size of input data. - * \param[in] inC channel number of input data. - * \param[in] inH height of input data. - * \param[in] inH with of input data. - * \param[in] padc0 how many values to add before the data in dimension of - * channel. - * \param[in] padc1 how many values to add after the data in dimension of - * channel. - * \param[in] padh0 how many values to add before the data in dimension of - * height. - * \param[in] padh1 how many values to add after the data in dimension of - * height. - * \param[in] padw0 how many values to add before the data in dimension of - * width. - * \param[in] padw1 how many values to add after the data in dimension of - * width. * + * \param[out] inGrad gradients of previous layer. + * \param[in] outGrad output gradients. + * \param[in] num batch size of input data. + * \param[in] inC channel number of input data. + * \param[in] inH height of input data. + * \param[in] inH with of input data. + * \param[in] pad the padding config, contains the size along the + * specify dimension. */ template void PadGrad(real* inGrad, @@ -87,10 +75,5 @@ void PadGrad(real* inGrad, const int inC, const int inH, const int inW, - const int padc0, - const int padc1, - const int padh0, - const int padh1, - const int padw0, - const int padw1); + const PadConf& pad); } // namespace paddle diff --git a/paddle/function/PadOpGpu.cu b/paddle/function/PadOpGpu.cu index 578d6e86d7534e..9104b1aca507c5 100644 --- a/paddle/function/PadOpGpu.cu +++ b/paddle/function/PadOpGpu.cu @@ -40,20 +40,18 @@ void Pad(real* outputs, const int inC, const int inH, const int inW, - const int padc0, - const int padc1, - const int padh0, - const int padh1, - const int padw0, - const int padw1) { + const PadConf& pad) { size_t nth = num * inC * inH * inW; int blockSize = 1024; int gridSize = (nth + 1024 - 1) / 1024; - int outC = inC + padc0 + padc1; - int outH = inH + padh0 + padh1; - int outW = inW + padw0 + padw1; + int cstart = pad.channelStart, cend = pad.channelEnd; + int hstart = pad.heightStart, hend = pad.heightEnd; + int wstart = pad.widthStart, wend = pad.widthEnd; + int outC = inC + cstart + cend; + int outH = inH + hstart + hend; + int outW = inW + wstart + wend; KePad<<>> - (outputs, inputs, inC, inH, inW, padc0, padh0, padw0, + (outputs, inputs, inC, inH, inW, cstart, hstart, wstart, outC, outH, outW, nth); CHECK_SYNC("Pad"); } @@ -81,20 +79,18 @@ void PadGrad(real* inGrad, const int inC, const int inH, const int inW, - const int padc0, - const int padc1, - const int padh0, - const int padh1, - const int padw0, - const int padw1) { + const PadConf& pad) { int nth = num * inC * inH * inW; int blockSize = 1024; int gridSize = (nth + 1024 - 1) / 1024; - int outC = inC + padc0 + padc1; - int outH = inH + padh0 + padh1; - int outW = inW + padw0 + padw1; + int cstart = pad.channelStart, cend = pad.channelEnd; + int hstart = pad.heightStart, hend = pad.heightEnd; + int wstart = pad.widthStart, wend = pad.widthEnd; + int outC = inC + cstart + cend; + int outH = inH + hstart + hend; + int outW = inW + wstart + wend; KePadDiff <<>> - (inGrad, outGrad, inC, inH, inW, padc0, padh0, padw0, + (inGrad, outGrad, inC, inH, inW, cstart, hstart, wstart, outC, outH, outW, nth); CHECK_SYNC("PadGrad"); } diff --git a/paddle/function/PadOpTest.cpp b/paddle/function/PadOpTest.cpp index dce2bac3e9a6ec..cd22d911356791 100644 --- a/paddle/function/PadOpTest.cpp +++ b/paddle/function/PadOpTest.cpp @@ -27,12 +27,12 @@ TEST(Pad, real) { FunctionCompare compare("Pad", FuncConfig() - .set("padc0", 2) - .set("padc1", 3) - .set("padh0", 1) - .set("padh1", 2) - .set("padw0", 3) - .set("padw1", 2)); + .set("cstart", 2) + .set("cend", 3) + .set("hstart", 1) + .set("hend", 2) + .set("wstart", 3) + .set("wend", 2)); TensorShape inDims{numSamples, channels, imgSizeH, imgSizeW}; TensorShape outDims{ numSamples, channels + 5, imgSizeH + 3, imgSizeW + 5}; @@ -54,12 +54,12 @@ TEST(PadGrad, real) { << " imgSizeH=" << imgSizeH << " imgSizeW=" << imgSizeW; FunctionCompare compare("PadGrad", FuncConfig() - .set("padc0", 2) - .set("padc1", 3) - .set("padh0", 1) - .set("padh1", 2) - .set("padw0", 3) - .set("padw1", 2)); + .set("cstart", 2) + .set("cend", 3) + .set("hstart", 1) + .set("hend", 2) + .set("wstart", 3) + .set("wend", 2)); TensorShape inDims{numSamples, channels, imgSizeH, imgSizeW}; TensorShape outDims{ numSamples, channels + 5, imgSizeH + 3, imgSizeW + 5}; diff --git a/paddle/gserver/layers/PadLayer.cpp b/paddle/gserver/layers/PadLayer.cpp index a2a469ff92fb2a..bb618c09f97777 100644 --- a/paddle/gserver/layers/PadLayer.cpp +++ b/paddle/gserver/layers/PadLayer.cpp @@ -49,21 +49,21 @@ bool PadLayer::init(const LayerMap& layerMap, createFunction(forward_, "Pad", FuncConfig() - .set("padc0", padc_[0]) - .set("padc1", padc_[1]) - .set("padh0", padh_[0]) - .set("padh1", padh_[1]) - .set("padw0", padw_[0]) - .set("padw1", padw_[1])); + .set("cstart", padc_[0]) + .set("cend", padc_[1]) + .set("hstart", padh_[0]) + .set("hend", padh_[1]) + .set("wstart", padw_[0]) + .set("wend", padw_[1])); createFunction(backward_, "PadGrad", FuncConfig() - .set("padc0", padc_[0]) - .set("padc1", padc_[1]) - .set("padh0", padh_[0]) - .set("padh1", padh_[1]) - .set("padw0", padw_[0]) - .set("padw1", padw_[1])); + .set("cstart", padc_[0]) + .set("cend", padc_[1]) + .set("hstart", padh_[0]) + .set("hend", padh_[1]) + .set("wstart", padw_[0]) + .set("wend", padw_[1])); return true; } diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 66817fc93be43b..85a28e14aeb8eb 100644 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -3617,6 +3617,31 @@ def pad_layer(input, input data and 3 zeros after the input data in channel dimension. pad_h means padding zeros in height dimension. pad_w means padding zeros in width dimension. + + For example, + + .. code-block:: + + input(2,2,2,3) = [ + [ [[1,2,3], [3,4,5]], + [[2,3,5], [1,6,7]] ], + [ [[4,3,1], [1,8,7]], + [[3,8,9], [2,3,5]] ] + ] + + pad_c=[1,1], pad_h=[0,0], pad_w=[0,0] + output(2,4,2,3) = [ + [ [[0,0,0], [0,0,0]], + [[1,2,3], [3,4,5]], + [[2,3,5], [1,6,7]], + [[0,0,0], [0,0,0]] ], + [ [[0,0,0], [0,0,0]], + [[4,3,1], [1,8,7]], + [[3,8,9], [2,3,5]], + [[0,0,0], [0,0,0]] ] + ] + + The simply usage is: .. code-block:: python From 4426573a6ef42dee2877b5b9bfb162c2485f9345 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Sun, 22 Jan 2017 16:51:54 +0800 Subject: [PATCH 083/370] follow comments --- paddle/function/CrossMapNormalOp.cpp | 29 +++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/paddle/function/CrossMapNormalOp.cpp b/paddle/function/CrossMapNormalOp.cpp index 2d2ff0ca868204..e795567cd12fae 100644 --- a/paddle/function/CrossMapNormalOp.cpp +++ b/paddle/function/CrossMapNormalOp.cpp @@ -120,25 +120,36 @@ void CrossMapNormalGrad(real* inputsGrad, * The original formula is: * * Input(x, y) - * Output(x, y) = ------------------------------------------------ - * alpha /min(F, f-[N/2] + N) - * (1 + ----- * | (Input(x, y))^2 ) ^ (beta) - * N /max(0, f-[N/2]) + * Output(x, y) = --------------------------------------------- + * -- upper + * (k + alpha * > (Input(x, y))^2) ^ (beta) + * -- lower * - * Argument in the Function: - * Input is NCHW format, while input.shape.ndims() is equal 4. + * upper is `min(F, f-[N/2] + N)` + * lower if `max(0, f-[N/2])` + * + * Function implementation: + * + * inputs and outpus is NCHW format, while input.shape.ndims() is equal 4. * And the meaning of each dimension(0-3) is respectively batch size, * feature maps, rows and columns. - * The above formula is for each image. + * + * Input and Output in the above formula is for each map of one image, and + * Input(x, y), Output(x, y) represents an element in an image. + * + * In the implementation of Function, k is equal to 1, + * so Function has no argument for k. + * + * Function Arguments: * * \param size_ represent N - * \param scale_ represent alpha / N + * \param scale_ represent alpha * \param pow_ represent beta * \param inputs[0] represent Input * \param outputs[0] represent Output * \param outputs[1] represent The denominator in the formula(except beta) * - * note: + * Note: * Save output[1] is to simplify the backward calculation. * TODO, if only consider the forward calculation, we can optimize to * remove the output[1]. From abeb3aae84027a296cf310034e398f8a9271c1e1 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Sun, 22 Jan 2017 16:55:26 +0800 Subject: [PATCH 084/370] Minor changes --- paddle/function/PadOp.cpp | 6 +++--- paddle/gserver/layers/PadLayer.h | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/paddle/function/PadOp.cpp b/paddle/function/PadOp.cpp index df44fd0fa628d8..f1a0d2a1a96f24 100644 --- a/paddle/function/PadOp.cpp +++ b/paddle/function/PadOp.cpp @@ -79,10 +79,10 @@ void PadGrad(real* inGrad, * * Argument in this Function: * \param pad_ A struct object contains the padding size in each dimension. - * It has six integers. The channelStart and channelEnd indicates + * It has six integers. The channelStart and channelEnd indicate * how many zeros to add before and after the input in channel - * dimension. And the heightStart and heightEnd indicates padding - * in height dimension. The widthStart and widthEnd indicates the + * dimension. And the heightStart and heightEnd indicate padding + * in height dimension. The widthStart and widthEnd indicate the * padding in width dimension. * \param inputs A 4D tensor, only one input. * \param outputs A 4D tensor, the output value after padding. diff --git a/paddle/gserver/layers/PadLayer.h b/paddle/gserver/layers/PadLayer.h index 1f5a4a54a0a07e..3e3a21a9970370 100644 --- a/paddle/gserver/layers/PadLayer.h +++ b/paddle/gserver/layers/PadLayer.h @@ -19,8 +19,9 @@ limitations under the License. */ namespace paddle { /** - * @brief response normalization across feature maps - * namely normalize in number of size_ channels + * \brief This layer pads zeros to inputs according to the specify dimension. + * The input and output is a 4D tensor. Padding zeros from the 2nd to + * the 4th dimenstion according padc_, padh_ and padw_. */ class PadLayer : public Layer { public: From 5b9450ae0869673ae11000c89adeec4d237c4ccd Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Sun, 22 Jan 2017 17:46:28 +0800 Subject: [PATCH 085/370] follow comments --- paddle/function/CrossMapNormalOp.cpp | 38 ++++++++++++++++++---------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/paddle/function/CrossMapNormalOp.cpp b/paddle/function/CrossMapNormalOp.cpp index e795567cd12fae..5c0bdd933b1e4a 100644 --- a/paddle/function/CrossMapNormalOp.cpp +++ b/paddle/function/CrossMapNormalOp.cpp @@ -119,14 +119,14 @@ void CrossMapNormalGrad(real* inputsGrad, * * The original formula is: * - * Input(x, y) - * Output(x, y) = --------------------------------------------- - * -- upper - * (k + alpha * > (Input(x, y))^2) ^ (beta) - * -- lower + * Input(i, x, y) + * Output(i, x, y) = ---------------------------------------------- + * -- upper + * (k + alpha * > (Input(j, x, y))^2) ^ (beta) + * -- j = lower * - * upper is `min(F, f-[N/2] + N)` - * lower if `max(0, f-[N/2])` + * upper is `min(C, c + N/2)` + * lower if `max(0, c - N/2)` * * Function implementation: * @@ -134,8 +134,12 @@ void CrossMapNormalGrad(real* inputsGrad, * And the meaning of each dimension(0-3) is respectively batch size, * feature maps, rows and columns. * - * Input and Output in the above formula is for each map of one image, and - * Input(x, y), Output(x, y) represents an element in an image. + * Input and Output in the above formula is for each map(i) of one image, and + * Input(i, x, y), Output(i, x, y) represents an element in an image. + * + * C is the number of feature maps of one image, and N is a hyper-parameters + * is configured when Function is initialized. The sum in the denominator + * is the sum of the same position in the neighboring maps. * * In the implementation of Function, k is equal to 1, * so Function has no argument for k. @@ -199,20 +203,26 @@ class CrossMapNormalFunc : public FunctionBase { /** * \brief Backward calculation for normalization with across maps. * + * Function implementation: + * * The implementation of this Function is derived from the * CrossMapNormalFunc implementation. * * InputGrad = OutputGrad * denoms ^ (-beta) - * / - * + | (OutputGrad * OutputValue * (-2 * alpha * beta) / denoms) * InputValue - * / + * -- upper + * + > (OutputGrad * OutputValue * (-2 * alpha * beta) / denoms) * InputValue + * -- lower * - * Argument in the Function: * The data of inputs/outputs format is the same as the forward interface * and is NCHW. * + * The upper and lower is the same as forward. The logic of the sum + * is also the same as forward. + * + * Function Arguments: + * * \param size_ represent N - * \param scale_ represent alpha / N + * \param scale_ represent alpha * \param pow_ represent beta * \param inputs[0] represent InputValue, inputs[0] of CrossMapNormalFunc * \param inputs[1] represent OutputValue, outputs[0] of CrossMapNormalFunc From 225a8fa14b8fa04c814da02ff9f240f1819373f3 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Mon, 23 Jan 2017 11:26:20 +0800 Subject: [PATCH 086/370] Add numInputs_ and numOutputs_ --- paddle/function/CrossMapNormalOp.cpp | 18 ++++++++++++++---- paddle/function/Function.h | 13 +++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/paddle/function/CrossMapNormalOp.cpp b/paddle/function/CrossMapNormalOp.cpp index 5c0bdd933b1e4a..3fab2127a15116 100644 --- a/paddle/function/CrossMapNormalOp.cpp +++ b/paddle/function/CrossMapNormalOp.cpp @@ -162,14 +162,19 @@ template class CrossMapNormalFunc : public FunctionBase { public: void init(const FuncConfig& config) override { + // function arguments size_ = config.get("size"); scale_ = config.get("scale"); pow_ = config.get("pow"); + + // number of inputs and outputs + numInputs_ = 1; + numOutputs_ = 2; } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK_EQ((size_t)1, inputs.size()); - CHECK_EQ((size_t)2, outputs.size()); + CHECK_EQ((size_t)numInputs_, inputs.size()); + CHECK_EQ((size_t)numOutputs_, outputs.size()); CHECK_EQ(inputs[0].shape().ndims(), (size_t)4); CHECK(inputs[0].shape() == outputs[0].shape()); @@ -236,14 +241,19 @@ template class CrossMapNormalGradFunc : public FunctionBase { public: void init(const FuncConfig& config) override { + // function arguments size_ = config.get("size"); scale_ = config.get("scale"); pow_ = config.get("pow"); + + // number of inputs and outputs + numInputs_ = 4; + numOutputs_ = 1; } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK_EQ((size_t)4, inputs.size()); - CHECK_EQ((size_t)1, outputs.size()); + CHECK_EQ((size_t)numInputs_, inputs.size()); + CHECK_EQ((size_t)numOutputs_, outputs.size()); CHECK_EQ(inputs[0].shape().ndims(), (size_t)4); CHECK(inputs[0].shape() == inputs[1].shape()); diff --git a/paddle/function/Function.h b/paddle/function/Function.h index 9215c137eb8e85..4a6c79b6ebdf82 100644 --- a/paddle/function/Function.h +++ b/paddle/function/Function.h @@ -153,7 +153,20 @@ class FunctionBase { virtual void calc(const BufferArgs& inputs, const BufferArgs& outputs) {} + int getNumInputs() const { return numInputs_; } + + int getNumOutputs() const { return numOutputs_; } + static ClassRegistrar funcRegistrar_; + +protected: + // numInputs_ and numOutputs_ represents the maximum + // input and output supported by Function. + // Some functions are optimized for input and output, + // so when comparing the number of arguments, for these functions + // inputs.size() <= numInputs_ or outputs.size() <= numOutputs_ + size_t numInputs_; + size_t numOutputs_; }; #define FUNC_NAME(typeName, deviceName) #typeName "-" #deviceName From 9896f15e7cabd5d68ec03157439a44bbb709c221 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Mon, 23 Jan 2017 12:44:03 +0800 Subject: [PATCH 087/370] Add FunctionBase::ops() --- paddle/function/CrossMapNormalOp.cpp | 30 ++++++++++++++++++++-------- paddle/function/Function.h | 7 +++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/paddle/function/CrossMapNormalOp.cpp b/paddle/function/CrossMapNormalOp.cpp index 3fab2127a15116..8749a48327604b 100644 --- a/paddle/function/CrossMapNormalOp.cpp +++ b/paddle/function/CrossMapNormalOp.cpp @@ -182,23 +182,37 @@ class CrossMapNormalFunc : public FunctionBase { CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO); CHECK_EQ(outputs[1].getArgType(), ASSIGN_TO); - size_t samples = inputs[0].shape()[0]; - size_t channels = inputs[0].shape()[1]; - size_t height = inputs[0].shape()[2]; - size_t width = inputs[0].shape()[3]; + size_t batchSize = inputs[0].shape()[0]; + size_t maps = inputs[0].shape()[1]; + size_t rows = inputs[0].shape()[2]; + size_t columns = inputs[0].shape()[3]; CrossMapNormal(outputs[0].data(), outputs[1].data(), inputs[0].data(), - samples, - channels, - height, - width, + batchSize, + maps, + rows, + columns, size_, scale_, pow_); } + // Only need the shape of the input, can calculate the + // floating-point operation. + size_t ops(const BufferArgs& inputs, const BufferArgs& outputs) override { + CHECK_EQ((size_t)numInputs_, inputs.size()); + size_t batchSize = inputs[0].shape()[0]; + size_t maps = inputs[0].shape()[1]; + size_t rows = inputs[0].shape()[2]; + size_t columns = inputs[0].shape()[3]; + + // number of floating-point operations + // an approximate value + size_t ops = batchSize * maps * ((rows * columns) * size_); + } + private: size_t size_; real scale_; diff --git a/paddle/function/Function.h b/paddle/function/Function.h index 4a6c79b6ebdf82..65688eebee975c 100644 --- a/paddle/function/Function.h +++ b/paddle/function/Function.h @@ -153,6 +153,13 @@ class FunctionBase { virtual void calc(const BufferArgs& inputs, const BufferArgs& outputs) {} + // Calculate the number of floating-point operations of this Function. + // The inputs and outputs arguments do not need to contain the actual data, + // only the shape. + virtual size_t ops(const BufferArgs& inputs, const BufferArgs& outputs) { + return 0; + } + int getNumInputs() const { return numInputs_; } int getNumOutputs() const { return numOutputs_; } From c4437fa2312b7550fef89ddac00d057361804385 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Mon, 23 Jan 2017 13:07:16 +0800 Subject: [PATCH 088/370] Add FunctionBase::check() --- paddle/function/CrossMapNormalOp.cpp | 21 ++++++++++++++------- paddle/function/Function.h | 6 ++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/paddle/function/CrossMapNormalOp.cpp b/paddle/function/CrossMapNormalOp.cpp index 8749a48327604b..99af02ac744146 100644 --- a/paddle/function/CrossMapNormalOp.cpp +++ b/paddle/function/CrossMapNormalOp.cpp @@ -173,13 +173,9 @@ class CrossMapNormalFunc : public FunctionBase { } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK_EQ((size_t)numInputs_, inputs.size()); - CHECK_EQ((size_t)numOutputs_, outputs.size()); - - CHECK_EQ(inputs[0].shape().ndims(), (size_t)4); - CHECK(inputs[0].shape() == outputs[0].shape()); - CHECK(inputs[0].shape() == outputs[1].shape()); - + check(inputs, outputs); + // ArgType check still on here, + // not sure whether it is better to put inside the check. CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO); CHECK_EQ(outputs[1].getArgType(), ASSIGN_TO); size_t batchSize = inputs[0].shape()[0]; @@ -199,6 +195,15 @@ class CrossMapNormalFunc : public FunctionBase { pow_); } + void check(const BufferArgs& inputs, const BufferArgs& outputs) override { + CHECK_EQ((size_t)numInputs_, inputs.size()); + CHECK_EQ((size_t)numOutputs_, outputs.size()); + + CHECK_EQ(inputs[0].shape().ndims(), (size_t)4); + CHECK(inputs[0].shape() == outputs[0].shape()); + CHECK(inputs[0].shape() == outputs[1].shape()); + } + // Only need the shape of the input, can calculate the // floating-point operation. size_t ops(const BufferArgs& inputs, const BufferArgs& outputs) override { @@ -211,6 +216,8 @@ class CrossMapNormalFunc : public FunctionBase { // number of floating-point operations // an approximate value size_t ops = batchSize * maps * ((rows * columns) * size_); + + return ops; } private: diff --git a/paddle/function/Function.h b/paddle/function/Function.h index 65688eebee975c..4802c2e846cfa2 100644 --- a/paddle/function/Function.h +++ b/paddle/function/Function.h @@ -153,6 +153,12 @@ class FunctionBase { virtual void calc(const BufferArgs& inputs, const BufferArgs& outputs) {} + // This member function is used to check whether the BufferType and shape of + // the inputs and outputs arguments of the Function are correct. + // General calc function which will call this check to do arguments check. + // Also before the call calc, the caller can also check their own arguments. + virtual void check(const BufferArgs& inputs, const BufferArgs& outputs) {} + // Calculate the number of floating-point operations of this Function. // The inputs and outputs arguments do not need to contain the actual data, // only the shape. From a9228e2a406ecb3588ea0c2d112971260d87e1a3 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Mon, 23 Jan 2017 13:49:19 +0800 Subject: [PATCH 089/370] Fix CrossMapNormalGradFunc --- paddle/function/CrossMapNormalOp.cpp | 59 ++++++++++++++++++---------- paddle/function/Function.h | 5 ++- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/paddle/function/CrossMapNormalOp.cpp b/paddle/function/CrossMapNormalOp.cpp index 99af02ac744146..ef878bfbba961b 100644 --- a/paddle/function/CrossMapNormalOp.cpp +++ b/paddle/function/CrossMapNormalOp.cpp @@ -196,8 +196,8 @@ class CrossMapNormalFunc : public FunctionBase { } void check(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK_EQ((size_t)numInputs_, inputs.size()); - CHECK_EQ((size_t)numOutputs_, outputs.size()); + CHECK_EQ(numInputs_, inputs.size()); + CHECK_EQ(numOutputs_, outputs.size()); CHECK_EQ(inputs[0].shape().ndims(), (size_t)4); CHECK(inputs[0].shape() == outputs[0].shape()); @@ -215,7 +215,7 @@ class CrossMapNormalFunc : public FunctionBase { // number of floating-point operations // an approximate value - size_t ops = batchSize * maps * ((rows * columns) * size_); + size_t ops = batchSize * maps * rows * columns * (size_ * 2 + 3); return ops; } @@ -273,15 +273,7 @@ class CrossMapNormalGradFunc : public FunctionBase { } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK_EQ((size_t)numInputs_, inputs.size()); - CHECK_EQ((size_t)numOutputs_, outputs.size()); - - CHECK_EQ(inputs[0].shape().ndims(), (size_t)4); - CHECK(inputs[0].shape() == inputs[1].shape()); - CHECK(inputs[0].shape() == inputs[2].shape()); - CHECK(inputs[0].shape() == inputs[3].shape()); - CHECK(inputs[0].shape() == outputs[0].shape()); - + check(inputs, outputs); if (outputs[0].getArgType() != ADD_TO) { // Currently, some algorithm implementations are ASSIGN_TO mode, // if need to support the ADD_TO calculation, need to clear the output. @@ -290,25 +282,52 @@ class CrossMapNormalGradFunc : public FunctionBase { tmp.zero(); } - size_t samples = inputs[0].shape()[0]; - size_t channels = inputs[0].shape()[1]; - size_t height = inputs[0].shape()[2]; - size_t width = inputs[0].shape()[3]; + size_t batchSize = inputs[0].shape()[0]; + size_t maps = inputs[0].shape()[1]; + size_t rows = inputs[0].shape()[2]; + size_t columns = inputs[0].shape()[3]; CrossMapNormalGrad(outputs[0].data(), inputs[0].data(), inputs[1].data(), inputs[2].data(), inputs[3].data(), - samples, - channels, - height, - width, + batchSize, + maps, + rows, + columns, size_, scale_, pow_); } + void check(const BufferArgs& inputs, const BufferArgs& outputs) override { + CHECK_EQ(numInputs_, inputs.size()); + CHECK_EQ(numOutputs_, outputs.size()); + + CHECK_EQ(inputs[0].shape().ndims(), (size_t)4); + CHECK(inputs[0].shape() == inputs[1].shape()); + CHECK(inputs[0].shape() == inputs[2].shape()); + CHECK(inputs[0].shape() == inputs[3].shape()); + CHECK(inputs[0].shape() == outputs[0].shape()); + } + + // Only need the shape of one input, can calculate the + // floating-point operation. + size_t ops(const BufferArgs& inputs, const BufferArgs& outputs) override { + CHECK_LT((size_t)1, inputs.size()); + size_t batchSize = inputs[0].shape()[0]; + size_t maps = inputs[0].shape()[1]; + size_t rows = inputs[0].shape()[2]; + size_t columns = inputs[0].shape()[3]; + + // number of floating-point operations + // an approximate value + size_t ops = batchSize * maps * rows * columns * (size_ * 4 + 2); + + return ops; + } + private: size_t size_; real scale_; diff --git a/paddle/function/Function.h b/paddle/function/Function.h index 4802c2e846cfa2..3bbeb6e525f85b 100644 --- a/paddle/function/Function.h +++ b/paddle/function/Function.h @@ -156,12 +156,15 @@ class FunctionBase { // This member function is used to check whether the BufferType and shape of // the inputs and outputs arguments of the Function are correct. // General calc function which will call this check to do arguments check. - // Also before the call calc, the caller can also check their own arguments. + // And before the calc called, the caller can also check their own arguments. virtual void check(const BufferArgs& inputs, const BufferArgs& outputs) {} // Calculate the number of floating-point operations of this Function. // The inputs and outputs arguments do not need to contain the actual data, // only the shape. + // And some Functions have the same input and output shapes, + // so you may not need to enter the complete number of arguments. + // But entering the full arguments is always correct for this interface. virtual size_t ops(const BufferArgs& inputs, const BufferArgs& outputs) { return 0; } From a3f0aed00d304d3ac43735dcc83460b7b724f0a9 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 23 Jan 2017 18:44:51 +0800 Subject: [PATCH 090/370] add python v2 package --- python/CMakeLists.txt | 4 +++- python/paddle/v2/__init__.py | 13 +++++++++++++ python/setup.py.in | 3 ++- 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 python/paddle/v2/__init__.py diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 1cda4762eb2a55..ee7a5bff84ca96 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -4,11 +4,13 @@ set(OUTPUT_DIR file(GLOB TRAINER_PY_FILES . ./paddle/trainer/*.py) file(GLOB HELPERS_PY_FILES . ./paddle/trainer_config_helpers/*.py) file(GLOB UTILS_PY_FILES . ./paddle/utils/*.py) +file(GLOB V2_PY_FILES . ./paddle/v2/*.py) set(PY_FILES paddle/__init__.py ${TRAINER_PY_FILES} ${HELPERS_PY_FILES} - ${UTILS_PY_FILES}) + ${UTILS_PY_FILES} + ${V2_PY_FILES}) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in ${CMAKE_CURRENT_BINARY_DIR}/setup.py) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py new file mode 100644 index 00000000000000..f662d6826321eb --- /dev/null +++ b/python/paddle/v2/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. diff --git a/python/setup.py.in b/python/setup.py.in index b66a42e87c7870..1e1324eea825ab 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -4,7 +4,8 @@ packages=['paddle', 'paddle.proto', 'paddle.trainer', 'paddle.trainer_config_helpers', - 'paddle.utils'] + 'paddle.utils', + 'paddle.v2'] setup(name='paddle', version='${PADDLE_VERSION}', From 12e9c003b6654e6cb621858285f7d3b09b1b85bc Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 23 Jan 2017 19:38:42 +0800 Subject: [PATCH 091/370] add optimizer --- demo/mnist/api_train.py | 40 +++++++++--------------- python/paddle/v2/__init__.py | 4 +++ python/paddle/v2/optimizer.py | 58 +++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 25 deletions(-) create mode 100644 python/paddle/v2/optimizer.py diff --git a/demo/mnist/api_train.py b/demo/mnist/api_train.py index f301da382ff8a5..8573d8143a085b 100644 --- a/demo/mnist/api_train.py +++ b/demo/mnist/api_train.py @@ -13,15 +13,7 @@ import random from mnist_util import read_from_mnist from paddle.trainer_config_helpers import * - - -def optimizer_config(): - settings( - learning_rate=1e-4, - learning_method=AdamOptimizer(), - batch_size=1000, - model_average=ModelAverage(average_window=0.5), - regularization=L2Regularization(rate=0.5)) +import paddle.v2 def network_config(): @@ -75,19 +67,23 @@ def input_order_converter(generator): def main(): api.initPaddle("-use_gpu=false", "-trainer_count=4") # use 4 cpu cores - # get enable_types for each optimizer. - # enable_types = [value, gradient, momentum, etc] - # For each optimizer(SGD, Adam), GradientMachine should enable different - # buffers. - opt_config_proto = parse_optimizer_config(optimizer_config) - opt_config = api.OptimizationConfig.createFromProto(opt_config_proto) - _temp_optimizer_ = api.ParameterOptimizer.create(opt_config) - enable_types = _temp_optimizer_.getParameterTypes() + optimizer = paddle.v2.optimizer.Adam( + learning_rate=1e-4, + batch_size=1000, + model_average=ModelAverage(average_window=0.5), + regularization=L2Regularization(rate=0.5)) + + # Create Local Updater. Local means not run in cluster. + # For a cluster training, here we can change to createRemoteUpdater + # in future. + updater = optimizer.create_local_updater() + assert isinstance(updater, api.ParameterUpdater) # Create Simple Gradient Machine. model_config = parse_network_config(network_config) - m = api.GradientMachine.createFromConfigProto( - model_config, api.CREATE_MODE_NORMAL, enable_types) + m = api.GradientMachine.createFromConfigProto(model_config, + api.CREATE_MODE_NORMAL, + optimizer.enable_types()) # This type check is not useful. Only enable type hint in IDE. # Such as PyCharm @@ -96,12 +92,6 @@ def main(): # Initialize Parameter by numpy. init_parameter(network=m) - # Create Local Updater. Local means not run in cluster. - # For a cluster training, here we can change to createRemoteUpdater - # in future. - updater = api.ParameterUpdater.createLocalUpdater(opt_config) - assert isinstance(updater, api.ParameterUpdater) - # Initialize ParameterUpdater. updater.init(m) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index f662d6826321eb..b2ea87b086101d 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -11,3 +11,7 @@ # 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. + +import optimizer + +__all__ = ['optimizer'] diff --git a/python/paddle/v2/optimizer.py b/python/paddle/v2/optimizer.py new file mode 100644 index 00000000000000..aa2942bc9faeb2 --- /dev/null +++ b/python/paddle/v2/optimizer.py @@ -0,0 +1,58 @@ +import py_paddle.swig_paddle as swig_api +import paddle.trainer_config_helpers.optimizers as v1_optimizers +import paddle.trainer_config_helpers.config_parser_utils as config_parser_utils +import paddle.v2 + +__all__ = ['Adam', 'Adamax'] + + +class Optimizer(object): + def __init__(self, **kwargs): + if 'batch_size' in kwargs: + del kwargs['batch_size'] # not important for python library. + + def __impl__(): + v1_optimizers.settings(batch_size=1, **kwargs) + + self.__opt_conf_proto__ = config_parser_utils.parse_optimizer_config( + __impl__) + self.__opt_conf__ = swig_api.OptimizationConfig.createFromProto( + self.__opt_conf_proto__) + + def enable_types(self): + """ + get enable_types for each optimizer. + enable_types = [value, gradient, momentum, etc] + For each optimizer(SGD, Adam), GradientMachine should enable different + buffers. + """ + tmp = swig_api.ParameterOptimizer.create(self.__opt_conf__) + assert isinstance(tmp, swig_api.ParameterOptimizer) + return tmp.getParameterTypes() + + def create_local_updater(self): + return swig_api.ParameterUpdater.createLocalUpdater(self.__opt_conf__) + + def create_remote_updater(self, pass_num): + return swig_api.ParameterUpdater.createRemoteUpdater(self.__opt_conf__, + pass_num) + + +class Adam(Optimizer): + def __init__(self, beta1=0.9, beta2=0.999, epsilon=1e-8, **kwargs): + learning_method = v1_optimizers.AdamOptimizer( + beta1=beta1, beta2=beta2, epsilon=epsilon) + super(Adam, self).__init__(learning_method=learning_method, **kwargs) + + +class Adamax(Optimizer): + def __init__(self, beta1=0.9, beta2=0.999, **kwargs): + learning_method = v1_optimizers.AdamaxOptimizer( + beta1=beta1, beta2=beta2) + super(Adamax, self).__init__(learning_method=learning_method, **kwargs) + + +if __name__ == '__main__': + swig_api.initPaddle('--use_gpu=false') + opt = paddle.v2.optimizer.Adam() + print opt.enable_types() From 23c8ad859c4acbf133fd00ec65643fffa27754df Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 24 Jan 2017 13:51:32 +0800 Subject: [PATCH 092/370] Make MyServer as a stack variable --- paddle/pserver/test/test_ProtoServer.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/paddle/pserver/test/test_ProtoServer.cpp b/paddle/pserver/test/test_ProtoServer.cpp index e70e1670d31993..04236fda2fb62b 100644 --- a/paddle/pserver/test/test_ProtoServer.cpp +++ b/paddle/pserver/test/test_ProtoServer.cpp @@ -161,15 +161,8 @@ TEST(ProtoServer, extended) { int main(int argc, char** argv) { paddle::initMain(argc, argv); testing::InitGoogleTest(&argc, argv); - - std::unique_ptr server; - if (FLAGS_rdma_tcp == "rdma") { - server.reset(new MyServer(FLAGS_port, 0)); - } else { - server.reset(new MyServer(FLAGS_port)); - } - - server->start(); + MyServer server(FLAGS_port, FLAGS_rdma_tcp == "rdma" ? 0 : -1); + server.start(); usleep(10000); return RUN_ALL_TESTS(); From 1f972361774a60c011715280880600249a8d6203 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 24 Jan 2017 14:03:35 +0800 Subject: [PATCH 093/370] Remove unused init method in paddle::Trainer --- paddle/trainer/Trainer.cpp | 10 ---------- paddle/trainer/Trainer.h | 5 ----- 2 files changed, 15 deletions(-) diff --git a/paddle/trainer/Trainer.cpp b/paddle/trainer/Trainer.cpp index 8465addaf9e038..bd84545375117b 100644 --- a/paddle/trainer/Trainer.cpp +++ b/paddle/trainer/Trainer.cpp @@ -90,16 +90,6 @@ DEFINE_string(model_list, "", "File that saves the model list when evaluation"); namespace paddle { -void Trainer::init(int argc, char** argv) { - initMain(argc, argv); - initPython(argc, argv); - - auto config = TrainerConfigHelper::createFromFlagConfig(); - feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW); - - init(config); -} - void Trainer::init(const std::shared_ptr& config, bool testing, const std::shared_ptr& gradientMachine, diff --git a/paddle/trainer/Trainer.h b/paddle/trainer/Trainer.h index 7cbf18ace7a5fe..c8ee4726c24c33 100644 --- a/paddle/trainer/Trainer.h +++ b/paddle/trainer/Trainer.h @@ -71,11 +71,6 @@ class Trainer { const std::shared_ptr& dataProvider = nullptr, const std::shared_ptr& testDataProvider = nullptr); - /** - * Initialize Trainer from command line flags. - */ - void init(int argc, char** argv); - /** * Train until num_passes reached. * One pass means neural network train through all training data. From 5b1f66fe9788a16110d6a3932d381d8299c481b1 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 24 Jan 2017 15:05:06 +0800 Subject: [PATCH 094/370] Removed unused GradientMachine::create --- .../gradientmachines/GradientMachine.cpp | 49 ----- .../gradientmachines/GradientMachine.h | 33 ---- paddle/trainer/tests/CMakeLists.txt | 8 - paddle/trainer/tests/test_Prediction.cpp | 174 ------------------ 4 files changed, 264 deletions(-) delete mode 100644 paddle/trainer/tests/test_Prediction.cpp diff --git a/paddle/gserver/gradientmachines/GradientMachine.cpp b/paddle/gserver/gradientmachines/GradientMachine.cpp index 36ca05b919b136..3eb87d9b85c820 100644 --- a/paddle/gserver/gradientmachines/GradientMachine.cpp +++ b/paddle/gserver/gradientmachines/GradientMachine.cpp @@ -60,55 +60,6 @@ GradientMachine* GradientMachine::create( return nullptr; } -GradientMachine* GradientMachine::create(const std::string& modelFile, - DataConfig* dataConfig) { - std::ifstream is(modelFile); - CHECK(is) << "Fail to open " << modelFile; - return create(is, dataConfig); -} - -GradientMachine* GradientMachine::create(std::istream& is, - DataConfig* dataConfig) { - TrainerConfig trainerConfig; - GradientMachine* ret = create(is, &trainerConfig); - if (dataConfig && trainerConfig.has_data_config()) { - *dataConfig = trainerConfig.data_config(); - } - return ret; -} - -GradientMachine* GradientMachine::create(const std::string& modelFile, - TrainerConfig* trainerConfig) { - std::ifstream is(modelFile); - CHECK(is) << "Fail to open " << modelFile; - return create(is, trainerConfig); -} - -GradientMachine* GradientMachine::create(std::istream& is, - TrainerConfig* trainerConfig) { - TrainerConfig trainerConfigTemp; - int64_t size; - CHECK(is.read((char*)&size, sizeof(size))) << "Fail to read "; - std::string buf; - buf.resize(size); - CHECK(is.read(&buf[0], size)) << "Fail to read "; - CHECK(trainerConfigTemp.ParseFromString(buf)) << "Fail to parse config"; - std::unique_ptr machine( - create(trainerConfigTemp.model_config())); - std::vector& parameters = machine->getParameters(); - for (auto& para : parameters) { - para->load(is); - } - - machine->onLoadParameter(); - - if (trainerConfig) { - *trainerConfig = trainerConfigTemp; - } - - return machine.release(); -} - void GradientMachine::saveParameters(const std::string& dir) const { LOG(INFO) << "Saving parameters to " << dir; diff --git a/paddle/gserver/gradientmachines/GradientMachine.h b/paddle/gserver/gradientmachines/GradientMachine.h index 1e35c7e2b8d185..0829968d87c5dc 100644 --- a/paddle/gserver/gradientmachines/GradientMachine.h +++ b/paddle/gserver/gradientmachines/GradientMachine.h @@ -89,39 +89,6 @@ class GradientMachine { std::vector{ PARAMETER_VALUE, PARAMETER_GRADIENT, PARAMETER_MOMENTUM}); - /** - * Create a gradient machine from the merged model file. - * The merged model file can be generated using tools/merge_model - * If dataConfig is not null, it will be filled with the DataConfig - * from the TrainerConfig - */ - static GradientMachine* create(const std::string& modelFile, - DataConfig* dataConfig); - - /** - * Create a gradient machine from a stream which contains the merged - * model file. The merged model file can be generated using tools/merge_model - * If dataConfig is not null, it will be filled with the DataConfig - * from the TrainerConfig - */ - static GradientMachine* create(std::istream& is, DataConfig* dataConfig); - - /** - * Create a gradient machine from the merged model file. - * The merged model file can be generated using tools/merge_model - * If trainerConfig is not null, it will be filled with the TrainerConfig - */ - static GradientMachine* create(const std::string& modelFile, - TrainerConfig* trainerConfig); - - /** - * Create a gradient machine from a stream which contains the merged - * model file. The merged model file can be generated using tools/merge_model - * If trainerConfig is not null, it will be filled with the TrainerConfig - */ - static GradientMachine* create(std::istream& is, - TrainerConfig* trainerConfig); - virtual ~GradientMachine() {} /** diff --git a/paddle/trainer/tests/CMakeLists.txt b/paddle/trainer/tests/CMakeLists.txt index 22e07bd0e98a4c..c5c76a030d9e5f 100644 --- a/paddle/trainer/tests/CMakeLists.txt +++ b/paddle/trainer/tests/CMakeLists.txt @@ -1,11 +1,3 @@ -################# test_Prediction ###################### -add_unittest_without_exec(test_Prediction - test_Prediction.cpp) -add_test(NAME test_Prediction - COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python - ${CMAKE_CURRENT_BINARY_DIR}/test_Prediction --merger=${CMAKE_CURRENT_BINARY_DIR}/../paddle_merge_model - WORKING_DIRECTORY ${PROJ_ROOT}/paddle/) - ################# test_Compare ############################ add_unittest_without_exec(test_Compare test_Compare.cpp) diff --git a/paddle/trainer/tests/test_Prediction.cpp b/paddle/trainer/tests/test_Prediction.cpp deleted file mode 100644 index 0c79404eee1c09..00000000000000 --- a/paddle/trainer/tests/test_Prediction.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* 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 - -#include "paddle/trainer/Trainer.h" - -#include - -DECLARE_string(config); -DECLARE_string(config_args); -DEFINE_string(merger, - "./paddle_merge_model", - "path to paddle_merge_model binary"); - -using namespace paddle; // NOLINT -using namespace std; // NOLINT - -static const string& configFile = "trainer/tests/sample_trainer_config.conf"; -static const string& mergedModelFile = "./test_model_file"; -static const string& modelDir = "./test_model_dir"; - -void checkBuffer(real* vec1, real* vec2, size_t len) { - for (size_t i = 0; i < len; i++) { - EXPECT_EQ(vec1[i], vec2[i]) << "vec1:" << vec1[i] << " vec2:" << vec2[i]; - } -} - -void checkParameters(vector A, vector B) { - CHECK_EQ(B.size(), A.size()) << "parameter size not equal"; - for (size_t i = 0; i < A.size(); i++) { - auto vec1 = A[i]->getBuf(PARAMETER_VALUE); - auto vec2 = B[i]->getBuf(PARAMETER_VALUE); - CHECK_EQ(vec1->useGpu_, vec2->useGpu_) << "use gpu not equal"; - CHECK_EQ(vec1->getSize(), vec2->getSize()) << "size not equal"; - - if (vec1->useGpu_ == false) { - checkBuffer(vec1->getData(), vec2->getData(), vec1->getSize()); - } else { - VectorPtr cpuVec1 = Vector::create(vec1->getSize(), false); - VectorPtr cpuVec2 = Vector::create(vec2->getSize(), false); - cpuVec1->copyFrom(*vec1, HPPL_STREAM_DEFAULT); - cpuVec2->copyFrom(*vec2, HPPL_STREAM_DEFAULT); - hl_stream_synchronize(HPPL_STREAM_DEFAULT); - checkBuffer(cpuVec1->getData(), cpuVec2->getData(), cpuVec1->getSize()); - } - } -} - -TEST(GradientMachine, create) { -#ifdef PADDLE_ONLY_CPU - FLAGS_use_gpu = false; -#endif - mkDir(modelDir.c_str()); - FLAGS_config = configFile; - FLAGS_config_args = "with_cost=False"; - auto config = TrainerConfigHelper::createFromFlagConfig(); - - // save model to directory - unique_ptr gradientMachine1( - GradientMachine::create(*config)); - gradientMachine1->saveParameters(modelDir); - Trainer trainer; - trainer.init(config); - ParameterUtil* paramUtil = trainer.getParameterUtilPtr(); - if (paramUtil != NULL) { - paramUtil->saveConfigWithPath(modelDir); - } - - // create a different GradientMachine - unique_ptr gradientMachine2( - GradientMachine::create(*config)); - gradientMachine2->randParameters(); - - // merge config and model to one file - string cmd = FLAGS_merger + " --model_dir=" + modelDir + - " --config_args=with_cost=False" + " --model_file=" + - mergedModelFile; - LOG(INFO) << cmd; - int ret = system(cmd.c_str()); - EXPECT_EQ(0, ret); - if (ret) { - return; - } - - // create GradientMachine from the merged model - DataConfig dataConfig; - unique_ptr gradientMachine3( - GradientMachine::create(mergedModelFile, &dataConfig)); - CHECK(gradientMachine3); - EXPECT_EQ(dataConfig.type(), "simple"); - EXPECT_EQ(dataConfig.feat_dim(), 3); - - // compare the parameters of GradientMachine and GradientMachine3 - std::vector paraMachine1 = gradientMachine1->getParameters(); - std::vector paraMachine3 = gradientMachine3->getParameters(); - checkParameters(paraMachine1, paraMachine3); - - // Test that the GradientMachine created from the merged model - // is same as the orginnal one. - vector inArgs(1); - vector outArgs; - - int inputDim = 3; - int numSamples = 2; - CpuMatrix cpuInput(numSamples, inputDim); - for (int i = 0; i < numSamples; ++i) { - for (int j = 0; j < inputDim; ++j) { - cpuInput.getData()[i * inputDim + j] = - rand() / (real)RAND_MAX; // NOLINT TODO(yuyang): use rand_r - } - } - MatrixPtr input = Matrix::create(numSamples, - inputDim, - /* trans */ false, - FLAGS_use_gpu); - input->copyFrom(cpuInput); - inArgs[0].value = input; - gradientMachine1->forward(inArgs, &outArgs, PASS_TEST); - EXPECT_EQ((size_t)1, outArgs.size()); - - vector outArgs2; - gradientMachine2->forward(inArgs, &outArgs2, PASS_TEST); - CpuMatrix out1(outArgs[0].value->getHeight(), outArgs[0].value->getWidth()); - CpuMatrix out2(outArgs2[0].value->getHeight(), outArgs2[0].value->getWidth()); - out1.copyFrom(*outArgs[0].value); - out2.copyFrom(*outArgs2[0].value); - for (size_t i = 0; i < out1.getHeight() * out1.getWidth(); i++) { - EXPECT_NE(out1.getData()[i], out2.getData()[i]); - } - - gradientMachine3->forward(inArgs, &outArgs2, PASS_TEST); - out2.copyFrom(*outArgs2[0].value); - checkBuffer( - out1.getData(), out2.getData(), out2.getHeight() * out2.getWidth()); - - cmd = " rm -rf " + modelDir + "/*"; - LOG(INFO) << "cmd " << cmd; - ret = system(cmd.c_str()); - EXPECT_EQ(0, ret); - if (ret) { - return; - } - - cmd = " rm -rf " + mergedModelFile; - LOG(INFO) << "cmd " << cmd; - ret = system(cmd.c_str()); - EXPECT_EQ(0, ret); - if (ret) { - return; - } - - // clean up - rmDir(modelDir.c_str()); - remove(mergedModelFile.c_str()); -} - -int main(int argc, char** argv) { - initMain(argc, argv); - initPython(argc, argv); - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} From 936301f157f8c557eea80eda4c0b9d2525dbab52 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Fri, 13 Jan 2017 14:55:43 -0800 Subject: [PATCH 095/370] Use and test Daoyuan's SparseMatrixArg. --- paddle/function/BufferArg.cpp | 6 ++-- paddle/function/BufferArg.h | 28 ++++++++++++++-- paddle/function/CMakeLists.txt | 1 + paddle/function/MulOp.cpp | 60 ++++++++++++++++++++++++++++++++++ paddle/function/MulOp.h | 30 +++++++++++++++++ paddle/function/MulOpGpu.cu | 57 ++++++++++++++++++++++++++++++++ paddle/function/MulOpTest.cpp | 56 +++++++++++++++++++++++++++++++ paddle/function/TensorType.h | 26 ++++++++++++++- 8 files changed, 259 insertions(+), 5 deletions(-) create mode 100644 paddle/function/MulOp.cpp create mode 100644 paddle/function/MulOp.h create mode 100644 paddle/function/MulOpGpu.cu create mode 100644 paddle/function/MulOpTest.cpp diff --git a/paddle/function/BufferArg.cpp b/paddle/function/BufferArg.cpp index 5d595deb12c6c8..4064daf4159e22 100644 --- a/paddle/function/BufferArg.cpp +++ b/paddle/function/BufferArg.cpp @@ -32,14 +32,16 @@ const SparseMatrixArg& BufferArg::sparse() const { SparseMatrixArg::SparseMatrixArg(const CpuSparseMatrix& sparse, ArgType argType) : BufferArg(sparse, argType), row_(reinterpret_cast(sparse.getRows()), VALUE_TYPE_INT32), - col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32) { + col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32), + trans_(const_cast(sparse).getTranspose()) { bufferType_ = TENSOR_SPARSE; } SparseMatrixArg::SparseMatrixArg(const GpuSparseMatrix& sparse, ArgType argType) : BufferArg(sparse, argType), row_(reinterpret_cast(sparse.getRows()), VALUE_TYPE_INT32), - col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32) { + col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32), + trans_(const_cast(sparse).getTranspose()) { bufferType_ = TENSOR_SPARSE; } diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index 84209265ce7634..3489510b25f098 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -167,7 +167,7 @@ class BufferArg { ValueType valueType() const { return valueType_; } BufferType bufferType() const { return bufferType_; } const TensorShape& shape() const { return shape_; } - bool isSparse() const { return (TENSOR_SPARSE == bufferType_); } + bool isSparse() const { return TENSOR_SPARSE == bufferType_; } bool isSequenceArg() const { return TENSOR_SEQUENCE_DATA == bufferType_; } const SequenceArg& sequence() const; @@ -271,13 +271,15 @@ class SparseMatrixArg : public BufferArg { size_t nnz, SparseDataFormat format, SparseDataType type, + bool trans = false, ArgType argType = UNSPECIFIED) : BufferArg(buf, valueType, shape, argType), row_(row), col_(col), nnz_(nnz), format_(format), - type_(type) { + type_(type), + trans_(trans) { bufferType_ = TENSOR_SPARSE; CHECK((valueType == VALUE_TYPE_FLOAT) || (valueType == VALUE_TYPE_DOUBLE)); CHECK_EQ(shape_.ndims(), (size_t)2); @@ -294,6 +296,24 @@ class SparseMatrixArg : public BufferArg { SparseMatrixArg(const GpuSparseMatrix& sparse, ArgType argType = UNSPECIFIED); + template + typename Tensor::SparseMatrix SparseMatrix() const { + CHECK(buf_); + CHECK(valueType_ == DataType::value); + // CHECK(deviceType_ == DType); + CHECK_EQ(2, shape_.ndims()); + return typename Tensor::SparseMatrix( + reinterpret_cast(buf_), + reinterpret_cast(row_.data()), + reinterpret_cast(col_.data()), + shape_[0], + shape_[1], + nnz_, + static_cast(type_), + static_cast(format_), + trans_); + } + ~SparseMatrixArg() {} void* getRowBuf() const { return row_.data(); } @@ -302,6 +322,8 @@ class SparseMatrixArg : public BufferArg { size_t nnz() const { return nnz_; } + bool isTranspose() const { return trans_; } + SparseDataFormat dataFormat() const { return format_; } SparseDataType dataType() const { return type_; } @@ -312,6 +334,8 @@ class SparseMatrixArg : public BufferArg { size_t nnz_; SparseDataFormat format_; SparseDataType type_; + /// todo(tianbing), move trans_ up to BufferArg + bool trans_; }; } // namespace paddle diff --git a/paddle/function/CMakeLists.txt b/paddle/function/CMakeLists.txt index 6d20868072c3ac..fae3b7b20a70b5 100644 --- a/paddle/function/CMakeLists.txt +++ b/paddle/function/CMakeLists.txt @@ -26,6 +26,7 @@ if(WITH_TESTING) add_simple_unittest(FunctionTest) add_simple_unittest(ContextProjectionOpTest) add_simple_unittest(PadOpTest) + add_simple_unittest(MulOpTest) endif() endif() diff --git a/paddle/function/MulOp.cpp b/paddle/function/MulOp.cpp new file mode 100644 index 00000000000000..1fa29fae8d4e1e --- /dev/null +++ b/paddle/function/MulOp.cpp @@ -0,0 +1,60 @@ +/* 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 "MulOp.h" + +namespace paddle { + +/** + * mul operator + * out = scaleT * out + scaleAB*(in1 * in2) + * + * \param outputs[0] output matrix, N * M + * \param inputs[0] first input (sparse) matrix, N * K + * \param inputs[1] second input matrix, K * M (non-transpose) + */ +template +class MulFunc : public FunctionBase { +public: + void init(const FuncConfig& config) override { + scaleAB_ = config.get("scaleAB"); + scaleT_ = config.get("scaleT"); + } + + void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { + /// todo(tianbing), add more checks + CHECK_EQ((size_t)1, inputs.size()); + CHECK_EQ((size_t)2, outputs.size()); + CHECK(inputs[0].data() && inputs[1].data() && outputs[0].data()); + CHECK_EQ(inputs[0].shape().ndims(), (size_t)2); + CHECK_EQ(inputs[1].shape().ndims(), (size_t)2); + CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); + CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO); + + CHECK(inputs[0].isSparse()) << "SparseMatrix requried here"; + const auto in1_mat = inputs[0].sparse().SparseMatrix(); + auto out_mat = outputs[0].matrix(); + const auto in2_mat = inputs[1].matrix(); + MulOp(out_mat, in1_mat, in2_mat, scaleAB_, scaleT_); + } + +private: + real scaleAB_; + real scaleT_; +}; + +#ifndef PADDLE_ONLY_CPU +REGISTER_TYPED_FUNC(MulOp, GPU, MulFunc); +#endif +} // namespace paddle diff --git a/paddle/function/MulOp.h b/paddle/function/MulOp.h new file mode 100644 index 00000000000000..bcea1864026b27 --- /dev/null +++ b/paddle/function/MulOp.h @@ -0,0 +1,30 @@ +/* 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" +#include "paddle/math/Matrix.h" +#include "paddle/math/SparseMatrix.h" + +namespace paddle { + +template +void MulOp(GpuMatrix& out, + const GpuSparseMatrix& a, + const GpuMatrix& b, + real scaleAB, + real scaleT); + +} // namespace paddle diff --git a/paddle/function/MulOpGpu.cu b/paddle/function/MulOpGpu.cu new file mode 100644 index 00000000000000..db716c1e46b4e1 --- /dev/null +++ b/paddle/function/MulOpGpu.cu @@ -0,0 +1,57 @@ +/* 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 "MulOp.h" +#include "paddle/math/Matrix.h" +#include "paddle/math/SparseMatrix.h" + +namespace paddle { +/** + * out = scale_t * out + scale_ab * (a * b) + */ +template <> +void MulOp(GpuMatrix& out, + const GpuSparseMatrix& a, + const GpuMatrix& b, + real scale_ab, + real scale_t) { + CHECK(out.isContiguous()); + CHECK(b.isContiguous()); + CHECK(b.useGpu_ == true) << "Matrix type are not equal"; + CHECK(!out.trans_ && !b.trans_) << "not supported"; + if (!a.trans_) { + CHECK(out.width_ == b.width_ && out.height_ == a.height_ + && a.width_ == b.height_) << "Matrix dimensions are not equal"; + } else { + CHECK(out.width_ == b.width_ && out.height_ == a.width_ + && a.height_ == b.height_) << "Matrix dimensions are not equal"; + } + hl_trans_op_t a_trans = a.trans_ ? HPPL_OP_T : HPPL_OP_N; + hl_sparse_matrix_s a_data = a.sMatrix_.get(); + real* b_data = b.data_; + real* out_data = out.data_; + hl_matrix_csr_mul_dense(a_data, + a_trans, + b_data, + HPPL_OP_N, + out_data, + out.height_, + out.width_, + b.height_, + scale_ab, + scale_t); +} + +} // namespace paddle diff --git a/paddle/function/MulOpTest.cpp b/paddle/function/MulOpTest.cpp new file mode 100644 index 00000000000000..bc1fa9f607a575 --- /dev/null +++ b/paddle/function/MulOpTest.cpp @@ -0,0 +1,56 @@ +/* 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 +#include "FunctionTest.h" +#include "paddle/math/Matrix.h" +#include "paddle/math/SparseMatrix.h" +#include "paddle/testing/TestUtil.h" + +using namespace paddle; // NOLINT + +void testSpMatrixMul(int M, int N, int K, real rate, real scale1, real scale2) { + /// todo(tianbing) check CPU/GPU + const auto gpuFunc = FunctionBase::funcRegistrar_.createByType("MulOP-GPU"); + gpuFunc->init(FuncConfig().set("scaleAB", scale1).set("scaleT", scale2)); + + int nnz = M * K * rate; + auto gpuA = std::make_shared(M, K, nnz); + const auto gpuB = std::make_shared(K, N); + const auto gpuOut = std::make_shared(M, N); + + gpuA->randomizeUniform(); + gpuB->randomizeUniform(); + gpuOut->randomizeUniform(); + + BufferArgs inputs; + BufferArgs outputs; + inputs.addArg(*gpuA); + inputs.addArg(*gpuB); + outputs.addArg(*gpuOut); + + gpuFunc->calc(inputs, outputs); +} + +TEST(SMatrix, sMatrixMul) { + for (auto M : {1, 40, 128, 200}) { + for (auto N : {100, 2000, 20480}) { + for (auto K : {100, 512, 1024}) { + /// todo(tianbing), add scaleAB and scaleT + VLOG(3) << " M=" << M << " N=" << N << " K=" << K; + testSpMatrixMul(M, N, K, 0.05, 1, 1); + } + } + } +} diff --git a/paddle/function/TensorType.h b/paddle/function/TensorType.h index 98942cff9e2ea4..73ac1cc70d2cd8 100644 --- a/paddle/function/TensorType.h +++ b/paddle/function/TensorType.h @@ -87,6 +87,29 @@ struct MatrixT { using type = void; // Not implemented }; +template +struct SparseMatrixT; + +template <> +struct SparseMatrixT { + using type = CpuSparseMatrix; +}; + +template <> +struct SparseMatrixT { + using type = GpuSparseMatrix; +}; + +template <> +struct SparseMatrixT { + using type = void; // Not implemented +}; + +template <> +struct SparseMatrixT { + using type = void; // Not implemented +}; + template struct VectorT; @@ -114,8 +137,9 @@ struct VectorT { template struct Tensor { - typedef typename detail::MatrixT::type Matrix; typedef typename detail::VectorT::type Vector; + typedef typename detail::MatrixT::type Matrix; + typedef typename detail::SparseMatrixT::type SparseMatrix; }; } // namespace paddle From 1f0cbcf3508f061548636f0a703dac1908a98104 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Mon, 16 Jan 2017 16:10:45 -0800 Subject: [PATCH 096/370] add GpuMatrix::mul, CpuMatrix::mul operators --- paddle/function/BufferArg.h | 2 +- paddle/function/MulOp.cpp | 478 +++++++++++++++++++++++++++++++++- paddle/function/MulOp.h | 41 +++ paddle/function/MulOpGpu.cu | 120 ++++++++- paddle/function/MulOpTest.cpp | 36 ++- 5 files changed, 652 insertions(+), 25 deletions(-) diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index 3489510b25f098..1f86f49911c484 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -167,7 +167,7 @@ class BufferArg { ValueType valueType() const { return valueType_; } BufferType bufferType() const { return bufferType_; } const TensorShape& shape() const { return shape_; } - bool isSparse() const { return TENSOR_SPARSE == bufferType_; } + bool isSparseArg() const { return TENSOR_SPARSE == bufferType_; } bool isSequenceArg() const { return TENSOR_SEQUENCE_DATA == bufferType_; } const SequenceArg& sequence() const; diff --git a/paddle/function/MulOp.cpp b/paddle/function/MulOp.cpp index 1fa29fae8d4e1e..7d341182523cbb 100644 --- a/paddle/function/MulOp.cpp +++ b/paddle/function/MulOp.cpp @@ -13,16 +13,471 @@ See the License for the specific language governing permissions and limitations under the License. */ #include "MulOp.h" +#include "paddle/math/MathFunctions.h" +#include "paddle/math/SIMDFunctions.h" +#include "paddle/utils/ThreadLocal.h" + +#ifndef PADDLE_TYPE_DOUBLE +#define GEMM paddle::gemm +#else +#define GEMM paddle::gemm +#endif + +namespace { +inline void vecAddTo(real* a, const real* b, size_t len) { + for (unsigned int i = 0; i < len; ++i) { + a[i] += b[i]; + } +} + +inline void vecAddTo(real* a, const real* b, real scaleB, size_t len) { + for (unsigned int i = 0; i < len; ++i) { + a[i] += scaleB * b[i]; + } +} + +inline void colVecAddTo( + real* a, const real* b, size_t len, size_t aWidth, size_t bWidth) { + for (unsigned int i = 0; i < len; ++i) { + a[i * aWidth] += b[i * bWidth]; + } +} + +inline void colVecAddTo( + real* a, real* b, real c, size_t len, size_t aWidth, size_t bWidth) { + for (unsigned int i = 0; i < len; ++i) { + a[i * aWidth] += b[i * bWidth] * c; + } +} +} // namespace namespace paddle { +template <> +void MulOp(CpuSparseMatrix& out, + const CpuMatrix& a, + const CpuMatrix& b, + real scaleAB, + real scaleT) { + /// todo(tianbing), clean the code + CHECK(!out.isTransposed()) << "Not supported"; + CHECK_EQ(out.getValueType(), FLOAT_VALUE); + + const real* A = a.getData(); + const real* B = b.getData(); + real* C = out.getValue(); + int* rows = out.getRows(); + int* cols = out.getCols(); + size_t height = out.getHeight(); + size_t width = out.getWidth(); + if (scaleT == 0) { + out.zeroMem(); + } + + if (!a.isTransposed() && !b.isTransposed()) { + size_t m = a.getWidth(); + CHECK_EQ(b.getHeight(), m); + CHECK_EQ(a.getHeight(), height); + CHECK_EQ(b.getWidth(), width); + if (out.getFormat() == SPARSE_CSC) { + for (size_t i = 0; i < width; i++) { + size_t start = out.getColStartIdx(i); + size_t end = out.getColStartIdx(i + 1); + for (size_t j = start; j < end; j++) { + real sum = 0; + size_t rowIdx = rows[j]; + for (size_t k = 0; k < m; k++) { + sum += A[rowIdx * m + k] * B[k * width + i]; + } + C[j] = scaleAB * sum + scaleT * C[j]; + } + } + } else { + for (size_t i = 0; i < height; i++) { + size_t start = out.getRowStartIdx(i); + size_t end = out.getRowStartIdx(i + 1); + for (size_t j = start; j < end; j++) { + real sum = 0; + size_t colIdx = cols[j]; + for (size_t k = 0; k < m; k++) { + sum += A[i * m + k] * B[k * width + colIdx]; + } + C[j] = scaleAB * sum + scaleT * C[j]; + } + } + } + } else if (a.isTransposed() && !b.isTransposed()) { + size_t m = a.getHeight(); + CHECK_EQ(m, b.getHeight()); + CHECK_EQ(b.getWidth(), width); + CHECK_EQ(a.getWidth(), height); + + if (out.getFormat() == SPARSE_CSC) { + for (size_t i = 0; i < width; i++) { + size_t start = out.getColStartIdx(i); + size_t end = out.getColStartIdx(i + 1); + for (size_t j = start; j < end; j++) { + real sum = 0; + size_t rowIdx = rows[j]; + for (size_t k = 0; k < m; k++) { + sum += A[k * height + rowIdx] * B[k * width + i]; + } + C[j] = scaleAB * sum + scaleT * C[j]; + } + } + } else { + for (size_t i = 0; i < height; i++) { + int start = out.getRowStartIdx(i); + int end = out.getRowStartIdx(i + 1); + for (int j = start; j < end; j++) { + real sum = 0; + size_t colIdx = cols[j]; + for (size_t k = 0; k < m; k++) { + sum += A[k * height + i] * B[k * width + colIdx]; + } + C[j] = scaleAB * sum + scaleT * C[j]; + } + } + } + } else if (!a.isTransposed() && b.isTransposed()) { + size_t m = a.getWidth(); + CHECK_EQ(b.getWidth(), m); + CHECK_EQ(a.getHeight(), height); + CHECK_EQ(b.getHeight(), width); + if (out.getFormat() == SPARSE_CSR) { + for (size_t i = 0; i < height; i++) { + size_t start = out.getRowStartIdx(i); + size_t end = out.getRowStartIdx(i + 1); + for (size_t j = start; j < end; j++) { + real sum = 0; + size_t colIdx = cols[j]; + for (size_t k = 0; k < m; k++) { + sum += A[i * m + k] * B[colIdx * m + k]; + } + C[j] = scaleAB * sum + scaleT * C[j]; + } + } + } else { + LOG(FATAL) << "Not supported csc format " + "when a is not trans and b is trans"; + } + } else { + LOG(FATAL) << "Not supported"; + } +} + +template <> +void MulOp(CpuMatrix& out, + const CpuMatrix& a, + const CpuMatrix& b, + real scaleAB, + real scaleT) { + /// todo(tianbing), clean the code + CHECK(!out.isTransposed()) << "Not supported"; + CBLAS_TRANSPOSE aTrans = CblasNoTrans; + size_t aRow = a.getHeight(); + size_t aCol = a.getWidth(); + CBLAS_TRANSPOSE bTrans = CblasNoTrans; + size_t bRow = b.getHeight(); + size_t bCol = b.getWidth(); + if (a.isTransposed()) { + aTrans = CblasTrans; + aRow = a.getWidth(); + aCol = a.getHeight(); + } + if (b.isTransposed()) { + bTrans = CblasTrans; + bRow = b.getWidth(); + bCol = b.getHeight(); + } + + /// C = A * B, for matrix format + CHECK_EQ(aCol, bRow); + CHECK_EQ(aRow, out.getHeight()); + CHECK_EQ(bCol, out.getWidth()); + + const real* A = a.getData(); + const real* B = b.getData(); + real* C = out.getData(); + + int M = out.getHeight(); + int N = out.getWidth(); + int K = aCol; + int lda = a.getStride(); + int ldb = b.getStride(); + int ldc = out.getStride(); + + GEMM(aTrans, bTrans, M, N, K, scaleAB, A, lda, B, ldb, scaleT, C, ldc); + + VLOG(2) << " A[0]=" << A[0] << " A[1]=" << A[1] << " B[0]=" << B[0] + << " B[1]=" << B[1] << " C[0]=" << C[0] << " C[1]=" << C[1]; +} + +static ThreadLocal> threadLocalColArray; + +template <> +void MulOp(CpuMatrix& out, + const CpuSparseMatrix& a, + const CpuMatrix& b, + real scaleAB, + real scaleT) { + /// todo(tianbing), clean the code + CHECK(!out.isTransposed()) << "Not supported"; + CHECK(!b.isTransposed()) << "Not supported"; + CHECK(scaleT == 0 || scaleT == 1) << "Not support"; + CHECK_EQ(scaleAB, static_cast(1.0)) << "Not supported"; + CHECK_EQ(a.getFormat(), SPARSE_CSR) << "Not supported"; + + const real* B = b.getData(); + real* C = out.getData(); + size_t height = out.getHeight(); + size_t width = out.getWidth(); + int* cols = a.getCols(); + real* values = a.getValue(); + + if (scaleT == 0) { + out.zeroMem(); + } + + if (!a.isTransposed()) { + size_t m = a.getWidth(); + CHECK_EQ(b.getHeight(), m); + CHECK_EQ(a.getHeight(), height); + CHECK_EQ(b.getWidth(), width); + + if (a.getValueType() == NO_VALUE) { + if (width % 32 == 0) { // use libaddto + CHECK_EQ((size_t)B % 32, 0UL); + CHECK_EQ((size_t)C % 32, 0UL); + auto& colArray = *threadLocalColArray; + for (size_t i = 0; i < a.getHeight(); ++i) { + const int start = a.getRowStartIdx(i); + const int end = a.getRowStartIdx(i + 1); + size_t colNum = end - start; + colArray.resize(colNum); + for (int j = 0; j < end - start; ++j) { + colArray[j] = const_cast(b).getRow(cols[j + start]); + } + simd::batchAddTo(out.getRow(i), &colArray[0], colNum, width); + } + + } else { + for (size_t i = 0; i < a.getHeight(); ++i) { + const int start = a.getRowStartIdx(i); + const int end = a.getRowStartIdx(i + 1); + for (int j = start; j < end; ++j) { + vecAddTo(out.getRow(i), + const_cast(b).getRow(cols[j]), + width); + } + } + } + } else if (a.getValueType() == FLOAT_VALUE) { + for (size_t i = 0; i < a.getHeight(); ++i) { + const int start = a.getRowStartIdx(i); + const int end = a.getRowStartIdx(i + 1); + for (int j = start; j < end; ++j) { + vecAddTo(out.getRow(i), + const_cast(b).getRow(cols[j]), + values[j], + width); + } + } + } + } else /*if (a->isTransposed())*/ { + size_t m = a.getHeight(); + CHECK_EQ(b.getHeight(), m); + CHECK_EQ(a.getWidth(), height); + CHECK_EQ(b.getWidth(), width); + if (a.getValueType() == NO_VALUE) { + if (width % 32 == 0) { // use libaddto + CHECK_EQ((size_t)B % 32, 0UL); + CHECK_EQ((size_t)C % 32, 0UL); + for (size_t i = 0; i < a.getHeight(); ++i) { + const int start = a.getRowStartIdx(i); + const int end = a.getRowStartIdx(i + 1); + for (int j = start; j < end; ++j) { + simd::addTo(out.getRow(cols[j]), + const_cast(b).getRow(i), + width); + } + } + + } else { + for (size_t i = 0; i < a.getHeight(); ++i) { + const int start = a.getRowStartIdx(i); + const int end = a.getRowStartIdx(i + 1); + for (int j = start; j < end; ++j) { + vecAddTo(out.getRow(cols[j]), + const_cast(b).getRow(i), + width); + } + } + } + } else if (a.getValueType() == FLOAT_VALUE) { + for (size_t i = 0; i < a.getHeight(); ++i) { + const int start = a.getRowStartIdx(i); + const int end = a.getRowStartIdx(i + 1); + for (int j = start; j < end; ++j) { + vecAddTo(out.getRow(cols[j]), + const_cast(b).getRow(i), + values[j], + width); + } + } + } + } +} + +template <> +void MulOp(CpuMatrix& out, + const CpuMatrix& a, + const CpuSparseMatrix& b, + real scaleAB, + real scaleT) { + /// todo(tianbing), clean the code + CHECK(!out.trans_) << "Not supported"; + CHECK(!a.isTransposed()) << "Not supported"; + CHECK(scaleT == 0 || scaleT == 1); + CHECK_EQ(scaleAB, static_cast(1.0)); + + real* A = const_cast(a.getData()); + real* B = const_cast(b.getValue()); + real* C = out.getData(); + int* rows = b.getRows(); + int* cols = b.getCols(); + + if (scaleT == 0) { + out.zeroMem(); + } + /// todo(tianbing), clean the code + if (b.getFormat() == SPARSE_CSC) { + if (!b.isTransposed()) { + size_t m = a.getWidth(); + CHECK_EQ(b.getHeight(), m); + CHECK_EQ(a.getHeight(), out.height_); + CHECK_EQ(b.getWidth(), out.width_); + + if (b.getValueType() == NO_VALUE) { + for (size_t j = 0; j < b.getWidth(); ++j) { + int start = b.getColStartIdx(j); + int end = b.getColStartIdx(j + 1); + for (int i = start; i < end; ++i) { + colVecAddTo( + C + j, A + rows[i], out.height_, out.width_, a.getWidth()); + } + } + } else if (b.getValueType() == FLOAT_VALUE) { + for (size_t j = 0; j < b.getWidth(); ++j) { + int start = b.getColStartIdx(j); + int end = b.getColStartIdx(j + 1); + for (int i = start; i < end; ++i) { + colVecAddTo(C + j, + A + rows[i], + B[i], + out.height_, + out.width_, + a.getWidth()); + } + } + } + } else /*if (b.isTransposed())*/ { + size_t m = a.getWidth(); + CHECK_EQ(b.getHeight(), out.width_); + CHECK_EQ(a.getHeight(), out.height_); + CHECK_EQ(b.getWidth(), m); + if (b.getValueType() == NO_VALUE) { + for (size_t i = 0; i < b.getWidth(); ++i) { + int start = b.getColStartIdx(i); + int end = b.getColStartIdx(i + 1); + for (int j = start; j < end; ++j) { + colVecAddTo( + C + rows[j], A + i, out.height_, out.width_, a.getWidth()); + } + } + } else if (b.getValueType() == FLOAT_VALUE) { + for (size_t i = 0; i < b.getWidth(); ++i) { + int start = b.getColStartIdx(i); + int end = b.getColStartIdx(i + 1); + for (int j = start; j < end; ++j) { + colVecAddTo(C + rows[j], + A + i, + B[j], + out.height_, + out.width_, + a.getWidth()); + } + } + } + } + } else { + if (!b.isTransposed()) { + size_t m = a.getWidth(); + CHECK_EQ(b.getHeight(), m); + CHECK_EQ(a.getHeight(), out.height_); + CHECK_EQ(b.getWidth(), out.width_); + + if (b.getValueType() == NO_VALUE) { + for (size_t j = 0; j < b.getHeight(); ++j) { + int start = b.getRowStartIdx(j); + int end = b.getRowStartIdx(j + 1); + for (int i = start; i < end; ++i) { + colVecAddTo( + C + cols[i], A + j, out.height_, out.width_, a.getWidth()); + } + } + } else if (b.getValueType() == FLOAT_VALUE) { + for (size_t j = 0; j < b.getHeight(); ++j) { + int start = b.getRowStartIdx(j); + int end = b.getRowStartIdx(j + 1); + for (int i = start; i < end; ++i) { + colVecAddTo(C + cols[i], + A + j, + B[i], + out.height_, + out.width_, + a.getWidth()); + } + } + } + } else /*if (b.isTransposed())*/ { + size_t m = a.getWidth(); + CHECK_EQ(b.getHeight(), out.width_); + CHECK_EQ(a.getHeight(), out.height_); + CHECK_EQ(b.getWidth(), m); + if (b.getValueType() == NO_VALUE) { + for (size_t i = 0; i < b.getHeight(); ++i) { + int start = b.getRowStartIdx(i); + int end = b.getRowStartIdx(i + 1); + for (int j = start; j < end; ++j) { + colVecAddTo( + C + i, A + cols[j], out.height_, out.width_, a.getWidth()); + } + } + } else if (b.getValueType() == FLOAT_VALUE) { + for (size_t i = 0; i < b.getHeight(); ++i) { + int start = b.getRowStartIdx(i); + int end = b.getRowStartIdx(i + 1); + for (int j = start; j < end; ++j) { + colVecAddTo(C + i, + A + cols[j], + B[j], + out.height_, + out.width_, + a.getWidth()); + } + } + } + } + } +} /** * mul operator * out = scaleT * out + scaleAB*(in1 * in2) * - * \param outputs[0] output matrix, N * M - * \param inputs[0] first input (sparse) matrix, N * K - * \param inputs[1] second input matrix, K * M (non-transpose) + * \param outputs[0] output matrix, M * N + * \param inputs[0] first input (sparse) matrix, M * K (if non-trans) + * \param inputs[1] second input matrix, K * N (if non-trans) */ template class MulFunc : public FunctionBase { @@ -33,19 +488,23 @@ class MulFunc : public FunctionBase { } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - /// todo(tianbing), add more checks - CHECK_EQ((size_t)1, inputs.size()); - CHECK_EQ((size_t)2, outputs.size()); + CHECK_EQ((size_t)2, inputs.size()); + CHECK_EQ((size_t)1, outputs.size()); CHECK(inputs[0].data() && inputs[1].data() && outputs[0].data()); CHECK_EQ(inputs[0].shape().ndims(), (size_t)2); CHECK_EQ(inputs[1].shape().ndims(), (size_t)2); CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO); - CHECK(inputs[0].isSparse()) << "SparseMatrix requried here"; - const auto in1_mat = inputs[0].sparse().SparseMatrix(); + auto in1_mat = inputs[0].matrix(); + if (inputs[0].isSparseArg()) { + in1_mat = inputs[0].sparse().SparseMatrix(); + } + auto in2_mat = inputs[1].matrix(); + if (inputs[1].isSparseArg()) { + in2_mat = inputs[1].sparse().SparseMatrix(); + } auto out_mat = outputs[0].matrix(); - const auto in2_mat = inputs[1].matrix(); MulOp(out_mat, in1_mat, in2_mat, scaleAB_, scaleT_); } @@ -54,6 +513,7 @@ class MulFunc : public FunctionBase { real scaleT_; }; +REGISTER_TYPED_FUNC(MulOp, CPU, MulFunc); #ifndef PADDLE_ONLY_CPU REGISTER_TYPED_FUNC(MulOp, GPU, MulFunc); #endif diff --git a/paddle/function/MulOp.h b/paddle/function/MulOp.h index bcea1864026b27..f3699f8c78cda7 100644 --- a/paddle/function/MulOp.h +++ b/paddle/function/MulOp.h @@ -19,6 +19,40 @@ limitations under the License. */ #include "paddle/math/SparseMatrix.h" namespace paddle { +template +void MulOp(CpuMatrix& out, + const CpuMatrix& a, + const CpuMatrix& b, + real scaleAB, + real scaleT); + +template +void MulOp(CpuMatrix& out, + const CpuSparseMatrix& a, + const CpuMatrix& b, + real scaleAB, + real scaleT); + +template +void MulOp(CpuMatrix& out, + const CpuMatrix& a, + const CpuSparseMatrix& b, + real scaleAB, + real scaleT); + +template +void MulOp(CpuSparseMatrix& out, + const CpuMatrix& a, + const CpuMatrix& b, + real scaleAB, + real scaleT); + +template +void MulOp(GpuMatrix& out, + const GpuMatrix& a, + const GpuMatrix& b, + real scaleAB, + real scaleT); template void MulOp(GpuMatrix& out, @@ -27,4 +61,11 @@ void MulOp(GpuMatrix& out, real scaleAB, real scaleT); +template +void MulOp(GpuMatrix& out, + const GpuMatrix& a, + const GpuSparseMatrix& b, + real scaleAB, + real scaleT); + } // namespace paddle diff --git a/paddle/function/MulOpGpu.cu b/paddle/function/MulOpGpu.cu index db716c1e46b4e1..73d788a4743326 100644 --- a/paddle/function/MulOpGpu.cu +++ b/paddle/function/MulOpGpu.cu @@ -20,6 +20,65 @@ limitations under the License. */ namespace paddle { /** * out = scale_t * out + scale_ab * (a * b) + * out : output matrix, M * N + */ +template <> +void MulOp(GpuMatrix& out, + const GpuMatrix& a, + const GpuMatrix& b, + real scale_ab, + real scale_t) { + CHECK(!out.isTransposed()) << "Not supported"; + + if (!a.isTransposed() && !b.isTransposed()) { + /// a : M * K, b: K * N + CHECK_EQ(out.width_, b.width_); + CHECK_EQ(out.height_, a.height_); + CHECK_EQ(a.width_, b.height_); + } else if (a.isTransposed() && !b.isTransposed()) { + /// a : K * M, b : K * N + CHECK_EQ(out.width_, b.width_); + CHECK_EQ(out.height_, a.width_); + CHECK_EQ(a.height_, b.height_); + } else if (!a.isTransposed() && b.isTransposed()) { + /// a: M * K, b : N * K + CHECK_EQ(out.width_, b.height_); + CHECK_EQ(out.height_, a.height_); + CHECK_EQ(a.width_, b.width_); + } else { + LOG(FATAL) << "Is not supported"; + } + + real* a_data = a.data_; + real* b_data = b.data_; + real* out_data = out.data_; + int dim_m = out.getHeight(); + int dim_n = out.getWidth(); + int dim_k = !a.isTransposed() ? a.width_ : a.height_; + int lda = a.getStride(); + int ldb = b.getStride(); + int ldc = out.getStride(); + hl_trans_op_t trans_a = !a.isTransposed() ? HPPL_OP_N : HPPL_OP_T; + hl_trans_op_t trans_b = !b.isTransposed() ? HPPL_OP_N : HPPL_OP_T; + + hl_matrix_mul(a_data, + trans_a, + b_data, + trans_b, + out_data, + dim_m, + dim_n, + dim_k, + scale_ab, + scale_t, + lda, + ldb, + ldc); +} + +/** + * out = scale_t * out + scale_ab * (a * b) + * out : M * N */ template <> void MulOp(GpuMatrix& out, @@ -32,12 +91,15 @@ void MulOp(GpuMatrix& out, CHECK(b.useGpu_ == true) << "Matrix type are not equal"; CHECK(!out.trans_ && !b.trans_) << "not supported"; if (!a.trans_) { + /// a: M * K, b: K * N CHECK(out.width_ == b.width_ && out.height_ == a.height_ - && a.width_ == b.height_) << "Matrix dimensions are not equal"; + && a.width_ == b.height_) << "Matrix dimensions are not equal"; } else { + /// a: K * M, transpose, b: K * N CHECK(out.width_ == b.width_ && out.height_ == a.width_ - && a.height_ == b.height_) << "Matrix dimensions are not equal"; + && a.height_ == b.height_) << "Matrix dimensions are not equal"; } + hl_trans_op_t a_trans = a.trans_ ? HPPL_OP_T : HPPL_OP_N; hl_sparse_matrix_s a_data = a.sMatrix_.get(); real* b_data = b.data_; @@ -54,4 +116,58 @@ void MulOp(GpuMatrix& out, scale_t); } +/** + * out = scale_t * out + scale_ab * (a * b) + * out : M * N + */ +template <> +void MulOp(GpuMatrix& out, + const GpuMatrix& a, + const GpuSparseMatrix& b, + real scale_ab, + real scale_t) { + CHECK(out.isContiguous()); + CHECK(a.isContiguous()); + CHECK(a.useGpu_ == true) << "Matrix type are not equal"; + + hl_sparse_matrix_s b_data = b.sMatrix_.get(); + real* a_data = a.data_; + real* out_data = out.data_; + hl_trans_op_t trans_b = b.trans_ ? HPPL_OP_T : HPPL_OP_N; + if (!b.trans_) { + /// a : M * K, b : K * N + CHECK(out.width_ == b.width_ && + out.height_ == a.height_ && a.width_ == b.height_) + << "Matrix dimensions are not equal"; + } else { + /// a : M * K, b : N * K, transpose + CHECK(out.width_ == b.height_ && + out.height_ == a.height_ && a.width_ == b.width_) + << "Matrix dimensions are not equal"; + } + if (b.format_ == SPARSE_CSC) { + hl_matrix_dense_mul_csc(a_data, + HPPL_OP_N, + b_data, + trans_b, + out_data, + out.height_, + out.width_, + a.width_, + scale_ab, + scale_t); + } else { + hl_matrix_dense_mul_csr(a_data, + HPPL_OP_N, + b_data, + trans_b, + out_data, + out.height_, + out.width_, + a.width_, + scale_ab, + scale_t); + } +} + } // namespace paddle diff --git a/paddle/function/MulOpTest.cpp b/paddle/function/MulOpTest.cpp index bc1fa9f607a575..ce9d37d664710c 100644 --- a/paddle/function/MulOpTest.cpp +++ b/paddle/function/MulOpTest.cpp @@ -22,31 +22,41 @@ using namespace paddle; // NOLINT void testSpMatrixMul(int M, int N, int K, real rate, real scale1, real scale2) { /// todo(tianbing) check CPU/GPU - const auto gpuFunc = FunctionBase::funcRegistrar_.createByType("MulOP-GPU"); + const auto gpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-GPU"); gpuFunc->init(FuncConfig().set("scaleAB", scale1).set("scaleT", scale2)); - int nnz = M * K * rate; - auto gpuA = std::make_shared(M, K, nnz); - const auto gpuB = std::make_shared(K, N); - const auto gpuOut = std::make_shared(M, N); + int nnz = M * N * rate; + MatrixPtr cpuA = std::make_shared(M, K); + MatrixPtr cpuB = std::make_shared(N, K); + MatrixPtr cpuC(new CpuSparseMatrix(M, N, nnz)); - gpuA->randomizeUniform(); - gpuB->randomizeUniform(); - gpuOut->randomizeUniform(); + MatrixPtr gpuA = std::make_shared(M, K); + MatrixPtr gpuB = std::make_shared(N, K); + MatrixPtr gpuC(new GpuSparseMatrix(M, N, nnz)); + + cpuA->randomizeUniform(); + cpuB->randomizeUniform(); + cpuC->randomizeUniform(); + + hl_stream_t stream(HPPL_STREAM_3); + gpuA->copyFrom(*cpuA, stream); + gpuB->copyFrom(*cpuB, stream); + gpuC->copyFrom(*cpuC, stream); + hl_stream_synchronize(stream); BufferArgs inputs; BufferArgs outputs; - inputs.addArg(*gpuA); - inputs.addArg(*gpuB); - outputs.addArg(*gpuOut); + inputs.addArg(*gpuA->getTranspose()); + inputs.addArg(*gpuB->getTranspose()); + outputs.addArg(*gpuC, ASSIGN_TO); gpuFunc->calc(inputs, outputs); } TEST(SMatrix, sMatrixMul) { for (auto M : {1, 40, 128, 200}) { - for (auto N : {100, 2000, 20480}) { - for (auto K : {100, 512, 1024}) { + for (auto N : {100}) { + for (auto K : {100}) { /// todo(tianbing), add scaleAB and scaleT VLOG(3) << " M=" << M << " N=" << N << " K=" << K; testSpMatrixMul(M, N, K, 0.05, 1, 1); From 2df8eec5204506ddfb7f55e8c88e0271fbf9bf3b Mon Sep 17 00:00:00 2001 From: xutianbing Date: Mon, 16 Jan 2017 20:30:27 -0800 Subject: [PATCH 097/370] Pass Unit test for GpuMatrix::mul(GpuMatrix, GpuMatrix) and CpuMatrix::mul(CpuMatrix, CpuMatrix) --- paddle/function/BufferArg.cpp | 6 +-- paddle/function/BufferArg.h | 17 +++---- paddle/function/MulOp.cpp | 12 ++--- paddle/function/MulOp.h | 7 +++ paddle/function/MulOpGpu.cu | 9 ++++ paddle/function/MulOpTest.cpp | 85 +++++++++++++++++++++++------------ 6 files changed, 88 insertions(+), 48 deletions(-) diff --git a/paddle/function/BufferArg.cpp b/paddle/function/BufferArg.cpp index 4064daf4159e22..5d595deb12c6c8 100644 --- a/paddle/function/BufferArg.cpp +++ b/paddle/function/BufferArg.cpp @@ -32,16 +32,14 @@ const SparseMatrixArg& BufferArg::sparse() const { SparseMatrixArg::SparseMatrixArg(const CpuSparseMatrix& sparse, ArgType argType) : BufferArg(sparse, argType), row_(reinterpret_cast(sparse.getRows()), VALUE_TYPE_INT32), - col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32), - trans_(const_cast(sparse).getTranspose()) { + col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32) { bufferType_ = TENSOR_SPARSE; } SparseMatrixArg::SparseMatrixArg(const GpuSparseMatrix& sparse, ArgType argType) : BufferArg(sparse, argType), row_(reinterpret_cast(sparse.getRows()), VALUE_TYPE_INT32), - col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32), - trans_(const_cast(sparse).getTranspose()) { + col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32) { bufferType_ = TENSOR_SPARSE; } diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index 1f86f49911c484..2da1115ec968cc 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -98,7 +98,8 @@ class BufferArg { const_cast(reinterpret_cast(matrix.getData()))), valueType_(DataType::value), shape_(2), - argType_(argType) { + argType_(argType), + trans_(matrix.isTransposed()) { bufferType_ = TENSOR_NORMAL; shape_.setDim(0, matrix.getHeight()); shape_.setDim(1, matrix.getWidth()); @@ -111,7 +112,8 @@ class BufferArg { const_cast(reinterpret_cast(matrix.getData()))), valueType_(DataType::value), shape_(shape), - argType_(argType) { + argType_(argType), + trans_(matrix.isTransposed()) { bufferType_ = TENSOR_NORMAL; CHECK_EQ(matrix.getElementCnt(), shape.getElements()); } @@ -143,7 +145,7 @@ class BufferArg { // CHECK(deviceType_ == DType); CHECK_EQ((size_t)2, shape_.ndims()); return typename Tensor::Matrix( - reinterpret_cast(buf_), shape_[0], shape_[1]); + reinterpret_cast(buf_), shape_[0], shape_[1], trans_); } template @@ -179,6 +181,7 @@ class BufferArg { TensorShape shape_; BufferType bufferType_{TENSOR_UNKNOWN}; ArgType argType_{UNSPECIFIED}; + bool trans_{false}; // leading dimensions. The size is dims_.size() // Dims lds_; }; @@ -271,15 +274,13 @@ class SparseMatrixArg : public BufferArg { size_t nnz, SparseDataFormat format, SparseDataType type, - bool trans = false, ArgType argType = UNSPECIFIED) : BufferArg(buf, valueType, shape, argType), row_(row), col_(col), nnz_(nnz), format_(format), - type_(type), - trans_(trans) { + type_(type) { bufferType_ = TENSOR_SPARSE; CHECK((valueType == VALUE_TYPE_FLOAT) || (valueType == VALUE_TYPE_DOUBLE)); CHECK_EQ(shape_.ndims(), (size_t)2); @@ -322,8 +323,6 @@ class SparseMatrixArg : public BufferArg { size_t nnz() const { return nnz_; } - bool isTranspose() const { return trans_; } - SparseDataFormat dataFormat() const { return format_; } SparseDataType dataType() const { return type_; } @@ -334,8 +333,6 @@ class SparseMatrixArg : public BufferArg { size_t nnz_; SparseDataFormat format_; SparseDataType type_; - /// todo(tianbing), move trans_ up to BufferArg - bool trans_; }; } // namespace paddle diff --git a/paddle/function/MulOp.cpp b/paddle/function/MulOp.cpp index 7d341182523cbb..1c593bb083e009 100644 --- a/paddle/function/MulOp.cpp +++ b/paddle/function/MulOp.cpp @@ -483,8 +483,8 @@ template class MulFunc : public FunctionBase { public: void init(const FuncConfig& config) override { - scaleAB_ = config.get("scaleAB"); - scaleT_ = config.get("scaleT"); + alpha_ = config.get("scaleAB"); + beta_ = config.get("scaleT"); } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { @@ -494,7 +494,7 @@ class MulFunc : public FunctionBase { CHECK_EQ(inputs[0].shape().ndims(), (size_t)2); CHECK_EQ(inputs[1].shape().ndims(), (size_t)2); CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); - CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO); + CHECK_EQ(outputs[0].getArgType(), ADD_TO); auto in1_mat = inputs[0].matrix(); if (inputs[0].isSparseArg()) { @@ -505,12 +505,12 @@ class MulFunc : public FunctionBase { in2_mat = inputs[1].sparse().SparseMatrix(); } auto out_mat = outputs[0].matrix(); - MulOp(out_mat, in1_mat, in2_mat, scaleAB_, scaleT_); + MulOp(out_mat, in1_mat, in2_mat, alpha_, beta_); } private: - real scaleAB_; - real scaleT_; + real alpha_; + real beta_; }; REGISTER_TYPED_FUNC(MulOp, CPU, MulFunc); diff --git a/paddle/function/MulOp.h b/paddle/function/MulOp.h index f3699f8c78cda7..b7b1f56af10375 100644 --- a/paddle/function/MulOp.h +++ b/paddle/function/MulOp.h @@ -68,4 +68,11 @@ void MulOp(GpuMatrix& out, real scaleAB, real scaleT); +template +void MulOp(GpuSparseMatrix& out, + const GpuMatrix& a, + const GpuMatrix& b, + real scaleAB, + real scaleT); + } // namespace paddle diff --git a/paddle/function/MulOpGpu.cu b/paddle/function/MulOpGpu.cu index 73d788a4743326..3691c7f3206126 100644 --- a/paddle/function/MulOpGpu.cu +++ b/paddle/function/MulOpGpu.cu @@ -170,4 +170,13 @@ void MulOp(GpuMatrix& out, } } +template <> +void MulOp(GpuSparseMatrix& out, + const GpuMatrix& a, + const GpuMatrix& b, + real scale_ab, + real scale_t) { +/// todo(tianbing), implement it +} + } // namespace paddle diff --git a/paddle/function/MulOpTest.cpp b/paddle/function/MulOpTest.cpp index ce9d37d664710c..3229193660ea03 100644 --- a/paddle/function/MulOpTest.cpp +++ b/paddle/function/MulOpTest.cpp @@ -16,50 +16,79 @@ limitations under the License. */ #include "FunctionTest.h" #include "paddle/math/Matrix.h" #include "paddle/math/SparseMatrix.h" +#include "paddle/math/tests/test_matrixUtil.h" #include "paddle/testing/TestUtil.h" using namespace paddle; // NOLINT -void testSpMatrixMul(int M, int N, int K, real rate, real scale1, real scale2) { - /// todo(tianbing) check CPU/GPU +/** + * C = alpha * C + beta * (A * B) + */ +void testMatrixMul(bool transa, bool transb, int dimM, int dimN, int dimK) { + real alpha = 1.5; + real beta = 2.0; + + const auto cpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-CPU"); + cpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); const auto gpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-GPU"); - gpuFunc->init(FuncConfig().set("scaleAB", scale1).set("scaleT", scale2)); + gpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); - int nnz = M * N * rate; - MatrixPtr cpuA = std::make_shared(M, K); - MatrixPtr cpuB = std::make_shared(N, K); - MatrixPtr cpuC(new CpuSparseMatrix(M, N, nnz)); + int heightA = (transa == false) ? dimM : dimK; + int widthA = (transa == false) ? dimK : dimM; + int heightB = (transb == false) ? dimK : dimN; + int widthB = (transb == false) ? dimN : dimK; + int heightC = dimM; + int widthC = dimN; - MatrixPtr gpuA = std::make_shared(M, K); - MatrixPtr gpuB = std::make_shared(N, K); - MatrixPtr gpuC(new GpuSparseMatrix(M, N, nnz)); + auto cpuA = std::make_shared(heightA, widthA, transa); + auto cpuB = std::make_shared(heightB, widthB, transb); + auto cpuC = std::make_shared(heightC, widthC); + auto gpuA = std::make_shared(heightA, widthA, transa); + auto gpuB = std::make_shared(heightB, widthB, transb); + auto gpuC = std::make_shared(heightC, widthC); cpuA->randomizeUniform(); cpuB->randomizeUniform(); cpuC->randomizeUniform(); + gpuA->copyFrom(*cpuA); + gpuB->copyFrom(*cpuB); + gpuC->copyFrom(*cpuC); - hl_stream_t stream(HPPL_STREAM_3); - gpuA->copyFrom(*cpuA, stream); - gpuB->copyFrom(*cpuB, stream); - gpuC->copyFrom(*cpuC, stream); - hl_stream_synchronize(stream); + BufferArgs cpuInputs; + BufferArgs cpuOutputs; + cpuInputs.addArg(*cpuA); + cpuInputs.addArg(*cpuB); + cpuOutputs.addArg(*cpuC, ADD_TO); + cpuFunc->calc(cpuInputs, cpuOutputs); - BufferArgs inputs; - BufferArgs outputs; - inputs.addArg(*gpuA->getTranspose()); - inputs.addArg(*gpuB->getTranspose()); - outputs.addArg(*gpuC, ASSIGN_TO); + BufferArgs gpuInputs; + BufferArgs gpuOutputs; + gpuInputs.addArg(*gpuA); + gpuInputs.addArg(*gpuB); + gpuOutputs.addArg(*gpuC, ADD_TO); + gpuFunc->calc(gpuInputs, gpuOutputs); - gpuFunc->calc(inputs, outputs); + autotest::TensorCheckErr(*cpuC, *gpuC); } -TEST(SMatrix, sMatrixMul) { - for (auto M : {1, 40, 128, 200}) { - for (auto N : {100}) { - for (auto K : {100}) { - /// todo(tianbing), add scaleAB and scaleT - VLOG(3) << " M=" << M << " N=" << N << " K=" << K; - testSpMatrixMul(M, N, K, 0.05, 1, 1); +TEST(Matrix, mul) { + for (auto transa : {false, true}) { + for (auto transb : {false, true}) { + for (auto dimM : {1, 10, 100}) { + for (auto dimN : {1, 10}) { + for (auto dimK : {8}) { + if (true == transa && true == transb) { + continue; + } + VLOG(3) << setiosflags(std::ios::left) << std::setfill(' ') + << " transa=" << transa << " transb=" << transb + << " dimM=" << std::setw(5) << dimM + << " dimN=" << std::setw(5) << dimN + << " dimK=" << std::setw(5) << dimK; + + testMatrixMul(transa, transb, dimM, dimN, dimK); + } + } } } } From 1ca2846ef688bfc532918e9e977eb4b519f3c4e8 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Tue, 17 Jan 2017 21:50:57 -0800 Subject: [PATCH 098/370] Pass unit test for CpuMatrix::mul(CpuMatrix, CpuSparseMatrix) and GpuMatrix::mul(CpuMatrix, GpuSparseMatrix) --- paddle/function/BufferArg.cpp | 12 ++- paddle/function/BufferArg.h | 27 +++---- paddle/function/MulOp.cpp | 50 +++++++++++-- paddle/function/MulOp.h | 2 + paddle/function/MulOpTest.cpp | 134 ++++++++++++++++++++++++++++++++++ 5 files changed, 198 insertions(+), 27 deletions(-) diff --git a/paddle/function/BufferArg.cpp b/paddle/function/BufferArg.cpp index 5d595deb12c6c8..39773c76280ba3 100644 --- a/paddle/function/BufferArg.cpp +++ b/paddle/function/BufferArg.cpp @@ -32,14 +32,22 @@ const SparseMatrixArg& BufferArg::sparse() const { SparseMatrixArg::SparseMatrixArg(const CpuSparseMatrix& sparse, ArgType argType) : BufferArg(sparse, argType), row_(reinterpret_cast(sparse.getRows()), VALUE_TYPE_INT32), - col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32) { + col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32), + /// todo(tianbing), make sure how to get NNZ + nnz_(sparse.getElementCnt()), + format_(sparse.getFormat()), + type_(sparse.getValueType()) { bufferType_ = TENSOR_SPARSE; } SparseMatrixArg::SparseMatrixArg(const GpuSparseMatrix& sparse, ArgType argType) : BufferArg(sparse, argType), row_(reinterpret_cast(sparse.getRows()), VALUE_TYPE_INT32), - col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32) { + col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32), + /// todo(tianbing), make sure how to get NNZ + nnz_(sparse.getElementCnt()), + format_(sparse.getFormat()), + type_(sparse.getValueType()) { bufferType_ = TENSOR_SPARSE; } diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index 2da1115ec968cc..eac3fe4420369b 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -30,13 +30,6 @@ enum BufferType { TENSOR_SPARSE = 4 }; -enum SparseDataType { - SPARSE_NO_VALUE = 0, // do not need value pointer, all values are 1 - SPARSE_FLOAT_VALUE = 1 -}; - -enum SparseDataFormat { SPARSE_CSR_FORMAT = 0, SPARSE_CSC_FORMAT = 1 }; - class BufferArg; class SequenceArg; class SparseMatrixArg; @@ -272,8 +265,8 @@ class SparseMatrixArg : public BufferArg { const BufferArg& row, const BufferArg& col, size_t nnz, - SparseDataFormat format, - SparseDataType type, + SparseFormat format, + SparseValueType type, ArgType argType = UNSPECIFIED) : BufferArg(buf, valueType, shape, argType), row_(row), @@ -286,9 +279,9 @@ class SparseMatrixArg : public BufferArg { CHECK_EQ(shape_.ndims(), (size_t)2); CHECK_EQ(row_.shape().ndims(), (size_t)1); CHECK_EQ(col_.shape().ndims(), (size_t)1); - if (format == SPARSE_CSR_FORMAT) { + if (format == SPARSE_CSR) { CHECK_EQ(nnz, col.shape()[0]); - } else if (format == SPARSE_CSC_FORMAT) { + } else if (format == SPARSE_CSC) { CHECK_EQ(nnz, row.shape()[0]); } } @@ -310,8 +303,8 @@ class SparseMatrixArg : public BufferArg { shape_[0], shape_[1], nnz_, - static_cast(type_), - static_cast(format_), + type_, + format_, trans_); } @@ -323,16 +316,16 @@ class SparseMatrixArg : public BufferArg { size_t nnz() const { return nnz_; } - SparseDataFormat dataFormat() const { return format_; } + SparseFormat dataFormat() const { return format_; } - SparseDataType dataType() const { return type_; } + SparseValueType dataType() const { return type_; } private: BufferArg row_; BufferArg col_; size_t nnz_; - SparseDataFormat format_; - SparseDataType type_; + SparseFormat format_; + SparseValueType type_; }; } // namespace paddle diff --git a/paddle/function/MulOp.cpp b/paddle/function/MulOp.cpp index 1c593bb083e009..85f7f535dcfa42 100644 --- a/paddle/function/MulOp.cpp +++ b/paddle/function/MulOp.cpp @@ -13,6 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. */ #include "MulOp.h" +/// todo(tianbing), delete it +#include #include "paddle/math/MathFunctions.h" #include "paddle/math/SIMDFunctions.h" #include "paddle/utils/ThreadLocal.h" @@ -496,16 +498,48 @@ class MulFunc : public FunctionBase { CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); CHECK_EQ(outputs[0].getArgType(), ADD_TO); - auto in1_mat = inputs[0].matrix(); - if (inputs[0].isSparseArg()) { - in1_mat = inputs[0].sparse().SparseMatrix(); + /// todo(tianbing), support SparseMatrixArg for out_mat + auto out_mat = outputs[0].matrix(); + LOG(INFO) << "out_mat:"; + out_mat.print(std::cout); + if (!inputs[0].isSparseArg() && !inputs[1].isSparseArg()) { + LOG(INFO) << "in1_mat:"; + inputs[0].matrix().print(std::cout); + LOG(INFO) << "in2_mat:"; + inputs[1].matrix().print(std::cout); + MulOp(out_mat, + inputs[0].matrix(), + inputs[1].matrix(), + alpha_, + beta_); + return; } - auto in2_mat = inputs[1].matrix(); - if (inputs[1].isSparseArg()) { - in2_mat = inputs[1].sparse().SparseMatrix(); + + if (!inputs[0].isSparseArg() && inputs[1].isSparseArg()) { + LOG(INFO) << "in1_mat:"; + inputs[0].matrix().print(std::cout); + LOG(INFO) << "in2_mat:"; + inputs[1].sparse().SparseMatrix().print(std::cout); + MulOp(out_mat, + inputs[0].matrix(), + inputs[1].sparse().SparseMatrix(), + alpha_, + beta_); + return; + } + + if (inputs[0].isSparseArg() && !inputs[1].isSparseArg()) { + LOG(INFO) << "in1_mat:"; + inputs[0].sparse().SparseMatrix().print(std::cout); + LOG(INFO) << "in2_mat:"; + inputs[1].matrix().print(std::cout); + MulOp(out_mat, + inputs[0].sparse().SparseMatrix(), + inputs[1].matrix(), + alpha_, + beta_); + return; } - auto out_mat = outputs[0].matrix(); - MulOp(out_mat, in1_mat, in2_mat, alpha_, beta_); } private: diff --git a/paddle/function/MulOp.h b/paddle/function/MulOp.h index b7b1f56af10375..23bfd0fa932178 100644 --- a/paddle/function/MulOp.h +++ b/paddle/function/MulOp.h @@ -15,6 +15,8 @@ limitations under the License. */ #pragma once #include "Function.h" +/// todo(tianbing), delete +#include #include "paddle/math/Matrix.h" #include "paddle/math/SparseMatrix.h" diff --git a/paddle/function/MulOpTest.cpp b/paddle/function/MulOpTest.cpp index 3229193660ea03..fd02504678efd6 100644 --- a/paddle/function/MulOpTest.cpp +++ b/paddle/function/MulOpTest.cpp @@ -13,6 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. */ #include +/// todo(tianbing), delete +#include #include "FunctionTest.h" #include "paddle/math/Matrix.h" #include "paddle/math/SparseMatrix.h" @@ -72,6 +74,7 @@ void testMatrixMul(bool transa, bool transb, int dimM, int dimN, int dimK) { } TEST(Matrix, mul) { + LOG(INFO) << "test for dense = dense * dense matrix"; for (auto transa : {false, true}) { for (auto transb : {false, true}) { for (auto dimM : {1, 10, 100}) { @@ -93,3 +96,134 @@ TEST(Matrix, mul) { } } } + +struct MatrixPara { + size_t height; + size_t width; + bool trans; + bool sparse; + size_t nnz; + SparseFormat format; +}; + +/** + * C += A * B, A, C dense, B sparse + */ +void testDSparseDMatrix() { + real alpha = 1.0; + real beta = 1.0; + const auto cpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-CPU"); + cpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); + const auto gpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-GPU"); + gpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); + + constexpr size_t dimM = 2; + constexpr size_t dimN = 2; + constexpr size_t dimK = 3; + constexpr size_t NNZ = 3; + constexpr SparseFormat FORMAT = SPARSE_CSC; + + MatrixPara paraA{dimM, dimK, /*trans*/ false, /*sparse*/ false, NNZ, FORMAT}; + MatrixPara paraB{dimK, dimN, /*trans*/ false, /*sparse*/ true, NNZ, FORMAT}; + MatrixPara paraC{dimM, dimN, /*trans*/ false, /*sparse*/ false, NNZ, FORMAT}; + + auto cpuMatrixA = + Matrix::create(paraA.height, paraA.width, paraA.trans, false); + auto gpuMatrixA = + Matrix::create(paraA.height, paraA.width, paraA.trans, true); + auto cpuDenseA = + Matrix::create(paraA.height, paraA.width, paraA.trans, false); + CpuSparseMatrix cpuMatrixB(paraB.height, + paraB.width, + paraB.nnz, + FLOAT_VALUE, + paraB.format, + paraB.trans); + + GpuSparseMatrix gpuMatrixB(paraB.height, + paraB.width, + paraB.nnz, + FLOAT_VALUE, + paraB.format, + paraB.trans); + + auto cpuDenseB = + Matrix::create(paraB.height, paraB.width, paraB.trans, false); + auto cpuMatrixC = + Matrix::create(paraC.height, paraC.width, paraC.trans, false); + auto gpuMatrixC = + Matrix::create(paraC.height, paraC.width, paraC.trans, true); + auto cpuDenseC = + Matrix::create(paraC.height, paraC.width, paraC.trans, false); + auto gpuMatrixC_d2h = + Matrix::create(paraC.height, paraC.width, paraC.trans, false); + /*matrix init*/ + hl_stream_t stream(HPPL_STREAM_1); + cpuMatrixA->randomizeUniform(); + cpuMatrixB.randomizeUniform(); + cpuMatrixC->randomizeUniform(); + + gpuMatrixA->copyFrom(*cpuMatrixA, stream); + gpuMatrixB.copyFrom(cpuMatrixB, stream); + gpuMatrixC->copyFrom(*cpuMatrixC, stream); + + cpuDenseA->copyFrom(*cpuMatrixA); + cpuDenseB->copyFrom(cpuMatrixB); + cpuDenseC->copyFrom(*cpuMatrixC); + hl_stream_synchronize(stream); + + LOG(INFO) << "cpuMatrixA: "; + cpuMatrixA->print(std::cout); + LOG(INFO) << "cpuMatrixB: "; + (&cpuMatrixB)->print(std::cout); + LOG(INFO) << "cpuMatrixC: "; + cpuMatrixC->print(std::cout); + + LOG(INFO) << "cpuDenseA: "; + cpuDenseA->print(std::cout); + LOG(INFO) << "cpuDenseB: "; + cpuDenseB->print(std::cout); + LOG(INFO) << "cpuDenseC: "; + cpuDenseC->print(std::cout); + + LOG(INFO) << "gpuMatrixA: "; + gpuMatrixA->print(std::cout); + LOG(INFO) << "gpuMatrixB: "; + (&gpuMatrixB)->print(std::cout); + LOG(INFO) << "gpuMatrixC: "; + gpuMatrixC->print(std::cout); + + /*matrix mul*/ + BufferArgs cpuInputs; + BufferArgs cpuOutputs; + cpuInputs.addArg(*cpuMatrixA); + cpuInputs.addArg(cpuMatrixB); + cpuOutputs.addArg(*cpuMatrixC, ADD_TO); + cpuFunc->calc(cpuInputs, cpuOutputs); + + BufferArgs gpuInputs; + BufferArgs gpuOutputs; + gpuInputs.addArg(*gpuMatrixA); + gpuInputs.addArg(gpuMatrixB); + gpuOutputs.addArg(*gpuMatrixC, ADD_TO); + gpuFunc->calc(gpuInputs, gpuOutputs); + + BufferArgs denseInputs; + BufferArgs denseOutputs; + denseInputs.addArg(*cpuDenseA); + denseInputs.addArg(*cpuDenseB); + denseOutputs.addArg(*cpuDenseC, ADD_TO); + cpuFunc->calc(denseInputs, denseOutputs); + + gpuMatrixC_d2h->copyFrom(*gpuMatrixC, stream); + hl_stream_synchronize(stream); + /*check result*/ + // autotest::TensorCheckErr(*cpuMatrixC, *gpuMatrixC); + checkMatrixEqual(cpuMatrixC, cpuDenseC); + checkMatrixEqual(cpuMatrixC, gpuMatrixC_d2h); +} + +TEST(Matrix, SparseMatrixMul) { + LOG(INFO) << "test for dense = dense * sparse matrix"; + testDSparseDMatrix(); +} From 4751cc8f7e7f8fd00dc95aa117a767a3247f0796 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Wed, 18 Jan 2017 15:50:47 -0800 Subject: [PATCH 099/370] Pass unit test for SparseCpuMatrix::mul(CpuMatrix, CpuMatrix), SparseGpuMatrix::mul(GpuMatrix, GpuMatrix), CpuMatrix::mul(CpuSparseMatrix, CpuMatrix), and GpuMatrix::mul(GpuSparseMatrix, GpuMatrix) --- paddle/function/MulOp.cpp | 39 ++-- paddle/function/MulOpGpu.cu | 31 ++- paddle/function/MulOpTest.cpp | 301 ++++++++++++++++++++-------- paddle/math/SparseMatrix.cpp | 1 - paddle/math/tests/test_matrixUtil.h | 41 ++++ 5 files changed, 312 insertions(+), 101 deletions(-) diff --git a/paddle/function/MulOp.cpp b/paddle/function/MulOp.cpp index 85f7f535dcfa42..37f8808605e10c 100644 --- a/paddle/function/MulOp.cpp +++ b/paddle/function/MulOp.cpp @@ -498,15 +498,10 @@ class MulFunc : public FunctionBase { CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); CHECK_EQ(outputs[0].getArgType(), ADD_TO); - /// todo(tianbing), support SparseMatrixArg for out_mat auto out_mat = outputs[0].matrix(); - LOG(INFO) << "out_mat:"; - out_mat.print(std::cout); - if (!inputs[0].isSparseArg() && !inputs[1].isSparseArg()) { - LOG(INFO) << "in1_mat:"; - inputs[0].matrix().print(std::cout); - LOG(INFO) << "in2_mat:"; - inputs[1].matrix().print(std::cout); + /// matrix = matrix * matrix + if (!inputs[0].isSparseArg() && !inputs[1].isSparseArg() && + !outputs[0].isSparseArg()) { MulOp(out_mat, inputs[0].matrix(), inputs[1].matrix(), @@ -515,11 +510,9 @@ class MulFunc : public FunctionBase { return; } - if (!inputs[0].isSparseArg() && inputs[1].isSparseArg()) { - LOG(INFO) << "in1_mat:"; - inputs[0].matrix().print(std::cout); - LOG(INFO) << "in2_mat:"; - inputs[1].sparse().SparseMatrix().print(std::cout); + /// matrix = matrix * sparse matrix + if (!inputs[0].isSparseArg() && inputs[1].isSparseArg() && + !outputs[0].isSparseArg()) { MulOp(out_mat, inputs[0].matrix(), inputs[1].sparse().SparseMatrix(), @@ -528,11 +521,9 @@ class MulFunc : public FunctionBase { return; } - if (inputs[0].isSparseArg() && !inputs[1].isSparseArg()) { - LOG(INFO) << "in1_mat:"; - inputs[0].sparse().SparseMatrix().print(std::cout); - LOG(INFO) << "in2_mat:"; - inputs[1].matrix().print(std::cout); + /// matrix = sparse matrix * matrix + if (inputs[0].isSparseArg() && !inputs[1].isSparseArg() && + !outputs[0].isSparseArg()) { MulOp(out_mat, inputs[0].sparse().SparseMatrix(), inputs[1].matrix(), @@ -540,6 +531,18 @@ class MulFunc : public FunctionBase { beta_); return; } + + /// sparse matrix = matrix * matrix + auto out_sparse_mat = outputs[0].sparse().SparseMatrix(); + if (!inputs[0].isSparseArg() && !inputs[1].isSparseArg() && + outputs[0].isSparseArg()) { + MulOp(out_sparse_mat, + inputs[0].matrix(), + inputs[1].matrix(), + alpha_, + beta_); + return; + } } private: diff --git a/paddle/function/MulOpGpu.cu b/paddle/function/MulOpGpu.cu index 3691c7f3206126..3c4654b9b27574 100644 --- a/paddle/function/MulOpGpu.cu +++ b/paddle/function/MulOpGpu.cu @@ -176,7 +176,36 @@ void MulOp(GpuSparseMatrix& out, const GpuMatrix& b, real scale_ab, real scale_t) { -/// todo(tianbing), implement it + /// todo(tianbing), clean the code + CHECK(a.useGpu_ && b.useGpu_) << "type not match"; + CHECK(!out.trans_) << "trans not supported"; + real* a_data = const_cast(a.getData()); + real* b_data = const_cast(b.getData()); + hl_sparse_matrix_s out_data = out.sMatrix_.get(); + hl_trans_op_t a_trans = a.trans_ ? HPPL_OP_T : HPPL_OP_N; + hl_trans_op_t b_trans = b.trans_ ? HPPL_OP_T : HPPL_OP_N; + + if (!a.trans_ && !b.trans_) { + CHECK(out.height_ == a.getHeight()); + CHECK(out.width_ == b.getWidth()); + CHECK(a.getWidth() == b.getHeight()); + } else if (a.trans_ && !b.trans_) { + CHECK(out.height_ == a.getWidth()); + CHECK(out.width_ == b.getWidth()); + CHECK(a.getHeight() == b.getHeight()); + } else if (!a.trans_ && b.trans_) { + CHECK(out.height_ == a.getHeight()); + CHECK(out.width_ == b.getHeight()); + CHECK(a.getWidth() == b.getWidth()); + } else { + LOG(INFO) << "Not support"; + } + int dim_m = out.height_; + int dim_n = out.width_; + int dim_k = !b.trans_ ? b.getHeight() : b.getWidth(); + hl_sparse_matrix_mul( + a_data, a_trans, b_data, b_trans, out_data, + dim_m, dim_n, dim_k, scale_ab, scale_t); } } // namespace paddle diff --git a/paddle/function/MulOpTest.cpp b/paddle/function/MulOpTest.cpp index fd02504678efd6..630070b845a9af 100644 --- a/paddle/function/MulOpTest.cpp +++ b/paddle/function/MulOpTest.cpp @@ -24,9 +24,10 @@ limitations under the License. */ using namespace paddle; // NOLINT /** - * C = alpha * C + beta * (A * B) + * C = alpha * C + beta * (A * B), A, B, C dense matrix + * dense = dense * dense */ -void testMatrixMul(bool transa, bool transb, int dimM, int dimN, int dimK) { +void testDDDMatrix(bool transa, bool transb, int dimM, int dimN, int dimK) { real alpha = 1.5; real beta = 2.0; @@ -73,7 +74,7 @@ void testMatrixMul(bool transa, bool transb, int dimM, int dimN, int dimK) { autotest::TensorCheckErr(*cpuC, *gpuC); } -TEST(Matrix, mul) { +TEST(Matrix, DDDMul) { LOG(INFO) << "test for dense = dense * dense matrix"; for (auto transa : {false, true}) { for (auto transb : {false, true}) { @@ -89,7 +90,7 @@ TEST(Matrix, mul) { << " dimN=" << std::setw(5) << dimN << " dimK=" << std::setw(5) << dimK; - testMatrixMul(transa, transb, dimM, dimN, dimK); + testDDDMatrix(transa, transb, dimM, dimN, dimK); } } } @@ -97,19 +98,100 @@ TEST(Matrix, mul) { } } -struct MatrixPara { - size_t height; - size_t width; - bool trans; - bool sparse; - size_t nnz; - SparseFormat format; -}; +/** + * C += A * B, B, C dense, A sparse + * dense = sparse * dense + */ +void testDSparseDMatrix( + size_t dimM, size_t dimN, size_t dimK, size_t nnz, SparseFormat FORMAT) { + real alpha = 1.0; + real beta = 1.0; + const auto cpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-CPU"); + cpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); + const auto gpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-GPU"); + gpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); + + CpuSparseMatrix cpuMatrixA(dimM, dimK, nnz, FLOAT_VALUE, FORMAT, false); + GpuSparseMatrix gpuMatrixA(dimM, dimK, nnz, FLOAT_VALUE, FORMAT, false); + CpuMatrix cpuDenseA(dimM, dimK, false); + + auto cpuMatrixB = Matrix::create(dimK, dimN, false, false); + auto gpuMatrixB = Matrix::create(dimK, dimN, false, true); + auto cpuDenseB = Matrix::create(dimK, dimN, false, false); + + auto cpuMatrixC = Matrix::create(dimM, dimN, false, false); + auto gpuMatrixC = Matrix::create(dimM, dimN, false, true); + auto cpuDenseC = Matrix::create(dimM, dimN, false, false); + + /*matrix init*/ + hl_stream_t stream(HPPL_STREAM_1); + cpuMatrixA.randomizeUniform(); + cpuMatrixB->randomizeUniform(); + cpuMatrixC->randomizeUniform(); + + gpuMatrixA.copyFrom(cpuMatrixA, stream); + gpuMatrixB->copyFrom(*cpuMatrixB, stream); + gpuMatrixC->copyFrom(*cpuMatrixC, stream); + + cpuDenseA.copyFrom(cpuMatrixA); + cpuDenseB->copyFrom(*cpuMatrixB); + cpuDenseC->copyFrom(*cpuMatrixC); + hl_stream_synchronize(stream); + + /*matrix mul*/ + BufferArgs cpuInputs; + BufferArgs cpuOutputs; + cpuInputs.addArg(cpuMatrixA); + cpuInputs.addArg(*cpuMatrixB); + cpuOutputs.addArg(*cpuMatrixC, ADD_TO); + cpuFunc->calc(cpuInputs, cpuOutputs); + + BufferArgs gpuInputs; + BufferArgs gpuOutputs; + gpuInputs.addArg(gpuMatrixA); + gpuInputs.addArg(*gpuMatrixB); + gpuOutputs.addArg(*gpuMatrixC, ADD_TO); + gpuFunc->calc(gpuInputs, gpuOutputs); + + BufferArgs denseInputs; + BufferArgs denseOutputs; + denseInputs.addArg(cpuDenseA); + denseInputs.addArg(*cpuDenseB); + denseOutputs.addArg(*cpuDenseC, ADD_TO); + cpuFunc->calc(denseInputs, denseOutputs); + + /*check result*/ + autotest::TensorCheckErr(*cpuMatrixC, *cpuDenseC); + autotest::TensorCheckErr(*cpuMatrixC, *gpuMatrixC); +} + +TEST(Matrix, DSparseDMul) { + LOG(INFO) << "test for dense = sparse * dense matrix"; + for (const auto dimM : {10, 100, 1000}) { + for (const auto dimN : {10, 100}) { + for (const auto dimK : {3, 10}) { + for (const auto nnz : {3, 10}) { + for (const auto FORMAT : {SPARSE_CSR}) { + VLOG(3) << setiosflags(std::ios::left) << std::setfill(' ') + << " dimM=" << std::setw(5) << dimM + << " dimN=" << std::setw(5) << dimN + << " dimK=" << std::setw(5) << dimK + << " nnz=" << std::setw(5) << nnz + << " format=" << std::setw(5) << FORMAT; + testDSparseDMatrix(dimM, dimN, dimK, nnz, FORMAT); + } + } + } + } + } +} /** * C += A * B, A, C dense, B sparse + * dense = dense * sparse */ -void testDSparseDMatrix() { +void testDDSparseMatrix( + size_t dimM, size_t dimN, size_t dimK, size_t nnz, SparseFormat FORMAT) { real alpha = 1.0; real beta = 1.0; const auto cpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-CPU"); @@ -117,46 +199,19 @@ void testDSparseDMatrix() { const auto gpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-GPU"); gpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); - constexpr size_t dimM = 2; - constexpr size_t dimN = 2; - constexpr size_t dimK = 3; - constexpr size_t NNZ = 3; - constexpr SparseFormat FORMAT = SPARSE_CSC; - - MatrixPara paraA{dimM, dimK, /*trans*/ false, /*sparse*/ false, NNZ, FORMAT}; - MatrixPara paraB{dimK, dimN, /*trans*/ false, /*sparse*/ true, NNZ, FORMAT}; - MatrixPara paraC{dimM, dimN, /*trans*/ false, /*sparse*/ false, NNZ, FORMAT}; - - auto cpuMatrixA = - Matrix::create(paraA.height, paraA.width, paraA.trans, false); - auto gpuMatrixA = - Matrix::create(paraA.height, paraA.width, paraA.trans, true); - auto cpuDenseA = - Matrix::create(paraA.height, paraA.width, paraA.trans, false); - CpuSparseMatrix cpuMatrixB(paraB.height, - paraB.width, - paraB.nnz, - FLOAT_VALUE, - paraB.format, - paraB.trans); - - GpuSparseMatrix gpuMatrixB(paraB.height, - paraB.width, - paraB.nnz, - FLOAT_VALUE, - paraB.format, - paraB.trans); - - auto cpuDenseB = - Matrix::create(paraB.height, paraB.width, paraB.trans, false); - auto cpuMatrixC = - Matrix::create(paraC.height, paraC.width, paraC.trans, false); - auto gpuMatrixC = - Matrix::create(paraC.height, paraC.width, paraC.trans, true); - auto cpuDenseC = - Matrix::create(paraC.height, paraC.width, paraC.trans, false); - auto gpuMatrixC_d2h = - Matrix::create(paraC.height, paraC.width, paraC.trans, false); + auto cpuMatrixA = Matrix::create(dimM, dimK, false, false); + auto gpuMatrixA = Matrix::create(dimM, dimK, false, true); + auto cpuDenseA = Matrix::create(dimM, dimK, false, false); + + CpuSparseMatrix cpuMatrixB(dimK, dimN, nnz, FLOAT_VALUE, FORMAT, false); + + GpuSparseMatrix gpuMatrixB(dimK, dimN, nnz, FLOAT_VALUE, FORMAT, false); + + auto cpuDenseB = Matrix::create(dimK, dimN, false, false); + auto cpuMatrixC = Matrix::create(dimM, dimN, false, false); + auto gpuMatrixC = Matrix::create(dimM, dimN, false, true); + auto cpuDenseC = Matrix::create(dimM, dimN, false, false); + /*matrix init*/ hl_stream_t stream(HPPL_STREAM_1); cpuMatrixA->randomizeUniform(); @@ -172,27 +227,6 @@ void testDSparseDMatrix() { cpuDenseC->copyFrom(*cpuMatrixC); hl_stream_synchronize(stream); - LOG(INFO) << "cpuMatrixA: "; - cpuMatrixA->print(std::cout); - LOG(INFO) << "cpuMatrixB: "; - (&cpuMatrixB)->print(std::cout); - LOG(INFO) << "cpuMatrixC: "; - cpuMatrixC->print(std::cout); - - LOG(INFO) << "cpuDenseA: "; - cpuDenseA->print(std::cout); - LOG(INFO) << "cpuDenseB: "; - cpuDenseB->print(std::cout); - LOG(INFO) << "cpuDenseC: "; - cpuDenseC->print(std::cout); - - LOG(INFO) << "gpuMatrixA: "; - gpuMatrixA->print(std::cout); - LOG(INFO) << "gpuMatrixB: "; - (&gpuMatrixB)->print(std::cout); - LOG(INFO) << "gpuMatrixC: "; - gpuMatrixC->print(std::cout); - /*matrix mul*/ BufferArgs cpuInputs; BufferArgs cpuOutputs; @@ -215,15 +249,120 @@ void testDSparseDMatrix() { denseOutputs.addArg(*cpuDenseC, ADD_TO); cpuFunc->calc(denseInputs, denseOutputs); - gpuMatrixC_d2h->copyFrom(*gpuMatrixC, stream); - hl_stream_synchronize(stream); /*check result*/ - // autotest::TensorCheckErr(*cpuMatrixC, *gpuMatrixC); - checkMatrixEqual(cpuMatrixC, cpuDenseC); - checkMatrixEqual(cpuMatrixC, gpuMatrixC_d2h); + autotest::TensorCheckErr(*cpuMatrixC, *cpuDenseC); + autotest::TensorCheckErr(*cpuMatrixC, *gpuMatrixC); } -TEST(Matrix, SparseMatrixMul) { +TEST(Matrix, DDSparseMul) { LOG(INFO) << "test for dense = dense * sparse matrix"; - testDSparseDMatrix(); + for (const auto dimM : {10, 100, 1000}) { + for (const auto dimN : {10, 100}) { + for (const auto dimK : {3, 10}) { + for (const auto nnz : {3, 10}) { + for (const auto FORMAT : {SPARSE_CSR, SPARSE_CSC}) { + VLOG(3) << setiosflags(std::ios::left) << std::setfill(' ') + << " dimM=" << std::setw(5) << dimM + << " dimN=" << std::setw(5) << dimN + << " dimK=" << std::setw(5) << dimK + << " nnz=" << std::setw(5) << nnz + << " format=" << std::setw(5) << FORMAT; + testDDSparseMatrix(dimM, dimN, dimK, nnz, FORMAT); + } + } + } + } + } +} + +/** + * C += A * B, A sparse, B, C dense + * sparse = dense * dense + */ +void testSparseDDMatrix( + size_t dimM, size_t dimN, size_t dimK, size_t nnz, SparseFormat FORMAT) { + real alpha = 1.0; + real beta = 1.0; + const auto cpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-CPU"); + cpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); + const auto gpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-GPU"); + gpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); + + auto cpuMatrixA = Matrix::create(dimM, dimK, false, false); + auto gpuMatrixA = Matrix::create(dimM, dimK, false, true); + auto cpuDenseA = Matrix::create(dimM, dimK, false, false); + + auto cpuMatrixB = Matrix::create(dimK, dimN, false, false); + auto gpuMatrixB = Matrix::create(dimK, dimN, false, true); + auto cpuDenseB = Matrix::create(dimK, dimN, false, false); + + CpuSparseMatrix cpuMatrixC(dimM, dimN, nnz, FLOAT_VALUE, FORMAT, false); + CpuSparseMatrix gpuMatrixC_d2h(dimM, dimN, nnz, FLOAT_VALUE, FORMAT, false); + GpuSparseMatrix gpuMatrixC(dimM, dimN, nnz, FLOAT_VALUE, FORMAT, false); + CpuMatrix cpuDenseC(dimM, dimN, false); + + /*matrix init*/ + hl_stream_t stream(HPPL_STREAM_1); + cpuMatrixA->randomizeUniform(); + cpuMatrixB->randomizeUniform(); + cpuMatrixC.randomizeUniform(); + + gpuMatrixA->copyFrom(*cpuMatrixA, stream); + gpuMatrixB->copyFrom(*cpuMatrixB, stream); + gpuMatrixC.copyFrom(cpuMatrixC, stream); + + cpuDenseA->copyFrom(*cpuMatrixA); + cpuDenseB->copyFrom(*cpuMatrixB); + cpuDenseC.copyFrom(cpuMatrixC); + hl_stream_synchronize(stream); + + /*matrix mul*/ + BufferArgs cpuInputs; + BufferArgs cpuOutputs; + cpuInputs.addArg(*cpuMatrixA); + cpuInputs.addArg(*cpuMatrixB); + cpuOutputs.addArg(cpuMatrixC, ADD_TO); + cpuFunc->calc(cpuInputs, cpuOutputs); + + BufferArgs gpuInputs; + BufferArgs gpuOutputs; + gpuInputs.addArg(*gpuMatrixA); + gpuInputs.addArg(*gpuMatrixB); + gpuOutputs.addArg(gpuMatrixC, ADD_TO); + gpuFunc->calc(gpuInputs, gpuOutputs); + + BufferArgs denseInputs; + BufferArgs denseOutputs; + denseInputs.addArg(*cpuDenseA); + denseInputs.addArg(*cpuDenseB); + denseOutputs.addArg(cpuDenseC, ADD_TO); + cpuFunc->calc(denseInputs, denseOutputs); + + gpuMatrixC_d2h.copyFrom(gpuMatrixC, stream); + hl_stream_synchronize(stream); + + /*check result*/ + checkSMatrixEqual(cpuMatrixC, gpuMatrixC_d2h); + checkSMatrixEqual2Dense(cpuMatrixC, cpuDenseC); +} + +TEST(Matrix, SparseDDMul) { + LOG(INFO) << "test for sparse = dense * dense matrix"; + for (const auto dimM : {10, 100, 1000}) { + for (const auto dimN : {10, 100}) { + for (const auto dimK : {3, 10}) { + for (const auto nnz : {3, 10}) { + for (const auto FORMAT : {SPARSE_CSC, SPARSE_CSR}) { + VLOG(3) << setiosflags(std::ios::left) << std::setfill(' ') + << " dimM=" << std::setw(5) << dimM + << " dimN=" << std::setw(5) << dimN + << " dimK=" << std::setw(5) << dimK + << " nnz=" << std::setw(5) << nnz + << " format=" << std::setw(5) << FORMAT; + testSparseDDMatrix(dimM, dimN, dimK, nnz, FORMAT); + } + } + } + } + } } diff --git a/paddle/math/SparseMatrix.cpp b/paddle/math/SparseMatrix.cpp index 720a035ecbd26d..3bae6d373f240f 100644 --- a/paddle/math/SparseMatrix.cpp +++ b/paddle/math/SparseMatrix.cpp @@ -177,7 +177,6 @@ GpuSparseMatrix::GpuSparseMatrix(real* value, hl_sparse_matrix_s_ptr tmp2(tmp, hl_destruct_sparse_matrix); sMatrix_ = tmp2; } - LOG(INFO) << "weight to matrix "; } } diff --git a/paddle/math/tests/test_matrixUtil.h b/paddle/math/tests/test_matrixUtil.h index 9aa74b15193723..47f461474622d1 100644 --- a/paddle/math/tests/test_matrixUtil.h +++ b/paddle/math/tests/test_matrixUtil.h @@ -30,6 +30,17 @@ void checkMatrixEqual(const MatrixPtr& a, const MatrixPtr& b) { } } +void checkSMatrixEqual(const CpuSparseMatrix& a, const CpuSparseMatrix& b) { + ASSERT_EQ(a.getWidth(), b.getWidth()); + ASSERT_EQ(a.getHeight(), b.getHeight()); + ASSERT_EQ(a.isTransposed(), b.isTransposed()); + ASSERT_EQ(a.getFormat(), b.getFormat()); + ASSERT_EQ(a.getElementCnt(), b.getElementCnt()); + for (size_t r = 0; r < a.getElementCnt(); ++r) { + ASSERT_FLOAT_EQ(a.getValue()[r], b.getValue()[r]); + } +} + void checkSMatrixEqual(const CpuSparseMatrixPtr& a, const CpuSparseMatrixPtr& b) { ASSERT_EQ(a->getWidth(), b->getWidth()); @@ -73,6 +84,36 @@ void checkSMatrixEqual2(const CpuSparseMatrixPtr& a, } } +void checkSMatrixEqual2Dense(const CpuSparseMatrix& a, const CpuMatrix& b) { + ASSERT_EQ(a.getWidth(), b.getWidth()); + ASSERT_EQ(a.getHeight(), b.getHeight()); + ASSERT_EQ(a.isTransposed(), b.isTransposed()); + + if (a.getFormat() == SPARSE_CSC) { + int* rows = a.getRows(); + for (size_t i = 0; i < a.getWidth(); i++) { + for (size_t j = a.getColStartIdx(i); j < a.getColStartIdx(i + 1); j++) { + if (a.getValueType() == FLOAT_VALUE) { + ASSERT_FLOAT_EQ(a.getValue()[j], b.getElement(rows[j], i)); + } else { + ASSERT_FLOAT_EQ(1.0, b.getElement(rows[j], i)); + } + } + } + } else { + int* cols = a.getCols(); + for (size_t i = 0; i < a.getHeight(); i++) { + for (size_t j = a.getRowStartIdx(i); j < a.getRowStartIdx(i + 1); j++) { + if (a.getValueType() == FLOAT_VALUE) { + ASSERT_FLOAT_EQ(a.getValue()[j], b.getElement(i, cols[j])); + } else { + ASSERT_FLOAT_EQ(1.0, b.getElement(i, cols[j])); + } + } + } + } +} + void checkSMatrixEqual2Dense(const CpuSparseMatrixPtr& a, const CpuMatrixPtr& b) { ASSERT_EQ(a->getWidth(), b->getWidth()); From 171eaff21689de58fd8ecc29926151d9ba304b60 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Wed, 18 Jan 2017 18:16:37 -0800 Subject: [PATCH 100/370] clean the code a little bit. --- paddle/function/MulOp.cpp | 162 +++++---------------- paddle/function/MulOpGpu.cu | 255 ++++++++++++++++------------------ paddle/function/MulOpTest.cpp | 13 +- 3 files changed, 166 insertions(+), 264 deletions(-) diff --git a/paddle/function/MulOp.cpp b/paddle/function/MulOp.cpp index 37f8808605e10c..1117944a4ed994 100644 --- a/paddle/function/MulOp.cpp +++ b/paddle/function/MulOp.cpp @@ -38,13 +38,6 @@ inline void vecAddTo(real* a, const real* b, real scaleB, size_t len) { } } -inline void colVecAddTo( - real* a, const real* b, size_t len, size_t aWidth, size_t bWidth) { - for (unsigned int i = 0; i < len; ++i) { - a[i * aWidth] += b[i * bWidth]; - } -} - inline void colVecAddTo( real* a, real* b, real c, size_t len, size_t aWidth, size_t bWidth) { for (unsigned int i = 0; i < len; ++i) { @@ -336,140 +329,59 @@ void MulOp(CpuMatrix& out, const CpuSparseMatrix& b, real scaleAB, real scaleT) { - /// todo(tianbing), clean the code CHECK(!out.trans_) << "Not supported"; CHECK(!a.isTransposed()) << "Not supported"; CHECK(scaleT == 0 || scaleT == 1); CHECK_EQ(scaleAB, static_cast(1.0)); + if (!b.isTransposed()) { /// b is not Transpose + CHECK(b.getHeight() == a.getWidth() && a.getHeight() == out.getHeight() && + b.getWidth() == out.getWidth()); + } else { + CHECK(b.getHeight() == out.getWidth() && a.getHeight() == out.getHeight() && + b.getWidth() == a.getWidth()); + } + if (scaleT == 0) { + out.zeroMem(); + } real* A = const_cast(a.getData()); real* B = const_cast(b.getValue()); real* C = out.getData(); int* rows = b.getRows(); int* cols = b.getCols(); - if (scaleT == 0) { - out.zeroMem(); - } - /// todo(tianbing), clean the code + /// b.getFormat() == SPARSE_CSC if (b.getFormat() == SPARSE_CSC) { - if (!b.isTransposed()) { - size_t m = a.getWidth(); - CHECK_EQ(b.getHeight(), m); - CHECK_EQ(a.getHeight(), out.height_); - CHECK_EQ(b.getWidth(), out.width_); - - if (b.getValueType() == NO_VALUE) { - for (size_t j = 0; j < b.getWidth(); ++j) { - int start = b.getColStartIdx(j); - int end = b.getColStartIdx(j + 1); - for (int i = start; i < end; ++i) { - colVecAddTo( - C + j, A + rows[i], out.height_, out.width_, a.getWidth()); - } - } - } else if (b.getValueType() == FLOAT_VALUE) { - for (size_t j = 0; j < b.getWidth(); ++j) { - int start = b.getColStartIdx(j); - int end = b.getColStartIdx(j + 1); - for (int i = start; i < end; ++i) { - colVecAddTo(C + j, - A + rows[i], - B[i], - out.height_, - out.width_, - a.getWidth()); - } - } - } - } else /*if (b.isTransposed())*/ { - size_t m = a.getWidth(); - CHECK_EQ(b.getHeight(), out.width_); - CHECK_EQ(a.getHeight(), out.height_); - CHECK_EQ(b.getWidth(), m); - if (b.getValueType() == NO_VALUE) { - for (size_t i = 0; i < b.getWidth(); ++i) { - int start = b.getColStartIdx(i); - int end = b.getColStartIdx(i + 1); - for (int j = start; j < end; ++j) { - colVecAddTo( - C + rows[j], A + i, out.height_, out.width_, a.getWidth()); - } - } - } else if (b.getValueType() == FLOAT_VALUE) { - for (size_t i = 0; i < b.getWidth(); ++i) { - int start = b.getColStartIdx(i); - int end = b.getColStartIdx(i + 1); - for (int j = start; j < end; ++j) { - colVecAddTo(C + rows[j], - A + i, - B[j], - out.height_, - out.width_, - a.getWidth()); - } - } + for (size_t j = 0; j < b.getWidth(); ++j) { + int start = b.getColStartIdx(j); + int end = b.getColStartIdx(j + 1); + for (int i = start; i < end; ++i) { + colVecAddTo(!b.isTransposed() ? C + j : C + rows[i], + !b.isTransposed() ? A + rows[i] : A + j, + (b.getValueType() == NO_VALUE) ? (real)1.0 : B[i], + out.getHeight(), + out.getWidth(), + a.getWidth()); } } - } else { - if (!b.isTransposed()) { - size_t m = a.getWidth(); - CHECK_EQ(b.getHeight(), m); - CHECK_EQ(a.getHeight(), out.height_); - CHECK_EQ(b.getWidth(), out.width_); - - if (b.getValueType() == NO_VALUE) { - for (size_t j = 0; j < b.getHeight(); ++j) { - int start = b.getRowStartIdx(j); - int end = b.getRowStartIdx(j + 1); - for (int i = start; i < end; ++i) { - colVecAddTo( - C + cols[i], A + j, out.height_, out.width_, a.getWidth()); - } - } - } else if (b.getValueType() == FLOAT_VALUE) { - for (size_t j = 0; j < b.getHeight(); ++j) { - int start = b.getRowStartIdx(j); - int end = b.getRowStartIdx(j + 1); - for (int i = start; i < end; ++i) { - colVecAddTo(C + cols[i], - A + j, - B[i], - out.height_, - out.width_, - a.getWidth()); - } - } - } - } else /*if (b.isTransposed())*/ { - size_t m = a.getWidth(); - CHECK_EQ(b.getHeight(), out.width_); - CHECK_EQ(a.getHeight(), out.height_); - CHECK_EQ(b.getWidth(), m); - if (b.getValueType() == NO_VALUE) { - for (size_t i = 0; i < b.getHeight(); ++i) { - int start = b.getRowStartIdx(i); - int end = b.getRowStartIdx(i + 1); - for (int j = start; j < end; ++j) { - colVecAddTo( - C + i, A + cols[j], out.height_, out.width_, a.getWidth()); - } - } - } else if (b.getValueType() == FLOAT_VALUE) { - for (size_t i = 0; i < b.getHeight(); ++i) { - int start = b.getRowStartIdx(i); - int end = b.getRowStartIdx(i + 1); - for (int j = start; j < end; ++j) { - colVecAddTo(C + i, - A + cols[j], - B[j], - out.height_, - out.width_, - a.getWidth()); - } - } + return; + } + + /// b.getFormat() == SPARSE_CSR + if (b.getFormat() == SPARSE_CSR) { + for (size_t j = 0; j < b.getHeight(); ++j) { + int start = b.getRowStartIdx(j); + int end = b.getRowStartIdx(j + 1); + for (int i = start; i < end; ++i) { + colVecAddTo(!b.isTransposed() ? C + cols[i] : C + j, + !b.isTransposed() ? A + j : A + cols[i], + (b.getValueType() == NO_VALUE) ? (real)1.0 : B[i], + out.getHeight(), + out.getWidth(), + a.getWidth()); } } + return; } } diff --git a/paddle/function/MulOpGpu.cu b/paddle/function/MulOpGpu.cu index 3c4654b9b27574..09d2a764911f18 100644 --- a/paddle/function/MulOpGpu.cu +++ b/paddle/function/MulOpGpu.cu @@ -19,154 +19,147 @@ limitations under the License. */ namespace paddle { /** - * out = scale_t * out + scale_ab * (a * b) + * out = scaleT * out + scaleAB * (a * b) * out : output matrix, M * N */ template <> void MulOp(GpuMatrix& out, const GpuMatrix& a, const GpuMatrix& b, - real scale_ab, - real scale_t) { - CHECK(!out.isTransposed()) << "Not supported"; - + real scaleAB, + real scaleT) { + CHECK(!out.isTransposed()) << "Transpose not supported for out matrix"; if (!a.isTransposed() && !b.isTransposed()) { - /// a : M * K, b: K * N - CHECK_EQ(out.width_, b.width_); - CHECK_EQ(out.height_, a.height_); - CHECK_EQ(a.width_, b.height_); + /// a : M * K, b: K * N + CHECK(out.getWidth() == b.getWidth() && + out.getHeight() == a.getHeight() && + a.getWidth() == b.getHeight()); } else if (a.isTransposed() && !b.isTransposed()) { - /// a : K * M, b : K * N - CHECK_EQ(out.width_, b.width_); - CHECK_EQ(out.height_, a.width_); - CHECK_EQ(a.height_, b.height_); + /// a : K * M, b : K * N + CHECK(out.getWidth() == b.getWidth() && + out.getHeight() == a.getWidth() && + a.getHeight() == b.getHeight()); } else if (!a.isTransposed() && b.isTransposed()) { - /// a: M * K, b : N * K - CHECK_EQ(out.width_, b.height_); - CHECK_EQ(out.height_, a.height_); - CHECK_EQ(a.width_, b.width_); + /// a: M * K, b : N * K + CHECK(out.getWidth() == b.getHeight() && + out.getHeight() == a.getHeight() && + a.getWidth() == b.getWidth()); } else { - LOG(FATAL) << "Is not supported"; + LOG(FATAL) << "Not support for both a and b are Transposed Matrices"; } - real* a_data = a.data_; - real* b_data = b.data_; - real* out_data = out.data_; - int dim_m = out.getHeight(); - int dim_n = out.getWidth(); - int dim_k = !a.isTransposed() ? a.width_ : a.height_; - int lda = a.getStride(); - int ldb = b.getStride(); - int ldc = out.getStride(); - hl_trans_op_t trans_a = !a.isTransposed() ? HPPL_OP_N : HPPL_OP_T; - hl_trans_op_t trans_b = !b.isTransposed() ? HPPL_OP_N : HPPL_OP_T; - - hl_matrix_mul(a_data, - trans_a, - b_data, - trans_b, - out_data, - dim_m, - dim_n, - dim_k, - scale_ab, - scale_t, - lda, - ldb, - ldc); + real* aData = const_cast(a.getData()); + real* bData = const_cast(b.getData()); + real* outData = const_cast(out.getData()); + hl_matrix_mul(aData, + !a.isTransposed() ? HPPL_OP_N : HPPL_OP_T, + bData, + !b.isTransposed() ? HPPL_OP_N : HPPL_OP_T, + outData, + out.getHeight(), + out.getWidth(), + !a.isTransposed() ? a.getWidth() : a.getHeight(), + scaleAB, + scaleT, + a.getStride(), + b.getStride(), + out.getStride()); } /** - * out = scale_t * out + scale_ab * (a * b) + * out = scaleT * out + scaleAB * (a * b) * out : M * N */ template <> void MulOp(GpuMatrix& out, const GpuSparseMatrix& a, const GpuMatrix& b, - real scale_ab, - real scale_t) { + real scaleAB, + real scaleT) { CHECK(out.isContiguous()); CHECK(b.isContiguous()); - CHECK(b.useGpu_ == true) << "Matrix type are not equal"; - CHECK(!out.trans_ && !b.trans_) << "not supported"; - if (!a.trans_) { + CHECK(b.useGpu_) << "Matrix type are not equal"; + CHECK(!out.isTransposed() && !b.isTransposed()) << "not supported"; + if (!a.isTransposed()) { /// a: M * K, b: K * N - CHECK(out.width_ == b.width_ && out.height_ == a.height_ - && a.width_ == b.height_) << "Matrix dimensions are not equal"; + CHECK(out.getWidth() == b.getWidth() && out.getHeight() == a.getHeight() + && a.getWidth() == b.getHeight()) << "Matrix dimensions are not equal"; } else { /// a: K * M, transpose, b: K * N - CHECK(out.width_ == b.width_ && out.height_ == a.width_ - && a.height_ == b.height_) << "Matrix dimensions are not equal"; + CHECK(out.getWidth() == b.getWidth() && out.getHeight() == a.getWidth() + && a.getHeight() == b.getHeight()) << "Matrix dimensions are not equal"; } - hl_trans_op_t a_trans = a.trans_ ? HPPL_OP_T : HPPL_OP_N; - hl_sparse_matrix_s a_data = a.sMatrix_.get(); - real* b_data = b.data_; - real* out_data = out.data_; - hl_matrix_csr_mul_dense(a_data, - a_trans, - b_data, + hl_trans_op_t aTrans = a.isTransposed() ? HPPL_OP_T : HPPL_OP_N; + hl_sparse_matrix_s aData = a.sMatrix_.get(); + real* bData = const_cast(b.getData()); + real* outData = const_cast(out.getData()); + hl_matrix_csr_mul_dense(aData, + aTrans, + bData, HPPL_OP_N, - out_data, - out.height_, - out.width_, - b.height_, - scale_ab, - scale_t); + outData, + out.getHeight(), + out.getWidth(), + b.getHeight(), + scaleAB, + scaleT); } /** - * out = scale_t * out + scale_ab * (a * b) + * out = scaleT * out + scaleAB * (a * b) * out : M * N */ template <> void MulOp(GpuMatrix& out, const GpuMatrix& a, const GpuSparseMatrix& b, - real scale_ab, - real scale_t) { + real scaleAB, + real scaleT) { CHECK(out.isContiguous()); CHECK(a.isContiguous()); - CHECK(a.useGpu_ == true) << "Matrix type are not equal"; - - hl_sparse_matrix_s b_data = b.sMatrix_.get(); - real* a_data = a.data_; - real* out_data = out.data_; - hl_trans_op_t trans_b = b.trans_ ? HPPL_OP_T : HPPL_OP_N; - if (!b.trans_) { - /// a : M * K, b : K * N - CHECK(out.width_ == b.width_ && - out.height_ == a.height_ && a.width_ == b.height_) - << "Matrix dimensions are not equal"; + CHECK(a.useGpu_) << "Matrix type are not equal"; + if (!b.isTransposed()) { + /// a : M * K, b : K * N + CHECK(out.getWidth() == b.getWidth() && + out.getHeight() == a.getHeight() && + a.getWidth() == b.getHeight()) + << "Matrix dimensions are not equal"; } else { - /// a : M * K, b : N * K, transpose - CHECK(out.width_ == b.height_ && - out.height_ == a.height_ && a.width_ == b.width_) - << "Matrix dimensions are not equal"; + /// a : M * K, b : N * K, transpose + CHECK(out.getWidth() == b.getHeight() && + out.getHeight() == a.getHeight() && + a.getWidth() == b.getWidth()) + << "Matrix dimensions are not equal"; } + + hl_trans_op_t bTrans = b.isTransposed() ? HPPL_OP_T : HPPL_OP_N; + hl_sparse_matrix_s bData = b.sMatrix_.get(); + real* aData = const_cast(a.getData()); + real* outData = const_cast(out.getData()); + if (b.format_ == SPARSE_CSC) { - hl_matrix_dense_mul_csc(a_data, + hl_matrix_dense_mul_csc(aData, HPPL_OP_N, - b_data, - trans_b, - out_data, - out.height_, - out.width_, - a.width_, - scale_ab, - scale_t); + bData, + bTrans, + outData, + out.getHeight(), + out.getWidth(), + a.getWidth(), + scaleAB, + scaleT); } else { - hl_matrix_dense_mul_csr(a_data, + hl_matrix_dense_mul_csr(aData, HPPL_OP_N, - b_data, - trans_b, - out_data, - out.height_, - out.width_, - a.width_, - scale_ab, - scale_t); + bData, + bTrans, + outData, + out.getHeight(), + out.getWidth(), + a.getWidth(), + scaleAB, + scaleT); } } @@ -174,38 +167,36 @@ template <> void MulOp(GpuSparseMatrix& out, const GpuMatrix& a, const GpuMatrix& b, - real scale_ab, - real scale_t) { - /// todo(tianbing), clean the code - CHECK(a.useGpu_ && b.useGpu_) << "type not match"; - CHECK(!out.trans_) << "trans not supported"; - real* a_data = const_cast(a.getData()); - real* b_data = const_cast(b.getData()); - hl_sparse_matrix_s out_data = out.sMatrix_.get(); - hl_trans_op_t a_trans = a.trans_ ? HPPL_OP_T : HPPL_OP_N; - hl_trans_op_t b_trans = b.trans_ ? HPPL_OP_T : HPPL_OP_N; - - if (!a.trans_ && !b.trans_) { - CHECK(out.height_ == a.getHeight()); - CHECK(out.width_ == b.getWidth()); - CHECK(a.getWidth() == b.getHeight()); - } else if (a.trans_ && !b.trans_) { - CHECK(out.height_ == a.getWidth()); - CHECK(out.width_ == b.getWidth()); - CHECK(a.getHeight() == b.getHeight()); - } else if (!a.trans_ && b.trans_) { - CHECK(out.height_ == a.getHeight()); - CHECK(out.width_ == b.getHeight()); - CHECK(a.getWidth() == b.getWidth()); + real scaleAB, + real scaleT) { + CHECK(a.useGpu_ && b.useGpu_) << "matrix device type not match"; + CHECK(!out.isTransposed()) << "Transpose is not supported for out matrix"; + + if (!a.isTransposed() && !b.isTransposed()) { + CHECK(out.getHeight() == a.getHeight() && + out.getWidth() == b.getWidth() && + a.getWidth() == b.getHeight()); + } else if (a.isTransposed() && !b.isTransposed()) { + CHECK(out.getHeight() == a.getWidth() && + out.getWidth() == b.getWidth() && + a.getHeight() == b.getHeight()); + } else if (!a.isTransposed() && b.isTransposed()) { + CHECK(out.getHeight() == a.getHeight() && + out.getWidth() == b.getHeight() && + a.getWidth() == b.getWidth()); } else { - LOG(INFO) << "Not support"; + LOG(FATAL) << "Not support for both a and b are Transposed Matrices"; } - int dim_m = out.height_; - int dim_n = out.width_; - int dim_k = !b.trans_ ? b.getHeight() : b.getWidth(); - hl_sparse_matrix_mul( - a_data, a_trans, b_data, b_trans, out_data, - dim_m, dim_n, dim_k, scale_ab, scale_t); + + hl_trans_op_t aTrans = a.isTransposed() ? HPPL_OP_T : HPPL_OP_N; + hl_trans_op_t bTrans = b.isTransposed() ? HPPL_OP_T : HPPL_OP_N; + int dimK = !b.isTransposed() ? b.getHeight() : b.getWidth(); + real* aData = const_cast(a.getData()); + real* bData = const_cast(b.getData()); + hl_sparse_matrix_s outData = out.sMatrix_.get(); + + hl_sparse_matrix_mul(aData, aTrans, bData, bTrans, outData, + out.getHeight(), out.getWidth(), dimK, scaleAB, scaleT); } } // namespace paddle diff --git a/paddle/function/MulOpTest.cpp b/paddle/function/MulOpTest.cpp index 630070b845a9af..965ffea20ce7fb 100644 --- a/paddle/function/MulOpTest.cpp +++ b/paddle/function/MulOpTest.cpp @@ -76,12 +76,12 @@ void testDDDMatrix(bool transa, bool transb, int dimM, int dimN, int dimK) { TEST(Matrix, DDDMul) { LOG(INFO) << "test for dense = dense * dense matrix"; - for (auto transa : {false, true}) { - for (auto transb : {false, true}) { - for (auto dimM : {1, 10, 100}) { - for (auto dimN : {1, 10}) { - for (auto dimK : {8}) { - if (true == transa && true == transb) { + for (const auto transa : {false, true}) { + for (const auto transb : {false, true}) { + for (const auto dimM : {1, 10, 100}) { + for (const auto dimN : {1, 10}) { + for (const auto dimK : {8}) { + if (transa && transb) { continue; } VLOG(3) << setiosflags(std::ios::left) << std::setfill(' ') @@ -89,7 +89,6 @@ TEST(Matrix, DDDMul) { << " dimM=" << std::setw(5) << dimM << " dimN=" << std::setw(5) << dimN << " dimK=" << std::setw(5) << dimK; - testDDDMatrix(transa, transb, dimM, dimN, dimK); } } From 9ade63e61cfb50753714118864d0f6680c025f96 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Wed, 18 Jan 2017 22:19:44 -0800 Subject: [PATCH 101/370] clean code a little bit. --- paddle/function/MulOp.cpp | 224 ++++++++++++-------------------------- 1 file changed, 72 insertions(+), 152 deletions(-) diff --git a/paddle/function/MulOp.cpp b/paddle/function/MulOp.cpp index 1117944a4ed994..b911ccd13b607a 100644 --- a/paddle/function/MulOp.cpp +++ b/paddle/function/MulOp.cpp @@ -56,7 +56,16 @@ void MulOp(CpuSparseMatrix& out, /// todo(tianbing), clean the code CHECK(!out.isTransposed()) << "Not supported"; CHECK_EQ(out.getValueType(), FLOAT_VALUE); + CHECK(!a.isTransposed() || !b.isTransposed()) + << "Not support both a and b are transpose matrices"; + if (!a.isTransposed() && b.isTransposed()) { + CHECK(out.getFormat() != SPARSE_CSC) + << "Not supported CSC format when a is not trans and b is trans"; + } + if (scaleT == 0) { + out.zeroMem(); + } const real* A = a.getData(); const real* B = b.getData(); real* C = out.getValue(); @@ -64,15 +73,11 @@ void MulOp(CpuSparseMatrix& out, int* cols = out.getCols(); size_t height = out.getHeight(); size_t width = out.getWidth(); - if (scaleT == 0) { - out.zeroMem(); - } if (!a.isTransposed() && !b.isTransposed()) { + CHECK(b.getHeight() == a.getWidth() && a.getHeight() == height && + b.getWidth() == width); size_t m = a.getWidth(); - CHECK_EQ(b.getHeight(), m); - CHECK_EQ(a.getHeight(), height); - CHECK_EQ(b.getWidth(), width); if (out.getFormat() == SPARSE_CSC) { for (size_t i = 0; i < width; i++) { size_t start = out.getColStartIdx(i); @@ -86,26 +91,27 @@ void MulOp(CpuSparseMatrix& out, C[j] = scaleAB * sum + scaleT * C[j]; } } - } else { + } else { /// out.getFormat() == SPARSE_CSR for (size_t i = 0; i < height; i++) { size_t start = out.getRowStartIdx(i); size_t end = out.getRowStartIdx(i + 1); for (size_t j = start; j < end; j++) { real sum = 0; size_t colIdx = cols[j]; - for (size_t k = 0; k < m; k++) { + for (size_t k = 0; k < a.getWidth(); k++) { sum += A[i * m + k] * B[k * width + colIdx]; } C[j] = scaleAB * sum + scaleT * C[j]; } } } - } else if (a.isTransposed() && !b.isTransposed()) { - size_t m = a.getHeight(); - CHECK_EQ(m, b.getHeight()); - CHECK_EQ(b.getWidth(), width); - CHECK_EQ(a.getWidth(), height); + return; + } + if (a.isTransposed() && !b.isTransposed()) { + CHECK(a.getHeight() == b.getHeight() && b.getWidth() == width && + a.getWidth() == height); + size_t m = a.getHeight(); if (out.getFormat() == SPARSE_CSC) { for (size_t i = 0; i < width; i++) { size_t start = out.getColStartIdx(i); @@ -119,25 +125,27 @@ void MulOp(CpuSparseMatrix& out, C[j] = scaleAB * sum + scaleT * C[j]; } } - } else { + } else { /// out.getFormat() == SPARSE_CSR for (size_t i = 0; i < height; i++) { int start = out.getRowStartIdx(i); int end = out.getRowStartIdx(i + 1); for (int j = start; j < end; j++) { real sum = 0; size_t colIdx = cols[j]; - for (size_t k = 0; k < m; k++) { + for (size_t k = 0; k < a.getHeight(); k++) { sum += A[k * height + i] * B[k * width + colIdx]; } C[j] = scaleAB * sum + scaleT * C[j]; } } } - } else if (!a.isTransposed() && b.isTransposed()) { + return; + } + + if (!a.isTransposed() && b.isTransposed()) { + CHECK(b.getWidth() == a.getWidth() && a.getHeight() == height && + b.getHeight() == width); size_t m = a.getWidth(); - CHECK_EQ(b.getWidth(), m); - CHECK_EQ(a.getHeight(), height); - CHECK_EQ(b.getHeight(), width); if (out.getFormat() == SPARSE_CSR) { for (size_t i = 0; i < height; i++) { size_t start = out.getRowStartIdx(i); @@ -151,12 +159,8 @@ void MulOp(CpuSparseMatrix& out, C[j] = scaleAB * sum + scaleT * C[j]; } } - } else { - LOG(FATAL) << "Not supported csc format " - "when a is not trans and b is trans"; } - } else { - LOG(FATAL) << "Not supported"; + return; } } @@ -166,159 +170,75 @@ void MulOp(CpuMatrix& out, const CpuMatrix& b, real scaleAB, real scaleT) { - /// todo(tianbing), clean the code - CHECK(!out.isTransposed()) << "Not supported"; - CBLAS_TRANSPOSE aTrans = CblasNoTrans; - size_t aRow = a.getHeight(); - size_t aCol = a.getWidth(); - CBLAS_TRANSPOSE bTrans = CblasNoTrans; - size_t bRow = b.getHeight(); - size_t bCol = b.getWidth(); - if (a.isTransposed()) { - aTrans = CblasTrans; - aRow = a.getWidth(); - aCol = a.getHeight(); - } - if (b.isTransposed()) { - bTrans = CblasTrans; - bRow = b.getWidth(); - bCol = b.getHeight(); - } + CHECK(!out.isTransposed()) << "out matrix transpose not supported"; + CBLAS_TRANSPOSE aTrans = a.isTransposed() ? CblasTrans : CblasNoTrans; + size_t aRow = a.isTransposed() ? a.getWidth() : a.getHeight(); + size_t aCol = a.isTransposed() ? a.getHeight() : a.getWidth(); + CBLAS_TRANSPOSE bTrans = b.isTransposed() ? CblasTrans : CblasNoTrans; + size_t bRow = b.isTransposed() ? b.getWidth() : b.getHeight(); + size_t bCol = b.isTransposed() ? b.getHeight() : b.getWidth(); /// C = A * B, for matrix format CHECK_EQ(aCol, bRow); CHECK_EQ(aRow, out.getHeight()); CHECK_EQ(bCol, out.getWidth()); - const real* A = a.getData(); - const real* B = b.getData(); - real* C = out.getData(); - - int M = out.getHeight(); - int N = out.getWidth(); - int K = aCol; - int lda = a.getStride(); - int ldb = b.getStride(); - int ldc = out.getStride(); - - GEMM(aTrans, bTrans, M, N, K, scaleAB, A, lda, B, ldb, scaleT, C, ldc); - - VLOG(2) << " A[0]=" << A[0] << " A[1]=" << A[1] << " B[0]=" << B[0] - << " B[1]=" << B[1] << " C[0]=" << C[0] << " C[1]=" << C[1]; + GEMM(aTrans, + bTrans, + out.getHeight(), + out.getWidth(), + aCol, + scaleAB, + a.getData(), + a.getStride(), + b.getData(), + b.getStride(), + scaleT, + out.getData(), + out.getStride()); } -static ThreadLocal> threadLocalColArray; - template <> void MulOp(CpuMatrix& out, const CpuSparseMatrix& a, const CpuMatrix& b, real scaleAB, real scaleT) { - /// todo(tianbing), clean the code CHECK(!out.isTransposed()) << "Not supported"; CHECK(!b.isTransposed()) << "Not supported"; CHECK(scaleT == 0 || scaleT == 1) << "Not support"; CHECK_EQ(scaleAB, static_cast(1.0)) << "Not supported"; CHECK_EQ(a.getFormat(), SPARSE_CSR) << "Not supported"; - const real* B = b.getData(); - real* C = out.getData(); - size_t height = out.getHeight(); - size_t width = out.getWidth(); - int* cols = a.getCols(); - real* values = a.getValue(); + if (!a.isTransposed()) { + CHECK(b.getHeight() == a.getWidth() && a.getHeight() == out.getHeight() && + b.getWidth() == out.getWidth()); + } else { + CHECK(b.getHeight() == a.getHeight() && a.getWidth() == out.getHeight() && + b.getWidth() == out.getWidth()); + } if (scaleT == 0) { out.zeroMem(); } + const real* B = b.getData(); + real* C = out.getData(); + if (out.getWidth() % 32 == 0) { + CHECK_EQ((size_t)B % 32, 0UL); + CHECK_EQ((size_t)C % 32, 0UL); + } - if (!a.isTransposed()) { - size_t m = a.getWidth(); - CHECK_EQ(b.getHeight(), m); - CHECK_EQ(a.getHeight(), height); - CHECK_EQ(b.getWidth(), width); - - if (a.getValueType() == NO_VALUE) { - if (width % 32 == 0) { // use libaddto - CHECK_EQ((size_t)B % 32, 0UL); - CHECK_EQ((size_t)C % 32, 0UL); - auto& colArray = *threadLocalColArray; - for (size_t i = 0; i < a.getHeight(); ++i) { - const int start = a.getRowStartIdx(i); - const int end = a.getRowStartIdx(i + 1); - size_t colNum = end - start; - colArray.resize(colNum); - for (int j = 0; j < end - start; ++j) { - colArray[j] = const_cast(b).getRow(cols[j + start]); - } - simd::batchAddTo(out.getRow(i), &colArray[0], colNum, width); - } - - } else { - for (size_t i = 0; i < a.getHeight(); ++i) { - const int start = a.getRowStartIdx(i); - const int end = a.getRowStartIdx(i + 1); - for (int j = start; j < end; ++j) { - vecAddTo(out.getRow(i), - const_cast(b).getRow(cols[j]), - width); - } - } - } - } else if (a.getValueType() == FLOAT_VALUE) { - for (size_t i = 0; i < a.getHeight(); ++i) { - const int start = a.getRowStartIdx(i); - const int end = a.getRowStartIdx(i + 1); - for (int j = start; j < end; ++j) { - vecAddTo(out.getRow(i), - const_cast(b).getRow(cols[j]), - values[j], - width); - } - } - } - } else /*if (a->isTransposed())*/ { - size_t m = a.getHeight(); - CHECK_EQ(b.getHeight(), m); - CHECK_EQ(a.getWidth(), height); - CHECK_EQ(b.getWidth(), width); - if (a.getValueType() == NO_VALUE) { - if (width % 32 == 0) { // use libaddto - CHECK_EQ((size_t)B % 32, 0UL); - CHECK_EQ((size_t)C % 32, 0UL); - for (size_t i = 0; i < a.getHeight(); ++i) { - const int start = a.getRowStartIdx(i); - const int end = a.getRowStartIdx(i + 1); - for (int j = start; j < end; ++j) { - simd::addTo(out.getRow(cols[j]), - const_cast(b).getRow(i), - width); - } - } - - } else { - for (size_t i = 0; i < a.getHeight(); ++i) { - const int start = a.getRowStartIdx(i); - const int end = a.getRowStartIdx(i + 1); - for (int j = start; j < end; ++j) { - vecAddTo(out.getRow(cols[j]), - const_cast(b).getRow(i), - width); - } - } - } - } else if (a.getValueType() == FLOAT_VALUE) { - for (size_t i = 0; i < a.getHeight(); ++i) { - const int start = a.getRowStartIdx(i); - const int end = a.getRowStartIdx(i + 1); - for (int j = start; j < end; ++j) { - vecAddTo(out.getRow(cols[j]), - const_cast(b).getRow(i), - values[j], - width); - } - } + int* cols = a.getCols(); + real* values = a.getValue(); + for (size_t i = 0; i < a.getHeight(); ++i) { + const int start = a.getRowStartIdx(i); + const int end = a.getRowStartIdx(i + 1); + for (int j = start; j < end; ++j) { + vecAddTo(!a.isTransposed() ? out.getRow(i) : out.getRow(cols[j]), + !a.isTransposed() ? const_cast(b).getRow(cols[j]) + : const_cast(b).getRow(i), + (a.getValueType() == FLOAT_VALUE) ? values[j] : (real)1.0, + out.getWidth()); } } } From 316bf75afd7676b3bb4f5d53af44a6b1d88203bf Mon Sep 17 00:00:00 2001 From: xutianbing Date: Thu, 19 Jan 2017 13:21:07 -0800 Subject: [PATCH 102/370] clean code in function/MulOp.cpp --- paddle/function/MulOp.cpp | 145 +++++++++++++------------------------- paddle/function/MulOp.h | 2 - 2 files changed, 48 insertions(+), 99 deletions(-) diff --git a/paddle/function/MulOp.cpp b/paddle/function/MulOp.cpp index b911ccd13b607a..bd3bc5c087d669 100644 --- a/paddle/function/MulOp.cpp +++ b/paddle/function/MulOp.cpp @@ -26,22 +26,16 @@ limitations under the License. */ #endif namespace { -inline void vecAddTo(real* a, const real* b, size_t len) { - for (unsigned int i = 0; i < len; ++i) { - a[i] += b[i]; - } -} - inline void vecAddTo(real* a, const real* b, real scaleB, size_t len) { for (unsigned int i = 0; i < len; ++i) { - a[i] += scaleB * b[i]; + a[i] += (1.0 == scaleB) ? b[i] : scaleB * b[i]; } } inline void colVecAddTo( real* a, real* b, real c, size_t len, size_t aWidth, size_t bWidth) { for (unsigned int i = 0; i < len; ++i) { - a[i * aWidth] += b[i * bWidth] * c; + a[i * aWidth] += (1.0 == c) ? b[i * bWidth] : b[i * bWidth] * c; } } } // namespace @@ -53,15 +47,19 @@ void MulOp(CpuSparseMatrix& out, const CpuMatrix& b, real scaleAB, real scaleT) { - /// todo(tianbing), clean the code CHECK(!out.isTransposed()) << "Not supported"; CHECK_EQ(out.getValueType(), FLOAT_VALUE); CHECK(!a.isTransposed() || !b.isTransposed()) << "Not support both a and b are transpose matrices"; - if (!a.isTransposed() && b.isTransposed()) { - CHECK(out.getFormat() != SPARSE_CSC) - << "Not supported CSC format when a is not trans and b is trans"; - } + + size_t height = out.getHeight(); + size_t width = out.getWidth(); + size_t aRow = !a.isTransposed() ? a.getHeight() : a.getWidth(); + size_t aCol = !a.isTransposed() ? a.getWidth() : a.getHeight(); + size_t bRow = !b.isTransposed() ? b.getHeight() : b.getWidth(); + size_t bCol = !b.isTransposed() ? b.getWidth() : b.getHeight(); + /// C = A * B, for matrix format + CHECK(aCol == bRow && aRow == height && bCol == width); if (scaleT == 0) { out.zeroMem(); @@ -71,93 +69,46 @@ void MulOp(CpuSparseMatrix& out, real* C = out.getValue(); int* rows = out.getRows(); int* cols = out.getCols(); - size_t height = out.getHeight(); - size_t width = out.getWidth(); - if (!a.isTransposed() && !b.isTransposed()) { - CHECK(b.getHeight() == a.getWidth() && a.getHeight() == height && - b.getWidth() == width); - size_t m = a.getWidth(); - if (out.getFormat() == SPARSE_CSC) { - for (size_t i = 0; i < width; i++) { - size_t start = out.getColStartIdx(i); - size_t end = out.getColStartIdx(i + 1); - for (size_t j = start; j < end; j++) { - real sum = 0; - size_t rowIdx = rows[j]; - for (size_t k = 0; k < m; k++) { - sum += A[rowIdx * m + k] * B[k * width + i]; - } - C[j] = scaleAB * sum + scaleT * C[j]; - } - } - } else { /// out.getFormat() == SPARSE_CSR - for (size_t i = 0; i < height; i++) { - size_t start = out.getRowStartIdx(i); - size_t end = out.getRowStartIdx(i + 1); - for (size_t j = start; j < end; j++) { - real sum = 0; - size_t colIdx = cols[j]; - for (size_t k = 0; k < a.getWidth(); k++) { - sum += A[i * m + k] * B[k * width + colIdx]; - } - C[j] = scaleAB * sum + scaleT * C[j]; - } - } - } - return; - } - - if (a.isTransposed() && !b.isTransposed()) { - CHECK(a.getHeight() == b.getHeight() && b.getWidth() == width && - a.getWidth() == height); - size_t m = a.getHeight(); - if (out.getFormat() == SPARSE_CSC) { - for (size_t i = 0; i < width; i++) { - size_t start = out.getColStartIdx(i); - size_t end = out.getColStartIdx(i + 1); - for (size_t j = start; j < end; j++) { - real sum = 0; - size_t rowIdx = rows[j]; - for (size_t k = 0; k < m; k++) { - sum += A[k * height + rowIdx] * B[k * width + i]; - } - C[j] = scaleAB * sum + scaleT * C[j]; - } - } - } else { /// out.getFormat() == SPARSE_CSR - for (size_t i = 0; i < height; i++) { - int start = out.getRowStartIdx(i); - int end = out.getRowStartIdx(i + 1); - for (int j = start; j < end; j++) { - real sum = 0; - size_t colIdx = cols[j]; - for (size_t k = 0; k < a.getHeight(); k++) { - sum += A[k * height + i] * B[k * width + colIdx]; - } - C[j] = scaleAB * sum + scaleT * C[j]; + /// SPARSE_CSC, {a any, b not trans} + if (out.getFormat() == SPARSE_CSC) { + /// b not trans and a any + CHECK(!b.isTransposed()); + size_t m = !a.isTransposed() ? a.getWidth() : a.getHeight(); + for (size_t i = 0; i < width; i++) { + size_t start = out.getColStartIdx(i); + size_t end = out.getColStartIdx(i + 1); + for (size_t j = start; j < end; j++) { + real sum = 0; + size_t rowIdx = rows[j]; + for (size_t k = 0; k < m; k++) { + sum += + (!a.isTransposed() ? A[rowIdx * m + k] : A[k * height + rowIdx]) * + B[k * width + i]; } + C[j] = scaleAB * sum + scaleT * C[j]; } } return; } - if (!a.isTransposed() && b.isTransposed()) { - CHECK(b.getWidth() == a.getWidth() && a.getHeight() == height && - b.getHeight() == width); + /// SPARSE_CSR, {a any, b not trans} or {a not trans, b trans} + if (out.getFormat() == SPARSE_CSR) { + /// a and b can not both transpose + CHECK(!(a.isTransposed() && b.isTransposed())); size_t m = a.getWidth(); - if (out.getFormat() == SPARSE_CSR) { - for (size_t i = 0; i < height; i++) { - size_t start = out.getRowStartIdx(i); - size_t end = out.getRowStartIdx(i + 1); - for (size_t j = start; j < end; j++) { - real sum = 0; - size_t colIdx = cols[j]; - for (size_t k = 0; k < m; k++) { - sum += A[i * m + k] * B[colIdx * m + k]; - } - C[j] = scaleAB * sum + scaleT * C[j]; + for (size_t i = 0; i < height; i++) { + size_t start = out.getRowStartIdx(i); + size_t end = out.getRowStartIdx(i + 1); + for (size_t j = start; j < end; j++) { + real sum = 0; + size_t colIdx = cols[j]; + for (size_t k = 0; k < m; k++) { + sum += + (!a.isTransposed() ? A[i * m + k] : A[k * height + i]) * + (!b.isTransposed() ? B[k * width + colIdx] : B[colIdx * m + k]); } + C[j] = scaleAB * sum + scaleT * C[j]; } } return; @@ -330,11 +281,11 @@ class MulFunc : public FunctionBase { CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); CHECK_EQ(outputs[0].getArgType(), ADD_TO); - auto out_mat = outputs[0].matrix(); + auto outMat = outputs[0].matrix(); /// matrix = matrix * matrix if (!inputs[0].isSparseArg() && !inputs[1].isSparseArg() && !outputs[0].isSparseArg()) { - MulOp(out_mat, + MulOp(outMat, inputs[0].matrix(), inputs[1].matrix(), alpha_, @@ -345,7 +296,7 @@ class MulFunc : public FunctionBase { /// matrix = matrix * sparse matrix if (!inputs[0].isSparseArg() && inputs[1].isSparseArg() && !outputs[0].isSparseArg()) { - MulOp(out_mat, + MulOp(outMat, inputs[0].matrix(), inputs[1].sparse().SparseMatrix(), alpha_, @@ -356,7 +307,7 @@ class MulFunc : public FunctionBase { /// matrix = sparse matrix * matrix if (inputs[0].isSparseArg() && !inputs[1].isSparseArg() && !outputs[0].isSparseArg()) { - MulOp(out_mat, + MulOp(outMat, inputs[0].sparse().SparseMatrix(), inputs[1].matrix(), alpha_, @@ -365,10 +316,10 @@ class MulFunc : public FunctionBase { } /// sparse matrix = matrix * matrix - auto out_sparse_mat = outputs[0].sparse().SparseMatrix(); + auto outSparseMat = outputs[0].sparse().SparseMatrix(); if (!inputs[0].isSparseArg() && !inputs[1].isSparseArg() && outputs[0].isSparseArg()) { - MulOp(out_sparse_mat, + MulOp(outSparseMat, inputs[0].matrix(), inputs[1].matrix(), alpha_, diff --git a/paddle/function/MulOp.h b/paddle/function/MulOp.h index 23bfd0fa932178..b7b1f56af10375 100644 --- a/paddle/function/MulOp.h +++ b/paddle/function/MulOp.h @@ -15,8 +15,6 @@ limitations under the License. */ #pragma once #include "Function.h" -/// todo(tianbing), delete -#include #include "paddle/math/Matrix.h" #include "paddle/math/SparseMatrix.h" From 077f936aa5d3ead02880256774189ee8c47999f6 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Sat, 21 Jan 2017 21:24:23 -0800 Subject: [PATCH 103/370] Support SparseMatrixArg unit test using Daoyuan's new Function Test. --- paddle/function/BufferArg.cpp | 2 - paddle/function/BufferArg.h | 49 ++++++- paddle/function/FunctionTest.h | 98 ++++++++++--- paddle/function/MulOp.h | 2 + paddle/function/MulOpTest.cpp | 249 ++++++++++----------------------- 5 files changed, 203 insertions(+), 197 deletions(-) diff --git a/paddle/function/BufferArg.cpp b/paddle/function/BufferArg.cpp index 39773c76280ba3..a4f1c2d96417b3 100644 --- a/paddle/function/BufferArg.cpp +++ b/paddle/function/BufferArg.cpp @@ -33,7 +33,6 @@ SparseMatrixArg::SparseMatrixArg(const CpuSparseMatrix& sparse, ArgType argType) : BufferArg(sparse, argType), row_(reinterpret_cast(sparse.getRows()), VALUE_TYPE_INT32), col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32), - /// todo(tianbing), make sure how to get NNZ nnz_(sparse.getElementCnt()), format_(sparse.getFormat()), type_(sparse.getValueType()) { @@ -44,7 +43,6 @@ SparseMatrixArg::SparseMatrixArg(const GpuSparseMatrix& sparse, ArgType argType) : BufferArg(sparse, argType), row_(reinterpret_cast(sparse.getRows()), VALUE_TYPE_INT32), col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32), - /// todo(tianbing), make sure how to get NNZ nnz_(sparse.getElementCnt()), format_(sparse.getFormat()), type_(sparse.getValueType()) { diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index eac3fe4420369b..17a4e4a6b0eec9 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -71,17 +71,24 @@ class BufferArg { public: BufferArg(ValueType valueType, const TensorShape& shape, - ArgType argType = UNSPECIFIED) + ArgType argType = UNSPECIFIED, + bool trans = false) : buf_(nullptr), valueType_(valueType), shape_(shape), - argType_(argType) {} + argType_(argType), + trans_(trans) {} BufferArg(void* buf, ValueType valueType, const TensorShape& shape, - ArgType argType = UNSPECIFIED) - : buf_(buf), valueType_(valueType), shape_(shape), argType_(argType) {} + ArgType argType = UNSPECIFIED, + bool trans = false) + : buf_(buf), + valueType_(valueType), + shape_(shape), + argType_(argType), + trans_(trans) {} BufferArg(void* buf, ValueType valueType) : buf_(buf), valueType_(valueType) {} @@ -162,6 +169,7 @@ class BufferArg { ValueType valueType() const { return valueType_; } BufferType bufferType() const { return bufferType_; } const TensorShape& shape() const { return shape_; } + bool isTransposed() const { return trans_; } bool isSparseArg() const { return TENSOR_SPARSE == bufferType_; } bool isSequenceArg() const { return TENSOR_SEQUENCE_DATA == bufferType_; } @@ -175,6 +183,7 @@ class BufferArg { BufferType bufferType_{TENSOR_UNKNOWN}; ArgType argType_{UNSPECIFIED}; bool trans_{false}; + // todo(tianbing), add deviceType_ // leading dimensions. The size is dims_.size() // Dims lds_; }; @@ -267,8 +276,9 @@ class SparseMatrixArg : public BufferArg { size_t nnz, SparseFormat format, SparseValueType type, - ArgType argType = UNSPECIFIED) - : BufferArg(buf, valueType, shape, argType), + ArgType argType = UNSPECIFIED, + bool trans = false) + : BufferArg(buf, valueType, shape, argType, trans), row_(row), col_(col), nnz_(nnz), @@ -286,6 +296,33 @@ class SparseMatrixArg : public BufferArg { } } + SparseMatrixArg(ValueType valueType, + const TensorShape& shape, + size_t nnz, + SparseFormat format, + SparseValueType type, + ArgType argType = UNSPECIFIED, + bool trans = false) + : BufferArg(valueType, shape, argType, trans), + /// len of row_ : height + 1 (CSR), buf_ == nullptr + row_(format == SPARSE_CSR + ? BufferArg(VALUE_TYPE_INT32, TensorShape{shape[0] + 1}) + : BufferArg(VALUE_TYPE_INT32, TensorShape{nnz})), + /// len of col_ : width + 1 (CSC), buf_ == nullptr + col_(format == SPARSE_CSR + ? BufferArg(VALUE_TYPE_INT32, TensorShape{nnz}) + : BufferArg(VALUE_TYPE_INT32, TensorShape{shape[1] + 1})), + nnz_(nnz), + format_(format), + type_(type) { + bufferType_ = TENSOR_SPARSE; + /// todo(tianbing) + /// valueType and shape_.ndims() == 2 need to check before + /// this constructor to make sure row_ and col_ are right + CHECK((valueType == VALUE_TYPE_FLOAT) || (valueType == VALUE_TYPE_DOUBLE)); + CHECK_EQ(shape_.ndims(), (size_t)2); + } + SparseMatrixArg(const CpuSparseMatrix& sparse, ArgType argType = UNSPECIFIED); SparseMatrixArg(const GpuSparseMatrix& sparse, ArgType argType = UNSPECIFIED); diff --git a/paddle/function/FunctionTest.h b/paddle/function/FunctionTest.h index 24e7a36a43cfa8..9d38671bc3c5c9 100644 --- a/paddle/function/FunctionTest.h +++ b/paddle/function/FunctionTest.h @@ -13,6 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. */ #include "Function.h" +#include "paddle/math/Matrix.h" +#include "paddle/math/SparseMatrix.h" #include "paddle/math/Vector.h" #include "paddle/math/tests/TensorCheck.h" #include "paddle/testing/TestUtil.h" @@ -62,29 +64,41 @@ class FunctionCompare { cpuMemory_.emplace_back(std::make_shared(size)); gpuMemory_.emplace_back(std::make_shared(size)); - cpuInputs_.emplace_back(std::make_shared( - cpuMemory_.back()->getBuf(), input.valueType(), input.shape())); - gpuInputs_.emplace_back(std::make_shared( - gpuMemory_.back()->getBuf(), input.valueType(), input.shape())); + cpuInputs_.emplace_back( + std::make_shared(cpuMemory_.back()->getBuf(), + input.valueType(), + input.shape(), + UNSPECIFIED, + input.isTransposed())); + gpuInputs_.emplace_back( + std::make_shared(gpuMemory_.back()->getBuf(), + input.valueType(), + input.shape(), + UNSPECIFIED, + input.isTransposed())); } // output need only contains shape, do not contains data. - void addOutputs(const BufferArg& output) { + void addOutputs(const BufferArg& output, ArgType argType = ASSIGN_TO) { size_t size = output.shape().getElements() * sizeOfValuType(output.valueType()); cpuMemory_.emplace_back(std::make_shared(size)); gpuMemory_.emplace_back(std::make_shared(size)); - cpuOutputs_.emplace_back( - std::make_shared(cpuMemory_.back()->getBuf(), - output.valueType(), - output.shape(), - ASSIGN_TO)); - gpuOutputs_.emplace_back( - std::make_shared(gpuMemory_.back()->getBuf(), - output.valueType(), - output.shape(), - ASSIGN_TO)); + cpuOutputs_.emplace_back(std::make_shared( + cpuMemory_.back()->getBuf(), + output.valueType(), + output.shape(), + // todo(tianbing), argType = output.getArgType(), but default ASSIGN_TO + argType, + output.isTransposed())); + gpuOutputs_.emplace_back(std::make_shared( + gpuMemory_.back()->getBuf(), + output.valueType(), + output.shape(), + // todo(tianbing), argType = output.getArgType(), but default ASSIGN_TO + argType, + output.isTransposed())); } void addInputs(const SequenceArg& input) { @@ -107,10 +121,36 @@ class FunctionCompare { // TODO: need be implemented. } + void addInputs(const SparseMatrixArg& input) { + cpuSparse_ = std::make_shared(input.shape()[0], + input.shape()[1], + input.nnz(), + input.dataType(), + input.dataFormat(), + input.isTransposed()); + + gpuSparse_ = std::make_shared(input.shape()[0], + input.shape()[1], + input.nnz(), + input.dataType(), + input.dataFormat(), + input.isTransposed()); + + /// init sparse matrix + hl_stream_t stream(HPPL_STREAM_1); + cpuSparse_->randomizeUniform(); + gpuSparse_->copyFrom(*cpuSparse_, stream); + hl_stream_synchronize(stream); + + cpuInputs_.emplace_back(std::make_shared(*cpuSparse_)); + gpuInputs_.emplace_back(std::make_shared(*gpuSparse_)); + } + void run() { // prepare cpu/gpu arguments initInputs(); + initOutputs(); // function calculate auto callFunction = [](FunctionBase* function, std::vector& inputs, @@ -129,7 +169,7 @@ class FunctionCompare { callFunction(cpuFunc_.get(), cpuInputs_, cpuOutputs_); callFunction(gpuFunc_.get(), gpuInputs_, gpuOutputs_); - // check outputs and inouts + // check outputs compareOutputs(); } @@ -140,6 +180,10 @@ class FunctionCompare { protected: void initInputs() { for (size_t i = 0; i < cpuInputs_.size(); i++) { + if (cpuInputs_[i]->isSparseArg()) { + continue; /// sparse matrix already init + } + initArg(*cpuInputs_[i]); // TODO: Need a BufferCopy used to copy from one BufferArg to another. @@ -152,6 +196,25 @@ class FunctionCompare { } } + void initOutputs() { + for (size_t i = 0; i < cpuOutputs_.size(); i++) { + if (cpuOutputs_[i]->isSparseArg()) { + LOG(INFO) << "output sparse matrix already init"; + continue; + } + + initArg(*cpuOutputs_[i]); + + // TODO: Need a BufferCopy used to copy from one BufferArg to another. + CpuVector cpuVector(cpuOutputs_[i]->shape().getElements(), + (real*)cpuOutputs_[i]->data()); + GpuVector gpuVector(gpuOutputs_[i]->shape().getElements(), + (real*)gpuOutputs_[i]->data()); + + gpuVector.copyFrom(cpuVector); + } + } + void compareOutputs() { for (size_t i = 0; i < cpuOutputs_.size(); i++) { // TODO, Need a BufferCheck used to compare the two buffers. @@ -159,7 +222,6 @@ class FunctionCompare { auto gpu = gpuOutputs_[i]; CpuVector cpuVector(cpu->shape().getElements(), (real*)cpu->data()); GpuVector gpuVector(cpu->shape().getElements(), (real*)gpu->data()); - autotest::TensorCheckErr(cpuVector, gpuVector); } } @@ -195,6 +257,8 @@ class FunctionCompare { std::vector cpuOutputs_; std::vector gpuInputs_; std::vector gpuOutputs_; + std::shared_ptr cpuSparse_; + std::shared_ptr gpuSparse_; }; } // namespace paddle diff --git a/paddle/function/MulOp.h b/paddle/function/MulOp.h index b7b1f56af10375..fda5b0924982e8 100644 --- a/paddle/function/MulOp.h +++ b/paddle/function/MulOp.h @@ -15,6 +15,8 @@ limitations under the License. */ #pragma once #include "Function.h" +/// todo(tianbing), delete it +#include #include "paddle/math/Matrix.h" #include "paddle/math/SparseMatrix.h" diff --git a/paddle/function/MulOpTest.cpp b/paddle/function/MulOpTest.cpp index 965ffea20ce7fb..7300a2014bd8ed 100644 --- a/paddle/function/MulOpTest.cpp +++ b/paddle/function/MulOpTest.cpp @@ -24,58 +24,39 @@ limitations under the License. */ using namespace paddle; // NOLINT /** - * C = alpha * C + beta * (A * B), A, B, C dense matrix + * C += A * B, A, B, C dense matrix * dense = dense * dense */ -void testDDDMatrix(bool transa, bool transb, int dimM, int dimN, int dimK) { - real alpha = 1.5; - real beta = 2.0; - - const auto cpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-CPU"); - cpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); - const auto gpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-GPU"); - gpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); - - int heightA = (transa == false) ? dimM : dimK; - int widthA = (transa == false) ? dimK : dimM; - int heightB = (transb == false) ? dimK : dimN; - int widthB = (transb == false) ? dimN : dimK; - int heightC = dimM; - int widthC = dimN; - - auto cpuA = std::make_shared(heightA, widthA, transa); - auto cpuB = std::make_shared(heightB, widthB, transb); - auto cpuC = std::make_shared(heightC, widthC); - auto gpuA = std::make_shared(heightA, widthA, transa); - auto gpuB = std::make_shared(heightB, widthB, transb); - auto gpuC = std::make_shared(heightC, widthC); - - cpuA->randomizeUniform(); - cpuB->randomizeUniform(); - cpuC->randomizeUniform(); - gpuA->copyFrom(*cpuA); - gpuB->copyFrom(*cpuB); - gpuC->copyFrom(*cpuC); - - BufferArgs cpuInputs; - BufferArgs cpuOutputs; - cpuInputs.addArg(*cpuA); - cpuInputs.addArg(*cpuB); - cpuOutputs.addArg(*cpuC, ADD_TO); - cpuFunc->calc(cpuInputs, cpuOutputs); - - BufferArgs gpuInputs; - BufferArgs gpuOutputs; - gpuInputs.addArg(*gpuA); - gpuInputs.addArg(*gpuB); - gpuOutputs.addArg(*gpuC, ADD_TO); - gpuFunc->calc(gpuInputs, gpuOutputs); - - autotest::TensorCheckErr(*cpuC, *gpuC); +void testFuncDDDMatrix( + bool transa, bool transb, size_t dimM, size_t dimN, size_t dimK) { + real alpha = 1.0; + real beta = 1.0; + size_t heightA = (transa == false) ? dimM : dimK; + size_t widthA = (transa == false) ? dimK : dimM; + size_t heightB = (transb == false) ? dimK : dimN; + size_t widthB = (transb == false) ? dimN : dimK; + size_t heightC = dimM; + size_t widthC = dimN; + // init Test object + FunctionCompare test("MulOp", + FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); + // prepare input arguments + /// matrix A : HA * WA + test.addInputs(BufferArg( + VALUE_TYPE_FLOAT, TensorShape{heightA, widthA}, UNSPECIFIED, transa)); + /// matrix B: HB * WB + test.addInputs(BufferArg( + VALUE_TYPE_FLOAT, TensorShape{heightB, widthB}, UNSPECIFIED, transb)); + + /// output matrix C: HC * WC + test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{heightC, widthC}), + ADD_TO); + // run Function + test.run(); } -TEST(Matrix, DDDMul) { - LOG(INFO) << "test for dense = dense * dense matrix"; +TEST(MulOp, DDDMatrixMul) { + LOG(INFO) << "function test for dense = dense * dense matrix"; for (const auto transa : {false, true}) { for (const auto transb : {false, true}) { for (const auto dimM : {1, 10, 100}) { @@ -89,7 +70,7 @@ TEST(Matrix, DDDMul) { << " dimM=" << std::setw(5) << dimM << " dimN=" << std::setw(5) << dimN << " dimK=" << std::setw(5) << dimK; - testDDDMatrix(transa, transb, dimM, dimN, dimK); + testFuncDDDMatrix(transa, transb, dimM, dimN, dimK); } } } @@ -101,71 +82,33 @@ TEST(Matrix, DDDMul) { * C += A * B, B, C dense, A sparse * dense = sparse * dense */ -void testDSparseDMatrix( +void testFuncDSparseDMatrix( size_t dimM, size_t dimN, size_t dimK, size_t nnz, SparseFormat FORMAT) { real alpha = 1.0; real beta = 1.0; - const auto cpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-CPU"); - cpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); - const auto gpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-GPU"); - gpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); - - CpuSparseMatrix cpuMatrixA(dimM, dimK, nnz, FLOAT_VALUE, FORMAT, false); - GpuSparseMatrix gpuMatrixA(dimM, dimK, nnz, FLOAT_VALUE, FORMAT, false); - CpuMatrix cpuDenseA(dimM, dimK, false); - - auto cpuMatrixB = Matrix::create(dimK, dimN, false, false); - auto gpuMatrixB = Matrix::create(dimK, dimN, false, true); - auto cpuDenseB = Matrix::create(dimK, dimN, false, false); - - auto cpuMatrixC = Matrix::create(dimM, dimN, false, false); - auto gpuMatrixC = Matrix::create(dimM, dimN, false, true); - auto cpuDenseC = Matrix::create(dimM, dimN, false, false); - - /*matrix init*/ - hl_stream_t stream(HPPL_STREAM_1); - cpuMatrixA.randomizeUniform(); - cpuMatrixB->randomizeUniform(); - cpuMatrixC->randomizeUniform(); - - gpuMatrixA.copyFrom(cpuMatrixA, stream); - gpuMatrixB->copyFrom(*cpuMatrixB, stream); - gpuMatrixC->copyFrom(*cpuMatrixC, stream); - - cpuDenseA.copyFrom(cpuMatrixA); - cpuDenseB->copyFrom(*cpuMatrixB); - cpuDenseC->copyFrom(*cpuMatrixC); - hl_stream_synchronize(stream); - - /*matrix mul*/ - BufferArgs cpuInputs; - BufferArgs cpuOutputs; - cpuInputs.addArg(cpuMatrixA); - cpuInputs.addArg(*cpuMatrixB); - cpuOutputs.addArg(*cpuMatrixC, ADD_TO); - cpuFunc->calc(cpuInputs, cpuOutputs); - - BufferArgs gpuInputs; - BufferArgs gpuOutputs; - gpuInputs.addArg(gpuMatrixA); - gpuInputs.addArg(*gpuMatrixB); - gpuOutputs.addArg(*gpuMatrixC, ADD_TO); - gpuFunc->calc(gpuInputs, gpuOutputs); - - BufferArgs denseInputs; - BufferArgs denseOutputs; - denseInputs.addArg(cpuDenseA); - denseInputs.addArg(*cpuDenseB); - denseOutputs.addArg(*cpuDenseC, ADD_TO); - cpuFunc->calc(denseInputs, denseOutputs); - - /*check result*/ - autotest::TensorCheckErr(*cpuMatrixC, *cpuDenseC); - autotest::TensorCheckErr(*cpuMatrixC, *gpuMatrixC); + // init Test object + FunctionCompare test("MulOp", + FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); + // prepare input arguments + /// sparse matrix A : M * K + test.addInputs(SparseMatrixArg(VALUE_TYPE_FLOAT, + TensorShape{dimM, dimK}, + nnz, + FORMAT, + FLOAT_VALUE, + UNSPECIFIED, + false)); + /// matrix B: K * N + test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimK, dimN})); + + /// output matrix C: M * N + test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimM, dimN}), ADD_TO); + // run Function + test.run(); } -TEST(Matrix, DSparseDMul) { - LOG(INFO) << "test for dense = sparse * dense matrix"; +TEST(MuLOp, DSparseDMul) { + LOG(INFO) << "function test for dense = sparse * dense matrix"; for (const auto dimM : {10, 100, 1000}) { for (const auto dimN : {10, 100}) { for (const auto dimK : {3, 10}) { @@ -177,7 +120,7 @@ TEST(Matrix, DSparseDMul) { << " dimK=" << std::setw(5) << dimK << " nnz=" << std::setw(5) << nnz << " format=" << std::setw(5) << FORMAT; - testDSparseDMatrix(dimM, dimN, dimK, nnz, FORMAT); + testFuncDSparseDMatrix(dimM, dimN, dimK, nnz, FORMAT); } } } @@ -189,72 +132,34 @@ TEST(Matrix, DSparseDMul) { * C += A * B, A, C dense, B sparse * dense = dense * sparse */ -void testDDSparseMatrix( +void testFuncDDSparseMatrix( size_t dimM, size_t dimN, size_t dimK, size_t nnz, SparseFormat FORMAT) { real alpha = 1.0; real beta = 1.0; - const auto cpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-CPU"); - cpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); - const auto gpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-GPU"); - gpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); - - auto cpuMatrixA = Matrix::create(dimM, dimK, false, false); - auto gpuMatrixA = Matrix::create(dimM, dimK, false, true); - auto cpuDenseA = Matrix::create(dimM, dimK, false, false); - - CpuSparseMatrix cpuMatrixB(dimK, dimN, nnz, FLOAT_VALUE, FORMAT, false); - - GpuSparseMatrix gpuMatrixB(dimK, dimN, nnz, FLOAT_VALUE, FORMAT, false); - - auto cpuDenseB = Matrix::create(dimK, dimN, false, false); - auto cpuMatrixC = Matrix::create(dimM, dimN, false, false); - auto gpuMatrixC = Matrix::create(dimM, dimN, false, true); - auto cpuDenseC = Matrix::create(dimM, dimN, false, false); - - /*matrix init*/ - hl_stream_t stream(HPPL_STREAM_1); - cpuMatrixA->randomizeUniform(); - cpuMatrixB.randomizeUniform(); - cpuMatrixC->randomizeUniform(); - - gpuMatrixA->copyFrom(*cpuMatrixA, stream); - gpuMatrixB.copyFrom(cpuMatrixB, stream); - gpuMatrixC->copyFrom(*cpuMatrixC, stream); - - cpuDenseA->copyFrom(*cpuMatrixA); - cpuDenseB->copyFrom(cpuMatrixB); - cpuDenseC->copyFrom(*cpuMatrixC); - hl_stream_synchronize(stream); - - /*matrix mul*/ - BufferArgs cpuInputs; - BufferArgs cpuOutputs; - cpuInputs.addArg(*cpuMatrixA); - cpuInputs.addArg(cpuMatrixB); - cpuOutputs.addArg(*cpuMatrixC, ADD_TO); - cpuFunc->calc(cpuInputs, cpuOutputs); - - BufferArgs gpuInputs; - BufferArgs gpuOutputs; - gpuInputs.addArg(*gpuMatrixA); - gpuInputs.addArg(gpuMatrixB); - gpuOutputs.addArg(*gpuMatrixC, ADD_TO); - gpuFunc->calc(gpuInputs, gpuOutputs); - - BufferArgs denseInputs; - BufferArgs denseOutputs; - denseInputs.addArg(*cpuDenseA); - denseInputs.addArg(*cpuDenseB); - denseOutputs.addArg(*cpuDenseC, ADD_TO); - cpuFunc->calc(denseInputs, denseOutputs); - - /*check result*/ - autotest::TensorCheckErr(*cpuMatrixC, *cpuDenseC); - autotest::TensorCheckErr(*cpuMatrixC, *gpuMatrixC); + // init Test object + FunctionCompare test("MulOp", + FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); + // prepare input arguments + /// matrix A : M * K + test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimM, dimK})); + + /// matrix B: K * N + test.addInputs(SparseMatrixArg(VALUE_TYPE_FLOAT, + TensorShape{dimK, dimN}, + nnz, + FORMAT, + FLOAT_VALUE, + UNSPECIFIED, + false)); + + /// output matrix C: M * N + test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimM, dimN}), ADD_TO); + // run Function + test.run(); } -TEST(Matrix, DDSparseMul) { - LOG(INFO) << "test for dense = dense * sparse matrix"; +TEST(MulOp, DDSparseMul) { + LOG(INFO) << "function test for dense = dense * sparse matrix"; for (const auto dimM : {10, 100, 1000}) { for (const auto dimN : {10, 100}) { for (const auto dimK : {3, 10}) { @@ -266,7 +171,7 @@ TEST(Matrix, DDSparseMul) { << " dimK=" << std::setw(5) << dimK << " nnz=" << std::setw(5) << nnz << " format=" << std::setw(5) << FORMAT; - testDDSparseMatrix(dimM, dimN, dimK, nnz, FORMAT); + testFuncDDSparseMatrix(dimM, dimN, dimK, nnz, FORMAT); } } } From bc5d7bb6d221d7f921db70a8d1c7757bbff8ac15 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Sun, 22 Jan 2017 14:46:40 -0800 Subject: [PATCH 104/370] Add Sparse = dense * dense unit test with Daoyuan's Function test --- paddle/function/BufferArg.h | 3 ++ paddle/function/FunctionTest.h | 40 +++++++++++++--- paddle/function/MulOp.cpp | 7 +++ paddle/function/MulOpTest.cpp | 86 +++++++++------------------------- 4 files changed, 67 insertions(+), 69 deletions(-) diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index 17a4e4a6b0eec9..7565047a570778 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -172,6 +172,7 @@ class BufferArg { bool isTransposed() const { return trans_; } bool isSparseArg() const { return TENSOR_SPARSE == bufferType_; } bool isSequenceArg() const { return TENSOR_SEQUENCE_DATA == bufferType_; } + virtual size_t numElements() const { return shape_.getElements(); } const SequenceArg& sequence() const; const SparseMatrixArg& sparse() const; @@ -353,6 +354,8 @@ class SparseMatrixArg : public BufferArg { size_t nnz() const { return nnz_; } + size_t numElements() const override { return nnz_; } + SparseFormat dataFormat() const { return format_; } SparseValueType dataType() const { return type_; } diff --git a/paddle/function/FunctionTest.h b/paddle/function/FunctionTest.h index 9d38671bc3c5c9..6515cba1629c07 100644 --- a/paddle/function/FunctionTest.h +++ b/paddle/function/FunctionTest.h @@ -101,6 +101,34 @@ class FunctionCompare { output.isTransposed())); } + /// add and init output sparse matrix + void addOutputs(const SparseMatrixArg& output, ArgType argType = ASSIGN_TO) { + cpuSparse_ = std::make_shared(output.shape()[0], + output.shape()[1], + output.nnz(), + output.dataType(), + output.dataFormat(), + output.isTransposed()); + + gpuSparse_ = std::make_shared(output.shape()[0], + output.shape()[1], + output.nnz(), + output.dataType(), + output.dataFormat(), + output.isTransposed()); + + /// init sparse matrix + hl_stream_t stream(HPPL_STREAM_1); + cpuSparse_->randomizeUniform(); + gpuSparse_->copyFrom(*cpuSparse_, stream); + hl_stream_synchronize(stream); + + cpuOutputs_.emplace_back( + std::make_shared(*cpuSparse_, argType)); + gpuOutputs_.emplace_back( + std::make_shared(*gpuSparse_, argType)); + } + void addInputs(const SequenceArg& input) { size_t batchSize = input.shape()[0]; size_t numSeqs = batchSize / 10 + 1; @@ -199,8 +227,7 @@ class FunctionCompare { void initOutputs() { for (size_t i = 0; i < cpuOutputs_.size(); i++) { if (cpuOutputs_[i]->isSparseArg()) { - LOG(INFO) << "output sparse matrix already init"; - continue; + continue; /// sparse matrix already init } initArg(*cpuOutputs_[i]); @@ -218,10 +245,11 @@ class FunctionCompare { void compareOutputs() { for (size_t i = 0; i < cpuOutputs_.size(); i++) { // TODO, Need a BufferCheck used to compare the two buffers. - auto cpu = cpuOutputs_[i]; - auto gpu = gpuOutputs_[i]; - CpuVector cpuVector(cpu->shape().getElements(), (real*)cpu->data()); - GpuVector gpuVector(cpu->shape().getElements(), (real*)gpu->data()); + const auto cpu = cpuOutputs_[i]; + const auto gpu = gpuOutputs_[i]; + CHECK_EQ(cpu->numElements(), gpu->numElements()); + CpuVector cpuVector(cpu->numElements(), (real*)cpu->data()); + GpuVector gpuVector(gpu->numElements(), (real*)gpu->data()); autotest::TensorCheckErr(cpuVector, gpuVector); } } diff --git a/paddle/function/MulOp.cpp b/paddle/function/MulOp.cpp index bd3bc5c087d669..4d7f1a7fa92a56 100644 --- a/paddle/function/MulOp.cpp +++ b/paddle/function/MulOp.cpp @@ -319,6 +319,13 @@ class MulFunc : public FunctionBase { auto outSparseMat = outputs[0].sparse().SparseMatrix(); if (!inputs[0].isSparseArg() && !inputs[1].isSparseArg() && outputs[0].isSparseArg()) { + /* + LOG(INFO) << "input0"; + inputs[0].matrix().print(std::cout); + LOG(INFO) << "input1"; + inputs[1].matrix().print(std::cout); + LOG(INFO) << "output sparse matrix"; + outSparseMat.print(std::cout); */ MulOp(outSparseMat, inputs[0].matrix(), inputs[1].matrix(), diff --git a/paddle/function/MulOpTest.cpp b/paddle/function/MulOpTest.cpp index 7300a2014bd8ed..05460c80970d93 100644 --- a/paddle/function/MulOpTest.cpp +++ b/paddle/function/MulOpTest.cpp @@ -183,75 +183,35 @@ TEST(MulOp, DDSparseMul) { * C += A * B, A sparse, B, C dense * sparse = dense * dense */ -void testSparseDDMatrix( +void testFuncSparseDDMatrix( size_t dimM, size_t dimN, size_t dimK, size_t nnz, SparseFormat FORMAT) { real alpha = 1.0; real beta = 1.0; - const auto cpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-CPU"); - cpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); - const auto gpuFunc = FunctionBase::funcRegistrar_.createByType("MulOp-GPU"); - gpuFunc->init(FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); - - auto cpuMatrixA = Matrix::create(dimM, dimK, false, false); - auto gpuMatrixA = Matrix::create(dimM, dimK, false, true); - auto cpuDenseA = Matrix::create(dimM, dimK, false, false); - - auto cpuMatrixB = Matrix::create(dimK, dimN, false, false); - auto gpuMatrixB = Matrix::create(dimK, dimN, false, true); - auto cpuDenseB = Matrix::create(dimK, dimN, false, false); - - CpuSparseMatrix cpuMatrixC(dimM, dimN, nnz, FLOAT_VALUE, FORMAT, false); - CpuSparseMatrix gpuMatrixC_d2h(dimM, dimN, nnz, FLOAT_VALUE, FORMAT, false); - GpuSparseMatrix gpuMatrixC(dimM, dimN, nnz, FLOAT_VALUE, FORMAT, false); - CpuMatrix cpuDenseC(dimM, dimN, false); - - /*matrix init*/ - hl_stream_t stream(HPPL_STREAM_1); - cpuMatrixA->randomizeUniform(); - cpuMatrixB->randomizeUniform(); - cpuMatrixC.randomizeUniform(); - - gpuMatrixA->copyFrom(*cpuMatrixA, stream); - gpuMatrixB->copyFrom(*cpuMatrixB, stream); - gpuMatrixC.copyFrom(cpuMatrixC, stream); - - cpuDenseA->copyFrom(*cpuMatrixA); - cpuDenseB->copyFrom(*cpuMatrixB); - cpuDenseC.copyFrom(cpuMatrixC); - hl_stream_synchronize(stream); - - /*matrix mul*/ - BufferArgs cpuInputs; - BufferArgs cpuOutputs; - cpuInputs.addArg(*cpuMatrixA); - cpuInputs.addArg(*cpuMatrixB); - cpuOutputs.addArg(cpuMatrixC, ADD_TO); - cpuFunc->calc(cpuInputs, cpuOutputs); - - BufferArgs gpuInputs; - BufferArgs gpuOutputs; - gpuInputs.addArg(*gpuMatrixA); - gpuInputs.addArg(*gpuMatrixB); - gpuOutputs.addArg(gpuMatrixC, ADD_TO); - gpuFunc->calc(gpuInputs, gpuOutputs); - - BufferArgs denseInputs; - BufferArgs denseOutputs; - denseInputs.addArg(*cpuDenseA); - denseInputs.addArg(*cpuDenseB); - denseOutputs.addArg(cpuDenseC, ADD_TO); - cpuFunc->calc(denseInputs, denseOutputs); + // init Test object + FunctionCompare test("MulOp", + FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); + // prepare input arguments + /// matrix A : M * K + test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimM, dimK})); - gpuMatrixC_d2h.copyFrom(gpuMatrixC, stream); - hl_stream_synchronize(stream); + /// matrix B: K * N + test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimK, dimN})); - /*check result*/ - checkSMatrixEqual(cpuMatrixC, gpuMatrixC_d2h); - checkSMatrixEqual2Dense(cpuMatrixC, cpuDenseC); + /// output sparse matrix C: M * N + test.addOutputs(SparseMatrixArg(VALUE_TYPE_FLOAT, + TensorShape{dimM, dimN}, + nnz, + FORMAT, + FLOAT_VALUE, + UNSPECIFIED, + false), + ADD_TO); + // run Function + test.run(); } -TEST(Matrix, SparseDDMul) { - LOG(INFO) << "test for sparse = dense * dense matrix"; +TEST(MulOp, SparseDDMul) { + LOG(INFO) << "function test for sparse = dense * dense matrix"; for (const auto dimM : {10, 100, 1000}) { for (const auto dimN : {10, 100}) { for (const auto dimK : {3, 10}) { @@ -263,7 +223,7 @@ TEST(Matrix, SparseDDMul) { << " dimK=" << std::setw(5) << dimK << " nnz=" << std::setw(5) << nnz << " format=" << std::setw(5) << FORMAT; - testSparseDDMatrix(dimM, dimN, dimK, nnz, FORMAT); + testFuncSparseDDMatrix(dimM, dimN, dimK, nnz, FORMAT); } } } From b3be73580717f571d37bb655887d6449024d0ab7 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Mon, 23 Jan 2017 15:00:36 -0800 Subject: [PATCH 105/370] Daoyuan's comments. --- paddle/function/BufferArg.h | 37 +++---- paddle/function/FunctionTest.h | 40 +++----- paddle/function/MulOp.cpp | 173 ++++++++++++++++----------------- paddle/function/MulOp.h | 40 ++++++-- paddle/function/MulOpGpu.cu | 114 +++++++--------------- paddle/function/MulOpTest.cpp | 72 +++++++------- 6 files changed, 217 insertions(+), 259 deletions(-) diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index 7565047a570778..f3634364ab29f7 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -71,24 +71,17 @@ class BufferArg { public: BufferArg(ValueType valueType, const TensorShape& shape, - ArgType argType = UNSPECIFIED, - bool trans = false) + ArgType argType = UNSPECIFIED) : buf_(nullptr), valueType_(valueType), shape_(shape), - argType_(argType), - trans_(trans) {} + argType_(argType) {} BufferArg(void* buf, ValueType valueType, const TensorShape& shape, - ArgType argType = UNSPECIFIED, - bool trans = false) - : buf_(buf), - valueType_(valueType), - shape_(shape), - argType_(argType), - trans_(trans) {} + ArgType argType = UNSPECIFIED) + : buf_(buf), valueType_(valueType), shape_(shape), argType_(argType) {} BufferArg(void* buf, ValueType valueType) : buf_(buf), valueType_(valueType) {} @@ -98,8 +91,7 @@ class BufferArg { const_cast(reinterpret_cast(matrix.getData()))), valueType_(DataType::value), shape_(2), - argType_(argType), - trans_(matrix.isTransposed()) { + argType_(argType) { bufferType_ = TENSOR_NORMAL; shape_.setDim(0, matrix.getHeight()); shape_.setDim(1, matrix.getWidth()); @@ -112,8 +104,7 @@ class BufferArg { const_cast(reinterpret_cast(matrix.getData()))), valueType_(DataType::value), shape_(shape), - argType_(argType), - trans_(matrix.isTransposed()) { + argType_(argType) { bufferType_ = TENSOR_NORMAL; CHECK_EQ(matrix.getElementCnt(), shape.getElements()); } @@ -145,7 +136,7 @@ class BufferArg { // CHECK(deviceType_ == DType); CHECK_EQ((size_t)2, shape_.ndims()); return typename Tensor::Matrix( - reinterpret_cast(buf_), shape_[0], shape_[1], trans_); + reinterpret_cast(buf_), shape_[0], shape_[1]); } template @@ -169,7 +160,6 @@ class BufferArg { ValueType valueType() const { return valueType_; } BufferType bufferType() const { return bufferType_; } const TensorShape& shape() const { return shape_; } - bool isTransposed() const { return trans_; } bool isSparseArg() const { return TENSOR_SPARSE == bufferType_; } bool isSequenceArg() const { return TENSOR_SEQUENCE_DATA == bufferType_; } virtual size_t numElements() const { return shape_.getElements(); } @@ -183,7 +173,6 @@ class BufferArg { TensorShape shape_; BufferType bufferType_{TENSOR_UNKNOWN}; ArgType argType_{UNSPECIFIED}; - bool trans_{false}; // todo(tianbing), add deviceType_ // leading dimensions. The size is dims_.size() // Dims lds_; @@ -277,9 +266,8 @@ class SparseMatrixArg : public BufferArg { size_t nnz, SparseFormat format, SparseValueType type, - ArgType argType = UNSPECIFIED, - bool trans = false) - : BufferArg(buf, valueType, shape, argType, trans), + ArgType argType = UNSPECIFIED) + : BufferArg(buf, valueType, shape, argType), row_(row), col_(col), nnz_(nnz), @@ -302,9 +290,8 @@ class SparseMatrixArg : public BufferArg { size_t nnz, SparseFormat format, SparseValueType type, - ArgType argType = UNSPECIFIED, - bool trans = false) - : BufferArg(valueType, shape, argType, trans), + ArgType argType = UNSPECIFIED) + : BufferArg(valueType, shape, argType), /// len of row_ : height + 1 (CSR), buf_ == nullptr row_(format == SPARSE_CSR ? BufferArg(VALUE_TYPE_INT32, TensorShape{shape[0] + 1}) @@ -343,7 +330,7 @@ class SparseMatrixArg : public BufferArg { nnz_, type_, format_, - trans_); + false); } ~SparseMatrixArg() {} diff --git a/paddle/function/FunctionTest.h b/paddle/function/FunctionTest.h index 6515cba1629c07..baa94abffa09b6 100644 --- a/paddle/function/FunctionTest.h +++ b/paddle/function/FunctionTest.h @@ -64,22 +64,14 @@ class FunctionCompare { cpuMemory_.emplace_back(std::make_shared(size)); gpuMemory_.emplace_back(std::make_shared(size)); - cpuInputs_.emplace_back( - std::make_shared(cpuMemory_.back()->getBuf(), - input.valueType(), - input.shape(), - UNSPECIFIED, - input.isTransposed())); - gpuInputs_.emplace_back( - std::make_shared(gpuMemory_.back()->getBuf(), - input.valueType(), - input.shape(), - UNSPECIFIED, - input.isTransposed())); + cpuInputs_.emplace_back(std::make_shared( + cpuMemory_.back()->getBuf(), input.valueType(), input.shape())); + gpuInputs_.emplace_back(std::make_shared( + gpuMemory_.back()->getBuf(), input.valueType(), input.shape())); } // 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 = ADD_TO) { size_t size = output.shape().getElements() * sizeOfValuType(output.valueType()); cpuMemory_.emplace_back(std::make_shared(size)); @@ -89,16 +81,14 @@ class FunctionCompare { cpuMemory_.back()->getBuf(), output.valueType(), output.shape(), - // todo(tianbing), argType = output.getArgType(), but default ASSIGN_TO - argType, - output.isTransposed())); + // todo(tianbing), argType = output.getArgType(), but default ADD_TO + argType)); gpuOutputs_.emplace_back(std::make_shared( gpuMemory_.back()->getBuf(), output.valueType(), output.shape(), - // todo(tianbing), argType = output.getArgType(), but default ASSIGN_TO - argType, - output.isTransposed())); + // todo(tianbing), argType = output.getArgType(), but default ADD_TO + argType)); } /// add and init output sparse matrix @@ -107,15 +97,13 @@ class FunctionCompare { output.shape()[1], output.nnz(), output.dataType(), - output.dataFormat(), - output.isTransposed()); + output.dataFormat()); gpuSparse_ = std::make_shared(output.shape()[0], output.shape()[1], output.nnz(), output.dataType(), - output.dataFormat(), - output.isTransposed()); + output.dataFormat()); /// init sparse matrix hl_stream_t stream(HPPL_STREAM_1); @@ -154,15 +142,13 @@ class FunctionCompare { input.shape()[1], input.nnz(), input.dataType(), - input.dataFormat(), - input.isTransposed()); + input.dataFormat()); gpuSparse_ = std::make_shared(input.shape()[0], input.shape()[1], input.nnz(), input.dataType(), - input.dataFormat(), - input.isTransposed()); + input.dataFormat()); /// init sparse matrix hl_stream_t stream(HPPL_STREAM_1); diff --git a/paddle/function/MulOp.cpp b/paddle/function/MulOp.cpp index 4d7f1a7fa92a56..965115121eb967 100644 --- a/paddle/function/MulOp.cpp +++ b/paddle/function/MulOp.cpp @@ -46,21 +46,11 @@ void MulOp(CpuSparseMatrix& out, const CpuMatrix& a, const CpuMatrix& b, real scaleAB, - real scaleT) { - CHECK(!out.isTransposed()) << "Not supported"; + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans) { CHECK_EQ(out.getValueType(), FLOAT_VALUE); - CHECK(!a.isTransposed() || !b.isTransposed()) - << "Not support both a and b are transpose matrices"; - - size_t height = out.getHeight(); - size_t width = out.getWidth(); - size_t aRow = !a.isTransposed() ? a.getHeight() : a.getWidth(); - size_t aCol = !a.isTransposed() ? a.getWidth() : a.getHeight(); - size_t bRow = !b.isTransposed() ? b.getHeight() : b.getWidth(); - size_t bCol = !b.isTransposed() ? b.getWidth() : b.getHeight(); - /// C = A * B, for matrix format - CHECK(aCol == bRow && aRow == height && bCol == width); - if (scaleT == 0) { out.zeroMem(); } @@ -69,12 +59,14 @@ void MulOp(CpuSparseMatrix& out, real* C = out.getValue(); int* rows = out.getRows(); int* cols = out.getCols(); + size_t width = out.getWidth(); + size_t height = out.getHeight(); /// SPARSE_CSC, {a any, b not trans} if (out.getFormat() == SPARSE_CSC) { /// b not trans and a any - CHECK(!b.isTransposed()); - size_t m = !a.isTransposed() ? a.getWidth() : a.getHeight(); + CHECK(!bTrans); + size_t m = !aTrans ? a.getWidth() : a.getHeight(); for (size_t i = 0; i < width; i++) { size_t start = out.getColStartIdx(i); size_t end = out.getColStartIdx(i + 1); @@ -82,9 +74,8 @@ void MulOp(CpuSparseMatrix& out, real sum = 0; size_t rowIdx = rows[j]; for (size_t k = 0; k < m; k++) { - sum += - (!a.isTransposed() ? A[rowIdx * m + k] : A[k * height + rowIdx]) * - B[k * width + i]; + sum += (!aTrans ? A[rowIdx * m + k] : A[k * height + rowIdx]) * + B[k * width + i]; } C[j] = scaleAB * sum + scaleT * C[j]; } @@ -95,7 +86,7 @@ void MulOp(CpuSparseMatrix& out, /// SPARSE_CSR, {a any, b not trans} or {a not trans, b trans} if (out.getFormat() == SPARSE_CSR) { /// a and b can not both transpose - CHECK(!(a.isTransposed() && b.isTransposed())); + CHECK(!(aTrans && bTrans)); size_t m = a.getWidth(); for (size_t i = 0; i < height; i++) { size_t start = out.getRowStartIdx(i); @@ -104,9 +95,8 @@ void MulOp(CpuSparseMatrix& out, real sum = 0; size_t colIdx = cols[j]; for (size_t k = 0; k < m; k++) { - sum += - (!a.isTransposed() ? A[i * m + k] : A[k * height + i]) * - (!b.isTransposed() ? B[k * width + colIdx] : B[colIdx * m + k]); + sum += (!aTrans ? A[i * m + k] : A[k * height + i]) * + (!bTrans ? B[k * width + colIdx] : B[colIdx * m + k]); } C[j] = scaleAB * sum + scaleT * C[j]; } @@ -120,25 +110,15 @@ void MulOp(CpuMatrix& out, const CpuMatrix& a, const CpuMatrix& b, real scaleAB, - real scaleT) { - CHECK(!out.isTransposed()) << "out matrix transpose not supported"; - CBLAS_TRANSPOSE aTrans = a.isTransposed() ? CblasTrans : CblasNoTrans; - size_t aRow = a.isTransposed() ? a.getWidth() : a.getHeight(); - size_t aCol = a.isTransposed() ? a.getHeight() : a.getWidth(); - CBLAS_TRANSPOSE bTrans = b.isTransposed() ? CblasTrans : CblasNoTrans; - size_t bRow = b.isTransposed() ? b.getWidth() : b.getHeight(); - size_t bCol = b.isTransposed() ? b.getHeight() : b.getWidth(); - - /// C = A * B, for matrix format - CHECK_EQ(aCol, bRow); - CHECK_EQ(aRow, out.getHeight()); - CHECK_EQ(bCol, out.getWidth()); - - GEMM(aTrans, - bTrans, + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans) { + GEMM(aTrans ? CblasTrans : CblasNoTrans, + bTrans ? CblasTrans : CblasNoTrans, out.getHeight(), out.getWidth(), - aCol, + !aTrans ? a.getWidth() : a.getHeight(), scaleAB, a.getData(), a.getStride(), @@ -154,21 +134,12 @@ void MulOp(CpuMatrix& out, const CpuSparseMatrix& a, const CpuMatrix& b, real scaleAB, - real scaleT) { - CHECK(!out.isTransposed()) << "Not supported"; - CHECK(!b.isTransposed()) << "Not supported"; - CHECK(scaleT == 0 || scaleT == 1) << "Not support"; - CHECK_EQ(scaleAB, static_cast(1.0)) << "Not supported"; - CHECK_EQ(a.getFormat(), SPARSE_CSR) << "Not supported"; - - if (!a.isTransposed()) { - CHECK(b.getHeight() == a.getWidth() && a.getHeight() == out.getHeight() && - b.getWidth() == out.getWidth()); - } else { - CHECK(b.getHeight() == a.getHeight() && a.getWidth() == out.getHeight() && - b.getWidth() == out.getWidth()); - } - + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans) { + CHECK_EQ(a.getFormat(), SPARSE_CSR) + << "Not supported SPARSE_CSR format for a"; if (scaleT == 0) { out.zeroMem(); } @@ -185,9 +156,9 @@ void MulOp(CpuMatrix& out, const int start = a.getRowStartIdx(i); const int end = a.getRowStartIdx(i + 1); for (int j = start; j < end; ++j) { - vecAddTo(!a.isTransposed() ? out.getRow(i) : out.getRow(cols[j]), - !a.isTransposed() ? const_cast(b).getRow(cols[j]) - : const_cast(b).getRow(i), + vecAddTo(!aTrans ? out.getRow(i) : out.getRow(cols[j]), + !aTrans ? const_cast(b).getRow(cols[j]) + : const_cast(b).getRow(i), (a.getValueType() == FLOAT_VALUE) ? values[j] : (real)1.0, out.getWidth()); } @@ -199,19 +170,10 @@ void MulOp(CpuMatrix& out, const CpuMatrix& a, const CpuSparseMatrix& b, real scaleAB, - real scaleT) { - CHECK(!out.trans_) << "Not supported"; - CHECK(!a.isTransposed()) << "Not supported"; - CHECK(scaleT == 0 || scaleT == 1); - CHECK_EQ(scaleAB, static_cast(1.0)); - if (!b.isTransposed()) { /// b is not Transpose - CHECK(b.getHeight() == a.getWidth() && a.getHeight() == out.getHeight() && - b.getWidth() == out.getWidth()); - } else { - CHECK(b.getHeight() == out.getWidth() && a.getHeight() == out.getHeight() && - b.getWidth() == a.getWidth()); - } - + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans) { if (scaleT == 0) { out.zeroMem(); } @@ -227,8 +189,8 @@ void MulOp(CpuMatrix& out, int start = b.getColStartIdx(j); int end = b.getColStartIdx(j + 1); for (int i = start; i < end; ++i) { - colVecAddTo(!b.isTransposed() ? C + j : C + rows[i], - !b.isTransposed() ? A + rows[i] : A + j, + colVecAddTo(!bTrans ? C + j : C + rows[i], + !bTrans ? A + rows[i] : A + j, (b.getValueType() == NO_VALUE) ? (real)1.0 : B[i], out.getHeight(), out.getWidth(), @@ -244,8 +206,8 @@ void MulOp(CpuMatrix& out, int start = b.getRowStartIdx(j); int end = b.getRowStartIdx(j + 1); for (int i = start; i < end; ++i) { - colVecAddTo(!b.isTransposed() ? C + cols[i] : C + j, - !b.isTransposed() ? A + j : A + cols[i], + colVecAddTo(!bTrans ? C + cols[i] : C + j, + !bTrans ? A + j : A + cols[i], (b.getValueType() == NO_VALUE) ? (real)1.0 : B[i], out.getHeight(), out.getWidth(), @@ -270,16 +232,43 @@ class MulFunc : public FunctionBase { void init(const FuncConfig& config) override { alpha_ = config.get("scaleAB"); beta_ = config.get("scaleT"); + aTrans_ = config.get("aTrans"); + bTrans_ = config.get("bTrans"); + cTrans_ = config.get("cTrans"); } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { + CHECK(!cTrans_) << "output matrix should not be transposed"; + CHECK(!aTrans_ || !bTrans_) + << "Not support both a and b are transpose matrices"; + CHECK_EQ((size_t)2, inputs.size()); CHECK_EQ((size_t)1, outputs.size()); CHECK(inputs[0].data() && inputs[1].data() && outputs[0].data()); CHECK_EQ(inputs[0].shape().ndims(), (size_t)2); CHECK_EQ(inputs[1].shape().ndims(), (size_t)2); CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); - CHECK_EQ(outputs[0].getArgType(), ADD_TO); + + size_t aRow = !aTrans_ ? inputs[0].shape()[0] : inputs[0].shape()[1]; + size_t aCol = !aTrans_ ? inputs[0].shape()[1] : inputs[0].shape()[0]; + size_t bRow = !bTrans_ ? inputs[1].shape()[0] : inputs[1].shape()[1]; + size_t bCol = !bTrans_ ? inputs[1].shape()[1] : inputs[1].shape()[0]; + /// C = A * B, or C += A * B, for matrix format + CHECK_EQ(aCol, bRow); + CHECK_EQ(aRow, outputs[0].shape()[0]); + CHECK_EQ(bCol, outputs[0].shape()[1]); + + /// only support C = A * B or C += A * B + CHECK_EQ(alpha_, static_cast(1.0)); + CHECK((beta_ == 0 && outputs[0].getArgType() == ASSIGN_TO) || + (beta_ == 1 && outputs[0].getArgType() == ADD_TO)); + + /// support dense = not both sparse * sparse + /// or sparse = dense * dense + CHECK((!outputs[0].isSparseArg() && + !(inputs[0].isSparseArg() && inputs[1].isSparseArg())) || + (outputs[0].isSparseArg() && !inputs[0].isSparseArg() && + !inputs[1].isSparseArg())); auto outMat = outputs[0].matrix(); /// matrix = matrix * matrix @@ -289,29 +278,40 @@ class MulFunc : public FunctionBase { inputs[0].matrix(), inputs[1].matrix(), alpha_, - beta_); + beta_, + aTrans_, + bTrans_, + cTrans_); return; } /// matrix = matrix * sparse matrix if (!inputs[0].isSparseArg() && inputs[1].isSparseArg() && !outputs[0].isSparseArg()) { + CHECK(!aTrans_) << "Not supported a transpose"; MulOp(outMat, inputs[0].matrix(), inputs[1].sparse().SparseMatrix(), alpha_, - beta_); + beta_, + aTrans_, + bTrans_, + cTrans_); return; } /// matrix = sparse matrix * matrix if (inputs[0].isSparseArg() && !inputs[1].isSparseArg() && !outputs[0].isSparseArg()) { + CHECK(!bTrans_) << "Not supported b transpose"; MulOp(outMat, inputs[0].sparse().SparseMatrix(), inputs[1].matrix(), alpha_, - beta_); + beta_, + aTrans_, + bTrans_, + cTrans_); return; } @@ -319,18 +319,14 @@ class MulFunc : public FunctionBase { auto outSparseMat = outputs[0].sparse().SparseMatrix(); if (!inputs[0].isSparseArg() && !inputs[1].isSparseArg() && outputs[0].isSparseArg()) { - /* - LOG(INFO) << "input0"; - inputs[0].matrix().print(std::cout); - LOG(INFO) << "input1"; - inputs[1].matrix().print(std::cout); - LOG(INFO) << "output sparse matrix"; - outSparseMat.print(std::cout); */ MulOp(outSparseMat, inputs[0].matrix(), inputs[1].matrix(), alpha_, - beta_); + beta_, + aTrans_, + bTrans_, + cTrans_); return; } } @@ -338,6 +334,9 @@ class MulFunc : public FunctionBase { private: real alpha_; real beta_; + bool aTrans_; + bool bTrans_; + bool cTrans_; }; REGISTER_TYPED_FUNC(MulOp, CPU, MulFunc); diff --git a/paddle/function/MulOp.h b/paddle/function/MulOp.h index fda5b0924982e8..a7703482255fec 100644 --- a/paddle/function/MulOp.h +++ b/paddle/function/MulOp.h @@ -26,55 +26,79 @@ void MulOp(CpuMatrix& out, const CpuMatrix& a, const CpuMatrix& b, real scaleAB, - real scaleT); + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans); template void MulOp(CpuMatrix& out, const CpuSparseMatrix& a, const CpuMatrix& b, real scaleAB, - real scaleT); + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans); template void MulOp(CpuMatrix& out, const CpuMatrix& a, const CpuSparseMatrix& b, real scaleAB, - real scaleT); + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans); template void MulOp(CpuSparseMatrix& out, const CpuMatrix& a, const CpuMatrix& b, real scaleAB, - real scaleT); + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans); template void MulOp(GpuMatrix& out, const GpuMatrix& a, const GpuMatrix& b, real scaleAB, - real scaleT); + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans); template void MulOp(GpuMatrix& out, const GpuSparseMatrix& a, const GpuMatrix& b, real scaleAB, - real scaleT); + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans); template void MulOp(GpuMatrix& out, const GpuMatrix& a, const GpuSparseMatrix& b, real scaleAB, - real scaleT); + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans); template void MulOp(GpuSparseMatrix& out, const GpuMatrix& a, const GpuMatrix& b, real scaleAB, - real scaleT); + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans); } // namespace paddle diff --git a/paddle/function/MulOpGpu.cu b/paddle/function/MulOpGpu.cu index 09d2a764911f18..94bee72034ff28 100644 --- a/paddle/function/MulOpGpu.cu +++ b/paddle/function/MulOpGpu.cu @@ -27,38 +27,22 @@ void MulOp(GpuMatrix& out, const GpuMatrix& a, const GpuMatrix& b, real scaleAB, - real scaleT) { - CHECK(!out.isTransposed()) << "Transpose not supported for out matrix"; - if (!a.isTransposed() && !b.isTransposed()) { - /// a : M * K, b: K * N - CHECK(out.getWidth() == b.getWidth() && - out.getHeight() == a.getHeight() && - a.getWidth() == b.getHeight()); - } else if (a.isTransposed() && !b.isTransposed()) { - /// a : K * M, b : K * N - CHECK(out.getWidth() == b.getWidth() && - out.getHeight() == a.getWidth() && - a.getHeight() == b.getHeight()); - } else if (!a.isTransposed() && b.isTransposed()) { - /// a: M * K, b : N * K - CHECK(out.getWidth() == b.getHeight() && - out.getHeight() == a.getHeight() && - a.getWidth() == b.getWidth()); - } else { - LOG(FATAL) << "Not support for both a and b are Transposed Matrices"; - } - + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans) { + CHECK(a.useGpu_ && b.useGpu_) << "matrix device type not match"; real* aData = const_cast(a.getData()); real* bData = const_cast(b.getData()); real* outData = const_cast(out.getData()); hl_matrix_mul(aData, - !a.isTransposed() ? HPPL_OP_N : HPPL_OP_T, + !aTrans ? HPPL_OP_N : HPPL_OP_T, bData, - !b.isTransposed() ? HPPL_OP_N : HPPL_OP_T, + !bTrans ? HPPL_OP_N : HPPL_OP_T, outData, out.getHeight(), out.getWidth(), - !a.isTransposed() ? a.getWidth() : a.getHeight(), + !aTrans ? a.getWidth() : a.getHeight(), scaleAB, scaleT, a.getStride(), @@ -75,27 +59,19 @@ void MulOp(GpuMatrix& out, const GpuSparseMatrix& a, const GpuMatrix& b, real scaleAB, - real scaleT) { + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans) { CHECK(out.isContiguous()); CHECK(b.isContiguous()); - CHECK(b.useGpu_) << "Matrix type are not equal"; - CHECK(!out.isTransposed() && !b.isTransposed()) << "not supported"; - if (!a.isTransposed()) { - /// a: M * K, b: K * N - CHECK(out.getWidth() == b.getWidth() && out.getHeight() == a.getHeight() - && a.getWidth() == b.getHeight()) << "Matrix dimensions are not equal"; - } else { - /// a: K * M, transpose, b: K * N - CHECK(out.getWidth() == b.getWidth() && out.getHeight() == a.getWidth() - && a.getHeight() == b.getHeight()) << "Matrix dimensions are not equal"; - } + CHECK(a.useGpu_ && b.useGpu_) << "matrix device type not match"; - hl_trans_op_t aTrans = a.isTransposed() ? HPPL_OP_T : HPPL_OP_N; hl_sparse_matrix_s aData = a.sMatrix_.get(); real* bData = const_cast(b.getData()); real* outData = const_cast(out.getData()); hl_matrix_csr_mul_dense(aData, - aTrans, + aTrans ? HPPL_OP_T : HPPL_OP_N, bData, HPPL_OP_N, outData, @@ -115,25 +91,14 @@ void MulOp(GpuMatrix& out, const GpuMatrix& a, const GpuSparseMatrix& b, real scaleAB, - real scaleT) { + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans) { CHECK(out.isContiguous()); CHECK(a.isContiguous()); - CHECK(a.useGpu_) << "Matrix type are not equal"; - if (!b.isTransposed()) { - /// a : M * K, b : K * N - CHECK(out.getWidth() == b.getWidth() && - out.getHeight() == a.getHeight() && - a.getWidth() == b.getHeight()) - << "Matrix dimensions are not equal"; - } else { - /// a : M * K, b : N * K, transpose - CHECK(out.getWidth() == b.getHeight() && - out.getHeight() == a.getHeight() && - a.getWidth() == b.getWidth()) - << "Matrix dimensions are not equal"; - } + CHECK(a.useGpu_ && b.useGpu_) << "matrix device type not match"; - hl_trans_op_t bTrans = b.isTransposed() ? HPPL_OP_T : HPPL_OP_N; hl_sparse_matrix_s bData = b.sMatrix_.get(); real* aData = const_cast(a.getData()); real* outData = const_cast(out.getData()); @@ -142,7 +107,7 @@ void MulOp(GpuMatrix& out, hl_matrix_dense_mul_csc(aData, HPPL_OP_N, bData, - bTrans, + bTrans ? HPPL_OP_T : HPPL_OP_N, outData, out.getHeight(), out.getWidth(), @@ -153,7 +118,7 @@ void MulOp(GpuMatrix& out, hl_matrix_dense_mul_csr(aData, HPPL_OP_N, bData, - bTrans, + bTrans ? HPPL_OP_T : HPPL_OP_N, outData, out.getHeight(), out.getWidth(), @@ -168,35 +133,26 @@ void MulOp(GpuSparseMatrix& out, const GpuMatrix& a, const GpuMatrix& b, real scaleAB, - real scaleT) { + real scaleT, + bool aTrans, + bool bTrans, + bool cTrans) { CHECK(a.useGpu_ && b.useGpu_) << "matrix device type not match"; - CHECK(!out.isTransposed()) << "Transpose is not supported for out matrix"; - - if (!a.isTransposed() && !b.isTransposed()) { - CHECK(out.getHeight() == a.getHeight() && - out.getWidth() == b.getWidth() && - a.getWidth() == b.getHeight()); - } else if (a.isTransposed() && !b.isTransposed()) { - CHECK(out.getHeight() == a.getWidth() && - out.getWidth() == b.getWidth() && - a.getHeight() == b.getHeight()); - } else if (!a.isTransposed() && b.isTransposed()) { - CHECK(out.getHeight() == a.getHeight() && - out.getWidth() == b.getHeight() && - a.getWidth() == b.getWidth()); - } else { - LOG(FATAL) << "Not support for both a and b are Transposed Matrices"; - } - hl_trans_op_t aTrans = a.isTransposed() ? HPPL_OP_T : HPPL_OP_N; - hl_trans_op_t bTrans = b.isTransposed() ? HPPL_OP_T : HPPL_OP_N; - int dimK = !b.isTransposed() ? b.getHeight() : b.getWidth(); real* aData = const_cast(a.getData()); real* bData = const_cast(b.getData()); hl_sparse_matrix_s outData = out.sMatrix_.get(); - hl_sparse_matrix_mul(aData, aTrans, bData, bTrans, outData, - out.getHeight(), out.getWidth(), dimK, scaleAB, scaleT); + hl_sparse_matrix_mul(aData, + aTrans ? HPPL_OP_T : HPPL_OP_N, + bData, + bTrans ? HPPL_OP_T : HPPL_OP_N, + outData, + out.getHeight(), + out.getWidth(), + !bTrans ? b.getHeight() : b.getWidth(), + scaleAB, + scaleT); } } // namespace paddle diff --git a/paddle/function/MulOpTest.cpp b/paddle/function/MulOpTest.cpp index 05460c80970d93..f67fa41612cf06 100644 --- a/paddle/function/MulOpTest.cpp +++ b/paddle/function/MulOpTest.cpp @@ -39,18 +39,21 @@ void testFuncDDDMatrix( size_t widthC = dimN; // init Test object FunctionCompare test("MulOp", - FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); + FuncConfig() + .set("scaleAB", alpha) + .set("scaleT", beta) + .set("aTrans", transa) + .set("bTrans", transb) + .set("cTrans", false)); // prepare input arguments /// matrix A : HA * WA - test.addInputs(BufferArg( - VALUE_TYPE_FLOAT, TensorShape{heightA, widthA}, UNSPECIFIED, transa)); + test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{heightA, widthA})); /// matrix B: HB * WB - test.addInputs(BufferArg( - VALUE_TYPE_FLOAT, TensorShape{heightB, widthB}, UNSPECIFIED, transb)); + test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{heightB, widthB})); /// output matrix C: HC * WC test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{heightC, widthC}), - ADD_TO); + beta == 1.0 ? ADD_TO : ASSIGN_TO); // run Function test.run(); } @@ -88,21 +91,22 @@ void testFuncDSparseDMatrix( real beta = 1.0; // init Test object FunctionCompare test("MulOp", - FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); + FuncConfig() + .set("scaleAB", alpha) + .set("scaleT", beta) + .set("aTrans", false) + .set("bTrans", false) + .set("cTrans", false)); // prepare input arguments /// sparse matrix A : M * K - test.addInputs(SparseMatrixArg(VALUE_TYPE_FLOAT, - TensorShape{dimM, dimK}, - nnz, - FORMAT, - FLOAT_VALUE, - UNSPECIFIED, - false)); + test.addInputs(SparseMatrixArg( + VALUE_TYPE_FLOAT, TensorShape{dimM, dimK}, nnz, FORMAT, FLOAT_VALUE)); /// matrix B: K * N test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimK, dimN})); /// output matrix C: M * N - test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimM, dimN}), ADD_TO); + test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimM, dimN}), + beta == 1.0 ? ADD_TO : ASSIGN_TO); // run Function test.run(); } @@ -138,22 +142,23 @@ void testFuncDDSparseMatrix( real beta = 1.0; // init Test object FunctionCompare test("MulOp", - FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); + FuncConfig() + .set("scaleAB", alpha) + .set("scaleT", beta) + .set("aTrans", false) + .set("bTrans", false) + .set("cTrans", false)); // prepare input arguments /// matrix A : M * K test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimM, dimK})); /// matrix B: K * N - test.addInputs(SparseMatrixArg(VALUE_TYPE_FLOAT, - TensorShape{dimK, dimN}, - nnz, - FORMAT, - FLOAT_VALUE, - UNSPECIFIED, - false)); + test.addInputs(SparseMatrixArg( + VALUE_TYPE_FLOAT, TensorShape{dimK, dimN}, nnz, FORMAT, FLOAT_VALUE)); /// output matrix C: M * N - test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimM, dimN}), ADD_TO); + test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimM, dimN}), + beta == 1.0 ? ADD_TO : ASSIGN_TO); // run Function test.run(); } @@ -189,7 +194,12 @@ void testFuncSparseDDMatrix( real beta = 1.0; // init Test object FunctionCompare test("MulOp", - FuncConfig().set("scaleAB", alpha).set("scaleT", beta)); + FuncConfig() + .set("scaleAB", alpha) + .set("scaleT", beta) + .set("aTrans", false) + .set("bTrans", false) + .set("cTrans", false)); // prepare input arguments /// matrix A : M * K test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimM, dimK})); @@ -198,14 +208,10 @@ void testFuncSparseDDMatrix( test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimK, dimN})); /// output sparse matrix C: M * N - test.addOutputs(SparseMatrixArg(VALUE_TYPE_FLOAT, - TensorShape{dimM, dimN}, - nnz, - FORMAT, - FLOAT_VALUE, - UNSPECIFIED, - false), - ADD_TO); + test.addOutputs( + SparseMatrixArg( + VALUE_TYPE_FLOAT, TensorShape{dimM, dimN}, nnz, FORMAT, FLOAT_VALUE), + beta == 1.0 ? ADD_TO : ASSIGN_TO); // run Function test.run(); } From 999cd14a6e94f474d646b04ec135d5e6f3f85189 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Mon, 23 Jan 2017 21:21:50 -0800 Subject: [PATCH 106/370] Further address Daoyuan's comments, clean the code. --- paddle/function/BufferArg.cpp | 8 ++-- paddle/function/BufferArg.h | 69 ++++++++++++++++++--------------- paddle/function/FunctionTest.h | 71 +++++++++++++++++----------------- paddle/function/MulOp.cpp | 49 +++++++++++++++++------ paddle/function/MulOp.h | 11 ++++-- paddle/function/MulOpGpu.cu | 62 +++++++++-------------------- paddle/function/MulOpTest.cpp | 2 - paddle/function/TensorType.h | 4 ++ paddle/math/Matrix.h | 2 + 9 files changed, 147 insertions(+), 131 deletions(-) diff --git a/paddle/function/BufferArg.cpp b/paddle/function/BufferArg.cpp index a4f1c2d96417b3..2b70036e3ff7de 100644 --- a/paddle/function/BufferArg.cpp +++ b/paddle/function/BufferArg.cpp @@ -34,8 +34,8 @@ SparseMatrixArg::SparseMatrixArg(const CpuSparseMatrix& sparse, ArgType argType) row_(reinterpret_cast(sparse.getRows()), VALUE_TYPE_INT32), col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32), nnz_(sparse.getElementCnt()), - format_(sparse.getFormat()), - type_(sparse.getValueType()) { + format_(static_cast(sparse.getFormat())), + type_(static_cast(sparse.getValueType())) { bufferType_ = TENSOR_SPARSE; } @@ -44,8 +44,8 @@ SparseMatrixArg::SparseMatrixArg(const GpuSparseMatrix& sparse, ArgType argType) row_(reinterpret_cast(sparse.getRows()), VALUE_TYPE_INT32), col_(reinterpret_cast(sparse.getCols()), VALUE_TYPE_INT32), nnz_(sparse.getElementCnt()), - format_(sparse.getFormat()), - type_(sparse.getValueType()) { + format_(static_cast(sparse.getFormat())), + type_(static_cast(sparse.getValueType())) { bufferType_ = TENSOR_SPARSE; } diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index f3634364ab29f7..177d20005b54b8 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -72,19 +72,21 @@ class BufferArg { BufferArg(ValueType valueType, const TensorShape& shape, ArgType argType = UNSPECIFIED) - : buf_(nullptr), - valueType_(valueType), - shape_(shape), - argType_(argType) {} + : buf_(nullptr), valueType_(valueType), shape_(shape), argType_(argType) { + bufferType_ = TENSOR_NORMAL; + } BufferArg(void* buf, ValueType valueType, const TensorShape& shape, ArgType argType = UNSPECIFIED) - : buf_(buf), valueType_(valueType), shape_(shape), argType_(argType) {} + : buf_(buf), valueType_(valueType), shape_(shape), argType_(argType) { + bufferType_ = TENSOR_NORMAL; + } - BufferArg(void* buf, ValueType valueType) - : buf_(buf), valueType_(valueType) {} + BufferArg(void* buf, ValueType valueType) : buf_(buf), valueType_(valueType) { + bufferType_ = TENSOR_NORMAL; + } BufferArg(const Matrix& matrix, ArgType argType = UNSPECIFIED) : buf_( @@ -173,7 +175,7 @@ class BufferArg { TensorShape shape_; BufferType bufferType_{TENSOR_UNKNOWN}; ArgType argType_{UNSPECIFIED}; - // todo(tianbing), add deviceType_ + // TODO(tianbing), add deviceType_ // leading dimensions. The size is dims_.size() // Dims lds_; }; @@ -186,6 +188,7 @@ class SequenceIdArg : public BufferArg { public: SequenceIdArg(const TensorShape& shape, ArgType argType = UNSPECIFIED) : BufferArg(VALUE_TYPE_INT32, shape, argType) { + bufferType_ = TENSOR_SEQUENCE_ID; CHECK_EQ(shape_.ndims(), (size_t)1); CHECK_GT(shape_[0], 1); numSeqs_ = shape_[0] - 1; @@ -223,7 +226,9 @@ class SequenceArg : public BufferArg { SequenceArg(ValueType valueType, const TensorShape& shape, ArgType argType = UNSPECIFIED) - : BufferArg(valueType, shape, argType), startPositions_(TensorShape()) {} + : BufferArg(valueType, shape, argType), startPositions_(TensorShape()) { + bufferType_ = TENSOR_SEQUENCE_DATA; + } SequenceArg(void* buf, ValueType valueType, @@ -271,16 +276,16 @@ class SparseMatrixArg : public BufferArg { row_(row), col_(col), nnz_(nnz), - format_(format), - type_(type) { + format_(static_cast(format)), + type_(static_cast(type)) { bufferType_ = TENSOR_SPARSE; CHECK((valueType == VALUE_TYPE_FLOAT) || (valueType == VALUE_TYPE_DOUBLE)); CHECK_EQ(shape_.ndims(), (size_t)2); CHECK_EQ(row_.shape().ndims(), (size_t)1); CHECK_EQ(col_.shape().ndims(), (size_t)1); - if (format == SPARSE_CSR) { + if (format_ == T_SPARSE_CSR) { CHECK_EQ(nnz, col.shape()[0]); - } else if (format == SPARSE_CSC) { + } else if (format_ == T_SPARSE_CSC) { CHECK_EQ(nnz, row.shape()[0]); } } @@ -292,23 +297,23 @@ class SparseMatrixArg : public BufferArg { SparseValueType type, ArgType argType = UNSPECIFIED) : BufferArg(valueType, shape, argType), - /// len of row_ : height + 1 (CSR), buf_ == nullptr - row_(format == SPARSE_CSR - ? BufferArg(VALUE_TYPE_INT32, TensorShape{shape[0] + 1}) - : BufferArg(VALUE_TYPE_INT32, TensorShape{nnz})), - /// len of col_ : width + 1 (CSC), buf_ == nullptr - col_(format == SPARSE_CSR - ? BufferArg(VALUE_TYPE_INT32, TensorShape{nnz}) - : BufferArg(VALUE_TYPE_INT32, TensorShape{shape[1] + 1})), + row_(BufferArg(nullptr, VALUE_TYPE_INT32)), + col_(BufferArg(nullptr, VALUE_TYPE_INT32)), nnz_(nnz), - format_(format), - type_(type) { + format_(static_cast(format)), + type_(static_cast(type)) { bufferType_ = TENSOR_SPARSE; - /// todo(tianbing) - /// valueType and shape_.ndims() == 2 need to check before - /// this constructor to make sure row_ and col_ are right CHECK((valueType == VALUE_TYPE_FLOAT) || (valueType == VALUE_TYPE_DOUBLE)); CHECK_EQ(shape_.ndims(), (size_t)2); + + /// len of row_ : height + 1 (CSR) or nnz (CSC), buf_ == nullptr + row_ = (format_ == T_SPARSE_CSR + ? BufferArg(VALUE_TYPE_INT32, TensorShape{shape_[0] + 1}) + : BufferArg(VALUE_TYPE_INT32, TensorShape{nnz})); + /// len of col_ : width + 1 (CSC) or nnz (CSR), buf_ == nullptr + col_ = (format_ == T_SPARSE_CSR + ? BufferArg(VALUE_TYPE_INT32, TensorShape{nnz}) + : BufferArg(VALUE_TYPE_INT32, TensorShape{shape_[1] + 1})); } SparseMatrixArg(const CpuSparseMatrix& sparse, ArgType argType = UNSPECIFIED); @@ -328,8 +333,8 @@ class SparseMatrixArg : public BufferArg { shape_[0], shape_[1], nnz_, - type_, - format_, + static_cast(type_), + static_cast(format_), false); } @@ -343,16 +348,16 @@ class SparseMatrixArg : public BufferArg { size_t numElements() const override { return nnz_; } - SparseFormat dataFormat() const { return format_; } + SparseDataFormat dataFormat() const { return format_; } - SparseValueType dataType() const { return type_; } + SparseDataType dataType() const { return type_; } private: BufferArg row_; BufferArg col_; size_t nnz_; - SparseFormat format_; - SparseValueType type_; + SparseDataFormat format_; + SparseDataType type_; }; } // namespace paddle diff --git a/paddle/function/FunctionTest.h b/paddle/function/FunctionTest.h index baa94abffa09b6..99669a4495578d 100644 --- a/paddle/function/FunctionTest.h +++ b/paddle/function/FunctionTest.h @@ -15,7 +15,6 @@ limitations under the License. */ #include "Function.h" #include "paddle/math/Matrix.h" #include "paddle/math/SparseMatrix.h" -#include "paddle/math/Vector.h" #include "paddle/math/tests/TensorCheck.h" #include "paddle/testing/TestUtil.h" @@ -77,33 +76,33 @@ class FunctionCompare { cpuMemory_.emplace_back(std::make_shared(size)); gpuMemory_.emplace_back(std::make_shared(size)); - cpuOutputs_.emplace_back(std::make_shared( - cpuMemory_.back()->getBuf(), - output.valueType(), - output.shape(), - // todo(tianbing), argType = output.getArgType(), but default ADD_TO - argType)); - gpuOutputs_.emplace_back(std::make_shared( - gpuMemory_.back()->getBuf(), - output.valueType(), - output.shape(), - // todo(tianbing), argType = output.getArgType(), but default ADD_TO - argType)); + cpuOutputs_.emplace_back( + std::make_shared(cpuMemory_.back()->getBuf(), + output.valueType(), + output.shape(), + argType)); + gpuOutputs_.emplace_back( + std::make_shared(gpuMemory_.back()->getBuf(), + output.valueType(), + output.shape(), + argType)); } /// add and init output sparse matrix void addOutputs(const SparseMatrixArg& output, ArgType argType = ASSIGN_TO) { - cpuSparse_ = std::make_shared(output.shape()[0], - output.shape()[1], - output.nnz(), - output.dataType(), - output.dataFormat()); - - gpuSparse_ = std::make_shared(output.shape()[0], - output.shape()[1], - output.nnz(), - output.dataType(), - output.dataFormat()); + cpuSparse_ = std::make_shared( + output.shape()[0], + output.shape()[1], + output.nnz(), + static_cast(output.dataType()), + static_cast(output.dataFormat())); + + gpuSparse_ = std::make_shared( + output.shape()[0], + output.shape()[1], + output.nnz(), + static_cast(output.dataType()), + static_cast(output.dataFormat())); /// init sparse matrix hl_stream_t stream(HPPL_STREAM_1); @@ -138,17 +137,19 @@ class FunctionCompare { } void addInputs(const SparseMatrixArg& input) { - cpuSparse_ = std::make_shared(input.shape()[0], - input.shape()[1], - input.nnz(), - input.dataType(), - input.dataFormat()); - - gpuSparse_ = std::make_shared(input.shape()[0], - input.shape()[1], - input.nnz(), - input.dataType(), - input.dataFormat()); + cpuSparse_ = std::make_shared( + input.shape()[0], + input.shape()[1], + input.nnz(), + static_cast(input.dataType()), + static_cast(input.dataFormat())); + + gpuSparse_ = std::make_shared( + input.shape()[0], + input.shape()[1], + input.nnz(), + static_cast(input.dataType()), + static_cast(input.dataFormat())); /// init sparse matrix hl_stream_t stream(HPPL_STREAM_1); diff --git a/paddle/function/MulOp.cpp b/paddle/function/MulOp.cpp index 965115121eb967..7bbdf7b2e47462 100644 --- a/paddle/function/MulOp.cpp +++ b/paddle/function/MulOp.cpp @@ -41,6 +41,7 @@ inline void colVecAddTo( } // namespace namespace paddle { +/// sparse matrix (+)= dense matrix * dense matrix template <> void MulOp(CpuSparseMatrix& out, const CpuMatrix& a, @@ -105,6 +106,7 @@ void MulOp(CpuSparseMatrix& out, } } +/// dense matrix (+)= dense matrix * dense matrix template <> void MulOp(CpuMatrix& out, const CpuMatrix& a, @@ -129,6 +131,7 @@ void MulOp(CpuMatrix& out, out.getStride()); } +/// dense matrix (+)= sparse matrix * dense matrix template <> void MulOp(CpuMatrix& out, const CpuSparseMatrix& a, @@ -138,8 +141,6 @@ void MulOp(CpuMatrix& out, bool aTrans, bool bTrans, bool cTrans) { - CHECK_EQ(a.getFormat(), SPARSE_CSR) - << "Not supported SPARSE_CSR format for a"; if (scaleT == 0) { out.zeroMem(); } @@ -165,6 +166,7 @@ void MulOp(CpuMatrix& out, } } +/// dense matrix (+)= dense matrix * sparse matrix template <> void MulOp(CpuMatrix& out, const CpuMatrix& a, @@ -183,7 +185,7 @@ void MulOp(CpuMatrix& out, int* rows = b.getRows(); int* cols = b.getCols(); - /// b.getFormat() == SPARSE_CSC + /// SPARSE_CSC format if (b.getFormat() == SPARSE_CSC) { for (size_t j = 0; j < b.getWidth(); ++j) { int start = b.getColStartIdx(j); @@ -200,7 +202,7 @@ void MulOp(CpuMatrix& out, return; } - /// b.getFormat() == SPARSE_CSR + /// SPARSE_CSR format if (b.getFormat() == SPARSE_CSR) { for (size_t j = 0; j < b.getHeight(); ++j) { int start = b.getRowStartIdx(j); @@ -220,11 +222,32 @@ void MulOp(CpuMatrix& out, /** * mul operator - * out = scaleT * out + scaleAB*(in1 * in2) + * out = scaleT * out + scaleAB * (in1 * in2) + * here, scaleT in {0, 1}, scaleAB == 1, + * out = in1 (A) * in2 (B), ASSIGN_TO + * out += in1 (A) * in2 (B), ADD_TO + * + * + * \param outputs[0] output matrix (out), M * N, + * could be either Sparse or Dense Matrix + * M is num of rows, N is num of columns + * \param inputs[0] first input matrix (A), M * K (if non-trans) + * could be either Sparse or Dense Matrix + * M is num of rows, K is num of columns + * \param inputs[1] second input matrix (B), K * N (if non-trans) + * could be either Sparse or Dense Matrix + * K is num of rows, N is num of columns + * + * Support eight Mul operators, with both GPU and CPU devices + * For each device, four Mul operators are supported: + * 1. dense (out) = dense (A) * dense (B) + * 2. dense (out) = sparse (A) * dense (B) + * sparse matrix only support SPARSE_CSR format + * 3. dense (out) = dense (A) * sparse (B) + * sparse matrix support SPARSE_CSC and SPARSE_CSR formats + * 4. sparse (out) = dense (A) * dense (B) + * sparse matrix support SPARSE_CSC and SPARSE_CSR formats * - * \param outputs[0] output matrix, M * N - * \param inputs[0] first input (sparse) matrix, M * K (if non-trans) - * \param inputs[1] second input matrix, K * N (if non-trans) */ template class MulFunc : public FunctionBase { @@ -271,7 +294,7 @@ class MulFunc : public FunctionBase { !inputs[1].isSparseArg())); auto outMat = outputs[0].matrix(); - /// matrix = matrix * matrix + /// dense matrix = dense matrix * dense matrix if (!inputs[0].isSparseArg() && !inputs[1].isSparseArg() && !outputs[0].isSparseArg()) { MulOp(outMat, @@ -285,7 +308,7 @@ class MulFunc : public FunctionBase { return; } - /// matrix = matrix * sparse matrix + /// dense matrix = dense matrix * sparse matrix if (!inputs[0].isSparseArg() && inputs[1].isSparseArg() && !outputs[0].isSparseArg()) { CHECK(!aTrans_) << "Not supported a transpose"; @@ -300,10 +323,12 @@ class MulFunc : public FunctionBase { return; } - /// matrix = sparse matrix * matrix + /// dense matrix = sparse matrix * dense matrix if (inputs[0].isSparseArg() && !inputs[1].isSparseArg() && !outputs[0].isSparseArg()) { CHECK(!bTrans_) << "Not supported b transpose"; + CHECK_EQ(inputs[0].sparse().dataFormat(), T_SPARSE_CSR) + << "Only supported SPARSE_CSR format for sparse matrix a"; MulOp(outMat, inputs[0].sparse().SparseMatrix(), inputs[1].matrix(), @@ -315,7 +340,7 @@ class MulFunc : public FunctionBase { return; } - /// sparse matrix = matrix * matrix + /// sparse matrix = dense matrix * dense matrix auto outSparseMat = outputs[0].sparse().SparseMatrix(); if (!inputs[0].isSparseArg() && !inputs[1].isSparseArg() && outputs[0].isSparseArg()) { diff --git a/paddle/function/MulOp.h b/paddle/function/MulOp.h index a7703482255fec..0991f69e1b286a 100644 --- a/paddle/function/MulOp.h +++ b/paddle/function/MulOp.h @@ -15,12 +15,11 @@ limitations under the License. */ #pragma once #include "Function.h" -/// todo(tianbing), delete it -#include #include "paddle/math/Matrix.h" #include "paddle/math/SparseMatrix.h" namespace paddle { +/// CPU, dense matrix (+)= dense matrix * dense matrix template void MulOp(CpuMatrix& out, const CpuMatrix& a, @@ -31,6 +30,7 @@ void MulOp(CpuMatrix& out, bool bTrans, bool cTrans); +/// CPU, dense matrix (+)= sparse matrix * dense matrix template void MulOp(CpuMatrix& out, const CpuSparseMatrix& a, @@ -41,6 +41,7 @@ void MulOp(CpuMatrix& out, bool bTrans, bool cTrans); +/// CPU, dense matrix (+)= dense matrix * sparse matrix template void MulOp(CpuMatrix& out, const CpuMatrix& a, @@ -51,6 +52,7 @@ void MulOp(CpuMatrix& out, bool bTrans, bool cTrans); +/// CPU, sparse matrix (+)= dense matrix * dense matrix template void MulOp(CpuSparseMatrix& out, const CpuMatrix& a, @@ -61,6 +63,7 @@ void MulOp(CpuSparseMatrix& out, bool bTrans, bool cTrans); +/// GPU, dense matrix (+)= dense matrix * dense matrix template void MulOp(GpuMatrix& out, const GpuMatrix& a, @@ -71,6 +74,7 @@ void MulOp(GpuMatrix& out, bool bTrans, bool cTrans); +/// GPU, dense matrix (+)= sparse matrix * dense matrix template void MulOp(GpuMatrix& out, const GpuSparseMatrix& a, @@ -81,6 +85,7 @@ void MulOp(GpuMatrix& out, bool bTrans, bool cTrans); +/// GPU, dense matrix (+)= dense matrix * sparse matrix template void MulOp(GpuMatrix& out, const GpuMatrix& a, @@ -90,7 +95,7 @@ void MulOp(GpuMatrix& out, bool aTrans, bool bTrans, bool cTrans); - +/// GPU, sparse matrix (+)= dense matrix * dense matrix template void MulOp(GpuSparseMatrix& out, const GpuMatrix& a, diff --git a/paddle/function/MulOpGpu.cu b/paddle/function/MulOpGpu.cu index 94bee72034ff28..e194b702a607a5 100644 --- a/paddle/function/MulOpGpu.cu +++ b/paddle/function/MulOpGpu.cu @@ -18,10 +18,7 @@ limitations under the License. */ #include "paddle/math/SparseMatrix.h" namespace paddle { -/** - * out = scaleT * out + scaleAB * (a * b) - * out : output matrix, M * N - */ +/// dense matrix (+)= dense matrix * dense matrix template <> void MulOp(GpuMatrix& out, const GpuMatrix& a, @@ -32,14 +29,11 @@ void MulOp(GpuMatrix& out, bool bTrans, bool cTrans) { CHECK(a.useGpu_ && b.useGpu_) << "matrix device type not match"; - real* aData = const_cast(a.getData()); - real* bData = const_cast(b.getData()); - real* outData = const_cast(out.getData()); - hl_matrix_mul(aData, + hl_matrix_mul(const_cast(a.getData()), !aTrans ? HPPL_OP_N : HPPL_OP_T, - bData, + const_cast(b.getData()), !bTrans ? HPPL_OP_N : HPPL_OP_T, - outData, + const_cast(out.getData()), out.getHeight(), out.getWidth(), !aTrans ? a.getWidth() : a.getHeight(), @@ -50,10 +44,7 @@ void MulOp(GpuMatrix& out, out.getStride()); } -/** - * out = scaleT * out + scaleAB * (a * b) - * out : M * N - */ +/// dense matrix (+)= sparse matrix * dense matrix template <> void MulOp(GpuMatrix& out, const GpuSparseMatrix& a, @@ -66,15 +57,11 @@ void MulOp(GpuMatrix& out, CHECK(out.isContiguous()); CHECK(b.isContiguous()); CHECK(a.useGpu_ && b.useGpu_) << "matrix device type not match"; - - hl_sparse_matrix_s aData = a.sMatrix_.get(); - real* bData = const_cast(b.getData()); - real* outData = const_cast(out.getData()); - hl_matrix_csr_mul_dense(aData, + hl_matrix_csr_mul_dense(a.sMatrix_.get(), aTrans ? HPPL_OP_T : HPPL_OP_N, - bData, + const_cast(b.getData()), HPPL_OP_N, - outData, + const_cast(out.getData()), out.getHeight(), out.getWidth(), b.getHeight(), @@ -82,10 +69,7 @@ void MulOp(GpuMatrix& out, scaleT); } -/** - * out = scaleT * out + scaleAB * (a * b) - * out : M * N - */ +/// dense matrix (+)= dense matrix * sparse matrix template <> void MulOp(GpuMatrix& out, const GpuMatrix& a, @@ -99,27 +83,23 @@ void MulOp(GpuMatrix& out, CHECK(a.isContiguous()); CHECK(a.useGpu_ && b.useGpu_) << "matrix device type not match"; - hl_sparse_matrix_s bData = b.sMatrix_.get(); - real* aData = const_cast(a.getData()); - real* outData = const_cast(out.getData()); - if (b.format_ == SPARSE_CSC) { - hl_matrix_dense_mul_csc(aData, + hl_matrix_dense_mul_csc(const_cast(a.getData()), HPPL_OP_N, - bData, + b.sMatrix_.get(), bTrans ? HPPL_OP_T : HPPL_OP_N, - outData, + const_cast(out.getData()), out.getHeight(), out.getWidth(), a.getWidth(), scaleAB, scaleT); } else { - hl_matrix_dense_mul_csr(aData, + hl_matrix_dense_mul_csr(const_cast(a.getData()), HPPL_OP_N, - bData, + b.sMatrix_.get(), bTrans ? HPPL_OP_T : HPPL_OP_N, - outData, + const_cast(out.getData()), out.getHeight(), out.getWidth(), a.getWidth(), @@ -128,6 +108,7 @@ void MulOp(GpuMatrix& out, } } +/// sparse matrix (+)= dense matrix * dense matrix template <> void MulOp(GpuSparseMatrix& out, const GpuMatrix& a, @@ -138,16 +119,11 @@ void MulOp(GpuSparseMatrix& out, bool bTrans, bool cTrans) { CHECK(a.useGpu_ && b.useGpu_) << "matrix device type not match"; - - real* aData = const_cast(a.getData()); - real* bData = const_cast(b.getData()); - hl_sparse_matrix_s outData = out.sMatrix_.get(); - - hl_sparse_matrix_mul(aData, + hl_sparse_matrix_mul(const_cast(a.getData()), aTrans ? HPPL_OP_T : HPPL_OP_N, - bData, + const_cast(b.getData()), bTrans ? HPPL_OP_T : HPPL_OP_N, - outData, + out.sMatrix_.get(), out.getHeight(), out.getWidth(), !bTrans ? b.getHeight() : b.getWidth(), diff --git a/paddle/function/MulOpTest.cpp b/paddle/function/MulOpTest.cpp index f67fa41612cf06..0aca3eb40b7c31 100644 --- a/paddle/function/MulOpTest.cpp +++ b/paddle/function/MulOpTest.cpp @@ -13,8 +13,6 @@ See the License for the specific language governing permissions and limitations under the License. */ #include -/// todo(tianbing), delete -#include #include "FunctionTest.h" #include "paddle/math/Matrix.h" #include "paddle/math/SparseMatrix.h" diff --git a/paddle/function/TensorType.h b/paddle/function/TensorType.h index 73ac1cc70d2cd8..8308bbd8ad4fe1 100644 --- a/paddle/function/TensorType.h +++ b/paddle/function/TensorType.h @@ -31,6 +31,10 @@ enum DeviceType { DEVICE_TYPE_GPU = 2 }; +enum SparseDataType { T_NO_VALUE = 0, T_FLOAT_VALUE = 1 }; + +enum SparseDataFormat { T_SPARSE_CSR = 0, T_SPARSE_CSC = 1 }; + inline int sizeOfValuType(ValueType valueType) { if (valueType == VALUE_TYPE_INT32) { return 4; diff --git a/paddle/math/Matrix.h b/paddle/math/Matrix.h index dd24f8821d4976..57c0c2fe40a95d 100644 --- a/paddle/math/Matrix.h +++ b/paddle/math/Matrix.h @@ -31,6 +31,7 @@ limitations under the License. */ namespace paddle { +/// TODO(tianbing), move to paddle/function/TensorType.h enum SparseValueType { NO_VALUE = 0, FLOAT_VALUE = 1 }; /** @@ -56,6 +57,7 @@ enum SparseValueType { NO_VALUE = 0, FLOAT_VALUE = 1 }; * value [1, 1, 2, 2, 5] * @endcode */ +/// TODO(tianbing), move to paddle/function/TensorType.h enum SparseFormat { SPARSE_CSR = 0, SPARSE_CSC = 1 }; class Matrix; From 5b1a5c116a04895d0bedadcfc09ccae2154d7428 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Wed, 25 Jan 2017 11:28:45 -0800 Subject: [PATCH 107/370] Daoyuan's comments. --- paddle/function/FunctionTest.h | 2 +- paddle/function/MulOp.cpp | 59 ++++++++++++---------------------- paddle/function/MulOp.h | 25 ++++++-------- paddle/function/MulOpGpu.cu | 12 +++---- paddle/function/MulOpTest.cpp | 50 ++++++++-------------------- 5 files changed, 48 insertions(+), 100 deletions(-) diff --git a/paddle/function/FunctionTest.h b/paddle/function/FunctionTest.h index 99669a4495578d..00f59f97d4c8c1 100644 --- a/paddle/function/FunctionTest.h +++ b/paddle/function/FunctionTest.h @@ -70,7 +70,7 @@ class FunctionCompare { } // output need only contains shape, do not contains data. - void addOutputs(const BufferArg& output, ArgType argType = ADD_TO) { + void addOutputs(const BufferArg& output, ArgType argType = ASSIGN_TO) { size_t size = output.shape().getElements() * sizeOfValuType(output.valueType()); cpuMemory_.emplace_back(std::make_shared(size)); diff --git a/paddle/function/MulOp.cpp b/paddle/function/MulOp.cpp index 7bbdf7b2e47462..91b4b8ed91b605 100644 --- a/paddle/function/MulOp.cpp +++ b/paddle/function/MulOp.cpp @@ -49,8 +49,7 @@ void MulOp(CpuSparseMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans) { + bool bTrans) { CHECK_EQ(out.getValueType(), FLOAT_VALUE); if (scaleT == 0) { out.zeroMem(); @@ -114,8 +113,7 @@ void MulOp(CpuMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans) { + bool bTrans) { GEMM(aTrans ? CblasTrans : CblasNoTrans, bTrans ? CblasTrans : CblasNoTrans, out.getHeight(), @@ -139,8 +137,7 @@ void MulOp(CpuMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans) { + bool bTrans) { if (scaleT == 0) { out.zeroMem(); } @@ -174,8 +171,7 @@ void MulOp(CpuMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans) { + bool bTrans) { if (scaleT == 0) { out.zeroMem(); } @@ -222,10 +218,10 @@ void MulOp(CpuMatrix& out, /** * mul operator - * out = scaleT * out + scaleAB * (in1 * in2) + * out = scaleT * out + scaleAB * (A * B) * here, scaleT in {0, 1}, scaleAB == 1, - * out = in1 (A) * in2 (B), ASSIGN_TO - * out += in1 (A) * in2 (B), ADD_TO + * out = A * B, ASSIGN_TO + * out += A * B, ADD_TO * * * \param outputs[0] output matrix (out), M * N, @@ -253,15 +249,11 @@ template class MulFunc : public FunctionBase { public: void init(const FuncConfig& config) override { - alpha_ = config.get("scaleAB"); - beta_ = config.get("scaleT"); aTrans_ = config.get("aTrans"); bTrans_ = config.get("bTrans"); - cTrans_ = config.get("cTrans"); } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK(!cTrans_) << "output matrix should not be transposed"; CHECK(!aTrans_ || !bTrans_) << "Not support both a and b are transpose matrices"; @@ -281,10 +273,8 @@ class MulFunc : public FunctionBase { CHECK_EQ(aRow, outputs[0].shape()[0]); CHECK_EQ(bCol, outputs[0].shape()[1]); - /// only support C = A * B or C += A * B - CHECK_EQ(alpha_, static_cast(1.0)); - CHECK((beta_ == 0 && outputs[0].getArgType() == ASSIGN_TO) || - (beta_ == 1 && outputs[0].getArgType() == ADD_TO)); + /// only support C = A * B (ASSIGN_TO) or C += A * B (ADD_TO) + real scaleT = (outputs[0].getArgType() == ADD_TO) ? 1.0 : 0.0; /// support dense = not both sparse * sparse /// or sparse = dense * dense @@ -300,11 +290,10 @@ class MulFunc : public FunctionBase { MulOp(outMat, inputs[0].matrix(), inputs[1].matrix(), - alpha_, - beta_, + 1.0, // scaleAB + scaleT, aTrans_, - bTrans_, - cTrans_); + bTrans_); return; } @@ -315,11 +304,10 @@ class MulFunc : public FunctionBase { MulOp(outMat, inputs[0].matrix(), inputs[1].sparse().SparseMatrix(), - alpha_, - beta_, + 1.0, // scaleAB + scaleT, aTrans_, - bTrans_, - cTrans_); + bTrans_); return; } @@ -332,11 +320,10 @@ class MulFunc : public FunctionBase { MulOp(outMat, inputs[0].sparse().SparseMatrix(), inputs[1].matrix(), - alpha_, - beta_, + 1.0, // scaleAB + scaleT, aTrans_, - bTrans_, - cTrans_); + bTrans_); return; } @@ -347,21 +334,17 @@ class MulFunc : public FunctionBase { MulOp(outSparseMat, inputs[0].matrix(), inputs[1].matrix(), - alpha_, - beta_, + 1.0, // scaleAB + scaleT, aTrans_, - bTrans_, - cTrans_); + bTrans_); return; } } private: - real alpha_; - real beta_; bool aTrans_; bool bTrans_; - bool cTrans_; }; REGISTER_TYPED_FUNC(MulOp, CPU, MulFunc); diff --git a/paddle/function/MulOp.h b/paddle/function/MulOp.h index 0991f69e1b286a..b6016a6ab6e9d6 100644 --- a/paddle/function/MulOp.h +++ b/paddle/function/MulOp.h @@ -27,8 +27,7 @@ void MulOp(CpuMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans); + bool bTrans); /// CPU, dense matrix (+)= sparse matrix * dense matrix template @@ -38,8 +37,7 @@ void MulOp(CpuMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans); + bool bTrans); /// CPU, dense matrix (+)= dense matrix * sparse matrix template @@ -49,8 +47,7 @@ void MulOp(CpuMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans); + bool bTrans); /// CPU, sparse matrix (+)= dense matrix * dense matrix template @@ -60,8 +57,7 @@ void MulOp(CpuSparseMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans); + bool bTrans); /// GPU, dense matrix (+)= dense matrix * dense matrix template @@ -71,8 +67,7 @@ void MulOp(GpuMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans); + bool bTrans); /// GPU, dense matrix (+)= sparse matrix * dense matrix template @@ -82,8 +77,7 @@ void MulOp(GpuMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans); + bool bTrans); /// GPU, dense matrix (+)= dense matrix * sparse matrix template @@ -93,8 +87,8 @@ void MulOp(GpuMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans); + bool bTrans); + /// GPU, sparse matrix (+)= dense matrix * dense matrix template void MulOp(GpuSparseMatrix& out, @@ -103,7 +97,6 @@ void MulOp(GpuSparseMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans); + bool bTrans); } // namespace paddle diff --git a/paddle/function/MulOpGpu.cu b/paddle/function/MulOpGpu.cu index e194b702a607a5..dcfcb2325d7dae 100644 --- a/paddle/function/MulOpGpu.cu +++ b/paddle/function/MulOpGpu.cu @@ -26,8 +26,7 @@ void MulOp(GpuMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans) { + bool bTrans) { CHECK(a.useGpu_ && b.useGpu_) << "matrix device type not match"; hl_matrix_mul(const_cast(a.getData()), !aTrans ? HPPL_OP_N : HPPL_OP_T, @@ -52,8 +51,7 @@ void MulOp(GpuMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans) { + bool bTrans) { CHECK(out.isContiguous()); CHECK(b.isContiguous()); CHECK(a.useGpu_ && b.useGpu_) << "matrix device type not match"; @@ -77,8 +75,7 @@ void MulOp(GpuMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans) { + bool bTrans) { CHECK(out.isContiguous()); CHECK(a.isContiguous()); CHECK(a.useGpu_ && b.useGpu_) << "matrix device type not match"; @@ -116,8 +113,7 @@ void MulOp(GpuSparseMatrix& out, real scaleAB, real scaleT, bool aTrans, - bool bTrans, - bool cTrans) { + bool bTrans) { CHECK(a.useGpu_ && b.useGpu_) << "matrix device type not match"; hl_sparse_matrix_mul(const_cast(a.getData()), aTrans ? HPPL_OP_T : HPPL_OP_N, diff --git a/paddle/function/MulOpTest.cpp b/paddle/function/MulOpTest.cpp index 0aca3eb40b7c31..158c3c90983b12 100644 --- a/paddle/function/MulOpTest.cpp +++ b/paddle/function/MulOpTest.cpp @@ -27,8 +27,7 @@ using namespace paddle; // NOLINT */ void testFuncDDDMatrix( bool transa, bool transb, size_t dimM, size_t dimN, size_t dimK) { - real alpha = 1.0; - real beta = 1.0; + real scaleT = 1.0; size_t heightA = (transa == false) ? dimM : dimK; size_t widthA = (transa == false) ? dimK : dimM; size_t heightB = (transb == false) ? dimK : dimN; @@ -36,13 +35,8 @@ void testFuncDDDMatrix( size_t heightC = dimM; size_t widthC = dimN; // init Test object - FunctionCompare test("MulOp", - FuncConfig() - .set("scaleAB", alpha) - .set("scaleT", beta) - .set("aTrans", transa) - .set("bTrans", transb) - .set("cTrans", false)); + FunctionCompare test( + "MulOp", FuncConfig().set("aTrans", transa).set("bTrans", transb)); // prepare input arguments /// matrix A : HA * WA test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{heightA, widthA})); @@ -51,7 +45,7 @@ void testFuncDDDMatrix( /// output matrix C: HC * WC test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{heightC, widthC}), - beta == 1.0 ? ADD_TO : ASSIGN_TO); + scaleT == 1.0 ? ADD_TO : ASSIGN_TO); // run Function test.run(); } @@ -85,16 +79,10 @@ TEST(MulOp, DDDMatrixMul) { */ void testFuncDSparseDMatrix( size_t dimM, size_t dimN, size_t dimK, size_t nnz, SparseFormat FORMAT) { - real alpha = 1.0; - real beta = 1.0; + real scaleT = 1.0; // init Test object FunctionCompare test("MulOp", - FuncConfig() - .set("scaleAB", alpha) - .set("scaleT", beta) - .set("aTrans", false) - .set("bTrans", false) - .set("cTrans", false)); + FuncConfig().set("aTrans", false).set("bTrans", false)); // prepare input arguments /// sparse matrix A : M * K test.addInputs(SparseMatrixArg( @@ -104,7 +92,7 @@ void testFuncDSparseDMatrix( /// output matrix C: M * N test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimM, dimN}), - beta == 1.0 ? ADD_TO : ASSIGN_TO); + scaleT == 1.0 ? ADD_TO : ASSIGN_TO); // run Function test.run(); } @@ -136,16 +124,10 @@ TEST(MuLOp, DSparseDMul) { */ void testFuncDDSparseMatrix( size_t dimM, size_t dimN, size_t dimK, size_t nnz, SparseFormat FORMAT) { - real alpha = 1.0; - real beta = 1.0; + real scaleT = 1.0; // init Test object FunctionCompare test("MulOp", - FuncConfig() - .set("scaleAB", alpha) - .set("scaleT", beta) - .set("aTrans", false) - .set("bTrans", false) - .set("cTrans", false)); + FuncConfig().set("aTrans", false).set("bTrans", false)); // prepare input arguments /// matrix A : M * K test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimM, dimK})); @@ -156,7 +138,7 @@ void testFuncDDSparseMatrix( /// output matrix C: M * N test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimM, dimN}), - beta == 1.0 ? ADD_TO : ASSIGN_TO); + scaleT == 1.0 ? ADD_TO : ASSIGN_TO); // run Function test.run(); } @@ -188,16 +170,10 @@ TEST(MulOp, DDSparseMul) { */ void testFuncSparseDDMatrix( size_t dimM, size_t dimN, size_t dimK, size_t nnz, SparseFormat FORMAT) { - real alpha = 1.0; - real beta = 1.0; + real scaleT = 1.0; // init Test object FunctionCompare test("MulOp", - FuncConfig() - .set("scaleAB", alpha) - .set("scaleT", beta) - .set("aTrans", false) - .set("bTrans", false) - .set("cTrans", false)); + FuncConfig().set("aTrans", false).set("bTrans", false)); // prepare input arguments /// matrix A : M * K test.addInputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{dimM, dimK})); @@ -209,7 +185,7 @@ void testFuncSparseDDMatrix( test.addOutputs( SparseMatrixArg( VALUE_TYPE_FLOAT, TensorShape{dimM, dimN}, nnz, FORMAT, FLOAT_VALUE), - beta == 1.0 ? ADD_TO : ASSIGN_TO); + scaleT == 1.0 ? ADD_TO : ASSIGN_TO); // run Function test.run(); } From 67bf06ce7301ee0abdaeaf65a3f7ec885469dd74 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Thu, 26 Jan 2017 11:15:51 -0800 Subject: [PATCH 108/370] paddle on aws with kubernetes tutorial now works --- doc/howto/usage/k8s/k8s_aws_en.md | 559 ++++++++---------- .../usage/k8s/src/add_security_group.png | Bin 237481 -> 118948 bytes doc/howto/usage/k8s/src/create_efs.png | Bin 250321 -> 241814 bytes doc/howto/usage/k8s/src/job.yaml | 43 -- doc/howto/usage/k8s/src/k8s_data/Dockerfile | 7 + doc/howto/usage/k8s/src/k8s_data/README.md | 6 + doc/howto/usage/k8s/src/k8s_data/get_data.sh | 26 + doc/howto/usage/k8s/src/k8s_train/Dockerfile | 6 + doc/howto/usage/k8s/src/k8s_train/README.md | 5 + .../usage/k8s/src/{ => k8s_train}/start.sh | 12 +- .../k8s/src/{ => k8s_train}/start_paddle.py | 29 +- .../usage/k8s/src/worker_security_group.png | Bin 0 -> 89208 bytes 12 files changed, 331 insertions(+), 362 deletions(-) delete mode 100644 doc/howto/usage/k8s/src/job.yaml create mode 100644 doc/howto/usage/k8s/src/k8s_data/Dockerfile create mode 100644 doc/howto/usage/k8s/src/k8s_data/README.md create mode 100755 doc/howto/usage/k8s/src/k8s_data/get_data.sh create mode 100644 doc/howto/usage/k8s/src/k8s_train/Dockerfile create mode 100644 doc/howto/usage/k8s/src/k8s_train/README.md rename doc/howto/usage/k8s/src/{ => k8s_train}/start.sh (55%) rename doc/howto/usage/k8s/src/{ => k8s_train}/start_paddle.py (84%) create mode 100644 doc/howto/usage/k8s/src/worker_security_group.png diff --git a/doc/howto/usage/k8s/k8s_aws_en.md b/doc/howto/usage/k8s/k8s_aws_en.md index a6422b9be00e21..7930807969c0e9 100644 --- a/doc/howto/usage/k8s/k8s_aws_en.md +++ b/doc/howto/usage/k8s/k8s_aws_en.md @@ -1,6 +1,49 @@ -# Kubernetes on AWS +# Distributed PaddlePaddle Training on AWS with Kubernetes -## Create AWS Account and IAM Account +We will show you step by step on how to run distributed PaddlePaddle training on AWS cluster with Kubernetes. Let's start from core concepts. + +## Distributed PaddlePaddle Training Core Concepts + +### Distributed Training Job + +A distributed training job is represented by a [Kubernetes job](https://kubernetes.io/docs/user-guide/jobs/#what-is-a-job). + +Each Kuberentes job is described by a job config file, which specifies the information like the number of [pods](https://kubernetes.io/docs/user-guide/pods/#what-is-a-pod) in the job and environment variables. + +In a distributed training job, we would: + +1. prepare partitioned training data and configuration file on a distributed file system (in this tutorial we use Amazon Elastic File System), and +1. create and submit the Kubernetes job config to the Kubernetes cluster to start the training job. + +### Parameter Servers and Trainers + +There are two roles in a PaddlePaddle cluster: *parameter server (pserver)* and *trainer*. Each parameter server process maintains a shard of the global model. Each trainer has its local copy of the model, and uses its local data to update the model. During the training process, trainers send model updates to parameter servers, parameter servers are responsible for aggregating these updates, so that trainers can synchronize their local copy with the global model. + +

![Model is partitioned into two shards. Managed by two parameter servers respectively.](src/pserver_and_trainer.png)
+ +In order to communicate with pserver, trainer needs to know the ip address of each pserver. In kubernetes it's better to use a service discovery mechanism (e.g., DNS hostname) rather than static ip address, since any pserver's pod may be killed and a new pod could be schduled onto another node of different ip address. However, now we are using static ip. This will be improved. + +Parameter server and trainer are packaged into a same docker image. They will run once pod is scheduled by kubernetes job. + +### Trainer ID + +Each trainer process requires a trainer ID, a zero-based index value, passed in as a command-line parameter. The trainer process thus reads the data partition indexed by this ID. + +### Training + +The entry-point of a container is a shell script. It can see some environment variables pre-defined by Kubernetes. This includes one that gives the job's identity, which can be used in a remote call to the Kubernetes apiserver that lists all pods in the job. + +We rank each pod by sorting them by their ips. The rank of each pod could be the "pod ID". Because we run one trainer and one parameter server in each pod, we can use this "pod ID" as the trainer ID. A detailed workflow of the entry-point script is as follows: + +1. Query the api server to get pod information, and assign the `trainer_id` by sorting the ip. +1. Copy the training data from EFS persistent volume into container. +1. Parse the `paddle pserver` and `paddle trainer` startup parameters from environment variables, and then start up the processes. +1. Trainer with `train_id` 0 will automatically write results onto EFS volume. + + +## PaddlePaddle on AWS with Kubernetes + +### Create AWS Account and IAM Account Under each AWS account, we can create multiple [IAM](http://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html) users. This allows us to grant some privileges to each IAM user and to create/operate AWS clusters as an IAM user. @@ -25,11 +68,6 @@ Please be aware that this tutorial needs the following privileges for the user i - AWSKeyManagementServicePowerUser -## PaddlePaddle on AWS - -Here we will show you step by step on how to run PaddlePaddle training on AWS cluster. - - ### Download kube-aws and kubectl #### kube-aws @@ -103,7 +141,6 @@ And then configure your AWS account information: ``` aws configure - ``` @@ -113,7 +150,7 @@ Fill in the required fields: ``` AWS Access Key ID: YOUR_ACCESS_KEY_ID AWS Secrete Access Key: YOUR_SECRETE_ACCESS_KEY -Default region name: us-west-1 +Default region name: us-west-2 Default output format: json ``` @@ -131,25 +168,28 @@ aws ec2 describe-instances The keypair that will authenticate SSH access to your EC2 instances. The public half of this key pair will be configured on each CoreOS node. -Follow [EC2 Keypair docs](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) to create a EC2 key pair +Follow [EC2 Keypair User Guide](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) to create a EC2 key pair After creating a key pair, you will use the key pair name to configure the cluster. -Key pairs are only available to EC2 instances in the same region. We are using us-west-1 in our tutorial, so make sure to creat key pairs in that region (N. California). +Key pairs are only available to EC2 instances in the same region. We are using us-west-2 in our tutorial, so make sure to creat key pairs in that region (Oregon). + +Your browser will download a `key-name.pem` file which is the key to access the EC2 instances. We will use it later. + #### KMS key Amazon KMS keys are used to encrypt and decrypt cluster TLS assets. If you already have a KMS Key that you would like to use, you can skip creating a new key and provide the Arn string for your existing key. -You can create a KMS key in the AWS console, or with the aws command line tool: +You can create a KMS key with the aws command line tool: ``` -aws kms --region=us-west-1 create-key --description="kube-aws assets" +aws kms --region=us-west-2 create-key --description="kube-aws assets" { "KeyMetadata": { "CreationDate": 1458235139.724, "KeyState": "Enabled", - "Arn": "arn:aws:kms:us-west-1:aaaaaaaaaaaaa:key/xxxxxxxxxxxxxxxxxxx", + "Arn": "arn:aws:kms:us-west-2:aaaaaaaaaaaaa:key/xxxxxxxxxxxxxxxxxxx", "AWSAccountId": "xxxxxxxxxxxxx", "Enabled": true, "KeyUsage": "ENCRYPT_DECRYPT", @@ -161,14 +201,14 @@ aws kms --region=us-west-1 create-key --description="kube-aws assets" We will need to use the value of `Arn` later. -And then you need to add several inline policies in your user permission. +And then let's add several inline policies in your IAM user permission. -Go to IAM user page, click on `Add inline policy` button, and then select `Custom Policy` +Go to [IAM Console](https://console.aws.amazon.com/iam/home?region=us-west-2#/home). Click on button `Users`, click user that we just created, and then click on `Add inline policy` button, and select `Custom Policy`. -paste into following inline policies: +Paste into following inline policies: ``` -{ + (Caution: node_0, node_1, node_2 directories represents PaddlePaddle node and train_id, not the Kubernetes node){ "Version": "2012-10-17", "Statement": [ { @@ -195,7 +235,7 @@ paste into following inline policies: "cloudformation:DescribeStackEvents" ], "Resource": [ - "arn:aws:cloudformation:us-west-1:AWS_ACCOUNT_ID:stack/MY_CLUSTER_NAME/*" + "arn:aws:cloudformation:us-west-2:AWS_ACCOUNT_ID:stack/MY_CLUSTER_NAME/*" ] } ] @@ -214,20 +254,20 @@ aws sts get-caller-identity --output text --query Account When the cluster is created, the controller will expose the TLS-secured API on a DNS name. -The A record of that DNS name needs to be point to the cluster ip address. +DNS name should have a CNAME points to cluster DNS name or an A record points to the cluster IP address. -We will need to use DNS name later in tutorial. If you don't already own one, you can choose any DNS name (e.g., `paddle`) and modify `/etc/hosts` to associate cluster ip with that DNS name. +We will need to use DNS name later in tutorial. #### S3 bucket You need to create an S3 bucket before startup the Kubernetes cluster. -There are some bugs in aws cli in creating S3 bucket, so let's use the [Web console](https://console.aws.amazon.com/s3/home?region=us-west-1). +There are some bugs in aws cli in creating S3 bucket, so let's use the [S3 Console](https://console.aws.amazon.com/s3/home?region=us-west-2). -Click on `Create Bucket`, fill in a unique BUCKET_NAME, and make sure region is us-west-1 (Northern California). +Click on `Create Bucket`, fill in a unique BUCKET_NAME, and make sure region is us-west-2 (Oregon). -#### Initialize an asset directory +#### Initialize Assets Create a directory on your local machine to hold the generated assets: @@ -242,10 +282,10 @@ Initialize the cluster CloudFormation stack with the KMS Arn, key pair name, and kube-aws init \ --cluster-name=MY_CLUSTER_NAME \ --external-dns-name=MY_EXTERNAL_DNS_NAME \ ---region=us-west-1 \ ---availability-zone=us-west-1a \ +--region=us-west-2 \ +--availability-zone=us-west-2a \ --key-name=KEY_PAIR_NAME \ ---kms-key-arn="arn:aws:kms:us-west-1:xxxxxxxxxx:key/xxxxxxxxxxxxxxxxxxx" +--kms-key-arn="arn:aws:kms:us-west-2:xxxxxxxxxx:key/xxxxxxxxxxxxxxxxxxx" ``` `MY_CLUSTER_NAME`: the one you picked in [KMS key](#kms-key) @@ -256,14 +296,15 @@ kube-aws init \ `--kms-key-arn`: the "Arn" in [KMS key](#kms-key) -Here `us-west-1a` is used for parameter `--availability-zone`, but supported availability zone varies among AWS accounts. +Here `us-west-2a` is used for parameter `--availability-zone`, but supported availability zone varies among AWS accounts. -Please check if `us-west-1a` is supported by `aws ec2 --region us-west-1 describe-availability-zones`, if not switch to other supported availability zone. (e.g., `us-west-1a`, or `us-west-1b`) +Please check if `us-west-2a` is supported by `aws ec2 --region us-west-2 describe-availability-zones`, if not switch to other supported availability zone. (e.g., `us-west-2a`, or `us-west-2b`) -Note: please don't use `us-west-1c`. Subnets can currently only be created in the following availability zones: us-west-1b, us-west-1a. There will now be a cluster.yaml file in the asset directory. This is the main configuration file for your cluster. +By default `kube-aws` will only create one worker node. Let's edit `cluster.yaml` and change `workerCount` from 1 to 3. + #### Render contents of the asset directory @@ -278,41 +319,14 @@ The next command generates the default set of cluster assets in your asset direc ``` kube-aws render stack ``` - -Here's what the directory structure looks like: - -``` -$ tree -. -├── cluster.yaml -├── credentials -│ ├── admin-key.pem -│ ├── admin.pem -│ ├── apiserver-key.pem -│ ├── apiserver.pem -│ ├── ca-key.pem -│ ├── ca.pem -│ ├── worker-key.pem -│ └── worker.pem -│ ├── etcd-key.pem -│ └── etcd.pem -│ ├── etcd-client-key.pem -│ └── etcd-client.pem -├── kubeconfig -├── stack-template.json -└── userdata - ├── cloud-config-controller - └── cloud-config-worker -``` - -These assets (templates and credentials) are used to create, update and interact with your Kubernetes cluster. +Assets (templates and credentials) that are used to create, update and interact with your Kubernetes cluster will be created under your current folder. ### Kubernetes Cluster Start Up #### Create the instances defined in the CloudFormation template -Now let's create your cluster (choose any PREFIX for the command below): +Now let's create your cluster (choose any `PREFIX` for the command below): ``` kube-aws up --s3-uri s3://BUCKET_NAME/PREFIX @@ -328,239 +342,158 @@ You can invoke `kube-aws status` to get the cluster API endpoint after cluster c ``` $ kube-aws status Cluster Name: paddle-cluster -Controller DNS Name: paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-1.elb.amazonaws.com +Controller DNS Name: paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-2.elb.amazonaws.com ``` +If you own a DNS name, set the A record to any of the above ip. __Or__ you can set up CNAME point to `Controller DNS Name` (`paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-2.elb.amazonaws.com`) + +##### Find IP address + Use command `dig` to check the load balancer hostname to get the ip address. ``` -$ dig paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-1.elb.amazonaws.com +$ dig paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-2.elb.amazonaws.com ;; QUESTION SECTION: -;paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-1.elb.amazonaws.com. IN A +;paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-2.elb.amazonaws.com. IN A ;; ANSWER SECTION: -paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-1.elb.amazonaws.com. 59 IN A 54.241.164.52 -paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-1.elb.amazonaws.com. 59 IN A 54.67.102.112 +paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-2.elb.amazonaws.com. 59 IN A 54.241.164.52 +paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-2.elb.amazonaws.com. 59 IN A 54.67.102.112 ``` In the above output, both ip `54.241.164.52`, `54.67.102.112` will work. -If you own a DNS name, set the A record to any of the above ip. Otherwise you can edit `/etc/hosts` to associate ip with the DNS name. #### Access the cluster Once the API server is running, you should see: ``` -$ kubectl --kubeconfig=kubeconfig get nodes -NAME STATUS AGE -ip-10-0-0-xxx.us-west-1.compute.internal Ready 5m -ip-10-0-0-xxx.us-west-1.compute.internal Ready 5m -ip-10-0-0-xx.us-west-1.compute.internal Ready,SchedulingDisabled 5m +$ kubectl --kubeconfig=kubeconfig get nodes +NAME STATUS AGE +ip-10-0-0-134.us-west-2.compute.internal Ready 6m +ip-10-0-0-238.us-west-2.compute.internal Ready 6m +ip-10-0-0-50.us-west-2.compute.internal Ready 6m +ip-10-0-0-55.us-west-2.compute.internal Ready 6m ``` ### Setup Elastic File System for Cluster -Training data is usually served on a distributed filesystem, we use Elastic File System (EFS) on AWS. Ceph might be a better solution, but it requires high version of Linux kernel that might not be stable enough at this moment. We haven't automated the EFS setup at this moment, so please do the following steps: - +Training data is usually served on a distributed filesystem, we use Elastic File System (EFS) on AWS. -1. Make sure you added AmazonElasticFileSystemFullAccess policy in your group. +1. Create security group for EFS in [security group console](https://us-west-2.console.aws.amazon.com/ec2/v2/home?region=us-west-2#SecurityGroups:sort=groupId) + 1. Look up security group id for `paddle-cluster-sg-worker` (`sg-055ee37d` in the image below) +
![](src/worker_security_group.png)
+ 2. Add security group `paddle-efs` with `ALL TCP` inbound rule and custom source as group id of `paddle-cluster-sg-worker`. And VPC of `paddle-cluster-vpc`. Make sure availability zone is same as the one you used in [Initialize Assets](#initialize-assets). +
![](src/add_security_group.png)
-1. Create the Elastic File System in AWS console, and attach the new VPC with it. +2. Create the Elastic File System in [EFS console](https://us-west-2.console.aws.amazon.com/efs/home?region=us-west-2#/wizard/1) with `paddle-cluster-vpc` VPC. Make sure subnet is `paddle-cluster-Subnet0` andd security group is `paddle-efs`.
![](src/create_efs.png)
-1. Modify the Kubernetes security group under ec2/Security Groups, add additional inbound policy "All TCP TCP 0 - 65535 0.0.0.0/0" for Kubernetes default VPC security group. -
![](src/add_security_group.png)
- - -1. Follow the EC2 mount instruction to mount the disk onto all the Kubernetes nodes, we recommend to mount EFS disk onto ~/efs. -
![](src/efs_mount.png)
- - -We will place user config and divided training data onto EFS. Training task will cache related files by copying them from EFS into container. It will also write the training results back onto EFS. We will show you how to place the data later in this article. - - - -### Core Concepts of PaddlePaddle Training on AWS - -Now we've already setup a 3 nodes distributed Kubernetes cluster, and on each node we've attached the EFS volume. In this training demo, we will create three Kubernetes pods and schedule them on three nodes. Each pod contains a PaddlePaddle container. When container gets created, it will start parameter server (pserver) and trainer process, load the training data from EFS volume and start the distributed training task. - -#### Distributed Training Job - -A distributed training job is represented by a [kubernetes job](https://kubernetes.io/docs/user-guide/jobs/#what-is-a-job). - -Each Kuberentes job is described by a job config file, which specifies the information like the number of pods in the job and environment variables. - -In a distributed training job, we would: - -1. upload the partitioned training data and configuration file onto EFS volume, and -1. create and submit the Kubernetes job config to the Kubernetes cluster to start the training job. - -#### Parameter Servers and Trainers - -There are two roles in a PaddlePaddle cluster: `parameter server` and `trainer`. Each parameter server process maintains a shard of the global model. Each trainer has its local copy of the model, and uses its local data to update the model. During the training process, trainers send model updates to parameter servers, parameter servers are responsible for aggregating these updates, so that trainers can synchronize their local copy with the global model. - -
![Model is partitioned into two shards. Managed by two parameter servers respectively.](src/pserver_and_trainer.png)
- -In order to communicate with pserver, trainer needs to know the ip address of each pserver. In kubernetes it's better to use a service discovery mechanism (e.g., DNS hostname) rather than static ip address, since any pserver's pod may be killed and a new pod could be schduled onto another node of different ip address. We will improve paddlepaddle's service discovery ability. For now we will use static ip. - -Parameter server and trainer are packaged into a same docker image. They will run once pod is scheduled by kubernetes job. - -#### Trainer ID - -Each trainer process requires a trainer ID, a zero-based index value, passed in as a command-line parameter. The trainer process thus reads the data partition indexed by this ID. - -#### Training - -The entry-point of a container is a Python script. As it runs in a pod, it can see some environment variables pre-defined by Kubernetes. This includes one that gives the job's identity, which can be used in a remote call to the Kubernetes apiserver that lists all pods in the job. - -We rank each pod by sorting them by their ips. The rank of each pod could be the "pod ID". Because we run one trainer and one parameter server in each pod, we can use this "pod ID" as the trainer ID. A detailed workflow of the entry-point script is as follows: - -1. Query the api server to get pod information, and assign the `trainer_id` by sorting the ip. -1. Copy the training data from EFS sharing volume into container. -1. Parse the `paddle pserver` and `paddle trainer` startup parameters from environment variables, and then start up the processes. -1. Trainer with `train_id` 0 will automatically write results onto EFS volume. - - ### Start PaddlePaddle Training Demo on AWS -Now we'll start a PaddlePaddle training demo on AWS, steps are as follows: - -1. Build PaddlePaddle Docker image. -1. Divide the training data file and upload it onto the EFS sharing volume. -1. Create the training job config file, and start up the job. -1. Check the result after training. - -#### Build PaddlePaddle Docker Image - -PaddlePaddle docker image need to provide the runtime environment for `pserver` and `trainer`, so the container use this image should have two main function: - -1. Copy the training data into container. -1. Generate the startup parameter for `pserver` and `trainer` process, and startup the training. - +#### Configure Kubernetes Volume that Points to EFS -We need to create a new image since official `paddledev/paddle:cpu-latest` only have PaddlePaddle binary, but lack of the above functionalities. - -Dockerfile for creating the new image is as follows: +First we need to create a [PersistentVolume](https://kubernetes.io/docs/user-guide/persistent-volumes/) to provision EFS volumn. +Save following snippet as `pv.yaml` ``` -FROM paddledev/paddle:cpu-latest - -MAINTAINER zjsxzong89@gmail.com - -COPY start.sh /root/ -COPY start_paddle.py /root/ -CMD ["bash"," -c","/root/start.sh"] +apiVersion: v1 +kind: PersistentVolume +metadata: + name: efsvol +spec: + capacity: + storage: 100Gi + accessModes: + - ReadWriteMany + nfs: + server: EFS_DNS_NAME + path: "/" ``` -At this point, we will copy our `start.sh` and `start_paddle.py` file into container, and then exec `start_paddle.py` script to start up the training, all the steps like assigning trainer_id, getting other nodes' ip are implemented in `start_paddle.py`. - -`start_paddle.py` will start parsing the parameters. +`EFS_DNS_NAME`: DNS name as shown in description of `paddle-efs` that we created. Looks similar to `fs-2cbf7385.efs.us-west-2.amazonaws.com` +Run following command to create a persistent volumn: ``` -parser = argparse.ArgumentParser(prog="start_paddle.py", - description='simple tool for k8s') - args, train_args_list = parser.parse_known_args() - train_args = refine_unknown_args(train_args_list) - train_args_dict = dict(zip(train_args[:-1:2], train_args[1::2])) - podlist = getPodList() +kubectl --kubeconfig=kubeconfig create -f pv.yaml ``` -And then using function `getPodList()` to query all the pod information from the job name through Kubernetes api server. When all the pods are in the running status, using `getIdMap(podlist)` to get the trainer_id. +Next let's create a [PersistentVolumeClaim](https://kubernetes.io/docs/user-guide/persistent-volumes/) to claim the persistent volume. +Save following snippet as `pvc.yaml`. ``` - podlist = getPodList() - # need to wait until all pods are running - while not isPodAllRunning(podlist): - time.sleep(10) - podlist = getPodList() - idMap = getIdMap(podlist) +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: efsvol +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 50Gi ``` -In function `getIdMap(podlist)`, we use podlist to get the ip address for each pod and sort them, use the index as the trainer_id. - +Run following command to create a persistent volumn claim: ``` -def getIdMap(podlist): - ''' - generate tainer_id by ip - ''' - ips = [] - for pod in podlist["items"]: - ips.append(pod["status"]["podIP"]) - ips.sort() - idMap = {} - for i in range(len(ips)): - idMap[ips[i]] = i - return idMap +kubectl --kubeconfig=kubeconfig create -f pvc.yaml ``` -After getting `idMap`, we use function `startPaddle(idMap, train_args_dict)` to generate `paddle pserver` and `paddle train` start up parameters and then start up the processes. +#### Prepare Training Data -In function `startPaddle`, the most important work is to generate `paddle pserver` and `paddle train` start up parameters. For example, `paddle train` parameter parsing, we will get parameters like `PADDLE_NIC`, `PADDLE_PORT`, `PADDLE_PORTS_NUM`, and get the `trainer_id` from `idMap`. +We will now launch a kubernetes job that downloads, saves and evenly splits training data into 3 shards on the persistent volumn that we just created. +save following snippet as `paddle-data-job.yaml` ``` - program = 'paddle train' - args = " --nics=" + PADDLE_NIC - args += " --port=" + str(PADDLE_PORT) - args += " --ports_num=" + str(PADDLE_PORTS_NUM) - args += " --comment=" + "paddle_process_by_paddle" - ip_string = "" - for ip in idMap.keys(): - ip_string += (ip + ",") - ip_string = ip_string.rstrip(",") - args += " --pservers=" + ip_string - args_ext = "" - for key, value in train_args_dict.items(): - args_ext += (' --' + key + '=' + value) - localIP = socket.gethostbyname(socket.gethostname()) - trainerId = idMap[localIP] - args += " " + args_ext + " --trainer_id=" + \ - str(trainerId) + " --save_dir=" + JOB_PATH_OUTPUT -``` - -Use `docker build` to build toe Docker Image: - -``` -docker build -t your_repo/paddle:mypaddle . +apiVersion: batch/v1 +kind: Job +metadata: + name: paddle-data +spec: + template: + metadata: + name: pi + spec: + containers: + - name: paddle-data + image: paddledev/paddle-tutorial:k8s_data + imagePullPolicy: Always + volumeMounts: + - mountPath: "/efs" + name: efs + env: + - name: OUT_DIR + value: /efs/paddle-cluster-job + - name: SPLIT_COUNT + value: "3" + volumes: + - name: efs + persistentVolumeClaim: + claimName: efsvol + restartPolicy: Never ``` -And then push the built image onto docker registry. - +Run following command to launch the job: ``` -docker push your_repo/paddle:mypaddle +kubectl --kubeconfig=kubeconfig create -f paddle-data-job.yaml ``` -#### Upload Training Data File - -Here we will use PaddlePaddle's official recommendation demo as the content for this training, we put the training data file into a directory named by job name, which located in EFS sharing volume, the tree structure for the directory looks like: - +Job may take 7 min to finish, use following command to check job status. Do not proceed until `SUCCESSFUL` for `paddle-data` job is `1` ``` -efs -└── paddle-cluster-job - ├── data - │ ├── 0 - │ │ - │ ├── 1 - │ │ - │ └── 2 - ├── output - └── recommendation +$ kubectl --kubeconfig=kubeconfig get jobs +NAME DESIRED SUCCESSFUL AGE +paddle-data 1 1 6m ``` -The `paddle-cluster-job` directory is the job name for this training, this training includes 3 PaddlePaddle node, we store the partitioned data under `paddle-cluster-job/data` directory, directory 0, 1, 2 each represent 3 nodes' trainer_id. the training data in in recommendation directory, the training results and logs will be in the output directory. - +Data preparation is done by docker image `paddledev/paddle-tutorial:k8s_data`, see [here](src/k8s_data/) for how to build this docker image and source code. -#### Create Kubernetes Job - -Kubernetes use yaml file to describe job details, and then use command line tool to create the job in Kubernetes cluster. - -In yaml file, we describe the Docker image we use for this training, the node number we need to startup, the volume mounting information and all the necessary parameters we need for `paddle pserver` and `paddle train` processes. - -The yaml file content is as follows: +#### Start Training +Now we are ready to start paddle training job. Save following snippet as `paddle-cluster-job.yaml` ``` apiVersion: batch/v1 kind: Job @@ -574,12 +507,12 @@ spec: name: paddle-cluster-job spec: volumes: - - name: jobpath - hostPath: - path: /home/admin/efs + - name: efs + persistentVolumeClaim: + claimName: efsvol containers: - name: trainer - image: drinkcode/paddle:k8s-job + image: paddledev/paddle-tutorial:k8s_train command: ["bin/bash", "-c", "/root/start.sh"] env: - name: JOB_NAME @@ -589,7 +522,7 @@ spec: - name: JOB_NAMESPACE value: default - name: TRAIN_CONFIG_DIR - value: recommendation + value: quick_start - name: CONF_PADDLE_NIC value: eth0 - name: CONF_PADDLE_PORT @@ -600,106 +533,124 @@ spec: value: "2" - name: CONF_PADDLE_GRADIENT_NUM value: "3" + - name: TRAINER_COUNT + value: "3" volumeMounts: - - name: jobpath - mountPath: /home/jobpath + - mountPath: "/home/jobpath" + name: efs ports: - - name: jobport - hostPort: 30001 - containerPort: 30001 + - name: jobport0 + hostPort: 7164 + containerPort: 7164 + - name: jobport1 + hostPort: 7165 + containerPort: 7165 + - name: jobport2 + hostPort: 7166 + containerPort: 7166 + - name: jobport3 + hostPort: 7167 + containerPort: 7167 restartPolicy: Never - ``` -In yaml file, the metadata's name is the job's name. `parallelism, completions` means this job will simultaneously start up 3 PaddlePaddle nodes, and this job will be finished when there are 3 finished pods. For the data store volume, we declare the path jobpath, it mount the /home/admin/efs on host machine into the container with path /home/jobpath. So in container, the /home/jobpath actually stores the data onto EFS sharing volume. - -`env` field represents container's environment variables, we pass the PaddlePaddle parameters into containers by using the `env` field. +`parallelism: 3, completions: 3` means this job will simultaneously start 3 PaddlePaddle pods, and this job will be finished when there are 3 finished pods. -`JOB_PATH` represents the sharing volume path, `JOB_NAME` represents job name, `TRAIN_CONFIG_DIR` represents the training data file directory, we can these three parameters to get the file path for this training. +`env` field represents container's environment variables, we specify PaddlePaddle parameters by environment variables. -`CONF_PADDLE_NIC` represents `paddle pserver` process's `--nics` parameters, the NIC name. +`ports` indicates that TCP port 7164 - 7167 are exposed for communication between `pserver` ans trainer. port starts continously from `CONF_PADDLE_PORT` (7164) to `CONF_PADDLE_PORT + CONF_PADDLE_PORTS_NUM + CONF_PADDLE_PORTS_NUM_SPARSE - 1` (7167). We use multiple ports for dense and sparse paramter updates to improve latency. -`CONF_PADDLE_PORT` represents `paddle pserver` process's `--port` parameters, `CONF_PADDLE_PORTS_NUM` represents `--port_num` parameter. - -`CONF_PADDLE_PORTS_NUM_SPARSE` represents the sparse updated port number, `--ports_num_for_sparse` parameter. +Run following command to launch the job. +``` +kubectl --kubeconfig=kubeconfig create -f paddle-claster-job.yaml +``` -`CONF_PADDLE_GRADIENT_NUM` represents the training node number, `--num_gradient_servers` parameter. +Inspect individual pods -After we create the yaml file, we can use Kubernetes command line tool to create the job onto the cluster. +``` +$ kubectl --kubeconfig=kubeconfig get pods +NAME READY STATUS RESTARTS AGE +paddle-cluster-job-cm469 1/1 Running 0 9m +paddle-cluster-job-fnt03 1/1 Running 0 9m +paddle-cluster-job-jx4xr 1/1 Running 0 9m +``` +Inspect individual console output ``` -kubectl create -f job.yaml +kubectl --kubeconfig=kubeconfig log -f POD_NAME ``` -After we execute the above command, Kubernetes will create 3 pods and then pull the PaddlePaddle image, then start up the containers for training. +`POD_NAME`: name of any pod (e.g., `paddle-cluster-job-cm469`). +Run `kubectl --kubeconfig=kubeconfig describe job paddle-cluster-job` to check training job status. It will complete in around 20 minutes. +The details for start `pserver` and `trainer` are hidden inside docker image `paddledev/paddle-tutorial:k8s_train`, see [here](src/k8s_train/) for how to build the docker image and source code. -#### Check Training Results +#### Inspect Training Output -During the training, we can see the logs and models on EFS sharing volume, the output directory contains the training results. (Caution: node_0, node_1, node_2 directories represents PaddlePaddle node and train_id, not the Kubernetes node) +Training output (model snapshot and logs) will be saved in EFS. We can ssh into worker EC2 instance, mount EFS and check training output. +1. ssh Into Worker EC2 instance ``` -[root@paddle-kubernetes-node0 output]# tree -d -. -├── node_0 -│ ├── server.log -│ └── train.log -├── node_1 -│ ├── server.log -│ └── train.log -├── node_2 -...... -├── pass-00002 -│ ├── done -│ ├── ___embedding_0__.w0 -│ ├── ___embedding_1__.w0 -...... +chmod 400 key-name.pem +ssh -i key-name.pem core@INSTANCE_IP ``` -We can always check the container training status through logs, for example: +`INSTANCE_IP`: public IP address of EC2 kubernetes worker node. Go to [EC2 console](https://us-west-2.console.aws.amazon.com/ec2/v2/home?region=us-west-2#Instances:sort=instanceId) and check `public IP` of any `paddle-cluster-kube-aws-worker` instance. +2. Mount EFS ``` -[root@paddle-kubernetes-node0 node_0]# cat train.log -I1116 09:10:17.123121 50 Util.cpp:155] commandline: - /usr/local/bin/../opt/paddle/bin/paddle_trainer - --nics=eth0 --port=7164 - --ports_num=2 --comment=paddle_process_by_paddle - --pservers=192.168.129.66,192.168.223.143,192.168.129.71 - --ports_num_for_sparse=2 --config=./trainer_config.py - --trainer_count=4 --num_passes=10 --use_gpu=0 - --log_period=50 --dot_period=10 --saving_period=1 - --local=0 --trainer_id=0 - --save_dir=/home/jobpath/paddle-cluster-job/output -I1116 09:10:17.123440 50 Util.cpp:130] Calling runInitFunctions -I1116 09:10:17.123764 50 Util.cpp:143] Call runInitFunctions done. -[WARNING 2016-11-16 09:10:17,227 default_decorators.py:40] please use keyword arguments in paddle config. -[INFO 2016-11-16 09:10:17,239 networks.py:1282] The input order is [movie_id, title, genres, user_id, gender, age, occupation, rating] -[INFO 2016-11-16 09:10:17,239 networks.py:1289] The output order is [__regression_cost_0__] -I1116 09:10:17.392917 50 Trainer.cpp:170] trainer mode: Normal -I1116 09:10:17.613910 50 PyDataProvider2.cpp:257] loading dataprovider dataprovider::process -I1116 09:10:17.680917 50 PyDataProvider2.cpp:257] loading dataprovider dataprovider::process -I1116 09:10:17.681543 50 GradientMachine.cpp:134] Initing parameters.. -I1116 09:10:18.012390 50 GradientMachine.cpp:141] Init parameters done. -I1116 09:10:18.018641 50 ParameterClient2.cpp:122] pserver 0 192.168.129.66:7164 -I1116 09:10:18.018950 50 ParameterClient2.cpp:122] pserver 1 192.168.129.66:7165 -I1116 09:10:18.019069 50 ParameterClient2.cpp:122] pserver 2 192.168.223.143:7164 -I1116 09:10:18.019492 50 ParameterClient2.cpp:122] pserver 3 192.168.223.143:7165 -I1116 09:10:18.019716 50 ParameterClient2.cpp:122] pserver 4 192.168.129.71:7164 -I1116 09:10:18.019836 50 ParameterClient2.cpp:122] pserver 5 192.168.129.71:7165 +mkdir efs +sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 EFS_DNS_NAME:/ efs ``` -It'll take around 8 hours to finish this PaddlePaddle recommendation training demo on three 2 core 8 GB EC2 machine (m3.large). +`EFS_DNS_NAME`: DNS name as shown in description of `paddle-efs` that we created. Look similar to `fs-2cbf7385.efs.us-west-2.amazonaws.com`. +Now folder `efs` will have structure similar to: +``` +-- paddle-cluster-job + |-- ... + |-- output + | |-- node_0 + | | |-- server.log + | | `-- train.log + | |-- node_1 + | | |-- server.log + | | `-- train.log + | |-- node_2 + | | |-- server.log + | | `-- train.log + | |-- pass-00000 + | | |-- ___fc_layer_0__.w0 + | | |-- ___fc_layer_0__.wbias + | | |-- done + | | |-- path.txt + | | `-- trainer_config.lr.py + | |-- pass-00001... +``` +`server.log` contains log for `pserver`. `train.log` contains log for `trainer`. Model description and snapshot is stored in `pass-0000*`. ### Kubernetes Cluster Tear Down +#### Delete EFS + +Go to [EFS Console](https://us-west-2.console.aws.amazon.com/efs/home?region=us-west-2) and delete the EFS volumn that we created. + +#### Delete security group + +Go to [Security Group Console](https://us-west-2.console.aws.amazon.com/ec2/v2/home?region=us-west-2#SecurityGroups:sort=groupId) and delete security group `paddle-efs`. -If you want to tear down the whole Kubernetes cluster, make sure to *delete* the EFS volume first (otherwise, you will get stucked on following steps), and then use the following command: + +#### Delete S3 Bucket + +Go to [S3 Console](https://console.aws.amazon.com/s3/home?region=us-west-2#) and delete the S3 bucket that we created. + +#### Destroy Cluster ``` kube-aws destroy ``` -It's an async call, it might take 5 min to tear down the whole cluster. -If you created any Kubernetes Services of type LoadBalancer, you must delete these first, as the CloudFormation cannot be fully destroyed if any externally-managed resources still exist. +The command will return immediately, but it might take 5 min to tear down the whole cluster. + +You can go to [CludFormation Console](https://us-west-2.console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks?filter=active) to check destroy process. diff --git a/doc/howto/usage/k8s/src/add_security_group.png b/doc/howto/usage/k8s/src/add_security_group.png index 50eed4c6573a18d6ae0f9df9bd6a3cae05493e3c..bd34f46c9b0ada7027fd53e553e7d033255d25fc 100644 GIT binary patch literal 118948 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
h+n|c$CYJ=vXBNGSD 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

;Z>aHpm|~z;JVY=H3+B8 z1(?9_ge$fU5-~~NNWAEZ(BQ>`c^V$MvrH=JdNc}O*Ksq9FKe6!+54h zRokZUCLE1_M87lm`fg`z;B`&LCMY6Jw&s{!$w<_r8q}kup-R>QuL#_i5W^}?!C${~ ztS7M7sPraujT*!DpsHB=onTgvB=VcOCJecv*aR8SPKN5xVbGg7is{*T_oTah#-o## zJfYO{W|d$w5Te2`!XOb&I5+mZ7jHzQUrA!bL4N_3pljbiK@OJbkxYKv6^k!3M?H=3 zpU?HEPx|U|r;dvAZH7*51E^l-~&;jP?c9-n+-*tD!9wef}T+?(t6W@vPdBUmh=Df<9w zs`DzZMhsKU|A*E|Fg-tF;<0Y|C80+1n)u4ZPVOXwStw1e6?iqFJwhB#nansYKmV<+ z0FSG>O+l>i20@tww+s0c3k3UG_k3~>vyl(_y@W?R>V_UYc4T`p@eCZlN8`k}JvL>c zBS&Xt!LlN|P~sa*CP(A(3h49N?layxkQmw2>mz#%edq*44>hpE-I7I!!c~NKINsG) zgU;`LC`VXxJHfyQ46c~`X5D!0%=E;@|0V$(ctdEC{aH=3vsq$y1*{QLi;4vMFJ0$3 zUs;*YSp~C}GYP%w^dR2dnTw`|3;t*z_}Un9yFZ*~oYieUJ^&_(+DWgG7aQ$_XsoDF zBCd6wZxrUVfDv)UVc*J(&$=iw*>EN2m8A|6%zz9e@2l%gePJkd=0g1{lLZ?+zqw7W z&v6gGpFqr|Vn*SX5fOb69ra59gW*!QhExkltanI}1h&j_D_1#on->P7Vr;N{A}Y$RFh5F3oI2 zQuQa=ew}~BiT3;veE}k+x=Q9A$v~%b&In4#)0|rl&xSNLdfDYfV@>wk{a`XiwGVb7 zQ3R~qYL74wxLx1$Uzn`na(PklTT(nz?b^9JN-jAJddRaJl5Z`)yr6DY0>M)Q-yapg zL)_mPqSj3fHru!+Tv1ya{KyP44XdG2NTwKvv+H&R1mV*;il6*2r@sHGA6;n3_?8!w6BQ zSW|$XFV+A2h}r*X?;aDW+{?rlY|nPIUp*sWaDY2tAdyr$}?*60*{a!)-@&ZD>|sDT6Ryq^9*P;gu6eCFIv-F5OYyk@6g%bRDCs`wbN z&mcD^@D|}YzSFHHmJQqE>8G%B4o2TZ^i>I{YCDraWYz~BO1XSh%;E*K|iKMd*|rLqxz20t5N>HbQ3edG?H8dVT2H7xvH z7eG~(oq9_Ya1iA7K`fH;bZXl)JWn0X<PCvNNhzU2sT$wy!!Zj?-CyuJ2*)Y(Y4k zp<60j_stbjTGJ~Ls6hBCQ1WQVbOXcUC|(}_&D-RJ#jb|)aH*q$6(B`#llA81&yi~j zVkD~>IYU(1s2nm=FYo4~|fy4(AG1~AQeZ$!p zc27yR3*u7_cE>rp^G*Gh-fwx~^5OLm`n zB+x24<@Ix|kHf}hKSnjMF3~p0;OJ|SD&v>W;M;9yXoI(B1ztRJvVrR zSrkqvrlso${k^^O`{2=r{I}>mn>%mtO%9G8e_tA;*(`D#{OwRh`oIc&vLr0D>kK4h z7&&|z$rGzlNRU5(9FA*d>Z=CVXKAZ%5b0K*ziWs;gbIqJ9WopLQld0c&b?Y?FGWV9 zNpBvt8=qg=v#*J_S5FG?*EMP@H6TUT@)#qLkwnTaP8rxiu1=sWSU}*J+suvw0Xklz zHl`~RcV{=((~!vlq2b>yE17AgxN_iCnROQBc}nkL<%|B_32IR4rS?~|b&_5Q_f5mA zkr)?pJ|mGz-=69gjS}CX*>cj+#5^b3@WtBuPgf~U8uzw7Lj9bC>Hbam&8R3U{OpGr zPyUwtIjv-sbM8JRoIafp_Ja#Co^7Qb;K=$Y_V?8@JsAl+YE*g9xDdV0gn7R(8V(41FiItyp3Dnnif~^8<=11RS&a# z7~>X-t=D)vhcyuAcU1H(4;^2`Waf+>&QalmQ?BW|`7DymQz9)}ck;}3Cv|_^2RHK_ zw0sKNyl~g=wE4S%O-`1hsAfj#7L1+$)^!cYY1pynCTJS2b!xvi)mhfKilQt+)2HC0 zZbu;jPY*kV@d_r!J7*#z$1G!{{Z#vB2&+NG zPT;K3H`-ITx?V7|aGy-AayZD+07Z|oTJ1+(4KHo`=T^h!xxCNAc2pL?{qu3@pV zd2(s`@3>DoN{>HXvoA$94V`vN+bDMwV84kC5qSf|Y=d&=ay{v8lCW-dAUR<`YB{W1#X^9T@MN zt4x<q=NpgRTC@E|C)I94Au~{FT^%dFk*V| z%twyH?#xDn+o`+1F}s|YO?CfGqEY%5yi`pN+0|_YzgRdQcGt*Yfm=Os=oMjdG#fV` zE*#_{DB2WZ^MpTyOH*Q5JQcjiAK+`|;d?K6JUHEU@)-?Aq=;6;l5eU+zy4h`|5+e$ zu=#zF{(H$NE%+Dulw12YIBAENs}||}WK^qn9@A{3 zHJF@Ycz&$cTeFs-i#?JW7ClKpnCx_gr0eR*55NqCr}XC`mBNXae;&W}%#gU~C5Yk1 z2{e7P6qGV2sbO*ACD`$wfyh4Zf1?H4KU+w}zl>vc3zW%oa z5axX*H4J3_CeD8Cmpi?1jn$BFBX8HK)%mQTp*{x-ssswS@I*!%fq7^yB}> z+*^iKxo!Rb0#bq?y=WBaT7XKof`o*0NQWpQ-6;(V5NT-vk&u>_X3-%a-HTSb`!|*Tv-pYu)#pW6n9|7~k<3LuxC|%!&DhL3UIocT)*Y1PmBHtfyM{ z6G*4VcT;z;dV}Eb(AGJ5AfEqt&mbxNmkurnz4Fn@;1kbbOC7g)X^{cTXYX<%5qWML z$4!Cp@2s<;cc(+HdU0`bYj;7_-G};CIyzk5=kYFm#oh7UI3_`g3s0BglrW5-(Um4& zMNM#tjL~mt*xo6ONqKG}YhN!(Vu`3WQbR$TnwNoG7-0pF2nUkS;~z*uH0{Jjqw1`K z7>v}hS9a(%Rt@PGE8iF8A?zA*Ym*LigQI_=oDsjmf;u%-p&-P6CdtA^?eKvkBE!=e zaOAof9?JvqGlYqp7f{L=;$CZbAC7)6tp8IHI{qMS*#db`2(~!verEBq7(%@lUKW%{ zO1#n<@1i8>5!Cr{x_E$ksX2ipZI842P+kLWZf7Ox3w3y6R=ISQ(Ga=^%ikf7JdxMH zmVl_90l@Rju?O!8WUF->algp*ruR#Rv`?fFTJxF0hwub$HpcdxOj~)Kjx)z4!Sk0E zO4KULO?h*Gq^Q*5%}58FXxdaB^Zqe5!O|=CQ7%!rwTkL)H9t)%pvCuko)nCLXw6Ys-}Fi2hJ1GT#^ zLfOia`$61DSf}&#F0Gs?t5A$i^;?6n-B95Mns&$VJ1g4rZ(=2sr3WSY!l|p$0vEEP z73I>>>Av>*OCMJuB3^D|SGGn)FrHBPMVdd=c*AF(Wbos#ek$_3iq^98;>U8r%FwIJ zP~izyy>;~U3a9K*x2%+X<)ekd*^{#Adw9*yax63G5$pPtT09 zD)yc;h%FJiCN!Z=*mnsY(D+>+wl(_J8zxg0t8OQjA7MGfT}m&k4^tF57&f(1TZ*$! z5jL4J(Q1~bHA|_Nt*dIa5buy$@@NgCuqF^S@n>*{NH+S#vn}|hmGiMn1*2d$U&Gl@ z5zEet2wRcj-xx8ufJJ-#RS{^;ivrIeH!-YBk3O=SS>fh4e1mz44}YQch}_JsAcg?J z2g6juHX($G?7N?5uog(9_@S-gWQIX1E%24#+BQTr42K&q?3=7Wk_3VDryy+(v-5+2 z7w@vh{gRs_1%gc=gFsZ&LHT(Xh0WRu+@x=c(56M1Tk-mHD{F+iv{23rKrt35q{*VV zka^o3Q@vt2EeTP+9>YP+21c)^G{^fmj#!eZFj;2;GWbJoij&jP2AZ6wo-GNR{1oQf zRxFyU<8#D;I$7cSJYHcXQp4oo4{x5N54pU{iOIeG@x|?r`g;aR*FSYI-(rr=)l;6) z+lgfOn!EpD$7-lH>sZ2w&`Sl9Yqb+ZLhKa@=1ZC zU?F?wLv(V<_swtL^zo1gg?nl1d~R$~_>n+P!)ETEf#F5aU;u93vXhR1F{A~O^(Vcr6-%(f_ojdD)sax;ov*>&UXNMkhB|YF>oObUpZ5w~1C1vX zjW6qV&*mX1d*>cyCW536iydkH2c_{}t=?z9Dm$wlDLR)uzWuE_?COLjz@a$ucxBXG zz?zQ(2xr|jr)oaSPskGWbKezwyCZh!-=8N|XKHK-_?x&!b1sJkoWIGlh4zxAy8o`+!!4Rk9dvPeVoq{2D)5Oqj#&s`gl`2 z4j@B?6k@^9sz_U3j~>3lCkv^zAGJd6Xmrt07l&Wz^|wn(Cjt$@7PEG23ujSZPnFL1 zDzYPPuXvoLg1%Rq5v5XImW(hnxWz^bwaL4f1`jK~!uyk&YlAkl`9I)aTfe3p2c2oS z!`O7lwV=L&d_8pM9=N6Ikd``{rLQltaZ{O0T4TPdbZ52N4=2A5xO#h-o0!jCKhpnZ z>J`u0we$oDS-*E75$Lgav6P_-#6%8iI@+ZKq9n9|)a)z0flr}=%u|tR2<77%v+qAe zVY-qD8M+n;JII{HP5|cY*Y%u%s&6c~2*0V0=}w$FwrwA?&p+h+EK(uwI8{Odnno)@k| z4SjXIDtgapoOEi|Aos(>MqNl3f8>#o6IV6)xiM*$+HsBMEwtjGtq2jM@*Yr{y$xTv z*C6Q|VRsUvswiu;$I%6Zh=oNb(JsYrP!9Otys4A3?ftUryv{!w=Ab)LGY@}i2fWMA zgP3CLb`#wGg4ufY0!p3~2RHlQlldB98L5Bw^q;nhrC~21Dy5Qg^GMp_V|a zjp^a@EiAEJ>OhJe*=Xx-_@O+ms3g=Q<0swl6|Mta%o^+AFlPC)a;D)65KVPY<+5#7 zjyZl8xlqPgF7J9q9=ASBQf2lfYU(ZYk#VO|J?~sUlo={bj0~UJq&>$TBU^ zY{+^w{7x0^pmZ&Od25>+W2TE~if6f9NDv{-z1-ochoDaLJXgZJFILs|__hIhI^1$& zP54|##Q;I;wkLW`DpClh64WZ9KCg_go)YOE_|?KHdPjYb_*85` zMqq_}=jW%_Qr^6IRnC*vMek*sy!M&>f*9Mf8|B_DqCc?V^cVWlUgU=~-# z3VN5PJz#1TGoe;76=aKgMIUWPjgCE;Wj-N1W7dY#mCPUX4jmC#3azE>76Gwo_SotD z(<=+HGi@m&axa1{(2BUMDMis>d>vYJta5#)?k#J!=J8~oXhO{NU~%cv(+G=u`&BKU z?p!ysFSsOFd0wm%5gP#aIhXfqJIJd`*8MRkP!MK6zEyK&k!&lCAb%M2weOYCib)`! z_0AS(xt-)hd838xvShHgJWM3{d0d?Nk}n;%4K|-}i+;5R1KO4MekSdc+E)9^gCg%~ zekHHSb5h$k436rYdQ!Pl5sPb0TjxalF)evKeO>oryqiD5Zr<@;4mD$czQ-_n=UH<1 z=a(#3U*-5LGls@*RtgsuM_Pauxe=}@WR9|WuPgdBh0^QsGC!TCYI(k~uQOF6ms{FA zb5yA3^uBSUft$Ukx@Frm|db6k8MAXTJ&6~ zD3zgNykdWITZ;M&`Y9thz+L~-hp9l{M_$yKj1xY$Cc4hsB1r=8^v(yK3DCZAhl%Q7 zd#z~fENWIQHDBe`Kiq_y{6-8b$kgb9x3$czI8cZW3o1Ui<1ahbYQ%_b!m40rL`53F zj(AvX42ub|S(P^a@SQ))eQ-etucymaT&6|qnKop|_>DGa!RllebCB@vTs;fHgmMC`fUZ%ff#W?|z?u(6>Ay{VM?XDP{XXhtf zn)Oeq+*UJK!n2}pdP-;;2Q2U_of^aV`oi6m5|^u0;4D9iGk>aLDw8QQEh0W=hHimv zSIt8Z+j&8=XZ3E0pPjssbd)$sNGz|iar!mm?>ILINf<{<=8O^E_X?O9KHXFHFd`wz zH%rgz4uD0zW1|ojr2WjgaDHja&)9dnNAPkU-#Y=O4T32Nte&h_%KL-RbY_zZ!5a*? z>bvCU#nLQ9H!`;?M@8f^k+EG*N*r{0wi^Rgi=ndSv_YsG&6)JUPg(g~=CtEUJm%}i zMR7fB{FZ3Ld1GxnHvNPjWr9Wk?b+m`HfH2r#Oc+8Vf-!8(n9Ic?Lsq4^5{>s=(QI)S&SZ97eaxP^^RU`uDlLI-?+mivG4q8FBc*Cp%7dG50%^oqu-$rSa;|SlM8Du zz{}nkY&!Ec)cvONRQ&8ZqgazXWZc26j>+^FI6w zlvE;N6+O5`fp8FBMU09AXH*$(esI}x%P8^;xs^M|6x{i_yC~Xq3!#k^NVLdK@EV2L z#maxbL44vEVPX~liC>yJsz3T_e8#}`gJ&~RnFc8`RoWBV7wJ^#?FVwUcn#~03o(Gu zyRq+H;)Y)Nfh&|`q=gL*6S{vM?B0F0`%qw?AZzcW-`lH&g~)cVKf%VghJpVcRm3V? z*L_EDnc(Rw%g|Gi`Cy-34-+(c_|0lq3_;Vcva`mhcayg!L&F|FmPU?*m5z9km@!5P z@+^HS=T^y%Hnt#sRc3QKVGA|o4NKN3Wd)g>0J_d&=Ih#z{N!L~DsPS^uEocas$p$t zyzLd#^JP&&lcQef_OxOaB8V~UnaW0$k)?v){F!gg$J^rEPVEe%bDN0vT6mmIWy@gA z>@e2F<9&JF+Tf9T#XQg_diE2}5F_PS76r7bc+ao5hzFcY(7!>&LBojA&Y)VP2;E`5 zEt2Jz*s=KJcy}BV_x7C>W_tSo({b8OCN9I_CM#2a`$egW(mAIfYA5Ej)WbA8!X3C+ zOn_N{kr$D);38#=E5XsZn^60tRoRm+&5|yZC60xGz6(d|nkU`MNv~65lEG@Z2~GLA z>Yt%tp2@wOxJcN~DyAuFy^J9hW@o{&$yB(QaVsVR64F-oiH&Vube6AsG7CU1@6a|R zE#2>$SkEs?t=n|IY#o|*n&cqA-G+1f;HmnvhtzdI!n7j$^E82H667_PMqWJ|WcAJR zbMxs}+`)}viz|?B(I8z{eQ`JYkg?qF(VjkSB~nTz zeBz+c@7iboF**NK>O>sh;n4%UZhnN<*@ouNl6D$&I5h;iIFG=uk%qVEVy}sFA=Mi9 zlX4#AQ8LDqpG?=xUH7}_S>nw0f*cF7$NH$ZPX9ThvUc}lIs(8cv zlr4B%MR1Ed(1yKN{S&gnITK6ozW_4ei1(^Y^N}N2h0zI$KDsg4YI)2g${j-j;wn$t zWF7^@LP+k+Mp^X3tIvf4Z!imdFnPyBiG~m3wQ2dvOuxFXR^7Yx(osP;vqg&HlmBF_ zGHjtfPcpOYp&7Mgi}(r~zF#rD$KkzO%(c~(a>|UGKxU@O{<7s6--yXni~WZMKlHNg z69dvdZqT7*qms+u#d(fV?@exK`kM4M=8u+Sly)m*U|sbxZEtsm}AGwS3=w*Gg)D)S!U>HcVYa(} zVpcJD+A8%4G>D1yrO_X4RIj9VVlkgH*9N#}2{iCIYl?0@;5Z&qbR7etx}5usOI6>* z_k4-8*l{ zjfkWlH|#N8Hix-k{Ft<(xTDv#8fI|5&{cy4RH^?^VtyTFXrfyWJEnD?kkn_)Tc?6Gw4mGZD z*Qrkpdnh((YPONzyYWyy?wY+YwSjm~bAOGvGV%#OCjMs$Y?daYUjltlSQwdit~B>eBLlgx#fSfS!Zb1tDWl20b%Q zjfMtVE>BnbrBR)?-gW7iC1~9TDwUDFSRQ`9e_B1)mn?D7tgjo3eJIu840ZYD&ot1- zttz}@&oow=#fZ1>?K@zNeHxe`A83D!YJ$z4qV?T}VNf7qi*lZ<3+)E+rEi*hRUfHQ zt4WB+PQ=S&i5xTpKJiBgt1>}^)a_Sol|w&zx+2G`)Z`o{0%H|580oB7X;`HShIO!a z%;Na_!|@mbZ|qFzOi!*knqv^rkiG;BUyL2(q&m9wGSPzG5r^rpy6qZ3v<$;#E~PBd z4F+LtcO~8O3+`%v^%Z{N*Cev|sCn~2ijm>NdPaQ#i)Nz$oaUyntV!q_+4|R{)|-XV z2y-ty9*&gOlEleiZ*{M{S}v|kVX^g0FYJ7mIq%^#t^E;}Q~DmSmHutMvF$X64{tXu zykIuFo|TqsF}gX9vNY{Z5%yQMvs)g6id0?JyZkB*$}**|8HOW=qp>hhAQa(}f}Zf! zsG8KJvkyf(K*8uRAwLWql&ozDWoY%Q2_&bvpm-eO7UzJQpN!|1X!KXfAw2vV0=IxL zRY@>hUAo)WtROjjhm3I@S`vHY1kWcwYr)ruG^a|~si@)R+iXfOxg^ZQJ2zCQNi3vm zHuFdeFA07WMw-3KJtE8wYEBB7kKf`kdVHb4_vJR(Ru~D7ULURB*{OkjPA0=9p5)PV*H5+J}73Y!Y68Pe^mv0EIAQ~1!T8@}LbdX`0awEC2` z%H3oCT66cVJ@1QAZ}mbqgZfCGJ>Y)xhfBp3g|CYppt3DxmPtX9`ZT+qYgFFk?E_V1 zlc%o}EPviB(4UMvjF(=$XD(%@ghIoVQ9MBRG+5bZ2%@s8QvB^(aJZabm5dA;&SUn9 zv2FU-tu|o~b=DrX4lZ!x++&w-X#lwvc|B#XWnMe?o%|tpqpp#VVg*%UCUd?~$2&qh zWqlkc`P%5p^+<(owz|glYY_P3NWI+8Ve*Tfx&oUOS$KmZiI^*A+N0^JjBY>kP!D1! zE5Enq^G=ldykeM%an=ak`XcS~ZfnF9T{rWA@$?HC0x#EDkhr*XZeiTqaGHIkBe*nT z`E1bAP3L4b*Zaa|_DS;U!w<(YRbmDrnY6a+t&xgp++KU+(W^=W6|o$XLf8#tl@P(w zo05zfsnic^4pjeA8Vt2Ug;Dc51(cviqj3uwPN7_2)`XWr6(gchqSLBq0?B*IEf6}> zT7pJxFDPM;2pNq=!wuqF3QuWGj@3s`JtK-A+xwHZ?=)}ODkbnT7qs8o7rf2NwA+i9nrRjyj`LU1*&7tw;Ykzq(lS{rB`86#v#W#Y5H zuGt{yDagP1QqRiP2W5CZh*qD;_=d0Ey0uN$aF8CmM`)$Eohi;R}loTkbP^sr%Xv8uU#rx$KLwjI>1fQ!BR2wbX~+ z3xt%e7&NPKCOuAi3lz4dvrmMpxz>dt?K@RjugCgRwi&(Ja7A$jm6{~6*PPm5!8nOw zidfWyFrKkux+QmcX6FwmZ6Y^F1@EY-F_UymRkiEvA2nQgmIlLmBF|RSdp^eUK0d0t z(cQxvokrehWZPZl+9|L9E_JD@H3>sBu9ZpAgVP`5{kgQL$d7`uj~=>K@z0#d6IFVu zpu9AonE5B8_+*#_+6J%u4IU|!`DkX~g7%KJ+}_OcbxYk+4>ZC^`)F()@|%p2&-EIH z#soAsJjT*uJN_C97(mJ~<5(xIzL7vj5W~_krRKdV1pV;NB~(JVF+xolyZrGO_U|qg zFNhhHs((&s3MFcJw+q`-)U3l&Tm?lnLX2h+lcD5I_Ja$QJDW$T9%N=HCit+hyj}Ja z+Gliv64yO%N9T1g0U?w`HLP={75$2Q>t~SKi4u9Qrt_8z|L61c$pjDn$?N0~)XG1y^OhLt~o{rW!|B(icf#oSY>L_uNu{tX-DBUP7GsK2AC z*1f0X>0=po>AoMHrc1&pLPKw$iv>iQb&Z$7Zd!NL5i9%mU2pbgRlOX_09wRMDz=u} z*UrMY>Z?@7Wj^)nuAGEN7t3MThG$3do6{G)BeTzFqWCVy;3_PPJhP#4sKZe}Cp#0v zyuDis3aXU^074XU%ZO2qvp^$5MOv}-cd?L~+diVG7np+K%7Hxkeb=RNITGjy5q(ul z-mAQl?F4d<3s;&?l+E`nO^A&k^tUut_3Vxi9z9xwf=Q2g+ml~v8v2&f__7gB4W@CQ zC6*uK-JtESqDI`hdPCoskih@l&+t-fp1T7QBj8M0haV;Em zc_-$UdnKKCC=mdvveG-^&fAXPG(W<~LVKg~=w7P>v?E!qQ7iloDC^dl1chfqBEZPB zGl$-}htn1~H9At5-QY1|&ZHM#u>sYuG|#TTko;)hUD=FOTeEZvK3Ykb{A9{EZW_H{ zspPH`&XxLWtlY6$ZxBTpudA#d+49zf9eRgM*lN#18AeOn#IL&ARg0_Pwyzdp%3^&YBWB-(|@ z3N1Nyf+KVs(t8`k&ZO@Pk>Y2C2PmQ^tv;xJSatVQWhy2kBBi=2K`qA{rE>0<=$XCk zBAd1&JBV#VnBQMs-VlR8{HV$5bsPde^9KC3b@fu*y-S!i8a0Mn_*hT`+L0Bkwl&o~ z@ucqt;^pTr8mBO9#3nNqlgeXVF~*_8?ldFrWMCCxpxWvhYV=c4w{VN1qyE+@9#Cv( zlnf=JRdg^eeq&04hRenIb$`&3&7$#IC3EC^?e~2Tr4er#*`1g+%4i*8RQOqc$=#Hd ze4HHL{g4yYZT|RI?*SmMB!~=o9&L#!h2k`vygaQg_ z^5dpFa>)IC_YXY^BWyQM1%5RAdT|FO!vzo=P&zf83Tb*&ZwCjqp)o`MCU}m**xzTe!IK(WDa}D=BNsaV7K1}8$V2Ae$RYpLLJ&%H`$Dbv z97LB8J4ylEzlPB_QPQwaLAC=r7{xc$g4GZG-Gly1Y4!wDI%kfjM$JF|d>*_)W}u_B ztTv)`=)XRJiGsLiKSYcw6B&IoBt`!1esR3M+nU32{n=)c9RoYNiP+Ky@BjJ`(sD?U zN@RzBACrT)?abGItXo4ZFfq(g`e2m~CIZrjh^IXaeg^vZCNG5AmprMSqy0@Z{9nGy zH-iAn^X8e}z((tR2hqo?K6cK3Mo0oB3^$>uiCIt$J=?a0!rDz%@UO=BySgTahQ904 zu#MPuBibXar<`AgpN8L!r96eBsVhM5TWFhwVVneE}vS zSh~VsJ5Jj?aTq$JYydb@ZRaO@LstM_Onh(g=N{CaKHRHK;=d1;4gm5$sEUZ?84D^5 z+5=ZnG}hXcKg|?!5BXJ)>*=8AorB!y7Zj_F%s>x>YXy-+ieHec(xwr9lUqs>V!x>+ z`QI!xaS>ludK_GyO)#4aBf76S3cnssIPj)HC64~Agp__H-U6f8%`d8VvjyU2hL>^_ zo6qZBCc7g6F#lp`|2}wzJy^w01EtAL4wYdMV8VU1AA^r##7_x)ug+6kfb6L;#7glb z*Hb^ zu!jvs8=n8|*Gb3#I69L+QLX5I0JQ##*&tuCaTN*6JGC&x{SVLbzozn!AHlaEVR@ql z-WRx@_Za^hmFb@Y=&M5H(qlq1q)H5!c}yNN?7v&~zkiB#Yy}`p1?&h8);wkTU%Z$9G{L;!^e9TOMTGP9{bVv-|NZ0q=6@mNzV}D8GINTb{omgW(82oQ zY=2|2{xIBhCRCy;mT1t);OKf|(%-g@w~gsoU^vn{){Fl3aFnG2C|H>&4%UAfufIIC zuLSbwRyIA*{JSgHS6d0}R@!Ok*Z*p3|6$()Zvw2Ax%8Cn@7hpf0Ta}D5F6PAUpEZZH6M;$jud{OygB4m@7ZX7)>*KUn~1fBQKf8;T=6&s$nw|10C| ze@u!3bnyDO_xX{B8gMNgS}$tM`w^HGQl2Vm0vn(LY{vBgpk13%lmF;n}yF_qYCshr5Bi z6ri)=@>qX87^$Z;S!^<1ZE^x(gpb9`fW>|fEnJx9PY3Y7kHmlhu-1F?t{`|wf@C$@ zHN7B3IyyWFh5=y$_NRL!2>_c1B{ws?X1CYNm!mFV4aj-rJnf*wd7H6h@7>?tu@H)2 zGkMPxLurOARed!67}YP-3p%ulh#)nhX_mLdz^xeLeYTw+P#*u>N*fn{+0kkE`|mt7E_1%dZ6ulsX{6+_X3(_zP0R?S zw;ntM)#zR2lOKx;JpS38EMQMKRAXaZf3h4nS#7^Uy0_e$Z@=z}{W$#zYD~U7*VlWV zjFter%6{D6C5*(Pmh=h!02J#lYDuEKiWaV4)e2jz8!iqPfUEoRhWW`-JZ*@t!O&w@ z6)@uBl-I4qCVYllWoNwRU=@{xy@0TKrGs>?Z_d82e#O80%PYYGprtCL-~IV;oL$cG zD5gLDLJL4T!jNFubc5*-Xq;UqLwuG}8{D(iJ~R9Q>j)r!@qhnDBQ`Dx$uVkET|~l4 zZ9(J*p4}yaphD6@0@`nDV~5Sfg0G zm|79l95_(}PIw=dA+h6#wgrg{t*65dkdkH}nqvqUAPc~eIoQvopAMI`ZRSB_^&&

t#8Ut1fSE$uCAV3y&iBGMr#s5{iPh* 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�fuy`r+Bc*i*N@AeAQ$RbL;cE`S<@zM}eCsaBrq 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≤N&{|>|dR=DF5|{ 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
!kgl!T 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°S$fL*tf)R)^V7b$W+(vY)!?nM)+I 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

-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 diff --git a/doc/howto/usage/k8s/src/create_efs.png b/doc/howto/usage/k8s/src/create_efs.png index f4d448d1518e11a11d535efb9c3a78b56cc13149..e5f1526033d1daf401700989af1d25919bcb7675 100644 GIT binary patch literal 241814 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 literal 250321 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 *jO-vF; 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

![route53 zone setting](src/route53_create_zone.png)
- Add A record - Click on the zone "paddle" just created - Click the button "Create record set" - Name : leave blank - type: "A" - - Value: + - Value: `` + -
![route53 create recordset](src/route53_create_recordset.png)
- Verify name service - Connect to any instance created by kube-aws via ssh - Run command "host paddle", see if the ip returned is the private ip of kube-controller diff --git a/doc/howto/usage/k8s/src/route53_create_recordset.png b/doc/howto/usage/k8s/src/route53_create_recordset.png new file mode 100644 index 0000000000000000000000000000000000000000..c4afac6b666186920707668a8d74bc0d6ad3bc07 GIT binary patch literal 114396 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

{+-Eca$*Qy;nOTb(a1O&t%GUjt{-)NZJ5%gmA; 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

)|v~87scqi*gsyWd-|? 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Ν2-!vig0b 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 literal 0 HcmV?d00001 From a3ab50044f4e79489e2ce647844fcdeb59c4e59d Mon Sep 17 00:00:00 2001 From: xichen Date: Wed, 1 Feb 2017 15:50:18 -0800 Subject: [PATCH 134/370] update image size --- .../k8s/src/route53_create_recordset.png | Bin 114396 -> 35749 bytes .../usage/k8s/src/route53_create_zone.png | Bin 177965 -> 60518 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/howto/usage/k8s/src/route53_create_recordset.png b/doc/howto/usage/k8s/src/route53_create_recordset.png index c4afac6b666186920707668a8d74bc0d6ad3bc07..34e476c7beac30fcdde13fccc4cc8d08b4be3d35 100644 GIT binary patch literal 35749 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%0AAp~;o;gSm3%-qLSW%IcN8x>C>( zFs64!%w2=vlZjF)qq>4r{X!)sLUv65@Po?Hay?ECF_WsalK**xL%h=U$o4qzwG!Hu zuF-QvvIS$*=@X@qYJEZppj6s^6XucN1XE0l_hYc6`+S%`_fw1v6V7@=w^=o)v}N2i z0qH0j(TM*FmuD^86wsKy)qE!Hqi`6R(d@W?u0IVcvK3fw+Ea18sol2RJE}$ARQH{) z+aBxp*0eT>E(4J@*k1G(QDmbylBd z*J+D}2sY)Vf_Y_{m1A~kc?k!OTMtXD4pc#1(~@<-iU=viV(z@p&yf`HCL7nt-UCg; ztvoZJqUQ&F6)Sj75dSCr=?1b#=?RW&U^=8uq&Z4&HDlE1=!QJjJG-X;DWu79Gjv~D zeh;=iG6y!t7-8ZOfjc+lW_RY96~pZ;(6`Fvc4_JHf4nke6%NJ5@P;-~$3oH>?_W=H zHhC-q0V+L08WV5kF1n^Q^T?x^09pPUe0@N#UZ$M)+J z0fS7Xwm+sP*H$}uwb7YvTO;PUR7WH&PW2_(l}so|skl)r+dW*p5KYkM{WzcG z+KiQHbKA@IDTnDJwX{Nzt2d|D!u8$mYrHJW*MVNu6-XH%b7#SmhW&e-0S5DFnq+9| z=#I1C!9gRR-CDJ?WfRY-@gt6EgHGt_O{nkmG@Yq%|EIAG_q>|C=WT7ankGO|-^wAi z*h8zX0}(|Rn$>FL%^m9FIy3NyRHVTg;7HW(M5oO^3=0|k6t&$u>XZO6#pOv=Oz>nS zWX-te;Aa@Ehy?yHP&LMo9gz(gc3_pYV(`q%c#67JFG#H9)e9~CG2fc1;I33zSQjf_ z>}tVjNzP0@vQP?A zdBgKAZ@`F|w-I1^icZxa)s%lH?EKRVFL!QXx$~6p25HpH@#-D*R`Xat=lznzRX%&h zkkQt>o4iiD$LNCCodY&wM$3#t3;!2iA%jP|)|7YPqfc@f(YsJ7pFM0+VV@VJ8unTW zJ-`c2^Jz_$n3_8f{-O54@OtAc8M${)dAdS8JI<`Gxqdc#28`9&z`w6vqRFS0tPRmQ z^~#xT_+gpXwwo5S7T|RvfeGFzw}*_Hc^2+SpP2wwR+10C^JIXPLY(w&A=E{vju**> zmMsE5YZpa*_a7jfFUW4mM}$?@68OHaMksElhCeSdc|7l9^a1Qk-a%TmiB8;E-43QZ zdYq1~u6lmdwR8h7)4@_l&H^W?r+nTsZuE}0O2auysS26l_BfeO=XtZqk!?$>`};WG z*qYc`SXJ;WfNAv4DK3wm$SV{_qIcFm!}=AY*kKg#J#}`>E!Ld-AyE>y&oDbZA^9I1 z4}!|hOD=^bMs`B^oH zFlMJylU#x z-QnuCf3BAku0=L^Xh)uYS1~}EmRQV7mu2wPaZ-X9=lg(tvR5g>vzH7toTmaFuRR;( zlr`@D(TF$xNjpdOF6(iTg~Yxi$a3Z~ubq=Z-;R~h8n=EshaBT5T@M;0pCp8{Pw!Sp{q7qYV!Gc)7)b|NC-J#f@* zX=f>+r`IN9($aT3=-ZF&2^dj6YdWmoyyf(QxC3Y)1gGU;OJC`-kAd7r8g(AZHyD8hj$@S`bm=qii{Hfg|r_CGQkhbI-cIcClU$tbf2gzmt2byseex=BCqCKO5rhPXutV^kSe%G zJ253irC`eBFh!h9| zF%T&QX^EPv-8Z`%R+)Munxa!yJMQ&q{Pr2f(3P|$-XV8Q97>q#hE13ZOmOpwlrprq zzH-z+)fdS8ewIg1ZKSo|0M|gxXZd7@NjiE{7YnEm$ zRpL-Z=6bEbvB?yXx5qP-%sPjGI0I_6Xn@t=uJ*(At&NDS8Pg^Kfo?AL%PjVcVcb{A zKvb_%U+I<+!_BIf1sx8Vuf!FQ(fNYA=F=3kb??jo0Q&vRoSCnZh+Wh&XN&8km)eNn zz8YTgwG;2sBBxVEv#t6w25URm5V5#I--18;Z6UbmKEEHA0364HJoQz+^2li#D=GeN zZgq`KPe1!=-9U(y`bU1Oxd|YHVdvL5hcH2sl&n?pBCLchj8^d3x=1MXlYX1-JoOxn zE(;(hB?HF`4ekVYQ7$ z7ISkV=BL-8%N#lTGojv3Jtxo!c82{ZPFMp~WulW9PLl}^4yHOWMwE(9vT%2P$&I~^ z{0dF__TqIk$@G^*$5&RT#4n;YYf-<+uVc8)QOn}QIK-Wdl58IYwX`Eu6G-se>x+A6 z(o>n>aFkGJD457Z5mx)lXcBUZJ{CpxE_%|5?3-slk^|5*sAPj}QrBCjvuRs0dM}X0 z2QfFiaJMLHb5$kmUJPv*i3)t*`Bl|`kCN73+(S^%l>C|v_V$IcMZ(0B>PqpR_G{Q# zC8ervMt+OghA4H{3|0B-8)DkaSU$XvX15FC=%`i&P^{P^}VD*VDorYRFNc^bjp@CG)(o@P(vxkKVDv-D<~ z93MXb`r!LrJs12O6|#YDu13hD!rhcVd`r69cfXk z@*ltze6vHvo4UCVk4bMO!uc$@9rp+)%98eufw;-)l&qhE*d32y!v{rmx1rcLbvSM# zdcCd;iRPPCMie!yeG#pnrm}6CdCg^8ZuCcRPrtFV%rAqbLq8$vM^mzKX?+z?O{92L zW3L8JaWW4N%FkN_#+@Mc5{{f49}dx1w#Uj8-b-12)V6>Ka6YO=x;|pdgP-JhWyi{bd~~ zFTJ(TS9cYgddbqB&3dxLE@5drIaQEwc>Y}5(GMi(Kb7QjK^$(Agqsm;LzT%M7t8Xz zz_KZY4W_n?nZJD3{{hI1o zU-L`)>4UuTG3*_q=W9J1JE#ILbWR1Xe-gB?fXs}2H`1E6-kQKvQKy0w4Eg@P7b3rB&R1#X=4#Tm`K-xaT;X3c6GW4c?{7WVx0G@Tw~Rhk!KfjNz@00 zfCn&;=Oi{II^7l)D#i42$Q=jVjqA%&WK5U^b=AAf>`T;YwW>^c@_U6V%2Es;#y+Nv z1!Xf;kJ$AW&(NSfYpu~SjLKB zUCLWVn$~$G-}$Q*zq?<(`<$vG4YtbpRBHdQsN4{4Vp6caQHMOH6BIHV-EC71vaA-M zQpI`6Ha}ZsaLB}zf>Qe-iZ7hT?$J8r%=m?lgz&&u4b2xhEu?6REI+jSaF_7Qp-(&2|cjDIDNsa3vohqRK!w9U3`Y%qfVqahc0@y2r1569mL!!oKN~jdy}d|V)ULhJwN0bA z)MlLaearpqajiML)vbSvT&>3e3FBx1d7zS)YSX-wVcd;E9R`dNRFAO#R^7)x_k?ws zPtH$_A2L|gQ***#Ii;0p0MS6{aZaI7lqi0~1i)&*V9JY#5$$x-SP=M;FKwzSDw|3_ z9fgID7xb`NvBB?QY^lj~LL<=RaUun*LsX>l)d|8;xG~*rLTvHzabV&V&%S#vgBx>v z5x?s#R7=$39#*mO{7E<1bf(h{inkEDk}wZj5>LA}nNSEeo!!U~hg>hM+|(RZK-`Er zV9n32CIqdTJ6^9pj;tQ?Is72@U&zL2yiRxTgBMS#Gp$FPI-8}7Dk;!eKcO&cZ^C|b zIOpdtCo${>&Y(({*QLWY%n-g=PRddT) z8B19(O@ercjq8EMgdc@EM<=Ep4^O!Jb`Xo`iML1lyQyUe8mMT6wyu-c&B{`vM23qi zh?6j$;O7?V&`le*^nzU~606!A79F1v#YtC>x>oLgsJ;I50@%I~X;c8g>ITX=VukpuxtGMp`-c4$8CLi|p#s#sqHE)NIX}fgKLK_3uA*-_Jyv$`Z^; zNapu;>3@%H)uuU55Adq$22LaMC#jDwoV^FS_jgR z;|5ZFyv#+YPb&17nF2kF^M|k8TTXu4rrjJU=+5*}j>BfDn3vj%#&krX^C?aP_tsl_ z8T)Yh>oPOJVC1Lo-;C0})h}-fBZkTE@EZYcV>qiTS?n4?xrh4A9>@-2DSl4dlR|n(7jOs_S=2|iXN;}s!Ask(2FvK>R*CR@+PhH zg5{Q<&yqingR*vKDoJdY>`wr?v;?dA^vVLD8XE}LV(t3@EL2plHE^g{P6~IZj4}aC z6A$v>;;kjyetrjm{j%&@Zh3AfAq<7{K{eM{1bb$KZk;y&N} z!^45LL$m9oD_23@bZ}m#I?uw1x~I?Srcr(S5OW`rs3cU8SG&d1mN+WC%nzTvbK`}I!Q?cPSrH3adk;@jxXjU1{j=jBWS z^^2l4TZBa{07bGMp;zuIU|M=kSMBVyH4dUL*d)y4+{X%S)`RIh>`#*nL zj&ZD;IpqrQby>Pxq^K zl^Lk0H#r1LLy5n!b>{amDcb{2T#_wH^susGfBvdwaiVxtib>rz3;V!uxSoqwt85SJ zl70tcfQsgLiTNrCQ7K90wdWD9uX7OM?-Lza1w74N)UY#!*aj4&$QR2m4XtQ4G7;{_ zg-N3Ithodc(1dim{lJtmXU}Lqu-UL$#8&7Zn2E1L{^8eD+kfC$oCeAw!9~m3her>@ zJWBH>6AQ~j;ru0`Rz3%;Ks7KQ^n0}{k0zZ0e{s?Lwd(wH5G^WCRu6ts&sH)BN-RJc zHNug_b=Ha)VutyJoFrf=NjrK!EYAOQU>|xL&Ffv{VXU$TPeZmyr8AkD#eG^1c8nu< zRnyncvO ziQ_3^y?vqZR@P?GEDfX0&_{%44r%=25Ze>hBso%4`bIf1OKp#&KHB@7gQDpK#6Iha z#LM5F4pG%k2UX;KNbf6Xx3C`ezH|6F_1sd2Tn?vMb&`6`pb>YTP@&HffR}7OeRqO+p1v*RK5e|C zkUD%%pqoiL(|)_43GqMKAmAvxbHcJSNW0Rav&#krIKuMDFZGcI>g~co5g{38sNY>6 zF-FhLxk(Bgj@=wT#bO)Ts`|Cu8ksiXDdtC<9Q)%sI&P4T96QqUPtU-d)`(1Hbr#EM z(cM)I)9CATE=i^2O-p=`oZku$#6Ho?ICt))DfvH6u9V7*eX42d<>644hY(B3qkN3lNGj;R1M~H%LA1fho8HKv~BYD z_A)|=bgK-1lyNg1np10=z$5mziW0qVj=og-OtD&$O1R`AC6~K(r8RLOpF0M%O{O^$49HN*ZHkdKxP5jVQaC6(A$bICVEIQ`B>M~A*10<%|7EQkk@^o{Tmh4w zI$IY%lp6N%Wj@-xc1G88uO8Nxc9RuOvm5JG1_kDuRJqpnJgA_3P*zs!hLj)tiLnQ9ztt|2v7*ddQ=j93xRaYb{uWbJ-0bItsidh zmjyD0;1nVu^jFd4K?x;HPUfSv5!V=vNisd>BE+Fw8=@8=gDDH&8Asrioun2EADc)3 zm-#g0Bthcs*)U(r%}#pM_?|v{a?SP_mY;K-vfVjh zI~C%~C9NT$Zoet;$GU6jOWd4EV!Y?w76M80^Jfd!S_7cEBT{SAZ|sKOM$I8cQ_C5% znvU4T$24=E2IDYFf0d7xN+>XPn#T6xB*eCucDUQ&Iejr{MEWZJg@VM}#Xh}U0wND7 zoPeJ{4SV038!ik#4b$KC=FGj(494?kSh|lfmJh4Dmhl9t`Y?u`Z>mcbm_-zy+ZHfeO*$DEp@4oFBMpX13F_AUI3HPLhTIngr{ zLb2Z4(F~k|$z~QQpp}iB0yPZ1r!71RnPB&oq?;f47>V?arT}ziQemF8U(A_NG1TU` zbsA=qOEx(yoVOm1g2BB4d^oN@py#P>|Jpi=i-hfHswYT&_EyXp@!0nu!8Wc*v9Mly zQ-*S+E@{_d$cBV58yID?1iA=lB1hqX@rT$L%de+$`M>zE(e;LxNiUn}Rt%ArRm)dP zxLYh}doMe(S?Vn^wdDath+^G!qOy-{DhJAb5sXqg>%nrg(Z#v_)m8ns8zRPGW4{Le z*Y?&i!pG7ZL?A)HN&dEF-J)XFsh5?)wmwlvQS{f$WgfR{mpS>(mN;)3Y)Y#3bow(( zZnLd)&$k%}S_H-)%d+A{#$9D1W5l+U_ML)@IT>wXmSYi4f+~yUpx(^P$GkDGcTRFd zH=f7pFHt#hKI%fKV5@@7hiW76+{1t%aXC51Zgjz91x?18a%!Fvs9uRB2jf-GN;oJ| z45*zQ-BB-?LAo}F)VMu3{`1Snue-Q9WT0eM8z&+{X+QP&R$(I%>yJxwHWkxOQ(InI zZlHo0DTzbvIVCEes7cENspHa9`cEU3wB+yRr)OP;VXPa=?|=`_B94azQgay&)L>f> z_6^Q&)dKA=?%3vyJ5#H{nA%m)ZoQ)xP0*c!_M~-%Ms!Fg*Sj6{Z zy92TF^0~$};Ht&WnLpX8De>ye)5li(^Tru?$^5rK$-{zXjd65Jf4~IL&qzD!%u!X) ztbK%gWk_6Jo1ATjbV4l+Xu^37az#=8Ga+ETUSwN+o#X&vVP#N{fv}jPCR^G*$9)x{*5ra0Pj?`a{h|d zPjM{Jf51qC-6YKl1S8nunSlmme+IE?Pclr!@lUz z?eFbd@DV;-RY8qu?5flxexqzuM$El2FfzviEb?#n!@I&j*WMi@zXY8m(?RVzQBTr@ zVgk8%=%c>qd$obQke&zHw*yoQpP?h5Pvo+8x7p%jx&0r~x z4ExH0`X>C2wK%j%zAhyc-fEV5asf;;nc5-wmLPu&W^P}_M|gE8?h@q!NMc>-+EK*o zfd`XL1s9t;I2fR(bb+J_jbS^97LKn3Sp&ug5RI5xrkbmPOJ>VcKq4 zWz4as?J*WA!meb5&SV`hSzhpDuBGjQp1##@MG}Ig?uFfM`5#$+5 zA7<8&<#zSZjz!O&g&K|wh29^6%z{>SL-YpWF-=1Vi0~Iyn`R2Ib+<8VOjXhjS_T*a zlV(kC!{ZC6H`3rINH&FEtTJ>MezkyZe;CIk-Tb{Y0sr~`1@`*) z>cwBw{z�$^SdG{~-ClQ2Qh5|1WBPMEy6(zhwIlYJWuii{xKGw*R2^hwfhj{w3Rg zQ2RsoFOvV8I{(7}{8$X6@mmqy18K6Y93o z=fCWS=HFPW$vXa_NuGQQ6_}@{+^YEilZ*g%sOU zZy|XhP=&XJ!`vg_lz^>j-=%N?O77Qkit4wU6t-qJj62-DcEp@8@N|((dT-uicHjTN z>DTelV0JAayWQRa`9gbjlXazVU(UDVzWS2B6q>NB=L*B{gQ`$nX*@pm3yGgR&1XYk zt+fgnRR1MG#u~Jhm+67BO1{AmSLKEg7T4Dxo^}kQ^;&or7>l8{zSqa;L*R@?fJU)y zy>H^;1RsiY0qnrGVo-#M8=HP92$JjpD26~e|HqY(k*hc z+!^_Wv+m-+^g4o=ha^3(b3-8EF$>bi~nJESPqT>Ot!fOp&l zhRqA1@#$NjPt&I^iw#e$mCsgDz}G!pj6Sa4>=s>`TEI(@(-kLo#UWhLP?Q}*ymi}7=jDU@k^Ar* zP7kgKa318|?QTWOs-t8JZw%k{;mEIy8*|$)(#WHi$57)Fm*Q^efPU+2c*i~MOaFUT zoHlW44?DsEisy35v)_p0t{}wsg*J?jv%GSw?yrOsjFP#9m0Kny7M^VVi9#>ndp0gf zDWGkPJp!)vQg%x8);X@Xa69;I&hXf$w%k;G(R;tTRXJX^`McfI#eBr|$SWd;$dBNn zcAMV1a{aRO4`wQuCxSb zPRfGY_T{rmX}GYHr;>^$Rz*1f7SvuR%A!!g;$R!(^yDb=IDDAg*WkaP{5f+qG&LrhD+=d&v;=VM`E5q*>_KlxCS#JSH; zGHWEMS#OQ_DyV1^!>j}fByTu3T8Wcy3NszKVjcF*@)y#KiBk?j@7caq`!4t;rmPVB z4I)U^SIJ9&T&uhW$sGF@xEb+!^3x|U179I}%-!@C^{)-h@p9hgS%Ci@QcteV>oyGQ ziYeUqBmM`Z1M5t&+n3uS@~Pl2eU2|(gYX9g3Ctat%Ovfh+96ie3LH6I#pBzak87PR zeA%SIqfE5#ve*Bg#ecguw{#ag$^2_hKbZa6|G4%>?Tw7T^-L3Q z|E&6Ry|&!<_P>kUCFIgyZ7_QCZ_DF3%Gn!!Cn?uVmiln~fKhkuYGt{E{u^e3_byEi zHJa1;cVB0n#&+%3Q&Usr-xv2kn0|-j{N~d2bJgJfsNb(Se-oml_@A0Am+A_Qah232 zgH*03_0Q{?XQ`xeReu2tePL;2F`sGYaU(cJfyLCicR9p1wc=JWs9=#+CK5qyhpXB5~^>#`1auj&B?V@$*nSx-^vc)s;eTdN#Z4aqCale600K`}KbLh*2~7Y^(fD!z literal 114396 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

{+-Eca$*Qy;nOTb(a1O&t%GUjt{-)NZJ5%gmA; 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 literal 177965 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

)|v~87scqi*gsyWd-|? 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Ν2-!vig0b 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 From 1cc336218b669fdebc144348824c9eaa7eb7af53 Mon Sep 17 00:00:00 2001 From: xichen Date: Wed, 1 Feb 2017 15:56:00 -0800 Subject: [PATCH 135/370] add image size control --- doc/howto/usage/k8s/k8s_aws_en.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/howto/usage/k8s/k8s_aws_en.md b/doc/howto/usage/k8s/k8s_aws_en.md index eda2b639e2f5d9..8d88e9d1cd6097 100644 --- a/doc/howto/usage/k8s/k8s_aws_en.md +++ b/doc/howto/usage/k8s/k8s_aws_en.md @@ -384,14 +384,14 @@ Edit `/etc/hosts` to associate above ip with the DNS name. - Domain name: "paddle" - Type: "Private hosted zone for amazon VPC" - VPC ID: `` - -

![route53 zone setting](src/route53_create_zone.png)
+ -
![route53 zone setting](src/route53_create_zone.png =400x)
- Add A record - Click on the zone "paddle" just created - Click the button "Create record set" - Name : leave blank - type: "A" - Value: `` - -
![route53 create recordset](src/route53_create_recordset.png)
+ -
![route53 create recordset](src/route53_create_recordset.png =400x)
- Verify name service - Connect to any instance created by kube-aws via ssh - Run command "host paddle", see if the ip returned is the private ip of kube-controller From e81d557e36182d1e04174ebf718422d8435f192b Mon Sep 17 00:00:00 2001 From: xichen Date: Wed, 1 Feb 2017 16:22:14 -0800 Subject: [PATCH 136/370] visual tweaks for route53 config --- doc/howto/usage/k8s/k8s_aws_en.md | 6 ++++-- .../usage/k8s/src/route53_create_zone.png | Bin 60518 -> 52035 bytes 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/howto/usage/k8s/k8s_aws_en.md b/doc/howto/usage/k8s/k8s_aws_en.md index 8d88e9d1cd6097..ce72b0803818d5 100644 --- a/doc/howto/usage/k8s/k8s_aws_en.md +++ b/doc/howto/usage/k8s/k8s_aws_en.md @@ -384,14 +384,16 @@ Edit `/etc/hosts` to associate above ip with the DNS name. - Domain name: "paddle" - Type: "Private hosted zone for amazon VPC" - VPC ID: `` - -
![route53 zone setting](src/route53_create_zone.png =400x)
+ + ![route53 zone setting](src/route53_create_zone.png) - Add A record - Click on the zone "paddle" just created - Click the button "Create record set" - Name : leave blank - type: "A" - Value: `` - -
![route53 create recordset](src/route53_create_recordset.png =400x)
+ + ![route53 create recordset](src/route53_create_recordset.png) - Verify name service - Connect to any instance created by kube-aws via ssh - Run command "host paddle", see if the ip returned is the private ip of kube-controller diff --git a/doc/howto/usage/k8s/src/route53_create_zone.png b/doc/howto/usage/k8s/src/route53_create_zone.png index b8162da4426b38241222323fa4a51b98f820888d..25b7ddb831c5cba97f4b2edddd27da3234d621af 100644 GIT binary patch literal 52035 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
  • 5` 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
    )>Gs+^~o~fr(AlBct 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

    NAYRpF+djrl{|qS*tfI?EFo>bI`xnvJ^u0P8SL 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ⅅgVsMhu0jxm2H&>c_{yY&|HP=wM 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

    hb2 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

  • 5` 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 z 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 z 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 EXO=7cY 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 From ca367a80e3eb019aa5290055552228f844ade130 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Wed, 1 Mar 2017 10:58:22 +0800 Subject: [PATCH 360/370] follow comments --- python/paddle/v2/topology.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index 6329915350bbb4..e2709e39de9d9d 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -74,12 +74,10 @@ def find_data_layer(layer): if isinstance(layer, v2_layer.DataLayerV2): data_layers[layer.name] = layer if not isinstance(layer, collections.Sequence): - for parent_layer in layer.__parent_layers__.values(): + layer = [layer] + for each_l in layer: + for parent_layer in each_l.__parent_layers__.values(): find_data_layer(parent_layer) - else: - for each_l in layer: - for parent_layer in each_l.__parent_layers__.values(): - find_data_layer(parent_layer) for layer in self.layers: find_data_layer(layer) @@ -93,8 +91,8 @@ def data_type(self): """ data_types_lists = [] + data_layers = self.data_layers() for each in self.__model_config__.input_layer_names: - data_layers = self.data_layers() data_types_lists.append((each, data_layers[each].type)) return data_types_lists From ca6fc145e3c6ec1d2a4dd3648f9564e48e311e7a Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Wed, 1 Mar 2017 12:19:52 +0800 Subject: [PATCH 361/370] add some comments --- paddle/py_paddle/dataprovider_converter.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/paddle/py_paddle/dataprovider_converter.py b/paddle/py_paddle/dataprovider_converter.py index 60a0f2c0444863..57e58e077d7fbe 100644 --- a/paddle/py_paddle/dataprovider_converter.py +++ b/paddle/py_paddle/dataprovider_converter.py @@ -26,7 +26,14 @@ def __init__(self, input_type, pos): if not isinstance(self.input_type, dp2.InputType): raise ValueError("input type should be dataprovider2.InputType") self.pos = pos - self.use_gpu = True if swig_paddle.isUsingGpu() and ( + # data_in_gpu is used to indicate whether to create argument on GPU + # or not in GPU mode. Now if using one thread (trainer_count=1), + # trainer uses NeuralNetwork which needs to create argument on GPU + # before calling forward function. So, set data_in_gpu to True. + # Otherwise, trainer uses MultiGradientMachine which will transfer + # data from CPU to GPU in the forward function, set data_in_gpu to + # False in this case. + self.data_in_gpu = True if swig_paddle.isUsingGpu() and ( swig_paddle.getTrainerCount() == 1) else False def scan(self, dat): From 566e5f1fcbe77e2e2f931e977064fcb878d4908b Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Wed, 1 Mar 2017 13:25:51 +0800 Subject: [PATCH 362/370] rename use_gpu to data_in_gpu --- paddle/py_paddle/dataprovider_converter.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/paddle/py_paddle/dataprovider_converter.py b/paddle/py_paddle/dataprovider_converter.py index 57e58e077d7fbe..c009b05cdeeb9d 100644 --- a/paddle/py_paddle/dataprovider_converter.py +++ b/paddle/py_paddle/dataprovider_converter.py @@ -33,8 +33,8 @@ def __init__(self, input_type, pos): # Otherwise, trainer uses MultiGradientMachine which will transfer # data from CPU to GPU in the forward function, set data_in_gpu to # False in this case. - self.data_in_gpu = True if swig_paddle.isUsingGpu() and ( - swig_paddle.getTrainerCount() == 1) else False + self.data_in_gpu = swig_paddle.isUsingGpu( + ) and swig_paddle.getTrainerCount() == 1 def scan(self, dat): pass @@ -63,7 +63,7 @@ def finish_scan(self, argument): if self.__mat__.dtype != numpy.float32: self.__mat__ = self.__mat__.astype(numpy.float32) m = swig_paddle.Matrix.createDenseFromNumpy(self.__mat__, True, - self.use_gpu) + self.data_in_gpu) argument.setSlotValue(self.pos, m) @@ -115,7 +115,7 @@ def scan(self, dat): self.__ids__.append(dat) def finish_scan(self, argument): - ids = swig_paddle.IVector.create(self.__ids__, self.use_gpu) + ids = swig_paddle.IVector.create(self.__ids__, self.data_in_gpu) assert isinstance(argument, swig_paddle.Arguments) argument.setSlotIds(self.pos, ids) From 4fa6e8e5cb1993a5c9b96bc42d90c0b5d56e6dd2 Mon Sep 17 00:00:00 2001 From: "yi.wu" Date: Wed, 1 Mar 2017 13:43:23 +0800 Subject: [PATCH 363/370] Refine doc fix link error --- doc/howto/usage/k8s/k8s_distributed_cn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/howto/usage/k8s/k8s_distributed_cn.md b/doc/howto/usage/k8s/k8s_distributed_cn.md index 3a47a3832fee82..4027f804a639e0 100644 --- a/doc/howto/usage/k8s/k8s_distributed_cn.md +++ b/doc/howto/usage/k8s/k8s_distributed_cn.md @@ -2,7 +2,7 @@ 前一篇文章介绍了如何在Kubernetes集群上启动一个单机PaddlePaddle训练作业 (Job)。在这篇文章里,我们介绍如何在Kubernetes集群上进行分布式PaddlePaddle训练作业。关于PaddlePaddle的分布式训练,文章 [Cluster Training](https://github.com/baidu/Paddle/blob/develop/doc/cluster/opensource/cluster_train.md)介绍了一种通过SSH远程分发任务,进行分布式训练的方法,与此不同的是,本文将介绍在Kubernetes容器管理平台上快速构建PaddlePaddle容器集群,进行分布式训练的方案。 -有关Kubernetes相关概念以及如何搭建和配置Kubernetes集群,可以参考[k8s_basis](./k8s_basis.md)。 +有关Kubernetes相关概念以及如何搭建和配置Kubernetes集群,可以参考[k8s_basis](./k8s_basis_cn.md)。 ## 整体方案 From 6dd21658dc96ac46c22c2287a21cd78c1f616667 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 1 Mar 2017 14:07:04 +0800 Subject: [PATCH 364/370] Add config_base.py for Layer --- python/paddle/v2/config_base.py | 72 ++++++++++++++++++++++++++++++++ python/paddle/v2/layer.py | 73 +-------------------------------- 2 files changed, 73 insertions(+), 72 deletions(-) create mode 100644 python/paddle/v2/config_base.py diff --git a/python/paddle/v2/config_base.py b/python/paddle/v2/config_base.py new file mode 100644 index 00000000000000..c733f4866dca0a --- /dev/null +++ b/python/paddle/v2/config_base.py @@ -0,0 +1,72 @@ +import collections + +from paddle.trainer_config_helpers.default_decorators import wrap_name_default +import paddle.trainer_config_helpers as conf_helps + + +class Layer(object): + def __init__(self, name=None, parent_layers=None): + assert isinstance(parent_layers, dict) + self.name = name + self.__parent_layers__ = parent_layers + + def to_proto(self, context): + """ + function to set proto attribute + """ + kwargs = dict() + for layer_name in self.__parent_layers__: + if not isinstance(self.__parent_layers__[layer_name], + collections.Sequence): + v1_layer = self.__parent_layers__[layer_name].to_proto( + context=context) + else: + v1_layer = map(lambda x: x.to_proto(context=context), + self.__parent_layers__[layer_name]) + kwargs[layer_name] = v1_layer + + if self.name is None: + return self.to_proto_impl(**kwargs) + elif self.name not in context: + context[self.name] = self.to_proto_impl(**kwargs) + + return context[self.name] + + def to_proto_impl(self, **kwargs): + raise NotImplementedError() + + +def __convert_to_v2__(method_name, parent_names, is_default_name=True): + if is_default_name: + wrapper = wrap_name_default(name_prefix=method_name) + else: + wrapper = None + + class V2LayerImpl(Layer): + def __init__(self, **kwargs): + parent_layers = dict() + other_kwargs = dict() + for pname in parent_names: + if kwargs.has_key(pname): + parent_layers[pname] = kwargs[pname] + + for key in kwargs.keys(): + if key not in parent_names: + other_kwargs[key] = kwargs[key] + + name = kwargs.get('name', None) + super(V2LayerImpl, self).__init__(name, parent_layers) + self.__other_kwargs__ = other_kwargs + + if wrapper is not None: + __init__ = wrapper(__init__) + + def to_proto_impl(self, **kwargs): + args = dict() + for each in kwargs: + args[each] = kwargs[each] + for each in self.__other_kwargs__: + args[each] = self.__other_kwargs__[each] + return getattr(conf_helps, method_name)(**args) + + return V2LayerImpl diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 19f3c2f998d83c..67111f1315fbb0 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -65,10 +65,7 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. Also, the creation of a protobuf message is hidden in the invocation of paddle.v2.parameters.create, no longer exposed to users. """ - -import collections -import inspect - +from config_base import Layer, __convert_to_v2__ import paddle.trainer_config_helpers as conf_helps from paddle.trainer_config_helpers.config_parser_utils import \ parse_network_config as __parse__ @@ -107,74 +104,6 @@ def __real_func__(): return __parse__(__real_func__) -class Layer(object): - def __init__(self, name=None, parent_layers=None): - assert isinstance(parent_layers, dict) - self.name = name - self.__parent_layers__ = parent_layers - - def to_proto(self, context): - """ - function to set proto attribute - """ - kwargs = dict() - for layer_name in self.__parent_layers__: - if not isinstance(self.__parent_layers__[layer_name], - collections.Sequence): - v1_layer = self.__parent_layers__[layer_name].to_proto( - context=context) - else: - v1_layer = map(lambda x: x.to_proto(context=context), - self.__parent_layers__[layer_name]) - kwargs[layer_name] = v1_layer - - if self.name is None: - return self.to_proto_impl(**kwargs) - elif self.name not in context: - context[self.name] = self.to_proto_impl(**kwargs) - - return context[self.name] - - def to_proto_impl(self, **kwargs): - raise NotImplementedError() - - -def __convert_to_v2__(method_name, parent_names, is_default_name=True): - if is_default_name: - wrapper = wrap_name_default(name_prefix=method_name) - else: - wrapper = None - - class V2LayerImpl(Layer): - def __init__(self, **kwargs): - parent_layers = dict() - other_kwargs = dict() - for pname in parent_names: - if kwargs.has_key(pname): - parent_layers[pname] = kwargs[pname] - - for key in kwargs.keys(): - if key not in parent_names: - other_kwargs[key] = kwargs[key] - - name = kwargs.get('name', None) - super(V2LayerImpl, self).__init__(name, parent_layers) - self.__other_kwargs__ = other_kwargs - - if wrapper is not None: - __init__ = wrapper(__init__) - - def to_proto_impl(self, **kwargs): - args = dict() - for each in kwargs: - args[each] = kwargs[each] - for each in self.__other_kwargs__: - args[each] = self.__other_kwargs__[each] - return getattr(conf_helps, method_name)(**args) - - return V2LayerImpl - - """ Some layer may need some special config, and can not use __convert_to_v2__ to convert. So we also need to implement some special LayerV2. From 057d0cbd6ebb8fdd97f324c58deaf7b9cdf11c61 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 1 Mar 2017 14:19:35 +0800 Subject: [PATCH 365/370] Complete networks. --- python/paddle/v2/__init__.py | 3 ++- python/paddle/v2/config_base.py | 14 ++++++++++ python/paddle/v2/networks.py | 45 +++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 python/paddle/v2/networks.py diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index b31efe170dbf11..f055c845c7c42b 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -24,12 +24,13 @@ from . import reader import attr import pooling +import networks import py_paddle.swig_paddle as api __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', 'event', 'data_type', 'attr', 'pooling', 'data_feeder', 'dataset', 'reader', - 'topology' + 'topology', 'networks' ] diff --git a/python/paddle/v2/config_base.py b/python/paddle/v2/config_base.py index c733f4866dca0a..035f96b0f2e978 100644 --- a/python/paddle/v2/config_base.py +++ b/python/paddle/v2/config_base.py @@ -1,3 +1,17 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + import collections from paddle.trainer_config_helpers.default_decorators import wrap_name_default diff --git a/python/paddle/v2/networks.py b/python/paddle/v2/networks.py new file mode 100644 index 00000000000000..74d91593d8551b --- /dev/null +++ b/python/paddle/v2/networks.py @@ -0,0 +1,45 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + +import paddle.trainer_config_helpers.networks as conf_nw +import inspect +from config_base import __convert_to_v2__ + +__all__ = [] + + +def __initialize__(): + for each_subnetwork in conf_nw.__all__: + if each_subnetwork in ['inputs', 'outputs']: + continue + func = getattr(conf_nw, each_subnetwork) + if hasattr(func, 'argspec'): + argspec = func.argspec + else: + argspec = inspect.getargspec(func) + if each_subnetwork == 'simple_attention': + parents = ['encoded_sequence', 'encoded_proj', 'decoder_state'] + else: + parents = filter(lambda x: x.startswith('input'), argspec.args) + assert len(parents) != 0, each_subnetwork + v2_subnet = __convert_to_v2__( + each_subnetwork, + parent_names=parents, + is_default_name='name' in argspec.args) + globals()[each_subnetwork] = v2_subnet + global __all__ + __all__.append(each_subnetwork) + + +__initialize__() From 3590cb1e4d32fdba7505d0f6a98aacf999927314 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 1 Mar 2017 14:23:25 +0800 Subject: [PATCH 366/370] Add unittests --- python/paddle/v2/tests/test_layer.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/python/paddle/v2/tests/test_layer.py b/python/paddle/v2/tests/test_layer.py index b138ddbbe6c0a4..0055679a91801a 100644 --- a/python/paddle/v2/tests/test_layer.py +++ b/python/paddle/v2/tests/test_layer.py @@ -18,6 +18,7 @@ import paddle.v2.data_type as data_type import paddle.v2.layer as layer import paddle.v2.pooling as pooling +import paddle.v2.networks as networks pixel = layer.data(name='pixel', type=data_type.dense_vector(128)) label = layer.data(name='label', type=data_type.integer_value(10)) @@ -251,5 +252,13 @@ def test_operator(self): print layer.parse_network(conv1) +class NetworkTests(unittest.TestCase): + def test_vgg(self): + img = layer.data(name='pixel', type=data_type.dense_vector(784)) + vgg_out = networks.small_vgg( + input_image=img, num_channels=1, num_classes=2) + print layer.parse_network(vgg_out) + + if __name__ == '__main__': unittest.main() From 91d818866a650ebaec266805b56c55f76c618de9 Mon Sep 17 00:00:00 2001 From: "yi.wu" Date: Wed, 1 Mar 2017 14:48:43 +0800 Subject: [PATCH 367/370] Refine k8s doc change title --- doc/howto/usage/k8s/k8s_distributed_cn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/howto/usage/k8s/k8s_distributed_cn.md b/doc/howto/usage/k8s/k8s_distributed_cn.md index 4027f804a639e0..7213a977b8a2a4 100644 --- a/doc/howto/usage/k8s/k8s_distributed_cn.md +++ b/doc/howto/usage/k8s/k8s_distributed_cn.md @@ -1,4 +1,4 @@ -# 使用Paddle在Kubernetes集群上完成分布式训练 +# Kubernetes分布式训练 前一篇文章介绍了如何在Kubernetes集群上启动一个单机PaddlePaddle训练作业 (Job)。在这篇文章里,我们介绍如何在Kubernetes集群上进行分布式PaddlePaddle训练作业。关于PaddlePaddle的分布式训练,文章 [Cluster Training](https://github.com/baidu/Paddle/blob/develop/doc/cluster/opensource/cluster_train.md)介绍了一种通过SSH远程分发任务,进行分布式训练的方法,与此不同的是,本文将介绍在Kubernetes容器管理平台上快速构建PaddlePaddle容器集群,进行分布式训练的方案。 From 4c24ac1a9952349c0965d5c50a07878ec2632e17 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 1 Mar 2017 14:50:55 +0800 Subject: [PATCH 368/370] Init inferencer. --- python/paddle/v2/__init__.py | 6 +++- python/paddle/v2/inferencer.py | 54 ++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 python/paddle/v2/inferencer.py diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index b31efe170dbf11..cc8f33f9800391 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -24,12 +24,13 @@ from . import reader import attr import pooling +import inferencer import py_paddle.swig_paddle as api __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', 'event', 'data_type', 'attr', 'pooling', 'data_feeder', 'dataset', 'reader', - 'topology' + 'topology', 'inferencer', 'infer' ] @@ -39,3 +40,6 @@ def init(**kwargs): args.append('--%s=%s' % (key, str(kwargs[key]))) api.initPaddle(*args) + + +infer = inferencer.infer diff --git a/python/paddle/v2/inferencer.py b/python/paddle/v2/inferencer.py new file mode 100644 index 00000000000000..36a8ee37114e20 --- /dev/null +++ b/python/paddle/v2/inferencer.py @@ -0,0 +1,54 @@ +import py_paddle.swig_paddle as api + +import topology +from data_feeder import DataFeeder +import itertools +import numpy + +__all__ = ['InferenceEngine', 'infer'] + + +class InferenceEngine(object): + def __init__(self, output, parameters): + topo = topology.Topology(output) + gm = api.GradientMachine.createFromConfigProto( + topo.proto(), api.CREATE_MODE_TESTING, [api.PARAMETER_VALUE]) + for param in gm.getParameters(): + val = param.getBuf(api.PARAMETER_VALUE) + name = param.getName() + assert isinstance(val, api.Matrix) + val.copyFromNumpyMat(parameters.get(name)) + self.__gradient_machine__ = gm + self.__data_types__ = topo.data_type() + + def iter_infer(self, reader, reader_dict=None): + feeder = DataFeeder(self.__data_types__, reader_dict) + out_args = api.Arguments.createArguments(0) + self.__gradient_machine__.start() + for data_batch in reader(): + yield self.__gradient_machine__.forwardTest( + feeder(data_batch), out_args, api.PASS_TEST) + self.__gradient_machine__.finish() + + def iter_infer_field(self, field, **kwargs): + for result in self.iter_infer(**kwargs): + yield [each_result[field] for each_result in result] + + def infer(self, field='value', **kwargs): + retv = [] + for result in itertools.izip( + self.iter_infer_field( + field=field, **kwargs)): + retv.append(numpy.concatenate(result)) + return retv + + def default_reader_dict(self): + reader_dict = dict() + for i, tp in enumerate(self.__data_types__): + reader_dict[tp[0]] = i + return reader_dict + + +def infer(output, parameters, reader, reader_dict=None, field='value'): + inferer = InferenceEngine(output=output, parameters=parameters) + return inferer.infer(field=field, reader=reader, reader_dict=reader_dict) From 9ba231d3d1c13923bb42a02a88f92bce2fc6afd1 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 1 Mar 2017 15:49:39 +0800 Subject: [PATCH 369/370] Complete inferencer. --- demo/mnist/api_train_v2.py | 13 +++++++++++++ python/paddle/v2/dataset/mnist.py | 29 ++++++++++++++-------------- python/paddle/v2/inferencer.py | 27 +++++++++++++++----------- python/paddle/v2/reader/decorator.py | 20 ++++++++++++++++--- 4 files changed, 61 insertions(+), 28 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index a59b30ccdb2edd..637596e7bc1c0a 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -44,6 +44,19 @@ def event_handler(event): batch_size=32), event_handler=event_handler) + # output is a softmax layer. It returns probabilities. + # Shape should be (100, 10) + probs = paddle.infer( + output=inference, + parameters=parameters, + reader=paddle.reader.batched( + paddle.reader.limited( + paddle.reader.map_readers(lambda item: (item[0], ), + paddle.dataset.mnist.test()), + limit=100), + batch_size=32)) + print probs.shape + if __name__ == '__main__': main() diff --git a/python/paddle/v2/dataset/mnist.py b/python/paddle/v2/dataset/mnist.py index 1512a3c3189de4..ebcdff78b317ce 100644 --- a/python/paddle/v2/dataset/mnist.py +++ b/python/paddle/v2/dataset/mnist.py @@ -35,24 +35,25 @@ def reader(): l = subprocess.Popen([zcat_cmd, label_filename], stdout=subprocess.PIPE) l.stdout.read(8) # skip some magic bytes - while True: - labels = numpy.fromfile( - l.stdout, 'ubyte', count=buffer_size).astype("int") + try: # reader could be break. + while True: + labels = numpy.fromfile( + l.stdout, 'ubyte', count=buffer_size).astype("int") - if labels.size != buffer_size: - break # numpy.fromfile returns empty slice after EOF. + if labels.size != buffer_size: + break # numpy.fromfile returns empty slice after EOF. - images = numpy.fromfile( - m.stdout, 'ubyte', count=buffer_size * 28 * 28).reshape( - (buffer_size, 28 * 28)).astype('float32') + images = numpy.fromfile( + m.stdout, 'ubyte', count=buffer_size * 28 * 28).reshape( + (buffer_size, 28 * 28)).astype('float32') - images = images / 255.0 * 2.0 - 1.0 + images = images / 255.0 * 2.0 - 1.0 - for i in xrange(buffer_size): - yield images[i, :], int(labels[i]) - - m.terminate() - l.terminate() + for i in xrange(buffer_size): + yield images[i, :], int(labels[i]) + finally: + m.terminate() + l.terminate() return reader diff --git a/python/paddle/v2/inferencer.py b/python/paddle/v2/inferencer.py index 36a8ee37114e20..33f5ad1c07c6e2 100644 --- a/python/paddle/v2/inferencer.py +++ b/python/paddle/v2/inferencer.py @@ -16,18 +16,18 @@ def __init__(self, output, parameters): for param in gm.getParameters(): val = param.getBuf(api.PARAMETER_VALUE) name = param.getName() - assert isinstance(val, api.Matrix) - val.copyFromNumpyMat(parameters.get(name)) + assert isinstance(val, api.Vector) + val.copyFromNumpyArray(parameters.get(name).flatten()) self.__gradient_machine__ = gm self.__data_types__ = topo.data_type() def iter_infer(self, reader, reader_dict=None): + if reader_dict is None: + reader_dict = self.default_reader_dict() feeder = DataFeeder(self.__data_types__, reader_dict) - out_args = api.Arguments.createArguments(0) self.__gradient_machine__.start() for data_batch in reader(): - yield self.__gradient_machine__.forwardTest( - feeder(data_batch), out_args, api.PASS_TEST) + yield self.__gradient_machine__.forwardTest(feeder(data_batch)) self.__gradient_machine__.finish() def iter_infer_field(self, field, **kwargs): @@ -35,12 +35,17 @@ def iter_infer_field(self, field, **kwargs): yield [each_result[field] for each_result in result] def infer(self, field='value', **kwargs): - retv = [] - for result in itertools.izip( - self.iter_infer_field( - field=field, **kwargs)): - retv.append(numpy.concatenate(result)) - return retv + retv = None + for result in self.iter_infer_field(field=field, **kwargs): + if retv is None: + retv = [[]] * len(result) + for i, item in enumerate(result): + retv[i].append(item) + retv = [numpy.concatenate(out) for out in retv] + if len(retv) == 1: + return retv[0] + else: + return retv def default_reader_dict(self): reader_dict = dict() diff --git a/python/paddle/v2/reader/decorator.py b/python/paddle/v2/reader/decorator.py index 5687f118ce2779..fe5acbdff59447 100644 --- a/python/paddle/v2/reader/decorator.py +++ b/python/paddle/v2/reader/decorator.py @@ -14,13 +14,13 @@ __all__ = [ 'map_readers', 'buffered', 'compose', 'chain', 'shuffle', - 'ComposeNotAligned', 'batched' + 'ComposeNotAligned', 'batched', 'limited' ] -from Queue import Queue -from threading import Thread import itertools import random +from Queue import Queue +from threading import Thread def map_readers(func, *readers): @@ -213,3 +213,17 @@ def batched_reader(): yield batch return batched_reader + + +def limited(reader, limit): + """ + Limit the max number of samples that reader could return. + """ + + def limited_reader(): + for i, item in enumerate(reader()): + if i == limit: + break + yield item + + return limited_reader From 500d8836d03287621e983f815a919d9a29749c6d Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 1 Mar 2017 18:49:13 +0800 Subject: [PATCH 370/370] Follow comments --- demo/mnist/api_train_v2.py | 4 ++-- python/paddle/v2/inferencer.py | 6 +++--- python/paddle/v2/reader/decorator.py | 13 ++++++++----- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 637596e7bc1c0a..06beb7024d1fd0 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -50,10 +50,10 @@ def event_handler(event): output=inference, parameters=parameters, reader=paddle.reader.batched( - paddle.reader.limited( + paddle.reader.firstn( paddle.reader.map_readers(lambda item: (item[0], ), paddle.dataset.mnist.test()), - limit=100), + n=100), batch_size=32)) print probs.shape diff --git a/python/paddle/v2/inferencer.py b/python/paddle/v2/inferencer.py index 33f5ad1c07c6e2..ac03b016c9b8bf 100644 --- a/python/paddle/v2/inferencer.py +++ b/python/paddle/v2/inferencer.py @@ -5,10 +5,10 @@ import itertools import numpy -__all__ = ['InferenceEngine', 'infer'] +__all__ = ['Inference', 'infer'] -class InferenceEngine(object): +class Inference(object): def __init__(self, output, parameters): topo = topology.Topology(output) gm = api.GradientMachine.createFromConfigProto( @@ -55,5 +55,5 @@ def default_reader_dict(self): def infer(output, parameters, reader, reader_dict=None, field='value'): - inferer = InferenceEngine(output=output, parameters=parameters) + inferer = Inference(output=output, parameters=parameters) return inferer.infer(field=field, reader=reader, reader_dict=reader_dict) diff --git a/python/paddle/v2/reader/decorator.py b/python/paddle/v2/reader/decorator.py index fe5acbdff59447..b7657e27764f09 100644 --- a/python/paddle/v2/reader/decorator.py +++ b/python/paddle/v2/reader/decorator.py @@ -14,7 +14,7 @@ __all__ = [ 'map_readers', 'buffered', 'compose', 'chain', 'shuffle', - 'ComposeNotAligned', 'batched', 'limited' + 'ComposeNotAligned', 'batched', 'firstn' ] import itertools @@ -215,15 +215,18 @@ def batched_reader(): return batched_reader -def limited(reader, limit): +def firstn(reader, n): """ Limit the max number of samples that reader could return. """ - def limited_reader(): + # TODO(yuyang18): Check if just drop the reader, could clean the opened + # resource or not? + + def firstn_reader(): for i, item in enumerate(reader()): - if i == limit: + if i == n: break yield item - return limited_reader + return firstn_reader

  • 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 z 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 z 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 EXO=7cY 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 literal 22084 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�gYl^6l-ltkTlmdD|aM=)lE&m0c9Ljcj^BL7lC-z2L>3r2HR0o`S5yv$fIU z(Ljy{fR*V8?ml`NzCU4E3@Tu^MghIeYibgs5OPxjuhw}@!ls?k06$%=1#iA_y#)3t z;IW^h?|p21<;s;|L6cuUK7hPkewHGl2+j8iMUGPF%rDN4C(2Ail6@}Rg~2{g-rJ{z{~1EjGA5=6N?hjSsKMb2|Q zAc<=Mt|OpqlmbNH1hrKR76GKj0R~k^bIV_IbHfdAPht|1Rq#@tNHzFzCz|8ed!kl> zUjR9H4SV~~X!({vqeYCa!-r3t==~(%x>>N$8MD@Kx+!Q5+@~8k+KJj}Z`SQ8fT^vt zklPLc*5Pz{j$&bClu4Hg0==4zY%!ggWjzAW5pJy2(c7yDh@$Y_9^3DdbUI#Vh7y^zS=ItIwCM6Z3 z32<}s%HgDK%=e#t?+D023RQMtVIkL`(Ho>9(`^r z+P|SrTvqOq$}LH{U=7uY6>DnJ zDNPtd7?);Qsiw2JG%*borLhPl7P%z$`Px5Vf8P0Newg?BzTfwAd7jVndFKs#*L`P1 zdi_3g6ad6k12Uy_vL-X5+YC66HSDvoUlGi3W7%6cL~#3+;Zo3gG69f?b;&}--a~(yFaIpy38yE@gjx`daI;5xsY9|tg5+f`*s$*xqK!=FC!y^XTIgxZu-xy`6j$4 zbUIyx^txs9=FrK(HWd|>4tEcB5yZv_KoMag|cPB=Px_k+{{P`xDn2YQolmS^R0@O&P#&ZO9>?ShWvT$VJS;*%lj-1Ooy_e?w^+cbwv9Tc_@^En%Fs`N20K!=@Y%j@IkIDgmfFsK1i+-=HWI@>xjn%GEQ!8{Zs=s;fvrKy^ zT_^eWq-yd>Vg2BS&yzSYWpMaqjgw!}gk71*m#ej<@19o;9IcmCg}AhFX)an?T3dVL z1BrZtE|uJGY2Je!_dJOADdY=f<**6G!+DUj+f`4j4wN^}mtY%kj*lPSe#MM);lh5r zAxc+)6L%+$CJIZcK1@x;;3;ES&s0czj^Qu=BvM6c%RmQ)m%^G?A;}Wr-C3Ffa;&sD zRdpIy>gZFcBKb+`&OETY!|P6&Q1W6>V=eXdh1ez9vI=&E65xu8p|( z0qmi;xR}t2k;0|#UbTm-4|RbMr{5BQc^ptvM#3wm^6BY~(EQ&PH~we{=u zfvv9>Khl8A0T9AQEzCc5b#!)GUR(P6k`ORo=VSCFf{-6GIGpY3Tb*}+aR@NI$?))S zFt{%-P$H2O;0F(~Hc%fU>hC+|8{f0Fx96s+t}B37nLn~hUZ`U_IGBQ|)z(AM#0^jx zL!z`sooUOCSY)N(+3`2QT|)LPfuL1;cU-HsRZ{mi+PkEtfTs?}tLD#ojdz?c87 zC&$0FX0nbSukVd*a*-_vKq@bH`>2o#m34vVP1Z@eOvF`%c=hb*jt-WF286YHz{BK< z<$3K;B&3|`{+>x`n9Am4X1*6H8+szip%HR0>ypW!rFe7&sXFpC;AC&!&rls`Rkw*9LgUHl}%%4bpBhmBr8Tr%g3VS zULlr;vodnlM#fu)-g&&aj4D}}5wgXNwc_>I2nMmBr6cFk)6<#eU1K)VO3%x&xFV0T nXk=*E78GxYJ^4R=n!@Hzow=b{nG)e=My#J{=WHvq@jvqqm+3b2 From de4ee731bcdf0b2ce3e719806a47777d2ae520bd Mon Sep 17 00:00:00 2001 From: "yi.wu" Date: Tue, 28 Feb 2017 17:23:43 +0800 Subject: [PATCH 349/370] Refine k8s distributed training doc --- doc/howto/usage/k8s/k8s_basis.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/howto/usage/k8s/k8s_basis.md b/doc/howto/usage/k8s/k8s_basis.md index e296d69dceb416..f42631ced00858 100644 --- a/doc/howto/usage/k8s/k8s_basis.md +++ b/doc/howto/usage/k8s/k8s_basis.md @@ -12,9 +12,7 @@ - [*Namespaces*](https://kubernetes.io/docs/user-guide/namespaces/) 命名空间,在kubernetes中创建的所有资源对象(例如上文的pod,job)等都属于一个命名空间,在同一个命名空间中,资源对象的名字是唯一的,不同空间的资源名可以重复,命名空间主要为了对象进行逻辑上的分组便于管理。本文只使用了默认命名空间。 -- [*PersistentVolume*]() - -- [*PersistentVolumeClaim*]() +- [*PersistentVolume*](https://kubernetes.io/docs/user-guide/persistent-volumes/): 和[*PersistentVolumeClaim*](https://kubernetes.io/docs/user-guide/persistent-volumes/#persistentvolumeclaims)结合,将外部的存储服务在Kubernetes中描述成为统一的资源形式,便于存储资源管理和Pod引用。 # 部署Kubernetes集群 From fe44bc9082f6d1467fc90d68718902ed298b51dd Mon Sep 17 00:00:00 2001 From: "yi.wu" Date: Tue, 28 Feb 2017 18:37:57 +0800 Subject: [PATCH 350/370] Refine k8s doc update --- doc/howto/index_cn.rst | 1 + doc/howto/usage/k8s/{k8s_basis.md => k8s_basis_cn.md} | 0 2 files changed, 1 insertion(+) rename doc/howto/usage/k8s/{k8s_basis.md => k8s_basis_cn.md} (100%) diff --git a/doc/howto/index_cn.rst b/doc/howto/index_cn.rst index bd3d0ec2920570..5b84eea491f874 100644 --- a/doc/howto/index_cn.rst +++ b/doc/howto/index_cn.rst @@ -10,6 +10,7 @@ usage/cmd_parameter/index_cn.rst usage/concepts/use_concepts_cn.rst usage/cluster/cluster_train_cn.md + usage/k8s/k8s_basis_cn.md usage/k8s/k8s_cn.md usage/k8s/k8s_distributed_cn.md diff --git a/doc/howto/usage/k8s/k8s_basis.md b/doc/howto/usage/k8s/k8s_basis_cn.md similarity index 100% rename from doc/howto/usage/k8s/k8s_basis.md rename to doc/howto/usage/k8s/k8s_basis_cn.md From 6bf6034ac63d3dc9336c89d5d38aa9f0d6262238 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Tue, 28 Feb 2017 18:43:32 +0800 Subject: [PATCH 351/370] follow comments --- paddle/api/PaddleAPI.h | 2 +- paddle/py_paddle/dataprovider_converter.py | 11 ++++------- python/paddle/v2/tests/test_data_feeder.py | 1 - 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/paddle/api/PaddleAPI.h b/paddle/api/PaddleAPI.h index 0223dec4f42efe..d99e9a4ad48ea4 100644 --- a/paddle/api/PaddleAPI.h +++ b/paddle/api/PaddleAPI.h @@ -47,7 +47,7 @@ void setUseGpu(bool useGpu); /// Return true if this py_paddle is compiled in GPU Version bool isGpuVersion(); -/// Return FLAGS_use_gpu +/// Return FLAGS_trainer_count int getTrainerCount(); /// The Error of IO Operation. Such as file not found, etc. diff --git a/paddle/py_paddle/dataprovider_converter.py b/paddle/py_paddle/dataprovider_converter.py index 8d5c57e10fd358..60a0f2c0444863 100644 --- a/paddle/py_paddle/dataprovider_converter.py +++ b/paddle/py_paddle/dataprovider_converter.py @@ -26,6 +26,8 @@ def __init__(self, input_type, pos): if not isinstance(self.input_type, dp2.InputType): raise ValueError("input type should be dataprovider2.InputType") self.pos = pos + self.use_gpu = True if swig_paddle.isUsingGpu() and ( + swig_paddle.getTrainerCount() == 1) else False def scan(self, dat): pass @@ -33,11 +35,6 @@ def scan(self, dat): def finish_scan(self, argument): pass - def use_gpu(self): - gpu = True if swig_paddle.isUsingGpu() and ( - swig_paddle.getTrainerCount() == 1) else False - return gpu - class DenseScanner(IScanner): """ @@ -59,7 +56,7 @@ def finish_scan(self, argument): if self.__mat__.dtype != numpy.float32: self.__mat__ = self.__mat__.astype(numpy.float32) m = swig_paddle.Matrix.createDenseFromNumpy(self.__mat__, True, - self.use_gpu()) + self.use_gpu) argument.setSlotValue(self.pos, m) @@ -111,7 +108,7 @@ def scan(self, dat): self.__ids__.append(dat) def finish_scan(self, argument): - ids = swig_paddle.IVector.create(self.__ids__, self.use_gpu()) + ids = swig_paddle.IVector.create(self.__ids__, self.use_gpu) assert isinstance(argument, swig_paddle.Arguments) argument.setSlotIds(self.pos, ids) diff --git a/python/paddle/v2/tests/test_data_feeder.py b/python/paddle/v2/tests/test_data_feeder.py index 916d3aa4cdcbca..ab2bc5df76cd83 100644 --- a/python/paddle/v2/tests/test_data_feeder.py +++ b/python/paddle/v2/tests/test_data_feeder.py @@ -240,4 +240,3 @@ def test_multiple_features_tuple(self): if api.isGpuVersion(): api.setUseGpu(True) unittest.main() - unittest.main() From ffd045a0d0c127e28eb9283c91f9f439984a0bdf Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Tue, 28 Feb 2017 21:49:54 +0800 Subject: [PATCH 352/370] Fix data_layers and data_type function in topology.py --- python/paddle/v2/topology.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index a51b1073b4fc4f..6329915350bbb4 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -68,13 +68,18 @@ def data_layers(self): get all data layer :return: """ - data_layers = set() + data_layers = dict() def find_data_layer(layer): if isinstance(layer, v2_layer.DataLayerV2): - data_layers.add(layer) - for parent_layer in layer.__parent_layers__.values(): - find_data_layer(parent_layer) + data_layers[layer.name] = layer + if not isinstance(layer, collections.Sequence): + for parent_layer in layer.__parent_layers__.values(): + find_data_layer(parent_layer) + else: + for each_l in layer: + for parent_layer in each_l.__parent_layers__.values(): + find_data_layer(parent_layer) for layer in self.layers: find_data_layer(layer) @@ -86,8 +91,12 @@ def data_type(self): get data_type from proto, such as: [('image', dense_vector(768)), ('label', integer_value(10))] """ - return [(data_layer.name, data_layer.type) - for data_layer in self.data_layers()] + + data_types_lists = [] + for each in self.__model_config__.input_layer_names: + data_layers = self.data_layers() + data_types_lists.append((each, data_layers[each].type)) + return data_types_lists def __check_layer_type__(layer): From 89d300191eed4f2ec75d673ebdce80a671e3cac1 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 28 Feb 2017 19:49:46 +0000 Subject: [PATCH 353/370] Add early draft of imdb.py and unit test --- python/paddle/v2/dataset/imdb.py | 19 +++++++++++++++++++ python/paddle/v2/dataset/tests/imdb_test.py | 6 ++++++ 2 files changed, 25 insertions(+) create mode 100644 python/paddle/v2/dataset/imdb.py create mode 100644 python/paddle/v2/dataset/tests/imdb_test.py diff --git a/python/paddle/v2/dataset/imdb.py b/python/paddle/v2/dataset/imdb.py new file mode 100644 index 00000000000000..7a191cb583d4ce --- /dev/null +++ b/python/paddle/v2/dataset/imdb.py @@ -0,0 +1,19 @@ +# /usr/bin/env python +# -*- coding:utf-8 -*- + +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. +""" +IMDB dataset: http://ai.stanford.edu/%7Eamaas/data/sentiment/aclImdb_v1.tar.gz +""" diff --git a/python/paddle/v2/dataset/tests/imdb_test.py b/python/paddle/v2/dataset/tests/imdb_test.py new file mode 100644 index 00000000000000..fafaf414044a4a --- /dev/null +++ b/python/paddle/v2/dataset/tests/imdb_test.py @@ -0,0 +1,6 @@ +import paddle.v2.dataset.common + +URL = 'http://ai.stanford.edu/%7Eamaas/data/sentiment/aclImdb_v1.tar.gz' +MD5 = '7c2ac02c03563afcf9b574c7e56c153a' + +paddle.v2.dataset.common.download From 349319e5ed9c2ddb0af5a6fb66280c6b7b3bb552 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 28 Feb 2017 20:02:32 +0000 Subject: [PATCH 354/370] Add imdb_test.py --- python/paddle/v2/dataset/tests/imdb_test.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/python/paddle/v2/dataset/tests/imdb_test.py b/python/paddle/v2/dataset/tests/imdb_test.py index fafaf414044a4a..5cfb6203e78ec1 100644 --- a/python/paddle/v2/dataset/tests/imdb_test.py +++ b/python/paddle/v2/dataset/tests/imdb_test.py @@ -1,6 +1,12 @@ import paddle.v2.dataset.common +import tarfile URL = 'http://ai.stanford.edu/%7Eamaas/data/sentiment/aclImdb_v1.tar.gz' MD5 = '7c2ac02c03563afcf9b574c7e56c153a' -paddle.v2.dataset.common.download +tarf = tarfile.open(paddle.v2.dataset.common.download(URL, 'imdb', MD5)) + +tf = tarf.next() +while tf != None: + print tf.name + tf = tarf.next() From da6af5917f3e055b12163da4e048de73f4d2d86b Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 28 Feb 2017 06:35:27 +0000 Subject: [PATCH 355/370] Add imikolov.py and unittest for book chapter word2vec --- python/paddle/v2/dataset/imikolov.py | 88 +++++++++++++++++++ .../paddle/v2/dataset/tests/imikolov_test.py | 20 +++++ 2 files changed, 108 insertions(+) create mode 100644 python/paddle/v2/dataset/imikolov.py create mode 100644 python/paddle/v2/dataset/tests/imikolov_test.py diff --git a/python/paddle/v2/dataset/imikolov.py b/python/paddle/v2/dataset/imikolov.py new file mode 100644 index 00000000000000..e6d0357f97fa9c --- /dev/null +++ b/python/paddle/v2/dataset/imikolov.py @@ -0,0 +1,88 @@ +""" +imikolov's simple dataset: http://www.fit.vutbr.cz/~imikolov/rnnlm/ +""" +import paddle.v2.dataset.common +import tarfile +import collections + +__all__ = ['train', 'test'] + +URL = 'http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz' +MD5 = '30177ea32e27c525793142b6bf2c8e2d' + + +def add(a_dict, ele): + if ele in a_dict: + a_dict[ele] += 1 + else: + a_dict[ele] = 1 + + +def word_count(f, word_freq=None): + if word_freq == None: + word_freq = {} + + for l in f: + for w in l.strip().split(): + add(word_freq, w) + add(word_freq, '') + add(word_freq, '') + + return word_freq + + +def build_dict(train_filename, test_filename): + with tarfile.open( + paddle.v2.dataset.common.download( + paddle.v2.dataset.imikolov.URL, 'imikolov', + paddle.v2.dataset.imikolov.MD5)) as tf: + trainf = tf.extractfile(train_filename) + testf = tf.extractfile(test_filename) + word_freq = word_count(testf, word_count(trainf)) + + STOPWORD_FREQ = 3000 + TYPO_FREQ = 50 + word_freq = filter(lambda x: x[1] > TYPO_FREQ and x[1] < STOPWORD_FREQ, + word_freq.items()) + + dictionary = sorted(word_freq, key=lambda x: (-x[1], x[0])) + words, _ = list(zip(*dictionary)) + word_idx = dict(zip(words, xrange(len(words)))) + word_idx[''] = len(words) + + return word_idx + + +word_idx = {} + + +def reader_creator(filename, n): + global word_idx + if len(word_idx) == 0: + word_idx = build_dict('./simple-examples/data/ptb.train.txt', + './simple-examples/data/ptb.valid.txt') + + def reader(): + with tarfile.open( + paddle.v2.dataset.common.download( + paddle.v2.dataset.imikolov.URL, 'imikolov', + paddle.v2.dataset.imikolov.MD5)) as tf: + f = tf.extractfile(filename) + + ANY = word_idx[''] + for l in f: + l = [''] + l.strip().split() + [''] + if len(l) >= n: + l = [word_idx.get(w, ANY) for w in l] + for i in range(n, len(l) + 1): + yield l[i - n:i] + + return reader + + +def train(n): + return reader_creator('./simple-examples/data/ptb.train.txt', n) + + +def test(n): + return reader_creator('./simple-examples/data/ptb.valid.txt', n) diff --git a/python/paddle/v2/dataset/tests/imikolov_test.py b/python/paddle/v2/dataset/tests/imikolov_test.py new file mode 100644 index 00000000000000..9b1748eaaa7f91 --- /dev/null +++ b/python/paddle/v2/dataset/tests/imikolov_test.py @@ -0,0 +1,20 @@ +import paddle.v2.dataset.imikolov +import unittest + + +class TestMikolov(unittest.TestCase): + def check_reader(self, reader, n): + for l in reader(): + self.assertEqual(len(l), n) + + def test_train(self): + n = 5 + self.check_reader(paddle.v2.dataset.imikolov.train(n), n) + + def test_test(self): + n = 5 + self.check_reader(paddle.v2.dataset.imikolov.test(n), n) + + +if __name__ == '__main__': + unittest.main() From a2cec420c82575913a155b922122291eefe3b622 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 28 Feb 2017 20:28:05 +0000 Subject: [PATCH 356/370] In response to comments from Wen-bo --- python/paddle/v2/dataset/imikolov.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/python/paddle/v2/dataset/imikolov.py b/python/paddle/v2/dataset/imikolov.py index e6d0357f97fa9c..d9518dd27e9bbe 100644 --- a/python/paddle/v2/dataset/imikolov.py +++ b/python/paddle/v2/dataset/imikolov.py @@ -3,7 +3,6 @@ """ import paddle.v2.dataset.common import tarfile -import collections __all__ = ['train', 'test'] @@ -40,10 +39,8 @@ def build_dict(train_filename, test_filename): testf = tf.extractfile(test_filename) word_freq = word_count(testf, word_count(trainf)) - STOPWORD_FREQ = 3000 TYPO_FREQ = 50 - word_freq = filter(lambda x: x[1] > TYPO_FREQ and x[1] < STOPWORD_FREQ, - word_freq.items()) + word_freq = filter(lambda x: x[1] > TYPO_FREQ, word_freq.items()) dictionary = sorted(word_freq, key=lambda x: (-x[1], x[0])) words, _ = list(zip(*dictionary)) From eb1e34d2c36b23f2047012dfce1424626d1e4d6f Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Wed, 1 Mar 2017 00:05:09 +0000 Subject: [PATCH 357/370] Add imdb and unit test --- python/paddle/v2/dataset/common.py | 7 ++ python/paddle/v2/dataset/imdb.py | 101 ++++++++++++++++++++ python/paddle/v2/dataset/tests/imdb_test.py | 49 ++++++++-- 3 files changed, 148 insertions(+), 9 deletions(-) diff --git a/python/paddle/v2/dataset/common.py b/python/paddle/v2/dataset/common.py index a5ffe25a116e9b..fcf4437ffaf329 100644 --- a/python/paddle/v2/dataset/common.py +++ b/python/paddle/v2/dataset/common.py @@ -32,3 +32,10 @@ def download(url, module_name, md5sum): shutil.copyfileobj(r.raw, f) return filename + + +def dict_add(a_dict, ele): + if ele in a_dict: + a_dict[ele] += 1 + else: + a_dict[ele] = 1 diff --git a/python/paddle/v2/dataset/imdb.py b/python/paddle/v2/dataset/imdb.py index 7a191cb583d4ce..433e37380f840f 100644 --- a/python/paddle/v2/dataset/imdb.py +++ b/python/paddle/v2/dataset/imdb.py @@ -17,3 +17,104 @@ """ IMDB dataset: http://ai.stanford.edu/%7Eamaas/data/sentiment/aclImdb_v1.tar.gz """ +import paddle.v2.dataset.common +import tarfile +import Queue +import re +import string +import threading + +__all__ = ['build_dict', 'train', 'test'] + +URL = 'http://ai.stanford.edu/%7Eamaas/data/sentiment/aclImdb_v1.tar.gz' +MD5 = '7c2ac02c03563afcf9b574c7e56c153a' + + +# Read files that match pattern. Tokenize and yield each file. +def tokenize(pattern): + with tarfile.open(paddle.v2.dataset.common.download(URL, 'imdb', + MD5)) as tarf: + # Note that we should use tarfile.next(), which does + # sequential access of member files, other than + # tarfile.extractfile, which does random access and might + # destroy hard disks. + tf = tarf.next() + while tf != None: + if bool(pattern.match(tf.name)): + # newline and punctuations removal and ad-hoc tokenization. + yield tarf.extractfile(tf).read().rstrip("\n\r").translate( + None, string.punctuation).lower().split() + tf = tarf.next() + + +def build_dict(pattern, cutoff): + word_freq = {} + for doc in tokenize(pattern): + for word in doc: + paddle.v2.dataset.common.dict_add(word_freq, word) + + # Not sure if we should prune less-frequent words here. + word_freq = filter(lambda x: x[1] > cutoff, word_freq.items()) + + dictionary = sorted(word_freq, key=lambda x: (-x[1], x[0])) + words, _ = list(zip(*dictionary)) + word_idx = dict(zip(words, xrange(len(words)))) + word_idx[''] = len(words) + return word_idx + + +def reader_creator(pos_pattern, neg_pattern, word_idx, buffer_size): + UNK = word_idx[''] + + qs = [Queue.Queue(maxsize=buffer_size), Queue.Queue(maxsize=buffer_size)] + + def load(pattern, queue): + for doc in tokenize(pattern): + queue.put(doc) + queue.put(None) + + def reader(): + # Creates two threads that loads positive and negative samples + # into qs. + t0 = threading.Thread( + target=load, args=( + pos_pattern, + qs[0], )) + t0.daemon = True + t0.start() + + t1 = threading.Thread( + target=load, args=( + neg_pattern, + qs[1], )) + t1.daemon = True + t1.start() + + # Read alternatively from qs[0] and qs[1]. + i = 0 + doc = qs[i].get() + while doc != None: + yield [word_idx.get(w, UNK) for w in doc], i % 2 + i += 1 + doc = qs[i % 2].get() + + # If any queue is empty, reads from the other queue. + i += 1 + doc = qs[i % 2].get() + while doc != None: + yield [word_idx.get(w, UNK) for w in doc], i % 2 + doc = qs[i % 2].get() + + return reader() + + +def train(word_idx): + return reader_creator( + re.compile("aclImdb/train/pos/.*\.txt$"), + re.compile("aclImdb/train/neg/.*\.txt$"), word_idx, 1000) + + +def test(word_idx): + return reader_creator( + re.compile("aclImdb/test/pos/.*\.txt$"), + re.compile("aclImdb/test/neg/.*\.txt$"), word_idx, 1000) diff --git a/python/paddle/v2/dataset/tests/imdb_test.py b/python/paddle/v2/dataset/tests/imdb_test.py index 5cfb6203e78ec1..e887af16634d2d 100644 --- a/python/paddle/v2/dataset/tests/imdb_test.py +++ b/python/paddle/v2/dataset/tests/imdb_test.py @@ -1,12 +1,43 @@ -import paddle.v2.dataset.common -import tarfile +import paddle.v2.dataset.imdb +import unittest +import re -URL = 'http://ai.stanford.edu/%7Eamaas/data/sentiment/aclImdb_v1.tar.gz' -MD5 = '7c2ac02c03563afcf9b574c7e56c153a' +TRAIN_POS_PATTERN = re.compile("aclImdb/train/pos/.*\.txt$") +TRAIN_NEG_PATTERN = re.compile("aclImdb/train/neg/.*\.txt$") +TRAIN_PATTERN = re.compile("aclImdb/train/.*\.txt$") -tarf = tarfile.open(paddle.v2.dataset.common.download(URL, 'imdb', MD5)) +TEST_POS_PATTERN = re.compile("aclImdb/test/pos/.*\.txt$") +TEST_NEG_PATTERN = re.compile("aclImdb/test/neg/.*\.txt$") +TEST_PATTERN = re.compile("aclImdb/test/.*\.txt$") -tf = tarf.next() -while tf != None: - print tf.name - tf = tarf.next() + +class TestIMDB(unittest.TestCase): + word_idx = None + + def test_build_dict(self): + if self.word_idx == None: + self.word_idx = paddle.v2.dataset.imdb.build_dict(TRAIN_PATTERN, + 150) + + self.assertEqual(len(self.word_idx), 7036) + + def check_dataset(self, dataset, expected_size): + if self.word_idx == None: + self.word_idx = paddle.v2.dataset.imdb.build_dict(TRAIN_PATTERN, + 150) + + sum = 0 + for l in dataset(self.word_idx): + self.assertEqual(l[1], sum % 2) + sum += 1 + self.assertEqual(sum, expected_size) + + def test_train(self): + self.check_dataset(paddle.v2.dataset.imdb.train, 25000) + + def test_test(self): + self.check_dataset(paddle.v2.dataset.imdb.test, 25000) + + +if __name__ == '__main__': + unittest.main() From 7275e0a8c175d491ab01e725af5e7dec72608521 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Wed, 1 Mar 2017 00:22:34 +0000 Subject: [PATCH 358/370] In response to comments from Helin --- python/paddle/v2/dataset/common.py | 7 +++++++ python/paddle/v2/dataset/imikolov.py | 16 +++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/python/paddle/v2/dataset/common.py b/python/paddle/v2/dataset/common.py index a5ffe25a116e9b..fcf4437ffaf329 100644 --- a/python/paddle/v2/dataset/common.py +++ b/python/paddle/v2/dataset/common.py @@ -32,3 +32,10 @@ def download(url, module_name, md5sum): shutil.copyfileobj(r.raw, f) return filename + + +def dict_add(a_dict, ele): + if ele in a_dict: + a_dict[ele] += 1 + else: + a_dict[ele] = 1 diff --git a/python/paddle/v2/dataset/imikolov.py b/python/paddle/v2/dataset/imikolov.py index d9518dd27e9bbe..b3791ddad66e58 100644 --- a/python/paddle/v2/dataset/imikolov.py +++ b/python/paddle/v2/dataset/imikolov.py @@ -10,14 +10,8 @@ MD5 = '30177ea32e27c525793142b6bf2c8e2d' -def add(a_dict, ele): - if ele in a_dict: - a_dict[ele] += 1 - else: - a_dict[ele] = 1 - - def word_count(f, word_freq=None): + add = paddle.v2.dataset.common.dict_add if word_freq == None: word_freq = {} @@ -45,7 +39,7 @@ def build_dict(train_filename, test_filename): dictionary = sorted(word_freq, key=lambda x: (-x[1], x[0])) words, _ = list(zip(*dictionary)) word_idx = dict(zip(words, xrange(len(words)))) - word_idx[''] = len(words) + word_idx[''] = len(words) return word_idx @@ -66,13 +60,13 @@ def reader(): paddle.v2.dataset.imikolov.MD5)) as tf: f = tf.extractfile(filename) - ANY = word_idx[''] + UNK = word_idx[''] for l in f: l = [''] + l.strip().split() + [''] if len(l) >= n: - l = [word_idx.get(w, ANY) for w in l] + l = [word_idx.get(w, UNK) for w in l] for i in range(n, len(l) + 1): - yield l[i - n:i] + yield tuple(l[i - n:i]) return reader From 2c0342cbfe1176e371005dcefe94c1c3ca1adb98 Mon Sep 17 00:00:00 2001 From: "yi.wu" Date: Wed, 1 Mar 2017 09:36:40 +0800 Subject: [PATCH 359/370] Refine k8s doc update --- doc/howto/usage/k8s/k8s_basis_cn.md | 4 ++-- doc/howto/usage/k8s/k8s_distributed_cn.md | 4 ++-- doc/howto/usage/k8s/src/k8s-paddle-arch.png | Bin 530508 -> 513104 bytes 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/howto/usage/k8s/k8s_basis_cn.md b/doc/howto/usage/k8s/k8s_basis_cn.md index f42631ced00858..6278dacb17a378 100644 --- a/doc/howto/usage/k8s/k8s_basis_cn.md +++ b/doc/howto/usage/k8s/k8s_basis_cn.md @@ -1,6 +1,6 @@ # Kubernetes 简介 -[*Kubernetes*](http://kubernetes.io/)是Google开源的容器集群管理系统,其提供应用部署、维护、 扩展机制等功能,利用Kubernetes能方便地管理跨机器运行容器化的应用。Kubernetes可以在物理机或虚拟机上运行,且支持部署到[AWS](http://kubernetes.io/docs/getting-started-guides/aws),[Azure](http://kubernetes.io/docs/getting-started-guides/azure/),[GCE](http://kubernetes.io/docs/getting-started-guides/gce)等多种公有云环境。介绍分布式训练之前,需要对[Kubernetes](http://kubernetes.io/)有一个基本的认识,下面先简要介绍一下本文用到的几个Kubernetes概念。 +[*Kubernetes*](http://kubernetes.io/)是Google开源的容器集群管理系统,其提供应用部署、维护、扩展机制等功能,利用Kubernetes能方便地管理跨机器运行容器化的应用。Kubernetes可以在物理机或虚拟机上运行,且支持部署到[AWS](http://kubernetes.io/docs/getting-started-guides/aws),[Azure](http://kubernetes.io/docs/getting-started-guides/azure/),[GCE](http://kubernetes.io/docs/getting-started-guides/gce)等多种公有云环境。介绍分布式训练之前,需要对[Kubernetes](http://kubernetes.io/)有一个基本的认识,下面先简要介绍一下本文用到的几个Kubernetes概念。 - [*Node*](http://kubernetes.io/docs/admin/node/) 表示一个Kubernetes集群中的一个工作节点,这个节点可以是物理机或者虚拟机,Kubernetes集群就是由node节点与master节点组成的。 @@ -51,7 +51,7 @@ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s htt ## 配置kubectl访问你的kubernetes集群 -编辑`~/.kube/config`这个配置文件,修改`Master-IP`的地址。如果使用SSL认证,则需要配置`certificate-authority`和`users`中的用户证书。如果是使用非SSL方式访问(比如通过8080都安口),也可以去掉这些证书的配置。 +编辑`~/.kube/config`这个配置文件,修改`Master-IP`的地址。如果使用SSL认证,则需要配置`certificate-authority`和`users`中的用户证书。如果是使用非SSL方式访问(比如通过8080端口),也可以去掉这些证书的配置。 ``` apiVersion: v1 clusters: diff --git a/doc/howto/usage/k8s/k8s_distributed_cn.md b/doc/howto/usage/k8s/k8s_distributed_cn.md index cfc3086036f014..3a47a3832fee82 100644 --- a/doc/howto/usage/k8s/k8s_distributed_cn.md +++ b/doc/howto/usage/k8s/k8s_distributed_cn.md @@ -6,7 +6,7 @@ ## 整体方案 -在训练之前,用户将配置与训练数据切分好放在MFS目录中,训练时,程序从此目录拷贝文件到容器内进行训练,将结果保存到此目录里。整体的结构图如下: +在训练之前,用户将配置与训练数据切分好放在分布式文件系统预先分配好的目录中(不同的分布式文件系统,需要使用其制定的方式挂载后并导入数据),训练时,程序从此目录拷贝文件到容器内进行训练,将结果保存到此目录里。整体的结构图如下: ![paddle on kubernetes结构图](src/k8s-paddle-arch.png) @@ -28,7 +28,7 @@ PaddlePaddle镜像需要提供`paddle pserver`与`paddle train`进程的运行 - 拷贝训练文件到容器内 - 生成`paddle pserver`与`paddle train`进程的启动参数,并且启动训练 -因为官方镜像 `paddledev/paddle:cpu-latest` 内已经包含PaddlePaddle的执行程序但是还没上述功能,所以我们可以在这个基础上,添加启动脚本,制作新镜像来完成以上的工作。参考镜像的[*Dockerfile*]((https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/usage/cluster/k8s/src/k8s_train/Dockerfile)。 +因为官方镜像 `paddledev/paddle:cpu-latest` 内已经包含PaddlePaddle的执行程序但是还没上述功能,所以我们可以在这个基础上,添加启动脚本,制作新镜像来完成以上的工作。参考镜像的[*Dockerfile*](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/usage/cluster/k8s/src/k8s_train/Dockerfile)。 ```bash $ cd doc/howto/usage/k8s/src/k8s_train diff --git a/doc/howto/usage/k8s/src/k8s-paddle-arch.png b/doc/howto/usage/k8s/src/k8s-paddle-arch.png index c41a62392978eb94ceeb0ff24f23964055f5e06c..2183a232ad402b76f82a67234a5c93e13ce97ac3 100644 GIT binary patch literal 513104 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

  • qcb8$LP68-?ilz>!CfWMks_S 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 literal 60518 zcmb5VbzEFcw*Ixn{#I7 z-nr+@KmF^fUAt;mtyOD1&#F}sN($1b$b`sm-n>EmEF+=v=FQvTH*elaBEmy!l%o4k z-n=~o3=BRa6$LF|q#-?@Fz^DBc z9T7;52-He?om^Q#L&l*~`td0cc=-oTwfH#z`u80iw2l{z3iPih?~rKzRzMp8KmY65 zcO#X5HT(Z-!a^e{e+P1&>a-p*RXnl`0TJU z)b8PWz4j6$z2|p*vUyR+cG1#0?mKsndhPMu_leWFB>nidWaZpe<&Mdc+kwNT zg4w|?v%-5%j1%`AVJ=5EF{rhR$>(AK!+-Zk1Lq=kjx6F8k#$4(TGsz^$-tu5@-4>S z;OAHQVrAXc$b}RG`;e7Z53($n$)}~4U5L}VuQ0pwh2wVbDnVjt_4s*xQE5|%tuYx2 z-0X?b+DPeFBzNJ?ijtnIQGJ`9{oD#|oHl9qU8I9hcd(>jS4E$)l2-SvK0{03P2lJEaV@>^L2QEAXF;?|i(`>} zls|hOE~Xi`w(-w4FJf$JkT@(Bf3YXQvHy%^&I68Z?XH z4VPr8{=6=m`1!Lmx-ik}oK=vJO?Mcb%zX`SX!3H_Iw{q_v~Mf#{G6zSv#FVsLYJYd z`hle-S4#A+3gk!uPVshRvg*(e9!Ih+?}*^6GZ2_cKeCoyUZzMClT4fMR(1BuK2YBQ zq~;qvUWTi{KQx{iknHlnGIQ(ZU-S+f{6eKFsE8LUTqV} zA%y>{N504%O#K*z7@7|JU(EvtCc|0DbPyF_Z;tL^G|M$MrC%12)r1NAhQ?FRQepEe zpP9V{$TlF=&7SFn;`S`$v1p2vNNV2(nf;k@lG@H zwX>JYq)kEJs?X7(g!7wrSbJCj+t}?J#(bZtE9-1RgnyQ()CkYwmy8MSrVe0MVy*T{ z_q9uRG^dA6`N-Nqs=wmJ{jr-~4ZOxI*wvEmxAfU}W%$9B1;iFMO2K%mh{s~m8WJ+U z>aU8mgj&6p&HquSGU5Y|lH<$*)}>chnSscomd zVq2hAg^-4Ha6EA-Azi;7E+5BsgL*fjmOZ>yKGJMU( z-!HnoVN=enPTrOQB&#ymCYJunsgocVqD7}w%8=*BOlA`$*JUD7pd#Ucvr%ArbKM+qCp1$MtsWqY@b zni<)`E|k(t^CLSe9>t-2!qfX(HtduTdTYhkProe9a(|!m-M~i9T*Qeu^b`+A@h1A? z5zRi5*BcY>#!7tN-i*uZQ{1r3QCEPwG}!k7Z`UuN2Z~b6jfw+CUwXRl20vTnh$xuv z8cYB9D*A#GKZt+YfHhn-E?R0x{Us~xq(@sLw79r$t#x52Fj?Ur4<)=;o1jVA#fw2? zUK_qE{mR_nT_1(CLun<;Jt*7q;N66QUAJs~;1HwuM#m76SNB^6?~}vp$XyRaE?pK! z;K4?7RO{EZ$V%>NtA2>#a~Xci6LIF2Q939hucD!S?WGfWoKHgLqu=kd_y(Pt)(?x^ z4{4ja+d-3(9{E<25+yeJ&v_y&YEL7#sDf5qy|p_bpT&Gx4cm;iv5k}Kr){1bH^(^* zs{9st$`bL{Y*(lv_2w|8fnFW^HCCOC&hEoZEWb!=1{VuRe8#z{SbF(!)-Baz3lo0+ zvIK2#iP*M%JhG{_v#PCbN*nQU#De^tB z#;{7>KS~Ip_`1uog3+LP!SCPY0uIq@c?yiOm049fmA$hL2_1RNd@X%pQU zEMCn@*ter8#i5Jm^Z11Ut(1%tQxP2Kh23GY8*H_i@n=A9#SW|)3bU}t+H;fo0gtNI7PSi zSp8-sT+%vB_yfOFtnQDEDbrOH;!em0+FmUoU6Lw*;8+^bIvF`pm4U$4;{&P^LlP)m zMK^|DrE~Tp{bJMRIHdXx7kT&q^@gOk6b~C4+cpQ&ii`;)Rivg0GU*r(AE(+KNZY=`A+xw=f;UO%~;BU#sv4ge`H}bZ}PsbqcB5 zSf*;o?OwHz>dbIS`tU(q4ue;YA4*jfMa!yW7R|nyh#9}c*fDCa6i)Hq9^@Inv(YA% z)uqkcS+)`(=LX1E9Xb~Z)>ykMYPVA)m1KEVJR1N2pq3sLXl1EdUE8PD=W!b) z7ihvZlTy;)#$LWqSozZtYP5;9P7w*WC)a6-7>ylzu9nyDg_kZ=96PFxw{7u1jUZa+ z96`=d1R}>%*!?kaNw7!ZTtX1)U_*@H1QdAPlT$^~v%@Eg)2nvFkKkuwpAtR-2JJZgnrJ*QV<?a)>MV?u>xf0-F$BOyV`m(V+sR8WBwy%56H^_sG38A}$8#SrrKaW}04L zdr$h(YKil4b?Hs6JMZ%En~TIZ2ua`@_0At8U4cbLC4va2qmF`Nld+U6&LzH?g{M-D zrMica>$~O(th_gX-rA#1ROC|AMdfCXp+^lbhfgjLUVb^};r$nBV%!+*seYwZrD0`H% z(ad`3VH3~IFSrh(XQol@K(IL~fKH%n5Ik)m(M%4a=-3e~U&I<69NKGQvV#Q|7GwEm ztMF$ZR+?Y(YXgWX%!k}G5RC&eLr1szJEJ=n&Ty)}NZp(I$RzP8Xv~gkaxEsIfE%I~ z^=EfCmCsgdkPH~R{dU2V+O6+D_20x?oIk3vW44VLt|-v|*8e3uO5q$MNs7E!c5(8X ztjO%R)5jD8$engcgqd?#88j6uEUI=URdVH#!^{&k8{mss*&*GwN{ei>?Q$3i8Jr!4 z2xOxAFGeG?T=C`WyMy1xE_`b>D({;4a=5kGiJqBydBXdJa--gpg5i1tXcZDu`o&IB zCbbEN8Q3c1$lt!=9lG(AK=9dg*u>PV@4ocU_!0ZCRquBU(>7K{t!!Ds?$P$cCP!48 zT!0o4-?rV1Uz2-fV2yY&_s8sIJ)AMO?1=^Oowvw$hA*0`tNj~ zxg=JbCbf)Zh~5@&XK-`Y`uMTr zN2aLAypVHSxpT-r<* zI(^@lrGURvC~;{@)D#Np;fiP&8_`3HjG4x*4hn zqMctJXqqmb5POjS=nH5{&YbGK3=2+P(*>cL%M2JZ=DyVB7P*(m!Y^HKMu@V+$A1o^ zg=kY%$728YcPt{R)PMj#3OP&Eha~If@pGUNycF@DvtNYE*VIoIL}s>O))05Pg_{Wl~gB(2%W=aW9vDt(+sj)b$C>1a5lT!>&{b2lck z-$>mdcA;U4R6Efw1PzSt_O+0eN}DX_3gOhLAJwIVB-=mfp0b@kFvJiR-iC!|`RGur z3RBzqgo@S6_)UF5JyT$PRS>c1l8S0+K0&}c@p^Z7r>=uKII(%>-beJvpY28Wef9L^ zoZh}ePa$HP15V6k?YvYg@Y!-mOLr=doiVUab+YV_qf1&+sMgLgs`(jK9S7sE>SGUy zJJ4zop1976V&n?TLf=}6VY^kIZI^wd`l#z@B_d_U%%hgGXaS8&RY(2Qj^&1#a%Seh zQLfliNU`AVhHllO5B2c-2gphMtQ4m^s)@ZuO!V`*-jYrj*WUW=>@1U#0xUL2vVrQ) zJN!u#Pj9DEMZ5;z1N6IKVhg{MjpuLQQ=4x5i&ox$^aZo}epESHtoU-E`g|?eD)3y2 zcBsyBc*a8wQnyWlNMosjLFPa=zUMdf-4E07g}^j}Ia~Gl8L5KKqW#^@3{7(b*xa1G zEt1jg2Z|X$J=;(hSs@2x^K?|0MoMSKEA1#-+yH~H!Saocz~cDKOsM+}PvMsD@bC+w$QtMwtL}|PTlBB!18kEaL3|3}6g$?|ScMdV)I{rf08R-3a zQs#YbjfsxQJeoi+BQQRhxn(x%C(BiGP8||?G^Y2-&hLe6+cktj+D;U3b_@71hxsJR zaN&u2c940e!X8rWm)d;OQ{y{L3i8-_BA)BAV%+gh41=bhbv-R8x4d$@xDRUgPL6=q z?s$1!FhwP8vE%`Yg}{A)0(Uz8jU<^+h`WY?SQ?jRHokP-a-zwHs@Sf1DlUg7156DF zfMi<8-WW}&XD$4l>L8M9-HQ0Z3gW$)5$OKMv<7dgGAmWrXDlr_F52O54W3FL*e z?nMR!>0H{jKBn>xjfV1l=6*H%;rJJAS|a2tm&{`_AJSFb&v@k)k1T7GOvU$z2t&MO z2M$aaomFpiPzq+?#)a&d@tejh7l%KXV$ zTE_&zy@i94hfBYo7jBGH<{MSR+9^6RC8zim5mZx2WkyQe+V=Vis*!MQbKjKOM^70e z_u1eE$;8I>Fjx(mgcP!tbGgqU?L;gSdG3PU%UFH=MvPDQ#gcX_GuCbVVDy+D(o|!} zJ@a^;=KIZMbz-)^#)ox$JWa_;IX*AH*wF)M6T^^%$Dt+`VhQ>2{HQYRKgolFD z%%E%4p$x@NDu=BstA*tFwRZ1&D6-nlSB}d9{3uI9nEi(W?w%{{x=fZ8FelxV;)1Pg z>ft6oujm(8O;AK@yI9WuV5gr#*uUqRyKYyvJ=2U5Uu<=v0}mT}Z+{rJzCi;@@$`~O zn;9RawRfIjg*~dC#3hGjjUvAGQrN+}qvfSFq9F?R_katYn z?lLfk&)t=KE*;!1L*T?fnQG(|wj>&5QPlyX8^2wWq*8VnMX~fF0`6rH|)ReDIF*rXZ zW~`-h{wKDsr?59~IMPrZ;#J(2i{h@3cq{St-jz->T(?(ku#%!H_s8`;wk^x-q*BMI z9zkDgW(@v3A|Sm`m^D5B5Yd;XdrPWDzt0h}8X5qx|O9e+cDLb8puo>V^tPzVA2yJL$qanWFqk+b8 z#mJ4M_mag562uCph>p28+#1b0i;%f?_AV(!E0&BEbTVaWdET&M@JpBl(W2P|>G@Ci zBhbnO4-Y(CFVSsmE1NlSST>lNQ^MSBdV;KmXtbT~otvQRBlc>}H;|TwfebkwPEWvN z)Gn`6h`7tCHIlV6q6hA?e=#1slwf+Qw+pH;(iT>wWMzhb$>2G+T3l>p=tFss>Twou zbQF>6L+|Qj3`ht`%d|1bwVyzZ0P0McWk-BJcvvFB?=%HI(b-LdCOEWH|yY3KsZ*Xf^tQJaZtmf=GaB}nkn0oajc8X!S>M_O@ zfZsPu-;|e$Zye5hL)X5(XHZj8j5YE&gTJf7{P|gjx|#0*Bl`+{ojzb?D=@DScWiX@ zXKleZ&2(%@kKBMqkVo|TBL`c)a$fmXO`;{pg%_7(7}BgY9=)<+K$h3%a;1>ytUc@@vx zIps(qnaxGXG^H3oE_Bsn{zsBZ)OG-s)#6J73U>=Pg5+5;hpL(Q&40J{4!V z=mNOP2PZao6Ac2ttdP!;VnX;mxE2m0doF`_O_&_SvSQ43i)z3Ghfr`cQ$@S2_eupE z$QfW&$q|tU;1|awoOKtzhU8Y&+uy)Q-NHeMv$;7*%PoPc3%rIs3F7h=qenFgL~N5| z-p|BORC$5Lz%T=Wi@?5(hQ)$kf4Gz*%U1-=CEhsbi+e>~Fxj6XXDn1)uZz}dI~W%^ z4Eb3r*{H7?rQdV(Z>GZ`xgnMrV47XV`?$~ulxQ(*_7O2+vcbid#k3(ScGIJHbP$0Z+qmB23z?*C#hHXoLN~pGVVdH3lNh zQw`LDs?OO`-R>4Kh8vM=wJ4%pqex0&RnC+hm4G7~WI+iP;luQYbz1Y5{;#qE!rxjk zXH*qqCL;UCX-DQZPEA+podk56r1N)+&NpgM>UqBuHTrg1tFM=fe{k+_<2DGZsBs>f zbil5IyQ?H}UuMa9K`TfLQJN{WuhW8p9a}plvR>W6K)k zvxjRM%%D!jJ2e)zDi3Xs^E&X^y!mSHw9qQ$bjt6mk)|oxTlgyiLKAsx_>E_@ttWoY zsHEE7>tl+gk9e`Vcl@JjE(SY&auoQHXHJd2?2SPPZJv1eT%BkvB{_hQZGEwlMvH)r z2%}ZOceGwB^Pw2?C~m>N3g}KkR8}Vkfl;0N3Jpa3Mo8bjDDvUot3FXTJLM@{-wwkr z4!e70whiVlJdpkt$E%-V$n!Nh)HeXvq60_sjb;;z+z>m4MxY1RM16ae2vf5il07t^za2jggbvt`H|?n{B=@yO+FnLp;Tp*B#dp?6Wk`EI zURd}+sjTqD!SGPM?v@LYECkHXQvq7ZaaFc2EUQP^nl3Hz<*8~3?Y|wYMuqZ1g~gh@ zmS)++V#fL%JdHlWX^5vt^`lzgp+c*e-Y@k9cI&Eie`4udDXp^a?JIMQM)n`6X~tT9 z^LdL94VV47cJE_U@L{+t#mk+>50{cDGrJxwme#w0sXH}ADfxl_SKAgw6GnT7(AElf!cQks!^#4r3|e7=`9GD(xl|@1^Jlg&RS{TTN4*jbax%hA+%QQSZJq5 zyC{`RX`G^@C+2L-2cgs^0(P_g+OvSQ?_vg2*A^T3xE zwAg!N72E>hYhzg#L^#)}56suV-L>*ZRB!yOwT_Kk79=(WZlcnfMO(F-vGQ#6BNT2S zb6oaM+Zr9w-hOqNT6Zu2AOXq4;|QMK*RP+gd)kN47?$V1qv)W5MstaC0~W*b!qC%tK}$;wU%ZfJNevOeleoZ%;q zT#bW43UjR8c|f?^o7}Wk;NQ6ErC_c&C|MpxKQFvv^UY{`Y0F$4ISuTM6x6f%`Z#Ow zs^!7R?o!TIl*fI&Mfs2jS+tLC$j*qE8CCwx@#@~;y6xh~CfrMAVRfVY;#D}MS~$M6 z5C(AQSd>5gl?_Yhw;_9&saakvkL%daZq&Wm{{6EieNj75s{;eHlZprub<<_?iA0Q*Hq!NvA_5+rJVP zem9?@G;gM=p3yQa$#ryL;mb!=s59@>r#v>RgPxa1tL>@`n95GHQCW%a%JmwgPack* zHIWOd58(whJWat{tIT}6p>pkJR?7YwhGg0V=ljHW#A-2DAD1?UQ2mL-$Jp*>SkUWU z03i_ivb%Azw};(vEW1e_eAj&zUgcqZ0q2HtIYCS;a%6rB=eyxcO&uF@;(=em_X!fI z`67brQ6KHFJy$fs-iWZ?*MI3~W&^Nj6m6CYa@(zZ^aIU7Mw|R6yordIM{(OUR2Igz zJ+F>BbAB?u0+$NSK7GHBq9tYgp5#Qj_|&@1T7xqksmea;D|O+?^yJZWgLLrjIcZwc zPf)`vuR$SGW9PPW14VX*OoHdsJ|=El5>Al(z!ewa_8kc3@ZTi??2RT zd+9QBYx$PZ0j%5i;--Ie%m))hJ?zIEC3w56uB`_ZeYdk%jq_1;BwuPFNz*yf5ZRo{ z+4$I|rcNn@SiKk308xP+QQSbR7juf>1-8)pqwFj>baEI;)RrkE>=wVqqX$gYp*9@d z?o@&d6%zNBEppM9YT#ZBET9|HM*U0*hxh~IthU4JasPl!e7zsHeczuX|8Z~DEx&aR zXqa6Sx#19eyUGlj;Gqxt7`tHr4e39I=|51r-1*6c2_x)Q29&Tq1$B<|{02(#MT5ph zO2PAXyMBu^WEOE-6|5IyaGWdU-H9jO(8H2omq~1~wML=9fOW|--%zg3!jy{>u|6s9 zom1WP?^uoTkLE{&CU}!ufKKkmPFD8$-iet_dxIul68>rOR{|%cZe#hc^N7{$B%(wu zYh>Qx0U)g_?S6^ernj@d?Xr`RV~zbZ$-jCa7u0}F>Fe zO5oZ-CV7gCoDM#4q@gxB@iVL6T(_~OaQ&w5TLg9BX^cSAAD_RinJ|V28?1*Bx_?RRifepq6i=hRcq4jOV;~MeywZU)5qr1RNRb}kFjf8B zI9TWglYz0kC`t8c;NZ+rQ79+m^Jwv(Yw-CK;UG~nD1oGc*^MM7fXjCi40 zxt9lcYEAm`=c;+vZf>%7ska{_SPxThjegZ*Gwb`gtM;Uj<&l;$u90z_)H#OJ`GZ!l z#fMARgi$sj{29TWW0UsL)$m1`1d@lX{72?uyE4#isp<-8Hwr&eRdJ=qp+T27!xwiv z=9tg`WZlEM_58SUdH})D)0O-Vb53v*o>+=!?7&%KM9P}%Yz6GE{;aEuN9C+(i6`r? zJg?u~(`G#Up6%`-*1_K!F>bt6QX(bsz43hrnuV&-d*sML0B^Y&3JP-O&&%K1 za@mOIwj%bD1cwI1C92-KJk7srbZFoy1xFUDJLA?=wrXWL&im`%sc`MXd$mH!IA9J0Ge(6 zhUSyvzdK0Vr{fh3Du&E5IHh+T_My%-bS&l?HC+@osJ#Nq>-6uVYjEW)NpG>4!Kl5IO8kx$jJOB1tnD*$hxO)V(D!FoNklPNy zN5u(9n|>W!Al4lYpluf$;n?3?5+?XA^5cZxZqa?yS62teWc|=lVVp&W2~x1NxinDt zq_x(hR=;yJ#68#n{2jt+dwOrOI9j-`Ut_5G;zsR&my+$B`KSrazmc-YFQg^=zLZYe3FO%rR~{w3&7is9bWdKWVg=gL+`< zjv9<$sPgAal-B;{HOG&gM=Y4zXAQSCe*We~(f^e!vO-fd-{T`FK}3F0YJGt$BLlBM zxdt#9HSGVPnW)6+YEHX3j!>W)AV51zVxz0gUH>i2@(W9r=Ao3Xgd$p@Ty8wxJ3Zm5 z#oR74%@>^11H-ZTI)BWZ_#82S^aH=L&N3a#doQ7AUn|0jHbY7`(j8s_FFt5s1#`GF znkO~NpEwK)EjNuz%LC3ODK!^CA$8``irPN^bS0eGX@86^R9Qz4d78K(s%qizerZE6 z%Yh@NE&Nr%cxKJ@$i4JpIsDD4`W&ebaCcsPf$SqFjJf6X{S^LLgFq?MaLOPr;J_m` zHvj3Wl=vcc8=VDc8p8X++hy{p?Tk0~QuuesEUUa!3+YK$aqD_D+xqWSm+e$Afa5Kr zFVk&t)yU*Rr{3`FfeCQmf7yisWdHbA2z5X3&dWR~sEHYU>vLUbO{pK-M1;(0j9a+O`Z_y-JjYPD?0`C7*Xs~UEI-u&e`{i$5GV8zr?>8aAb@hYH9W_Ua6SrXZ zb_#+x1l*R)1dlMI5W`=~I*}&E2Q!JukDH<=dymc&_6CN1X+IhdZuRcB)r1@EYAdd; z44?^OC-*w~@_^+E9~M{_%$!!#S!d-Nbl+5$0U+PJx;c;j<{)d@g%=0+;G|tPueWDK zOZCLe?vKjO5$EYNfQZ5D%hLH&eu&8M=;6$%PUB6V#j*IX7Te)4l zC%bh!XIt|HFgf7Q+uT5{yYnT|MzSE;vYK}zt1I}0l9Zz>4pj@|tZ#~aB{$*-oYvT8 zl0_snU*H;F8($?&jk#yn>#l|&$q*Si!vGdPAd5Ugs(@#ztwIbAiilt5)ojF2eb0sF z4ds|g$jM7y7}G&E=B!I>|D-6Rpr5kRI~CjoTi5SiZk`eZjHhII#BE_#+KNn%iN)iz8qaBK0@VfE z5kbDOI<;)MOn6T=O$WDlmqYXY4;+eK$w%D69Pz3Qqj-F`wG8E7za$^F*2Za+97`Uw zHjXyj=) z;9p29W;%R;-mO}+JHonIcc2@ajbrIn39^W~=ZKWYb@i^VdZn$AeIp-YPHuf1k5dyL zuguI($NWwa9?G7t+|d6qJ5-1s&8*9GH+|Hfaye9teVyANtVGIL|4{h5P6Fku)SzDO z2X~hLI%DgrRSJx*R6C4IAxrv1iKgfEXj;ios5FktZYEmS_Lo_#{;VmA1#< zaLVz?OgjUNgk%gz+I^;5hmkVODFGs+n~(sx!QT(%j8SLu5#&WLm{cIcZ!gGTqjH01 zNiAl2!O1U88cuV{v-o$|g7T22=abATvOB+cvp(mnUNKW7Vh5#C~ zd}0vi5gf;Y383HoDXw$s>iPZjt^+$|cMJ3i~ z+xZ++WP0!Ed5ZUL_VLUvC+FQbW5n54Ij*PYmhHO~X5H9I5UikT_+y4F>qhFgH&2Ag zkzP^9Wx2{S{1`Fj35X{Gnmew8Gdh6zA8Un>^!s<(d+EqbRWcZDz-@|%Tr%Kd}9LA8uMmsnuNvW=@)`2w^k@(!x-Q+2>lb*xOg zkNEjY@bY2LsPIwvSJZvnIJ37+jy8W}0U1(LpxGGXm>R#M4SoB@g5$-(dcQmsiHzwp zQdMlz2DiLu#nw=}=KYb6w?flOvS&fM@yr%LL)L46E&zU6sa213 zmn9|l=TBsx&Ube=0r`i`KHxVI5fL)XMZf-I4wsWJ-~A2a>S;*oWbvlb-W3OeR*b<{ zx*9zkP!hA5CS6)z(_T88E9q9xwA_pQ+#%GFRLAy;=Rd)xz1_+Jr;5?$wan|UV`ujP zdQ_(E9i4p5pgYM8Z2VroZ^?D>O|0@y*+pl$M?+QrD6&4{YlO_te~+yL*tP_jS8v}O zwz(=l`Su())C~P}D%R9jIN`V1z8#^;tQYTFA7oA>Z!19WbFwQC7<*&SV1G2ir< zHomTz&MmzOyo8b0(PO3W*le5iy}SnZ(b2b}diP{ORq=%l*yy|+P`R{mzf{fDz7`@2 ziEEDc|McL;moPC({xqBOD}>30?ZW;A23D07W#{3Wqgkdvkl_r|>k$x%;5)%nVr|F( z?4;ZR8sdDAi{(V66hjy~uKaMj_?)*D=D0H}@n@k3Ra(`xQ}BXS=Biwny0`FK0dxxi zkw3hF;eS3Q%?NH}EZ56o5~P!}hJJ)bXg8X1hIhHRPmNi0;YD6YWcbqpBdl8Q|9FwG z(DZ1NG+R7tEZGrZ!EJfP2xi?!>;AqBKi9APloRoef|=?f3NOdFZiPOjY>G^9hTLR` zRRh9nQ!Np78TQ(9F*@T;bjhIoi``xr${S45mFYiRIGjq68P~e5boziiA{7T`x2t-| z7T?Y2X4PZF8AgM6z;OF0`Q#uP+! zg@yNS{s$gx`tDj%%r7mDZ{rZ8lns*NOr_(<`Hq=LZ(6H)`-5W(bbjT?_pEnI{My~h zbx^ay9my*o{6$03Ic{1^*Ek>iGgE@GgL71V{a{(%s7-SZfZ-N8+8aU3{=e3uJZ`E?JxKV%LI&1(vYz z;mR+|2mt5W+2=9H1^GDw56_GD&#K54%5KfmklD*vinDsE zfenuJ&yRjf4gOi$-vicFZs=JI>PZ#;6p?;Hd~E+!FnREl5Dimpv{KP;*(beLyA3mV zn>V*F0YEreT|3Wd^bE<@>=a+m2S3#l-69lSCqh%lwV`tY1MoFUSd{c#;RAEepMq|9 zMrk8d%Ms!}?ml^Kndc1hXKhdmqudj$?8^TFxf;~2Ijw6Jg;RLWKyp$B7A&F)0K)n}2yImwRbzEbs zR>8inIpN69wx|2|gcJdBIm3TgtlUbBP_v&e3tCLB%@wgtKK}9(rRZ;cz!%xQp>)D6 zQ!X?D;;~lvE+;z@r&cSH3sOicSp2G&G!SA8x0y*s?hZrPI4EOjdv#jof(@k^v{Hy` z{Zn$Tw4L0^eZX#K-~RhW5e|;Sk7Zsh zldWA#nUAb$$oJ!4R|08F{+<~@_eT@S%oA*9nvp@7zXY5lR2Wdza??^^8~IUQ{SG3P zq^9(DD*-<%g-K$ly&_`C1Am}J{do9`;-Kwdr$vBJr`d)mBqX%N#wF@&73@tr^{+aV z(6BHze%YKP$~M9Of#a}N;Vv&PeUn&S4a}^t3BqTkLx2MIQ!XdFrkl+WJDFLi6f0xuAL+U|n zR}#aJFn0y%Iu45E+sO;OU<%Y3iqr@RcD|^=q7*1Wy+Y6JF69vO{Ry=P z5Z0=W5T4Gu#I!>D8z_~ApIm}fc@|>*oE|aiPYI@S?y7?=Wns^2q3aLD#A)aBH+IjT z@dlF(gu~yXB-Hz?q?geoT4l#sphgL@vZcujYO%NP@m&J6U%z=J4n$Bh?U?#wGR|?2 zKwbER+x-UfKca<-QqFkKpo%Fr@R4Psm5Pe62SvhRIn;6zzCe(JZcwK4V0&oGl=7C! zSb~ePM>*8+-8+m*E*yI4jmk_iFmd0-;JB79{3{pZJ)a1il<7uRV2-Lg8{FHY%&{V& z@Tm7&kEs<`qW4)EN#@k1`AHgA@$U%mem!Sl6~;bM^gue<(W!pv0Tsq16XBKLwv(@= z8ae{#;o9#?clt`T+i~q+9Oh5(wc5RFGheUUVJiitjU%&kokfS`)CS=WD*q8{hpW6- zFXm?nLBLNJTR1!#>Cb&keQiMzTFp8*92GgHKP=xZ8pfM*B{vUSTWex)gU1RCN_U+s zNa9igbS)^lFC6fkrrO6Gj>q)?_!k=_Y4ZO9^;DqP0ohm_Ni#2A3t|$Z^w4%HcIj&SiyR#N z-BN&fCHUX6_p zV7=9LqF!10*ysz(G1TcHtL$d2(8x%JBP5iy#aGeg^m~DymY6;&~>UGM(DfI z0<+TdV|>pyz_b(}w1Uf7Zvgrbq9J&d;jKrzzLW(_5ZIw~CtIm-#BYTksiu1@GNeIbHg zNUQilIAsiFPtY4e`z+73A$Sk~tD}wL+VUcP_)6OcNRljgJ0&3QR26+C5mM~EBLi4v z(FgeGqwHLPb@)aWg*JW1(b2)DXC_A7wMO0%z~Y0lgiX)i?2HyRo2Z!r9%!iyME@~| z58g*B)dqN2anm*!cvy6b#mFUQU^JN$i_{9yg*4Zvhr~N3$NL5HmW)1p%zvQSL$Zo+ zizC%Fl|q($U^~Q`O@RkiRpeZzZIl@kA>I>!G)dzf`uQ)rMJmV`K2-0QS+IO2-C;*R z;>&!OzY^?~h4tB|v#daL_7y9(jzal;&a563RkJD%Jg{i}P*i^c)o3Xvo~mJ zpZ=#IhmH@W!+$M4RGpQcDWS>(-C#f{2mhZv0JMvLED+ZJ;l+P!UPOhwq9VG-*DwE* z9gH{yuCE(M$HuCNVi*$t59=6l`mUqC05FKp&sxnH!D_CJe0_Yr*_Sg_&-f2Ikl+l7 zZzIo4Sy7}@x+4}XvJ~^9tfKm>*HGjC|KS1t`*!{xSMq=E=zo9m&hz$!1RfrKYZLYNE*`FJTs=I*^Hq%f{j-sS$=jTQ-TAq=dKQoG?s#z# zp|Op8Cb``4cqOdvTl!3~M`}4}%EsM0#7Taj`Dcvo+Xy2ob18Ei1|?92KLIh$+=SS;S#doJXXIa`A0dTRt9(fC`*&v~ z{sD5P#_ye*QL>F^+R!Um8Gj5VCF!aWHRa@-O4^XXQhmF7G}++Imrl^ko$~gh^%-@F zusmSnX8L1|s|fh9weE`b#%Hx}*>#i2AXdS*KSIz@ztz;;2i{w!ba0lPm;c3uje9Jn zl!Mms>CQ@!bjCM_Y)s^ChWBL)c|nVSIXeBv>1oJAZus(~Hjhn34QH^h|=N9`s#mZl5qFv zEJC-MVFWq}33Ju6I&7Hs8WPmlv=kxpdX$;@BFa*=t0~g6kP zU^Y-f6S+ISbqT=4>w6E4tfopCI5S1%?T8=2X8T*kJYQ-1bh$w(4c<^{n0R;uqJ)tW zdHIa1UvV+E8R`4J*wxz&XVJIt>Y;J5<3GG(vr0)}!AjFl8_l+xUvRxjSrFFOi(*17 zr%VhzF=BU;#LoB7Do)3nH}0P02ZNrcH_yv0ZuKub+B^=rf5+O5)xG!-YRm2e$Ztzi|yq{K8Z7$LwGN?>CgNX05k-&<~T8 zC^SU_*Pw9i~5j_~FSBSU;JrNCTSuT@T9iMF}dS zADUD#x;U;$PR_t4iyg)~-7OY@infjnWJpIYcZ(@`Q0>4aXuJrdDy zVbK4>*IS0Q)rH&I72Mt3o!}0|i@R%Zr?}G=cM22;?pB=OTHM{exNC4JC-1wz{hht{ zb3&5}&+N0s6qraoC1H;|!> z*%kYwgMIzp^GuBYi8aHTh#7odWTyhqz#+OMLv|({BY2i*e|Q_bw#&-a$@U0w_6wymgF=|2{QNg5nt-|&c4>g4&{KD@{NHCu zx(CYx>?=P97EhQ+)MxG3=4x}pND-kAF8fh>rZ_6Z51r4GB^*=p-$0w5L!=U>Q)p{8 zN0y{htPtn#c_0A7Y$$r|{e9N;1;=wdP)Y#W;lgdic~vQrtQJG@_C&m}?;>$$m5?yH z%g^{apxT!lfXptnf!{)p$&Sl)Du}(id1q~cy9-k!KwokFwdI%eIm!i&)$ns*^m_EB z7YiE*vVur+x)PZiAtJ0K$E23#g(vQs21CvDM)y^_>J+QuG3&FStEw`y;5mb_{Xvnf zw%5q`x4x-Qk04TbFl^DMjb)r@`_;$~Wndlm^{v%5^ZvB3({e8oq%W>FXni?tQE@`j zhB&Pz8MCZyKO#WER}ssE7I9tmA;}5#q$F|A@v?o(aP+q@5N8Zb0vk1*LO&lsc+TRw z`^PTUzCj6pJ36|0xWJC^o@HL_f*+v}U0)BpI7`;?j zNZzex0AyV3u>s~h~GHFG* zB4^$DRi z@eeN+qP9fN+?jDR*Bb$|w5hCibwm-c%*5$xWD@LRZbn*vuw9Tc_75K~NKnIuj6c$Y4uRH-+)Q5}rVo_m zPoWxkkx<|9(ZxD?skv8L1Q?viH%658L&8>usp~E((=0?CWapE4hiE6OlbOdfrJe#h2fz6!PXv zEe6B&NrwUQL`IH9iGM&Jie%GbDGTuQ^vrK*S!SwlXh<+kH2n*K!KNb(>KH4x3C89m z$;Nk~z^tVd8(m%I69NTxN-jMm&$y}n7a~cNFnr)mV)8^-?6`DgfO0NM^h2oYhnVuP z#&;y-?##fAvA61zz;PK99K&m$E#%098+rLsaz)&o(`euMv_}DGDCpfOC`k6_ z-gN8fSWVCSLwAClRe4{olzWYRcSW+)k-Sm(`~|FS?ZfM#PkCAUsbs>E+jW#7@AyX| za07$h47s|~b_1b{nGQmt>j(=it}J!%^6#xMfpPHz_OaAGn%eh6#tc^099-qHe`0a;lQS0ry|sgguoQ4n@`1${=key*u`6m@7An~KH07#8PX@`GNKA^UNHs)PPaN- z-q{;zefCOV?@X6A;S8}4UmnIXBRz$&&*uEE9>SZD_4F|bepWn$Ue};@^`FWPLeyFu zR1C{rSY9#yS=CXb(wQ~{}@c!#beV@yf-)9o620(iagy8(dfb5hSV2Yy5Yq-2>ZZkj7@K@PZiK@#xLGsE+&z zpE73DVQ=;0+R(gpmS`Ad5dJpZM=-ZOGaxe*o*c zp3ZpDfdW`@w?F(K@ne?y457&R&{%3vF&0`^$7X+W@{;SivuK59^z8rhvu&8^r=8uS zy;A~metxWkx-ij}3Eimdaz~w8DbxDuG%;(%I^E<6*e}*W^UTKW%2$l)&j-t1Av<0) z`~kET=ha}A&W@=uVwby5FldGNEA#iv^Nwc3ghYKqOT^LEZ8C-ZFgx){uxR^#=1ZGh zu-T27&pZ(?bP_|MD{VF9ExJoy+~AXLc|v)S>D{jlbD5Ih?qPVCjT38th)Aq$?0!;L z^drY4fE81aFOS-T1@wDU%b~u@oNp$spOWqo>rIJoZ6IDC;0SJxYuja!y@-P54(7tf z`v9-i6c{y|G5)GA5WC2p{ipHLE_zsN@Z#Yf78zXFDZ5cl>@!pXVKT_xx(E{#CL;)) z&K(4wdy}QG%GvGP&dn8JhF2Tgfj?inF)ZB^37~JFM znHjI#6bYXk(pX%;+b53@cCb}L%(`=q5YjkQ2Z*(=Ng+diguaW^)&?l!YsuM0P41IS z8=3UXcFc02gi3S=Uyn0j1tME5CUjTILt{L(zMLXYC~clFROg2RW4eYKkl4|+9)Cxd zJg+DaEIAfDX$l(%nG1s!m(N?IWtPKAXVWnUsITs}$IT8NtZrCHaY?cvOyyhZI+vOR z$N}DX4(VHWb>wEEGAi%Nvb6-;AF_;l4VnNR;8#1?09B z!C?kT4@#*sB(OQ5h7?p)ezc4I;Meo9mYI?;xLQlK(>JWwj|!uc9`#Ovc1@3#S-97N z3TlZOP0Hr_2t_5y-qlTT6BV@H^Vj;(=kI86a90KCKO)&)O+T=5M0?%zFfFeSa)NR@ z`!@MpAKjXJ3|K*F^LcqJsV1|rUGTYw*g0ESEr#RQVzI=j%7SdNbW-7FebNFtzm9$A zZP9MMU(9ggolLf#*|pZfKB(Pp@pexwE<3+qT)t z0gFpiLADYyFV0IX2Zig*vi|ZvlXX@VDp!M!er4Otn@4Q+kFYTy-3#XAmXw5t52|EK z@?1wCuO%e;sFr#V96CwSfPJyK6i5~l`e8IEo)0gC*}D^Dfh`Urq}_8Ws4hVC$hGK| z=QEHuSD0T@H6+v&(=RF4qwX?QdlqWHEUT1K6Xy2AaMqS|@(*)xDx!LP)PKJV$y)h_QsH-?EGDCtiLDJw&*NS{F zNp?W>n3#q%D@lrwT6}wsUdr**{_)wIYK&RO9D54VqXuvJi3&S1vrcf8xjSz&L|MHa ztpS_eWqZn4pflny!243uP?d*w>U&35c*cGIX>Y+nzONgU9*goU%ZTfwZl$qE zstzM^e{eeUHPhIp*-lNgo{i^))^d0i-3~dux#C>Y@7^)Wo$SrEHUHH2EZ)4NUhVb6vm)4r} z#k5VVNrSmO$-7m=1EYl`_^*osEL?w?;F&YCQcW->!w???*sk>nH<`Y`$ zNMO!|cdt7(JHuSBuB4Vl$~TkO%|wq|aoAR8`u>>Hkgqu=FZR{5w5uOyW}82fS$+Nb z2H#{3<+z>myYt?Ib`A(oAkTr|9}VygzOdA_%jPjD4wu2LORp28T==Y z0qgzx#N+JV^Eo*L>guEC;rs(ULRCIMy@EdcM($8s(k;D+Jv+mHy1e;`+muN7(T*nm zAHdB2EtGbyjQ-KygC3~q&SRD=Kc6wEh zloUiKOGzyshx>*~CZ?=&+Zx^rSfb`M2zQ419bqKl`7Ec|oRB@6?Nt(x^@QUA?Trw( z?*}QjrWkG9nRW|HDB0N1@T+mDGv=Gl)heGoH2FGr-9&jzS_2YHu@nY#d+6BFD;~PY zKC^e;59gnijfI8}3NoOOlgS2bF?xs7vWuKulcY4V)9s5IaS&<+T;5%NT7{PqEIBoO ze5`Tn;^uQr+B%U*`>N>Uf8@LSS1J1&d0TPjOdPxV!mmzWPsa^%ZIxT|_Ln9Y*&PR8 zOnrH9tO#alttpYkWJZuHIzd+a}tVAy9*Qq@mkGz!vp7lCPEJJ*2g zXMUcdumT#7W5!aRl>6}zxqg^7F{1J_InTdTgabd-k803Z*4p$sI(niOIS@O#q5B#; zj@PH^`6VN;zlj!8iYzV)xve4dN;Sk+(8GG9tfkRmVBJrl?KlY{khpJVs!}9TxHl27dtN1724Q3S4k^N({`0?=T+_gT*O+ zgoslB5HO&4?EQ!DpG+~jXfOz1K6o^>&R053pKBLf%$Lmuv}QPA)Um9p-!*Bo@|P$t zE|>h8_-l9ZOCw{LHA%9`>P*bn?R60?g0k~if%DHcS;Nt@z1iz$2Fdcxziq?M@jX7I z4h$r&+KrA4qE4g%gctajbX&CvS(jMtUM1#bU2$Hm16xXFr-YW5z{j?Nf=3UDYs9F& zo4V4|xISNM00Tjl@FcM#&j;JHz9>7q^HW3d@o&jf=_+7hK0}QRXg?A}=X+B1w5s!s zLlWa2gtrdwi9N9bigu)(0M^Uf8e?Lj)F>hQlMIYv;+~+7h4#T-C7+!-zQ;kE9qBN# z3sa&p>#K?L;LxSzh$}i<>2SFwchBw{@@T00&Qskd8C4!&&qn?3=WddAFw6hh)Z2?5u*00sxh~Ndt4nes zotv8RsLvO2f%FqW!#i$FM9tGt<0~*^^Q(D4DP9Q%?kRH?*pFkhCJui7I|3BC+DNq!(DaAZ%0yA z%jG4?;f9Zlp|?~nC&{0qP-_>i(9ku#Q26N;>CC_AhRnfxHb3WkNmS^JUwib08$ACE zSD_FLx5~>p!KwtSO$%l?F&_*juS3j8@3kSVS<@hgmB7BLad_>9h}T%;55d8GZpO8$ zY)TZoYn$h-eJ{S@n}28aQauL)u!CQmdw;}imUmnetQ7|CMimALhIdz~aWK8gRA5^J){{;C{ano)6x1geDQH-4OM2y1&W+7RRts>bM@db|9(k4yk$W)AOO5Z2 z^{DS@6&L*qULD279ELTB>-6%z=y}M;(qBfQ`XKxVKXo{HCc(z}-1wK%QI9~1!+L&; zU(gnA8k-*J@)i45QL_Wc9bza>YmvfXKk;tPg-pWaGGOW!NOosaQ9dt}O3*Is)7+~AN^h&h6lBfcZuN~HzZSz}>eR0xCM5zb;PD2w#`8@@d{ zGBh}K9vYoNzVciGoU&KVCY;Q%55l!DA@`-}IECG;VNhf*%S~XX$QA+1exhpfj*5>6 zuERbA6;bzzLZ)^Chax8K`$Yo+E#}J%G#->z zhe_yUDXes~bZ42C+~9r(=tO-S)(_kv#|zHha6*YQUd@k-F?(*26~dykUn{u|!~|lA zs&FGyivoAc4SQG8vpd|My=61ii1}#8+K-KoG{1VhCx5LblI}rKp73&yt`ilWRqL01 z>E#rO`DI)6pwgsR!+8rLA^xsd)O$Sh!B(W_tHTD4?IK*Af{eR#sYzbYFXS z>S%%FKu(d<7~kb+5YT5yC}oo5vte_}s~)tDk)dVhQ5)MNd>wjTF@af`IKdHU*gf=n zoNr>HU)z@-PADj`*2y+n{$!iv`_BjeiFHR;@6U==%={H3(W9oVppYfJ5UU%ivt>c-j7)@0K0w zwW^IDfvvETV5jOY_GyXin4gzf-+iQ(%&$0guCFHEu2TREMh?SXJ#(rpt|7JrVSewf z_aU!71(z>oap(bTtscNRPGn#-ejV9|cjfJF*$HM;!aeHCT*sKbpYMuNU$*e-Qxjsy zrce0~+}nE3`h07~8lrDIs&hxuyM*J99%)6#Ie0n0&5Vi6+&02k`{=M(SY#~zu5fMZ z?tUU_U0JF9HRmJ`!e@4Sd~Rju!XM8{U80cr7(85mv<9?X4AKpVFD3ih*s6WLbc zTA?MCU&viQ_{W%UJ=yE!1iIh6+`O8S`bT>|Rwgxpg50~e65-(c>z0v47HIWl3HL}n zqkMM^w|#)$s2NBy4wk)N7wQ;!8BXB>&wh-Vx}m#eRWtvgZw9XO{@mI7KC&R^cVa59 zse67-=DFzWeQL2#8aayB%;)@3P4~pS+#J5gJ^u?VZBEkRVDigEma!-2=`e1EFm?Lq z^`C=1wg!6#_3u0Wn|Qaa3AueImNT~ssdkSPj%JNH=o0YH#E+ZhN$W49M<)8Kc))#a zU3hWxj&bi{76{q`T6f^zcqI_+a_wbQ;0+a9+qI(p&x5)^3Z>*`PAcc68$MDlqCw8g zx#@vBu%es;&DiAgD^(ATFo$*+kq2Abr1+LMqqH<+O{L)r?9x0@FI5<}T*r;A2DZ^eu~wcP12#l4EtIo<*|;H$SDWhQPnr?Y74sb{G} zj)x4cn-!ca(o2`|kmSK(w=U_&e~%<&QI5}TEXtU4V{&56 z9XtJSo;mH10bpI2jVxAURA~bIhWASriSD7Hc=2qeV7ak`c3>IotYSkzLJG;)%=pqc zq~ouA^;(Nj?0(_FO0{N$LDGRgDvx?WtTApmV|dueswg^ylu+Rc{E?oK9@W@6t%T_2 zyG!MTh#Xz+#HzSMkTckr6YL?Q8UKqKh?x@|-tg*_0q@Wl^62yLZ8Hf=KjQ_SAl|gYfto@3n1D-t8f zhjuJm?5UwN{rD^d9g-ST4D^pZ-!4J!6~F3rGfDnH6vQJ3dDD8`l|ku`@6V}LI_S|| zW8)H>i2XtN(elipR@(koGf|Tef%&6uJY`V-fvhQD5_wOn!A!5pvX2Z#C;pRr?3koH1o<>q%=^o;I8L6eb2dO&&;mv2pe z5KW9Wpm4@@JSHyXAf04(2Iq$lz-m>#{;+Sj3$azFj%bj6$d;TUj5!S;ma)i9m10_@ zRot^E@j(N}p~^2#Y3clq&ycmuz_Mxp@SX0*pO?F}ua9!+wzc`1TlVrL#-*$;cyQ|* zjCH)@$)eUZY7c|SXc;WI`gg-5C(zy+l#pa);U?yLEmu}3%9%=?lOY1bEUTJ^+mBt~ z$=9KwnAeU9CktTh$Sv;Rqy)*iqp=p#81Ndus2r~|d%@K#v5tZ(oQWBhm^CTaWKAVYZdI0S)VI4)R4F=Z*lV7T$U*S-t}-XGe^#8{;D(5(IUqpik~ znT5J-^F^>cr0T273*mMyYfhF$HG*~Khpl>zx>Cy+#by<0CR|K>OQiAq0*#KN`-vq|gSJamn4s^VZS6^HpPJD)k~nZmc31Ic{gqXQ5RuDB3#ijB-rdcHr&-k?=9-O4^KIo2Mks zU-=ccu(%t6e%s^{U2-K3_{yH$^KZ?5ZTct^+c9OYkIH>K=`4#;DKkFmb~l_dY!NhV zvopm>n5SKyyCA&vswY6yKqN@N8H2Q0QKpx@u(dkqL4XR^2Blv?ET{U`o4<~9ManeO z>2Z>VdycJ@-X1o;IMHUjnx}ai*|=x;pOk4qTuHi2+$+!<&y_Ap($;4s zdCs5IZ@Up>JFHT$mZQhY1W)c^>b>y-kX^xbFwwfYux&?81@Ri}6^=JgXBY4CxSHC) zuwp9evVxu)kI&Ejo&Rj-CCVU^IW`8URKDaE50Ufs)m_YQZzc#fXV%1rzKM|Zi2?%w zhDs5to1q6%An1G010WW{KL;Ul{|tV>r2GE{Lk>vkxKr@*?0>gIBIV-yrLVw=$+hA* zcqxJom4ocFmAR!g80HEq?5~J|CsAs;?ki=PlOKHbM^rUe4!L#jO?5sZMNf)@IlEW# zr|59=3JYa`?>uzA2^%P1smoS@gsVMkWKf#7ji;9xf)^Z?RVm7r!kJg7p z+cC-SAAFG5R@F2N3Ai%*vtAR@E}OXj#V?H@x^6Depkd&H3pHfF8`jq-+pV-%$j5M6 zs~2)5{Lg$xjg@8%G5l(xSKJZ&iA4Bwb%{x(KwY9tQ_NL?<24i99A^^WxiB0$5(Sj44AA{}lwZL}wFg8*7~9qEvz8e(tw)`}NRV99?_~E-AIZb9M7W<8{hu>PWy#ohvHv9>6&bY` z%3Ewgqs3#Wl8THmybv{82}Kakz;2Zdi_qZ9Rh#Ma6oj{Ijhl zWR1}b%my;V!1JXncO!S5)Kk;Tx4{-@E-uf%_OUPal(wfnR&r=cE1BNsJrcUi^&#c2Sc6ESpV00E z13{aZRBvhOO=UGs{9rxkOHDW1Dkprgv;Rd?0>py8`R<{)4FpeLPT)`-Qj$?_6r)7R zvY}m9wjYMMePIcf3&4P@8YRCl`r|@lglSO~U)n1@RgPCnKht{D(v~X5w&Z}~Jp0Gs zP9)fhknw7Zx9&N&*gj(2txq}S`@!!qnjRVl;{KzyG&2=^#Jr=zheTLfw-fW$qDP%-{HmqXi{KRWY>jg_$rECJcn1n*dQi^C!^l0V&M8nY9 z38E_1=o1+di{qWV@Uu?s`%Nss+9)nCGELQPF;}CS zigIj{WD(ue{^1{`jm$D`d< z{91L3K)MdHb}yc_);q+l9A0oKS|%2n%z4#K=6AL!+exaNU8~bz!X-Gj?PeqAlc_gz zm>oOJy7Z%dj(i@s316aXEAWIg9%t7vJ%4vIJ1otAa$RScvv9-9aQ&-(?;Zsehl)W5JInpA9}+6cuABEg+#1M2Q{tS1Cm|R zwD{uXd}b9p0ktMM@+m2oe3i#4^KLmM78#UJ2LE(vSd* ztIWB*uZZh?#~98Ko2Wz+1|9l&$3@NRIl9F`}u?l}zpq`zw zsaNc-Hjf)L@#qC96+~Q_tOF*GuMo+X}i~5Pztd_L6?)?^%jyukrjs z9C9T58O+sFkIG5hg$VqGM~{L1l(>A>@{y8K9IfCu7HN?YSeLry6&|gDC9uv(iCN5g zx)|v2Weezaw*4923n**-bCsF0+D7O@{X&{KsRK$}J7(B_0*H!CxZ&lBDO zkvKz3coQoHeTMPMtLzKe07rPq2?UK16R0v6v~>?pO-)t0{$zPVQ(q@QqOANIO~+n% z&~3e!z@tueyz#4O6kt8*PVRQmF#Tw%b2VYSFq!h=QnXAA@%%N&Z9V76=n#M|p)`UR zc)H)Yl}$!wlLZxV%Fo%BQwCzEH@?s^=7Ps{`xTP}>w}IJqp^94rDu-<0t(VT^*Lkm zv;Z*OC|4yIfILI>=ePlxnrqa5&QVkOO06N6fjk@_J63SAP_FP}bWfPkVl?7<<9*H{ zij$U8D!@bGwY{RFr9r)Y=sHtM&gU2Y;6wXHRjFphG651EvfI2BYM>;L6Ra+g*SmvV z9Ox0!=B<)#|EH=etQ!};sLKUy7Vov;ahobn?YUpXi%#(I@wD!4kYdcN1oIqn2M2x{ zuLsM_Qnh2I>%R+j&`p2l62mkLJTsF8WsF?>VE1Lb+t*pS>?FFK=K&cR_xCr-peVCk z>*mi=zeXTILJj_ij)7Rm612)g1$1@#L}-yKt~mL;S&rq=mNAPR-w1g8bgdlsx0zkl z)s`1pLLKB|3>_pF|G+FL$*?HKn>urY7rbC39erQC#D9I|n%>hgtlv-vha4Znv6SDe z(kp^PeVXfsN8Va}M6=XX=k3p}g=+2mMQ_Oeac#bo(VbOZ>w`~aJ^|FXnZ+p@s>7KD+|_ciHXs@0>e|n9o!+hkrK9bY}MN51oQM8<+D{C zW-K~o0C>2l@(OcK|G3HZ8lhfdvEaws9D>x5&@WB#zOg?I6mviWBlAS8+8*Qq`bWNc4yb6nh80Rt?P@-C@8K82q9~?E{SutX9Xm9_i zCSFKmtb1Qtm(Ge1UtogLDG2~i6!q}9cIBl!zE%-K?kNb5x?YfdYdo~$6(3Xc_J=`wPKt$m}~URag|R5PXh5Iz{P_$I;74Q zv*QH@L&Xxt>KJP;JuV)~a9R4_dn02AI?Qw5P%eTTUk_;Dy634ejHtowYo{Tf{{||H zLcb-b*P_b}B5m+S;XEjB~{TX?jpN-1ZSoLl?7*z<&QNeyAdZv8vtC z^@p`fA$(x=!hEa?V;TZb8)&!n><}WdUo*lfG=a~d2So)x;$4tgnpURAi&7&eGt^bb zb%vjo#+s5X1_hvAm5WbwVnsRbddJ5f$y6-c4?JPd8JVpCMuzQ_*0-EpEroZP}ZLXxl&QdGGL?jLH<`A!n z5%-c@MdC)fvEmt2M>~&;g`Ce#Rh{l0gOnLc_$y3xMY#3G-?t*-P;f3Rv7Y1RpVmHu z;vP>N-u*D2Wn&W(R#l~*AZJ&)p7&tpNu*X^qf zSV+_kC2`LjGkyXNF_lqQZ!bJgmZUP1+exSOTopxtN`039hbzcN9#obepaphTn8!f{ zr8kZu9Cb`_Nt0vTrBQ}{9fxzd&JnmBS-&CbZQvnfRQFcD67qKfh8IA3DeQ13`9D?c|5M`rw?T>? znisO%wkz%l55$b$8B+`n%e;U5M;p7(WqxL#JV{t4v5rZ;MN~KG48W=B>LQioi8Uy& zRAWT1488@Kbkw~|e%xOWd^!aYodfG|fYJvHqnuyEBv@=w+fhT_Sj$SA2};WCC>Ia; zhWMhlU(A=9{ud5v=nt4&y{x-e&zRaVD9RS4pdo%m+g6F z$T;|99<(gb4pdeUdk&3m;-m3x@*fuQM~Qxph?f;sNZ4YBRGxc2gnWMAP47$G;(sps zeu$YtLU};6bMRN234t~l2R{Zc3i_RUsH|x{PMFd+*W&oW>=;G1qSS2#`Z3wl=V#5^ zcmLFIVQO7)X^L<~@;lAz^R0;T0;3v2adgnA!7gXZPNNAOwNTgb4PT01S(d|avHB3D z4g=rvjDqGuTG8#4t){L~a<}Iqk9ElKs0I^xM>1)WPJfjKqt?%GQ^Ub3Av1=i6=^YPx<* zze49!9@upzI+iUCWE=crK`cti8HG_RTmE*s%4Ii?bhj~_#==QP*q;I*pU3MFVoqW# zJi}PbZ12Srz^!1#k>8_ky5lE45M^=jHd*BvfrPyK_!qc^aMLJiejI5fim*J+^4MH4t1Xdv!WC}P z*5G0jqanQX?U8gDcc3x=87TUTwZ|N*(5ttX52hbBZKk&5D}q(B+1C^2YKy(onv?RZ zUIjGYPY7!mWEnQ|v_ituYkbf&fp@F!VL5&QT0KgwS{Wu-k~MKVI1u;mIU7Q>@^{1X z!5-+GbE9z~=T)8p;y*4;i69k-N4JZ#Eh`)cYgHn#`?XNf*pa6!eb(p%d>^73d<j#sPSpIi>>HTfBo%LIasRC8+&V_@$5!S_Cji2NJ9qK123QyR*7VD@_%Nl2KU z$BU82BWk?0UIx3c`8yn|a4AP|PQwl=(*0FjEzR!$5*F0Bx=D83$ zu#t5^IKdUjdArb{LhVo->^5sD(YIj|H!eyr$_md%&2sRIQGNSYG~eIr%LZkWBc9U{KPPql7M^wE!O#azsGOlO;eMRxy9BKaR5?@G>&MxlKgpj3@6Gdf3!T7 zDkB_tEo1RJNLtG8HQsT$0fBYQ4`)wMwNNfvmB?=H?~A72fHiAQUCK7@N-ZykjJeU+-qgXeAx|^#_`2jK! zSh4Fd-bu)Iq}h~Wv@oKz+7fjzb$AGFLXHWBx|WMyXQJ)S;`+TyeHH6`Q_9?Rjr2dM z$Rg(xUOCHv{2)w@72eu|WNH8?-p^(NaxyzQE0*GnvNO;~kuY-gWCGf-NEZtTe$>dd z_m%BqO$Y35!Lqa4UoR1ku*S7)InkUpwx+eeNB}six7jwX4U6Y!ykeN|aJl&d)S^zp z9a&H7!*&(A$My?wlMJ!XuTW1LXFp)SF;ZLk562#%ck&P~P2quFTCAo3lk zKq3rQ26$qfyvl2qaXE|=ivwk$mdb_og^(kPk}oP99|G4bJM-Aug;kdYkLpz_P@;^( ztMp>Aqa_`Jzcs~~+D7UjL`Q>iOlmT?9NC2iBEL>V`ni_2Av&hYG>L6m)1j>jCgBvO z2IM-f`g+ogDVBt^_>jZn4L)IPU(mL~c{Nk^tu;1=v}AodBu1QNAaD5VnH2cOAE5im zO%HF)D}qh!-sHJ^bFw!M;Fz;+?1?=CgD#;?W`7TP`TL427=9fub-~>x$$DmHbOZ5r ztevkV+tXXHMP=`zc<^m?kO##RduJgeUG|kSDsFv`6Oy&+dq|O?{l}zks#73}G|rs; zyx63%>|e8}VLk+?=YHl%?+IEXb%l=-RGE*NRt|%e@vi>mzms*8Y!E%n(}))|`&V zWZpm03XzEw*;C0jCWs+jndbfP7^uSh+-b2N>Pw2cq zJ`V+=bXAms_^=ZCf9W+m7MFZ)Q-y0yY~ol8nuvG!kiTKr0%IyX|1q4q@z)qi zR%ptvT@aGmN<}J0UK(RVn{2yuSe@I@Pg0(IeEi((^QI$xpz)qWtri|2(rd>LKkCGd zm>?Y~qD-F|WDUtJ!epQ$-Z+mf8br;p)~LtuxN_TdZ^2W-n(W&i%@g>&IT^I-D*qnU z-jNBYW@E}*WKv6KlZiN>_O;4FKw_g|A}l8&-Io!1G@RL*v2xe6fZ(@P+2cI%;36e0 zMR)e1m)i*hEtLW&sKO>k8Sv;INs6tfGNz!3pBHIGeMZd{9+|@6OD}AMn)mZTBu;-1 zI|T=a>xHQ?*{U{lr>lh~jG7A1>`q3YyGF{CVw{13#c?S5B$;%OgBMf`PzWQros z&!IlrC0bn1SRzTUQLMky*dxilRX{tY-^X==@28>agDX~+M70Uu_hC8e2C2rTSIo{m zE00LJkGFYfmc|U6=P#O8!&!r?Zjwj=M6stn#1Cstp@rnqpp#bG2ZTkirs~0q&|oC5 zi>bcuCTxR#WV=YC8_1xcAG&N8OOiO`oPtb)y+m4x6drz$GBYJXZ{qoHzAi9rFT%8Z zW>SVo`4avZ3HrYw2ePf0hvr5B_+UPGyYu1cyj{~E_l@yc^vc)Sd}jN0^gJt_lpp>d zs5vZ*hnXrq+`5CSijgBNrTUS$OH-j#dC6(s(Z@jS4fXABR9kRN1O&)A(5K);47A+7 zNlZ71YF*`rVdey zIL6m+Pv`#Yl*==pfFu?4=++#xn+IqjJ$M#0&0f*m0#N%IU1oUNsPbFtYIUOm#?0>O z%5sMKG!Hgei8K-J@hvAcOhw<<78HDx~-!8_Lcfa;_qG8 z_z=%vGK{BOM&m0jdiC8eF zc>l;;DQVXUcN)q|AW`Mcy}n>&`hgzai$fSs79LUTeu5hi3MW#n{cplSrvh^mT@B{9 z1wbF=u4oHaA`}@pv?Ou%g(A-r=XG~|R86LFy7|h3+sf%GkzZS;+yrE=0og^BV;;{m zn-wB~i=5YfznZ4Ca}X>1QJGB+3LO{p#Aa*myzZ2aJ)fJ4M4Ge)sB_Idau*z~W4G~M z1KR?04>csjctkv+|WBJ0G^grSNTWZbFhk@pPYHFsf|NhUQ0Mx+!mzY2~#6O9F{~jm!KMz9V z1Y420TkpTmqZz0pu4XXqax(msFIjav@*or zO)?qSzJ)`*+!8UkgT4p?1?&KXyW1ZlSLm_5Ygs&Y@BWQAc=MVf-eTirMbWk(nP>5s zy*p~fgl4UUS=1%02+{S5^s}TvIc?Bn66Knz{U!`fv<~K<^B!uldNf6e+Ap|&Px%{a z!Uj$Jmq&3a)t+k#XCyiS-My}`G*%iP|BY7kfTckas)m^Rf7&D}1d_;-%&C9;@8YcY zLE#(MJWkBb15(6lR9#Ssr zqn(K3H#5qP(3#EV8DdNP*&DnAt=Tw~bHef4+bf36tr`CPF`;wz9MUppKnurEbrv!~ zf)1dcChzuxK$qsdUexx?bHWp|oV_F99FLbom-2sp2tRPbUGuU%>Hm+WEfl8;xW0NK zVm}EXn5Ec$l0tz>Lsb^#YXQZ{Tt3Q>bR#liDWDo-y@ew*IRf=Gba10;t(2pvIhlb2 zXYS%wa@fy0p@oM=Gb7s0ZwQ4nr(w~4G%yAnQ2bh}ryYb7XU;2NOmZPv+LfxAqGC!D zR;=T_;VsD_)P#*?js0&1WlJwayC6)avOmdBMMEF3*K45U3Nmi^CNJaiHy1qK9t*(3XeQQ9WxU^V`)8fUw#hp?pZoxgclN6`8 zON%?j-5rV(+}(n^2a-wqeZQGCYt1bFfxGS{JLjIW_kOlL_<2wU3<1e87F2l$>`A_h zq0$|0cRgjcHJHM-8t0u#w#1&3te+B|b6BRa!U5_gb8<21V}uDsA8U&J+7mjtct)Q# z*)bNsNId6PsLh|^+Wj&|6jO`dP3U8n$19@)LiZz|H-B%-r`^T$?CyQD zISPyEh$S1~>e3Te2|aYOq*ADD_*>F6#xbg7U#7%mia*nfop+R{R{S)JE)a~eQ3_(o z@gxHEV=1UM)v?ZUCX1{;0;CIJG)auT^RvTq4$rg>xIi6Wv=UMFjWW6C335+2{jbV} zfG=4Ifoiv3kH?-pS)V73#{ADWhQ6vUI%_5Yhh`uy3qlkG?UG!C==?H}jb2zHy-#V~ zzt3t-Lh&lBd94=Nw8AD=d(XPzYv)ez1EXuofWtN#2g>g^%b$0YV;owvhUF`u@H?nM z$54z4pVlLlh#t~gpeB$#&?C6qGngJ19h#0N|7V$@cuHnHA-R`+yjvMRzMrVR5gN&@ zN2Zaw2I1ug2e#;cy8$g7^_N&$1nOP9TLIs-=Q<(RkH04`11HXI)08QW_4F!mfbG?Y zoxCKP&*M`J_-3i~&MS+Hn4byUV*zEX!>r{#;NjwSY`v%I@|MCQC6!C~qr$qpUsRO!9UDBR#(nNb z7(b|8FMfKs?fq6il9);ZT+yNE#WXt?P`jks$He|IF#J5M>1Yw+R-m1xorMqlO8~29$2HTGWryhJScrMG_3ogbS_s+~}oR?SpqPROymF(K{(PCP+0&mA8fs zCEeQ>L2%t%Jo^%-4%m5|-}ofmSC&i&Y#kgA+BYKc@6pOXHk&Qwo6z^8+T;iGCw9rp z+B|%)s(C>uIsYtOhVtcC^F_R!y%}pI49=a?=AZGI(nhDq81TvYMtOxGwVL+wzDEu){$fLaAyx0nBT>t%DN;emE%5>64N;1`+MahTI#RM*_E7JlF4)6ay{b*R_zS5{TBi+% zqxSBHM$8qtp#a^JEy3Y{BS`RF7bfz1#d2k#(5mH)?7$h#nb0Z|>qSaEs*CXPH2`9x z*n5)e_8drt)=gWiFSCtEO*?7D4g8;UeH5X5g`Uk){-VpC0vu57g2PG00{M5Sdg zWXsUkqSMmMi@$QpO@{^2eN>EY4%=TS7votOxDX}PudC!M7@KpatbdcG@7|7{1?14I zn*V6DFGn(3f7xNu$PiciYlHUu{M?}_n^Z&8f%Ra*0t3W$3AR&|r5KN66eMQ2=Lv5<+%A zNc0E#B*bhes$%EvTgjHbYU|GWuFsGr0{pYaskY2a-yRtX3_`*GlxiLS*o5PyeFr}sGQ6&9G1_QrQS9Ky&5TWpr-plpmxF?7HHMcTy!=Z>O)`^ zhliF-_aOHGR{Q#OV>pGA`Rm3SI1!K%u56pjCI_Kd=dhf+9HL?fm{(^TRCnJGZ#?AW zyRwV4;4sjl`|kltN5hOG__~adKV{H8()_`Wia7OX4aO3{-(a%*Yu(o-K0|PpzgKqu z$gMan-a^7E{>W;Qu|zJTWu=oW{F&;C@PS%lQC3(XzfNFNlhjg+M_Qb!DQdn8Z`!)4 zkN2X0zb8nkMorWtSIxtQt@^F%;f@Aew9xRbyvmC#<~KU$enh=Pb_2Skq|tj;R;jZA zx$oqF!t%2~@e_4OjYqEl)o>IaFlb#9SgGc!qQb!jx%?51GP(h>s3e9yx++@+zD6>o z%(nW%?zxX(SIJRL69edy`@$*B*fHL`-S>1B`vcjuRn~SJh5yvXg5q{;l-u_Jul0o& z)DxK{m(T9Ybd!`uuG3(%`Yo<#7d|Z6y*zwu+Xg3Ps9^(YnYDge&cJe@l5O5_&}0fT z(uGlh-lQGRcNT}RYbL*SVmkc(LT}>N)_{@&P?@B8braVNWc&uM_pF%rz%6S~IsX)F zOJTP(@n6l00mTHq1#f3(F?9tPU&8y`k_Juh!_K<_e|vTltK zLhcSYeg37kYmHah5sDMcbJD=_b%~TL0kov{F-qJ4&)xRqlLEBd$nN38N+`DY@S=1U z$%trf3#DD+_KThJ?^O~#6kEsoM_oj1+1E#xx=WhcoqaxlQ~vR%fgA6ad@mRpZ9ED{ z?R6Z`#PuR}yo&>uzQjREhzIHy-p^qG_Y<<|$lFDq8dvjHIvbO}fp6lHQU=o$hJ<6Del@s!$Q7v>Qh-1~3zK@Uc`!cp7+OVqPvUq}oWI)i;gurfnba6G} z83SF)00-#qo~Y&OzIdV)|4Wsus#@Qf2JiudUd`7AZ z`3KANsc-qAVq{w4F|i3zdClsU2XZ)X!?lKW>`FngRKHssXNjFOyw23azg}w?@BYpd(8gX*?=YG=$CymX^dSb1U6&?5kQ`!J4N!`8b+>q3Nwe!OY?#}zKy9D3< zXCsbcOy>UR?2ISWZOhMo`R8c;l>w#g{$klboAnRuLU~w!0WbQWC{QDwnN8XgfCAYc zzpD$DZ}2RQdiPH`x|3uw28_Fq^2+3Ilu!A1t?VRnPtbQ{8%fa^D>Q}>CxPj%Jf?Y(YF6!8_F*9&%5j|1D{CcoG}UGqi{d;#WP_e_SbKd zhCJ-OKA{jQe!2%17MA@`Y=7*>w?eNbY7}n%Ui>pyGiMxE3m-iIN^x*-u;fLz`{s|_ zI6%L26ut!;{E_Hy5Ft7p_4WUNw*YfR=z~h3&wX(+>qCZ{$nVrcRDI}w0u9WbQnugp zerS-|mmJX}?yrv761e{Rs@9nllM`v9^9?Qko?ujvVlRaSUA2Pi`3>`*$0xBK(ry+XPXAdc_r&Ryl;qP=kCe}uR2qth8kn1c|CxVu*;{H& z;0I@5imSTL>hD>7vWE5(2z81xdso$L69L?~*IT6y&hM06A|1wx6QdCZ=qXIr7X&F)3f9`r#Er z^j;3T9pFRJ=t$1mD+?=kfaSoUJLF}MnMV5;pUg88 zVkO?Iv7tZs1h?&Fz}=@_!8u3;ZiXG->a;sPJdQJq=U;gZwhv;mQpn5Dc+f=YTmKln z-e3}5s$sPf(q7}@XXz>o0g)wT#hw-f&OyS=}i4_2iv zC-Rd8Onm(&77gr&m-AdqvmRjB^mDK`{5KJ8^=8-PiFoVv$0j9@1Az~(EzJ^nLL7y- zK;Uvzqe0!E(bQ_+(ez@28&Wmc>#Sw5xS?QDzP-M3)a_XfEr>22W;yp>Pkqos3t zoFB%5=jl?!i|Wg-s}67sr{C&pe6@cqJw!UL9v7UmJ@W9wOJ1YVWgfi!LbPpRHVCWp ze331GDch<9Befa~i1=ENdm-joUPMAa@=6Ju=#-{Gd>H875ER$=reD|vJGE)Xg>hKu z+of?H{wGk)&NaY27>9f`jW66E#RdGW5!HZ7w_pXG8?di)8G9H)+qEv045d5i0Jb=B zJ(Yxs;Il03G4%_3f47On=uwgC?+W`2A1& zj(1}~qpNi))835y?BQtnDm;MTqffycP$QpB{-v<+1)~+&&$F|srTp!|-*DP4-5Pbz|hvn9u#Y-(Jv*%{E#7vTGg=`5WBd zAm&cPv8?=Xt)6!t>_WQII!~+pRI40RvjQBRVvHK>t(k_ePMmG(7?a$c1+FWn4le1s z5*D4Paey_}*_&DU9~tkMZR}FP0C_+ONau_4O4$2}Gs}oTvre$10Ey7YFq69oUu|_56H3 z{gi=3bnGp!k7($=fW4b*w5ZN(g+=9x&OKEt+=nW)x^ ze#bJ9(tL%#Km7npfv5i0pki+`H(&!1t9dM~QSvm3vk!ZXFRs%ss+n}2TROASwjmft zM0HX0Z96M!1y12I$+Pfj8DtKM1LCt-_`~%t+CLS*H?D&g<-o|-eE_sLV z)4F%B0Fdk;M^nnYlN}joOsePWINpSBD!*Y2WX^x%w2QKUBwfblaqv!m<#|3JJ z#~FmBpb?ls_{|A~>)Uwx#gbg>Rgugd{RlZgqUOe+Ub~g(6N)vRQ6a~I}mJBYb$#-Kc*iTc-B^Ne!Qz~!y-aRn9uyOH&KAv&~TGEjJs-2Lf zZ#edz1y$zv2JN%<;=42wbWZ-Ow+yjEv!hyLPDbVX5Em#mLF_ z+an6=Wyl9w?W@@YDbBrBDFMN-f8l@(VTdF zgs#d5$-VWF^@YB24GpuiU&p$Qemw^l(p}D3a3Mdws#z{{k)85z_&luJWV3cso(skf({6l3?YwB2LZ=^Uz4GA!Yu4bnkD? zR3}3u(O!ItgYt?{G3XpKa=vdT@Duz7Cg6>4tl7H%G5N`F&ruqd-h1)^H0@LVRu^YpHO&krej;u~ zl8WDyhpH(JbNdtVrqgEvO6CP??nlyQH0lE^(-SvrV__&$oohzzO@uyKa+Ni`6eyS1 z<(C2aCCx|5oG0b3U*5QQWS)VEO`_>QA*K8?$%xi`&y85Sx9 z;@>G1HH5wwDYtCK1X7lX)AZYG&}jWWxG^m(D*N35dFfVM?7^vQCzQYO|{uy)J(#co$JK~3=&jrgKpV0H{^0^a|;&)63(i@47DwIQ6!>V*T-S#VG- z19#!i+Fx(UqO9|mr+mkG1?@@Z}e5qUu%p>`G%toevbl{6}i(o2D$TvsaPtPZyI6x=*j*8FzPr z`($gB4&g}T=(qy8&{>uqA|XaAK!SE{`!QjokxZL>DI;<k z^23s_LD%SNTPRI$($RSz$Raw?`JZ(C_CP`Tf7e0TcY}IfDfda~g^FI<3uhnVjt09( zlp{^==+Ko*QE{lhu_#CYKf42o0eoRLHJ|h9G4&Mjz}7wzg*@&P-G;2X!$U6NTjA8; zQO6PFEu_u2PCnyQX#ECxl7XN@^dTQ#r3XCF+?fO3O^PBwBn9Wsf_k*ShsSIwLv{wC zn9$RdbjYVL2x2tjExiUUcRL9r1cJF_ES)HNJDRa>y?QI6blE@0|5ONkE9`xQ(;oP3 z%-#E@9D!wkL@~tzJ<|*_lG=iYE{-7ACU@nVtKfSd@Pkp8*Tf^@2yGPzL%cq2!@E5? zp*|e}J>UreZoWrAK3kBp6_lP3fFCAK^tWdbw@CP#wwp(Q!~8S;wnx$SV8G*}@)6PD!&6s- z+U3R}RZ`h>d5whI0ntaywzC3A=YUQ>CQ&ZFa) zQ-gMs_B)LGdExtJ(%TapZk+)W=X2sVc!X#Nzkrb(h8_wtdy6It~p}=Z06jqw}LO8yFf!ll=ub zAc}Z`L~JO%GkD9M)e^l70#xIbuftw}wrX6wyNDbf}G^W~}_@yL>dC7phWxGw71yP_^R~m=T`rGTfUq|=z z@}CKc96W8g?H2Vlzm?rX#UNQs?pE8cXr}b)5`{&;X-ROo9m#RJrDfmp>diUTYHA?j z6z6nS6k8%G;^*}jB%h=56;SPM-KZG?K6Y9Cy4E2nz4Q*(TvS_PHQ3yidH*Cc7*Bt+ zQ}}jMv_^X#@-Wign=-VqR#;F?A$mV*Amg!$=rhPRRRc*Ui);Kodu+ca@IC+`-z3@D zyk^!z1`vR^sI1%hGTZ`mI#}X9cqeT?9`+i@Z9^_V`X3*OO6Tv>f3qPFUSC!+ATW~Q zmn5ZIZBe7uPLPhR7Ue%t2b9s?U{>hVCLly^%Z~fGvrwfm6@~$Z=w`RAG0;?|-QTP} zt{^wcR62ji3uty+xc1R+Zp~xfB32Q}&GKn+!O6dV2Hk=-Zp>t1i0LbhrT2s~kpvUc zaSx=x0G5-e9RpKRxJW4FtnU#-zz7)zZ(9#Hc*+u^++c9Xg-C34Zxp)LO;1NRL# zJWzH?uPd(M$9}e+ru%!q<8%F`H-59%B%56g^MVzp|7`D_-7aJ_XMyfT%CKB7&h?c_ zdv+fLJmIXHi;zq1+t&BPc>C+;6fx+F>E1ALm{7yPjkwh>edYui=yWv7e)d5e{F;n5 z2NgurhKC+%Z%$5k5XPx<%mIy)pd_yPchPf;mM3!0T;5ho)X246QLt*v!-ZQ8A-6D+ zhGMmTC-@aa){&g)*CxzLq#`!{V}2LEIc7va4Qiy$4YSaruUgq>jV_`6->cVkvmvHY zA{8_Wb}Wx0qH8AsjlV$;EZXJT7~Uo(_{a+~$T!gA+H-Z1=cf-h85IY}XZ%D?6Wos) zJEvw{KTl6jduEY8Wzt1&Z%o2vZuF(~6gl;=BYrC*5lGOW#>eMA zjnii(Jsn&;o3fVDwaudu$f%_i;pUosw&zSPgfX#HLWG7@e7*N!Y|$7{Esw-K^Bq-Muf5bup}G`NI<9 zZYBDT!CEuqLgTg_vD5x}N(iWBZ-U#sqn^kewE_N;+5lddR8gDd4NLNkU?4N?)Fn+| zgFzft>8X02A6Y#l2R=V!s$o$Z{MFIRyg1|wAW)nAc0`-}=O>_CiM`ax7kMYGJl`a* z0Dg-}Pr_o&&>Jl1!AHV_NW#%lB7TXYq{Xyk&6Q8nmo2TiHSgT`s=D*KvDZ?s##j*= zY$B?Q&kTme&#Sv2;DD9h_QyU*^#`-iiq?#UAfY5y1GdrS;a@*pv+ziStshn&j&a1o zOWB^W5hz$AM)^EMsu>TO)Djmk&^jNER}sWG)+3DXn0pK=Pcsl!wXcakPD_z6 z^K)u|9fv1!Ncr^Qrb}hH@Y5GLR=L9<;o_8!N8h6t81KvQ@8}|A+724N+^TpmfqO~t zA3Jn(`}EllGG2AA!i49o9(zHEZzo{+D)u}SAK&`#Ns>wC`#a2s_QdtuM_8_;rsNwE z@&%LLHU=ZAiSl+hi+9ZrTsTCd-~vZA0un?#~r-a@1v2q~r>WvlIm= zporr-X}wMTEGhIK%aPakU8WRuTYh)PUKbQ4GN}Ghk7JJF1_E%HU&T?JW8eg?(K5b?E)K* zfX8)YOGTf623dt;cTL*4Nhj9JMb^j@cI(+6pusDn)Yer00w{TKcHSsbM<&Ar*ffV4 zj}wu24!6+w!6!ogyXOSbB*@&aRoOvt((pW|g=$1Uu~OeiE~d&PEo%+~f4y3J7)*m(3MxU{9x z;Z!Hi0&f^V^>cdO|N9y8akTt%N6GMlIZZ!giLE+Y@|V}vIo<6jNND}M`DAnX+h*be zZKtkJuGlE@vdkU`BzDneQTTb~adb&EtVj60kC+^E>2m43y#ALyR?D zH^5`=A&{w;oGF7TA;=^rz;qC%dWUPLANXW`_~mwA`{Obs)cei=?9J9Lnfuresg?0+ zmmyuL(JpMUD}SH-;6w~RKc&(FziRtvF$lxC8WHQKo@h$dmYfOvgo%6v^hR%wllk;F zIqKuzhg36Kf7mqI(BcT-cT;^?JtehvesdC{tfYP<*K^duquc06!rH#Ix7vBMph9Sp zk7<3@hdiac&KQt312SC$_`U(W;X1eTUU;rE>o*SjO5BmsB?Nvcrxh7m#WZv6PW}yT zwEGHJ$ZIbnY|iSzZ+_B5w|9c8z-{Cda9mkSwyh!_f?WT;r=cl2n3Pf8kV=I*VWZ06 z2x~g4t(}DR6Y#0+gX6K1W$s2RBw>dg@J>a2+SlN*TlsVp;Llzdm$ zD3}V?*&C~qHgj4?1EU!1D7Q>|+UnRWHVhmrW}XKf$Y~;GMGSx}90wY8OX~8gT#l7K zUps3?jTe%FX9wCw_K$Y(TOk+1!&;Q)I;S6C8ra17mwPgt;M*ifXGzU!P5{PO&jHgx(&DF+gmsfcS3Xk{O!co^%4wFQOC+Pb$WxZf|D@X z2Tt74y|(QwV)}yW6XC|`!Ez`G;?!E;FuuDd4u{A|NonX}TfBaB5JhY0!vN#e8cyq7 zxAgFE_qgNEmxr9~>U$rsL6`zg!@QIF+rya6T|AaHyn7w4I5~?C`fFByhq_vR2s!P8 zrcRYRb$xhd{e5WTD_2SZQFGOON|(93EV~9}vE?>(4L* z>2RwHnUlC^PF->ro{biTuj-pYws_XN>S}bsXelq$fcaQM{5E|*S=!io{3jUnzJKC%t}gGFkzSy1G_g&gS5y2yG_{AVcUwCJQHX+PQ9 zot&B)LR(wguC!TL21MzV*jwBcba%-4!<`c!+7mVxfnQ)8@?PwzE|2(4TA>5H&@HhAhUA&YJpVIa|fxjN(qy>M4 z6Htt%eV-5F2OnfnJiR=0PkvOK17O$Z#f&M*W&Ci*Wu*ju)`^_fp#VC(e;B4MyDYIn&eaRPkBg^k!Bxkb8tT)+>E?woKTUH6`yA0FX%ZK-qv+rJTNIAC-G^@9`=QUjzsc)2-yUWw>&WW=+~8gDsjNET z$h2N^X;{5gMo@?+l)K~*j(?na|LG;Ble9;M)=Oh%0vA{52s!^KVcoT6T6Bgu)|_8j z|JJTBF6e>wNo-vj8!{f#i1KhP7AJcQeG;YcfB@SG|)ubHFF&D zyH|&Qmvl@_@B`~0eY)(mXtu+b_PvE(?XqPKS;mT`18eih5U1YI$~PAe?@{bb?g!5= zdOF#uUVAn>Sr%mXiWctE`SH))s2!_enLQotWj{N!CxE$|li+y~{6Gje2=#S8T@exC z@$}q~s&(oV@|d2vdv&cIa>={Tl})2dj>i-{kGWH!75tAfiA36HM=PcR`VvXbQ2%C% z1HC7ju4IbtT5AX3qE&axRi+l59_e#*3B>E`HZK#`5^=VY?VSydqpo7$R-& zW(A9Th|B~((_HwT^bR+0M4SHj3k>qzWsb962cVAW&}M1P(40hKe$&<_M0QerI;}GB z`c2%Z-ulfX1D3z*S&8j}RmHUV;3IGGdf&ODONJT`KsmKp2j?*wU;5@GAoyponzRNE zdFv141j-DTs4W%b2HS=#_oWYIwz5H_($IGXc569b(t}o$D4?{--NwcZ4kE;05z2F6 ztVLq9yfnjKX;Yvk*S(TNeODnNA&P|yA7~?^MmRK?0i``oiC*q#UC$isG!s9%!i-#> z8;@2Azy1-Akb6?kZi8%q4%!W-$w_)p*=@&nbMZt*)=7CcajR*nDaW_oe(UA;%);Fv z!6l!$e!G3HSW`Hx^xR3KMG-ySEI-7W@H$edl6;UJW3qRS;`G!YjN5lb6T+wET=B{y zN%Ee?l7Ec7I@AC;mLGUpk6w;DJUzZqPwPxsI2|!$TFT1Q5fPlHx?n`#SyHK)EV*2F zznw=H(vop~O~b-X#8QIi;z@B1&<)OL#^mYCoqJX-@eZuKYDX`@dh_vAL`Uax2ByH2 zybS$S8Ld_OZ}APE=DRnjA*EkI)rc~CCa4ep3n_ElVU>X&E2LhstUps)D{}Re#1#u( zNH(VQGnaPvUvO~EY5=Y0Ub?3JU+`)r+r`SsX3aM zx2^OB)D0dL?b}EUUN!H&q0FFC#z&<$nTUpi{0=rUT!zNgE-fPZy`o?8iU>LHkH%m2 zYT)-)zygQg*9cj6HGM@m7C8Fi@HVnZNPQ)n5*J8~SQuW(gk_n!`(eb3>Ix^V>3cAt zW@TT4(22z~vYc6ySt*$_`fPW1EyTw9+D`TBR5jh%2!?(0sqZ3?cC}KeUgsb2mjZ?b zEELR^n!(zd9O^Og`cIxjYfb#q`>}PG@M(AUSTTrBrvMhV;zS6Kc zMH}Q4d+Ob#MM=>&q^{d-=?cz>A*N7c-p#-pXG;Z(B9=aB1@@cMq-XN5c9xx&Rst`~ zZR(pzvI7|lgi0iCKCxH80fLgG>7wI0005K&lY_mSV&Qjy71TdubidjUVp z++Rv9-o%KK$*n(~Q=!ESU*YW@dviPMN<*sN^Ss36liiVx`cu;YPgqv zKx>(y6*CRlPveR4vR&zoHpPu(OfxCR68F2tR1N=5AWd0@Fr$>(%X!S$%ZcrXgFvEP z4nAyg5W2L)Yo{08sl=6IPHjFaXA8%uyT^Ke1#IX5XX}v`l zIgbcimh^1Ii&V@z!`q99zv&0M43P|G*O+` ze_`US`#L87EMQ|5F2MzkKAQxMtXs`b>=?+xJ_HcomNXf3bNIwu+x#TmGl~3z zHGS`g9BMB%9l=787jWC7W>=(u4*i(Ux0NWSt1meOnBZ_@b*i|oDN>dfnscWY82rO2hR344 zC8Yi;@qMRH9Q!O&)xi38;Ky}Y7q0eXZIIp7FRm{sr4A*SGT|joA%?=YvMPmE1S-j?4&; zN~MvR`db{0Lf6~QQtwy;A(*ExBW|wn`Yk zf-_oyM;nSa+o*G!X){_mXJ@gX7>wC3U`VK<2uLT_`lYN4r6Di5Rj(NXu!Q<(@l?K z-Dah=;=FvQk+|Q!bpW0}dNi$z@@ZOUi-x5QoymYdAJZcE@Ntf%JF-1ab!+f`!K$sp z%FiKUqT&q*`Fms*KT3aEQzt__BR6;EB}|Al+Uc%*;Ec?Y1v!`mGLI-K#2cwihu~{v zR%{8BuEp4yO}`db>8THs8nVA*uYLXpd!Sru8QQ;owha4s3F`mHr5MyHMtR`)-)WPd z;SXzMf60@mHYICXI@Aei{&DjH;X5o78P&VPvRHu}UVgJ_rYjmHk2BP3PNRWOU|+sF z;>|Ph&_K??0L_G6Zad?;P2l4ZxFO_+kVD(gCZM!y)d!=z!tHKH;qKUkX)YzNHjk3O z5nz}{UuSv`Ub_U&r-Urjll`Qr18PhGm->r5FSdD7RFDe5MYQ^A0=>jmJ6q_u#$?d- zEIkS=ti0&tvaFcv{@TDCD=hj9;O$fC>HO8vfzSgTc0x4rnm6DTHC zk88u02c_caYzlL>-Hm=KwZUHzM)bRjR9}(JchXTr;KJ{CcF6^OBJwF#O7v9c9`C6@7`YHdW5w%1h|)AYEwsc;~045m`1J~Lerz1 zi&6)r9B@kDo0OUd!DIg44P+M;+jvk*d&+~JZz_JWCH+`c{;}<>VTLPohLZ07a;J#6 zNQtfM{>pfA=O-l4YxR^69y18Y{`q@sx*RyARJ{kEdevGWe<9a=#y3wI1&Wv%FA%FY z`*m{*j=*MFmSc=yt0%Qf6J_R!Gq|f{6VY{>Yupy0t&N-DV+GVZ--uhjb_*XGoGSaA zrI_VA$cNZZt8*ZvU{(yCSks-llB&5X+&WM$0;#6s);1g{Q;dqXkTdY$u&E|*D{iR{ zsTo=GeBb1&6V_ZPNYa}1m{ktr3!Ze`K3Z=mh;;Ir4SThAu@F8P52an`n{QnMvOL^P z@{2&=>d@YFzP-E8Iy@htweCI+b=%9Aw(P#wB6QYHrIW8dxN8b}9dqqi>L=6d>C_1% zXeTOR)~5W8H<;5W=V(5r+jbw#VG_j>?0AG#_RsDNfxI3l7TH(kyU%~ayv5It80-|z zo@+Vtj{|8=E)>Fk(QD8d5(^M;BF23xJPW- zdjbEPqWRZG#1<>dChIQ`6r>(=v3tXZt6Ri<0Mm~Gj9+cLx+M(f^qoJ1WmQ)`@l~+* z_P<6iCmemIDm*7*`@?tC(P25PxAhCD!N9w#`C->}N#pJ(ZW8G&J8LWQ4e3S>uD=b$ zMXRIB$>Y2Ui7S+<%08dlzV>;C=~<1Tu}R%~)@B(Lv`D#{B$1noCZNZ#Q{`wE*1B%U zadEK1S|SdTensrj5RwI5?7iBxE$);)bccQCGSec(-Q5iBP#pift1xD9UkSc@G8BFL z%=7+!+;Y9KkR^LGsp?>CQkPm^TU|QcjChaHYREAFI-GzSQlXcbP@8Em9u%D?a{4mD zRXeGLDVAF+J35G%sFZF)U_h%B+iq~Pb2&4Uz7g@5xYUY@OX(tgy^nE zQ1r!d@Yw`qtDK*ujPrf_bkP$JvuNVsYh!v{CW2tJRQtHR8X3I}t~#jh>HfLiXu%?Y z7V(+MtHLve;fZTnauY^NckRerTNeo>rh4XsmS_#>^Eym}M9j~Ed{X~;<9G_Kz3 z&?nub(BZsZs%mnPOWjn@;_NI*r&27P30G7gtj|ygtZI&Rsi3^I@WtT)v_3O6&)c;J z%~%w?%=h}|1@lieYob_?xQN@3-~c~n-AD5)F%GK^xv0J8oa-H)GjCpGi-UgubI=fV zc>9_)eQ3-UPg~ic$c55>litl!ASU~$E z+W-8;NopQW9!bK}ck|RxFXFz@;kiU!-u6)z6LnP0>QsPj?;wbJSC`Uq0U%ak)*dEkB8Uo2t+h{>v=z zwZOLcZdWTwb4I-!GgQ;^xof~3aAl#}aZ#Ih6;N|qFnsdHMc~VN%_{|MW|J#nXC8TM z>rv&n=NIIV7{@D#sd4uumO`<1b)4>tBJs=X*%|CQbouMcBP$P8uq`OTy@;Pqe?#VP zl#V_OOxsz5-T0ko7KSF@2-j~ zY2(^(bV6oJSGFUSPEae@T@$O@ESEiOfJwr=I+;3|5?Hm!=w;p!cfc&LI_;E(nXmt^ z0WV1bb*z2!Xc5hEN@RJO;4>UvON;4l>wgKr%E47rN#8)oqa z9g;@i-l!%6G?6kRtv$St!e6zEbnv25q-O^(?e*#H%b&F&a5cxC!^ckDU~?PG9uBn5 zn)cwCKwi#~z#&^hj}_&7^@X5FmWvo6z<&Y|@h2DnYEe&ah_?BpP{h@ZX*1BeRrXyO zfmacVR}f{Z%^8yE29sWzkz-zHHi_H#+19bcS6&gS)ekc!t7BI8+xbf9Yx`Bu?z<2u z2{t9=?SW(8f#GaAAuJq8V_$s?m_KOOOp%a9(S~8Krl4XK=sS&@i)%Y%@1a>|RNaBc zqb$Q+WCgU+t;$|wljZn_UoWXm(#duLk4Y{XQQ3yjI{cW~nPlg}#- z;{Sktqd%bEyDJ7*$*yxGV%gy6rxkQOl=A$s_jz^BdEykYMqCf33b4Ro@DXOz!SbZoT2QPnv<9me%$3t7n^7cIS|3HW(*=KBQLGc%G$Y(Lqpq&Orh)d2 z=^6x<8d-4vvrG^3d&e)G#5_#EYa3QTSej>)yQynO@;3kuwM{szOJ*trCUz+JX{ETx zK13?C1d60#@VkAHD8NmN70fZTnodiGmV7|2Q534~j%%v^i)=hT)oBHYPdYoZ$>%`I z`W%%>I95GHiYYv+UjVe2+vO#NRR`JQ46kQ)!aPeN6+Z6870k8syZ_)H#yG@IM^iS7 z*z2TZSbrwft*4nxvhXHKk&5Pc@AU(8Ku~C^+MP>P$ zX$X~q3dm#ES2s&77~)O^gESJ!H4`bI5A+n&Z!GY1@Lh;a~p6R+bMFA<=)|S zx>{X`#{z%bzcM3?K;ptDyc4QxL!%yOC4r6;p(?EG=`F3I{Qj&F7%a8hw;|u>(rxR69n>TbRM-B zwxf-v8trc%$yI7yZywC?~F049YcM2!U2o}#DOhgXV~8QS<}65ucAC`Na(Cc z=`Z+h9D;S%0mPDaQ~N4LXTREsE47KuwH+(*0{I{^TTVNXoB4QY319dpD2vU!BT=M6 zmEf=6#I?lhB(hX2o%fqRoY>*FEZG)&Ck38-yjUv?86t`ESPXn_yWsB{cB(5%$I|bp z(?X!_Pdr2-2kpzc;KzoJE7%%(+jSHbQrH`_F_hU+&NW)+Feisb3Y1`<#+3{AnN!(` z{`&a^?J?K7*i*ZbZptC#4(PF{vmF|a(m2HE`MrIa9)vG00)&Ia=P; zg*?fs==o=Nc9)Pk>u@ZNsDtHOx=?i(A3^&$$QJRtdycb?m=xf0yO{09TE}cWi z0`0SS*UX8na~!sJ_gd{x#Dabq4bC&AsCu(^JZl0QIe&zF$NAE_-Q?+y_jF_ab=viO zG=-!nATYM~>mC-igGX|w&F_xP#6bQPH+>Nr>#cRzW@3|);ardYPP#IZT+z<|V4$)= z{qwt82En8xQnpsjh`IeNv+a#5c9D$HtlG`mt3>#(naX>tz21}h5fBq9!BUDltW{b@ z(Oc580;ONJDZlz<GaVs z!rm1ETc2#03=#Ig(zjzpUrJvyd<9N`^8RP%>#`$L`vn{JyKKlKMZWbbU$4p7JozQa z4Vt!JSd_>a_+~v|USYnff4EW)_?`s%WSi|u)kzy|h;QIQCVUXR5)zk?*(1tEdU#y# zaClVv5|tmLO_rdJ`IELn-Sr)X#Q$J%dQ?K_Pldq$?-B}$|AprGf1fY^SWP+Pvm$9$ z?Ta}33)6j{IeB)fVMNg-$)(y<*pf>2eG5`y(p9*!=3;zb{!y`BD&VH5X7}?xEgPX! zHQ}tI%@73Zt8)4VP=$Y=Wv?V$`1OmEHUFt~TokVVQ}t1AXl9yAL(BO2FmJz}9hWK# zh>n5L-Rc;)MSbwwWBzG(`W%64x}34%)e&tKlV!i5GXMl~H&C6rq{;uWb z6pODvZCBnayaf6-d9r+xvZSdIAUZZpKyQy14|SY}(XQIr6xQpyCiLh9+hUyhLi&{$ zFJo^)@Bde2UmX`^x9xvbP*5bKTUzNxTIoh|h@mBi2FU@Gh9RVpZlt@rL1O5Jk?t6f zl(-}6d(Qj&opbKJ{Plch56_mY#hPr>l*;N=qsAfog$YBFpuc!S@lXftt_c=E|t!wR9Rvr8ZdLJ>8*+ zWhr*YCVjUni|3Bp?*i{$Q#+3(qOiYRfGr@;k<1!v;A%f_znJ>tcd-gxKC((|xrNgE z2NkdgHv9;cx6~XwJmm6CeE;}gIaW!@vY{U2xn=8g#e$COIUdY95XR&9ncifc8b|dN zL0a%ujG)=pzGO}Ji`W@P{!?B|;9TW&9L8u7~sqJ0+dj=)l;g#+EAkvYt&Eaq=X1Aus z&7QA*+J+>fx_tH0=-PEAP4O7-;Tl0gcsbkF-LYynPFoA5PCq=OtI&fh>ClV)&MdTO zWPiUg3h%xR>d*m7)tyj7Ec7$n-VOTD-4fUN2rxX%L#xb8(njBWkW#MG-QZXVdaMkp ze9H!U@8SsTEW1p^xoAln^8cmhU{RzoPpo0fu`NBSq~DBFv(jI@k{n`z+^vRDVaB^F z%zsBm{l!rIS{c7rRvR@vA2Fr_I~jZ`2i9L*lmqNs3TcpWU;Is5)qJ|vK{!PCXb0c6 z&dRMy3R?SWU3N9FIgJEN8*Mr7ziFfJW&j{lf%_HazuLG^86SY$eAO5gQ_d3hazA~J z_*&dnf*Uec0}Bz|zif1LLEiu9pMrb0NRRvJ&a9u|HRByL|0q814>yepSI!h~%d}sO z77|bO9B|ULdEN8jA^jNA_RdZOKr`Ogo_MZ;)JjhGzZS;Ed$Vr-brU%9pH~Mr-bEZn}Q}Yhfe0wct-^R^Z*wM_yz-Iae^N2oicw)qNT2Q;oPA&0k zu_aM#bL5&1hMy-`W+pMU>UmA=eJ;}L!fUM&)1*%wGR4UsAsbp~e0dHSpaN!Gm~ebd zN#p&PL6w674sIO~i?;4b^#XHuiCi5sa3o|-4B*!w{2kXIksQJ`}8W54|^#N_f zsc$LvgdM`trLs1V4LMd*`b5u2BkN{Vk8QY>Z8EX95CADR%Y~1njH;JQyzS@amJ+y+|^%n3Ls32uJ;pXpDs%@Ya4_*KWwY z%~0Km$L0KzYDc=HS6gt}@54pP;psI>fx3p^l1oO{>kM(kh646Mj?#`jO{NsSq1ftnzSSB;cL&VA;o+27vKLF6K^5Ld|$ApqLvJs`*$_3;0WUiW@zwD9d zPsWnbOkr#AUJaX+qoy-pXN$f(OE*@R6>rlSFz#u1#;!{r&%%&60YA+)Ogx#;PJG#! zsld}V8jol{;yn?Oo92$rDIkM?U#;*HW1C7@#NnL1hKn;>6G6{l=ZgV7=V{vbphury zv$Uo>cvMEW{d}@mgEp?LZZ*v8fXaL(!*YFtHfga#k9j>E+=^CIt%EXE#8=g;H?#1e z6*)z!Bzm?eixq?J)Ee)7ou}}VGcwk7HT_=uJqmHZUg7;os-Pu1x)m@3Tg7gG-(+3LAbjl6a$c-~=57JJ{V+Ou=3r&bl4$yDP+|E2E_Z%Sg?W7 zj?hpP?bSiX*Um^t4=F77BuIpu9`4Pu%`9k}yHR4VvX-hWPwU6U)t5xZSTWBsQBG(& zX?Ln=2RIz>f6H`@oIoUtpTiIdDcPYH?LW3MDs5ZKRbLx%|bZOXNJubF|3=`KpCZotrlQOY3 zc&QpYl<;IdNH!*xGtB!l*dC)X?qO!VBo$-&$Jnbp@46T51}XakBY`iMH|1FMw7BWK zKijdzqROTj_fC}+PM)i`S>_jY`V`(z5>E9U+Zdv>BV);Sz+i z0zE|7^Z|=+-bY~$Ao>(+4w$@~A8cRPnG#z>4T8rXECm;_RWEHLd>6mcyySU&X;!Pf zX=|2v6RP{4*Barr^qk#nll$1ONGm#&SefixNwbcttEGbGFz`!Wuj24kgLL64221(T zg0*om5QaEqu^B~@MJl9IO9f(7gjf6V@U%Emtui(^y(2Kb|1Da$NS^x2Yz(z;i6%tG zBpdEW!|$`$)7HsoVDN&=qVT(ITVDvD9f_9<$GT@D-uot^ae=(ndbN9n4j$w*3q)lE zoBMeLBQw^oqJ3w>bmyfNpJmv86R9>f2vZ2W+Uq26VT6durbd!7q;t14T3+W%L`>xk z&{m$EEFJkFvC;J%uj3itrpZKe?OQih66Ca?AC#Tfq@o9|Og})Jvm=00CCEn+s93Jj z`PSIa9yoAJL$ct{d&57>X67wn(@v@$$J_7p+JHdPS*MwRS=WmdS&*?ph?ad$6u_FU z6%w0n_r)!XVq*F`iP<1F0sAHv7AFQVI$fU?tj#a933GLvVPs^+-yw*u)B)x?QjAFO zF*K`doN8TGNTWYy1kMAN2^ksQjMg5N@Pw@f* zEP~AVX${f=k7H})gVy>~Q^2%CwMaBJ zK)g<(Wrk=v@@pCb&;|P;Tr8!LLp)JmvflnUJ`)UB7m5a_qC(A%Mm~Z6>Qp#H_rUR^ zj8@ELwlRODaT!<#z*bq0)Dy*l$l^N=dt9SCMyi&t;>gb5i zI8o0(gSgf2lv_>#>xs=x!+U#_f_Spa*K~bS!vnyJ&eE($sZK$q>1}vQv=J=@s?Bu} z@3-?7+If7IlT_@xM!ZdD-ng$E8Zh}XWi$}Y%9F(T)Ambnw=T+{TIOL~EA}BpV4){v zJR(|2RgTBB@Mmpa?tWwh!k%;mI_j8J*PG?#0BIV6X1*JRT@dYtN$&P@cNZSMAM1mv<*jddUH3^?|AX{GI>O}vhd9%cDL6H=LN#5ZaQMW zH!eQ#0grqdN#FC=bO&k7g|ISccg>0q7J^dL6@Tuh_OD&$kX7)8MrNFYF9A{oUZGcd zxt2EhS9+X9i~9$Makf_1#AZ=|m;9(Sf8o&oeem=zkc;pFe?rH*u<9Ljr;hhZ@UYdYMWTZi>FsDlrE|+Z$*1*8L^CIA&pmJ@%>2 z5i^!)rgwhRYwru%d3VjcaWkdEFC@I#iX*w?70FY?!)$3EzjA&=^t4)48-K$)6H)4l z7CKne%fKw@DjME#YSB(JxouWv3i^#)@hri@n(kAYC0f<>U(w1&&KFg9B3y6L(RU-c z?ZaENt>L~Irp8ku9DM%y+ZH%#T=MX(FaHm6eHoA(K69@`{Edq$4B0Q^34gnKYZnI& zeTsq&&RzzmRB@}D#=>rRHVBl)4Tn9fe3=ECY!nA)>mDuTji+Vm@l@^SAj%)c(?3i! zD5X1t2}d@?Zsz$>&kB{N#?9(@uw&gb+8@oIXa)s$`u}tqUwijm)T3wlZ9u*w4J?r{ ztTVL&Suko{&X={6GEw;L-X3``t?xg^=iyo6>TsTMgS1Eo4!QkCqJ2@)QjYmPsr|gi zc!udExxns2#b>*tiU%0S#>Qje-=8SeDvz?*pryKjiGdsbX;3sVKab}z3lrj}GS4ub z#P9~|C1=`6|As@SYuuQ*d#L+=Oy|21*|NiFE9d*a=0?8i(Jj<(&%r^DyRdUKjO|kS z`X~bt#?&@Hre{awYD8BDp9?L|lVfeRXrSxW8a_z*E`?`cB#(L@&!vLw}<3P>(PFKQumyDk8cZdqi+vvOE}U0=hkQj1qG zCSS^F;_F(k|9-N81R<3<7bE` z7SGl`kW{2z2G5eBX)sESFjF`f_sq^e>21ce*$r(mfQwM-{P6jpAI*89pVopMVZb0h zL(I8CpsX5Lj#LEc=7=F1tjgA?>m>H1a8G9=#wu?my`kVAE{JN3AIDk5-6KnmWI5W{ zD5l+w(~T68_7$;_crVVD&(CRQlh?C1_mc8ve;Q}r{gYpVGsj3ichuphpXtlJ?MX#` zpFi7+WN9~tY0}?;MtV)bx`j;2p_^gXKv@q9IFOB=1WQ|7hIcs3YAF(TZF||`P3m;$8Qma&4|^akb}&f)lxrRJHcn9$IGt6l`%+D2ikm_FNBts#0+i_Ge6m1GAMC^;vy(yqzn zetd;ixRkL2UkmmNaM~ApeZ8ia2eX9EBF!57hjKH3JfN!bT+BslIw92d{4Zh`Zu7j~ z+d~8Vw3!PeadxWEq6%$5KYojChVBsS5bp}872gciMh^eH9^ z4x?T@Y6DgYk03g8qe z;#5FC{`YG|Ui%C!%@(qwJJ$*4%;4PRr=GR%|jd6*G~ui?$n+ws#)U*uD2e!rNB z(4hEt$;Bs24k=2TSWiM}55H}rQhb^487H3@MTJ6oTZQI+^r(*lF zKHjF47O}q!FE4|=!OJ1(4zME6+%gV}9!XeB$h}E;4{7Doi$#m^c+yV-hK#HFy{m-SA2+9vQQl%a=!nppqZ*a<-Udza`E06sQb}njpH?J4FJMPaqk__)rNp$&UpHtyVNSYlwO=GwrY|!NUBKqgFd9iG zr-LKN2fOTP;t}onA&A;fU|rV3w%RTrDvU+UuX3 z8TIybq7ZL+Mk@Fi%Q{t2ZCwrx!RqWqG-msGcH3@5*dLkKBKV3E|5GY^J9EBrOp) z%gyYjjPEn%K*=#jOBNK}R3}RIRZNpi7j-W|r|*bgxPT(Z5M}DrLumkj2X2mM(8`(W z=vbS`#l<3VXxiF}o74P^pfA~pDoBIN>~)O@#>C+`I~w}ukv!H$Lyy2aV2I>^=RGq& z41pDSyjZrqadSttxJ-eRPWlVE6hdP=US(P%JOap8%y~mq-FdFs=*3EI{xmE=qcXQO z79hr^#l?~XtYFNG|6@iI#|B{a^;5ns+NTk7xi2Z}`jMi8^bW z%Au`kp{TS_XHgmKVgXA@54(m}Hyt189bfn>X?AwX1!^2b@2In; zuh_-Wj*DhS-dc!e%7@jUG8XeAB&LUX=CdQBuSO6H+HYoZ;qbp8I!0#l&XyPGd);R_~F^$zV_2}4>3}3j5Au@lQkHXl-rsbBTLoT{U6H#=m zqtQl$GDSR5f&Rla16#RS>!SWhfI^g#C4ms4D8;X!qLi=7h^P%5hcy4{l~ zDbx$S44x`-Jlut}Zel`uGs3=l*`YRb-r-MzD6?D2QAX3$QP%9tubkt%>OZgG-6^ha75M4MAYYbDAHiFdme>dT`Y z%xD%9=lpo<9+gCoLvcKJX0a*WKCYmSziq6rm(jIRXYDBiuZRwWgDQ_}4ZIaK@YHp{ zv|SY_=dwFSIe#8vv$uY+;8bAZOfvWScf)DckX!5oKbS;pda(mRvX#u$RIKF{SoWo= z5B=3AmhPYeAE$R{iVO|#hG9nYFOI7P&*Z+f`#omcB}y&$pbQeb+Ui;6!)FM{L0OkO zQBvuV{Iy_Am*1wg8^jb0e7aA;X%*TOU(r_m>=cmrIATHo?Rs-VN}>1@w55WcnD|*X zGLI`0RiyrYIjRZ3I2VOshcE`&VPu=pH%A^f7Kq$@`AXB zz22a-`$;uwjrpDZzB}>_h_10!=QB zmi0(P22^^kw(6=;!X{wyq#|X-m2G7_4=O?Ce2yC)+F0n1l}7@l6RUG{GA=#adZqGb zeI8et<3a&~x4CIIPsam(TLy$v_dl4Ke_?t4KQnbW`Au@k)odzcRG2A3>MH8fnQ$XH zC8CsgkL~sxyYrpXm@xC-KOe~&1$FYsEy4~xHxysSBKSl0OeYK=`81f3~Fm>6Ric{@oxK@_!uu z4}*wk=Fb}=AuRLHZy|`7yXk+{?jbJz_2B>QxBc_v|GWGDee!=VJJ?ETI;-t!Me#86 zPyp=iI;kzK>%91|k?EH>tjJ0=vxmao_J?Cu6X!jGgXg(lOl@df7rcnzs+Hp37o6N! z@1AJeNcrl0_^rpN?`>0!UvKZ6cMYm$!rdcz?t}5>=G_jqfex0{6+D)Hg!|XK!2EXX z)G|HsypTR4RM^z2ea`<^z2kjwSw9OUaiBu)pHIs5Z@_?S(D8xu`0_!u`ZpUMTu6&B zO!G|QC>fr>4{8~|x{D@eYZ(P>T3R9J-YGM(j>XE{b4{@c z(3&tQ2F(29)&+!x#)jb^(_PdAR4gf0t1g>p#`Q{qz#qT3drZeq`pK^O#GhX|gfzvs zO46l#%Vk{Tr#L%YdD`V-Izf8H%84z!a4B{e04j&Ks4sN$w>iV32G_zaZ0ND!;;(-E zSP9Kuz6zhjO_R04nOeIzx)KND4IMARy((!yrA#Gz$nNk?7H5PJ=~=$8#5r8XJs=1aTF+xLkR!k7%Zr9BaGIMw*+{iEp|1n ztq9)9$#Br@VvM{;X&C?LwE%#e07#q%mnKcW znW~j|KW=)shQ*cB*TjS^b?rsCCl%Ps#U zs&0tl>mr^NVak2TRWYtCrN`Bqjlvy7jqM*T8R`z!gdh6oM)Z8-PgZHanet}`AFOa* z$=lLSBFe&+ajQ4iY(w9aGxsN48l!6tAtzb4w;N?k4SeYu$}-Htq`d+xWT(ErMwpPFW(uLrUZu^J>hpF@DytEvU$7A;ge_y9 zx|p>5jj>ON^_k?F{mjBnNI=;@}*VH!(_HUaj5>|gP4veVwgaAMZtagsDA7{p3_+pTj9B^dJC#>5Sk0(?u;d7Cy*CNBA%888|3m`ph*(j)=Nm z*lrJHNuuz7_F3J1SoR@6JHpfMDR)~Vj4HR`(CqcI)*Mep0b7iSzAgd}Hs*CEo?ID+ z6c3+=jDht&;TXcN!`(E3Vfk2FMGov-KD(y2U-?Ig)u3i0!0fgP(C$!kFTrao&Zu`%a{nX}krd9K2>q zEG{(JSciEGy4kp)x4Zh`5i{+w_PN)lYbIx^82c`n=JoSeDC^Due9Yue{}8N1<4u9u3?DOXC4ns`xLP&iZdyDE3tM50gUdPh>+3f!8HziE* qSC0@$4~X4)OB(Oj{#z1wOI|2HA%`Bq+xlOKKWT9Vv0@Q@@Ban{EW1De From 6245fed240abb80ccaed43e08f6ad2b327e12cc4 Mon Sep 17 00:00:00 2001 From: Haonan Date: Thu, 2 Feb 2017 11:28:45 -0800 Subject: [PATCH 137/370] rotate_layer python interface fixes --- paddle/gserver/layers/FeatureMapExpandLayer.cpp | 3 +++ paddle/gserver/layers/GruStepLayer.cpp | 4 ++-- paddle/gserver/layers/RotateLayer.cpp | 2 ++ python/paddle/trainer/config_parser.py | 6 +++--- python/paddle/trainer_config_helpers/layers.py | 14 ++++++++------ .../tests/layers_test_config.py | 2 +- 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/paddle/gserver/layers/FeatureMapExpandLayer.cpp b/paddle/gserver/layers/FeatureMapExpandLayer.cpp index d023074c521675..4b685812aac247 100644 --- a/paddle/gserver/layers/FeatureMapExpandLayer.cpp +++ b/paddle/gserver/layers/FeatureMapExpandLayer.cpp @@ -95,6 +95,9 @@ void FeatureMapExpandLayer::forward(PassType passType) { void FeatureMapExpandLayer::backward(const UpdateCallback& callback) { MatrixPtr inGrad = getInputGrad(0); + if (NULL == inGrad) { + return; + } MatrixPtr outGrad = getOutputGrad(); size_t batchSize = getInput(0).getBatchSize(); int imgSize = inGrad->getWidth(); diff --git a/paddle/gserver/layers/GruStepLayer.cpp b/paddle/gserver/layers/GruStepLayer.cpp index ce692c490881c9..4a1006aa941f39 100644 --- a/paddle/gserver/layers/GruStepLayer.cpp +++ b/paddle/gserver/layers/GruStepLayer.cpp @@ -68,8 +68,8 @@ bool GruStepLayer::init(const LayerMap& layerMap, if (!Layer::init(layerMap, parameterMap)) return false; CHECK_EQ(2U, inputLayers_.size()); - CHECK_EQ(getSize() * getSize() * 3, parameters_[1]->getSize()); - weight_.reset(new Weight(getSize(), getSize() * 3, parameters_[1])); + CHECK_EQ(getSize() * getSize() * 3, parameters_[0]->getSize()); + weight_.reset(new Weight(getSize(), getSize() * 3, parameters_[0])); if (biasParameter_.get() != NULL) { CHECK_EQ(getSize() * 3, biasParameter_->getSize()); diff --git a/paddle/gserver/layers/RotateLayer.cpp b/paddle/gserver/layers/RotateLayer.cpp index 1cdd8366d5ddff..d928f1d93de0ee 100644 --- a/paddle/gserver/layers/RotateLayer.cpp +++ b/paddle/gserver/layers/RotateLayer.cpp @@ -25,6 +25,8 @@ bool RotateLayer::init(const LayerMap& layerMap, CHECK_EQ(inputLayers_.size(), 1UL); height_ = config_.height(); width_ = config_.width(); + CHECK_GT(height_, 0); + CHECK_GT(width_, 0); return true; } diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index 62efe5fca0caca..b02af991dc577e 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -1969,13 +1969,13 @@ def __init__(self, name, size, inputs, **xargs): @config_layer('rotate') class RotateLayer(LayerBase): - def __init__(self, name, inputs, height, device=None): + def __init__(self, name, inputs, height, width, device=None): super(RotateLayer, self).__init__( name, 'rotate', 0, inputs=inputs, device=device) config_assert( len(self.inputs) == 1, 'RotateLayer must have one and only one input') - self.config.height = height + self.set_layer_height_width(height, width) self.set_layer_size(self.get_input_layer(0).size) @@ -3007,7 +3007,7 @@ def __init__(self, config_assert(input_layer1.size == size, 'input_layer1.size != layer.size') self.config.active_gate_type = active_gate_type - self.create_input_parameter(1, size * size * 3, [size, size * 3]) + self.create_input_parameter(0, size * size * 3, [size, size * 3]) self.create_bias_parameter(bias, size * 3) diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 19f7ec3186596f..2636f6cc1a1653 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -1677,22 +1677,23 @@ def trans_layer(input, name=None, layer_attr=None): @wrap_name_default() @layer_support() -def rotate_layer(input, height, name=None, layer_attr=None): +def rotate_layer(input, height, width, name=None, layer_attr=None): """ - A layer for rotation (clock-wise), usually used when the input sample - is some image or map. + A layer for rotating 90 degrees (clock-wise), usually used when the input sample + is some image or feature map. .. math:: - y(j,i) = x(M-i-1,j) + y(j,i,:) = x(M-i-1,j,:) - where :math:`x` is (M x N) input, and :math:`y` is (N x M) output. + where :math:`x` is (M x N x C) input, and :math:`y` is (N x M x C) output. The example usage is: .. code-block:: python rot = rotate_layer(input=layer, - height=100) + height=100, + width=100) :param input: Input layer. :type input: LayerOutput @@ -1709,6 +1710,7 @@ def rotate_layer(input, height, name=None, layer_attr=None): l = Layer( name=name, height=height, + width=width, type=LayerType.ROTATE_LAYER, inputs=[input.name], **ExtraLayerAttribute.to_kwargs(layer_attr)) diff --git a/python/paddle/trainer_config_helpers/tests/layers_test_config.py b/python/paddle/trainer_config_helpers/tests/layers_test_config.py index 1964e6f113e642..e6cd35ee761d1a 100644 --- a/python/paddle/trainer_config_helpers/tests/layers_test_config.py +++ b/python/paddle/trainer_config_helpers/tests/layers_test_config.py @@ -39,7 +39,7 @@ assert z1.size > 0 y2 = fc_layer(input=y, size=15) -z2 = rotate_layer(input=y2, height=5) +z2 = rotate_layer(input=y2, height=5, width=3) cos1 = cos_sim(a=x1, b=y1) cos3 = cos_sim(a=x1, b=y2, size=3) From 7c04096ecbeb3f7846fa2b9b5724706be7fb54a9 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Fri, 3 Feb 2017 10:32:58 +0800 Subject: [PATCH 138/370] Remove compile warning on clang 8.0 in BufferArg.h * CHECK_XX in glog need the left and right values are both signed or unsigned integer. So we could use integer literal syntax in C/C++ to make literal unsigned or signed. Add suffix 'UL' means unsigned long. --- paddle/function/BufferArg.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index 177d20005b54b8..349b21e7e64064 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -189,8 +189,8 @@ class SequenceIdArg : public BufferArg { SequenceIdArg(const TensorShape& shape, ArgType argType = UNSPECIFIED) : BufferArg(VALUE_TYPE_INT32, shape, argType) { bufferType_ = TENSOR_SEQUENCE_ID; - CHECK_EQ(shape_.ndims(), (size_t)1); - CHECK_GT(shape_[0], 1); + CHECK_EQ(shape_.ndims(), 1UL); + CHECK_GT(shape_[0], 1UL); numSeqs_ = shape_[0] - 1; } @@ -199,7 +199,7 @@ class SequenceIdArg : public BufferArg { ArgType argType = UNSPECIFIED) : BufferArg(buf, VALUE_TYPE_INT32, shape, argType) { bufferType_ = TENSOR_SEQUENCE_ID; - CHECK_EQ(shape_.ndims(), (size_t)1); + CHECK_EQ(shape_.ndims(), 1UL); numSeqs_ = shape_[0] - 1; } @@ -280,9 +280,9 @@ class SparseMatrixArg : public BufferArg { type_(static_cast(type)) { bufferType_ = TENSOR_SPARSE; CHECK((valueType == VALUE_TYPE_FLOAT) || (valueType == VALUE_TYPE_DOUBLE)); - CHECK_EQ(shape_.ndims(), (size_t)2); - CHECK_EQ(row_.shape().ndims(), (size_t)1); - CHECK_EQ(col_.shape().ndims(), (size_t)1); + CHECK_EQ(shape_.ndims(), 2UL); + CHECK_EQ(row_.shape().ndims(), 1UL); + CHECK_EQ(col_.shape().ndims(), 1UL); if (format_ == T_SPARSE_CSR) { CHECK_EQ(nnz, col.shape()[0]); } else if (format_ == T_SPARSE_CSC) { @@ -304,7 +304,7 @@ class SparseMatrixArg : public BufferArg { type_(static_cast(type)) { bufferType_ = TENSOR_SPARSE; CHECK((valueType == VALUE_TYPE_FLOAT) || (valueType == VALUE_TYPE_DOUBLE)); - CHECK_EQ(shape_.ndims(), (size_t)2); + CHECK_EQ(shape_.ndims(), 2UL); /// len of row_ : height + 1 (CSR) or nnz (CSC), buf_ == nullptr row_ = (format_ == T_SPARSE_CSR @@ -325,7 +325,7 @@ class SparseMatrixArg : public BufferArg { CHECK(buf_); CHECK(valueType_ == DataType::value); // CHECK(deviceType_ == DType); - CHECK_EQ(2, shape_.ndims()); + CHECK_EQ(2UL, shape_.ndims()); return typename Tensor::SparseMatrix( reinterpret_cast(buf_), reinterpret_cast(row_.data()), From 2859532df01ff4494a1a8e60fde442e606ff435e Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Fri, 3 Feb 2017 12:45:22 +0800 Subject: [PATCH 139/370] Using override keyword in Layer --- .../RecurrentGradientMachine.cpp | 7 +- paddle/gserver/layers/AddtoLayer.h | 7 +- paddle/gserver/layers/AgentLayer.h | 25 +++--- paddle/gserver/layers/AverageLayer.h | 9 +-- paddle/gserver/layers/BatchNormBaseLayer.h | 3 +- .../gserver/layers/BatchNormalizationLayer.h | 9 ++- paddle/gserver/layers/BilinearInterpLayer.h | 7 +- paddle/gserver/layers/BlockExpandLayer.h | 7 +- paddle/gserver/layers/CRFDecodingLayer.h | 7 +- paddle/gserver/layers/CRFLayer.h | 7 +- paddle/gserver/layers/CTCLayer.h | 7 +- paddle/gserver/layers/ConcatenateLayer.cpp | 14 ++-- paddle/gserver/layers/ConvBaseLayer.h | 3 +- paddle/gserver/layers/ConvShiftLayer.cpp | 7 +- .../gserver/layers/ConvexCombinationLayer.cpp | 7 +- paddle/gserver/layers/CosSimLayer.h | 7 +- paddle/gserver/layers/CosSimVecMatLayer.cpp | 7 +- paddle/gserver/layers/CostLayer.cpp | 9 +-- paddle/gserver/layers/CostLayer.h | 79 ++++++++++++------- paddle/gserver/layers/CudnnBatchNormLayer.h | 7 +- paddle/gserver/layers/CudnnConvLayer.h | 7 +- paddle/gserver/layers/CudnnPoolLayer.h | 7 +- paddle/gserver/layers/DataLayer.h | 8 +- paddle/gserver/layers/DataNormLayer.h | 7 +- paddle/gserver/layers/EosIdCheckLayer.cpp | 8 +- paddle/gserver/layers/ExpandConvBaseLayer.h | 3 +- paddle/gserver/layers/ExpandConvLayer.h | 7 +- paddle/gserver/layers/ExpandConvTransLayer.h | 7 +- paddle/gserver/layers/ExpandLayer.h | 7 +- .../gserver/layers/FeatureMapExpandLayer.cpp | 7 +- paddle/gserver/layers/FullyConnectedLayer.h | 9 ++- paddle/gserver/layers/GatedRecurrentLayer.h | 13 +-- paddle/gserver/layers/GetOutputLayer.cpp | 7 +- paddle/gserver/layers/GruStepLayer.cpp | 7 +- .../gserver/layers/HierarchicalSigmoidLayer.h | 7 +- paddle/gserver/layers/InterpolationLayer.cpp | 7 +- paddle/gserver/layers/LstmLayer.h | 13 +-- paddle/gserver/layers/LstmStepLayer.cpp | 7 +- paddle/gserver/layers/MDLstmLayer.cpp | 7 +- paddle/gserver/layers/MaxIdLayer.cpp | 8 +- paddle/gserver/layers/MaxLayer.h | 9 +-- paddle/gserver/layers/MaxOutLayer.h | 7 +- paddle/gserver/layers/MixedLayer.h | 15 ++-- paddle/gserver/layers/MultiplexLayer.cpp | 7 +- paddle/gserver/layers/NCELayer.cpp | 9 ++- paddle/gserver/layers/NormLayer.h | 10 ++- paddle/gserver/layers/NormProjectionLayer.h | 7 +- paddle/gserver/layers/OuterProdLayer.cpp | 7 +- paddle/gserver/layers/PadLayer.h | 7 +- paddle/gserver/layers/ParameterReluLayer.h | 7 +- paddle/gserver/layers/PoolLayer.h | 3 +- paddle/gserver/layers/PoolProjectionLayer.h | 4 +- paddle/gserver/layers/PowerLayer.cpp | 7 +- paddle/gserver/layers/PrintLayer.cpp | 4 +- paddle/gserver/layers/PriorBox.cpp | 7 +- paddle/gserver/layers/RecurrentLayer.cpp | 13 +-- paddle/gserver/layers/RecurrentLayerGroup.cpp | 9 ++- paddle/gserver/layers/ResizeLayer.cpp | 9 ++- paddle/gserver/layers/SamplingIdLayer.cpp | 8 +- paddle/gserver/layers/ScalingLayer.cpp | 7 +- .../layers/SelectiveFullyConnectedLayer.h | 9 ++- paddle/gserver/layers/SequenceConcatLayer.cpp | 7 +- .../layers/SequenceLastInstanceLayer.cpp | 9 +-- paddle/gserver/layers/SequencePoolLayer.h | 9 +-- .../gserver/layers/SequenceReshapeLayer.cpp | 9 +-- paddle/gserver/layers/SlopeInterceptLayer.cpp | 9 +-- .../gserver/layers/SpatialPyramidPoolLayer.h | 9 +-- paddle/gserver/layers/SubSequenceLayer.cpp | 9 +-- paddle/gserver/layers/SumToOneNormLayer.cpp | 9 +-- paddle/gserver/layers/TensorLayer.h | 9 +-- paddle/gserver/layers/TransLayer.h | 7 +- paddle/gserver/layers/ValidationLayer.h | 23 +++--- paddle/gserver/layers/WarpCTCLayer.h | 7 +- 73 files changed, 369 insertions(+), 300 deletions(-) diff --git a/paddle/gserver/gradientmachines/RecurrentGradientMachine.cpp b/paddle/gserver/gradientmachines/RecurrentGradientMachine.cpp index a9a9f4f903e305..2ab964b8fc2e08 100644 --- a/paddle/gserver/gradientmachines/RecurrentGradientMachine.cpp +++ b/paddle/gserver/gradientmachines/RecurrentGradientMachine.cpp @@ -155,7 +155,8 @@ class BootBiasLayer : public Layer { public: 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 (biasParameter_) { @@ -174,7 +175,7 @@ class BootBiasLayer : public Layer { } } - virtual void forward(PassType passType) { + void forward(PassType passType) override { if (biases_) { MatrixPtr outV = getOutputValue(); outV->addBias(*(biases_->getW()), 1); @@ -182,7 +183,7 @@ class BootBiasLayer : public Layer { } } - virtual void backward(const UpdateCallback& callback) { + void backward(const UpdateCallback& callback) override { if (biases_) { backwardActivation(); biases_->getWGrad()->collectBias(*getOutputGrad(), 1); diff --git a/paddle/gserver/layers/AddtoLayer.h b/paddle/gserver/layers/AddtoLayer.h index 53d3f99cdd3439..4e98c174b46276 100644 --- a/paddle/gserver/layers/AddtoLayer.h +++ b/paddle/gserver/layers/AddtoLayer.h @@ -44,19 +44,20 @@ class AddtoLayer : public Layer { /** * Intialization of AddtoLayer. */ - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; /** * Forward propagation. * @note There is no weight matrix for each input, * because it just a simple add operation. */ - void forward(PassType passType); + void forward(PassType passType) override; /** * Backward propagation. */ - void backward(const UpdateCallback& callback = nullptr); + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/AgentLayer.h b/paddle/gserver/layers/AgentLayer.h index 41683ad6712d5d..b6dac7ae6fec2d 100644 --- a/paddle/gserver/layers/AgentLayer.h +++ b/paddle/gserver/layers/AgentLayer.h @@ -35,7 +35,8 @@ class AgentLayer : public Layer { ~AgentLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; // if *numSamples* set, // real layer output will only use first *numSamples* rows @@ -44,8 +45,8 @@ class AgentLayer : public Layer { numSamples_ = numSamples; } - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr) {} + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override {} }; /** @@ -56,8 +57,8 @@ class SequenceAgentLayer : public AgentLayer { explicit SequenceAgentLayer(const LayerConfig& config) : AgentLayer(config) {} ~SequenceAgentLayer() {} - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr) {} + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override {} }; /** @@ -78,7 +79,8 @@ class GatherAgentLayer : public Layer { virtual ~GatherAgentLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; // call before addRealLayer void copyIdAndSequenceInfo(const Argument& input, @@ -88,8 +90,8 @@ class GatherAgentLayer : public Layer { // add one real layer, can call many times void addRealLayer(LayerPtr layer) { realLayers_.push_back(layer); } - void forward(PassType passType); - void backward(const UpdateCallback& callback); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback) override; }; /** @@ -133,7 +135,8 @@ class ScatterAgentLayer : public Layer { 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 @@ -182,8 +185,8 @@ class ScatterAgentLayer : public Layer { numSequences_ = numSequences; } - void forward(PassType passType); - void backward(const UpdateCallback& callback); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback) override; }; /** diff --git a/paddle/gserver/layers/AverageLayer.h b/paddle/gserver/layers/AverageLayer.h index b3c4ecec8bc6f5..621e1d7bb12ec5 100644 --- a/paddle/gserver/layers/AverageLayer.h +++ b/paddle/gserver/layers/AverageLayer.h @@ -38,12 +38,11 @@ class AverageLayer : public SequencePoolLayer { explicit AverageLayer(const LayerConfig& 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); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; protected: MatrixPtr outMtx_; diff --git a/paddle/gserver/layers/BatchNormBaseLayer.h b/paddle/gserver/layers/BatchNormBaseLayer.h index 75bda95de1472b..230bafc31d96bb 100644 --- a/paddle/gserver/layers/BatchNormBaseLayer.h +++ b/paddle/gserver/layers/BatchNormBaseLayer.h @@ -52,7 +52,8 @@ class BatchNormBaseLayer : public Layer { */ 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 diff --git a/paddle/gserver/layers/BatchNormalizationLayer.h b/paddle/gserver/layers/BatchNormalizationLayer.h index 195acbbfc58db8..f6115801fc6b34 100644 --- a/paddle/gserver/layers/BatchNormalizationLayer.h +++ b/paddle/gserver/layers/BatchNormalizationLayer.h @@ -33,9 +33,10 @@ class BatchNormalizationLayer : public BatchNormBaseLayer { ~BatchNormalizationLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; protected: /// Epsilon value used in the batch normalization formula. @@ -58,7 +59,7 @@ class BatchNormalizationLayer : public BatchNormBaseLayer { /// to batch, channels* imagePixels. void shrinkMat(const MatrixPtr& in, MatrixPtr& out); - void onPassEnd() { firstTest_ = true; } + void onPassEnd() override { firstTest_ = true; } MatrixPtr tmpMat_, tmpGrad_; MatrixPtr expandedIn_, expandedOut_; diff --git a/paddle/gserver/layers/BilinearInterpLayer.h b/paddle/gserver/layers/BilinearInterpLayer.h index 4ff4b0ea793dc9..27c269f2781c99 100644 --- a/paddle/gserver/layers/BilinearInterpLayer.h +++ b/paddle/gserver/layers/BilinearInterpLayer.h @@ -38,9 +38,10 @@ class BilinearInterpLayer : public Layer { virtual ~BilinearInterpLayer() {} size_t getSize(); - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/BlockExpandLayer.h b/paddle/gserver/layers/BlockExpandLayer.h index cc96fdd03fcac6..8f347400e60ec8 100644 --- a/paddle/gserver/layers/BlockExpandLayer.h +++ b/paddle/gserver/layers/BlockExpandLayer.h @@ -58,10 +58,11 @@ class BlockExpandLayer : public Layer { ~BlockExpandLayer() {} - virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - virtual void forward(PassType passType); - virtual void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/CRFDecodingLayer.h b/paddle/gserver/layers/CRFDecodingLayer.h index 1fd444ad10e71d..3cbcac6cf62dec 100644 --- a/paddle/gserver/layers/CRFDecodingLayer.h +++ b/paddle/gserver/layers/CRFDecodingLayer.h @@ -32,9 +32,10 @@ namespace paddle { class CRFDecodingLayer : public CRFLayer { public: explicit CRFDecodingLayer(const LayerConfig& config) : CRFLayer(config) {} - virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); - virtual void forward(PassType passType); - virtual void backward(const UpdateCallback& callback); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; + void forward(PassType passType) override; + void backward(const UpdateCallback& callback) override; protected: std::unique_ptr crf_; diff --git a/paddle/gserver/layers/CRFLayer.h b/paddle/gserver/layers/CRFLayer.h index d21b32b68c1a40..de36a85083b6b2 100644 --- a/paddle/gserver/layers/CRFLayer.h +++ b/paddle/gserver/layers/CRFLayer.h @@ -29,9 +29,10 @@ namespace paddle { class CRFLayer : public Layer { public: explicit CRFLayer(const LayerConfig& config) : Layer(config) {} - virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); - virtual void forward(PassType passType); - virtual void backward(const UpdateCallback& callback); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; + void forward(PassType passType) override; + void backward(const UpdateCallback& callback) override; protected: size_t numClasses_; diff --git a/paddle/gserver/layers/CTCLayer.h b/paddle/gserver/layers/CTCLayer.h index 70d429bad656ad..f7a515f312d075 100644 --- a/paddle/gserver/layers/CTCLayer.h +++ b/paddle/gserver/layers/CTCLayer.h @@ -22,10 +22,11 @@ namespace paddle { class CTCLayer : public Layer { public: explicit CTCLayer(const LayerConfig& config) : Layer(config) {} - virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); - virtual void forward(PassType passType); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; + void forward(PassType passType) override; 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, const Argument& softmaxSeqs, const Argument& labelSeqs); diff --git a/paddle/gserver/layers/ConcatenateLayer.cpp b/paddle/gserver/layers/ConcatenateLayer.cpp index d19adace7d58af..c5fc4cf4f81a55 100644 --- a/paddle/gserver/layers/ConcatenateLayer.cpp +++ b/paddle/gserver/layers/ConcatenateLayer.cpp @@ -28,10 +28,11 @@ class ConcatenateLayer : public Layer { ~ConcatenateLayer() {} - virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - virtual void forward(PassType passType); - virtual void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(concat, ConcatenateLayer); @@ -101,10 +102,11 @@ class ConcatenateLayer2 : public Layer { ~ConcatenateLayer2() {} - virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - virtual void forward(PassType passType); - virtual void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; protected: std::vector> projections_; diff --git a/paddle/gserver/layers/ConvBaseLayer.h b/paddle/gserver/layers/ConvBaseLayer.h index aedf4100e32fa1..e9d15d94f806a5 100644 --- a/paddle/gserver/layers/ConvBaseLayer.h +++ b/paddle/gserver/layers/ConvBaseLayer.h @@ -80,7 +80,8 @@ class ConvBaseLayer : public Layer { public: 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 diff --git a/paddle/gserver/layers/ConvShiftLayer.cpp b/paddle/gserver/layers/ConvShiftLayer.cpp index 9bfb1ab7a47b11..002be415691f0b 100644 --- a/paddle/gserver/layers/ConvShiftLayer.cpp +++ b/paddle/gserver/layers/ConvShiftLayer.cpp @@ -47,10 +47,11 @@ class ConvShiftLayer : public Layer { ~ConvShiftLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(conv_shift, ConvShiftLayer); diff --git a/paddle/gserver/layers/ConvexCombinationLayer.cpp b/paddle/gserver/layers/ConvexCombinationLayer.cpp index ed57f2af3c6455..32eb3bf604acaa 100644 --- a/paddle/gserver/layers/ConvexCombinationLayer.cpp +++ b/paddle/gserver/layers/ConvexCombinationLayer.cpp @@ -49,10 +49,11 @@ class ConvexCombinationLayer : public Layer { ~ConvexCombinationLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(convex_comb, ConvexCombinationLayer); diff --git a/paddle/gserver/layers/CosSimLayer.h b/paddle/gserver/layers/CosSimLayer.h index 5dcc5d8a5b4dc7..65549626098f08 100644 --- a/paddle/gserver/layers/CosSimLayer.h +++ b/paddle/gserver/layers/CosSimLayer.h @@ -38,10 +38,11 @@ class CosSimLayer : public Layer { ~CosSimLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/CosSimVecMatLayer.cpp b/paddle/gserver/layers/CosSimVecMatLayer.cpp index ad490b0b8c4656..5f652319e56202 100644 --- a/paddle/gserver/layers/CosSimVecMatLayer.cpp +++ b/paddle/gserver/layers/CosSimVecMatLayer.cpp @@ -46,10 +46,11 @@ class CosSimVecMatLayer : public Layer { ~CosSimVecMatLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(cos_vm, CosSimVecMatLayer); diff --git a/paddle/gserver/layers/CostLayer.cpp b/paddle/gserver/layers/CostLayer.cpp index 7e9519f6b3af50..998b8d7d3034cb 100644 --- a/paddle/gserver/layers/CostLayer.cpp +++ b/paddle/gserver/layers/CostLayer.cpp @@ -367,8 +367,6 @@ void LambdaCost::backward(const UpdateCallback& callback) { getInputGrad(0)->add(*marginGrad_); } -void LambdaCost::onPassEnd() {} - void LambdaCost::calcGrad(const real* outputScore, const real* score, real* gradData, @@ -611,14 +609,15 @@ class SumCostLayer : public Layer { public: 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); if (!ret) return ret; CHECK_EQ(inputLayers_.size(), 1UL); return true; } - virtual void forward(PassType passType) { + void forward(PassType passType) override { Layer::forward(passType); const MatrixPtr& input = getInputValue(0); @@ -629,7 +628,7 @@ class SumCostLayer : public Layer { 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); } }; diff --git a/paddle/gserver/layers/CostLayer.h b/paddle/gserver/layers/CostLayer.h index 7f73bdb3f7d63e..b3045e0b31308a 100644 --- a/paddle/gserver/layers/CostLayer.h +++ b/paddle/gserver/layers/CostLayer.h @@ -32,15 +32,16 @@ class CostLayer : public Layer { public: 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 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, Argument& label, @@ -68,11 +69,14 @@ class MultiClassCrossEntropy : public CostLayer { explicit MultiClassCrossEntropy(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 backwardImp(Matrix& outputValue, Argument& label, Matrix& outputGrad); + void backwardImp(Matrix& outputValue, + Argument& label, + Matrix& outputGrad) override; }; /** @@ -95,11 +99,14 @@ class MultiClassCrossEntropyWithSelfNorm : public CostLayer { explicit MultiClassCrossEntropyWithSelfNorm(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 backwardImp(Matrix& outputValue, Argument& label, Matrix& outputGrad); + void backwardImp(Matrix& outputValue, + Argument& label, + Matrix& outputGrad) override; protected: MatrixPtr sftMaxSum_; @@ -117,11 +124,14 @@ class SoftBinaryClassCrossEntropy : public CostLayer { explicit SoftBinaryClassCrossEntropy(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 backwardImp(Matrix& outputValue, Argument& label, Matrix& outputGrad); + void backwardImp(Matrix& outputValue, + Argument& label, + Matrix& outputGrad) override; protected: MatrixPtr targetPerDim_; @@ -139,11 +149,14 @@ class SumOfSquaresCostLayer : public CostLayer { explicit SumOfSquaresCostLayer(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 backwardImp(Matrix& outputValue, Argument& label, Matrix& outputGrad); + void backwardImp(Matrix& outputValue, + Argument& label, + Matrix& outputGrad) override; }; /** @@ -162,17 +175,18 @@ class RankingCost : public Layer { public: 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 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)output; @@ -214,17 +228,16 @@ class LambdaCost : public Layer { public: 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 getScoreLayer() { return inputLayers_[1]; } - void forward(PassType passType); + void forward(PassType passType) override; - void backward(const UpdateCallback& callback = nullptr); - - void onPassEnd(); + void backward(const UpdateCallback& callback = nullptr) override; real calcNDCG(const real* outputScore, const real* score, int size); void calcGrad(const real* outputScore, @@ -256,11 +269,14 @@ class MultiBinaryLabelCrossEntropy : public CostLayer { explicit MultiBinaryLabelCrossEntropy(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 backwardImp(Matrix& outputValue, Argument& label, Matrix& outputGrad); + void backwardImp(Matrix& outputValue, + Argument& label, + Matrix& outputGrad) override; }; /** @@ -282,13 +298,16 @@ class HuberTwoClass : public CostLayer { public: 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 backwardImp(Matrix& outputValue, Argument& label, Matrix& outputGrad); + void backwardImp(Matrix& outputValue, + Argument& label, + Matrix& outputGrad) override; void backwardImpIn(Matrix& outputValue, Argument& label, Matrix& outputGrad); }; diff --git a/paddle/gserver/layers/CudnnBatchNormLayer.h b/paddle/gserver/layers/CudnnBatchNormLayer.h index b1e7d2082f1443..413efd4d3ecd73 100644 --- a/paddle/gserver/layers/CudnnBatchNormLayer.h +++ b/paddle/gserver/layers/CudnnBatchNormLayer.h @@ -35,14 +35,15 @@ class CudnnBatchNormLayer : public BatchNormBaseLayer { ~CudnnBatchNormLayer(); - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; /** * reshape tensor of ioDesc_. */ void reshape(int batchSize); - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; protected: /** diff --git a/paddle/gserver/layers/CudnnConvLayer.h b/paddle/gserver/layers/CudnnConvLayer.h index b869c695bd7530..919b1efc4e4532 100644 --- a/paddle/gserver/layers/CudnnConvLayer.h +++ b/paddle/gserver/layers/CudnnConvLayer.h @@ -45,9 +45,10 @@ class CudnnConvLayer : public ConvBaseLayer { ~CudnnConvLayer(); - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); - void forward(PassType passType); - void backward(const UpdateCallback& callback); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; + void forward(PassType passType) override; + void backward(const UpdateCallback& callback) override; void addBiases(); void bpropBiases(); }; diff --git a/paddle/gserver/layers/CudnnPoolLayer.h b/paddle/gserver/layers/CudnnPoolLayer.h index 072b2f9513f4ef..28294f5aa30ca4 100644 --- a/paddle/gserver/layers/CudnnPoolLayer.h +++ b/paddle/gserver/layers/CudnnPoolLayer.h @@ -45,7 +45,8 @@ class CudnnPoolLayer : public PoolLayer { hl_pooling_mode_t* mode = nullptr); explicit CudnnPoolLayer(const LayerConfig& config); ~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. @@ -53,8 +54,8 @@ class CudnnPoolLayer : public PoolLayer { * So reshaping is needed. */ void reshape(int batchSize); - virtual void forward(PassType passType); - virtual void backward(const UpdateCallback& callback = nullptr); + virtual void forward(PassType passType) override; + virtual void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/DataLayer.h b/paddle/gserver/layers/DataLayer.h index d3bc97bb6cd0b8..a9cf1f943c260a 100644 --- a/paddle/gserver/layers/DataLayer.h +++ b/paddle/gserver/layers/DataLayer.h @@ -33,13 +33,13 @@ class DataLayer : public Layer { /** * Prefetch sparse matrix/ids only. */ - void prefetch() { output_ = data_; } + void prefetch() override { output_ = data_; } /** * Forward propagation. Copy data_ (value, in, grad, ids, cpuSequenceDims, * sequenceStartPositions, subSequenceStartPositions, strs) to output_. */ - virtual void forward(PassType passType) { + void forward(PassType passType) override { Layer::forward(passType); copyDataToOutput(output_); if (FLAGS_show_layer_stat) { @@ -50,9 +50,9 @@ class DataLayer : public Layer { /** * 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++) { copyDataToOutput(outputOtherDevice_[i]); } diff --git a/paddle/gserver/layers/DataNormLayer.h b/paddle/gserver/layers/DataNormLayer.h index b3043cffd210fe..f0fd044e5b8343 100644 --- a/paddle/gserver/layers/DataNormLayer.h +++ b/paddle/gserver/layers/DataNormLayer.h @@ -44,10 +44,11 @@ class DataNormLayer : public Layer { ~DataNormLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; protected: int mode_; diff --git a/paddle/gserver/layers/EosIdCheckLayer.cpp b/paddle/gserver/layers/EosIdCheckLayer.cpp index fa53e2e4cfc8a2..686f1fa0543cb3 100644 --- a/paddle/gserver/layers/EosIdCheckLayer.cpp +++ b/paddle/gserver/layers/EosIdCheckLayer.cpp @@ -27,14 +27,14 @@ class EosIdCheckLayer : public Layer { public: explicit EosIdCheckLayer(const LayerConfig& config) : Layer(config) {} - virtual bool init(const LayerMap& layerMap, - const ParameterMap& parameterMap) { + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override { bool ret = Layer::init(layerMap, parameterMap); CHECK_EQ(1UL, inputLayers_.size()); return ret; } - virtual void forward(PassType passType) { + void forward(PassType passType) override { Layer::forward(passType); const Argument& input = getInput(0); @@ -42,7 +42,7 @@ class EosIdCheckLayer : public Layer { 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); diff --git a/paddle/gserver/layers/ExpandConvBaseLayer.h b/paddle/gserver/layers/ExpandConvBaseLayer.h index 8445642217cf3e..aabcdfc392d3e2 100644 --- a/paddle/gserver/layers/ExpandConvBaseLayer.h +++ b/paddle/gserver/layers/ExpandConvBaseLayer.h @@ -48,7 +48,8 @@ class ExpandConvBaseLayer : public ConvBaseLayer { ~ExpandConvBaseLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; size_t getOutputSize(); /** diff --git a/paddle/gserver/layers/ExpandConvLayer.h b/paddle/gserver/layers/ExpandConvLayer.h index de81a017e1bac3..60681690e5dd55 100644 --- a/paddle/gserver/layers/ExpandConvLayer.h +++ b/paddle/gserver/layers/ExpandConvLayer.h @@ -35,10 +35,11 @@ class ExpandConvLayer : public ExpandConvBaseLayer { ~ExpandConvLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/ExpandConvTransLayer.h b/paddle/gserver/layers/ExpandConvTransLayer.h index 4a527d67995e25..00b8f241889fdd 100644 --- a/paddle/gserver/layers/ExpandConvTransLayer.h +++ b/paddle/gserver/layers/ExpandConvTransLayer.h @@ -34,10 +34,11 @@ class ExpandConvTransLayer : public ExpandConvBaseLayer { ~ExpandConvTransLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/ExpandLayer.h b/paddle/gserver/layers/ExpandLayer.h index 5c636144235cdb..c21b3350e2bc4b 100644 --- a/paddle/gserver/layers/ExpandLayer.h +++ b/paddle/gserver/layers/ExpandLayer.h @@ -53,10 +53,11 @@ class ExpandLayer : public Layer { ~ExpandLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/FeatureMapExpandLayer.cpp b/paddle/gserver/layers/FeatureMapExpandLayer.cpp index d023074c521675..faadc70bc79c1c 100644 --- a/paddle/gserver/layers/FeatureMapExpandLayer.cpp +++ b/paddle/gserver/layers/FeatureMapExpandLayer.cpp @@ -46,10 +46,11 @@ class FeatureMapExpandLayer : public Layer { ~FeatureMapExpandLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(featmap_expand, FeatureMapExpandLayer); diff --git a/paddle/gserver/layers/FullyConnectedLayer.h b/paddle/gserver/layers/FullyConnectedLayer.h index ccd584585c97cb..64e7a050125aa9 100644 --- a/paddle/gserver/layers/FullyConnectedLayer.h +++ b/paddle/gserver/layers/FullyConnectedLayer.h @@ -36,13 +36,14 @@ class FullyConnectedLayer : public Layer { explicit FullyConnectedLayer(const LayerConfig& config) : Layer(config) {} ~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]; } - void prefetch(); - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void prefetch() override; + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/GatedRecurrentLayer.h b/paddle/gserver/layers/GatedRecurrentLayer.h index 25770ce57fbaa4..58dd760eb870e9 100644 --- a/paddle/gserver/layers/GatedRecurrentLayer.h +++ b/paddle/gserver/layers/GatedRecurrentLayer.h @@ -50,17 +50,18 @@ class GatedRecurrentLayer : public Layer, public GruCompute { public: 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: void forwardSequence(int batchSize, diff --git a/paddle/gserver/layers/GetOutputLayer.cpp b/paddle/gserver/layers/GetOutputLayer.cpp index b77fdbb30e11b7..4e29efd4612b18 100644 --- a/paddle/gserver/layers/GetOutputLayer.cpp +++ b/paddle/gserver/layers/GetOutputLayer.cpp @@ -22,17 +22,18 @@ class GetOutputLayer : public Layer { ~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; CHECK_EQ(1U, inputLayers_.size()); CHECK_NE(inputArgument_[0], ""); return true; } - void forward(PassType passType) { + void forward(PassType passType) override { output_ = getPrev(0)->getOutput(inputArgument_[0]); } - void backward(const UpdateCallback& callback = nullptr) {} + void backward(const UpdateCallback& callback = nullptr) override {} }; REGISTER_LAYER(get_output, GetOutputLayer); diff --git a/paddle/gserver/layers/GruStepLayer.cpp b/paddle/gserver/layers/GruStepLayer.cpp index 4a1006aa941f39..5b5cb25f9269a3 100644 --- a/paddle/gserver/layers/GruStepLayer.cpp +++ b/paddle/gserver/layers/GruStepLayer.cpp @@ -55,10 +55,11 @@ class GruStepLayer : public Layer, public GruCompute { ~GruStepLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(gru_step, GruStepLayer); diff --git a/paddle/gserver/layers/HierarchicalSigmoidLayer.h b/paddle/gserver/layers/HierarchicalSigmoidLayer.h index 70da3ac126e147..3f6875fb9f007c 100644 --- a/paddle/gserver/layers/HierarchicalSigmoidLayer.h +++ b/paddle/gserver/layers/HierarchicalSigmoidLayer.h @@ -61,9 +61,10 @@ class HierarchicalSigmoidLayer : public Layer { public: explicit HierarchicalSigmoidLayer(const LayerConfig& config) : Layer(config) {} - virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); - virtual void forward(PassType passType); - virtual void backward(const UpdateCallback& callback); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; + void forward(PassType passType) override; + void backward(const UpdateCallback& callback) override; protected: /** diff --git a/paddle/gserver/layers/InterpolationLayer.cpp b/paddle/gserver/layers/InterpolationLayer.cpp index 44fe1fb1fea420..eac7428571980b 100644 --- a/paddle/gserver/layers/InterpolationLayer.cpp +++ b/paddle/gserver/layers/InterpolationLayer.cpp @@ -43,10 +43,11 @@ class InterpolationLayer : public Layer { ~InterpolationLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(interpolation, InterpolationLayer); diff --git a/paddle/gserver/layers/LstmLayer.h b/paddle/gserver/layers/LstmLayer.h index f49df2c412f05f..c45a52d2e9aaf4 100644 --- a/paddle/gserver/layers/LstmLayer.h +++ b/paddle/gserver/layers/LstmLayer.h @@ -74,17 +74,18 @@ class LstmLayer : public Layer, public LstmCompute { public: explicit LstmLayer(const LayerConfig &config) : Layer(config) {} - bool init(const LayerMap &layerMap, const ParameterMap ¶meterMap); + bool init(const LayerMap &layerMap, + const ParameterMap ¶meterMap) 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: /** diff --git a/paddle/gserver/layers/LstmStepLayer.cpp b/paddle/gserver/layers/LstmStepLayer.cpp index 5fc6474b8653f4..568277a90c62c7 100644 --- a/paddle/gserver/layers/LstmStepLayer.cpp +++ b/paddle/gserver/layers/LstmStepLayer.cpp @@ -35,10 +35,11 @@ class LstmStepLayer : public Layer, public LstmCompute { ~LstmStepLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(lstm_step, LstmStepLayer); diff --git a/paddle/gserver/layers/MDLstmLayer.cpp b/paddle/gserver/layers/MDLstmLayer.cpp index 88d934d782b549..be0f2a07d4aae2 100644 --- a/paddle/gserver/layers/MDLstmLayer.cpp +++ b/paddle/gserver/layers/MDLstmLayer.cpp @@ -181,11 +181,12 @@ class MDLstmLayer : public LstmLayer { public: 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: void forwardOneSequence(int start, CoordIterator& coordIter); diff --git a/paddle/gserver/layers/MaxIdLayer.cpp b/paddle/gserver/layers/MaxIdLayer.cpp index 80555f3f7b3241..9e72b167cd963a 100644 --- a/paddle/gserver/layers/MaxIdLayer.cpp +++ b/paddle/gserver/layers/MaxIdLayer.cpp @@ -30,8 +30,8 @@ class MaxIdLayer : public Layer { public: explicit MaxIdLayer(const LayerConfig& config) : Layer(config) {} - virtual bool init(const LayerMap& layerMap, - const ParameterMap& parameterMap) { + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override { bool ret = Layer::init(layerMap, parameterMap); CHECK_EQ(1UL, inputLayers_.size()); @@ -40,7 +40,7 @@ class MaxIdLayer : public Layer { return ret; } - virtual void forward(PassType passType) { + void forward(PassType passType) override { Layer::forward(passType); const Argument& input = getInput(0); size_t batchSize = input.getBatchSize(); @@ -54,7 +54,7 @@ class MaxIdLayer : public Layer { input.value->rowMax(*output_.ids, *output_.in); } - virtual void backward(const UpdateCallback& callback) {} + void backward(const UpdateCallback& callback) override {} }; REGISTER_LAYER(maxid, MaxIdLayer); diff --git a/paddle/gserver/layers/MaxLayer.h b/paddle/gserver/layers/MaxLayer.h index 472ee0ccca1962..baa58ca2d7a697 100644 --- a/paddle/gserver/layers/MaxLayer.h +++ b/paddle/gserver/layers/MaxLayer.h @@ -42,14 +42,13 @@ class MaxLayer : public SequencePoolLayer { public: explicit MaxLayer(const LayerConfig& config) : SequencePoolLayer(config) {} - ~MaxLayer() {} - - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap) { + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override { return SequencePoolLayer::init(layerMap, parameterMap); } - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/MaxOutLayer.h b/paddle/gserver/layers/MaxOutLayer.h index 59c2245e0d6490..73fd8536be56b2 100644 --- a/paddle/gserver/layers/MaxOutLayer.h +++ b/paddle/gserver/layers/MaxOutLayer.h @@ -45,10 +45,11 @@ class MaxOutLayer : public Layer { explicit MaxOutLayer(const LayerConfig& config) : Layer(config) {} virtual ~MaxOutLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/MixedLayer.h b/paddle/gserver/layers/MixedLayer.h index 9655a152c7bc96..755c9deb8b1be3 100644 --- a/paddle/gserver/layers/MixedLayer.h +++ b/paddle/gserver/layers/MixedLayer.h @@ -35,21 +35,22 @@ class MixedLayer : public Layer { ~MixedLayer() {} - virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - virtual void prefetch(); - virtual void forward(PassType passType); - virtual void backward(const UpdateCallback& callback = nullptr); - virtual void resetState(); + void prefetch() override; + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; + void resetState() override; /** * setState() should be called after getState(). * 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. */ - virtual LayerStatePtr getState(); + LayerStatePtr getState() override; protected: std::vector> projections_; diff --git a/paddle/gserver/layers/MultiplexLayer.cpp b/paddle/gserver/layers/MultiplexLayer.cpp index d09720c5255747..297972b3cd9e4d 100644 --- a/paddle/gserver/layers/MultiplexLayer.cpp +++ b/paddle/gserver/layers/MultiplexLayer.cpp @@ -69,10 +69,11 @@ class MultiplexLayer : public Layer { ~MultiplexLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; private: /** diff --git a/paddle/gserver/layers/NCELayer.cpp b/paddle/gserver/layers/NCELayer.cpp index 3542e739df8d03..0bc2ef11829337 100644 --- a/paddle/gserver/layers/NCELayer.cpp +++ b/paddle/gserver/layers/NCELayer.cpp @@ -61,7 +61,8 @@ class NCELayer : public Layer { rand_(0, config.num_classes() - 1), prepared_(false) {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap) { + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override { /* Initialize the basic parent class */ Layer::init(layerMap, parameterMap); @@ -146,7 +147,7 @@ class NCELayer : public Layer { prepared_ = true; } - void prefetch() { + void prefetch() override { prepareSamples(); IVector::resizeOrCreate(labelIds_, samples_.size(), useGpu_); int* ids = labelIds_->getData(); @@ -163,7 +164,7 @@ class NCELayer : public Layer { } } - void forward(PassType passType) { + void forward(PassType passType) override { Layer::forward(passType); CHECK(!useGpu_) << "GPU is not supported"; @@ -199,7 +200,7 @@ class NCELayer : public Layer { forwardCost(); } - void backward(const UpdateCallback& callback) { + void backward(const UpdateCallback& callback) override { Matrix::resizeOrCreate(sampleOut_.grad, 1, samples_.size(), diff --git a/paddle/gserver/layers/NormLayer.h b/paddle/gserver/layers/NormLayer.h index 011bab8fdedab0..e77faaa3225709 100644 --- a/paddle/gserver/layers/NormLayer.h +++ b/paddle/gserver/layers/NormLayer.h @@ -30,7 +30,8 @@ class NormLayer : public Layer { public: 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); return true; } @@ -56,9 +57,10 @@ class ResponseNormLayer : public NormLayer { public: explicit ResponseNormLayer(const LayerConfig& config) : NormLayer(config) {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); - void forward(PassType passType) { LOG(FATAL) << "Not implemented"; } - void backward(const UpdateCallback& callback = nullptr) { + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; + void forward(PassType passType) override { LOG(FATAL) << "Not implemented"; } + void backward(const UpdateCallback& callback = nullptr) override { LOG(FATAL) << "Not implemented"; } }; diff --git a/paddle/gserver/layers/NormProjectionLayer.h b/paddle/gserver/layers/NormProjectionLayer.h index 2c0d8a3a718c48..2997ae8848c438 100644 --- a/paddle/gserver/layers/NormProjectionLayer.h +++ b/paddle/gserver/layers/NormProjectionLayer.h @@ -36,9 +36,10 @@ class CMRProjectionNormLayer : public ResponseNormLayer { size_t getSize(); - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; protected: TensorShape shape_; diff --git a/paddle/gserver/layers/OuterProdLayer.cpp b/paddle/gserver/layers/OuterProdLayer.cpp index b606e4436567eb..283fdb003a2bb9 100644 --- a/paddle/gserver/layers/OuterProdLayer.cpp +++ b/paddle/gserver/layers/OuterProdLayer.cpp @@ -38,10 +38,11 @@ class OuterProdLayer : public Layer { ~OuterProdLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(out_prod, OuterProdLayer); diff --git a/paddle/gserver/layers/PadLayer.h b/paddle/gserver/layers/PadLayer.h index 3e3a21a9970370..b2bbf28082e630 100644 --- a/paddle/gserver/layers/PadLayer.h +++ b/paddle/gserver/layers/PadLayer.h @@ -29,9 +29,10 @@ class PadLayer : public Layer { ~PadLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; protected: void setOutDims(const size_t batchSize); diff --git a/paddle/gserver/layers/ParameterReluLayer.h b/paddle/gserver/layers/ParameterReluLayer.h index a82497fc01ca1f..9a11b81ebf1f5c 100644 --- a/paddle/gserver/layers/ParameterReluLayer.h +++ b/paddle/gserver/layers/ParameterReluLayer.h @@ -56,9 +56,10 @@ class ParameterReluLayer : public Layer { ~ParameterReluLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/PoolLayer.h b/paddle/gserver/layers/PoolLayer.h index 318b89d7c2bce8..d43292ad2d4bbe 100644 --- a/paddle/gserver/layers/PoolLayer.h +++ b/paddle/gserver/layers/PoolLayer.h @@ -46,7 +46,8 @@ class PoolLayer : public Layer { */ 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 diff --git a/paddle/gserver/layers/PoolProjectionLayer.h b/paddle/gserver/layers/PoolProjectionLayer.h index 3dc6af2f0e9fb1..e31116de8ccb1f 100644 --- a/paddle/gserver/layers/PoolProjectionLayer.h +++ b/paddle/gserver/layers/PoolProjectionLayer.h @@ -40,7 +40,7 @@ class PoolProjectionLayer : public PoolLayer { size_t getSize(); - virtual void forward(PassType passType); - virtual void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/PowerLayer.cpp b/paddle/gserver/layers/PowerLayer.cpp index 64fecab5b08354..31c34b43e2995a 100644 --- a/paddle/gserver/layers/PowerLayer.cpp +++ b/paddle/gserver/layers/PowerLayer.cpp @@ -40,10 +40,11 @@ class PowerLayer : public Layer { ~PowerLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(power, PowerLayer); diff --git a/paddle/gserver/layers/PrintLayer.cpp b/paddle/gserver/layers/PrintLayer.cpp index ac7f658864fee6..85f52ad5debd03 100644 --- a/paddle/gserver/layers/PrintLayer.cpp +++ b/paddle/gserver/layers/PrintLayer.cpp @@ -19,8 +19,8 @@ namespace paddle { class PrintLayer : public Layer { public: explicit PrintLayer(const LayerConfig& config) : Layer(config) {} - void forward(PassType passType); - void backward(const UpdateCallback& callback) {} + void forward(PassType passType) override; + void backward(const UpdateCallback& callback) override {} }; void PrintLayer::forward(PassType passType) { diff --git a/paddle/gserver/layers/PriorBox.cpp b/paddle/gserver/layers/PriorBox.cpp index 36ace7597cd66c..bcf5e912a50fef 100644 --- a/paddle/gserver/layers/PriorBox.cpp +++ b/paddle/gserver/layers/PriorBox.cpp @@ -30,10 +30,11 @@ namespace paddle { class PriorBoxLayer : public Layer { public: 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 backward(const UpdateCallback& callback) {} + void forward(PassType passType) override; + void backward(const UpdateCallback& callback) override {} protected: int numPriors_; diff --git a/paddle/gserver/layers/RecurrentLayer.cpp b/paddle/gserver/layers/RecurrentLayer.cpp index b843fa1265cf3c..e4c2b483d2fa40 100644 --- a/paddle/gserver/layers/RecurrentLayer.cpp +++ b/paddle/gserver/layers/RecurrentLayer.cpp @@ -45,17 +45,18 @@ class RecurrentLayer : public Layer { public: 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: /** diff --git a/paddle/gserver/layers/RecurrentLayerGroup.cpp b/paddle/gserver/layers/RecurrentLayerGroup.cpp index af8dd61d84e2e5..78a74ff19a38cd 100644 --- a/paddle/gserver/layers/RecurrentLayerGroup.cpp +++ b/paddle/gserver/layers/RecurrentLayerGroup.cpp @@ -33,15 +33,15 @@ class RecurrentLayerGroup : public Layer { void initSubNetwork(NeuralNetwork* rootNetwork, const ModelConfig& config, const std::vector& parameterTypes, - bool useGpu); + bool useGpu) override; - void forward(PassType passType) { + void forward(PassType passType) override { REGISTER_TIMER_INFO("RecurrentGroupFwTime", getName().c_str()); const std::vector inArgs; std::vector outArgs; network_->forward(inArgs, &outArgs, passType); } - void backward(const UpdateCallback& callback) { + void backward(const UpdateCallback& callback) override { REGISTER_TIMER_INFO("RecurrentGroupBwTime", getName().c_str()); network_->backward(nullptr); @@ -53,7 +53,8 @@ class RecurrentLayerGroup : public Layer { /** * @see Layer.accessSubNetwork */ - void accessSubNetwork(const std::function& callback) { + void accessSubNetwork( + const std::function& callback) override { callback(*network_); } diff --git a/paddle/gserver/layers/ResizeLayer.cpp b/paddle/gserver/layers/ResizeLayer.cpp index 7fcb3adea01b9d..eb3b63c106901f 100644 --- a/paddle/gserver/layers/ResizeLayer.cpp +++ b/paddle/gserver/layers/ResizeLayer.cpp @@ -20,18 +20,19 @@ namespace paddle { /** * @brief A layer for resizing a minibatch matrix h*w to h'*w' * @note - * origin matrix height * witdth) + * origin matrix height * width) * resize matrix: (height * width / size) * size */ class ResizeLayer : public Layer { public: 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); diff --git a/paddle/gserver/layers/SamplingIdLayer.cpp b/paddle/gserver/layers/SamplingIdLayer.cpp index 59ff5d41b52909..2538d99bb71fa1 100644 --- a/paddle/gserver/layers/SamplingIdLayer.cpp +++ b/paddle/gserver/layers/SamplingIdLayer.cpp @@ -35,8 +35,8 @@ class SamplingIdLayer : public Layer { explicit SamplingIdLayer(const LayerConfig& config) : Layer(config), rand1_(0, 1) {} - virtual bool init(const LayerMap& layerMap, - const ParameterMap& parameterMap) { + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override { bool ret = Layer::init(layerMap, parameterMap); CHECK_EQ(1UL, inputLayers_.size()); if (useGpu_) { @@ -48,7 +48,7 @@ class SamplingIdLayer : public Layer { return ret; } - void forward(PassType passType) { + void forward(PassType passType) override { Layer::forward(passType); if (useGpu_) { for (size_t i = 0; i < inputLayers_.size(); i++) { @@ -83,7 +83,7 @@ class SamplingIdLayer : public Layer { output_.ids->copyFrom(ids.data(), batchSize); } - virtual void backward(const UpdateCallback& callback) {} + void backward(const UpdateCallback& callback) override {} }; REGISTER_LAYER(sampling_id, SamplingIdLayer); diff --git a/paddle/gserver/layers/ScalingLayer.cpp b/paddle/gserver/layers/ScalingLayer.cpp index 7f0084be6b57f5..a38ee0857a7679 100644 --- a/paddle/gserver/layers/ScalingLayer.cpp +++ b/paddle/gserver/layers/ScalingLayer.cpp @@ -37,10 +37,11 @@ class ScalingLayer : public Layer { ~ScalingLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(scaling, ScalingLayer); diff --git a/paddle/gserver/layers/SelectiveFullyConnectedLayer.h b/paddle/gserver/layers/SelectiveFullyConnectedLayer.h index bdf9a4652cc717..99126fdba542bd 100644 --- a/paddle/gserver/layers/SelectiveFullyConnectedLayer.h +++ b/paddle/gserver/layers/SelectiveFullyConnectedLayer.h @@ -65,9 +65,10 @@ class SelectiveFullyConnectedLayer : public Layer { : Layer(config), selCols_(nullptr) {} ~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]; } @@ -90,8 +91,8 @@ class SelectiveFullyConnectedLayer : public Layer { void fillSelectiveData( const std::shared_ptr>>& candidates); - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; private: /** diff --git a/paddle/gserver/layers/SequenceConcatLayer.cpp b/paddle/gserver/layers/SequenceConcatLayer.cpp index 069bc26e602ff7..b4677687a6cc77 100644 --- a/paddle/gserver/layers/SequenceConcatLayer.cpp +++ b/paddle/gserver/layers/SequenceConcatLayer.cpp @@ -35,10 +35,11 @@ class SequenceConcatLayer : public Layer { ~SequenceConcatLayer() {} - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(seqconcat, SequenceConcatLayer); diff --git a/paddle/gserver/layers/SequenceLastInstanceLayer.cpp b/paddle/gserver/layers/SequenceLastInstanceLayer.cpp index 4bfce766c769f4..7a13cd7ad0fecf 100644 --- a/paddle/gserver/layers/SequenceLastInstanceLayer.cpp +++ b/paddle/gserver/layers/SequenceLastInstanceLayer.cpp @@ -42,12 +42,11 @@ class SequenceLastInstanceLayer : public SequencePoolLayer { explicit SequenceLastInstanceLayer(const LayerConfig& 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); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(seqlastins, SequenceLastInstanceLayer); diff --git a/paddle/gserver/layers/SequencePoolLayer.h b/paddle/gserver/layers/SequencePoolLayer.h index aa9c132586e55d..85b51ccd1dc7e7 100644 --- a/paddle/gserver/layers/SequencePoolLayer.h +++ b/paddle/gserver/layers/SequencePoolLayer.h @@ -46,12 +46,11 @@ class SequencePoolLayer : public Layer { public: 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); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/SequenceReshapeLayer.cpp b/paddle/gserver/layers/SequenceReshapeLayer.cpp index 23924b0490851a..66f49159087ab9 100644 --- a/paddle/gserver/layers/SequenceReshapeLayer.cpp +++ b/paddle/gserver/layers/SequenceReshapeLayer.cpp @@ -34,12 +34,11 @@ class SequenceReshapeLayer : public Layer { public: 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); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(seqreshape, SequenceReshapeLayer); diff --git a/paddle/gserver/layers/SlopeInterceptLayer.cpp b/paddle/gserver/layers/SlopeInterceptLayer.cpp index b678f414b6d76f..faf98744a7fdcf 100644 --- a/paddle/gserver/layers/SlopeInterceptLayer.cpp +++ b/paddle/gserver/layers/SlopeInterceptLayer.cpp @@ -39,12 +39,11 @@ class SlopeInterceptLayer : public Layer { public: 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); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(slope_intercept, SlopeInterceptLayer); diff --git a/paddle/gserver/layers/SpatialPyramidPoolLayer.h b/paddle/gserver/layers/SpatialPyramidPoolLayer.h index 32e88cf141a667..7d3cb80443801a 100644 --- a/paddle/gserver/layers/SpatialPyramidPoolLayer.h +++ b/paddle/gserver/layers/SpatialPyramidPoolLayer.h @@ -43,9 +43,8 @@ class SpatialPyramidPoolLayer : public Layer { public: explicit SpatialPyramidPoolLayer(const LayerConfig& config) : Layer(config) {} - ~SpatialPyramidPoolLayer() {} - - virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; ProjectionConfig getConfig(size_t sizeX_, size_t sizeY_, @@ -54,7 +53,7 @@ class SpatialPyramidPoolLayer : public Layer { std::string& poolType_); size_t getSize(); - virtual void forward(PassType passType); - virtual void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/SubSequenceLayer.cpp b/paddle/gserver/layers/SubSequenceLayer.cpp index c52fbee26232ad..19b7ad1869af98 100644 --- a/paddle/gserver/layers/SubSequenceLayer.cpp +++ b/paddle/gserver/layers/SubSequenceLayer.cpp @@ -35,12 +35,11 @@ class SubSequenceLayer : public Layer { public: 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); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(subseq, SubSequenceLayer); diff --git a/paddle/gserver/layers/SumToOneNormLayer.cpp b/paddle/gserver/layers/SumToOneNormLayer.cpp index aa99b49380d368..00f8519550bcff 100644 --- a/paddle/gserver/layers/SumToOneNormLayer.cpp +++ b/paddle/gserver/layers/SumToOneNormLayer.cpp @@ -41,12 +41,11 @@ class SumToOneNormLayer : public Layer { public: 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); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; REGISTER_LAYER(sum_to_one_norm, SumToOneNormLayer); diff --git a/paddle/gserver/layers/TensorLayer.h b/paddle/gserver/layers/TensorLayer.h index ac38ffb6205703..43992f692d3ce4 100644 --- a/paddle/gserver/layers/TensorLayer.h +++ b/paddle/gserver/layers/TensorLayer.h @@ -44,13 +44,12 @@ class TensorLayer : public Layer { public: explicit TensorLayer(const LayerConfig& config) : Layer(config) {} - ~TensorLayer() {} - - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; Weight& getWeight(int idx) { return *weights_[idx]; } - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/TransLayer.h b/paddle/gserver/layers/TransLayer.h index b43fa1ebfb0032..08a2fb453284c8 100644 --- a/paddle/gserver/layers/TransLayer.h +++ b/paddle/gserver/layers/TransLayer.h @@ -32,9 +32,10 @@ class TransLayer : public Layer { public: 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 backward(const UpdateCallback& callback = nullptr); + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle diff --git a/paddle/gserver/layers/ValidationLayer.h b/paddle/gserver/layers/ValidationLayer.h index 4c1de7b3b7d697..c8b2634a1366ed 100644 --- a/paddle/gserver/layers/ValidationLayer.h +++ b/paddle/gserver/layers/ValidationLayer.h @@ -26,7 +26,8 @@ class ValidationLayer : public Layer { public: 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]; } @@ -37,13 +38,13 @@ class ValidationLayer : public Layer { 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 onPassEnd() = 0; + void onPassEnd() override = 0; }; /* @@ -57,11 +58,12 @@ class AucValidation : public ValidationLayer { cpuLabel_(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 { PredictionResult(real __out, int __label) : out(__out), label(__label) {} @@ -86,11 +88,12 @@ class PnpairValidation : public ValidationLayer { explicit PnpairValidation(const LayerConfig& 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: bool passBegin_; diff --git a/paddle/gserver/layers/WarpCTCLayer.h b/paddle/gserver/layers/WarpCTCLayer.h index 3d9ae9249af66d..7e8d7379d26788 100644 --- a/paddle/gserver/layers/WarpCTCLayer.h +++ b/paddle/gserver/layers/WarpCTCLayer.h @@ -30,9 +30,10 @@ class WarpCTCLayer : public Layer { explicit WarpCTCLayer(const LayerConfig& config) : Layer(config) {} ~WarpCTCLayer() {} - virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); - virtual void forward(PassType passType); - virtual void backward(const UpdateCallback& callback); + bool init(const LayerMap& layerMap, + const ParameterMap& parameterMap) override; + void forward(PassType passType) override; + void backward(const UpdateCallback& callback) override; protected: /** From e7419d690c3407ad7387d453a673b6f99656d342 Mon Sep 17 00:00:00 2001 From: reyoung Date: Fri, 3 Feb 2017 09:44:43 +0000 Subject: [PATCH 140/370] Remove virtual in override --- paddle/gserver/layers/CudnnPoolLayer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paddle/gserver/layers/CudnnPoolLayer.h b/paddle/gserver/layers/CudnnPoolLayer.h index 28294f5aa30ca4..f0aa22fe3af90c 100644 --- a/paddle/gserver/layers/CudnnPoolLayer.h +++ b/paddle/gserver/layers/CudnnPoolLayer.h @@ -54,8 +54,8 @@ class CudnnPoolLayer : public PoolLayer { * So reshaping is needed. */ void reshape(int batchSize); - virtual void forward(PassType passType) override; - virtual void backward(const UpdateCallback& callback = nullptr) override; + void forward(PassType passType) override; + void backward(const UpdateCallback& callback = nullptr) override; }; } // namespace paddle From 73dcf2cd58b9e38b465853dd95ace9e16f84f164 Mon Sep 17 00:00:00 2001 From: Haonan Date: Fri, 3 Feb 2017 11:49:38 -0800 Subject: [PATCH 141/370] improving code comments --- paddle/gserver/layers/RotateLayer.cpp | 3 ++- paddle/gserver/layers/RotateLayer.h | 2 +- paddle/gserver/tests/test_LayerGrad.cpp | 3 ++- python/paddle/trainer_config_helpers/layers.py | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/paddle/gserver/layers/RotateLayer.cpp b/paddle/gserver/layers/RotateLayer.cpp index d928f1d93de0ee..7c71088d786ab2 100644 --- a/paddle/gserver/layers/RotateLayer.cpp +++ b/paddle/gserver/layers/RotateLayer.cpp @@ -38,7 +38,8 @@ void RotateLayer::forward(PassType passType) { size_ = input->getWidth(); CHECK_GE(size_, height_ * width_); CHECK_EQ(size_ % (height_ * width_), 0) - << "The input's depth should be an int"; + << "total size_ is not dividable by (height_ * width_), i.e., " + << "channel number should be an integer"; channels_ = size_ / (height_ * width_); resizeOutput(batchSize_, size_); diff --git a/paddle/gserver/layers/RotateLayer.h b/paddle/gserver/layers/RotateLayer.h index a6f565a7e5dcfa..1a64d4d5a51d9c 100644 --- a/paddle/gserver/layers/RotateLayer.h +++ b/paddle/gserver/layers/RotateLayer.h @@ -21,7 +21,7 @@ namespace paddle { /** * A layer for rotating a multi-channel feature map (M x N x C) in the spatial * domain - * The rotation is 90 degrees in clock-wise + * The rotation is 90 degrees in clock-wise for each channel * \f[ * y(j,i,:) = x(M-i-1,j,:) * \f] diff --git a/paddle/gserver/tests/test_LayerGrad.cpp b/paddle/gserver/tests/test_LayerGrad.cpp index 685d2ca542b242..7e6842742e0d19 100644 --- a/paddle/gserver/tests/test_LayerGrad.cpp +++ b/paddle/gserver/tests/test_LayerGrad.cpp @@ -1320,9 +1320,10 @@ TEST(Layer, RotateLayer) { TestConfig config; config.biasSize = 0; config.layerConfig.set_type("rotate"); - const int INPUT_SIZE = 64; // height * width * depth + const int CHANNEL = 2; const int HEIGHT = 8; const int WIDTH = 4; + const int INPUT_SIZE = HEIGHT * WIDTH * CHANNEL; config.layerConfig.set_size(INPUT_SIZE); config.layerConfig.set_height(HEIGHT); config.layerConfig.set_width(WIDTH); diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 2636f6cc1a1653..66b842a25d9d87 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -1679,8 +1679,8 @@ def trans_layer(input, name=None, layer_attr=None): @layer_support() def rotate_layer(input, height, width, name=None, layer_attr=None): """ - A layer for rotating 90 degrees (clock-wise), usually used when the input sample - is some image or feature map. + A layer for rotating 90 degrees (clock-wise) for each feature channel, + usually used when the input sample is some image or feature map. .. math:: y(j,i,:) = x(M-i-1,j,:) From 996b1de1d83e972870c4a3c6e21b5cc4b0b93014 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Fri, 3 Feb 2017 23:48:54 +0000 Subject: [PATCH 142/370] Rename DataBase into create_data_config_proto --- python/paddle/trainer/config_parser.py | 14 ++++++------ .../trainer_config_helpers/data_sources.py | 22 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index 6701eced60d068..e3e2a6899e7fa7 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -894,7 +894,7 @@ def __init__(self, channels, groups, img_size_x=0, img_size_y=0): self.add_keys(locals()) -def DataBase(async_load_data=False, +def create_data_config_proto(async_load_data=False, constant_slots=None, data_ratio=1, is_main_data=True, @@ -924,7 +924,7 @@ def SimpleData(files=None, context_len=None, buffer_capacity=None, **xargs): - data_config = DataBase(**xargs) + data_config = create_data_config_proto(**xargs) data_config.type = 'simple' data_config.files = files data_config.feat_dim = feat_dim @@ -946,7 +946,7 @@ def PyData(files=None, constant_slots=None, load_thread_num=None, **xargs): - data_config = DataBase(**xargs) + data_config = create_data_config_proto(**xargs) data_config.type = 'py' if load_data_module in g_py_module_name_list: @@ -997,7 +997,7 @@ def ProtoData(files=None, constant_slots=None, load_thread_num=None, **xargs): - data_config = DataBase(**xargs) + data_config = create_data_config_proto(**xargs) if type is None: data_config.type = 'proto' else: @@ -1036,7 +1036,7 @@ def Data(type, buffer_capacity=None, **xargs): - data_config = DataBase(**xargs) + data_config = create_data_config_proto(**xargs) data_config.type = type data_config.files = files data_config.feat_dim = feat_dim @@ -1927,8 +1927,8 @@ def __init__(self, image_conf = self.config.inputs[0].image_conf parse_image(self.inputs[0].image, input_layer.name, image_conf) - # Only pass the width and height of input to batch_norm layer - # when either of it is non-zero. + # Only pass the width and height of input to batch_norm layer + # when either of it is non-zero. if input_layer.width != 0 or input_layer.height != 0: self.set_cnn_layer(name, image_conf.img_size_y, image_conf.img_size, image_conf.channels, False) diff --git a/python/paddle/trainer_config_helpers/data_sources.py b/python/paddle/trainer_config_helpers/data_sources.py index 622b4fc25ccff3..0ea8fc77eef9f5 100644 --- a/python/paddle/trainer_config_helpers/data_sources.py +++ b/python/paddle/trainer_config_helpers/data_sources.py @@ -58,8 +58,8 @@ def define_py_data_source(file_list, :param obj: python object name. May be a function name if using PyDataProviderWrapper. :type obj: basestring - :param args: The best practice is using dict to pass arguments into - DataProvider, and use :code:`@init_hook_wrapper` to + :param args: The best practice is using dict to pass arguments into + DataProvider, and use :code:`@init_hook_wrapper` to receive arguments. :type args: string or picklable object :param async: Load Data asynchronously or not. @@ -98,7 +98,7 @@ def define_py_data_sources(train_list, The annotation is almost the same as define_py_data_sources2, except that it can specific train_async and data_cls. - :param data_cls: + :param data_cls: :param train_list: Train list name. :type train_list: basestring :param test_list: Test list name. @@ -111,8 +111,8 @@ def define_py_data_sources(train_list, a tuple or list to this argument. :type obj: basestring or tuple or list :param args: The best practice is using dict() to pass arguments into - DataProvider, and use :code:`@init_hook_wrapper` to receive - arguments. If train and test is different, then pass a tuple + DataProvider, and use :code:`@init_hook_wrapper` to receive + arguments. If train and test is different, then pass a tuple or list to this argument. :type args: string or picklable object or list or tuple. :param train_async: Is training data load asynchronously or not. @@ -163,12 +163,12 @@ def define_py_data_sources2(train_list, test_list, module, obj, args=None): .. code-block:: python - define_py_data_sources2(train_list="train.list", - test_list="test.list", + define_py_data_sources2(train_list="train.list", + test_list="test.list", module="data_provider" # if train/test use different configurations, # obj=["process_train", "process_test"] - obj="process", + obj="process", args={"dictionary": dict_name}) The related data provider can refer to :ref:`api_pydataprovider2_sequential_model` . @@ -185,8 +185,8 @@ def define_py_data_sources2(train_list, test_list, module, obj, args=None): a tuple or list to this argument. :type obj: basestring or tuple or list :param args: The best practice is using dict() to pass arguments into - DataProvider, and use :code:`@init_hook_wrapper` to receive - arguments. If train and test is different, then pass a tuple + DataProvider, and use :code:`@init_hook_wrapper` to receive + arguments. If train and test is different, then pass a tuple or list to this argument. :type args: string or picklable object or list or tuple. :return: None @@ -195,7 +195,7 @@ def define_py_data_sources2(train_list, test_list, module, obj, args=None): def py_data2(files, load_data_module, load_data_object, load_data_args, **kwargs): - data = DataBase() + data = create_data_config_proto() data.type = 'py2' data.files = files data.load_data_module = load_data_module From 03148804bbe162a2cd9366aa491077073257905c Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Sat, 4 Feb 2017 15:10:58 +0800 Subject: [PATCH 143/370] remove usused arguments for maxout_layer, refine notes for pad_layer --- .../paddle/trainer_config_helpers/layers.py | 49 +++++++++---------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 66fa58ac91e33b..b124de66e94b59 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -3677,26 +3677,27 @@ def pad_layer(input, For example, - .. code-block:: - - input(2,2,2,3) = [ - [ [[1,2,3], [3,4,5]], - [[2,3,5], [1,6,7]] ], - [ [[4,3,1], [1,8,7]], - [[3,8,9], [2,3,5]] ] - ] - - pad_c=[1,1], pad_h=[0,0], pad_w=[0,0] - output(2,4,2,3) = [ - [ [[0,0,0], [0,0,0]], - [[1,2,3], [3,4,5]], - [[2,3,5], [1,6,7]], - [[0,0,0], [0,0,0]] ], - [ [[0,0,0], [0,0,0]], - [[4,3,1], [1,8,7]], - [[3,8,9], [2,3,5]], - [[0,0,0], [0,0,0]] ] - ] + .. code-block:: python + + input(2,2,2,3) = [ + [ [[1,2,3], [3,4,5]], + [[2,3,5], [1,6,7]] ], + [ [[4,3,1], [1,8,7]], + [[3,8,9], [2,3,5]] ] + ] + + pad_c=[1,1], pad_h=[0,0], pad_w=[0,0] + + output(2,4,2,3) = [ + [ [[0,0,0], [0,0,0]], + [[1,2,3], [3,4,5]], + [[2,3,5], [1,6,7]], + [[0,0,0], [0,0,0]] ], + [ [[0,0,0], [0,0,0]], + [[4,3,1], [1,8,7]], + [[3,8,9], [2,3,5]], + [[0,0,0], [0,0,0]] ] + ] The simply usage is: @@ -4191,13 +4192,7 @@ def block_expand_layer(input, @wrap_name_default() @layer_support() -def maxout_layer(input, - groups, - num_channels=None, - size_x=None, - size_y=None, - name=None, - layer_attr=None): +def maxout_layer(input, groups, num_channels=None, name=None, layer_attr=None): """ A layer to do max out on conv layer output. - Input: output of a conv layer. From ab279beed1725fae4fc4781ba891d80bde8eae0a Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Sun, 5 Feb 2017 01:01:21 +0000 Subject: [PATCH 144/370] Remove completely create_data_config_proto --- python/paddle/trainer/config_parser.py | 24 ------------------- .../trainer_config_helpers/data_sources.py | 3 ++- 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index e3e2a6899e7fa7..65ebc96136d823 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -894,30 +894,6 @@ def __init__(self, channels, groups, img_size_x=0, img_size_y=0): self.add_keys(locals()) -def create_data_config_proto(async_load_data=False, - constant_slots=None, - data_ratio=1, - is_main_data=True, - usage_ratio=None): - # default: all sub dataproviders are treat as "main data". - # see proto/DataConfig.proto for is_main_data - data_config = DataConfig() - - data_config.async_load_data = async_load_data - - if constant_slots: - data_config.constant_slots.extend(constant_slots) - data_config.data_ratio = data_ratio - data_config.is_main_data = is_main_data - - usage_ratio = default(usage_ratio, settings_deprecated["usage_ratio"]) - config_assert(usage_ratio >= 0 and usage_ratio <= 1, - "The range of usage_ratio is [0, 1]") - data_config.usage_ratio = usage_ratio - - return data_config - - @config_func def SimpleData(files=None, feat_dim=None, diff --git a/python/paddle/trainer_config_helpers/data_sources.py b/python/paddle/trainer_config_helpers/data_sources.py index 0ea8fc77eef9f5..6744dec5a87a5b 100644 --- a/python/paddle/trainer_config_helpers/data_sources.py +++ b/python/paddle/trainer_config_helpers/data_sources.py @@ -14,6 +14,7 @@ """ Data Sources are helpers to define paddle training data or testing data. """ +import paddle.proto.DataConfig_pb2 from paddle.trainer.config_parser import * from .utils import deprecated @@ -195,7 +196,7 @@ def define_py_data_sources2(train_list, test_list, module, obj, args=None): def py_data2(files, load_data_module, load_data_object, load_data_args, **kwargs): - data = create_data_config_proto() + data = paddle.proto.DataConfig_pb2.DataConfig() data.type = 'py2' data.files = files data.load_data_module = load_data_module From 058eeac0fc94500137ce0192136d45a62ada0569 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Sun, 5 Feb 2017 01:17:00 +0000 Subject: [PATCH 145/370] Revert "Remove completely create_data_config_proto" This reverts commit ab279beed1725fae4fc4781ba891d80bde8eae0a. --- python/paddle/trainer/config_parser.py | 24 +++++++++++++++++++ .../trainer_config_helpers/data_sources.py | 3 +-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index 65ebc96136d823..e3e2a6899e7fa7 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -894,6 +894,30 @@ def __init__(self, channels, groups, img_size_x=0, img_size_y=0): self.add_keys(locals()) +def create_data_config_proto(async_load_data=False, + constant_slots=None, + data_ratio=1, + is_main_data=True, + usage_ratio=None): + # default: all sub dataproviders are treat as "main data". + # see proto/DataConfig.proto for is_main_data + data_config = DataConfig() + + data_config.async_load_data = async_load_data + + if constant_slots: + data_config.constant_slots.extend(constant_slots) + data_config.data_ratio = data_ratio + data_config.is_main_data = is_main_data + + usage_ratio = default(usage_ratio, settings_deprecated["usage_ratio"]) + config_assert(usage_ratio >= 0 and usage_ratio <= 1, + "The range of usage_ratio is [0, 1]") + data_config.usage_ratio = usage_ratio + + return data_config + + @config_func def SimpleData(files=None, feat_dim=None, diff --git a/python/paddle/trainer_config_helpers/data_sources.py b/python/paddle/trainer_config_helpers/data_sources.py index 6744dec5a87a5b..0ea8fc77eef9f5 100644 --- a/python/paddle/trainer_config_helpers/data_sources.py +++ b/python/paddle/trainer_config_helpers/data_sources.py @@ -14,7 +14,6 @@ """ Data Sources are helpers to define paddle training data or testing data. """ -import paddle.proto.DataConfig_pb2 from paddle.trainer.config_parser import * from .utils import deprecated @@ -196,7 +195,7 @@ def define_py_data_sources2(train_list, test_list, module, obj, args=None): def py_data2(files, load_data_module, load_data_object, load_data_args, **kwargs): - data = paddle.proto.DataConfig_pb2.DataConfig() + data = create_data_config_proto() data.type = 'py2' data.files = files data.load_data_module = load_data_module From b36df98d01c537c4dbb14a625d9ec3936e460a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=9B=8A?= Date: Sat, 4 Feb 2017 17:24:18 -0800 Subject: [PATCH 146/370] Correct Python identation --- python/paddle/trainer/config_parser.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index e3e2a6899e7fa7..dd159f22d97f48 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -895,10 +895,10 @@ def __init__(self, channels, groups, img_size_x=0, img_size_y=0): def create_data_config_proto(async_load_data=False, - constant_slots=None, - data_ratio=1, - is_main_data=True, - usage_ratio=None): + onstant_slots=None, + data_ratio=1, + is_main_data=True, + usage_ratio=None): # default: all sub dataproviders are treat as "main data". # see proto/DataConfig.proto for is_main_data data_config = DataConfig() From b8f3a5c433841017760f53119b77b54d757f4fa5 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Sat, 4 Feb 2017 19:35:16 -0800 Subject: [PATCH 147/370] Correct the wrong deletion of a single character --- python/paddle/trainer/config_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index dd159f22d97f48..8b02be9af1a82b 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -895,7 +895,7 @@ def __init__(self, channels, groups, img_size_x=0, img_size_y=0): def create_data_config_proto(async_load_data=False, - onstant_slots=None, + constant_slots=None, data_ratio=1, is_main_data=True, usage_ratio=None): From ca25b9a50852529de83d99ff0750b4dbee673b62 Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Mon, 6 Feb 2017 10:48:28 +0800 Subject: [PATCH 148/370] remove unused notes in maxout layer --- python/paddle/trainer_config_helpers/layers.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index b124de66e94b59..1fdc4c46236371 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -4222,12 +4222,6 @@ def maxout_layer(input, groups, num_channels=None, name=None, layer_attr=None): :type num_channels: int|None :param groups: The group number of input layer. :type groups: int - :param size_x: conv output width. If None will be set - automatically from previous output. - :type size_x: int|None - :param size_y: conv output height. If None will be set - automatically from previous output. - :type size_y: int|None :param name: The name of this layer, which can not specify. :type name: None|basestring. :param layer_attr: Extra Layer attribute. From f3755dd455a60d9aaadd7978d229f7bdb5673c4b Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 7 Feb 2017 14:23:33 +0800 Subject: [PATCH 149/370] add v2-layers --- demo/mnist/api_train.py | 34 +++++------ python/paddle/v2/__init__.py | 3 +- python/paddle/v2/layers.py | 112 +++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 18 deletions(-) create mode 100644 python/paddle/v2/layers.py diff --git a/demo/mnist/api_train.py b/demo/mnist/api_train.py index 8573d8143a085b..6d071cdffe120f 100644 --- a/demo/mnist/api_train.py +++ b/demo/mnist/api_train.py @@ -6,25 +6,16 @@ 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 -from mnist_util import read_from_mnist -from paddle.trainer_config_helpers import * -import paddle.v2 +import numpy as np +import paddle.trainer.PyDataProvider2 as dp +import paddle.v2 +import py_paddle.swig_paddle as api +from paddle.trainer_config_helpers import * +from py_paddle import DataProviderConverter -def network_config(): - 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) +from mnist_util import read_from_mnist def init_parameter(network): @@ -79,8 +70,17 @@ def main(): updater = optimizer.create_local_updater() assert isinstance(updater, api.ParameterUpdater) + # define network + images = paddle.v2.layers.data_layer(name='pixel', size=784) + label = paddle.v2.layers.data_layer(name='label', size=10) + hidden1 = paddle.v2.layers.fc_layer(input=images, size=200) + hidden2 = paddle.v2.layers.fc_layer(input=hidden1, size=200) + inference = paddle.v2.layers.fc_layer( + input=hidden2, size=10, act=SoftmaxActivation()) + cost = paddle.v2.layers.classification_cost(input=inference, label=label) + # Create Simple Gradient Machine. - model_config = parse_network_config(network_config) + model_config = paddle.v2.layers.parse_network(cost) m = api.GradientMachine.createFromConfigProto(model_config, api.CREATE_MODE_NORMAL, optimizer.enable_types()) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index b2ea87b086101d..c04c0cc73a800a 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -13,5 +13,6 @@ # limitations under the License. import optimizer +import layers -__all__ = ['optimizer'] +__all__ = ['optimizer', 'layers'] diff --git a/python/paddle/v2/layers.py b/python/paddle/v2/layers.py new file mode 100644 index 00000000000000..14efe9412c3582 --- /dev/null +++ b/python/paddle/v2/layers.py @@ -0,0 +1,112 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + +import paddle.trainer_config_helpers as conf_helps +from paddle.trainer_config_helpers.config_parser_utils import \ + parse_network_config as __parse__ +from paddle.trainer_config_helpers.default_decorators import wrap_name_default +import collections + + +class Layer(object): + def __init__(self, name, parent_layer): + assert isinstance(parent_layer, dict) + assert isinstance(name, basestring) + self.name = name + self.__parent_layer__ = parent_layer + + def to_proto(self, context): + """ + function to set proto attribute + """ + kwargs = dict() + for param_name in self.__parent_layer__: + if not isinstance(self.__parent_layer__[param_name], + collections.Sequence): + param_value = self.__parent_layer__[param_name].to_proto( + context=context) + else: + param_value = map(lambda x: x.to_proto(context=context), + self.__parent_layer__[param_name]) + kwargs[param_name] = param_value + + if self.name not in context: + context[self.name] = self.to_proto_impl(**kwargs) + return context[self.name] + + def to_proto_impl(self, **kwargs): + raise NotImplementedError() + + +def parse_network(*outputs): + def __real_func__(): + context = dict() + real_output = [each.to_proto(context=context) for each in outputs] + conf_helps.outputs(real_output) + + return __parse__(__real_func__) + + +def __convert__(method_name, name_prefix, parent_names): + if name_prefix is not None: + wrapper = wrap_name_default(name_prefix=name_prefix) + else: + wrapper = None + + class __Impl__(Layer): + def __init__(self, name=None, **kwargs): + parent_layers = dict() + other_kwargs = dict() + for pname in parent_names: + parent_layers[pname] = kwargs[pname] + + for key in kwargs.keys(): + if key not in parent_names: + other_kwargs[key] = kwargs[key] + + super(__Impl__, self).__init__(name, parent_layers) + self.__other_kwargs__ = other_kwargs + + if wrapper is not None: + __init__ = wrapper(__init__) + + def to_proto_impl(self, **kwargs): + args = dict() + for each in kwargs: + args[each] = kwargs[each] + for each in self.__other_kwargs__: + args[each] = self.__other_kwargs__[each] + return getattr(conf_helps, method_name)(name=self.name, **args) + + return __Impl__ + + +data_layer = __convert__('data_layer', None, []) +fc_layer = __convert__('fc_layer', name_prefix='fc', parent_names=['input']) +classification_cost = __convert__( + 'classification_cost', + name_prefix='classification_cost', + parent_names=['input', 'label']) + +__all__ = ['data_layer', 'fc_layer', 'classification_cost', 'parse_network'] + +if __name__ == '__main__': + data = data_layer(name='pixel', size=784) + hidden = fc_layer(input=data, size=100, act=conf_helps.SigmoidActivation()) + predict = fc_layer( + input=[hidden, data], size=10, act=conf_helps.SoftmaxActivation()) + cost = classification_cost( + input=predict, label=data_layer( + name='label', size=10)) + print parse_network(cost) From 250f784122f3bfd67f9e8dd9fcaa437f07e0575a Mon Sep 17 00:00:00 2001 From: liaogang Date: Tue, 7 Feb 2017 14:41:00 +0800 Subject: [PATCH 150/370] Add std for setiosflags --- paddle/function/MulOpTest.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/paddle/function/MulOpTest.cpp b/paddle/function/MulOpTest.cpp index 158c3c90983b12..8748eb0d79fa0f 100644 --- a/paddle/function/MulOpTest.cpp +++ b/paddle/function/MulOpTest.cpp @@ -60,7 +60,7 @@ TEST(MulOp, DDDMatrixMul) { if (transa && transb) { continue; } - VLOG(3) << setiosflags(std::ios::left) << std::setfill(' ') + VLOG(3) << std::setiosflags(std::ios::left) << std::setfill(' ') << " transa=" << transa << " transb=" << transb << " dimM=" << std::setw(5) << dimM << " dimN=" << std::setw(5) << dimN @@ -104,7 +104,7 @@ TEST(MuLOp, DSparseDMul) { for (const auto dimK : {3, 10}) { for (const auto nnz : {3, 10}) { 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 << " dimN=" << std::setw(5) << dimN << " dimK=" << std::setw(5) << dimK @@ -150,7 +150,7 @@ TEST(MulOp, DDSparseMul) { for (const auto dimK : {3, 10}) { for (const auto nnz : {3, 10}) { 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 << " dimN=" << std::setw(5) << dimN << " dimK=" << std::setw(5) << dimK @@ -197,7 +197,7 @@ TEST(MulOp, SparseDDMul) { for (const auto dimK : {3, 10}) { for (const auto nnz : {3, 10}) { 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 << " dimN=" << std::setw(5) << dimN << " dimK=" << std::setw(5) << dimK From 1251501caf2c268e3e221520e624d5f64cce8c58 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Tue, 24 Jan 2017 21:19:59 -0800 Subject: [PATCH 151/370] rewrite unit test using new Function Test. --- paddle/function/BufferArg.h | 3 +- paddle/function/ContextProjectionOp.cpp | 70 +++++----- paddle/function/ContextProjectionOp.h | 1 - paddle/function/ContextProjectionOpTest.cpp | 139 ++++++------------- paddle/function/FunctionTest.h | 146 +++++++++++++++----- 5 files changed, 185 insertions(+), 174 deletions(-) diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index 349b21e7e64064..f7df56846f6d7b 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -226,7 +226,8 @@ class SequenceArg : public BufferArg { SequenceArg(ValueType valueType, const TensorShape& shape, ArgType argType = UNSPECIFIED) - : BufferArg(valueType, shape, argType), startPositions_(TensorShape()) { + : BufferArg(valueType, shape, argType), + startPositions_(TensorShape({shape[0]})) { bufferType_ = TENSOR_SEQUENCE_DATA; } diff --git a/paddle/function/ContextProjectionOp.cpp b/paddle/function/ContextProjectionOp.cpp index 6cd4e4abee8fcc..d81ea584016060 100644 --- a/paddle/function/ContextProjectionOp.cpp +++ b/paddle/function/ContextProjectionOp.cpp @@ -108,26 +108,23 @@ class ContextProjectionForwardFunc : public FunctionBase { } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK(1 == inputs.size() || 2 == inputs.size()); - CHECK_EQ((size_t)1, outputs.size()); + CHECK(1UL == inputs.size() || 2UL == inputs.size()); + CHECK_EQ(1UL, outputs.size()); CHECK(inputs[0].isSequenceArg() && outputs[0].isSequenceArg()) << "SequenceArg required here"; const auto val_seqs = dynamic_cast(inputs[0]); auto out_seq = dynamic_cast(outputs[0]); CHECK(out_seq.data() && val_seqs.data() && val_seqs.getSequenceId().data()); - CHECK_EQ(out_seq.shape().ndims(), (size_t)2); - CHECK_EQ(val_seqs.shape().ndims(), (size_t)2); - CHECK_EQ(val_seqs.getSequenceId().shape().ndims(), (size_t)1); - if (2 == inputs.size()) { - CHECK_EQ(inputs[1].shape().ndims(), (size_t)2); - } + CHECK_EQ(out_seq.shape().ndims(), 2UL); + CHECK_EQ(val_seqs.shape().ndims(), 2UL); /// dim of output = dim of input * context_length CHECK_EQ(out_seq.shape()[1], val_seqs.shape()[1] * context_length_); /// input and output has the same batch_size CHECK_EQ(val_seqs.shape()[0], out_seq.shape()[0]); - /// dim of input == dim of weight - if (2 == inputs.size()) { + if (2UL == 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]); } @@ -135,10 +132,11 @@ class ContextProjectionForwardFunc : public FunctionBase { auto out_mat = out_seq.matrix(); const auto in_mat = val_seqs.matrix(); const auto w_mat = - (2 == inputs.size()) + (2UL == inputs.size()) ? inputs[1].matrix() : typename Tensor::Matrix(nullptr, 0, 0); const auto seq_vec = val_seqs.getSequenceId().vector(); + ContextProjectionForward(out_mat, in_mat, w_mat, @@ -235,36 +233,40 @@ class ContextProjectionBackwardFunc : public FunctionBase { } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK_EQ((size_t)1, inputs.size()); - CHECK_EQ((size_t)2, outputs.size()); + CHECK_EQ(1UL, inputs.size()); + CHECK(1UL == outputs.size() || 2UL == outputs.size()); CHECK(inputs[0].isSequenceArg() && outputs[0].isSequenceArg()) << "SequenceArg required here"; const auto in_seq = dynamic_cast(inputs[0]); auto out_seq = dynamic_cast(outputs[0]); CHECK(in_seq.data() && in_seq.getSequenceId().data()); - CHECK_EQ(in_seq.shape().ndims(), (size_t)2); - CHECK_EQ(in_seq.getSequenceId().shape().ndims(), (size_t)1); - CHECK_EQ(out_seq.shape().ndims(), (size_t)2); - CHECK_EQ(out_seq.getSequenceId().shape().ndims(), (size_t)1); - CHECK_EQ(outputs[1].shape().ndims(), (size_t)2); + CHECK_EQ(in_seq.shape().ndims(), 2UL); + CHECK_EQ(out_seq.shape().ndims(), 2UL); + CHECK_EQ(out_seq.getSequenceId().shape().ndims(), 1UL); - /// 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 CHECK_EQ(out_seq.shape()[0], in_seq.shape()[0]); /// dim of output grad = dim of input grad * context_length CHECK_EQ(in_seq.shape()[1], out_seq.shape()[1] * context_length_); 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(); const auto out_grad_mat = in_seq.matrix(); auto in_grad_mat = !out_seq.data() ? typename Tensor::Matrix(nullptr, 0, 0) : out_seq.matrix(); - auto w_grad_mat = !outputs[1].data() - ? typename Tensor::Matrix(nullptr, 0, 0) - : outputs[1].matrix(); + auto w_grad_mat = + (2UL == outputs.size()) + ? outputs[1].matrix() + : typename Tensor::Matrix(nullptr, 0, 0); + ContextProjectionBackward(out_grad_mat, in_grad_mat, w_grad_mat, @@ -304,17 +306,17 @@ class ContextProjectionBackwardDataFunc : public FunctionBase { } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK_EQ(1, static_cast(inputs.size())); - CHECK_EQ(1, static_cast(outputs.size())); + CHECK_EQ(1UL, inputs.size()); + CHECK_EQ(1UL, outputs.size()); CHECK(inputs[0].isSequenceArg() && outputs[0].isSequenceArg()) << "SequenceArg required here"; const auto in_seq = dynamic_cast(inputs[0]); const auto out_seq = dynamic_cast(outputs[0]); CHECK(in_seq.data() && out_seq.data() && in_seq.getSequenceId().data()); - CHECK_EQ(static_cast(out_seq.shape().ndims()), 2); - CHECK_EQ(static_cast(in_seq.shape().ndims()), 2); - CHECK_EQ(static_cast(in_seq.getSequenceId().shape().ndims()), 1); + CHECK_EQ(out_seq.shape().ndims(), 2UL); + CHECK_EQ(in_seq.shape().ndims(), 2UL); + CHECK_EQ(in_seq.getSequenceId().shape().ndims(), 1UL); /// output layer grad dim == input layer grad dim * context_length_ CHECK_EQ(in_seq.shape().ndims(), out_seq.shape().ndims() * context_length_); /// input and output has the same batch_size @@ -355,14 +357,14 @@ class ContextProjectionBackwardWeightFunc : public FunctionBase { } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK_EQ(1, static_cast(inputs.size())); - CHECK_EQ(1, static_cast(outputs.size())); + CHECK_EQ(1UL, inputs.size()); + CHECK_EQ(1UL, outputs.size()); CHECK(inputs[0].isSequenceArg()) << "SequenceArg required here"; const auto in_seq = dynamic_cast(inputs[0]); CHECK(in_seq.data() && in_seq.getSequenceId().data() && outputs[0].data()); - CHECK_EQ(static_cast(outputs[0].shape().ndims()), 2); - CHECK_EQ(static_cast(in_seq.shape().ndims()), 2); - CHECK_EQ(static_cast(in_seq.getSequenceId().shape().ndims()), 1); + CHECK_EQ(outputs[0].shape().ndims(), 2UL); + CHECK_EQ(in_seq.shape().ndims(), 2UL); + CHECK_EQ(in_seq.getSequenceId().shape().ndims(), 1UL); CHECK_EQ(in_seq.shape()[0], outputs[0].shape()[0]); /// output layer grad dim == weight dim * context_length_ CHECK_EQ(in_seq.shape()[1], outputs[0].shape()[1] * context_length_); diff --git a/paddle/function/ContextProjectionOp.h b/paddle/function/ContextProjectionOp.h index 2bdd47e4e9b024..6f7d936379a537 100644 --- a/paddle/function/ContextProjectionOp.h +++ b/paddle/function/ContextProjectionOp.h @@ -13,7 +13,6 @@ See the License for the specific language governing permissions and limitations under the License. */ #pragma once - #include "Function.h" namespace paddle { diff --git a/paddle/function/ContextProjectionOpTest.cpp b/paddle/function/ContextProjectionOpTest.cpp index c9db2ff8008e0b..0f5d6a848d406d 100644 --- a/paddle/function/ContextProjectionOpTest.cpp +++ b/paddle/function/ContextProjectionOpTest.cpp @@ -28,55 +28,26 @@ void testMatrixProjectionForward(int context_start, std::max(0, (int)(context_start + context_length - 1)); if (pad == 0) is_padding = false; - FunctionCompare compare("ContextProjectionForward", - FuncConfig() - .set("context_length", context_length) - .set("context_start", context_start) - .set("begin_pad", std::max(0, -context_start))); - - CpuMatrix cpu_in(batch_size, input_dim); - cpu_in.randomizeUniform(); - GpuMatrix gpu_in(batch_size, input_dim); - gpu_in.copyFrom(cpu_in); - auto cpu_weight = - is_padding ? std::make_shared(pad, input_dim) : nullptr; - auto gpu_weight = - is_padding ? std::make_shared(pad, input_dim) : nullptr; - if (is_padding) { - cpu_weight->randomizeUniform(); - gpu_weight->copyFrom(*cpu_weight); + FunctionCompare test("ContextProjectionForward", + FuncConfig() + .set("context_length", context_length) + .set("context_start", context_start) + .set("begin_pad", std::max(0, -context_start))); + + // prepare input arguments + test.addSequence(SequenceIdArg(TensorShape{batch_size})); + test.addInputs( + SequenceArg(VALUE_TYPE_FLOAT, TensorShape{batch_size, input_dim})); + if (is_padding) { // weight + test.addInputs(SequenceArg(VALUE_TYPE_FLOAT, TensorShape{pad, input_dim})); } - IVectorPtr cpu_seq; - generateSequenceStartPositions(batch_size, cpu_seq); - IVectorPtr gpu_seq = IVector::create(cpu_seq->getSize(), true); - gpu_seq->copyFrom(*cpu_seq); - - 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); + test.addOutputs( + SequenceArg(VALUE_TYPE_FLOAT, + TensorShape{batch_size, input_dim * context_length}), + ADD_TO); - BufferArgs gpu_inputs; - BufferArgs gpu_outputs; - 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); + // run Function + test.run(); } void testMatrixProjectionBackward(int context_start, @@ -88,63 +59,31 @@ void testMatrixProjectionBackward(int context_start, std::max(0, (int)(context_start + context_length - 1)); if (pad == 0) is_padding = false; - FunctionCompare compare("ContextProjectionBackward", - FuncConfig() - .set("context_length", context_length) - .set("context_start", context_start) - .set("begin_pad", std::max(0, -context_start)) - .set("is_padding", is_padding) - .set("total_pad", pad)); - - CpuMatrix cpu_in_grad(batch_size, input_dim); - cpu_in_grad.randomizeUniform(); - GpuMatrix gpu_in_grad(batch_size, input_dim); - gpu_in_grad.copyFrom(cpu_in_grad); - - CpuMatrix cpu_out_grad(batch_size, input_dim * context_length); - cpu_out_grad.randomizeUniform(); - GpuMatrix gpu_out_grad(batch_size, input_dim * context_length); - gpu_out_grad.copyFrom(cpu_out_grad); - - 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(pad, input_dim) : nullptr; - auto gpu_w_grad = - is_padding ? std::make_shared(pad, input_dim) : nullptr; - if (is_padding) { - cpu_w_grad->randomizeUniform(); - gpu_w_grad->copyFrom(*cpu_w_grad); + FunctionCompare test("ContextProjectionBackward", + FuncConfig() + .set("context_length", context_length) + .set("context_start", context_start) + .set("begin_pad", std::max(0, -context_start)) + .set("is_padding", is_padding) + .set("total_pad", pad)); + + // prepare input arguments + test.addSequence(SequenceIdArg(TensorShape{batch_size})); + test.addInputs(SequenceArg( + VALUE_TYPE_FLOAT, TensorShape{batch_size, input_dim * context_length})); + test.addOutputs( + SequenceArg(VALUE_TYPE_FLOAT, TensorShape{batch_size, input_dim}), + ADD_TO); + if (is_padding) { // weight + test.addOutputs(BufferArg(VALUE_TYPE_FLOAT, TensorShape{pad, input_dim}), + ADD_TO); } - BufferArgs cpu_inputs; - BufferArgs cpu_outputs; - 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); - } + // run Function + test.run(); } -TEST(ContextProjection, projection) { +TEST(ContextProjection, Projection) { for (auto context_start : {-5, -3, -1, 0, 3}) { for (auto context_length : {1, 2, 5, 7}) { for (auto trainable_padding : {false, true}) { diff --git a/paddle/function/FunctionTest.h b/paddle/function/FunctionTest.h index 00f59f97d4c8c1..076aace14cc566 100644 --- a/paddle/function/FunctionTest.h +++ b/paddle/function/FunctionTest.h @@ -69,6 +69,54 @@ class FunctionCompare { 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(sizeId)); + gpuMemory_.emplace_back(std::make_shared(sizeId)); + cpuSeq_ = std::make_shared(cpuMemory_.back()->getBuf(), + TensorShape{numSeqs + 1}); + gpuSeq_ = std::make_shared(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(size)); + gpuMemory_.emplace_back(std::make_shared(size)); + + /// SequenceArg + cpuInputs_.emplace_back( + std::make_shared(cpuMemory_.back()->getBuf(), + input.valueType(), + input.shape(), + *cpuSeq_)); + gpuInputs_.emplace_back( + std::make_shared(gpuMemory_.back()->getBuf(), + input.valueType(), + input.shape(), + *gpuSeq_)); + } + // output need only contains shape, do not contains data. void addOutputs(const BufferArg& output, ArgType argType = ASSIGN_TO) { size_t size = @@ -86,6 +134,7 @@ class FunctionCompare { output.valueType(), output.shape(), argType)); +<<<<<<< HEAD } /// add and init output sparse matrix @@ -116,24 +165,31 @@ class FunctionCompare { std::make_shared(*gpuSparse_, argType)); } - void addInputs(const SequenceArg& input) { - 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(sizeId)); - gpuMemory_.emplace_back(std::make_shared(sizeId)); - - TensorShape seqsId({numSeqs + 1}); - // void* cpuBuffer = cpuMemory_.back()->getBuf(); - // void* gpuBuffer = gpuMemory_.back()->getBuf(); + void addOutputs(const SequenceArg& output, ArgType argType = ASSIGN_TO) { + CHECK_EQ(output.shape().ndims(), 2UL); + size_t batchSize = output.shape()[0]; + if (!cpuSeq_ || !gpuSeq_) { // sequence not exist + addSequence(SequenceIdArg(TensorShape{batchSize})); + } size_t size = - input.shape().getElements() * sizeOfValuType(input.valueType()); + output.shape().getElements() * sizeOfValuType(output.valueType()); cpuMemory_.emplace_back(std::make_shared(size)); gpuMemory_.emplace_back(std::make_shared(size)); - // TODO: need be implemented. + /// SequenceArg + cpuOutputs_.emplace_back( + std::make_shared(cpuMemory_.back()->getBuf(), + output.valueType(), + output.shape(), + *cpuSeq_, + argType)); + gpuOutputs_.emplace_back( + std::make_shared(gpuMemory_.back()->getBuf(), + output.valueType(), + output.shape(), + *gpuSeq_, + argType)); } void addInputs(const SparseMatrixArg& input) { @@ -193,14 +249,44 @@ class FunctionCompare { std::shared_ptr getGpuFunction() const { return gpuFunc_; } 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(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( + maxLen, batchSize - pos - numSeqs + i)); + buf[i] = pos; + pos += len; + VLOG(1) << " len=" << len; + } + buf[numSeqs] = batchSize; + } + void initInputs() { for (size_t i = 0; i < cpuInputs_.size(); i++) { if (cpuInputs_[i]->isSparseArg()) { continue; /// sparse matrix already init } - initArg(*cpuInputs_[i]); - + if (cpuInputs_[i]->isSequenceArg()) { + initArg(dynamic_cast(*cpuInputs_[i])); + } else { + initArg(*cpuInputs_[i]); + } // TODO: Need a BufferCopy used to copy from one BufferArg to another. CpuVector cpuVector(cpuInputs_[i]->shape().getElements(), (real*)cpuInputs_[i]->data()); @@ -217,7 +303,11 @@ class FunctionCompare { continue; /// sparse matrix already init } - initArg(*cpuOutputs_[i]); + if (cpuOutputs_[i]->isSequenceArg()) { + initArg(dynamic_cast(*cpuOutputs_[i])); + } else { + initArg(*cpuOutputs_[i]); + } // TODO: Need a BufferCopy used to copy from one BufferArg to another. CpuVector cpuVector(cpuOutputs_[i]->shape().getElements(), @@ -241,28 +331,6 @@ class FunctionCompare { } } - // 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(arg.data()); - int pos = 0; - size_t maxLen = 2 * batchSize / numSeqs; - for (int i = 0; i < (int)numSeqs; ++i) { - int len = uniformRandom( - std::min(maxLen, batchSize - pos - numSeqs + i)) + - 1; - buf[i] = pos; - pos += len; - VLOG(1) << " len=" << len; - } - buf[numSeqs] = batchSize; - } - protected: std::shared_ptr cpuFunc_; std::shared_ptr gpuFunc_; @@ -274,6 +342,8 @@ class FunctionCompare { std::vector gpuOutputs_; std::shared_ptr cpuSparse_; std::shared_ptr gpuSparse_; + std::shared_ptr cpuSeq_; + std::shared_ptr gpuSeq_; }; } // namespace paddle From e79841de9172329950b6ec1af00282321975c324 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Wed, 25 Jan 2017 10:35:47 -0800 Subject: [PATCH 152/370] fix test_LayerGrad. --- paddle/function/ContextProjectionOp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paddle/function/ContextProjectionOp.cpp b/paddle/function/ContextProjectionOp.cpp index d81ea584016060..b87750b74247bd 100644 --- a/paddle/function/ContextProjectionOp.cpp +++ b/paddle/function/ContextProjectionOp.cpp @@ -132,7 +132,7 @@ class ContextProjectionForwardFunc : public FunctionBase { auto out_mat = out_seq.matrix(); const auto in_mat = val_seqs.matrix(); const auto w_mat = - (2UL == inputs.size()) + (2UL == inputs.size() && inputs[1].data()) ? inputs[1].matrix() : typename Tensor::Matrix(nullptr, 0, 0); const auto seq_vec = val_seqs.getSequenceId().vector(); @@ -263,7 +263,7 @@ class ContextProjectionBackwardFunc : public FunctionBase { !out_seq.data() ? typename Tensor::Matrix(nullptr, 0, 0) : out_seq.matrix(); auto w_grad_mat = - (2UL == outputs.size()) + (2UL == outputs.size() && outputs[1].data()) ? outputs[1].matrix() : typename Tensor::Matrix(nullptr, 0, 0); From 02c5ecc334d282ceeafae81ab835444fb40e4445 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Tue, 7 Feb 2017 11:08:42 -0800 Subject: [PATCH 153/370] merge --- paddle/function/BufferArg.h | 2 +- paddle/function/FunctionTest.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/paddle/function/BufferArg.h b/paddle/function/BufferArg.h index f7df56846f6d7b..0dc7792f646457 100644 --- a/paddle/function/BufferArg.h +++ b/paddle/function/BufferArg.h @@ -190,7 +190,7 @@ class SequenceIdArg : public BufferArg { : BufferArg(VALUE_TYPE_INT32, shape, argType) { bufferType_ = TENSOR_SEQUENCE_ID; CHECK_EQ(shape_.ndims(), 1UL); - CHECK_GT(shape_[0], 1UL); + CHECK_GE(shape_[0], 1UL); numSeqs_ = shape_[0] - 1; } diff --git a/paddle/function/FunctionTest.h b/paddle/function/FunctionTest.h index 076aace14cc566..0cfafdb27f55a3 100644 --- a/paddle/function/FunctionTest.h +++ b/paddle/function/FunctionTest.h @@ -134,7 +134,6 @@ class FunctionCompare { output.valueType(), output.shape(), argType)); -<<<<<<< HEAD } /// add and init output sparse matrix From 0b7e7876ff715da9908ce66ef58ddeb3f30675fe Mon Sep 17 00:00:00 2001 From: xuwei06 Date: Tue, 7 Feb 2017 15:30:44 -0800 Subject: [PATCH 154/370] Fix mkDirRecursively Change-Id: Ie09fd666ca208994f22e9f83af6072f4d5e6aa1a --- paddle/utils/Util.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/paddle/utils/Util.cpp b/paddle/utils/Util.cpp index 220aac1ff11e0f..dbab4ec43ca2fa 100644 --- a/paddle/utils/Util.cpp +++ b/paddle/utils/Util.cpp @@ -289,6 +289,7 @@ void mkDir(const char* filename) { void mkDirRecursively(const char* dir) { struct stat sb; + if (*dir == 0) return; // empty string if (!stat(dir, &sb)) return; mkDirRecursively(path::dirname(dir).c_str()); From 9ee72367eeb667b8aad8e294964e319d37c3b674 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Tue, 3 Jan 2017 18:26:46 -0800 Subject: [PATCH 155/370] Cosine Simlarity Forward Paddle Function. --- paddle/function/CosSimOp.cpp | 93 ++++++++++++++++++++++++++++ paddle/function/CosSimOp.h | 40 ++++++++++++ paddle/function/CosSimOpGpu.cu | 102 +++++++++++++++++++++++++++++++ paddle/function/CosSimOpTest.cpp | 63 +++++++++++++++++++ 4 files changed, 298 insertions(+) create mode 100644 paddle/function/CosSimOp.cpp create mode 100644 paddle/function/CosSimOp.h create mode 100644 paddle/function/CosSimOpGpu.cu create mode 100644 paddle/function/CosSimOpTest.cpp diff --git a/paddle/function/CosSimOp.cpp b/paddle/function/CosSimOp.cpp new file mode 100644 index 00000000000000..c1473a19ede5c4 --- /dev/null +++ b/paddle/function/CosSimOp.cpp @@ -0,0 +1,93 @@ +/* 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 { +template <> +void CosSimForward(CpuMatrix* out_mat, + const CpuMatrix* in1_mat, + const CpuMatrix* in2_mat, + real scale) { + CHECK(out_mat && in1_mat && in2_mat); + 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) { + /// for each row, todo(tianbing), use TensorExpression square2 ? + 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)); + } +} + +/** + * \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 +class CosSimForwardFunc : public FunctionBase { + void init(const FuncConfig& config) override { + scale_ = config.get("scale"); + } + + void calc(const Arguments& inputs, + const Arguments& outputs, + const Arguments& inouts) override { + CHECK_EQ(inputs.size(), 2); + CHECK_EQ(outputs.size(), 1); + CHECK_EQ(inouts.size(), 0); + + CHECK_EQ(inputs[0].dims_[0], outputs[0].dims_[0]); + CHECK_EQ(inputs[0].dims_[1], inputs[1].dims_[1]); + CHECK_EQ(outputs[0].dims_[1], 1UL); + + CHECK(outputs[0].getData() && inputs[0].getData() && inputs[1].getData()); + auto out_mat = std::make_shared::type>( + outputs[0].getData(), outputs[0].dims_[0], outputs[0].dims_[1]); + const auto in1_mat = std::make_shared::type>( + inputs[0].getData(), inputs[0].dims_[0], inputs[0].dims_[1]); + const auto in2_mat = std::make_shared::type>( + inputs[1].getData(), inputs[1].dims_[0], inputs[1].dims_[1]); + + CosSimForward(out_mat.get(), in1_mat.get(), in2_mat.get(), scale_); + } + +private: + real scale_; +}; + +REGISTER_TYPED_FUNC(CosSimForward, CPU, CosSimForwardFunc); +#ifndef PADDLE_ONLY_CPU +REGISTER_TYPED_FUNC(CosSimForward, GPU, CosSimForwardFunc); +#endif +} // namespace paddle diff --git a/paddle/function/CosSimOp.h b/paddle/function/CosSimOp.h new file mode 100644 index 00000000000000..02250d6db9c644 --- /dev/null +++ b/paddle/function/CosSimOp.h @@ -0,0 +1,40 @@ +/* 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 data. + * \param[in] intput1 input data. + * \param[in] intput2 input data. + * \param[in] scale default 1.0. + * + */ +template +void CosSimForward(typename MatrixT::type* output, + const typename MatrixT::type* input1, + const typename MatrixT::type* input2, + real scale); + +} // namespace paddle diff --git a/paddle/function/CosSimOpGpu.cu b/paddle/function/CosSimOpGpu.cu new file mode 100644 index 00000000000000..34835fa5d87c39 --- /dev/null +++ b/paddle/function/CosSimOpGpu.cu @@ -0,0 +1,102 @@ +/* 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 "CosSimOp.h" + +namespace paddle { + +template +__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<<>> + (output, input1, input2, width, input1_height, input2_height, scale); + CHECK_SYNC("hl_cossim failed"); +} + +template <> +void CosSimForward(GpuMatrix* out_mat, + const GpuMatrix* in1_mat, + const GpuMatrix* in2_mat, + real scale) { + CHECK(out_mat && in1_mat && in2_mat); + CHECK(in1_mat->useGpu_ == true && in2_mat->useGpu_ == true) + << "Matrix type are not GPU"; + + size_t numSamples = 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); +} + +} // namespace paddle diff --git a/paddle/function/CosSimOpTest.cpp b/paddle/function/CosSimOpTest.cpp new file mode 100644 index 00000000000000..49c54620feb355 --- /dev/null +++ b/paddle/function/CosSimOpTest.cpp @@ -0,0 +1,63 @@ +/* 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 +#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 compare("CosSimForward", FuncConfig().set("scale", scale)); + + CpuMatrix cpu_arg1(height_x, width); + CpuMatrix gpu_arg1(height_x, width); + CpuMatrix cpu_arg2(height_y, width); + CpuMatrix gpu_arg2(height_y, width); + cpu_arg1.randomizeUniform(); + gpu_arg1.copyFrom(cpu_arg1); + cpu_arg2.randomizeUniform(); + cpu_arg2.add(-0.5); + gpu_arg2.copyFrom(cpu_arg2); + CpuMatrix cpu_out(height_x, 1); + GpuMatrix gpu_out(height_x, 1); + + compare.getCpuFunction()->calc( + {Tensor(cpu_arg1.getData(), Dims{height_x, width}), + Tensor(cpu_arg2.getData(), Dims{height_y, width})}, + {Tensor(cpu_out.getData(), Dims{height_x, 1})}, + {}); + compare.getGpuFunction()->calc( + {Tensor(gpu_arg1.getData(), Dims{height_x, width}), + Tensor(gpu_arg2.getData(), Dims{height_y, width})}, + {Tensor(gpu_out.getData(), Dims{height_x, 1})}, + {}); + + autotest::TensorCheckErr(cpu_out, gpu_out); +} + +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); + } + } + } + } +} From ccac20d2db4c61df1de0877d77f6e5c07a8cf0f1 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Tue, 3 Jan 2017 21:25:54 -0800 Subject: [PATCH 156/370] add Cosine Similarity Backward function. --- paddle/function/CosSimOp.cpp | 122 ++++++++++++++++++++++++++ paddle/function/CosSimOp.h | 21 +++++ paddle/function/CosSimOpGpu.cu | 142 ++++++++++++++++++++++++++++++- paddle/function/CosSimOpTest.cpp | 70 ++++++++++++++- 4 files changed, 352 insertions(+), 3 deletions(-) diff --git a/paddle/function/CosSimOp.cpp b/paddle/function/CosSimOp.cpp index c1473a19ede5c4..0ed5991ff1382e 100644 --- a/paddle/function/CosSimOp.cpp +++ b/paddle/function/CosSimOp.cpp @@ -86,8 +86,130 @@ class CosSimForwardFunc : public FunctionBase { real scale_; }; +template <> +void CosSimBackward(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 && out_val && in1_val && in2_val && in1_grad && in2_grad); + 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); + } + } + } +} + +/** + * \param inputs[0] output value 1, size: nSamples * 1. + * \param inputs[1] input value 1, size: nSamples * dim. + * \param inputs[2] input value 2, size: n2 * dim (n2 == 1 or n2 == nSamples). + * \param inputs[3] input grad 1, size: nSamples * dim. + * \param inputs[4] input grad 2, size: n2 * dim (n2 == 1 or n2 == nSamples). + * \param outputs[0] output grad, size : nSamples * 1. + */ +template +class CosSimBackwardFunc : public FunctionBase { + void init(const FuncConfig& config) override { + scale_ = config.get("scale"); + } + + void calc(const Arguments& inputs, + const Arguments& outputs, + const Arguments& inouts) override { + CHECK_EQ(inputs.size(), 5); + CHECK_EQ(outputs.size(), 1); + CHECK_EQ(inouts.size(), 0); + /// dim of out_grad and out_val == 1, column vector + CHECK_EQ(outputs[0].dims_[1], 1UL); + CHECK_EQ(inputs[0].dims_[1], 1UL); + /// nSamples of out_grad == out_val == in_val1 == in_grad1 + CHECK_EQ(inputs[0].dims_[0], outputs[0].dims_[0]); + CHECK_EQ(inputs[1].dims_[0], outputs[0].dims_[0]); + CHECK_EQ(inputs[3].dims_[0], outputs[0].dims_[0]); + /// dim of in1_val1 == in_val2 == in_grad1 == in_grad2 + CHECK_EQ(inputs[2].dims_[1], inputs[1].dims_[1]); + CHECK_EQ(inputs[3].dims_[1], inputs[1].dims_[1]); + CHECK_EQ(inputs[4].dims_[1], inputs[1].dims_[1]); + + CHECK(outputs[0].getData() && inputs[0].getData() && inputs[1].getData() && + inputs[2].getData() && inputs[3].getData() && inputs[4].getData()); + const auto out_grad = std::make_shared::type>( + outputs[0].getData(), outputs[0].dims_[0], outputs[0].dims_[1]); + const auto out_val = std::make_shared::type>( + inputs[0].getData(), inputs[0].dims_[0], inputs[0].dims_[1]); + const auto in1_val = std::make_shared::type>( + inputs[1].getData(), inputs[1].dims_[0], inputs[1].dims_[1]); + const auto in2_val = std::make_shared::type>( + inputs[2].getData(), inputs[2].dims_[0], inputs[2].dims_[1]); + auto in1_grad = std::make_shared::type>( + inputs[3].getData(), inputs[3].dims_[0], inputs[3].dims_[1]); + auto in2_grad = std::make_shared::type>( + inputs[4].getData(), inputs[4].dims_[0], inputs[4].dims_[1]); + + CosSimBackward(out_grad.get(), + out_val.get(), + in1_val.get(), + in2_val.get(), + in1_grad.get(), + in2_grad.get(), + 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 diff --git a/paddle/function/CosSimOp.h b/paddle/function/CosSimOp.h index 02250d6db9c644..f66a4344d09ce8 100644 --- a/paddle/function/CosSimOp.h +++ b/paddle/function/CosSimOp.h @@ -37,4 +37,25 @@ void CosSimForward(typename MatrixT::type* output, const typename MatrixT::type* input2, real scale); +/** + * \brief Cosine Similarity BackWard for Derivative. + * + * \param[out] output1 backward loss output grad. + * \param[in] input1 forward-output value. + * \param[in] input2 forward input value 1. + * \param[in] input3 forward input value 2. + * \param[in] input4 forward input grad 1. + * \param[in] input5 forward input grad 2. + * \param[in] scale default 1.0. + * + */ +template +void CosSimBackward(const typename MatrixT::type* out_grad, + const typename MatrixT::type* out_value, + const typename MatrixT::type* in1_value, + const typename MatrixT::type* in2_value, + typename MatrixT::type* in1_grad, + typename MatrixT::type* in2_grad, + real scale); + } // namespace paddle diff --git a/paddle/function/CosSimOpGpu.cu b/paddle/function/CosSimOpGpu.cu index 34835fa5d87c39..f654f0bc209c24 100644 --- a/paddle/function/CosSimOpGpu.cu +++ b/paddle/function/CosSimOpGpu.cu @@ -13,6 +13,7 @@ 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 { @@ -79,7 +80,7 @@ void hlCossim(real* output, KeCosSim<<>> (output, input1, input2, width, input1_height, input2_height, scale); - CHECK_SYNC("hl_cossim failed"); + CHECK_SYNC("hlCossim failed"); } template <> @@ -91,7 +92,7 @@ void CosSimForward(GpuMatrix* out_mat, CHECK(in1_mat->useGpu_ == true && in2_mat->useGpu_ == true) << "Matrix type are not GPU"; - size_t numSamples = out_mat->getHeight(); + size_t num_samples = out_mat->getHeight(); size_t dim = in1_mat->getWidth(); real* out = out_mat->getData(); const real* x = in1_mat->getData(); @@ -99,4 +100,141 @@ void CosSimForward(GpuMatrix* out_mat, hlCossim(out, x, y, dim, in1_mat->getHeight(), in2_mat->getHeight(), scale); } +template +__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<<>> + (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(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 && out_val && in1_val && in2_val && in1_grad && in2_grad); + 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 diff --git a/paddle/function/CosSimOpTest.cpp b/paddle/function/CosSimOpTest.cpp index 49c54620feb355..0d2ece2b98625a 100644 --- a/paddle/function/CosSimOpTest.cpp +++ b/paddle/function/CosSimOpTest.cpp @@ -50,7 +50,7 @@ void testCosSimForward(size_t height_x, autotest::TensorCheckErr(cpu_out, gpu_out); } -TEST(Matrix, cosSim) { +TEST(Matrix, cosSimForward) { for (auto height_x : {10, 100, 1000}) { for (auto height_y : {1, height_x}) { for (auto width : {10, 100, 1000}) { @@ -61,3 +61,71 @@ TEST(Matrix, cosSim) { } } } + +void testCosSimBackward(size_t height_x, + size_t height_y, + size_t width, + real scale) { + FunctionCompare compare("CosSimBackward", FuncConfig().set("scale", scale)); + + CpuMatrix cpu_out_grad(height_x, 1); + CpuMatrix cpu_out_val(height_x, 1); + CpuMatrix cpu_in1_val(height_x, width); + CpuMatrix cpu_in2_val(height_x, width); + CpuMatrix cpu_in1_grad(height_x, width); + CpuMatrix cpu_in2_grad(height_x, width); + + cpu_out_grad.randomizeUniform(); + cpu_out_val.randomizeUniform(); + cpu_in1_val.randomizeUniform(); + cpu_in2_val.randomizeUniform(); + cpu_in1_grad.randomizeUniform(); + cpu_in2_grad.randomizeUniform(); + + GpuMatrix gpu_out_grad(height_x, 1); + GpuMatrix gpu_out_val(height_x, 1); + GpuMatrix gpu_in1_val(height_x, width); + GpuMatrix gpu_in2_val(height_x, width); + GpuMatrix gpu_in1_grad(height_x, width); + GpuMatrix gpu_in2_grad(height_x, width); + + gpu_out_grad.copyFrom(cpu_out_grad); + gpu_out_val.copyFrom(cpu_out_val); + gpu_in1_val.copyFrom(cpu_in1_val); + gpu_in2_val.copyFrom(cpu_in2_val); + gpu_in1_grad.copyFrom(cpu_in1_grad); + gpu_in2_grad.copyFrom(cpu_in2_grad); + + compare.getCpuFunction()->calc( + {Tensor(cpu_out_val.getData(), Dims{height_x, 1}), + Tensor(cpu_in1_val.getData(), Dims{height_x, width}), + Tensor(cpu_in2_val.getData(), Dims{height_x, width}), + Tensor(cpu_in1_grad.getData(), Dims{height_x, width}), + Tensor(cpu_in2_grad.getData(), Dims{height_x, width})}, + {Tensor(cpu_out_grad.getData(), Dims{height_x, 1})}, + {}); + + compare.getGpuFunction()->calc( + {Tensor(gpu_out_val.getData(), Dims{height_x, 1}), + Tensor(gpu_in1_val.getData(), Dims{height_x, width}), + Tensor(gpu_in2_val.getData(), Dims{height_x, width}), + Tensor(gpu_in1_grad.getData(), Dims{height_x, width}), + Tensor(gpu_in2_grad.getData(), Dims{height_x, width})}, + {Tensor(gpu_out_grad.getData(), Dims{height_x, 1})}, + {}); + + autotest::TensorCheckErr(cpu_in1_grad, gpu_in1_grad); + autotest::TensorCheckErr(cpu_in2_grad, gpu_in2_grad); +} + +TEST(Matrix, cosSimBackward) { + for (auto height_x : {1, 10, 100}) { + for (auto height_y : {1, height_x}) { + for (auto width : {1, 10, 100}) { + for (auto scale : {1.0, 2.0}) { + testCosSimBackward(height_x, height_y, width, scale); + } + } + } + } +} From 58827e3e961aeac162eee4e9e80b9ff5b7864ff8 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Wed, 4 Jan 2017 14:37:08 -0800 Subject: [PATCH 157/370] update forward/backward in CosSimLayer and CosSimVecMatLayer. --- paddle/gserver/layers/CosSimLayer.cpp | 46 ++++++++++---- paddle/gserver/layers/CosSimLayer.h | 2 +- paddle/gserver/layers/CosSimVecMatLayer.cpp | 70 ++++++++++++++------- paddle/gserver/layers/CosSimVecMatLayer.h | 52 +++++++++++++++ 4 files changed, 135 insertions(+), 35 deletions(-) create mode 100644 paddle/gserver/layers/CosSimVecMatLayer.h diff --git a/paddle/gserver/layers/CosSimLayer.cpp b/paddle/gserver/layers/CosSimLayer.cpp index 254120443dc3d4..ac66fd4712af48 100644 --- a/paddle/gserver/layers/CosSimLayer.cpp +++ b/paddle/gserver/layers/CosSimLayer.cpp @@ -26,15 +26,23 @@ bool CosSimLayer::init(const LayerMap& layerMap, Layer::init(layerMap, parameterMap); 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; } void CosSimLayer::forward(PassType passType) { Layer::forward(passType); - /* malloc memory for the output_ if necessary */ int batchSize = getInputValue(0)->getHeight(); int size = getSize(); + CHECK_EQ(forward_.size(), 1) << "Only one forward function needed"; { REGISTER_TIMER_INFO("CosFwResetTimer", getName().c_str()); @@ -42,26 +50,42 @@ void CosSimLayer::forward(PassType passType) { } MatrixPtr outV = getOutputValue(); - /* activation */ { REGISTER_TIMER_INFO("CosFwAtvTimer", getName().c_str()); MatrixPtr prevOut1 = getInputValue(0); MatrixPtr prevOut2 = getInputValue(1); - outV->cosSim(*prevOut1, *prevOut2, config_.cos_scale()); + + CHECK(outV && prevOut1 && prevOut2); + forward_[0]->calc( + {Tensor(prevOut1->getData(), + Dims{prevOut1->getHeight(), prevOut1->getWidth()}), + Tensor(prevOut2->getData(), + Dims{prevOut2->getHeight(), prevOut2->getWidth()})}, + {Tensor(outV->getData(), Dims{outV->getHeight(), outV->getWidth()})}, + {}); } } void CosSimLayer::backward(const UpdateCallback& callback) { /* activation */ { REGISTER_TIMER_INFO("CosBpAtvTimer", getName().c_str()); - MatrixPtr outG = this->getOutputGrad(); - - outG->cosSimDerivative(*this->getOutputValue(), - *getInputValue(0), - *getInputValue(1), - *getInputGrad(0), - *getInputGrad(1), - config_.cos_scale()); + CHECK_EQ(backward_.size(), 1) << "Only one backward function needed"; + + const auto outG = this->getOutputGrad(); + const auto outV = this->getOutputValue(); + const auto inV1 = this->getInputValue(0); + const auto inV2 = this->getInputValue(1); + auto inG1 = this->getInputGrad(0); + auto inG2 = this->getInputGrad(1); + CHECK(outG && outV && inV1 && inV2 && inG1 && inG2); + backward_[0]->calc( + {Tensor(outV->getData(), Dims{outV->getHeight(), outV->getWidth()}), + Tensor(inV1->getData(), Dims{inV1->getHeight(), inV1->getWidth()}), + Tensor(inV2->getData(), Dims{inV2->getHeight(), inV2->getWidth()}), + Tensor(inG1->getData(), Dims{inG1->getHeight(), inG1->getWidth()}), + Tensor(inG2->getData(), Dims{inG2->getHeight(), inG2->getWidth()})}, + {Tensor(outG->getData(), Dims{outG->getHeight(), outG->getWidth()})}, + {}); } } diff --git a/paddle/gserver/layers/CosSimLayer.h b/paddle/gserver/layers/CosSimLayer.h index 65549626098f08..8afaee62c2dcac 100644 --- a/paddle/gserver/layers/CosSimLayer.h +++ b/paddle/gserver/layers/CosSimLayer.h @@ -28,7 +28,7 @@ namespace paddle { * * - Input1: A vector (batchSize * 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. */ diff --git a/paddle/gserver/layers/CosSimVecMatLayer.cpp b/paddle/gserver/layers/CosSimVecMatLayer.cpp index 5f652319e56202..427191e540778a 100644 --- a/paddle/gserver/layers/CosSimVecMatLayer.cpp +++ b/paddle/gserver/layers/CosSimVecMatLayer.cpp @@ -12,8 +12,7 @@ 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 "Layer.h" -#include "paddle/math/Matrix.h" +#include "CosSimVecMatLayer.h" #include "paddle/utils/Logging.h" #include "paddle/utils/Stat.h" @@ -98,11 +97,23 @@ bool CosSimVecMatLayer::init(const LayerMap& layerMap, dataDim, /* trans= */ false, useGpu_); + + /// todo(tianbing), do we really need to check these shared pointers? + 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; } void CosSimVecMatLayer::forward(PassType passType) { Layer::forward(passType); + CHECK_EQ(forward_.size(), 1) << "Only one forward function needed"; MatrixPtr inV0 = getInputValue(0); MatrixPtr inV1 = getInputValue(1); @@ -118,17 +129,26 @@ void CosSimVecMatLayer::forward(PassType passType) { } MatrixPtr outV = getOutputValue(); - + CHECK(outV && inV0 && inV1); REGISTER_TIMER_INFO("FwCosVMTimer", getName().c_str()); for (size_t i = 0; i < batchSize; i++) { tmpRow0->setData(inV0->rowBuf(i)); tmpMtx0->setData(inV1->rowBuf(i)); tmpRow2->setData(outV->rowBuf(i)); - tmpRow2->cosSim(*(tmpMtx0), *(tmpRow0), config_.cos_scale()); + + forward_[0]->calc({Tensor(tmpMtx0->getData(), + Dims{tmpMtx0->getHeight(), tmpMtx0->getWidth()}), + Tensor(tmpRow0->getData(), + Dims{tmpRow0->getHeight(), tmpRow0->getWidth()})}, + {Tensor(tmpRow2->getData(), + Dims{tmpRow2->getHeight(), tmpRow2->getWidth()})}, + {}); } } void CosSimVecMatLayer::backward(const UpdateCallback& callback) { + CHECK_EQ(backward_.size(), 1) << "Only one forward function needed"; + MatrixPtr inV0 = getInputValue(0); MatrixPtr inV1 = getInputValue(1); MatrixPtr inG0 = getInputGrad(0); @@ -137,27 +157,31 @@ void CosSimVecMatLayer::backward(const UpdateCallback& callback) { MatrixPtr outG = getOutputGrad(); size_t batchSize = inV0->getHeight(); - + CHECK(inV0 && inV1 && inG0 && inG1 && outV && outG); REGISTER_TIMER_INFO("BwCosVMTimer", getName().c_str()); - if (inG0 && inG1) { - for (size_t i = 0; i < batchSize; i++) { - tmpRow0->setData(inV0->rowBuf(i)); - tmpRow1->setData(inG0->rowBuf(i)); - tmpMtx0->setData(inV1->rowBuf(i)); - tmpMtx1->setData(inG1->rowBuf(i)); - tmpRow2->setData(outV->rowBuf(i)); - tmpRow3->setData(outG->rowBuf(i)); - - tmpRow3->cosSimDerivative(*(tmpRow2), - *(tmpMtx0), - *(tmpRow0), - *(tmpMtx1), - *(tmpRow1), - config_.cos_scale()); - } - } else { - CHECK(!inG0 || !inG1) << "Not supported"; + for (size_t i = 0; i < batchSize; i++) { + tmpRow0->setData(inV0->rowBuf(i)); + tmpRow1->setData(inG0->rowBuf(i)); + tmpMtx0->setData(inV1->rowBuf(i)); + tmpMtx1->setData(inG1->rowBuf(i)); + tmpRow2->setData(outV->rowBuf(i)); + tmpRow3->setData(outG->rowBuf(i)); + + backward_[0]->calc( + {Tensor(tmpRow2->getData(), + Dims{tmpRow2->getHeight(), tmpRow2->getWidth()}), + Tensor(tmpMtx0->getData(), + Dims{tmpMtx0->getHeight(), tmpMtx0->getWidth()}), + Tensor(tmpRow0->getData(), + Dims{tmpRow0->getHeight(), tmpRow0->getWidth()}), + Tensor(tmpMtx1->getData(), + Dims{tmpMtx1->getHeight(), tmpMtx1->getWidth()}), + Tensor(tmpRow1->getData(), + Dims{tmpRow1->getHeight(), tmpRow1->getWidth()})}, + {Tensor(tmpRow3->getData(), + Dims{tmpRow3->getHeight(), tmpRow3->getWidth()})}, + {}); } } diff --git a/paddle/gserver/layers/CosSimVecMatLayer.h b/paddle/gserver/layers/CosSimVecMatLayer.h new file mode 100644 index 00000000000000..bee83b58154b67 --- /dev/null +++ b/paddle/gserver/layers/CosSimVecMatLayer.h @@ -0,0 +1,52 @@ +/* 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 "Layer.h" +#include "paddle/math/Matrix.h" + +namespace paddle { +/** + * @brief A layer for computing cosine similarity between a vector + * and each row of a matrix + * out[i] = cos_scale * cos(in1, in2(i,:)); + * @note used in NEURAL TURING MACHINE + * + * Input1: a vector (batchSize * dataDim) + * + * Input2: a matrix in vector form (batchSize * (weightDim*dataDim)) + * + * Output: a vector (batchSize * weightDim) + */ + +class CosSimVecMatLayer : public Layer { +public: + explicit CosSimVecMatLayer(const LayerConfig& config) : Layer(config) {} + + ~CosSimVecMatLayer() {} + + bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + + void forward(PassType passType); + void backward(const UpdateCallback& callback = nullptr); + +protected: + MatrixPtr tmpMtx0; + MatrixPtr tmpMtx1; + MatrixPtr tmpRow0; + MatrixPtr tmpRow1; + MatrixPtr tmpRow2; + MatrixPtr tmpRow3; +}; + +} // namespace paddle From a948eea3ed84f950c6c95d84431eeb3717951fc3 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Wed, 4 Jan 2017 15:53:53 -0800 Subject: [PATCH 158/370] clean unused code. --- paddle/cuda/include/hl_matrix.h | 42 ----- paddle/cuda/include/stub/hl_matrix_stub.h | 19 --- paddle/cuda/src/hl_cuda_matrix.cu | 171 -------------------- paddle/function/CosSimOp.cpp | 52 +++--- paddle/function/CosSimOp.h | 20 +-- paddle/function/CosSimOpTest.cpp | 24 +-- paddle/gserver/layers/CosSimLayer.cpp | 12 +- paddle/gserver/layers/CosSimVecMatLayer.cpp | 14 +- paddle/gserver/layers/CosSimVecMatLayer.h | 2 + paddle/math/Matrix.cpp | 152 ----------------- paddle/math/Matrix.h | 36 ----- paddle/math/tests/test_Matrix.cpp | 22 --- paddle/math/tests/test_matrixCompare.cpp | 55 ------- 13 files changed, 64 insertions(+), 557 deletions(-) diff --git a/paddle/cuda/include/hl_matrix.h b/paddle/cuda/include/hl_matrix.h index 40828dd5cc76f4..6f21b82afdc6cd 100644 --- a/paddle/cuda/include/hl_matrix.h +++ b/paddle/cuda/include/hl_matrix.h @@ -188,48 +188,6 @@ extern void hl_param_relu_backward_diff(real* grad_o, int width, int height, 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]. diff --git a/paddle/cuda/include/stub/hl_matrix_stub.h b/paddle/cuda/include/stub/hl_matrix_stub.h index a1712d1e4d2a5d..f4e6461cdcf198 100644 --- a/paddle/cuda/include/stub/hl_matrix_stub.h +++ b/paddle/cuda/include/stub/hl_matrix_stub.h @@ -74,25 +74,6 @@ inline void hl_param_relu_backward_diff(real* grad_o, int height, 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, real* B_d, const int channel, diff --git a/paddle/cuda/src/hl_cuda_matrix.cu b/paddle/cuda/src/hl_cuda_matrix.cu index cd23bd31057c5c..96c07d9c3b7a37 100644 --- a/paddle/cuda/src/hl_cuda_matrix.cu +++ b/paddle/cuda/src/hl_cuda_matrix.cu @@ -584,177 +584,6 @@ void hl_param_relu_backward_diff(real* grad_o, CHECK_SYNC("hl_param_relu_backward_diff failed"); } -template -__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<<>> - (output, input1, input2, width, input1_height, input2_height, scale); - CHECK_SYNC("hl_cossim failed"); -} - -template -__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<<>> - (grad, output, prevOutX, prevOutY, prevGradX, prevGradY, width, - input1_height, input2_height, scale); - CHECK_SYNC("hl_cossim_derivate failed"); -} - __global__ void KeMatrixAddSharedBias(real* A, real* B, const int channel, diff --git a/paddle/function/CosSimOp.cpp b/paddle/function/CosSimOp.cpp index 0ed5991ff1382e..bcc17fd5319c6a 100644 --- a/paddle/function/CosSimOp.cpp +++ b/paddle/function/CosSimOp.cpp @@ -34,7 +34,6 @@ void CosSimForward(CpuMatrix* out_mat, 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) { - /// for each row, todo(tianbing), use TensorExpression square2 ? real square_sum_x = 0; real square_sum_y = 0; real xy = 0; @@ -147,12 +146,15 @@ void CosSimBackward(const CpuMatrix* out_grad, } /** - * \param inputs[0] output value 1, size: nSamples * 1. - * \param inputs[1] input value 1, size: nSamples * dim. - * \param inputs[2] input value 2, size: n2 * dim (n2 == 1 or n2 == nSamples). - * \param inputs[3] input grad 1, size: nSamples * dim. - * \param inputs[4] input grad 2, size: n2 * dim (n2 == 1 or n2 == nSamples). - * \param outputs[0] output grad, size : nSamples * 1. + * \param inouts[0] forward input grad 1, size: nSamples * dim. + * \param inouts[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 class CosSimBackwardFunc : public FunctionBase { @@ -163,35 +165,35 @@ class CosSimBackwardFunc : public FunctionBase { void calc(const Arguments& inputs, const Arguments& outputs, const Arguments& inouts) override { - CHECK_EQ(inputs.size(), 5); - CHECK_EQ(outputs.size(), 1); - CHECK_EQ(inouts.size(), 0); + CHECK_EQ(inputs.size(), 4); + CHECK_EQ(outputs.size(), 0); + CHECK_EQ(inouts.size(), 2); /// dim of out_grad and out_val == 1, column vector - CHECK_EQ(outputs[0].dims_[1], 1UL); CHECK_EQ(inputs[0].dims_[1], 1UL); + CHECK_EQ(inputs[1].dims_[1], 1UL); /// nSamples of out_grad == out_val == in_val1 == in_grad1 - CHECK_EQ(inputs[0].dims_[0], outputs[0].dims_[0]); - CHECK_EQ(inputs[1].dims_[0], outputs[0].dims_[0]); - CHECK_EQ(inputs[3].dims_[0], outputs[0].dims_[0]); + CHECK_EQ(inputs[1].dims_[0], inputs[0].dims_[0]); + CHECK_EQ(inputs[0].dims_[0], inputs[0].dims_[0]); + CHECK_EQ(inouts[0].dims_[0], inputs[0].dims_[0]); /// dim of in1_val1 == in_val2 == in_grad1 == in_grad2 - CHECK_EQ(inputs[2].dims_[1], inputs[1].dims_[1]); - CHECK_EQ(inputs[3].dims_[1], inputs[1].dims_[1]); - CHECK_EQ(inputs[4].dims_[1], inputs[1].dims_[1]); + CHECK_EQ(inputs[3].dims_[1], inputs[2].dims_[1]); + CHECK_EQ(inouts[0].dims_[1], inputs[2].dims_[1]); + CHECK_EQ(inouts[1].dims_[1], inputs[2].dims_[1]); - CHECK(outputs[0].getData() && inputs[0].getData() && inputs[1].getData() && - inputs[2].getData() && inputs[3].getData() && inputs[4].getData()); + CHECK(inputs[0].getData() && inputs[1].getData() && inputs[2].getData() && + inputs[3].getData() && inouts[0].getData() && inouts[1].getData()); const auto out_grad = std::make_shared::type>( - outputs[0].getData(), outputs[0].dims_[0], outputs[0].dims_[1]); - const auto out_val = std::make_shared::type>( inputs[0].getData(), inputs[0].dims_[0], inputs[0].dims_[1]); - const auto in1_val = std::make_shared::type>( + const auto out_val = std::make_shared::type>( inputs[1].getData(), inputs[1].dims_[0], inputs[1].dims_[1]); - const auto in2_val = std::make_shared::type>( + const auto in1_val = std::make_shared::type>( inputs[2].getData(), inputs[2].dims_[0], inputs[2].dims_[1]); - auto in1_grad = std::make_shared::type>( + const auto in2_val = std::make_shared::type>( inputs[3].getData(), inputs[3].dims_[0], inputs[3].dims_[1]); + auto in1_grad = std::make_shared::type>( + inouts[0].getData(), inouts[0].dims_[0], inouts[0].dims_[1]); auto in2_grad = std::make_shared::type>( - inputs[4].getData(), inputs[4].dims_[0], inputs[4].dims_[1]); + inouts[1].getData(), inouts[1].dims_[0], inouts[1].dims_[1]); CosSimBackward(out_grad.get(), out_val.get(), diff --git a/paddle/function/CosSimOp.h b/paddle/function/CosSimOp.h index f66a4344d09ce8..ed1f1e4d5345e2 100644 --- a/paddle/function/CosSimOp.h +++ b/paddle/function/CosSimOp.h @@ -25,9 +25,9 @@ namespace paddle { * = 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 data. - * \param[in] intput1 input data. - * \param[in] intput2 input data. + * \param[out] output output value. + * \param[in] intput1 input value. + * \param[in] intput2 input value. * \param[in] scale default 1.0. * */ @@ -40,13 +40,13 @@ void CosSimForward(typename MatrixT::type* output, /** * \brief Cosine Similarity BackWard for Derivative. * - * \param[out] output1 backward loss output grad. - * \param[in] input1 forward-output value. - * \param[in] input2 forward input value 1. - * \param[in] input3 forward input value 2. - * \param[in] input4 forward input grad 1. - * \param[in] input5 forward input grad 2. - * \param[in] scale default 1.0. + * \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 diff --git a/paddle/function/CosSimOpTest.cpp b/paddle/function/CosSimOpTest.cpp index 0d2ece2b98625a..f0e81ee0434178 100644 --- a/paddle/function/CosSimOpTest.cpp +++ b/paddle/function/CosSimOpTest.cpp @@ -97,22 +97,22 @@ void testCosSimBackward(size_t height_x, gpu_in2_grad.copyFrom(cpu_in2_grad); compare.getCpuFunction()->calc( - {Tensor(cpu_out_val.getData(), Dims{height_x, 1}), + {Tensor(cpu_out_grad.getData(), Dims{height_x, 1}), + Tensor(cpu_out_val.getData(), Dims{height_x, 1}), Tensor(cpu_in1_val.getData(), Dims{height_x, width}), - Tensor(cpu_in2_val.getData(), Dims{height_x, width}), - Tensor(cpu_in1_grad.getData(), Dims{height_x, width}), - Tensor(cpu_in2_grad.getData(), Dims{height_x, width})}, - {Tensor(cpu_out_grad.getData(), Dims{height_x, 1})}, - {}); + Tensor(cpu_in2_val.getData(), Dims{height_x, width})}, + {}, + {Tensor(cpu_in1_grad.getData(), Dims{height_x, width}), + Tensor(cpu_in2_grad.getData(), Dims{height_x, width})}); compare.getGpuFunction()->calc( - {Tensor(gpu_out_val.getData(), Dims{height_x, 1}), + {Tensor(gpu_out_grad.getData(), Dims{height_x, 1}), + Tensor(gpu_out_val.getData(), Dims{height_x, 1}), Tensor(gpu_in1_val.getData(), Dims{height_x, width}), - Tensor(gpu_in2_val.getData(), Dims{height_x, width}), - Tensor(gpu_in1_grad.getData(), Dims{height_x, width}), - Tensor(gpu_in2_grad.getData(), Dims{height_x, width})}, - {Tensor(gpu_out_grad.getData(), Dims{height_x, 1})}, - {}); + Tensor(gpu_in2_val.getData(), Dims{height_x, width})}, + {}, + {Tensor(gpu_in1_grad.getData(), Dims{height_x, width}), + Tensor(gpu_in2_grad.getData(), Dims{height_x, width})}); autotest::TensorCheckErr(cpu_in1_grad, gpu_in1_grad); autotest::TensorCheckErr(cpu_in2_grad, gpu_in2_grad); diff --git a/paddle/gserver/layers/CosSimLayer.cpp b/paddle/gserver/layers/CosSimLayer.cpp index ac66fd4712af48..b00eda2f64a1e1 100644 --- a/paddle/gserver/layers/CosSimLayer.cpp +++ b/paddle/gserver/layers/CosSimLayer.cpp @@ -79,13 +79,13 @@ void CosSimLayer::backward(const UpdateCallback& callback) { auto inG2 = this->getInputGrad(1); CHECK(outG && outV && inV1 && inV2 && inG1 && inG2); backward_[0]->calc( - {Tensor(outV->getData(), Dims{outV->getHeight(), outV->getWidth()}), + {Tensor(outG->getData(), Dims{outG->getHeight(), outG->getWidth()}), + Tensor(outV->getData(), Dims{outV->getHeight(), outV->getWidth()}), Tensor(inV1->getData(), Dims{inV1->getHeight(), inV1->getWidth()}), - Tensor(inV2->getData(), Dims{inV2->getHeight(), inV2->getWidth()}), - Tensor(inG1->getData(), Dims{inG1->getHeight(), inG1->getWidth()}), - Tensor(inG2->getData(), Dims{inG2->getHeight(), inG2->getWidth()})}, - {Tensor(outG->getData(), Dims{outG->getHeight(), outG->getWidth()})}, - {}); + Tensor(inV2->getData(), Dims{inV2->getHeight(), inV2->getWidth()})}, + {}, + {Tensor(inG1->getData(), Dims{inG1->getHeight(), inG1->getWidth()}), + Tensor(inG2->getData(), Dims{inG2->getHeight(), inG2->getWidth()})}); } } diff --git a/paddle/gserver/layers/CosSimVecMatLayer.cpp b/paddle/gserver/layers/CosSimVecMatLayer.cpp index 427191e540778a..120c4e84c55d0b 100644 --- a/paddle/gserver/layers/CosSimVecMatLayer.cpp +++ b/paddle/gserver/layers/CosSimVecMatLayer.cpp @@ -169,19 +169,19 @@ void CosSimVecMatLayer::backward(const UpdateCallback& callback) { tmpRow3->setData(outG->rowBuf(i)); backward_[0]->calc( - {Tensor(tmpRow2->getData(), + {Tensor(tmpRow3->getData(), + Dims{tmpRow3->getHeight(), tmpRow3->getWidth()}), + Tensor(tmpRow2->getData(), Dims{tmpRow2->getHeight(), tmpRow2->getWidth()}), Tensor(tmpMtx0->getData(), Dims{tmpMtx0->getHeight(), tmpMtx0->getWidth()}), Tensor(tmpRow0->getData(), - Dims{tmpRow0->getHeight(), tmpRow0->getWidth()}), - Tensor(tmpMtx1->getData(), + Dims{tmpRow0->getHeight(), tmpRow0->getWidth()})}, + {}, + {Tensor(tmpMtx1->getData(), Dims{tmpMtx1->getHeight(), tmpMtx1->getWidth()}), Tensor(tmpRow1->getData(), - Dims{tmpRow1->getHeight(), tmpRow1->getWidth()})}, - {Tensor(tmpRow3->getData(), - Dims{tmpRow3->getHeight(), tmpRow3->getWidth()})}, - {}); + Dims{tmpRow1->getHeight(), tmpRow1->getWidth()})}); } } diff --git a/paddle/gserver/layers/CosSimVecMatLayer.h b/paddle/gserver/layers/CosSimVecMatLayer.h index bee83b58154b67..df4e11848c46e9 100644 --- a/paddle/gserver/layers/CosSimVecMatLayer.h +++ b/paddle/gserver/layers/CosSimVecMatLayer.h @@ -12,6 +12,8 @@ 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 "Layer.h" #include "paddle/math/Matrix.h" diff --git a/paddle/math/Matrix.cpp b/paddle/math/Matrix.cpp index a8b53e2105b053..1964b2f8bfaebc 100644 --- a/paddle/math/Matrix.cpp +++ b/paddle/math/Matrix.cpp @@ -941,59 +941,6 @@ void GpuMatrix::softreluDerivative(Matrix& output) { void GpuMatrix::scaledTanh(Matrix& output, real p1, real 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() { CHECK(isContiguous()); @@ -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) { CHECK(output.useGpu_ == false && label.useGpu_ == false) << "Matrix type are not equal"; diff --git a/paddle/math/Matrix.h b/paddle/math/Matrix.h index c92c0a272d5a72..ea4bbb86b057b5 100644 --- a/paddle/math/Matrix.h +++ b/paddle/math/Matrix.h @@ -799,26 +799,6 @@ class Matrix : public BaseMatrix { LOG(FATAL) << "Not implemented"; } - /** - * cosine similarity, for each row i, - * this[i] = cos(output1[i], output2[i]) - * - * output2 can only have one row, then for each row i, - * this[i] = cos(output1[i], output2[0]) - */ - virtual void cosSim(Matrix& output1, Matrix& output2, real scale = 1.0f) { - LOG(FATAL) << "Not implemented"; - } - - virtual void cosSimDerivative(Matrix& output, - Matrix& prevOut1, - Matrix& prevOut2, - Matrix& prevGrad1, - Matrix& prevGrad2, - real scale = 1.0f) { - LOG(FATAL) << "Not implemented"; - } - /// print out the values of elements to os virtual void print(std::ostream& os) const { LOG(FATAL) << "Not implemented"; @@ -1324,14 +1304,6 @@ class GpuMatrix : public Matrix { void softreluDerivative(Matrix& output); void scaledTanh(Matrix& output, real p1, real p2); - void cosSim(Matrix& output1, Matrix& output2, real scale); - void cosSimDerivative(Matrix& output, - Matrix& prevOut1, - Matrix& prevOut2, - Matrix& prevGrad1, - Matrix& prevGrad2, - real scale); - virtual void print(std::ostream& os) const; virtual void print(std::ostream& os, size_t height, size_t width) const; @@ -1752,14 +1724,6 @@ class CpuMatrix : public Matrix { void softreluDerivative(Matrix& output); void scaledTanh(Matrix& output, real p1, real p2); - void cosSim(Matrix& output1, Matrix& output2, real scale); - void cosSimDerivative(Matrix& output, - Matrix& prevOut1, - Matrix& prevOut2, - Matrix& prevGrad1, - Matrix& prevGrad2, - real scale); - void print(std::ostream& os) const; void print(std::ostream& os, size_t height, size_t width) const; void printOneRow(std::ostream& os, size_t idx) const; diff --git a/paddle/math/tests/test_Matrix.cpp b/paddle/math/tests/test_Matrix.cpp index a4084bdf7c6953..1c21da5b76e956 100644 --- a/paddle/math/tests/test_Matrix.cpp +++ b/paddle/math/tests/test_Matrix.cpp @@ -181,28 +181,6 @@ TEST(Matrix, copyByRowIndex) { } } -void testCosSim(int heightX, int heightY, int width, real scale) { - AutoCompare test(heightX, 1); - CpuMatrix arg1(heightX, width); - CpuMatrix arg2(heightY, width); - arg1.randomizeUniform(); - arg2.randomizeUniform(); - arg2.add(-0.5); - test.cmpWithArg(&Matrix::cosSim, arg1, arg2, scale); -} - -TEST(Matrix, cosSim) { - for (auto heightX : {10, 100, 1000}) { - for (auto heightY : {1, heightX}) { - for (auto width : {10, 100, 1000}) { - for (auto scale : {1.0, 2.0}) { - testCosSim(heightX, heightY, width, scale); - } - } - } - } -} - void testParamReluForward(int height, int width, int w_height, int w_width) { AutoCompare test(height, width); CpuMatrix arg1(height, width); diff --git a/paddle/math/tests/test_matrixCompare.cpp b/paddle/math/tests/test_matrixCompare.cpp index e024f2cf1b913f..6caaea443c1df7 100644 --- a/paddle/math/tests/test_matrixCompare.cpp +++ b/paddle/math/tests/test_matrixCompare.cpp @@ -720,61 +720,6 @@ TEST(Matrix, sequenceAvgForward) { } } -void testCosSimDerivate(int heightX, int heightY, int width, real scale) { - MatrixPtr prevOutX = CpuMatrix::create(heightX, width, false, false); - MatrixPtr prevOutY = CpuMatrix::create(heightY, width, false, false); - MatrixPtr grad = CpuMatrix::create(heightX, 1, false, false); - MatrixPtr output = CpuMatrix::create(heightX, 1, false, false); - MatrixPtr prevGradX = CpuMatrix::create(heightX, width, false, false); - MatrixPtr prevGradY = CpuMatrix::create(heightY, width, false, false); - - prevOutX->randomizeUniform(); - prevOutY->randomizeUniform(); - grad->randomizeUniform(); - output->randomizeUniform(); - prevGradX->randomizeUniform(); - prevGradY->randomizeUniform(); - - MatrixPtr prevOutXGpu = GpuMatrix::create(heightX, width, false, true); - MatrixPtr prevOutYGpu = GpuMatrix::create(heightY, width, false, true); - MatrixPtr gradGpu = GpuMatrix::create(heightX, 1, false, true); - MatrixPtr outputGpu = GpuMatrix::create(heightX, 1, false, true); - MatrixPtr prevGradXGpu = GpuMatrix::create(heightX, width, false, true); - MatrixPtr prevGradYGpu = GpuMatrix::create(heightY, width, false, true); - - prevOutXGpu->copyFrom(*prevOutX); - prevOutYGpu->copyFrom(*prevOutY); - gradGpu->copyFrom(*grad); - outputGpu->copyFrom(*output); - prevGradXGpu->copyFrom(*prevGradX); - prevGradYGpu->copyFrom(*prevGradY); - - grad->cosSimDerivative( - *output, *prevOutX, *prevOutY, *prevGradX, *prevGradY, scale); - - gradGpu->cosSimDerivative(*outputGpu, - *prevOutXGpu, - *prevOutYGpu, - *prevGradXGpu, - *prevGradYGpu, - scale); - - TensorCheckErr(*prevGradX, *prevGradXGpu); - TensorCheckErr(*prevGradY, *prevGradYGpu); -} - -TEST(Matrix, cosSimDerivate) { - for (auto heightX : {1, 10, 100}) { - for (auto heightY : {1, heightX}) { - for (auto width : {1, 10, 100}) { - for (auto scale : {1.0, 2.0}) { - testCosSimDerivate(heightX, heightY, width, scale); - } - } - } - } -} - void testParamReluBackwardDiff(int height, int width, int w_height, From 47aaac00b0baa8374e3b09e7b8e35f2d8d3bedc6 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Wed, 4 Jan 2017 18:13:12 -0800 Subject: [PATCH 159/370] add some comments... --- paddle/function/CosSimOp.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/paddle/function/CosSimOp.cpp b/paddle/function/CosSimOp.cpp index bcc17fd5319c6a..1c3cb6f18b3d29 100644 --- a/paddle/function/CosSimOp.cpp +++ b/paddle/function/CosSimOp.cpp @@ -17,6 +17,15 @@ limitations under the License. */ #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(CpuMatrix* out_mat, const CpuMatrix* in1_mat, @@ -48,6 +57,13 @@ void CosSimForward(CpuMatrix* out_mat, } /** + * Cosine Similarity + * for each row i, + * out[i] = scale * cos(input1[i], input2[i]) + * = scale * /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. @@ -85,6 +101,20 @@ class CosSimForwardFunc : public FunctionBase { 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(const CpuMatrix* out_grad, const CpuMatrix* out_val, @@ -146,6 +176,8 @@ void CosSimBackward(const CpuMatrix* out_grad, } /** + * Cosine Similarity backward Derivative + * * \param inouts[0] forward input grad 1, size: nSamples * dim. * \param inouts[1] forward input grad 2, * size: n2 * dim (n2 == 1 or n2 == nSamples). From 877decdccc3475999abb72ae7383afc24c356cb8 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Wed, 11 Jan 2017 13:31:36 -0800 Subject: [PATCH 160/370] merge Daoyuan's FuncArg, address one of the comments. --- paddle/function/CMakeLists.txt | 1 + paddle/function/CosSimOp.cpp | 161 +++++++++----------- paddle/function/CosSimOp.h | 18 +-- paddle/function/CosSimOpGpu.cu | 71 ++++----- paddle/function/CosSimOpTest.cpp | 61 ++++---- paddle/function/FunctionTest.h | 4 + paddle/gserver/layers/CosSimLayer.cpp | 31 ++-- paddle/gserver/layers/CosSimVecMatLayer.cpp | 73 ++++++--- paddle/gserver/layers/CosSimVecMatLayer.h | 54 ------- 9 files changed, 226 insertions(+), 248 deletions(-) delete mode 100644 paddle/gserver/layers/CosSimVecMatLayer.h diff --git a/paddle/function/CMakeLists.txt b/paddle/function/CMakeLists.txt index fae3b7b20a70b5..1522510e8bb981 100644 --- a/paddle/function/CMakeLists.txt +++ b/paddle/function/CMakeLists.txt @@ -27,6 +27,7 @@ if(WITH_TESTING) add_simple_unittest(ContextProjectionOpTest) add_simple_unittest(PadOpTest) add_simple_unittest(MulOpTest) + add_simple_unittest(CosSimOpTest) endif() endif() diff --git a/paddle/function/CosSimOp.cpp b/paddle/function/CosSimOp.cpp index 1c3cb6f18b3d29..130ee56f3d9a51 100644 --- a/paddle/function/CosSimOp.cpp +++ b/paddle/function/CosSimOp.cpp @@ -27,21 +27,21 @@ namespace paddle { * */ template <> -void CosSimForward(CpuMatrix* out_mat, - const CpuMatrix* in1_mat, - const CpuMatrix* in2_mat, +void CosSimForward(CpuMatrix& out_mat, + const CpuMatrix& in1_mat, + const CpuMatrix& in2_mat, real scale) { - CHECK(out_mat && in1_mat && in2_mat); - size_t num_samples = out_mat->getHeight(); - size_t dim = in1_mat->getWidth(); + 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(); + 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; + 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; @@ -75,26 +75,26 @@ class CosSimForwardFunc : public FunctionBase { scale_ = config.get("scale"); } - void calc(const Arguments& inputs, - const Arguments& outputs, - const Arguments& inouts) override { + void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { CHECK_EQ(inputs.size(), 2); CHECK_EQ(outputs.size(), 1); - CHECK_EQ(inouts.size(), 0); - CHECK_EQ(inputs[0].dims_[0], outputs[0].dims_[0]); - CHECK_EQ(inputs[0].dims_[1], inputs[1].dims_[1]); - CHECK_EQ(outputs[0].dims_[1], 1UL); + CHECK_EQ(inputs[0].shape().ndims(), (size_t)2); + CHECK_EQ(inputs[1].shape().ndims(), (size_t)2); + CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); - CHECK(outputs[0].getData() && inputs[0].getData() && inputs[1].getData()); - auto out_mat = std::make_shared::type>( - outputs[0].getData(), outputs[0].dims_[0], outputs[0].dims_[1]); - const auto in1_mat = std::make_shared::type>( - inputs[0].getData(), inputs[0].dims_[0], inputs[0].dims_[1]); - const auto in2_mat = std::make_shared::type>( - inputs[1].getData(), inputs[1].dims_[0], inputs[1].dims_[1]); + 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); - CosSimForward(out_mat.get(), in1_mat.get(), in2_mat.get(), scale_); + CHECK(outputs[0].data() && inputs[0].data() && inputs[1].data()); + + CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO); + auto out_mat = outputs[0].matrix(); + const auto in1_mat = inputs[0].matrix(); + const auto in2_mat = inputs[1].matrix(); + + CosSimForward(out_mat, in1_mat, in2_mat, scale_); } private: @@ -116,28 +116,29 @@ class CosSimForwardFunc : public FunctionBase { * \param scale, default 1.0 */ template <> -void CosSimBackward(const CpuMatrix* out_grad, - const CpuMatrix* out_val, - const CpuMatrix* in1_val, - const CpuMatrix* in2_val, - CpuMatrix* in1_grad, - CpuMatrix* in2_grad, +void CosSimBackward(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 && out_val && in1_val && in2_val && in1_grad && in2_grad); - 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; + 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, @@ -178,8 +179,8 @@ void CosSimBackward(const CpuMatrix* out_grad, /** * Cosine Similarity backward Derivative * - * \param inouts[0] forward input grad 1, size: nSamples * dim. - * \param inouts[1] forward input grad 2, + * \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. @@ -194,46 +195,36 @@ class CosSimBackwardFunc : public FunctionBase { scale_ = config.get("scale"); } - void calc(const Arguments& inputs, - const Arguments& outputs, - const Arguments& inouts) override { + void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { CHECK_EQ(inputs.size(), 4); - CHECK_EQ(outputs.size(), 0); - CHECK_EQ(inouts.size(), 2); + CHECK_EQ(outputs.size(), 2); /// dim of out_grad and out_val == 1, column vector - CHECK_EQ(inputs[0].dims_[1], 1UL); - CHECK_EQ(inputs[1].dims_[1], 1UL); + 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].dims_[0], inputs[0].dims_[0]); - CHECK_EQ(inputs[0].dims_[0], inputs[0].dims_[0]); - CHECK_EQ(inouts[0].dims_[0], inputs[0].dims_[0]); + 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].dims_[1], inputs[2].dims_[1]); - CHECK_EQ(inouts[0].dims_[1], inputs[2].dims_[1]); - CHECK_EQ(inouts[1].dims_[1], inputs[2].dims_[1]); - - CHECK(inputs[0].getData() && inputs[1].getData() && inputs[2].getData() && - inputs[3].getData() && inouts[0].getData() && inouts[1].getData()); - const auto out_grad = std::make_shared::type>( - inputs[0].getData(), inputs[0].dims_[0], inputs[0].dims_[1]); - const auto out_val = std::make_shared::type>( - inputs[1].getData(), inputs[1].dims_[0], inputs[1].dims_[1]); - const auto in1_val = std::make_shared::type>( - inputs[2].getData(), inputs[2].dims_[0], inputs[2].dims_[1]); - const auto in2_val = std::make_shared::type>( - inputs[3].getData(), inputs[3].dims_[0], inputs[3].dims_[1]); - auto in1_grad = std::make_shared::type>( - inouts[0].getData(), inouts[0].dims_[0], inouts[0].dims_[1]); - auto in2_grad = std::make_shared::type>( - inouts[1].getData(), inouts[1].dims_[0], inouts[1].dims_[1]); - - CosSimBackward(out_grad.get(), - out_val.get(), - in1_val.get(), - in2_val.get(), - in1_grad.get(), - in2_grad.get(), - scale_); + 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(); + const auto out_val = inputs[1].matrix(); + const auto in1_val = inputs[2].matrix(); + const auto in2_val = inputs[3].matrix(); + auto in1_grad = outputs[0].matrix(); + auto in2_grad = outputs[1].matrix(); + + CosSimBackward( + out_grad, out_val, in1_val, in2_val, in1_grad, in2_grad, scale_); } private: diff --git a/paddle/function/CosSimOp.h b/paddle/function/CosSimOp.h index ed1f1e4d5345e2..be73064e6375bf 100644 --- a/paddle/function/CosSimOp.h +++ b/paddle/function/CosSimOp.h @@ -32,9 +32,9 @@ namespace paddle { * */ template -void CosSimForward(typename MatrixT::type* output, - const typename MatrixT::type* input1, - const typename MatrixT::type* input2, +void CosSimForward(typename Tensor::Matrix& output, + const typename Tensor::Matrix& input1, + const typename Tensor::Matrix& input2, real scale); /** @@ -50,12 +50,12 @@ void CosSimForward(typename MatrixT::type* output, * */ template -void CosSimBackward(const typename MatrixT::type* out_grad, - const typename MatrixT::type* out_value, - const typename MatrixT::type* in1_value, - const typename MatrixT::type* in2_value, - typename MatrixT::type* in1_grad, - typename MatrixT::type* in2_grad, +void CosSimBackward(const typename Tensor::Matrix& out_grad, + const typename Tensor::Matrix& out_value, + const typename Tensor::Matrix& in1_value, + const typename Tensor::Matrix& in2_value, + typename Tensor::Matrix& in1_grad, + typename Tensor::Matrix& in2_grad, real scale); } // namespace paddle diff --git a/paddle/function/CosSimOpGpu.cu b/paddle/function/CosSimOpGpu.cu index f654f0bc209c24..1dd733674fa054 100644 --- a/paddle/function/CosSimOpGpu.cu +++ b/paddle/function/CosSimOpGpu.cu @@ -65,12 +65,12 @@ __global__ void KeCosSim(real* output, } void hlCossim(real* output, - const real* input1, - const real* input2, - size_t width, - size_t input1_height, - size_t input2_height, - real scale) { + 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); @@ -84,20 +84,20 @@ void hlCossim(real* output, } template <> -void CosSimForward(GpuMatrix* out_mat, - const GpuMatrix* in1_mat, - const GpuMatrix* in2_mat, +void CosSimForward(GpuMatrix& out_mat, + const GpuMatrix& in1_mat, + const GpuMatrix& in2_mat, real scale) { - CHECK(out_mat && in1_mat && in2_mat); - CHECK(in1_mat->useGpu_ == true && in2_mat->useGpu_ == true) + 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); + 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 @@ -206,25 +206,26 @@ void hlCossimDerivative(const real* grad, } template <> -void CosSimBackward(const GpuMatrix* out_grad, - const GpuMatrix* out_val, - const GpuMatrix* in1_val, - const GpuMatrix* in2_val, - GpuMatrix* in1_grad, - GpuMatrix* in2_grad, +void CosSimBackward(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 && out_val && in1_val && in2_val && in1_grad && in2_grad); - CHECK(out_grad->useGpu_ && out_val->useGpu_ && in1_val->useGpu_ - && in2_val->useGpu_ && in1_grad->useGpu_ && in2_grad->useGpu_) + 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(); + 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, @@ -232,8 +233,8 @@ void CosSimBackward(const GpuMatrix* out_grad, prev_grad_x, prev_grad_y, dim, - in1_val->getHeight(), - in2_val->getHeight(), + in1_val.getHeight(), + in2_val.getHeight(), scale); } diff --git a/paddle/function/CosSimOpTest.cpp b/paddle/function/CosSimOpTest.cpp index f0e81ee0434178..dce959e81c6862 100644 --- a/paddle/function/CosSimOpTest.cpp +++ b/paddle/function/CosSimOpTest.cpp @@ -36,16 +36,20 @@ void testCosSimForward(size_t height_x, CpuMatrix cpu_out(height_x, 1); GpuMatrix gpu_out(height_x, 1); - compare.getCpuFunction()->calc( - {Tensor(cpu_arg1.getData(), Dims{height_x, width}), - Tensor(cpu_arg2.getData(), Dims{height_y, width})}, - {Tensor(cpu_out.getData(), Dims{height_x, 1})}, - {}); - compare.getGpuFunction()->calc( - {Tensor(gpu_arg1.getData(), Dims{height_x, width}), - Tensor(gpu_arg2.getData(), Dims{height_y, width})}, - {Tensor(gpu_out.getData(), Dims{height_x, 1})}, - {}); + BufferArgs cpu_inputs; + BufferArgs cpu_outputs; + cpu_inputs.addArg(cpu_arg1); + cpu_inputs.addArg(cpu_arg2); + cpu_outputs.addArg(cpu_out, ASSIGN_TO); + + BufferArgs gpu_inputs; + BufferArgs gpu_outputs; + gpu_inputs.addArg(gpu_arg1); + gpu_inputs.addArg(gpu_arg2); + gpu_outputs.addArg(gpu_out, ASSIGN_TO); + + compare.getCpuFunction()->calc(cpu_inputs, cpu_outputs); + compare.getGpuFunction()->calc(gpu_inputs, gpu_outputs); autotest::TensorCheckErr(cpu_out, gpu_out); } @@ -96,23 +100,26 @@ void testCosSimBackward(size_t height_x, gpu_in1_grad.copyFrom(cpu_in1_grad); gpu_in2_grad.copyFrom(cpu_in2_grad); - compare.getCpuFunction()->calc( - {Tensor(cpu_out_grad.getData(), Dims{height_x, 1}), - Tensor(cpu_out_val.getData(), Dims{height_x, 1}), - Tensor(cpu_in1_val.getData(), Dims{height_x, width}), - Tensor(cpu_in2_val.getData(), Dims{height_x, width})}, - {}, - {Tensor(cpu_in1_grad.getData(), Dims{height_x, width}), - Tensor(cpu_in2_grad.getData(), Dims{height_x, width})}); - - compare.getGpuFunction()->calc( - {Tensor(gpu_out_grad.getData(), Dims{height_x, 1}), - Tensor(gpu_out_val.getData(), Dims{height_x, 1}), - Tensor(gpu_in1_val.getData(), Dims{height_x, width}), - Tensor(gpu_in2_val.getData(), Dims{height_x, width})}, - {}, - {Tensor(gpu_in1_grad.getData(), Dims{height_x, width}), - Tensor(gpu_in2_grad.getData(), Dims{height_x, width})}); + BufferArgs cpu_inputs; + BufferArgs cpu_outputs; + cpu_inputs.addArg(cpu_out_grad); + cpu_inputs.addArg(cpu_out_val); + cpu_inputs.addArg(cpu_in1_val); + cpu_inputs.addArg(cpu_in2_val); + cpu_outputs.addArg(cpu_in1_grad, ADD_TO); + cpu_outputs.addArg(cpu_in2_grad, ADD_TO); + + BufferArgs gpu_inputs; + BufferArgs gpu_outputs; + gpu_inputs.addArg(gpu_out_grad); + gpu_inputs.addArg(gpu_out_val); + gpu_inputs.addArg(gpu_in1_val); + gpu_inputs.addArg(gpu_in2_val); + gpu_outputs.addArg(gpu_in1_grad, ADD_TO); + gpu_outputs.addArg(gpu_in2_grad, ADD_TO); + + compare.getCpuFunction()->calc(cpu_inputs, cpu_outputs); + compare.getGpuFunction()->calc(gpu_inputs, gpu_outputs); autotest::TensorCheckErr(cpu_in1_grad, gpu_in1_grad); autotest::TensorCheckErr(cpu_in2_grad, gpu_in2_grad); diff --git a/paddle/function/FunctionTest.h b/paddle/function/FunctionTest.h index 0cfafdb27f55a3..35de3a65d531f7 100644 --- a/paddle/function/FunctionTest.h +++ b/paddle/function/FunctionTest.h @@ -157,6 +157,9 @@ class FunctionCompare { cpuSparse_->randomizeUniform(); gpuSparse_->copyFrom(*cpuSparse_, stream); hl_stream_synchronize(stream); + void addInputs(const SequenceArg& input) { + size_t batchSize = input.shape()[0]; + size_t numSeqs = batchSize / 10 + 1; cpuOutputs_.emplace_back( std::make_shared(*cpuSparse_, argType)); @@ -331,6 +334,7 @@ class FunctionCompare { } protected: +<<<<<<< HEAD std::shared_ptr cpuFunc_; std::shared_ptr gpuFunc_; std::vector cpuMemory_; diff --git a/paddle/gserver/layers/CosSimLayer.cpp b/paddle/gserver/layers/CosSimLayer.cpp index b00eda2f64a1e1..a6c0300acf6752 100644 --- a/paddle/gserver/layers/CosSimLayer.cpp +++ b/paddle/gserver/layers/CosSimLayer.cpp @@ -56,13 +56,12 @@ void CosSimLayer::forward(PassType passType) { MatrixPtr prevOut2 = getInputValue(1); CHECK(outV && prevOut1 && prevOut2); - forward_[0]->calc( - {Tensor(prevOut1->getData(), - Dims{prevOut1->getHeight(), prevOut1->getWidth()}), - Tensor(prevOut2->getData(), - Dims{prevOut2->getHeight(), prevOut2->getWidth()})}, - {Tensor(outV->getData(), Dims{outV->getHeight(), outV->getWidth()})}, - {}); + BufferArgs inputs; + BufferArgs outputs; + inputs.addArg(*prevOut1); + inputs.addArg(*prevOut2); + outputs.addArg(*outV, ASSIGN_TO); + forward_[0]->calc(inputs, outputs); } } @@ -78,14 +77,16 @@ void CosSimLayer::backward(const UpdateCallback& callback) { auto inG1 = this->getInputGrad(0); auto inG2 = this->getInputGrad(1); CHECK(outG && outV && inV1 && inV2 && inG1 && inG2); - backward_[0]->calc( - {Tensor(outG->getData(), Dims{outG->getHeight(), outG->getWidth()}), - Tensor(outV->getData(), Dims{outV->getHeight(), outV->getWidth()}), - Tensor(inV1->getData(), Dims{inV1->getHeight(), inV1->getWidth()}), - Tensor(inV2->getData(), Dims{inV2->getHeight(), inV2->getWidth()})}, - {}, - {Tensor(inG1->getData(), Dims{inG1->getHeight(), inG1->getWidth()}), - Tensor(inG2->getData(), Dims{inG2->getHeight(), inG2->getWidth()})}); + 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); } } diff --git a/paddle/gserver/layers/CosSimVecMatLayer.cpp b/paddle/gserver/layers/CosSimVecMatLayer.cpp index 120c4e84c55d0b..29ebe1ca9f60fb 100644 --- a/paddle/gserver/layers/CosSimVecMatLayer.cpp +++ b/paddle/gserver/layers/CosSimVecMatLayer.cpp @@ -12,11 +12,44 @@ 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 "CosSimVecMatLayer.h" +#include "Layer.h" +#include "paddle/math/Matrix.h" #include "paddle/utils/Logging.h" #include "paddle/utils/Stat.h" namespace paddle { +/** + * @brief A layer for computing cosine similarity between a vector + * and each row of a matrix + * out[i] = cos_scale * cos(in1, in2(i,:)); + * @note used in NEURAL TURING MACHINE + * + * Input1: a vector (batchSize * dataDim) + * + * Input2: a matrix in vector form (batchSize * (weightDim*dataDim)) + * + * Output: a vector (batchSize * weightDim) + */ + +class CosSimVecMatLayer : public Layer { +public: + explicit CosSimVecMatLayer(const LayerConfig& config) : Layer(config) {} + + ~CosSimVecMatLayer() {} + + bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + + void forward(PassType passType); + void backward(const UpdateCallback& callback = nullptr); + +protected: + MatrixPtr tmpMtx0; + MatrixPtr tmpMtx1; + MatrixPtr tmpRow0; + MatrixPtr tmpRow1; + MatrixPtr tmpRow2; + MatrixPtr tmpRow3; +}; /** * @brief A layer for computing cosine similarity between a vector @@ -98,7 +131,6 @@ bool CosSimVecMatLayer::init(const LayerMap& layerMap, /* trans= */ false, useGpu_); - /// todo(tianbing), do we really need to check these shared pointers? CHECK(tmpRow0 && tmpRow1 && tmpRow2 && tmpRow3 && tmpMtx0 && tmpMtx1); createFunction(forward_, @@ -136,13 +168,12 @@ void CosSimVecMatLayer::forward(PassType passType) { tmpMtx0->setData(inV1->rowBuf(i)); tmpRow2->setData(outV->rowBuf(i)); - forward_[0]->calc({Tensor(tmpMtx0->getData(), - Dims{tmpMtx0->getHeight(), tmpMtx0->getWidth()}), - Tensor(tmpRow0->getData(), - Dims{tmpRow0->getHeight(), tmpRow0->getWidth()})}, - {Tensor(tmpRow2->getData(), - Dims{tmpRow2->getHeight(), tmpRow2->getWidth()})}, - {}); + BufferArgs inputs; + BufferArgs outputs; + inputs.addArg(*tmpMtx0); + inputs.addArg(*tmpRow0); + outputs.addArg(*tmpRow2, ASSIGN_TO); + forward_[0]->calc(inputs, outputs); } } @@ -168,20 +199,16 @@ void CosSimVecMatLayer::backward(const UpdateCallback& callback) { tmpRow2->setData(outV->rowBuf(i)); tmpRow3->setData(outG->rowBuf(i)); - backward_[0]->calc( - {Tensor(tmpRow3->getData(), - Dims{tmpRow3->getHeight(), tmpRow3->getWidth()}), - Tensor(tmpRow2->getData(), - Dims{tmpRow2->getHeight(), tmpRow2->getWidth()}), - Tensor(tmpMtx0->getData(), - Dims{tmpMtx0->getHeight(), tmpMtx0->getWidth()}), - Tensor(tmpRow0->getData(), - Dims{tmpRow0->getHeight(), tmpRow0->getWidth()})}, - {}, - {Tensor(tmpMtx1->getData(), - Dims{tmpMtx1->getHeight(), tmpMtx1->getWidth()}), - Tensor(tmpRow1->getData(), - Dims{tmpRow1->getHeight(), tmpRow1->getWidth()})}); + BufferArgs inputs; + BufferArgs outputs; + inputs.addArg(*tmpRow3); + inputs.addArg(*tmpRow2); + inputs.addArg(*tmpMtx0); + inputs.addArg(*tmpRow0); + outputs.addArg(*tmpMtx1, ADD_TO); + outputs.addArg(*tmpRow1, ADD_TO); + + backward_[0]->calc(inputs, outputs); } } diff --git a/paddle/gserver/layers/CosSimVecMatLayer.h b/paddle/gserver/layers/CosSimVecMatLayer.h deleted file mode 100644 index df4e11848c46e9..00000000000000 --- a/paddle/gserver/layers/CosSimVecMatLayer.h +++ /dev/null @@ -1,54 +0,0 @@ -/* 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 "Layer.h" -#include "paddle/math/Matrix.h" - -namespace paddle { -/** - * @brief A layer for computing cosine similarity between a vector - * and each row of a matrix - * out[i] = cos_scale * cos(in1, in2(i,:)); - * @note used in NEURAL TURING MACHINE - * - * Input1: a vector (batchSize * dataDim) - * - * Input2: a matrix in vector form (batchSize * (weightDim*dataDim)) - * - * Output: a vector (batchSize * weightDim) - */ - -class CosSimVecMatLayer : public Layer { -public: - explicit CosSimVecMatLayer(const LayerConfig& config) : Layer(config) {} - - ~CosSimVecMatLayer() {} - - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); - - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); - -protected: - MatrixPtr tmpMtx0; - MatrixPtr tmpMtx1; - MatrixPtr tmpRow0; - MatrixPtr tmpRow1; - MatrixPtr tmpRow2; - MatrixPtr tmpRow3; -}; - -} // namespace paddle From 9b17c3ff2ec6e3179db7ddffbe7a84a4704e1186 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Wed, 25 Jan 2017 13:53:28 -0800 Subject: [PATCH 161/370] rewrite unit test using Daoyuan's new FunctionTest. --- paddle/function/CosSimOp.cpp | 14 ++-- paddle/function/CosSimOpTest.cpp | 122 ++++++------------------------- paddle/function/FunctionTest.h | 17 ++++- 3 files changed, 47 insertions(+), 106 deletions(-) diff --git a/paddle/function/CosSimOp.cpp b/paddle/function/CosSimOp.cpp index 130ee56f3d9a51..7ece7b2dfedaf4 100644 --- a/paddle/function/CosSimOp.cpp +++ b/paddle/function/CosSimOp.cpp @@ -76,12 +76,12 @@ class CosSimForwardFunc : public FunctionBase { } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK_EQ(inputs.size(), 2); - CHECK_EQ(outputs.size(), 1); + CHECK_EQ(inputs.size(), 2UL); + CHECK_EQ(outputs.size(), 1UL); - CHECK_EQ(inputs[0].shape().ndims(), (size_t)2); - CHECK_EQ(inputs[1].shape().ndims(), (size_t)2); - CHECK_EQ(outputs[0].shape().ndims(), (size_t)2); + 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]); @@ -196,8 +196,8 @@ class CosSimBackwardFunc : public FunctionBase { } void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { - CHECK_EQ(inputs.size(), 4); - CHECK_EQ(outputs.size(), 2); + 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); diff --git a/paddle/function/CosSimOpTest.cpp b/paddle/function/CosSimOpTest.cpp index dce959e81c6862..48c815f027161b 100644 --- a/paddle/function/CosSimOpTest.cpp +++ b/paddle/function/CosSimOpTest.cpp @@ -22,114 +22,40 @@ void testCosSimForward(size_t height_x, size_t height_y, size_t width, real scale) { - FunctionCompare compare("CosSimForward", FuncConfig().set("scale", scale)); - - CpuMatrix cpu_arg1(height_x, width); - CpuMatrix gpu_arg1(height_x, width); - CpuMatrix cpu_arg2(height_y, width); - CpuMatrix gpu_arg2(height_y, width); - cpu_arg1.randomizeUniform(); - gpu_arg1.copyFrom(cpu_arg1); - cpu_arg2.randomizeUniform(); - cpu_arg2.add(-0.5); - gpu_arg2.copyFrom(cpu_arg2); - CpuMatrix cpu_out(height_x, 1); - GpuMatrix gpu_out(height_x, 1); - - BufferArgs cpu_inputs; - BufferArgs cpu_outputs; - cpu_inputs.addArg(cpu_arg1); - cpu_inputs.addArg(cpu_arg2); - cpu_outputs.addArg(cpu_out, ASSIGN_TO); - - BufferArgs gpu_inputs; - BufferArgs gpu_outputs; - gpu_inputs.addArg(gpu_arg1); - gpu_inputs.addArg(gpu_arg2); - gpu_outputs.addArg(gpu_out, ASSIGN_TO); - - compare.getCpuFunction()->calc(cpu_inputs, cpu_outputs); - compare.getGpuFunction()->calc(gpu_inputs, gpu_outputs); - - autotest::TensorCheckErr(cpu_out, gpu_out); -} - -TEST(Matrix, cosSimForward) { - 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); - } - } - } - } + 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 compare("CosSimBackward", FuncConfig().set("scale", scale)); - - CpuMatrix cpu_out_grad(height_x, 1); - CpuMatrix cpu_out_val(height_x, 1); - CpuMatrix cpu_in1_val(height_x, width); - CpuMatrix cpu_in2_val(height_x, width); - CpuMatrix cpu_in1_grad(height_x, width); - CpuMatrix cpu_in2_grad(height_x, width); - - cpu_out_grad.randomizeUniform(); - cpu_out_val.randomizeUniform(); - cpu_in1_val.randomizeUniform(); - cpu_in2_val.randomizeUniform(); - cpu_in1_grad.randomizeUniform(); - cpu_in2_grad.randomizeUniform(); - - GpuMatrix gpu_out_grad(height_x, 1); - GpuMatrix gpu_out_val(height_x, 1); - GpuMatrix gpu_in1_val(height_x, width); - GpuMatrix gpu_in2_val(height_x, width); - GpuMatrix gpu_in1_grad(height_x, width); - GpuMatrix gpu_in2_grad(height_x, width); - - gpu_out_grad.copyFrom(cpu_out_grad); - gpu_out_val.copyFrom(cpu_out_val); - gpu_in1_val.copyFrom(cpu_in1_val); - gpu_in2_val.copyFrom(cpu_in2_val); - gpu_in1_grad.copyFrom(cpu_in1_grad); - gpu_in2_grad.copyFrom(cpu_in2_grad); - - BufferArgs cpu_inputs; - BufferArgs cpu_outputs; - cpu_inputs.addArg(cpu_out_grad); - cpu_inputs.addArg(cpu_out_val); - cpu_inputs.addArg(cpu_in1_val); - cpu_inputs.addArg(cpu_in2_val); - cpu_outputs.addArg(cpu_in1_grad, ADD_TO); - cpu_outputs.addArg(cpu_in2_grad, ADD_TO); - - BufferArgs gpu_inputs; - BufferArgs gpu_outputs; - gpu_inputs.addArg(gpu_out_grad); - gpu_inputs.addArg(gpu_out_val); - gpu_inputs.addArg(gpu_in1_val); - gpu_inputs.addArg(gpu_in2_val); - gpu_outputs.addArg(gpu_in1_grad, ADD_TO); - gpu_outputs.addArg(gpu_in2_grad, ADD_TO); - - compare.getCpuFunction()->calc(cpu_inputs, cpu_outputs); - compare.getGpuFunction()->calc(gpu_inputs, gpu_outputs); - - autotest::TensorCheckErr(cpu_in1_grad, gpu_in1_grad); - autotest::TensorCheckErr(cpu_in2_grad, gpu_in2_grad); + 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, cosSimBackward) { - for (auto height_x : {1, 10, 100}) { +TEST(Matrix, cosSim) { + for (auto height_x : {10, 100, 1000}) { for (auto height_y : {1, height_x}) { - for (auto width : {1, 10, 100}) { + 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); } } diff --git a/paddle/function/FunctionTest.h b/paddle/function/FunctionTest.h index 35de3a65d531f7..68587ab1aca55a 100644 --- a/paddle/function/FunctionTest.h +++ b/paddle/function/FunctionTest.h @@ -157,6 +157,7 @@ class FunctionCompare { cpuSparse_->randomizeUniform(); gpuSparse_->copyFrom(*cpuSparse_, stream); hl_stream_synchronize(stream); + void addInputs(const SequenceArg& input) { size_t batchSize = input.shape()[0]; size_t numSeqs = batchSize / 10 + 1; @@ -300,6 +301,21 @@ class FunctionCompare { } void initOutputs() { + for (size_t i = 0; i < cpuOutputs_.size(); i++) { + initArg(*cpuOutputs_[i]); + + // TODO: Need a BufferCopy used to copy from one BufferArg to another. + CpuVector cpuVector(cpuOutputs_[i]->shape().getElements(), + (real*)cpuOutputs_[i]->data()); + GpuVector gpuVector(gpuOutputs_[i]->shape().getElements(), + (real*)gpuOutputs_[i]->data()); + + gpuVector.copyFrom(cpuVector); + } + } + + void compareOutputs() { +>>>>>>> rewrite unit test using Daoyuan's new FunctionTest. for (size_t i = 0; i < cpuOutputs_.size(); i++) { if (cpuOutputs_[i]->isSparseArg()) { continue; /// sparse matrix already init @@ -334,7 +350,6 @@ class FunctionCompare { } protected: -<<<<<<< HEAD std::shared_ptr cpuFunc_; std::shared_ptr gpuFunc_; std::vector cpuMemory_; From ae3ae084733b8c5db4885ac791e5f111a4477678 Mon Sep 17 00:00:00 2001 From: xutianbing Date: Wed, 8 Feb 2017 11:55:38 -0800 Subject: [PATCH 162/370] resolve merge confilicts --- paddle/function/FunctionTest.h | 19 ------------ paddle/gserver/layers/CosSimVecMatLayer.cpp | 33 --------------------- 2 files changed, 52 deletions(-) diff --git a/paddle/function/FunctionTest.h b/paddle/function/FunctionTest.h index 68587ab1aca55a..0cfafdb27f55a3 100644 --- a/paddle/function/FunctionTest.h +++ b/paddle/function/FunctionTest.h @@ -158,10 +158,6 @@ class FunctionCompare { gpuSparse_->copyFrom(*cpuSparse_, stream); hl_stream_synchronize(stream); - void addInputs(const SequenceArg& input) { - size_t batchSize = input.shape()[0]; - size_t numSeqs = batchSize / 10 + 1; - cpuOutputs_.emplace_back( std::make_shared(*cpuSparse_, argType)); gpuOutputs_.emplace_back( @@ -301,21 +297,6 @@ class FunctionCompare { } void initOutputs() { - for (size_t i = 0; i < cpuOutputs_.size(); i++) { - initArg(*cpuOutputs_[i]); - - // TODO: Need a BufferCopy used to copy from one BufferArg to another. - CpuVector cpuVector(cpuOutputs_[i]->shape().getElements(), - (real*)cpuOutputs_[i]->data()); - GpuVector gpuVector(gpuOutputs_[i]->shape().getElements(), - (real*)gpuOutputs_[i]->data()); - - gpuVector.copyFrom(cpuVector); - } - } - - void compareOutputs() { ->>>>>>> rewrite unit test using Daoyuan's new FunctionTest. for (size_t i = 0; i < cpuOutputs_.size(); i++) { if (cpuOutputs_[i]->isSparseArg()) { continue; /// sparse matrix already init diff --git a/paddle/gserver/layers/CosSimVecMatLayer.cpp b/paddle/gserver/layers/CosSimVecMatLayer.cpp index 29ebe1ca9f60fb..aabafd473aa1e0 100644 --- a/paddle/gserver/layers/CosSimVecMatLayer.cpp +++ b/paddle/gserver/layers/CosSimVecMatLayer.cpp @@ -18,39 +18,6 @@ limitations under the License. */ #include "paddle/utils/Stat.h" namespace paddle { -/** - * @brief A layer for computing cosine similarity between a vector - * and each row of a matrix - * out[i] = cos_scale * cos(in1, in2(i,:)); - * @note used in NEURAL TURING MACHINE - * - * Input1: a vector (batchSize * dataDim) - * - * Input2: a matrix in vector form (batchSize * (weightDim*dataDim)) - * - * Output: a vector (batchSize * weightDim) - */ - -class CosSimVecMatLayer : public Layer { -public: - explicit CosSimVecMatLayer(const LayerConfig& config) : Layer(config) {} - - ~CosSimVecMatLayer() {} - - bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); - - void forward(PassType passType); - void backward(const UpdateCallback& callback = nullptr); - -protected: - MatrixPtr tmpMtx0; - MatrixPtr tmpMtx1; - MatrixPtr tmpRow0; - MatrixPtr tmpRow1; - MatrixPtr tmpRow2; - MatrixPtr tmpRow3; -}; - /** * @brief A layer for computing cosine similarity between a vector * and each row of a matrix From a3a6997e3213d9d895e83d6c83130a060a6aafa8 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Wed, 8 Feb 2017 19:38:32 -0800 Subject: [PATCH 163/370] Add draft new_api.md --- doc/api/new_api.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 doc/api/new_api.md diff --git a/doc/api/new_api.md b/doc/api/new_api.md new file mode 100644 index 00000000000000..5a90cd1c756238 --- /dev/null +++ b/doc/api/new_api.md @@ -0,0 +1,38 @@ +import yi_json + +g = 100 +def read(): + queue q; + # warmup q + for i = 0 : 1000 + q.push(read()) + yield q.shuffle_get() + +input = paddle.layer.data(...) +intermediate = paddle.layers.fc(input) +output = paddle.layer.softmax(intermediate) + +model = paddle.model.create(output) + +train(model, data_provider=read, cluster="clusterId") + +#-------------------------------------------------------------------------------- + +# 1. package, docker build, docker push +# 2. kubectl, clusterId Kuberentes job, 10 trainer containers, 5 parameter server containers + +#-------------------------------------------------------------------------------- + +def train(): + if os.environ["kube_api_server"] == nil: + docker_build() + docker_push() + kube_ctrl_start_job() + else: + rank = kube_mpi_rank() + if rank == 0: + master() + elif rank >= 15: + parameter_server() + else: + _train() From 642e25e93be136ba012b52dfe44607cf92f0a0b6 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Thu, 9 Feb 2017 13:14:13 -0800 Subject: [PATCH 164/370] Move new_api.md into design/api.md --- doc/api/{new_api.md => design/api.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename doc/api/{new_api.md => design/api.md} (100%) diff --git a/doc/api/new_api.md b/doc/api/design/api.md similarity index 100% rename from doc/api/new_api.md rename to doc/api/design/api.md From 36036c0ea57fdd0d9df8a4a77d8ebce89f65552b Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Thu, 9 Feb 2017 13:15:37 -0800 Subject: [PATCH 165/370] Correct directory structure --- doc/{api => }/design/api.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename doc/{api => }/design/api.md (100%) diff --git a/doc/api/design/api.md b/doc/design/api.md similarity index 100% rename from doc/api/design/api.md rename to doc/design/api.md From dd229dc7406de698601835d1d6e025d327bfe165 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Thu, 9 Feb 2017 16:03:08 -0800 Subject: [PATCH 166/370] Update api.md --- doc/design/api.md | 128 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 90 insertions(+), 38 deletions(-) diff --git a/doc/design/api.md b/doc/design/api.md index 5a90cd1c756238..3cfb67cb00d791 100644 --- a/doc/design/api.md +++ b/doc/design/api.md @@ -1,38 +1,90 @@ -import yi_json - -g = 100 -def read(): - queue q; - # warmup q - for i = 0 : 1000 - q.push(read()) - yield q.shuffle_get() - -input = paddle.layer.data(...) -intermediate = paddle.layers.fc(input) -output = paddle.layer.softmax(intermediate) - -model = paddle.model.create(output) - -train(model, data_provider=read, cluster="clusterId") - -#-------------------------------------------------------------------------------- - -# 1. package, docker build, docker push -# 2. kubectl, clusterId Kuberentes job, 10 trainer containers, 5 parameter server containers - -#-------------------------------------------------------------------------------- - -def train(): - if os.environ["kube_api_server"] == nil: - docker_build() - docker_push() - kube_ctrl_start_job() - else: - rank = kube_mpi_rank() - if rank == 0: - master() - elif rank >= 15: - parameter_server() - else: - _train() +# Design Doc: PaddlePaddle API + +## Ingredients + +As the first step of our design, we list important concepts in deep +learning and try to figure their relationship, as shown below: + +``` +Model = {topology, parameters} + +Evaluator = {Model*, activations} +- forward +- test + +GradientMachine = {Model*, gradients} +- backward + +Optimizer = {Model*, Evaluator*, GradientMachine*} +- train +- update +- checkpoint +``` + +where the pair of curly braces `{` and `}` indicate *composition*, `*` +indicates a *reference*, and `-` marks a "class method". + + +### Model + +We used to think that parameters are part of the toplogy (or layers). +But that is not true, because multiple layers could share the same +parameter matrix. An example is a network that compares two text +segments in a semantic space: + +``` + semantic +text A -> projection ---\ + layer A \ + cosine + similarity -> output + layer + semantic / +text B -> projection ---/ + layer B +``` + +In this network, the two semantic projection layers (A and B) share +the same parameter matrix. + +For more information about our API that specifies topology and +parameter sharing, please refer to [TODO: API]. + + +### Evaluator + +Supposed that we have a trained ranking model, we should be able to +use it in our search engine. The search engine's Web server is a +concurrent program so to serve many HTTP requests simultaneously. It +doens't make sense for each of these threads to have its own copy of +model, because that would duplicate topologies and parameters. +However, each thread should be able to record layer outputs, i.e., +activations, computed from an input, derived from the request. With +*Evaluator* that saves activations, we can write the over-simplified +server program as: + +```python +m = paddle.model.load("trained.model") + +http.handle("/", + lambda req: + e = paddle.evaluator.create(m) + e.forward(req) + e.activation(layer="output")) # returns activations of layer "output" +``` + +### GradientMachine + +Similar to the evaluation, the training needs to compute gradients so +to update model parameters. Because an [optimizer](#optimizer) might +run multiple simultaneous threads to update the same model, gradients +should be separated from the model. Because gradients are only used +in training, but not serving, they should be separate from Evaluator. +Hence the `GradientMachine`. + +### Optimizer + +None of Model, Evaluator, nor GradientMachine implements the training +loop, hence Optimizer. We can define a concurrent optimizer that runs +multiple simultaneious threads to train a model -- just let each +thread has its own GradientMachine object. From e4eacd5810d7253c3444b465c8284c88f1b0e1f6 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Thu, 9 Feb 2017 18:14:38 -0800 Subject: [PATCH 167/370] Add Programming section --- doc/design/api.md | 201 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 194 insertions(+), 7 deletions(-) diff --git a/doc/design/api.md b/doc/design/api.md index 3cfb67cb00d791..d8825389cb6947 100644 --- a/doc/design/api.md +++ b/doc/design/api.md @@ -1,4 +1,4 @@ -# Design Doc: PaddlePaddle API +# PaddlePaddle API ## Ingredients @@ -27,8 +27,8 @@ indicates a *reference*, and `-` marks a "class method". ### Model -We used to think that parameters are part of the toplogy (or layers). -But that is not true, because multiple layers could share the same +We used to think that parameters are part of the topology (or layers). +But that is not true because multiple layers could share the same parameter matrix. An example is a network that compares two text segments in a semantic space: @@ -56,8 +56,7 @@ parameter sharing, please refer to [TODO: API]. Supposed that we have a trained ranking model, we should be able to use it in our search engine. The search engine's Web server is a concurrent program so to serve many HTTP requests simultaneously. It -doens't make sense for each of these threads to have its own copy of -model, because that would duplicate topologies and parameters. +doesn't make sense for each of these threads to have its own copy of the model because that would duplicate topologies and parameters. However, each thread should be able to record layer outputs, i.e., activations, computed from an input, derived from the request. With *Evaluator* that saves activations, we can write the over-simplified @@ -70,7 +69,7 @@ http.handle("/", lambda req: e = paddle.evaluator.create(m) e.forward(req) - e.activation(layer="output")) # returns activations of layer "output" + e.activation(layer="output")) # returns activations of layer "output" ``` ### GradientMachine @@ -86,5 +85,193 @@ Hence the `GradientMachine`. None of Model, Evaluator, nor GradientMachine implements the training loop, hence Optimizer. We can define a concurrent optimizer that runs -multiple simultaneious threads to train a model -- just let each +multiple simultaneous threads to train a model -- just let each thread has its own GradientMachine object. + +Most models should be able to be trained using the +`paddle.optimizer.SGD` by calling its `train` method. Many +customizations to the SGD algorithm happens with the update equation, +e.g., momentum and the Adam SGD algorithm. We make `train` calls +`update` to do an update, so that we can derive a `paddle.optimizer.Adam` +from `paddle.optimizer.SGD` by overrides only the `update` method. + + +## Programming + +A fictive example of PaddlePaddle program looks like the following: + +```python +import paddle + +def read(args): + f = open_file(args["filename"]) + mb = read_a_minibatch(f) + end_pass = eof(f) + if end_pass: + f = open_file(args["filename"]) # rewind for reading again + yield mb, end_pass + +input = paddle.layer.data(...) +intermediate = paddle.layers.fc(input) +output = paddle.layer.softmax(intermediate) + +model = paddle.model.create(output) + +paddle.train(model, data_provider=read) +``` + +This shows some important part of a program: + +1. Define how to read (and augment) data by defining a function, in + this example, `read`, that `yields` a minibatch and a boolean flag + `eof_of_pass`. + +1. Define the topology, `input`, `intermediate`, and `output` in this + example. + +1. Create parameters from the topology thus forms the model by calling + `paddel.model.create`. + +1. Train the model by calling `paddle.train`. + + +### 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. + + +#### A Synthetic Data Reader + +Sometimes we want to test a topology and/or a training algorithm using +synthetic data. We can do this by defining the reader a synthesizer: + +```python +def read(args): + x = sample_from_uniform(0.0, 1.0) + y = sample_from_gauss(2 * x, sigma) + yield {x, y}, False # no end-of-file so no end-of-pass +``` + +#### A Reader for Online Learning + +Readers can also read an infinite data stream, e.g., a log stream from +a search engine and collected by Kafka: + +```python +def read(args): + log_stream = kafka.open_channel(args["kafka channel name"]) + yeild log_stream.read(), False # no end-of-pass in online learning +``` + +### Topology + +By default, layers don't have names. But if we want to refer to a +layer later some time, for example, when we do serving using the model +and wants activations/outputs of a layer, we should give it a name. + +```python +input = paddle.layer.data(...) +intermediate = paddle.layer.fc(input, name="inter", ...) +output = paddle.layer.softmax(intermediate, name="output", ...) + +m = paddle.model.create(output) +e = paddle.evaluator.create(model) +e.forward(read_an_input()) # compute activations of all layers. +print e.activations(layer="inter") # retrieve the activations of layer "inter" +print e.activations(layer="output") # retrieve the activations of layer "output" +``` + +#### Sharing Parameters + +In [above section](#model) we shows a network whose two layers share +the same parameter matrix. To specify such cases, we give "parameter +names" to layers. If some layers have the same paraemter names, +`paddle.model.create` creates a single parameter matrix for these +layers: + +```python +text1 = paddle.layer.data(...) +sematic1 = paddle.layer.fc(text1, ..., parameter_name="sematic_projection") +text2 = paddle.layer.data(...) +sematic2 = paddle.layer.fc(text2, ..., parameter_name="sematic_projection") +out = paddle.layer.cosine(semantic1, semantic2) +``` + +We can also share parameter matrices between layers in different +models. To do this, we need an additional parameter that refers to a +model: + +```python +model1_input = paddle.layer.data(...) +model1_output = paddle.layer.softmax(model1_input, ..., + parameter_name="a_parameter_matrix") +model1 = paddle.model.create(model1_output) + +# Another model +model2_semantic = paddle.layer.fc(text2, ..., + parameter_name="a_parameter_matrix", + parameter_model=model1) +``` + +### Training + +The recommended way to training a model is to call `paddle.train`, +which simply calls `paddle.optimizer.Default`, a global variable of +type `paddle.optimizer.SGD`. Equivalently, we can do + +```python +opt = paddle.optimizer.SGD(...) +opt.train(model, reader=read, ...) +``` + +#### 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, + reader=read, + optimizer=paddle.optimizer.SGDOptimizer(...), + 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(): + 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: + optimizer.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 knowns +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. From b17bc8a88ff5191ff75985bf36a149df796b508d Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Thu, 9 Feb 2017 18:39:22 -0800 Subject: [PATCH 168/370] GradientMachien refers to Evaluator but not Model --- doc/design/api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/design/api.md b/doc/design/api.md index d8825389cb6947..fe37cf091c5298 100644 --- a/doc/design/api.md +++ b/doc/design/api.md @@ -12,7 +12,7 @@ Evaluator = {Model*, activations} - forward - test -GradientMachine = {Model*, gradients} +GradientMachine = {Evaluator*, gradients} - backward Optimizer = {Model*, Evaluator*, GradientMachine*} From 08c0051f95bdb2e3334d228fef8e1bc465e8ce5f Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Thu, 9 Feb 2017 18:52:53 -0800 Subject: [PATCH 169/370] Fix problem pointed out by Long-Fei --- doc/design/api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/design/api.md b/doc/design/api.md index fe37cf091c5298..17ab50fdb26e64 100644 --- a/doc/design/api.md +++ b/doc/design/api.md @@ -15,7 +15,7 @@ Evaluator = {Model*, activations} GradientMachine = {Evaluator*, gradients} - backward -Optimizer = {Model*, Evaluator*, GradientMachine*} +Optimizer = {Model*, GradientMachine*} - train - update - checkpoint From e60fe1df22fa9cd37003c258474b2aa1b8cde500 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Thu, 9 Feb 2017 18:56:51 -0800 Subject: [PATCH 170/370] Cost as a parameter to train and test --- doc/design/api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/design/api.md b/doc/design/api.md index 17ab50fdb26e64..dcf19451b11622 100644 --- a/doc/design/api.md +++ b/doc/design/api.md @@ -10,13 +10,13 @@ Model = {topology, parameters} Evaluator = {Model*, activations} - forward -- test +- test(cost, ...) GradientMachine = {Evaluator*, gradients} - backward Optimizer = {Model*, GradientMachine*} -- train +- train(cost, ...) - update - checkpoint ``` From 6de262c357ef9274da304ffa804df935db103bc4 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Thu, 9 Feb 2017 19:51:28 -0800 Subject: [PATCH 171/370] Correct minor problems --- doc/design/api.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/design/api.md b/doc/design/api.md index dcf19451b11622..dd4341b32490dc 100644 --- a/doc/design/api.md +++ b/doc/design/api.md @@ -1,4 +1,4 @@ -# PaddlePaddle API +# PaddlePaddle Design Doc ## Ingredients @@ -15,7 +15,7 @@ Evaluator = {Model*, activations} GradientMachine = {Evaluator*, gradients} - backward -Optimizer = {Model*, GradientMachine*} +Optimizer = {GradientMachine*} - train(cost, ...) - update - checkpoint @@ -96,7 +96,7 @@ e.g., momentum and the Adam SGD algorithm. We make `train` calls from `paddle.optimizer.SGD` by overrides only the `update` method. -## Programming +## Programming Interface A fictive example of PaddlePaddle program looks like the following: From 970440622fd985afeaed76ea812e4779bb0bf901 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Fri, 10 Feb 2017 17:08:39 +0800 Subject: [PATCH 172/370] Temporary disable async load data in PyDP2. * It seems some other change breaks the async load. It will cause data error in GPU mode. --- paddle/gserver/dataproviders/PyDataProvider2.cpp | 2 +- python/paddle/trainer_config_helpers/data_sources.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/paddle/gserver/dataproviders/PyDataProvider2.cpp b/paddle/gserver/dataproviders/PyDataProvider2.cpp index c26e242534f2af..b8079dc0796d0e 100644 --- a/paddle/gserver/dataproviders/PyDataProvider2.cpp +++ b/paddle/gserver/dataproviders/PyDataProvider2.cpp @@ -647,7 +647,7 @@ class PyDataProvider2 : public DataProvider { DataBatch& gpuBatch = *batch; std::vector& gpuArguments = gpuBatch.getStreams(); gpuArguments.resize(cpuArguments.size()); - gpuBatch.setSize(size); + gpuBatch.setSize(bsize); for (size_t i = 0; i < headers_.size(); ++i) { gpuArguments[i].resizeAndCopyFrom( cpuArguments[i], useGpu_, HPPL_STREAM_1); diff --git a/python/paddle/trainer_config_helpers/data_sources.py b/python/paddle/trainer_config_helpers/data_sources.py index 0ea8fc77eef9f5..ab9a2562dcccb3 100644 --- a/python/paddle/trainer_config_helpers/data_sources.py +++ b/python/paddle/trainer_config_helpers/data_sources.py @@ -201,7 +201,7 @@ def py_data2(files, load_data_module, load_data_object, load_data_args, data.load_data_module = load_data_module data.load_data_object = load_data_object data.load_data_args = load_data_args - data.async_load_data = True + data.async_load_data = False return data define_py_data_sources( From ff6f7827dd6e067ff759d84c4a7519cf09522d02 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Fri, 10 Feb 2017 22:17:37 +0800 Subject: [PATCH 173/370] Fix protobuf version in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 162bebba091d84..f9ad1c9203d0a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,7 +54,7 @@ before_install: 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 - - pip install numpy wheel protobuf sphinx recommonmark sphinx_rtd_theme virtualenv pre-commit requests==2.9.2 LinkChecker + - pip install numpy wheel 'protobuf==3.1' sphinx recommonmark sphinx_rtd_theme virtualenv pre-commit requests==2.9.2 LinkChecker script: - paddle/scripts/travis/main.sh notifications: From 71c3c93c72409118b928b01478af95081a00114a Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Fri, 10 Feb 2017 22:39:46 +0800 Subject: [PATCH 174/370] Fix unittest --- .../tests/configs/protostr/test_split_datasource.protostr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/paddle/trainer_config_helpers/tests/configs/protostr/test_split_datasource.protostr b/python/paddle/trainer_config_helpers/tests/configs/protostr/test_split_datasource.protostr index 1cfb92255aa92f..569b0b945a762e 100644 --- a/python/paddle/trainer_config_helpers/tests/configs/protostr/test_split_datasource.protostr +++ b/python/paddle/trainer_config_helpers/tests/configs/protostr/test_split_datasource.protostr @@ -19,7 +19,7 @@ model_config { data_config { type: "py2" files: "train.list" - async_load_data: true + async_load_data: false for_test: false load_data_module: "a" load_data_object: "c" @@ -58,7 +58,7 @@ opt_config { test_data_config { type: "py2" files: "test.list" - async_load_data: true + async_load_data: false for_test: true load_data_module: "b" load_data_object: "d" From 67855d3b4edec4780a16e9583ab183753acf1581 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sun, 12 Feb 2017 16:07:27 +0800 Subject: [PATCH 175/370] Add comments --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index f9ad1c9203d0a9..5d82d9729b75ef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,6 +54,8 @@ before_install: 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 + # 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: - paddle/scripts/travis/main.sh From 00bf87ab3fa496d7c63527ab8a08a3a9f15bfa1e Mon Sep 17 00:00:00 2001 From: liaogang Date: Mon, 13 Feb 2017 11:24:07 +0800 Subject: [PATCH 176/370] Add default mkl dir in cmake --- cmake/cblas.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/cblas.cmake b/cmake/cblas.cmake index 26306f9849100d..235c95f017f2b6 100644 --- a/cmake/cblas.cmake +++ b/cmake/cblas.cmake @@ -16,7 +16,8 @@ set(CBLAS_FOUND OFF) ## 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 ${MKL_ROOT}/include) From 5a1f0617459177da6c5d1b52b4d514da253df68e Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Sun, 12 Feb 2017 21:55:11 -0800 Subject: [PATCH 177/370] Update according to discussions in https://github.com/PaddlePaddle/Paddle/issues/1315 --- doc/design/api.md | 293 +++++++++++++++++++--------------------------- 1 file changed, 119 insertions(+), 174 deletions(-) diff --git a/doc/design/api.md b/doc/design/api.md index dd4341b32490dc..f66a34fa98a3bc 100644 --- a/doc/design/api.md +++ b/doc/design/api.md @@ -2,140 +2,148 @@ ## Ingredients -As the first step of our design, we list important concepts in deep -learning and try to figure their relationship, as shown below: +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: -``` -Model = {topology, parameters} +1. A *topology* is an expression of *layers*. -Evaluator = {Model*, activations} -- forward -- test(cost, ...) +1. A layer could be any kind of computation, including *cost*. -GradientMachine = {Evaluator*, gradients} -- backward +1. Some layers have parameters, some don't. Most costs don't have + parameters. -Optimizer = {GradientMachine*} -- train(cost, ...) -- update -- checkpoint -``` +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 -where the pair of curly braces `{` and `}` indicate *composition*, `*` -indicates a *reference*, and `-` marks a "class method". +As a summarization +of +[our disucssion](https://github.com/PaddlePaddle/Paddle/issues/1315), +let us present two examples here: -### Model +### Example 1. Sharing Parameters between Layers -We used to think that parameters are part of the topology (or layers). -But that is not true because multiple layers could share the same -parameter matrix. An example is a network that compares two text -segments in a semantic space: +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: ``` - semantic -text A -> projection ---\ - layer A \ - cosine - similarity -> output - layer - semantic / -text B -> projection ---/ - layer B +A -> f -\ +Q -> f --> cost +B -> f -/ ``` -In this network, the two semantic projection layers (A and B) share -the same parameter matrix. - -For more information about our API that specifies topology and -parameter sharing, please refer to [TODO: API]. - - -### Evaluator - -Supposed that we have a trained ranking model, we should be able to -use it in our search engine. The search engine's Web server is a -concurrent program so to serve many HTTP requests simultaneously. It -doesn't make sense for each of these threads to have its own copy of the model because that would duplicate topologies and parameters. -However, each thread should be able to record layer outputs, i.e., -activations, computed from an input, derived from the request. With -*Evaluator* that saves activations, we can write the over-simplified -server program as: +The following program trains the topology including the cost, and then +use the sub-network in the trained topology in inference: ```python -m = paddle.model.load("trained.model") - -http.handle("/", - lambda req: - e = paddle.evaluator.create(m) - e.forward(req) - e.activation(layer="output")) # returns activations of layer "output" +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.cost.less_than( + paddle.cost.cross_entropy(fA, fQ), + paddle.cost.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) ``` -### GradientMachine - -Similar to the evaluation, the training needs to compute gradients so -to update model parameters. Because an [optimizer](#optimizer) might -run multiple simultaneous threads to update the same model, gradients -should be separated from the model. Because gradients are only used -in training, but not serving, they should be separate from Evaluator. -Hence the `GradientMachine`. -### Optimizer +### Example 2. Sharing Parameters between "Models" -None of Model, Evaluator, nor GradientMachine implements the training -loop, hence Optimizer. We can define a concurrent optimizer that runs -multiple simultaneous threads to train a model -- just let each -thread has its own GradientMachine object. +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: -Most models should be able to be trained using the -`paddle.optimizer.SGD` by calling its `train` method. Many -customizations to the SGD algorithm happens with the update equation, -e.g., momentum and the Adam SGD algorithm. We make `train` calls -`update` to do an update, so that we can derive a `paddle.optimizer.Adam` -from `paddle.optimizer.SGD` by overrides only the `update` method. - - -## Programming Interface - -A fictive example of PaddlePaddle program looks like the following: + ```python -import paddle - -def read(args): - f = open_file(args["filename"]) - mb = read_a_minibatch(f) - end_pass = eof(f) - if end_pass: - f = open_file(args["filename"]) # rewind for reading again - yield mb, end_pass - -input = paddle.layer.data(...) -intermediate = paddle.layers.fc(input) -output = paddle.layer.softmax(intermediate) - -model = paddle.model.create(output) - -paddle.train(model, data_provider=read) +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.cost.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.cost.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) ``` -This shows some important part of a program: -1. Define how to read (and augment) data by defining a function, in - this example, `read`, that `yields` a minibatch and a boolean flag - `eof_of_pass`. +### Summarization -1. Define the topology, `input`, `intermediate`, and `output` in this - example. -1. Create parameters from the topology thus forms the model by calling - `paddel.model.create`. +Above two programs reveal some important design concerns: -1. Train the model by calling `paddle.train`. +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*. -### Reader +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, @@ -145,78 +153,15 @@ readers and writers by deriving from base classes `Reader` and decide to provide the flexibility to users to define their readers. -#### A Synthetic Data Reader - -Sometimes we want to test a topology and/or a training algorithm using -synthetic data. We can do this by defining the reader a synthesizer: +There are some open questions here: -```python -def read(args): - x = sample_from_uniform(0.0, 1.0) - y = sample_from_gauss(2 * x, sigma) - yield {x, y}, False # no end-of-file so no end-of-pass -``` - -#### A Reader for Online Learning - -Readers can also read an infinite data stream, e.g., a log stream from -a search engine and collected by Kafka: - -```python -def read(args): - log_stream = kafka.open_channel(args["kafka channel name"]) - yeild log_stream.read(), False # no end-of-pass in online learning -``` - -### Topology - -By default, layers don't have names. But if we want to refer to a -layer later some time, for example, when we do serving using the model -and wants activations/outputs of a layer, we should give it a name. +1. **Should a reader return a Python dictionary?** -```python -input = paddle.layer.data(...) -intermediate = paddle.layer.fc(input, name="inter", ...) -output = paddle.layer.softmax(intermediate, name="output", ...) - -m = paddle.model.create(output) -e = paddle.evaluator.create(model) -e.forward(read_an_input()) # compute activations of all layers. -print e.activations(layer="inter") # retrieve the activations of layer "inter" -print e.activations(layer="output") # retrieve the activations of layer "output" -``` - -#### Sharing Parameters +1. **How to map multiple outputs from a reader to multiple data layers?** -In [above section](#model) we shows a network whose two layers share -the same parameter matrix. To specify such cases, we give "parameter -names" to layers. If some layers have the same paraemter names, -`paddle.model.create` creates a single parameter matrix for these -layers: +1. **How to easily compose some existing readers to read more data and + feed a topology with more data layers?** -```python -text1 = paddle.layer.data(...) -sematic1 = paddle.layer.fc(text1, ..., parameter_name="sematic_projection") -text2 = paddle.layer.data(...) -sematic2 = paddle.layer.fc(text2, ..., parameter_name="sematic_projection") -out = paddle.layer.cosine(semantic1, semantic2) -``` - -We can also share parameter matrices between layers in different -models. To do this, we need an additional parameter that refers to a -model: - -```python -model1_input = paddle.layer.data(...) -model1_output = paddle.layer.softmax(model1_input, ..., - parameter_name="a_parameter_matrix") -model1 = paddle.model.create(model1_output) - -# Another model -model2_semantic = paddle.layer.fc(text2, ..., - parameter_name="a_parameter_matrix", - parameter_model=model1) -``` ### Training @@ -270,7 +215,7 @@ def dist_train(): 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 knowns +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 From ce49124dae0d7d8ff699afdd04053e118d58698e Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 13 Feb 2017 14:33:50 +0800 Subject: [PATCH 178/370] Draft for new API --- demo/mnist/api_train_v2.py | 61 +++++++++++++ python/paddle/v2/__init__.py | 14 ++- python/paddle/v2/parameters.py | 111 +++++++++++++++++++++++ python/paddle/v2/trainer.py | 160 +++++++++++++++++++++++++++++++++ 4 files changed, 344 insertions(+), 2 deletions(-) create mode 100644 demo/mnist/api_train_v2.py create mode 100644 python/paddle/v2/parameters.py create mode 100644 python/paddle/v2/trainer.py diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py new file mode 100644 index 00000000000000..19c11b6de5e0b5 --- /dev/null +++ b/demo/mnist/api_train_v2.py @@ -0,0 +1,61 @@ +from paddle.trainer_config_helpers import * +from paddle.trainer.PyDataProvider2 import dense_vector, integer_value +import paddle.v2 as paddle_v2 +import numpy +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 network_config(): + 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 event_handler(event): + if isinstance(event, paddle_v2.trainer.CompleteTrainOneBatch): + print "Pass %d, Batch %d, Cost %f" % (event.pass_id, event.batch_id, + event.cost) + else: + pass + + +def main(): + paddle_v2.init(use_gpu=False, trainer_count=1) + model_config = parse_network_config(network_config) + pool = paddle_v2.parameters.create(model_config) + for param_name in pool.get_names(): + array = pool.get_parameter(param_name) + array[:] = numpy.random.uniform(low=-1.0, high=1.0, size=array.shape) + + trainer = paddle_v2.trainer.SGDTrainer( + update_equation=paddle_v2.optimizer.Adam( + learning_rate=1e-4, + model_average=ModelAverage(average_window=0.5), + regularization=L2Regularization(rate=0.5))) + + trainer.train(train_data_reader=train_reader, + topology=model_config, + parameters=pool, + 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': dense_vector(784), + 'label': integer_value(10) + }) + + +if __name__ == '__main__': + main() diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index b2ea87b086101d..f50c36ce64995b 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -11,7 +11,17 @@ # 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. - import optimizer +import parameters +import py_paddle.swig_paddle as api +import trainer + +__all__ = ['optimizer', 'parameters', 'init', 'trainer'] + + +def init(**kwargs): + args = [] + for key in kwargs.keys(): + args.append('--%s=%s' % (key, str(kwargs[key]))) -__all__ = ['optimizer'] + api.initPaddle(*args) diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py new file mode 100644 index 00000000000000..892c68a38bd706 --- /dev/null +++ b/python/paddle/v2/parameters.py @@ -0,0 +1,111 @@ +import numpy as np + +from paddle.proto.ModelConfig_pb2 import ModelConfig +from paddle.proto.ParameterConfig_pb2 import ParameterConfig + +__all__ = ['IParameterPool', 'create', 'ParameterFlag'] + + +class ParameterFlag(object): + """ + The flag for IParameterPool.get_parameter. If writeable, operation on return + numpy array will also apply to Paddle parameter. But it will be slower in + GPU mode. + """ + READ_ONLY = 0x01 + WRITE_ONLY = 0x02 + READ_WRITE = READ_ONLY | WRITE_ONLY + + +class IParameterPool(object): + """ + Interface of Parameter Pool. The parameter pool is a dictionary of + parameters. User can modify parameter or customize parameter value + by `get_parameter`. + + .. code-block:: python + + pool = paddle.parameters.create(topo1, topo2) + + embedding = pool.get_parameter("embedding") + assert isinstance(embedding, numpy.ndarray) + print embedding[1:] + """ + + def get_parameter(self, name, flag=ParameterFlag.READ_WRITE): + """ + Get a parameter by name. + + :param name: parameter name. + :type name: basestring + :param flag: the flag for return value. readable or writable. + :type flag: int + :return: The parameter value + :rtype: np.ndarray + """ + raise NotImplementedError() + + def get_names(self): + """ + Get all parameter names + :return: all parameter names + :rtype: list + """ + raise NotImplementedError() + + +class NumpyParameterPool(IParameterPool): + def __init__(self): + self.__param_configs__ = dict() + self.__params__ = dict() + + def append(self, conf): + if not isinstance(conf, ParameterConfig): + raise ValueError("conf must be ParameterConfig") + + if not conf.IsInitialized(): + raise ValueError("conf is not initialized") + + self.__param_configs__[conf.name] = conf + self.__params__[conf.name] = None + + def get_config(self, name): + if name not in self.__param_configs__: + raise ValueError("parameter %s is not appended" % name) + + return self.__param_configs__[name] + + def get_parameter(self, name, *args, **kwargs): + if name not in self.__params__: + raise ValueError("parameter %s is not appended" % name) + + param = self.__params__[name] + if param is None: + shape = self.__param_configs__[name].dims + if len(shape) == 0: + raise ValueError("parameter %s is no shape" % name) + param = np.ndarray( + shape=[int(item) for item in shape], dtype='float32') + self.__params__[name] = param + return param + + def get_names(self): + return self.__param_configs__.keys() + + +def create(*topologies): + """ + Create parameter pool by topologies. + + :param topologies: + :return: + """ + pool = NumpyParameterPool() + for topo in topologies: + if not isinstance(topo, ModelConfig): + raise ValueError( + 'create must pass a topologies which type is ModelConfig') + + for param in topo.parameters: + pool.append(param) + return pool diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py new file mode 100644 index 00000000000000..933700c6155277 --- /dev/null +++ b/python/paddle/v2/trainer.py @@ -0,0 +1,160 @@ +import collections +from paddle.proto.ModelConfig_pb2 import ModelConfig +import paddle.v2.parameters +import paddle.v2.optimizer +import py_paddle.swig_paddle as api +from py_paddle import DataProviderConverter + +__all__ = ['ITrainer', 'SGDTrainer', 'CompleteTrainOneBatch', 'BaseEvent'] + + +class BaseEvent(object): + """ + Just a marker class + """ + pass + + +class CompleteTrainOneBatch(BaseEvent): + def __init__(self, pass_id, batch_id, cost): + self.pass_id = pass_id + self.batch_id = batch_id + self.cost = cost + + +def default_event_handler(event): + pass + + +class ITrainer(object): + def train(self, + train_data_reader, + topology, + parameters, + test_data_reader=None, + event_handler=None): + raise NotImplementedError() + + +class SGDTrainer(ITrainer): + def __init__(self, update_equation): + if not isinstance(update_equation, paddle.v2.optimizer.Optimizer): + raise ValueError() + + self.__optimizer__ = update_equation + + def train(self, + train_data_reader, + topology, + parameters, + num_passes=1, + test_data_reader=None, + event_handler=None, + batch_size=32, + data_types=None): + if event_handler is None: + event_handler = default_event_handler + + __check_train_args__(**locals()) + + gm = api.GradientMachine.createFromConfigProto( + topology, api.CREATE_MODE_NORMAL, self.__optimizer__.enable_types()) + assert isinstance(gm, api.GradientMachine) + __copy_parameter_from_pool__(gm, parameters) + + updater = self.__optimizer__.create_local_updater() + assert isinstance(updater, api.ParameterUpdater) + updater.init(gm) + + data_types_lists = [] + for each in topology.input_layer_names: + if each not in data_types: + raise ValueError() + data_types_lists.append(data_types[each]) + + converter = DataProviderConverter(input_types=data_types_lists) + + def input_reorder(func): + for item in func(): + retv = [] + for __layer_name__ in topology.input_layer_names: + retv.append(item[__layer_name__]) + yield retv + + gm.start() + + out_args = api.Arguments.createArguments(0) + for pass_id in xrange(num_passes): + updater.startPass() + for batch_id, data_batch in enumerate( + __generator_to_batch__( + input_reorder(train_data_reader), + batch_size=batch_size)): + pass_type = updater.startBatch(len(data_batch)) + gm.forwardBackward(converter(data_batch), out_args, pass_type) + for each_param in gm.getParameters(): + updater.update(each_param) + # Get cost. We use numpy to calculate total cost for this batch. + cost_vec = out_args.getSlotValue(0) + cost_vec = cost_vec.copyToNumpyMat() + cost = cost_vec.sum() / len(data_batch) + updater.finishBatch(cost) + + event_handler( + CompleteTrainOneBatch( + pass_id=pass_id, batch_id=batch_id, cost=cost)) + + updater.finishPass() + gm.finish() + + +def __generator_to_batch__(generator, batch_size): + ret_val = list() + for each_item in generator: + ret_val.append(each_item) + if len(ret_val) == batch_size: + yield ret_val + ret_val = list() + if len(ret_val) != 0: + yield ret_val + + +def __copy_parameter_from_pool__(gm, pool): + """ + + :param gm: + :type gm: api.GradientMachine + :param pool: + :type pool: paddle.v2.parameters.IParameterPool + :return: + """ + assert isinstance(pool, paddle.v2.parameters.IParameterPool) + for each_param in gm.getParameters(): + name = each_param.getName() + param = pool.get_parameter(name, + paddle.v2.parameters.ParameterFlag.READ_ONLY) + each_param.getBuf(api.PARAMETER_VALUE).copyFromNumpyArray(param.flatten( + ).astype('float32')) + + +def __check_train_args__(train_data_reader, topology, parameters, + test_data_reader, event_handler, **kwargs): + if not callable(train_data_reader) or not isinstance(train_data_reader(), + collections.Iterator): + raise ValueError('train_data_reader should be a function, ' + 'which can return a iterator') + + if test_data_reader is not None: + if not callable(test_data_reader) or not isinstance( + test_data_reader(), collections.Iterator): + raise ValueError('test_data_reader should be a function, which can ' + 'return a iterator') + + if not isinstance(topology, ModelConfig): + raise ValueError('topology should be a model config') + + if not isinstance(parameters, paddle.v2.parameters.IParameterPool): + raise ValueError('parameters should be a parameter pool') + + if not callable(event_handler): + raise ValueError('event handler should be a function') From dc7f2031caaf473ab618b25b6187af47b76b22e1 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 13 Feb 2017 15:06:02 +0800 Subject: [PATCH 179/370] Add comments for functions --- python/paddle/v2/trainer.py | 63 +++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 933700c6155277..3794ab07720e21 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -16,6 +16,10 @@ class BaseEvent(object): class CompleteTrainOneBatch(BaseEvent): + """ + Event On One Batch Training Complete. + """ + def __init__(self, pass_id, batch_id, cost): self.pass_id = pass_id self.batch_id = batch_id @@ -38,6 +42,11 @@ def train(self, class SGDTrainer(ITrainer): def __init__(self, update_equation): + """ + Simple SGD Trainer. + + :param update_equation: Maybe we should give a DSL for update equation? + """ if not isinstance(update_equation, paddle.v2.optimizer.Optimizer): raise ValueError() @@ -52,6 +61,21 @@ def train(self, event_handler=None, batch_size=32, data_types=None): + """ + Training method. Will train num_passes of input data. + + :param train_data_reader: + :param topology: Network Topology, a protobuf ModelConfig message. + :param parameters: The parameter pools. + :param num_passes: The total train passes. + :param test_data_reader: + :param event_handler: Event handler. A method will be invoked when event + occurred. + :type event_handler: (BaseEvent) => None + :param batch_size: Not important, will be removed after data refactor. + :param data_types: Not important, will be removed after data refactor. + :return: + """ if event_handler is None: event_handler = default_event_handler @@ -66,6 +90,9 @@ def train(self, assert isinstance(updater, api.ParameterUpdater) updater.init(gm) + gm.start() + out_args = api.Arguments.createArguments(0) + data_types_lists = [] for each in topology.input_layer_names: if each not in data_types: @@ -74,22 +101,11 @@ def train(self, converter = DataProviderConverter(input_types=data_types_lists) - def input_reorder(func): - for item in func(): - retv = [] - for __layer_name__ in topology.input_layer_names: - retv.append(item[__layer_name__]) - yield retv - - gm.start() - - out_args = api.Arguments.createArguments(0) for pass_id in xrange(num_passes): updater.startPass() for batch_id, data_batch in enumerate( - __generator_to_batch__( - input_reorder(train_data_reader), - batch_size=batch_size)): + __data_reader_to_batch__(train_data_reader, batch_size, + topology)): pass_type = updater.startBatch(len(data_batch)) gm.forwardBackward(converter(data_batch), out_args, pass_type) for each_param in gm.getParameters(): @@ -108,7 +124,25 @@ def input_reorder(func): gm.finish() +def __data_reader_to_batch__(reader, batch_size, topology): + """ + This function is not important, and will be removed when data refactored. + """ + + def input_reorder(func): + for item in func(): + retv = [] + for __layer_name__ in topology.input_layer_names: + retv.append(item[__layer_name__]) + yield retv + + return __generator_to_batch__(input_reorder(reader), batch_size=batch_size) + + def __generator_to_batch__(generator, batch_size): + """ + This function is not important, and will be removed when data refactored. + """ ret_val = list() for each_item in generator: ret_val.append(each_item) @@ -139,6 +173,9 @@ def __copy_parameter_from_pool__(gm, pool): def __check_train_args__(train_data_reader, topology, parameters, test_data_reader, event_handler, **kwargs): + """ + Check train function's argument types + """ if not callable(train_data_reader) or not isinstance(train_data_reader(), collections.Iterator): raise ValueError('train_data_reader should be a function, ' From e13d9c74a2d5196ad452bb1b1ceb21648be8ad50 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 13 Feb 2017 15:46:41 +0800 Subject: [PATCH 180/370] Expose Parameter to train event handler * User can get/set parameter in event now. * Add update equation --- demo/mnist/api_train_v2.py | 23 ++++-- python/paddle/v2/trainer.py | 139 ++++++++++++++++++++++++++++++++---- 2 files changed, 144 insertions(+), 18 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 19c11b6de5e0b5..6ceff8284d57b9 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -39,11 +39,24 @@ def main(): array = pool.get_parameter(param_name) array[:] = numpy.random.uniform(low=-1.0, high=1.0, size=array.shape) - trainer = paddle_v2.trainer.SGDTrainer( - update_equation=paddle_v2.optimizer.Adam( - learning_rate=1e-4, - model_average=ModelAverage(average_window=0.5), - regularization=L2Regularization(rate=0.5))) + def nag(v, g, vel_t_1): + """ + NAG Optimizer. A optimizer which Paddle CPP is not implemented. + https://arxiv.org/pdf/1212.0901v2.pdf eq.6 eq.7 + :param v: parameter value + :param g: parameter gradient + :param vel_t_1: t-1 velocity + :return: + """ + mu = 0.09 + e = 0.0001 + + vel_t = mu * vel_t_1 - e * g + + v[:] = v + (mu**2) * vel_t - (1 + mu) * e * g + vel_t_1[:] = vel_t + + trainer = paddle_v2.trainer.SGDTrainer(update_equation=nag) trainer.train(train_data_reader=train_reader, topology=model_config, diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 3794ab07720e21..0375caa55259fa 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -1,7 +1,8 @@ import collections from paddle.proto.ModelConfig_pb2 import ModelConfig -import paddle.v2.parameters -import paddle.v2.optimizer +from paddle.proto.ParameterConfig_pb2 import ParameterConfig +from . import parameters as v2_parameters +import numpy import py_paddle.swig_paddle as api from py_paddle import DataProviderConverter @@ -20,10 +21,11 @@ class CompleteTrainOneBatch(BaseEvent): Event On One Batch Training Complete. """ - def __init__(self, pass_id, batch_id, cost): + def __init__(self, pass_id, batch_id, cost, parameters): self.pass_id = pass_id self.batch_id = batch_id self.cost = cost + self.paramters = parameters def default_event_handler(event): @@ -40,6 +42,102 @@ def train(self, raise NotImplementedError() +class LazyParameterPool(v2_parameters.IParameterPool): + """ + :type __gradient_machine__: api.GradientMachine + """ + + def get_parameter(self, name, flag=v2_parameters.ParameterFlag.READ_WRITE): + param = filter(lambda x: x.getName() == name, + self.__gradient_machine__.getParameters()) + if len(param) == 0: + raise ValueError("Cannot found parameter with name %s" % name) + elif len(param) > 1: + raise RuntimeError("Unexpected branch") + else: + conf = param[0].getConfig().toProto() + param = param[0].getBuf(api.PARAMETER_VALUE) + assert isinstance(param, api.Vector) + assert isinstance(conf, ParameterConfig) + + shape = map(int, conf.dims) + if api.isUsingGpu(): + arr = param.copyToNumpyArray().reshape(shape) + if flag & v2_parameters.ParameterFlag.WRITE_ONLY: + self.need_copy = True + self.arrays[name] = arr + else: + arr = param.toNumpyArrayInplace().reshape(shape) + return arr + + def get_names(self): + return [ + param.getName() + for param in self.__gradient_machine__.getParameters() + ] + + def __init__(self, gradient_machine): + self.__gradient_machine__ = gradient_machine + self.need_copy = False + self.arrays = dict() + + +class CustomizeUpdateEquation(object): + def __init__(self, callback): + self.__callback__ = callback + if self.__callback__.func_code.co_argcount < 2: + raise ValueError( + "The update equation at least should contain 2 arguments, " + "first is value, second is gradient") + + self.local_params_count = self.__callback__.func_code.co_argcount - 2 + self.local_params = dict() + + def enable_types(self): + return [api.PARAMETER_VALUE, api.PARAMETER_GRADIENT] + + def init(self, gradient_machine): + assert isinstance(gradient_machine, api.GradientMachine) + for param in gradient_machine.getParameters(): + conf = param.getConfig().toProto() + shape = map(int, conf.dims) + self.local_params[conf.name] = [] + for _ in xrange(self.local_params_count): + self.local_params[conf.name].append( + numpy.zeros( + shape=shape, dtype='float32')) + + def create_local_updater(self): + return self + + def startPass(self): + pass + + def finishPass(self): + pass + + def startBatch(self, batch_size): + return api.PASS_TRAIN + + def finishBatch(self, cost): + pass + + def update(self, param): + conf = param.getConfig().toProto() + shape = map(int, conf.dims) + if not api.isUsingGpu(): + v = param.getBuf(api.PARAMETER_VALUE).toNumpyArrayInplace().reshape( + shape) + g = param.getBuf(api.PARAMETER_GRADIENT).toNumpyArrayInplace( + ).reshape(shape) + args = [v, g] + for arg in self.local_params[conf.name]: + args.append(arg) + self.__callback__(*args) + else: + raise NotImplementedError() + + class SGDTrainer(ITrainer): def __init__(self, update_equation): """ @@ -47,8 +145,8 @@ def __init__(self, update_equation): :param update_equation: Maybe we should give a DSL for update equation? """ - if not isinstance(update_equation, paddle.v2.optimizer.Optimizer): - raise ValueError() + if callable(update_equation): + update_equation = CustomizeUpdateEquation(update_equation) self.__optimizer__ = update_equation @@ -87,7 +185,6 @@ def train(self, __copy_parameter_from_pool__(gm, parameters) updater = self.__optimizer__.create_local_updater() - assert isinstance(updater, api.ParameterUpdater) updater.init(gm) gm.start() @@ -115,10 +212,16 @@ def train(self, cost_vec = cost_vec.copyToNumpyMat() cost = cost_vec.sum() / len(data_batch) updater.finishBatch(cost) - + pool = LazyParameterPool(gradient_machine=gm) event_handler( CompleteTrainOneBatch( - pass_id=pass_id, batch_id=batch_id, cost=cost)) + pass_id=pass_id, + batch_id=batch_id, + cost=cost, + parameters=pool)) + + if pool.need_copy: + __copy_parameter_from_lazy_pool__(gm, pool) updater.finishPass() gm.finish() @@ -153,20 +256,30 @@ def __generator_to_batch__(generator, batch_size): yield ret_val +def __copy_parameter_from_lazy_pool__(gm, pool): + assert isinstance(pool, LazyParameterPool) + for each_param_name in pool.arrays.keys(): + param = filter(lambda x: x.getName() == each_param_name, + gm.getParameters()) + assert len(param) == 1 + param = param[0] + param.getBuf(api.PARAMETER_VALUE).copyFromNumpyArray(pool.arrays[ + each_param_name].flatten().astype('float32')) + + def __copy_parameter_from_pool__(gm, pool): """ :param gm: :type gm: api.GradientMachine :param pool: - :type pool: paddle.v2.parameters.IParameterPool + :type pool: v2_parameters.IParameterPool :return: """ - assert isinstance(pool, paddle.v2.parameters.IParameterPool) + assert isinstance(pool, v2_parameters.IParameterPool) for each_param in gm.getParameters(): name = each_param.getName() - param = pool.get_parameter(name, - paddle.v2.parameters.ParameterFlag.READ_ONLY) + param = pool.get_parameter(name, v2_parameters.ParameterFlag.READ_ONLY) each_param.getBuf(api.PARAMETER_VALUE).copyFromNumpyArray(param.flatten( ).astype('float32')) @@ -190,7 +303,7 @@ def __check_train_args__(train_data_reader, topology, parameters, if not isinstance(topology, ModelConfig): raise ValueError('topology should be a model config') - if not isinstance(parameters, paddle.v2.parameters.IParameterPool): + if not isinstance(parameters, v2_parameters.IParameterPool): raise ValueError('parameters should be a parameter pool') if not callable(event_handler): From 8e0d1d8be1cd1fb9dd7671e27beb60509735c968 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 13 Feb 2017 17:55:10 +0800 Subject: [PATCH 181/370] Complete update equation. --- demo/mnist/api_train_v2.py | 2 +- python/paddle/v2/trainer.py | 33 +++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 6ceff8284d57b9..ab1581325aa95d 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -49,7 +49,7 @@ def nag(v, g, vel_t_1): :return: """ mu = 0.09 - e = 0.0001 + e = 0.00001 vel_t = mu * vel_t_1 - e * g diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 0375caa55259fa..9620e754208100 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -25,7 +25,7 @@ def __init__(self, pass_id, batch_id, cost, parameters): self.pass_id = pass_id self.batch_id = batch_id self.cost = cost - self.paramters = parameters + self.parameters = parameters def default_event_handler(event): @@ -44,6 +44,17 @@ def train(self, class LazyParameterPool(v2_parameters.IParameterPool): """ + Lazy Parameter Pool stores a reference to GradientMachine. User could invoke + `get_parameter` if needed, but the operation is lazy. It means the parameter + will only fetched from GPU or Parameter Server if `get_parameter` is + invoked. Also, set flag = writable will make a extra host2device copy after + reading/modifying parameter. + + This class is not exposed to User. User should treat this class as a normal + IParameterPool. + + See IParameterPool for usage documentation. + :type __gradient_machine__: api.GradientMachine """ @@ -130,12 +141,22 @@ def update(self, param): shape) g = param.getBuf(api.PARAMETER_GRADIENT).toNumpyArrayInplace( ).reshape(shape) - args = [v, g] - for arg in self.local_params[conf.name]: - args.append(arg) - self.__callback__(*args) + else: - raise NotImplementedError() + v = param.getBuf(api.PARAMETER_VALUE).copyToNumpyArray().reshape( + shape) + g = param.getBuf(api.PARAMETER_GRADIENT).copyToNumpyArray().reshape( + shape) + + args = [v, g] + for arg in self.local_params[conf.name]: + args.append(arg) + self.__callback__(*args) + + if api.isUsingGpu(): + param.getBuf(api.PARAMETER_VALUE).copyFromNumpyArray(v.flatten( + ).astype('float32')) + # discard gradient changed. class SGDTrainer(ITrainer): From 8b70f0f3d004b7fd88621c464c1e28b06999f7e4 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Mon, 13 Feb 2017 07:35:05 -0800 Subject: [PATCH 182/370] addrss https://github.com/PaddlePaddle/Paddle/issues/1319 as well --- doc/design/api.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/doc/design/api.md b/doc/design/api.md index f66a34fa98a3bc..777983cd7ae268 100644 --- a/doc/design/api.md +++ b/doc/design/api.md @@ -166,14 +166,19 @@ There are some open questions here: ### Training The recommended way to training a model is to call `paddle.train`, -which simply calls `paddle.optimizer.Default`, a global variable of -type `paddle.optimizer.SGD`. Equivalently, we can do +which simply calls `paddle.trainer.Default`, a global variable of +type `paddle.trainer.SGD`. Equivalently, we can do ```python -opt = paddle.optimizer.SGD(...) +opt = paddle.trainer.SGD(..., paddle.updater.Adam(...)) opt.train(model, reader=read, ...) ``` +Please be aware that a trainer requires an updater as its data +member. This is to make it easier to customize trainers, as +discussed [here](https://github.com/PaddlePaddle/Paddle/issues/1319). + + #### Distributed Training If users want to do distributed training on a cluster, s/he should @@ -185,8 +190,9 @@ 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, - optimizer=paddle.optimizer.SGDOptimizer(...), k8s_user="yi", k8s_token="kube_cluster_tls.pem", k8s_job="hello", @@ -196,7 +202,7 @@ paddle.dist_train(model, The pseudo code if `paddle.dist_train` is as follows: ```python -def dist_train(): +def dist_train(topology, parameters, trainer, reader, ...): if os.getenv("KUBERNETES_SERVICE_HOST") == None: image_name = k8s_user + '/' + k8s_job docker_build(image_name) @@ -209,7 +215,7 @@ def dist_train(): elif rank < 15: parameter_server() else: - optimizer.train(model, reader=read) + trainer.train(model, reader=read) ``` Please be aware that if a process is running on the Kubernetes From 3529c6c328e0d83289ff5d965707d1544d6ba64c Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Mon, 13 Feb 2017 14:34:01 -0800 Subject: [PATCH 183/370] Put all layers and costs in package paddle.layer --- doc/design/api.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/doc/design/api.md b/doc/design/api.md index 777983cd7ae268..6894329c7dcd6b 100644 --- a/doc/design/api.md +++ b/doc/design/api.md @@ -16,11 +16,11 @@ Some essential concepts that our API have to provide include: 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 @@ -59,9 +59,9 @@ 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.cost.less_than( - paddle.cost.cross_entropy(fA, fQ), - paddle.cost.corss_entropy(fB, fQ)) +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) @@ -86,7 +86,7 @@ correspond to the two networks in the following figure: ```python def G(in): # over-simplified example as G has only one layers: - return paddle.layer.fc(in, parameter_name="G") + return paddle.layer.fc(in, parameter_name="G") def D(in); # again, over-simplified: @@ -94,12 +94,12 @@ def D(in); # Construct the first topology, which contains both D and G. # By learning this topology, we update parameters of G. -d0 = paddle.cost.should_be_false(D(G(paddle.layer.data()))) +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 +# training this topology, we update parameters of D. Note # that d1 share parameters with d0. -d1 = paddle.cost.should_be_true(D(paddle.layer.data())) +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. @@ -132,16 +132,16 @@ Above two programs reveal some important design concerns: 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 @@ -190,7 +190,7 @@ access a Kubernetes cluster, s/he should be able to call ```python paddle.dist_train(model, - trainer=paddle.trainer.SGD(..., + trainer=paddle.trainer.SGD(..., paddle.updater.Adam(...)), reader=read, k8s_user="yi", From 92ab6148dee932ffb630a1188b5c4d6112379bc8 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Mon, 13 Feb 2017 16:07:07 -0800 Subject: [PATCH 184/370] Add Event Handler --- doc/design/api.md | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/doc/design/api.md b/doc/design/api.md index 6894329c7dcd6b..6b2fe82946dd78 100644 --- a/doc/design/api.md +++ b/doc/design/api.md @@ -163,7 +163,7 @@ There are some open questions here: feed a topology with more data layers?** -### Training +## Training The recommended way to training a model is to call `paddle.train`, which simply calls `paddle.trainer.Default`, a global variable of @@ -171,15 +171,42 @@ type `paddle.trainer.SGD`. Equivalently, we can do ```python opt = paddle.trainer.SGD(..., paddle.updater.Adam(...)) -opt.train(model, reader=read, ...) +opt.train(topology, parameters, reader=read, ...) ``` +### Updater + Please be aware that a trainer requires an updater as its data member. 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. BeginMinibatch +1. EndMinibatch +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.EndMinibatch): + print paddle.test(...) + +paddle.train(topology, parameters, reader, event_handler) +``` -#### Distributed Training +### 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 From 6915cb290176d1a6948ce0f83f8a460cab85337d Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Mon, 13 Feb 2017 16:10:17 -0800 Subject: [PATCH 185/370] Add metaplotlib for iPython --- doc/design/api.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/doc/design/api.md b/doc/design/api.md index 6b2fe82946dd78..8185d2af0ea264 100644 --- a/doc/design/api.md +++ b/doc/design/api.md @@ -176,9 +176,11 @@ opt.train(topology, parameters, reader=read, ...) ### Updater -Please be aware that a trainer requires an updater as its data -member. This is to make it easier to customize trainers, as -discussed [here](https://github.com/PaddlePaddle/Paddle/issues/1319). +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 @@ -188,8 +190,8 @@ that handle some events: 1. BeginTraining 1. EndTraining -1. BeginMinibatch -1. EndMinibatch +1. BeginIteration +1. EndIteration 1. BeginPass 1. EndPass @@ -200,12 +202,17 @@ An example as follows: ```python def event_handler(event): - if ininstance(event, paddle.event.EndMinibatch): + 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 From 0bd75a57e866bc1cff0b25cc1ea433f3104bf77e Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 14 Feb 2017 15:15:56 +0800 Subject: [PATCH 186/370] change layers to layer --- demo/mnist/api_train.py | 21 +++---- python/paddle/v2/__init__.py | 4 +- python/paddle/v2/{layers.py => layer.py} | 70 +++++++++++++++--------- 3 files changed, 58 insertions(+), 37 deletions(-) rename python/paddle/v2/{layers.py => layer.py} (70%) diff --git a/demo/mnist/api_train.py b/demo/mnist/api_train.py index 6d071cdffe120f..f0c56b77cf8578 100644 --- a/demo/mnist/api_train.py +++ b/demo/mnist/api_train.py @@ -10,7 +10,7 @@ import numpy as np import paddle.trainer.PyDataProvider2 as dp -import paddle.v2 +import paddle.v2 as paddle_v2 import py_paddle.swig_paddle as api from paddle.trainer_config_helpers import * from py_paddle import DataProviderConverter @@ -58,7 +58,7 @@ def input_order_converter(generator): def main(): 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, batch_size=1000, model_average=ModelAverage(average_window=0.5), @@ -71,16 +71,17 @@ def main(): assert isinstance(updater, api.ParameterUpdater) # define network - images = paddle.v2.layers.data_layer(name='pixel', size=784) - label = paddle.v2.layers.data_layer(name='label', size=10) - hidden1 = paddle.v2.layers.fc_layer(input=images, size=200) - hidden2 = paddle.v2.layers.fc_layer(input=hidden1, size=200) - inference = paddle.v2.layers.fc_layer( - input=hidden2, size=10, act=SoftmaxActivation()) - cost = paddle.v2.layers.classification_cost(input=inference, label=label) + images = paddle_v2.layer.data(name='pixel', size=784) + label = paddle_v2.layer.data(name='label', size=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=SoftmaxActivation()) + cost = paddle_v2.layer.classification_cost(input=inference, label=label) # Create Simple Gradient Machine. - model_config = paddle.v2.layers.parse_network(cost) + model_config = paddle_v2.layer.parse_network(cost) m = api.GradientMachine.createFromConfigProto(model_config, api.CREATE_MODE_NORMAL, optimizer.enable_types()) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index c04c0cc73a800a..590fb5cd523ce7 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -13,6 +13,6 @@ # limitations under the License. import optimizer -import layers +import layer -__all__ = ['optimizer', 'layers'] +__all__ = ['optimizer', 'layer'] diff --git a/python/paddle/v2/layers.py b/python/paddle/v2/layer.py similarity index 70% rename from python/paddle/v2/layers.py rename to python/paddle/v2/layer.py index 14efe9412c3582..4cdb2a3638a5d1 100644 --- a/python/paddle/v2/layers.py +++ b/python/paddle/v2/layer.py @@ -19,6 +19,21 @@ import collections +def parse_network(*outputs): + """ + parse all output layers and then generate a model config proto. + :param outputs: + :return: + """ + + def __real_func__(): + context = dict() + real_output = [each.to_proto(context=context) for each in outputs] + conf_helps.outputs(real_output) + + return __parse__(__real_func__) + + class Layer(object): def __init__(self, name, parent_layer): assert isinstance(parent_layer, dict) @@ -49,22 +64,13 @@ def to_proto_impl(self, **kwargs): raise NotImplementedError() -def parse_network(*outputs): - def __real_func__(): - context = dict() - real_output = [each.to_proto(context=context) for each in outputs] - conf_helps.outputs(real_output) - - return __parse__(__real_func__) - - -def __convert__(method_name, name_prefix, parent_names): +def __convert_to_v2__(method_name, name_prefix, parent_names): if name_prefix is not None: wrapper = wrap_name_default(name_prefix=name_prefix) else: wrapper = None - class __Impl__(Layer): + class V2LayerImpl(Layer): def __init__(self, name=None, **kwargs): parent_layers = dict() other_kwargs = dict() @@ -75,7 +81,7 @@ def __init__(self, name=None, **kwargs): if key not in parent_names: other_kwargs[key] = kwargs[key] - super(__Impl__, self).__init__(name, parent_layers) + super(V2LayerImpl, self).__init__(name, parent_layers) self.__other_kwargs__ = other_kwargs if wrapper is not None: @@ -89,24 +95,38 @@ def to_proto_impl(self, **kwargs): args[each] = self.__other_kwargs__[each] return getattr(conf_helps, method_name)(name=self.name, **args) - return __Impl__ + return V2LayerImpl -data_layer = __convert__('data_layer', None, []) -fc_layer = __convert__('fc_layer', name_prefix='fc', parent_names=['input']) -classification_cost = __convert__( +data = __convert_to_v2__('data_layer', None, []) +fc = __convert_to_v2__('fc_layer', name_prefix='fc', parent_names=['input']) +max_id = __convert_to_v2__( + 'maxid_layer', name_prefix='maxid_layer', parent_names=['input']) +classification_cost = __convert_to_v2__( 'classification_cost', name_prefix='classification_cost', parent_names=['input', 'label']) +cross_entropy_cost = __convert_to_v2__( + 'cross_entropy', + name_prefix='cross_entropy', + parent_names=['input', 'label']) -__all__ = ['data_layer', 'fc_layer', 'classification_cost', 'parse_network'] +__all__ = [ + 'parse_network', 'data', 'fc', 'max_id', 'classification_cost', + 'cross_entropy_cost' +] if __name__ == '__main__': - data = data_layer(name='pixel', size=784) - hidden = fc_layer(input=data, size=100, act=conf_helps.SigmoidActivation()) - predict = fc_layer( - input=[hidden, data], size=10, act=conf_helps.SoftmaxActivation()) - cost = classification_cost( - input=predict, label=data_layer( - name='label', size=10)) - print parse_network(cost) + pixel = data(name='pixel', size=784) + label = data(name='label', size=10) + hidden = fc(input=pixel, size=100, act=conf_helps.SigmoidActivation()) + inference = fc(input=hidden, size=10, act=conf_helps.SoftmaxActivation()) + maxid = max_id(input=inference) + cost1 = classification_cost(input=inference, label=label) + cost2 = cross_entropy_cost(input=inference, label=label) + + print parse_network(cost1) + print parse_network(cost2) + print parse_network(cost1, cost2) + print parse_network(cost2) + print parse_network(inference, maxid) From e0c3a6d602549633fd4ec732b88ca8e6ef2e7d27 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 14 Feb 2017 16:26:56 +0800 Subject: [PATCH 187/370] optimize parameter name --- python/paddle/v2/layer.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 4cdb2a3638a5d1..9c1589f9bfd554 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -35,26 +35,26 @@ def __real_func__(): class Layer(object): - def __init__(self, name, parent_layer): - assert isinstance(parent_layer, dict) + def __init__(self, name, parent_layers): + assert isinstance(parent_layers, dict) assert isinstance(name, basestring) self.name = name - self.__parent_layer__ = parent_layer + self.__parent_layers__ = parent_layers def to_proto(self, context): """ function to set proto attribute """ kwargs = dict() - for param_name in self.__parent_layer__: - if not isinstance(self.__parent_layer__[param_name], + for layer_name in self.__parent_layers__: + if not isinstance(self.__parent_layers__[layer_name], collections.Sequence): - param_value = self.__parent_layer__[param_name].to_proto( + v1_layer = self.__parent_layers__[layer_name].to_proto( context=context) else: - param_value = map(lambda x: x.to_proto(context=context), - self.__parent_layer__[param_name]) - kwargs[param_name] = param_value + v1_layer = map(lambda x: x.to_proto(context=context), + self.__parent_layers__[layer_name]) + kwargs[layer_name] = v1_layer if self.name not in context: context[self.name] = self.to_proto_impl(**kwargs) From 844d062007cb9f35a82006ecc748614a97182cc4 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 15 Feb 2017 15:19:07 +0800 Subject: [PATCH 188/370] Remove NAG optimizer --- demo/mnist/api_train_v2.py | 27 +++----------- python/paddle/v2/trainer.py | 74 ++----------------------------------- 2 files changed, 10 insertions(+), 91 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index ab1581325aa95d..d0ccc2c5aa8cf0 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -1,6 +1,6 @@ from paddle.trainer_config_helpers import * from paddle.trainer.PyDataProvider2 import dense_vector, integer_value -import paddle.v2 as paddle_v2 +import paddle.v2 as paddle import numpy import mnist_util @@ -24,7 +24,7 @@ def network_config(): def event_handler(event): - if isinstance(event, paddle_v2.trainer.CompleteTrainOneBatch): + if isinstance(event, paddle.trainer.CompleteTrainOneBatch): print "Pass %d, Batch %d, Cost %f" % (event.pass_id, event.batch_id, event.cost) else: @@ -32,31 +32,16 @@ def event_handler(event): def main(): - paddle_v2.init(use_gpu=False, trainer_count=1) + paddle.init(use_gpu=False, trainer_count=1) model_config = parse_network_config(network_config) - pool = paddle_v2.parameters.create(model_config) + pool = paddle.parameters.create(model_config) for param_name in pool.get_names(): array = pool.get_parameter(param_name) array[:] = numpy.random.uniform(low=-1.0, high=1.0, size=array.shape) - def nag(v, g, vel_t_1): - """ - NAG Optimizer. A optimizer which Paddle CPP is not implemented. - https://arxiv.org/pdf/1212.0901v2.pdf eq.6 eq.7 - :param v: parameter value - :param g: parameter gradient - :param vel_t_1: t-1 velocity - :return: - """ - mu = 0.09 - e = 0.00001 + adam_optimizer = paddle.optimizer.Adam(learning_rate=1e-3) - vel_t = mu * vel_t_1 - e * g - - v[:] = v + (mu**2) * vel_t - (1 + mu) * e * g - vel_t_1[:] = vel_t - - trainer = paddle_v2.trainer.SGDTrainer(update_equation=nag) + trainer = paddle.trainer.SGDTrainer(update_equation=adam_optimizer) trainer.train(train_data_reader=train_reader, topology=model_config, diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 9620e754208100..41dfb522dba617 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -2,7 +2,7 @@ from paddle.proto.ModelConfig_pb2 import ModelConfig from paddle.proto.ParameterConfig_pb2 import ParameterConfig from . import parameters as v2_parameters -import numpy +from . import optimizer as v2_optimizer import py_paddle.swig_paddle as api from py_paddle import DataProviderConverter @@ -93,72 +93,6 @@ def __init__(self, gradient_machine): self.arrays = dict() -class CustomizeUpdateEquation(object): - def __init__(self, callback): - self.__callback__ = callback - if self.__callback__.func_code.co_argcount < 2: - raise ValueError( - "The update equation at least should contain 2 arguments, " - "first is value, second is gradient") - - self.local_params_count = self.__callback__.func_code.co_argcount - 2 - self.local_params = dict() - - def enable_types(self): - return [api.PARAMETER_VALUE, api.PARAMETER_GRADIENT] - - def init(self, gradient_machine): - assert isinstance(gradient_machine, api.GradientMachine) - for param in gradient_machine.getParameters(): - conf = param.getConfig().toProto() - shape = map(int, conf.dims) - self.local_params[conf.name] = [] - for _ in xrange(self.local_params_count): - self.local_params[conf.name].append( - numpy.zeros( - shape=shape, dtype='float32')) - - def create_local_updater(self): - return self - - def startPass(self): - pass - - def finishPass(self): - pass - - def startBatch(self, batch_size): - return api.PASS_TRAIN - - def finishBatch(self, cost): - pass - - def update(self, param): - conf = param.getConfig().toProto() - shape = map(int, conf.dims) - if not api.isUsingGpu(): - v = param.getBuf(api.PARAMETER_VALUE).toNumpyArrayInplace().reshape( - shape) - g = param.getBuf(api.PARAMETER_GRADIENT).toNumpyArrayInplace( - ).reshape(shape) - - else: - v = param.getBuf(api.PARAMETER_VALUE).copyToNumpyArray().reshape( - shape) - g = param.getBuf(api.PARAMETER_GRADIENT).copyToNumpyArray().reshape( - shape) - - args = [v, g] - for arg in self.local_params[conf.name]: - args.append(arg) - self.__callback__(*args) - - if api.isUsingGpu(): - param.getBuf(api.PARAMETER_VALUE).copyFromNumpyArray(v.flatten( - ).astype('float32')) - # discard gradient changed. - - class SGDTrainer(ITrainer): def __init__(self, update_equation): """ @@ -166,9 +100,9 @@ def __init__(self, update_equation): :param update_equation: Maybe we should give a DSL for update equation? """ - if callable(update_equation): - update_equation = CustomizeUpdateEquation(update_equation) - + if not isinstance(update_equation, v2_optimizer.Optimizer): + raise ValueError("update equation parameter must be " + "paddle.v2.optimizer.Optimizer") self.__optimizer__ = update_equation def train(self, From 094d29aaadbdf17ede7d7950676ee0e91ff3b865 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 15 Feb 2017 15:57:02 +0800 Subject: [PATCH 189/370] Draft for parameters --- demo/mnist/api_train_v2.py | 29 +++-- python/paddle/v2/parameters.py | 212 +++++++++++++++++++-------------- python/paddle/v2/trainer.py | 104 ++-------------- 3 files changed, 148 insertions(+), 197 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index d0ccc2c5aa8cf0..8618a8f21115a0 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -23,29 +23,32 @@ def network_config(): outputs(cost) -def event_handler(event): - if isinstance(event, paddle.trainer.CompleteTrainOneBatch): - print "Pass %d, Batch %d, Cost %f" % (event.pass_id, event.batch_id, - event.cost) - else: - pass - - def main(): paddle.init(use_gpu=False, trainer_count=1) model_config = parse_network_config(network_config) - pool = paddle.parameters.create(model_config) - for param_name in pool.get_names(): - array = pool.get_parameter(param_name) + parameters = paddle.parameters.create(model_config) + for param_name in parameters.keys(): + array = parameters[param_name] array[:] = numpy.random.uniform(low=-1.0, high=1.0, size=array.shape) + parameters[param_name] = array + + adam_optimizer = paddle.optimizer.Optimizer( + learning_rate=0.01, learning_method=AdamOptimizer()) + + def event_handler(event): + if isinstance(event, paddle.trainer.CompleteTrainOneBatch): + para = parameters['___fc_layer_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()) - adam_optimizer = paddle.optimizer.Adam(learning_rate=1e-3) + else: + pass trainer = paddle.trainer.SGDTrainer(update_equation=adam_optimizer) trainer.train(train_data_reader=train_reader, topology=model_config, - parameters=pool, + 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 diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index 892c68a38bd706..a30bf5d3631f5a 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -2,110 +2,144 @@ from paddle.proto.ModelConfig_pb2 import ModelConfig from paddle.proto.ParameterConfig_pb2 import ParameterConfig +import py_paddle.swig_paddle as api -__all__ = ['IParameterPool', 'create', 'ParameterFlag'] +__all__ = ['Parameters', 'create'] -class ParameterFlag(object): - """ - The flag for IParameterPool.get_parameter. If writeable, operation on return - numpy array will also apply to Paddle parameter. But it will be slower in - GPU mode. +def create(*topologies): """ - READ_ONLY = 0x01 - WRITE_ONLY = 0x02 - READ_WRITE = READ_ONLY | WRITE_ONLY - + Create parameter pool by topologies. -class IParameterPool(object): + :param topologies: + :return: """ - Interface of Parameter Pool. The parameter pool is a dictionary of - parameters. User can modify parameter or customize parameter value - by `get_parameter`. - - .. code-block:: python + pool = Parameters() + for topo in topologies: + if not isinstance(topo, ModelConfig): + raise ValueError( + 'create must pass a topologies which type is ModelConfig') - pool = paddle.parameters.create(topo1, topo2) + for param in topo.parameters: + pool.append_config(param) + return pool - embedding = pool.get_parameter("embedding") - assert isinstance(embedding, numpy.ndarray) - print embedding[1:] - """ - def get_parameter(self, name, flag=ParameterFlag.READ_WRITE): - """ - Get a parameter by name. - - :param name: parameter name. - :type name: basestring - :param flag: the flag for return value. readable or writable. - :type flag: int - :return: The parameter value - :rtype: np.ndarray - """ - raise NotImplementedError() - - def get_names(self): - """ - Get all parameter names - :return: all parameter names - :rtype: list - """ - raise NotImplementedError() - - -class NumpyParameterPool(IParameterPool): +class Parameters(object): def __init__(self): - self.__param_configs__ = dict() - self.__params__ = dict() - - def append(self, conf): - if not isinstance(conf, ParameterConfig): - raise ValueError("conf must be ParameterConfig") - - if not conf.IsInitialized(): - raise ValueError("conf is not initialized") - - self.__param_configs__[conf.name] = conf - self.__params__[conf.name] = None - - def get_config(self, name): - if name not in self.__param_configs__: - raise ValueError("parameter %s is not appended" % name) - - return self.__param_configs__[name] - - def get_parameter(self, name, *args, **kwargs): - if name not in self.__params__: - raise ValueError("parameter %s is not appended" % name) + self.__param_conf__ = dict() + self.__gradient_machines__ = [] + self.__tmp_params__ = [] + + def append_config(self, param_conf): + if not isinstance(param_conf, ParameterConfig): + raise ValueError("param_conf must be paddle.proto.ParameterConfig") + + if param_conf.name in self.__param_conf__: + raise ValueError("duplicated parameter %s" % param_conf.name) + + self.__param_conf__[param_conf.name] = param_conf + + def keys(self): + return self.__param_conf__.keys() + + def names(self): + return self.keys() + + def has_key(self, key): + return key in self.__param_conf__.keys() + + def __getitem__(self, key): + shape = self.get_shape(key) + + if len(self.__gradient_machines__) == 0: + # create new parameter in python numpy. + return np.ndarray(shape=shape, dtype=np.float32) + else: + for each_gradient_machine in self.__gradient_machines__: + param = __get_parameter_in_gradient_machine__( + each_gradient_machine, key) + # for simplify implementation now, we always copy from C++ + assert isinstance(param, api.Parameter) + val = param.getBuf(api.PARAMETER_VALUE) + assert isinstance(val, api.Vector) + return val.copyToNumpyArray().reshape(shape=shape) + # else continue + + raise RuntimeError("Unexpected branch") + + def get_shape(self, key): + if not isinstance(key, basestring): + raise ValueError("parameter name should be string") + if not self.has_key(key): + raise ValueError("No such parameter %s" % key) + conf = self.__param_conf__[key] + return map(int, conf.dims) + + def __setitem__(self, key, value): + if not isinstance(value, np.ndarray): + raise ValueError("Must return ndarray") + value = value.astype(dtype=np.float32) + shape = self.get_shape(key) + if not reduce(lambda a, b: a and b, + map(lambda x: x[0] == x[1], zip(value.shape, shape))): + raise ValueError("Value shape mismatch, expect %s, should %s" % + (shape, value.shape)) + + if len(self.__gradient_machines__) == 0: + self.__tmp_params__.append((key, value)) + else: + for each_gradient_machine in self.__gradient_machines__: + __copy_parameter_to_gradient_machine__(each_gradient_machine, + key, value) + + def append_gradient_machine(self, gradient_machine): + if not isinstance(gradient_machine, api.GradientMachine): + raise ValueError("gradient_machine should be api.GradientMachine") + + if len(self.__tmp_params__) != 0: + for name, val in self.__tmp_params__: + try: + __copy_parameter_to_gradient_machine__(gradient_machine, + name, val) + except ValueError: + # If no such parameter in gradient machine, then don't copy + pass + + +def __get_parameter_in_gradient_machine__(gradient_machine, name): + """ - param = self.__params__[name] - if param is None: - shape = self.__param_configs__[name].dims - if len(shape) == 0: - raise ValueError("parameter %s is no shape" % name) - param = np.ndarray( - shape=[int(item) for item in shape], dtype='float32') - self.__params__[name] = param - return param + :param gradient_machine: + :type gradient_machine: api.GradientMachine + :param name: + :return: + :rtype: api.Parameter + """ + params = filter(lambda p: p.getName() == name, + gradient_machine.getParameters()) - def get_names(self): - return self.__param_configs__.keys() + if len(params) == 0: + raise ValueError("No such parameter") + elif len(params) > 1: + raise ValueError("Unexpected branch") + else: + return params[0] -def create(*topologies): +def __copy_parameter_to_gradient_machine__(gradient_machine, name, arr): """ - Create parameter pool by topologies. + Copy a python ndarray into the gradient machine. - :param topologies: + :param gradient_machine: + :type gradient_machine: api.GradientMachine + :param name: + :param arr: + :type arr: np.ndarray :return: + :rtype: api.Parameter """ - pool = NumpyParameterPool() - for topo in topologies: - if not isinstance(topo, ModelConfig): - raise ValueError( - 'create must pass a topologies which type is ModelConfig') - - for param in topo.parameters: - pool.append(param) - return pool + param = __get_parameter_in_gradient_machine__(gradient_machine, name) + vec = param.getBuf(api.PARAMETER_VALUE) + assert isinstance(vec, api.Vector) + vec.copyFromNumpyArray(arr.flatten()) diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 41dfb522dba617..baed7d0025b1d0 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -1,11 +1,12 @@ import collections -from paddle.proto.ModelConfig_pb2 import ModelConfig -from paddle.proto.ParameterConfig_pb2 import ParameterConfig -from . import parameters as v2_parameters -from . import optimizer as v2_optimizer + import py_paddle.swig_paddle as api from py_paddle import DataProviderConverter +from paddle.proto.ModelConfig_pb2 import ModelConfig +from . import optimizer as v2_optimizer +from . import parameters as v2_parameters + __all__ = ['ITrainer', 'SGDTrainer', 'CompleteTrainOneBatch', 'BaseEvent'] @@ -21,11 +22,10 @@ class CompleteTrainOneBatch(BaseEvent): Event On One Batch Training Complete. """ - def __init__(self, pass_id, batch_id, cost, parameters): + def __init__(self, pass_id, batch_id, cost): self.pass_id = pass_id self.batch_id = batch_id self.cost = cost - self.parameters = parameters def default_event_handler(event): @@ -42,57 +42,6 @@ def train(self, raise NotImplementedError() -class LazyParameterPool(v2_parameters.IParameterPool): - """ - Lazy Parameter Pool stores a reference to GradientMachine. User could invoke - `get_parameter` if needed, but the operation is lazy. It means the parameter - will only fetched from GPU or Parameter Server if `get_parameter` is - invoked. Also, set flag = writable will make a extra host2device copy after - reading/modifying parameter. - - This class is not exposed to User. User should treat this class as a normal - IParameterPool. - - See IParameterPool for usage documentation. - - :type __gradient_machine__: api.GradientMachine - """ - - def get_parameter(self, name, flag=v2_parameters.ParameterFlag.READ_WRITE): - param = filter(lambda x: x.getName() == name, - self.__gradient_machine__.getParameters()) - if len(param) == 0: - raise ValueError("Cannot found parameter with name %s" % name) - elif len(param) > 1: - raise RuntimeError("Unexpected branch") - else: - conf = param[0].getConfig().toProto() - param = param[0].getBuf(api.PARAMETER_VALUE) - assert isinstance(param, api.Vector) - assert isinstance(conf, ParameterConfig) - - shape = map(int, conf.dims) - if api.isUsingGpu(): - arr = param.copyToNumpyArray().reshape(shape) - if flag & v2_parameters.ParameterFlag.WRITE_ONLY: - self.need_copy = True - self.arrays[name] = arr - else: - arr = param.toNumpyArrayInplace().reshape(shape) - return arr - - def get_names(self): - return [ - param.getName() - for param in self.__gradient_machine__.getParameters() - ] - - def __init__(self, gradient_machine): - self.__gradient_machine__ = gradient_machine - self.need_copy = False - self.arrays = dict() - - class SGDTrainer(ITrainer): def __init__(self, update_equation): """ @@ -137,7 +86,7 @@ def train(self, gm = api.GradientMachine.createFromConfigProto( topology, api.CREATE_MODE_NORMAL, self.__optimizer__.enable_types()) assert isinstance(gm, api.GradientMachine) - __copy_parameter_from_pool__(gm, parameters) + parameters.append_gradient_machine(gm) updater = self.__optimizer__.create_local_updater() updater.init(gm) @@ -167,16 +116,9 @@ def train(self, cost_vec = cost_vec.copyToNumpyMat() cost = cost_vec.sum() / len(data_batch) updater.finishBatch(cost) - pool = LazyParameterPool(gradient_machine=gm) event_handler( CompleteTrainOneBatch( - pass_id=pass_id, - batch_id=batch_id, - cost=cost, - parameters=pool)) - - if pool.need_copy: - __copy_parameter_from_lazy_pool__(gm, pool) + pass_id=pass_id, batch_id=batch_id, cost=cost)) updater.finishPass() gm.finish() @@ -211,34 +153,6 @@ def __generator_to_batch__(generator, batch_size): yield ret_val -def __copy_parameter_from_lazy_pool__(gm, pool): - assert isinstance(pool, LazyParameterPool) - for each_param_name in pool.arrays.keys(): - param = filter(lambda x: x.getName() == each_param_name, - gm.getParameters()) - assert len(param) == 1 - param = param[0] - param.getBuf(api.PARAMETER_VALUE).copyFromNumpyArray(pool.arrays[ - each_param_name].flatten().astype('float32')) - - -def __copy_parameter_from_pool__(gm, pool): - """ - - :param gm: - :type gm: api.GradientMachine - :param pool: - :type pool: v2_parameters.IParameterPool - :return: - """ - assert isinstance(pool, v2_parameters.IParameterPool) - for each_param in gm.getParameters(): - name = each_param.getName() - param = pool.get_parameter(name, v2_parameters.ParameterFlag.READ_ONLY) - each_param.getBuf(api.PARAMETER_VALUE).copyFromNumpyArray(param.flatten( - ).astype('float32')) - - def __check_train_args__(train_data_reader, topology, parameters, test_data_reader, event_handler, **kwargs): """ @@ -258,7 +172,7 @@ def __check_train_args__(train_data_reader, topology, parameters, if not isinstance(topology, ModelConfig): raise ValueError('topology should be a model config') - if not isinstance(parameters, v2_parameters.IParameterPool): + if not isinstance(parameters, v2_parameters.Parameters): raise ValueError('parameters should be a parameter pool') if not callable(event_handler): From 62f51fce00cab139c50480a96ced51500e97243f Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Wed, 15 Feb 2017 17:38:37 -0800 Subject: [PATCH 190/370] add data provider design doc proposal --- doc/design/reader/README.md | 79 +++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 doc/design/reader/README.md diff --git a/doc/design/reader/README.md b/doc/design/reader/README.md new file mode 100644 index 00000000000000..fa37ad7b292003 --- /dev/null +++ b/doc/design/reader/README.md @@ -0,0 +1,79 @@ +# Python Data Provider Design Doc + +Data provider provides data for training. It will be passed into `paddle.train` as a parameter. + +## Data Provider Interface + +Data provider is a function with no parameter that creates a iterable (anything can be used in `for x in iterable`): + +``` +iterable = data_provider() +``` + +Element produced for the iterable should be a **single** entry of data, in format `[column_0_item, column_1_item, ...]`. Each element of the list needs to be supported data type (e.g., numpy 1d array of float32, list of int). + +For example, `column_0_item` could be image pixels of format numpy 1d array of float32, and `column_1_item` could be image label of format single int value: + +``` +for single_entry in iterable: + pixel = entry[0] + label = entry[1] +``` + +## Usage + +data provider, mapping from data provider column 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.data.mnist, ["image", "label"], 128, 10, ...) +``` +## Q & A + +### Why return only a single entry, but not a mini batch? + +If return a mini batch, data provider 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`. + +Concretely, always return a single entry make reusing existing data providers much easier (e.g., if existing data provider return not a single entry but 3 entries, training code will be more complex because it need to handle cases like batch size 2). + +### How to create custom data provider + +```python +def image_provider(path): + f = open(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() + +# use python lambda to change image_provier into a function with no parameters. +provider = lambda : image_provier("/path/to/data/") +paddle.train(provider, ["image", "label"], ...) +``` + +### How is `paddle.train` implemented + +An example implementation of paddle.train could be: + +```python +def make_minibatch_generator(reader, minibatch_size): + buf = [reader.next() for x in xrange(minibatch_size)] + while len(buf) > 0: + yield buf + buf = [reader.next() for x in xrange(minibatch_size)] + +def train(provider, mapping, batch_size, total_pass): + for pass_idx in range(total_pass): + for mini_batch in make_minibatch_generator(provider(pass_idx)): # this loop will never end in online learning. + do_forward_backward(mini_batch, mapping) +``` + +This is just an example implementation, more complicated logic like data prefetch could be implemented. From 059a162be5a3b7a6cb80f41e1dd73ccc39df0181 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 16 Feb 2017 11:27:25 +0800 Subject: [PATCH 191/370] Follow comments --- demo/mnist/api_train_v2.py | 2 +- python/paddle/v2/parameters.py | 3 +++ python/paddle/v2/trainer.py | 13 +++---------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 8618a8f21115a0..31c3e9932b68d4 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -36,7 +36,7 @@ def main(): learning_rate=0.01, learning_method=AdamOptimizer()) def event_handler(event): - if isinstance(event, paddle.trainer.CompleteTrainOneBatch): + if isinstance(event, paddle.trainer.EndIteration): para = parameters['___fc_layer_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()) diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index a30bf5d3631f5a..c2e74b8fb12069 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -49,6 +49,9 @@ def names(self): def has_key(self, key): return key in self.__param_conf__.keys() + def __iter__(self): + return iter(self.__param_conf__) + def __getitem__(self, key): shape = self.get_shape(key) diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index baed7d0025b1d0..63695be1566094 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -7,17 +7,10 @@ from . import optimizer as v2_optimizer from . import parameters as v2_parameters -__all__ = ['ITrainer', 'SGDTrainer', 'CompleteTrainOneBatch', 'BaseEvent'] +__all__ = ['ITrainer', 'SGDTrainer', 'EndIteration'] -class BaseEvent(object): - """ - Just a marker class - """ - pass - - -class CompleteTrainOneBatch(BaseEvent): +class EndIteration(object): """ Event On One Batch Training Complete. """ @@ -117,7 +110,7 @@ def train(self, cost = cost_vec.sum() / len(data_batch) updater.finishBatch(cost) event_handler( - CompleteTrainOneBatch( + EndIteration( pass_id=pass_id, batch_id=batch_id, cost=cost)) updater.finishPass() From c8067ed586d47c30e22df37026ff87410f694258 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 16 Feb 2017 11:36:23 +0800 Subject: [PATCH 192/370] Rearrange event. --- demo/mnist/api_train_v2.py | 4 ++-- python/paddle/v2/__init__.py | 3 ++- python/paddle/v2/event.py | 12 ++++++++++++ python/paddle/v2/trainer.py | 18 ++++-------------- 4 files changed, 20 insertions(+), 17 deletions(-) create mode 100644 python/paddle/v2/event.py diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 31c3e9932b68d4..f925d70765e1c6 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -36,7 +36,7 @@ def main(): learning_rate=0.01, learning_method=AdamOptimizer()) def event_handler(event): - if isinstance(event, paddle.trainer.EndIteration): + if isinstance(event, paddle.event.EndIteration): para = parameters['___fc_layer_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()) @@ -44,7 +44,7 @@ def event_handler(event): else: pass - trainer = paddle.trainer.SGDTrainer(update_equation=adam_optimizer) + trainer = paddle.trainer.SGD(update_equation=adam_optimizer) trainer.train(train_data_reader=train_reader, topology=model_config, diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index f50c36ce64995b..72f1168e94f2a7 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -15,8 +15,9 @@ import parameters import py_paddle.swig_paddle as api import trainer +import event -__all__ = ['optimizer', 'parameters', 'init', 'trainer'] +__all__ = ['optimizer', 'parameters', 'init', 'trainer', 'event'] def init(**kwargs): diff --git a/python/paddle/v2/event.py b/python/paddle/v2/event.py new file mode 100644 index 00000000000000..04158f4765299d --- /dev/null +++ b/python/paddle/v2/event.py @@ -0,0 +1,12 @@ +__all__ = ['EndIteration'] + + +class EndIteration(object): + """ + Event On One Batch Training Complete. + """ + + def __init__(self, pass_id, batch_id, cost): + self.pass_id = pass_id + self.batch_id = batch_id + self.cost = cost diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 63695be1566094..a29c3a05f85395 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -6,19 +6,9 @@ from paddle.proto.ModelConfig_pb2 import ModelConfig from . import optimizer as v2_optimizer from . import parameters as v2_parameters +from . import event as v2_event -__all__ = ['ITrainer', 'SGDTrainer', 'EndIteration'] - - -class EndIteration(object): - """ - Event On One Batch Training Complete. - """ - - def __init__(self, pass_id, batch_id, cost): - self.pass_id = pass_id - self.batch_id = batch_id - self.cost = cost +__all__ = ['ITrainer', 'SGD'] def default_event_handler(event): @@ -35,7 +25,7 @@ def train(self, raise NotImplementedError() -class SGDTrainer(ITrainer): +class SGD(ITrainer): def __init__(self, update_equation): """ Simple SGD Trainer. @@ -110,7 +100,7 @@ def train(self, cost = cost_vec.sum() / len(data_batch) updater.finishBatch(cost) event_handler( - EndIteration( + v2_event.EndIteration( pass_id=pass_id, batch_id=batch_id, cost=cost)) updater.finishPass() From 9646f2d3af637a96478788cd9d2592af4fdbc715 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 16 Feb 2017 12:24:04 +0800 Subject: [PATCH 193/370] Rename model_config => topology --- demo/mnist/api_train_v2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index f925d70765e1c6..2c0394aa0b1897 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -25,8 +25,8 @@ def network_config(): def main(): paddle.init(use_gpu=False, trainer_count=1) - model_config = parse_network_config(network_config) - parameters = paddle.parameters.create(model_config) + topology = parse_network_config(network_config) + parameters = paddle.parameters.create(topology) for param_name in parameters.keys(): array = parameters[param_name] array[:] = numpy.random.uniform(low=-1.0, high=1.0, size=array.shape) @@ -47,7 +47,7 @@ def event_handler(event): trainer = paddle.trainer.SGD(update_equation=adam_optimizer) trainer.train(train_data_reader=train_reader, - topology=model_config, + topology=topology, parameters=parameters, event_handler=event_handler, batch_size=32, # batch size should be refactor in Data reader From f9ea586431fe1c1851d3a59790c9e6197f69b60a Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 16 Feb 2017 15:19:29 +0800 Subject: [PATCH 194/370] Add get/set method --- demo/mnist/api_train_v2.py | 6 +++--- python/paddle/v2/parameters.py | 14 +++++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 2c0394aa0b1897..5e46d510ad35bb 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -28,16 +28,16 @@ def main(): topology = parse_network_config(network_config) parameters = paddle.parameters.create(topology) for param_name in parameters.keys(): - array = parameters[param_name] + array = parameters.get(param_name) array[:] = numpy.random.uniform(low=-1.0, high=1.0, size=array.shape) - parameters[param_name] = array + parameters.set(parameter_name=param_name, value=array) adam_optimizer = paddle.optimizer.Optimizer( learning_rate=0.01, learning_method=AdamOptimizer()) def event_handler(event): if isinstance(event, paddle.event.EndIteration): - para = parameters['___fc_layer_2__.w0'] + para = parameters.get('___fc_layer_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()) diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index c2e74b8fb12069..55e732a320b6e5 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -26,6 +26,10 @@ def create(*topologies): class Parameters(object): + """ + The parameters + """ + def __init__(self): self.__param_conf__ = dict() self.__gradient_machines__ = [] @@ -66,7 +70,8 @@ def __getitem__(self, key): assert isinstance(param, api.Parameter) val = param.getBuf(api.PARAMETER_VALUE) assert isinstance(val, api.Vector) - return val.copyToNumpyArray().reshape(shape=shape) + val = val.copyToNumpyArray() + return val # else continue raise RuntimeError("Unexpected branch") @@ -96,6 +101,12 @@ def __setitem__(self, key, value): __copy_parameter_to_gradient_machine__(each_gradient_machine, key, value) + def get(self, parameter_name): + return self.__getitem__(key=parameter_name) + + def set(self, parameter_name, value): + self.__setitem__(key=parameter_name, value=value) + def append_gradient_machine(self, gradient_machine): if not isinstance(gradient_machine, api.GradientMachine): raise ValueError("gradient_machine should be api.GradientMachine") @@ -108,6 +119,7 @@ def append_gradient_machine(self, gradient_machine): except ValueError: # If no such parameter in gradient machine, then don't copy pass + self.__gradient_machines__.append(gradient_machine) def __get_parameter_in_gradient_machine__(gradient_machine, name): From 8dc4c0538efa126e771ed807a62be50dc123d7a2 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 16 Feb 2017 16:37:16 +0800 Subject: [PATCH 195/370] Add comments --- python/paddle/v2/event.py | 3 + python/paddle/v2/parameters.py | 117 +++++++++++++++++++++++++++++++-- python/paddle/v2/trainer.py | 25 ++++++- 3 files changed, 138 insertions(+), 7 deletions(-) diff --git a/python/paddle/v2/event.py b/python/paddle/v2/event.py index 04158f4765299d..f6c6957438653d 100644 --- a/python/paddle/v2/event.py +++ b/python/paddle/v2/event.py @@ -1,3 +1,6 @@ +""" +All training events. +""" __all__ = ['EndIteration'] diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index 55e732a320b6e5..e5b7dabcb8eb3a 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -21,13 +21,29 @@ def create(*topologies): 'create must pass a topologies which type is ModelConfig') for param in topo.parameters: - pool.append_config(param) + pool.__append_config__(param) return pool class Parameters(object): """ - The parameters + Parameters is a dictionary contains Paddle's parameter. The key of + Parameters is the name of parameter. The value of Parameters is a plain + :code:`numpy.ndarry` . + + Basically usage is + + .. code-block:: python + + data = paddle.layers.data(...) + ... + out = paddle.layers.fc(...) + + parameters = paddle.parameters.create(out) + + parameter_names = parameters.names() + fc_mat = parameters.get('fc') + print fc_mat """ def __init__(self): @@ -35,7 +51,16 @@ def __init__(self): self.__gradient_machines__ = [] self.__tmp_params__ = [] - def append_config(self, param_conf): + def __append_config__(self, param_conf): + """ + Append a parameter configuration. It used to initialize Parameters and + should be invoked only in paddle.parameters.create + + :param param_conf: The parameter configuration in protobuf + :type param_conf: ParameterConfig + :return: Nothing + """ + if not isinstance(param_conf, ParameterConfig): raise ValueError("param_conf must be paddle.proto.ParameterConfig") @@ -45,18 +70,55 @@ def append_config(self, param_conf): self.__param_conf__[param_conf.name] = param_conf def keys(self): + """ + keys are the names of each parameter. + :return: list of parameter name + :rtype: list + """ return self.__param_conf__.keys() def names(self): + """ + names of each parameter. + :return: list of parameter name + :rtype: list + """ return self.keys() def has_key(self, key): + """ + has_key return true if there are such parameter name == key + :param key: Parameter name + :type key: basestring + :return: True if contains such key + """ return key in self.__param_conf__.keys() def __iter__(self): + """ + Return an iterator of parameter name. It is used by `for loop` + or `in` operator. + + .. code-block:: python + + parameters = paddle.parameters.create(...) + if "fc_param" in parameters: + print 'OK' + :return: an iterator of parameter name + :rtype: iterator + """ return iter(self.__param_conf__) def __getitem__(self, key): + """ + Get parameter by parameter name. It uses Python dict syntax. + + :note: It will always copy the parameter from C++ side. + :param key: Parameter name + :type key: basestring + :return: parameter value + :rtype: np.ndarray + """ shape = self.get_shape(key) if len(self.__gradient_machines__) == 0: @@ -77,20 +139,37 @@ def __getitem__(self, key): raise RuntimeError("Unexpected branch") def get_shape(self, key): + """ + get shape of the parameter. + :param key: parameter name + :type key: basestring + :return: parameter's shape + :rtype: tuple + """ if not isinstance(key, basestring): raise ValueError("parameter name should be string") if not self.has_key(key): raise ValueError("No such parameter %s" % key) conf = self.__param_conf__[key] - return map(int, conf.dims) + return tuple(map(int, conf.dims)) def __setitem__(self, key, value): + """ + Set parameter by parameter name & value. It use Python dict syntax. + + :note: It will always copy the parameter to C++ side. + :param key: Parameter name + :type key: basestring + :param value: Parameter matrix. + :type value: np.ndarray + :return: Nothing + """ + if not isinstance(value, np.ndarray): raise ValueError("Must return ndarray") value = value.astype(dtype=np.float32) shape = self.get_shape(key) - if not reduce(lambda a, b: a and b, - map(lambda x: x[0] == x[1], zip(value.shape, shape))): + if value.shape != shape: raise ValueError("Value shape mismatch, expect %s, should %s" % (shape, value.shape)) @@ -102,12 +181,38 @@ def __setitem__(self, key, value): key, value) def get(self, parameter_name): + """ + Get parameter by parameter name. + + :note: It will always copy the parameter from C++ side. + :param parameter_name: parameter name + :type parameter_name: basestring + :return: The parameter matrix. + :rtype: np.ndarray + """ return self.__getitem__(key=parameter_name) def set(self, parameter_name, value): + """ + Set parameter by parameter name & matrix. + :param parameter_name: parameter name + :type parameter_name: basestring + :param value: parameter matrix + :type value: np.ndarray + :return: Nothing. + """ self.__setitem__(key=parameter_name, value=value) def append_gradient_machine(self, gradient_machine): + """ + append gradient machine to parameters. This method is used internally in + Trainer.train. + + :param gradient_machine: Paddle C++ GradientMachine object. + :type gradient_machine: api.GradientMachine + :return: + """ + if not isinstance(gradient_machine, api.GradientMachine): raise ValueError("gradient_machine should be api.GradientMachine") diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index a29c3a05f85395..9ba13dc5c8a81f 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -12,16 +12,38 @@ def default_event_handler(event): + """ + Default event handler. It will print some log and save mode. + + TODO(yuyang18): Complete it! + :param event: + :return: + """ pass class ITrainer(object): + """ + The interface of Trainer. The only exposed method is `train`. + """ + def train(self, train_data_reader, topology, parameters, test_data_reader=None, event_handler=None): + """ + train method. + + :param train_data_reader: + :param topology: + :param parameters: + :param test_data_reader: + :param event_handler: + :return: + """ + raise NotImplementedError() @@ -30,7 +52,8 @@ def __init__(self, update_equation): """ Simple SGD Trainer. - :param update_equation: Maybe we should give a DSL for update equation? + :param update_equation: The optimizer object. + :type update_equation: v2_optimizer.Optimizer """ if not isinstance(update_equation, v2_optimizer.Optimizer): raise ValueError("update equation parameter must be " From 0446b488fd3db0b3e1b3c03a9a653a2843bdefca Mon Sep 17 00:00:00 2001 From: liaogang Date: Thu, 16 Feb 2017 20:46:10 +0800 Subject: [PATCH 196/370] LayerOutput for single machine multiple devices --- .../gradientmachines/GradientMachine.h | 2 + .../gradientmachines/MultiGradientMachine.cpp | 38 +++++++++++++++++++ .../gradientmachines/MultiGradientMachine.h | 2 + .../gradientmachines/NeuralNetwork.cpp | 1 + .../gserver/gradientmachines/NeuralNetwork.h | 3 +- 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/paddle/gserver/gradientmachines/GradientMachine.h b/paddle/gserver/gradientmachines/GradientMachine.h index 0829968d87c5dc..201b65bc45181b 100644 --- a/paddle/gserver/gradientmachines/GradientMachine.h +++ b/paddle/gserver/gradientmachines/GradientMachine.h @@ -134,6 +134,8 @@ class GradientMachine { backward(callback); } + virtual MatrixPtr getLayerOutput(const std::string& layerName) = 0; + // see comment in Layer.h for the function with the same name virtual void resetState() {} diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp index 80f223824d8dcc..a571b3d72f1d52 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp @@ -282,6 +282,44 @@ void MultiGradientMachine::forwardBackward(const std::vector& inArgs, backwardImp(callback); } +MatrixPtr MultiGradientMachine::getLayerOutput(const std::string& layerName) { + // neural networks are same in each trainer thread + // layer output height = height of layer output * thread nums + auto nn = dynamic_cast(threads_[0]->getGradientMachine()); + auto height = nn->getLayerOutput(layerName)->getHeight() * threads_.size(); + auto stream = HPPL_STREAM_DEFAULT; + + auto copyLayerOutput = [height, stream]( + MatrixPtr& dst, MatrixPtr src, int startRow, bool useGpu) { + size_t width = src->getWidth(); + if (!dst) { + dst = src->clone(height, width, useGpu); + } else { + dst->resize(height, width); + } + + MatrixPtr tmpMatrix = dst->subMatrix(startRow, src->getHeight()); + tmpMatrix->copyFrom(*src, stream); + }; + + MatrixPtr mats; + size_t startRow = 0; + + // copy one layer output from one trainer thread at each time + for (auto& thread : threads_) { + auto nn = dynamic_cast(thread->getGradientMachine()); + auto mat = nn->getLayerOutput(layerName); + copyLayerOutput(mats, mat, startRow, useGpu_); + startRow += mat->getHeight(); + } + + if (useGpu_) { + hl_stream_synchronize(HPPL_STREAM_DEFAULT); + } + + return mats; +} + void MultiGradientMachine::backwardImp(const UpdateCallback& callback) { for (size_t i = 0; i < parameters_.size(); i++) { if (!parameters_[i]->useGpu() || parameters_[i]->isStatic()) continue; diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.h b/paddle/gserver/gradientmachines/MultiGradientMachine.h index 9be15ef4bcf34f..988d5098179806 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.h +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.h @@ -189,6 +189,8 @@ class MultiGradientMachine : public GradientMachine { PassType passType, const UpdateCallback& callback); + virtual MatrixPtr getLayerOutput(const std::string& layerName); + virtual void onPassEnd(); virtual void finish(); diff --git a/paddle/gserver/gradientmachines/NeuralNetwork.cpp b/paddle/gserver/gradientmachines/NeuralNetwork.cpp index 22051e07ee0026..1f9ace4f67fdca 100644 --- a/paddle/gserver/gradientmachines/NeuralNetwork.cpp +++ b/paddle/gserver/gradientmachines/NeuralNetwork.cpp @@ -298,6 +298,7 @@ MatrixPtr NeuralNetwork::getLayerOutput(const std::string& layerName) { CHECK(it != layerMap_.end()) << "Cannot find layer: " << layerName; return it->second->getOutputValue(); } + void NeuralNetwork::onPassEnd() { for (auto& layer : layers_) { layer->onPassEnd(); diff --git a/paddle/gserver/gradientmachines/NeuralNetwork.h b/paddle/gserver/gradientmachines/NeuralNetwork.h index 25af4abcf81700..bf9ed09327f2f1 100644 --- a/paddle/gserver/gradientmachines/NeuralNetwork.h +++ b/paddle/gserver/gradientmachines/NeuralNetwork.h @@ -87,7 +87,8 @@ class NeuralNetwork : public GradientMachine { virtual void backward(const UpdateCallback& callback = nullptr); - MatrixPtr getLayerOutput(const std::string& layerName); + virtual MatrixPtr getLayerOutput(const std::string& layerName); + const LayerPtr& getLayer(const std::string& layerName) const { auto it = layerMap_.find(layerName); CHECK(it != layerMap_.end()) << "Unknown layer " << layerName; From fdbc289ac38dd288fdb11f3ae18da94455625772 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Thu, 16 Feb 2017 22:02:35 +0800 Subject: [PATCH 197/370] add v2 activation, add comment for v2 layer --- demo/mnist/api_train.py | 2 +- python/paddle/v2/__init__.py | 3 +- python/paddle/v2/activation.py | 37 +++++++++++++++++++++++ python/paddle/v2/layer.py | 54 ++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 python/paddle/v2/activation.py diff --git a/demo/mnist/api_train.py b/demo/mnist/api_train.py index f0c56b77cf8578..fe39f0bd23f78e 100644 --- a/demo/mnist/api_train.py +++ b/demo/mnist/api_train.py @@ -77,7 +77,7 @@ def main(): hidden2 = paddle_v2.layer.fc(input=hidden1, size=200) inference = paddle_v2.layer.fc(input=hidden2, size=10, - act=SoftmaxActivation()) + act=paddle_v2.activation.Softmax()) cost = paddle_v2.layer.classification_cost(input=inference, label=label) # Create Simple Gradient Machine. diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index 590fb5cd523ce7..ec4cbb484baaa6 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -14,5 +14,6 @@ import optimizer import layer +import activation -__all__ = ['optimizer', 'layer'] +__all__ = ['optimizer', 'layer', 'activation'] diff --git a/python/paddle/v2/activation.py b/python/paddle/v2/activation.py new file mode 100644 index 00000000000000..1f3aab9ef3c5f6 --- /dev/null +++ b/python/paddle/v2/activation.py @@ -0,0 +1,37 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + +from paddle.trainer_config_helpers.activations import * + +__all__ = [ + "Base", "Tanh", "Sigmoid", "Softmax", "Identity", "Linear", + 'SequenceSoftmax', "Exp", "Relu", "BRelu", "SoftRelu", "STanh", "Abs", + "Square", "Log" +] + +Base = BaseActivation +Tanh = TanhActivation +Sigmoid = SigmoidActivation +Softmax = SoftmaxActivation +SequenceSoftmax = SequenceSoftmaxActivation +Identity = IdentityActivation +Linear = Identity +Relu = ReluActivation +BRelu = BReluActivation +SoftRelu = SoftReluActivation +STanh = STanhActivation +Abs = AbsActivation +Square = SquareActivation +Exp = ExpActivation +Log = LogActivation diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 9c1589f9bfd554..4acbd5ef28c314 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -11,6 +11,60 @@ # 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. +""" +Before this new package paddle.v2.layer, users would need to use functions +in paddle.trainer_config_helpers.layers to configure networks. + +The Old Way: +========= +This old way requires that the creation of a network be defined in a Python +function, say network_config, and that this Python function being passed to +paddle.trainer_config_helpers.parse_network_config for the creation of +protobuf message description of this network. + +```python +def network_config(): + img = paddle.trainer_config_helpers.data_layer(name="pixel", size=784) + inference = paddle.trainer_config_helpers.fc_layer( + input=img, + size=10, + act=paddle.trainer_config_helpers.SoftmaxActivation()) + cost = paddle.trainer_config_helpers.classification_cost( + input=inference, + label=paddle.trainer_config_helpers.data_layer(name="label", size=10)) + +proto_desc = parse_network_config(network_config) +``` + +When parse_network_config executes network_config, those layer definition +functions like data_layer and fc_layer would change some Python global variables, +so that after the execution, parse_network_config could collect information from +these global variables and generates the protobuf message. + + + +The New Way: +========= +In this PR, we define a function in paddle.v2.layer which creates a Python +class for each layer creation function in paddle.trainer_config_helpers.layers. +Users can use create a network as follows: + +```python +img = paddle.v2.layer.data(name="pixel", size=784) +inference = paddle.v2.layer.fc(input=img, size=10, act=paddle.v2.layer.Softmax()) +cost = paddle.v2.layer.classification( + input=inference, + label=paddle.v2.layer.data(name="label", size=10)) + +parameters = paddle.v2.parameters.create(cost) +``` + +This new way doesn't require those invocations to layer definition functions +to be in a Python function but could be anywhere. + +Also, the creation of a protobuf message is hidden in the invocation of +paddle.v2.parameters.create, no longer exposed to users. +""" import paddle.trainer_config_helpers as conf_helps from paddle.trainer_config_helpers.config_parser_utils import \ From a9902a300bd35a1a497414ea3475cf79c7058f5c Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Thu, 16 Feb 2017 17:34:10 -0800 Subject: [PATCH 198/370] fix according to discussion --- doc/design/reader/README.md | 114 ++++++++++++++++++++++++++++-------- 1 file changed, 88 insertions(+), 26 deletions(-) diff --git a/doc/design/reader/README.md b/doc/design/reader/README.md index fa37ad7b292003..7fa62350c40d53 100644 --- a/doc/design/reader/README.md +++ b/doc/design/reader/README.md @@ -1,28 +1,86 @@ -# Python Data Provider Design Doc +# Python Data Reader Design Doc -Data provider provides data for training. It will be passed into `paddle.train` as a parameter. +Paddle reads data from data reader during training. It will be passed into `paddle.train` as a parameter. -## Data Provider Interface +## Data Reader Interface -Data provider is a function with no parameter that creates a iterable (anything can be used in `for x in iterable`): +Data reader is a function with no parameter that creates a iterable (anything can be used in `for x in iterable`): ``` -iterable = data_provider() +iterable = data_reader() ``` -Element produced for the iterable should be a **single** entry of data, in format `[column_0_item, column_1_item, ...]`. Each element of the list needs to be supported data type (e.g., numpy 1d array of float32, list of int). +Element produced for 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) -For example, `column_0_item` could be image pixels of format numpy 1d array of float32, and `column_1_item` could be image label of format single int value: +An example implementation for single item data reader: +```python +def data_reader_fake_image(): + while True: + yield numpy.random.uniform(-1, 1, size=20*20) +``` + +An example implementation for multiple item data reader: +```python +def data_reader_fake_image_and_label(): + while True: + yield numpy.random.uniform(-1, 1, size=20*20), False ``` -for single_entry in iterable: - pixel = entry[0] - label = entry[1] + +## Data Reader Decorators + +Data Reader Decorators 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 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 fake images as input for [Generative Adversarial Networks](https://arxiv.org/abs/1406.2661). + +We can do: + +```python +def data_reader_fake_image(): + while True: + yield numpy.random.uniform(-1, 1, size=20*20) + +def data_reader_bool(t): + while True: + yield t + +true_reader = lambda : data_reader_bool(True) +false_reader = lambda : data_reader_bool(False) + +reader = paddle.reader.combine(paddle.dataset.mnist, data_reader_fake_image, true_reader, false_reader) +# skipped 1 because paddle.dataset.mnist produces two items per data entry. +# 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 decorater that buffers `n` data entries and shuffle them before a data entry is read. + +Example: +```python +reader = paddle.reader.shuffle(paddle.dataset.mnist, 512) ``` ## Usage -data provider, mapping from data provider column to data layer, batch size and number of total pass will be passed into `paddle.train`: +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: @@ -31,32 +89,38 @@ label_layer = paddle.layer.data("label", ...) # ... -paddle.train(paddle.data.mnist, ["image", "label"], 128, 10, ...) +paddle.train(paddle.dataset.mnist, {"image":0, "label":1}, 128, 10, ...) ``` + ## Q & A ### Why return only a single entry, but not a mini batch? -If return a mini batch, data provider 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`. +If return a mini batch, 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`. -Concretely, always return a single entry make reusing existing data providers much easier (e.g., if existing data provider return not a single entry but 3 entries, training code will be more complex because it need to handle cases like batch size 2). +Practically, always return a single entry make reusing existing data reader much easier (e.g., if existing data 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). -### How to create custom data provider +### 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 ```python -def image_provider(path): - f = open(path) +def image_reader(image_path, label_path): + 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 + yield images[i, :], labels[i] # a single entry of data is created each time f.close() -# use python lambda to change image_provier into a function with no parameters. -provider = lambda : image_provier("/path/to/data/") -paddle.train(provider, ["image", "label"], ...) +# use python lambda to change image_reader into a function with no parameters. +reader = lambda : image_reader("/path/to/image_file", "/path/to/label_file") +paddle.train(reader, {"image":0, "label":1}, ...) ``` ### How is `paddle.train` implemented @@ -64,16 +128,14 @@ paddle.train(provider, ["image", "label"], ...) An example implementation of paddle.train could be: ```python -def make_minibatch_generator(reader, minibatch_size): +def minibatch_decorater(reader, minibatch_size): buf = [reader.next() for x in xrange(minibatch_size)] while len(buf) > 0: yield buf buf = [reader.next() for x in xrange(minibatch_size)] -def train(provider, mapping, batch_size, total_pass): +def train(reader, mapping, batch_size, total_pass): for pass_idx in range(total_pass): - for mini_batch in make_minibatch_generator(provider(pass_idx)): # this loop will never end in online learning. + for mini_batch in minibatch_decorater(reader()): # this loop will never end in online learning. do_forward_backward(mini_batch, mapping) ``` - -This is just an example implementation, more complicated logic like data prefetch could be implemented. From 9048311c4afc50ee8277a3f897648eab2bb7db0e Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Thu, 16 Feb 2017 17:45:48 -0800 Subject: [PATCH 199/370] fix gramma, typo, code and rearrange paragraph --- doc/design/reader/README.md | 51 ++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/doc/design/reader/README.md b/doc/design/reader/README.md index 7fa62350c40d53..be337a800fa085 100644 --- a/doc/design/reader/README.md +++ b/doc/design/reader/README.md @@ -27,11 +27,25 @@ def data_reader_fake_image_and_label(): yield numpy.random.uniform(-1, 1, size=20*20), False ``` +## 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 Decorators Data Reader Decorators 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 a few examples: +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 @@ -64,39 +78,25 @@ true_reader = lambda : data_reader_bool(True) false_reader = lambda : data_reader_bool(False) reader = paddle.reader.combine(paddle.dataset.mnist, data_reader_fake_image, true_reader, false_reader) -# skipped 1 because paddle.dataset.mnist produces two items per data entry. -# We don't care second item at this time. +# 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 decorater that buffers `n` data entries and shuffle them before a data entry is read. +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) ``` -## 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, ...) -``` - ## Q & A ### Why return only a single entry, but not a mini batch? -If return a mini batch, 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`. +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 reader much easier (e.g., if existing data 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). @@ -129,13 +129,16 @@ An example implementation of paddle.train could be: ```python def minibatch_decorater(reader, minibatch_size): - buf = [reader.next() for x in xrange(minibatch_size)] - while len(buf) > 0: - yield buf - buf = [reader.next() for x in xrange(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 minibatch_decorater(reader()): # this loop will never end in online learning. + for mini_batch in minibatch_decorater(reader): # this loop will never end in online learning. do_forward_backward(mini_batch, mapping) ``` From 7f19ca4fbe61f4a454eb55b018f222305f87ce7a Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Thu, 16 Feb 2017 17:53:46 -0800 Subject: [PATCH 200/370] fix capitalization --- doc/design/reader/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/design/reader/README.md b/doc/design/reader/README.md index be337a800fa085..8f7abf12f73354 100644 --- a/doc/design/reader/README.md +++ b/doc/design/reader/README.md @@ -43,7 +43,7 @@ paddle.train(paddle.dataset.mnist, {"image":0, "label":1}, 128, 10, ...) ## Data Reader Decorators -Data Reader Decorators 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. +Data reader decorators 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: From c57954e71cee4cc3e45f7dff21c770c4f636f319 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 17 Feb 2017 09:57:37 +0800 Subject: [PATCH 201/370] use v2.layer in api_train_v2 --- demo/mnist/api_train_v2.py | 36 ++++++++++++++++++------------------ python/paddle/v2/__init__.py | 5 +++-- python/paddle/v2/layer.py | 10 +++++----- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 5e46d510ad35bb..47584f33800b30 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -1,7 +1,7 @@ -from paddle.trainer_config_helpers import * -from paddle.trainer.PyDataProvider2 import dense_vector, integer_value -import paddle.v2 as paddle import numpy +import paddle.v2 as paddle +from paddle.trainer.PyDataProvider2 import dense_vector, integer_value + import mnist_util @@ -12,32 +12,32 @@ def train_reader(): yield item -def network_config(): - 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 main(): paddle.init(use_gpu=False, trainer_count=1) - topology = parse_network_config(network_config) + + # define network topology + images = paddle.layer.data(name='pixel', size=784) + label = paddle.layer.data(name='label', size=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) + + topology = paddle.layer.parse_network(cost) + print topology parameters = paddle.parameters.create(topology) 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.Optimizer( - learning_rate=0.01, learning_method=AdamOptimizer()) + adam_optimizer = paddle.optimizer.Adam(learning_rate=0.01) def event_handler(event): if isinstance(event, paddle.event.EndIteration): - para = parameters.get('___fc_layer_2__.w0') + 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()) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index 577e073ee56bad..bc064a21ae1502 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -19,8 +19,9 @@ import event import py_paddle.swig_paddle as api - -__all__ = ['optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', 'event'] +__all__ = [ + 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', 'event' +] def init(**kwargs): diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 4acbd5ef28c314..0ce4ecd569aa1d 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -72,6 +72,11 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. from paddle.trainer_config_helpers.default_decorators import wrap_name_default import collections +__all__ = [ + 'parse_network', 'data', 'fc', 'max_id', 'classification_cost', + 'cross_entropy_cost' +] + def parse_network(*outputs): """ @@ -165,11 +170,6 @@ def to_proto_impl(self, **kwargs): name_prefix='cross_entropy', parent_names=['input', 'label']) -__all__ = [ - 'parse_network', 'data', 'fc', 'max_id', 'classification_cost', - 'cross_entropy_cost' -] - if __name__ == '__main__': pixel = data(name='pixel', size=784) label = data(name='label', size=10) From dcc54bff3f2a51b7173f09f3b657c217060a60d1 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 17 Feb 2017 10:01:54 +0800 Subject: [PATCH 202/370] code clean --- demo/mnist/api_train_v2.py | 1 - 1 file changed, 1 deletion(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 47584f33800b30..59486ed1b3ba49 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -26,7 +26,6 @@ def main(): cost = paddle.layer.classification_cost(input=inference, label=label) topology = paddle.layer.parse_network(cost) - print topology parameters = paddle.parameters.create(topology) for param_name in parameters.keys(): array = parameters.get(param_name) From 7c5fd231063908e1d7699c995d1acebb2d321aa9 Mon Sep 17 00:00:00 2001 From: liaogang Date: Fri, 17 Feb 2017 13:08:39 +0800 Subject: [PATCH 203/370] Update MultiGradientMachine::getLayerOutput --- .../gradientmachines/MultiGradientMachine.cpp | 41 ++++++++----------- paddle/gserver/layers/CosSimLayer.cpp | 2 +- paddle/math/tests/test_RowBuffer.cpp | 8 ++-- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp index a571b3d72f1d52..56b1836e417072 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp @@ -283,41 +283,34 @@ void MultiGradientMachine::forwardBackward(const std::vector& inArgs, } MatrixPtr MultiGradientMachine::getLayerOutput(const std::string& layerName) { - // neural networks are same in each trainer thread - // layer output height = height of layer output * thread nums - auto nn = dynamic_cast(threads_[0]->getGradientMachine()); - auto height = nn->getLayerOutput(layerName)->getHeight() * threads_.size(); - auto stream = HPPL_STREAM_DEFAULT; - - auto copyLayerOutput = [height, stream]( - MatrixPtr& dst, MatrixPtr src, int startRow, bool useGpu) { - size_t width = src->getWidth(); - if (!dst) { - dst = src->clone(height, width, useGpu); - } else { - dst->resize(height, width); - } + // each thread has the same neuro network + auto nn = threads_[0]->getGradientMachine(); - MatrixPtr tmpMatrix = dst->subMatrix(startRow, src->getHeight()); - tmpMatrix->copyFrom(*src, stream); - }; + size_t height = 0; + size_t width = nn->getLayerOutput(layerName)->getWidth(); + for (auto& thread : threads_) { + auto out = thread->getGradientMachine()->getLayerOutput(layerName); + height += out->getHeight(); + CHECK_EQ(width, out->getWidth()); + } - MatrixPtr mats; - size_t startRow = 0; + MatrixPtr dst; + Matrix::resizeOrCreate(dst, height, width, false, useGpu_); // copy one layer output from one trainer thread at each time + size_t startRow = 0; for (auto& thread : threads_) { - auto nn = dynamic_cast(thread->getGradientMachine()); - auto mat = nn->getLayerOutput(layerName); - copyLayerOutput(mats, mat, startRow, useGpu_); - startRow += mat->getHeight(); + auto src = thread->getGradientMachine()->getLayerOutput(layerName); + auto tmpMatrix = dst->subMatrix(startRow, src->getHeight()); + tmpMatrix->copyFrom(*src, HPPL_STREAM_DEFAULT); + startRow += src->getHeight(); } if (useGpu_) { hl_stream_synchronize(HPPL_STREAM_DEFAULT); } - return mats; + return dst; } void MultiGradientMachine::backwardImp(const UpdateCallback& callback) { diff --git a/paddle/gserver/layers/CosSimLayer.cpp b/paddle/gserver/layers/CosSimLayer.cpp index a6c0300acf6752..1501c7437011d5 100644 --- a/paddle/gserver/layers/CosSimLayer.cpp +++ b/paddle/gserver/layers/CosSimLayer.cpp @@ -42,7 +42,7 @@ void CosSimLayer::forward(PassType passType) { /* malloc memory for the output_ if necessary */ int batchSize = getInputValue(0)->getHeight(); int size = getSize(); - CHECK_EQ(forward_.size(), 1) << "Only one forward function needed"; + CHECK_EQ(forward_.size(), 1UL) << "Only one forward function needed"; { REGISTER_TIMER_INFO("CosFwResetTimer", getName().c_str()); diff --git a/paddle/math/tests/test_RowBuffer.cpp b/paddle/math/tests/test_RowBuffer.cpp index 5f66f22ef73dcf..8cc4c69a1a4d8a 100644 --- a/paddle/math/tests/test_RowBuffer.cpp +++ b/paddle/math/tests/test_RowBuffer.cpp @@ -17,10 +17,10 @@ limitations under the License. */ TEST(RowBuffer, testAutoGrow) { paddle::RowBuffer buf(128); - ASSERT_EQ(128, buf.getWidth()); + ASSERT_EQ(128UL, buf.getWidth()); ASSERT_TRUE(buf.isAutoGrowth()); buf.resize(2); - ASSERT_EQ(2, buf.getRowCount()); + ASSERT_EQ(2UL, buf.getRowCount()); for (size_t i = 0; i < buf.getWidth() * 2; ++i) { buf.data()[i] = i; } @@ -35,7 +35,7 @@ TEST(RowBuffer, testAutoGrow) { data[i] = i; } - ASSERT_EQ(3, buf.getRowCount()); + ASSERT_EQ(3UL, buf.getRowCount()); for (size_t i = 0; i < buf.getRowCount() - 1; ++i) { for (size_t j = 0; j < buf.getWidth(); ++j) { ASSERT_NEAR(i * buf.getWidth() + j, buf.get(i)[j], 1e-5); @@ -51,7 +51,7 @@ TEST(RowBuffer, testWithMemBuf) { std::make_shared(128 * 2 * sizeof(real)); paddle::RowBuffer buf(mem, 128); ASSERT_TRUE(!buf.isAutoGrowth()); - ASSERT_EQ(2, buf.getRowCount()); + ASSERT_EQ(2UL, buf.getRowCount()); for (size_t i = 0; i < buf.getWidth() * 2; ++i) { buf.data()[i] = i; } From 258e5ec59f28f617397646edbf67d4a576f0d3f0 Mon Sep 17 00:00:00 2001 From: liaogang Date: Fri, 17 Feb 2017 13:23:38 +0800 Subject: [PATCH 204/370] update GradientMachine API --- paddle/api/GradientMachine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddle/api/GradientMachine.cpp b/paddle/api/GradientMachine.cpp index 66115f8293b905..a44763bfa53ed5 100644 --- a/paddle/api/GradientMachine.cpp +++ b/paddle/api/GradientMachine.cpp @@ -146,7 +146,7 @@ void GradientMachine::randParameters() { m->machine->randParameters(); } Matrix* GradientMachine::getLayerOutput(const std::string& layerName) const throw(UnsupportError) { - auto nn = std::dynamic_pointer_cast(m->machine); + auto nn = m->machine; if (nn) { auto mat = nn->getLayerOutput(layerName); return Matrix::createByPaddleMatrixPtr(&mat); From 3842bc4d7c904b2d0bda4aa48429a20c317f1420 Mon Sep 17 00:00:00 2001 From: liaogang Date: Fri, 17 Feb 2017 13:42:33 +0800 Subject: [PATCH 205/370] refine code --- .../gradientmachines/MultiGradientMachine.cpp | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp index 56b1836e417072..db13a886881ef7 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp @@ -285,32 +285,34 @@ void MultiGradientMachine::forwardBackward(const std::vector& inArgs, MatrixPtr MultiGradientMachine::getLayerOutput(const std::string& layerName) { // each thread has the same neuro network auto nn = threads_[0]->getGradientMachine(); - size_t height = 0; size_t width = nn->getLayerOutput(layerName)->getWidth(); + std::vector mats; + mats.reserve(threads_.size()); for (auto& thread : threads_) { - auto out = thread->getGradientMachine()->getLayerOutput(layerName); + MatrixPtr out = thread->getGradientMachine()->getLayerOutput(layerName); + mats.push_back(out); height += out->getHeight(); CHECK_EQ(width, out->getWidth()); } - MatrixPtr dst; - Matrix::resizeOrCreate(dst, height, width, false, useGpu_); + MatrixPtr layerOutput; + Matrix::resizeOrCreate(layerOutput, height, width, false, useGpu_); // copy one layer output from one trainer thread at each time size_t startRow = 0; - for (auto& thread : threads_) { - auto src = thread->getGradientMachine()->getLayerOutput(layerName); - auto tmpMatrix = dst->subMatrix(startRow, src->getHeight()); - tmpMatrix->copyFrom(*src, HPPL_STREAM_DEFAULT); - startRow += src->getHeight(); + + for (size_t i = 0; i < threads_.size(); i++) { + auto tmpMatrix = layerOutput->subMatrix(startRow, mats[i]->getHeight()); + tmpMatrix->copyFrom(*mats[i], HPPL_STREAM_DEFAULT); + startRow += mats[i]->getHeight(); } if (useGpu_) { hl_stream_synchronize(HPPL_STREAM_DEFAULT); } - return dst; + return layerOutput; } void MultiGradientMachine::backwardImp(const UpdateCallback& callback) { From 84552872a337b42252233023191698f992aa5808 Mon Sep 17 00:00:00 2001 From: liaogang Date: Fri, 17 Feb 2017 16:09:50 +0800 Subject: [PATCH 206/370] getLayerOutput in CPU --- paddle/gserver/gradientmachines/GradientMachine.h | 4 +++- .../gserver/gradientmachines/MultiGradientMachine.cpp | 10 +++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/paddle/gserver/gradientmachines/GradientMachine.h b/paddle/gserver/gradientmachines/GradientMachine.h index 201b65bc45181b..a814e771d12e3a 100644 --- a/paddle/gserver/gradientmachines/GradientMachine.h +++ b/paddle/gserver/gradientmachines/GradientMachine.h @@ -134,7 +134,9 @@ class GradientMachine { backward(callback); } - virtual MatrixPtr getLayerOutput(const std::string& layerName) = 0; + virtual MatrixPtr getLayerOutput(const std::string& layerName) { + return nullptr; + } // see comment in Layer.h for the function with the same name virtual void resetState() {} diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp index db13a886881ef7..7e60920376d195 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp @@ -283,7 +283,7 @@ void MultiGradientMachine::forwardBackward(const std::vector& inArgs, } MatrixPtr MultiGradientMachine::getLayerOutput(const std::string& layerName) { - // each thread has the same neuro network + // each thread has the same neural network auto nn = threads_[0]->getGradientMachine(); size_t height = 0; size_t width = nn->getLayerOutput(layerName)->getWidth(); @@ -297,21 +297,17 @@ MatrixPtr MultiGradientMachine::getLayerOutput(const std::string& layerName) { } MatrixPtr layerOutput; - Matrix::resizeOrCreate(layerOutput, height, width, false, useGpu_); + Matrix::resizeOrCreate(layerOutput, height, width, false, false); // copy one layer output from one trainer thread at each time size_t startRow = 0; for (size_t i = 0; i < threads_.size(); i++) { auto tmpMatrix = layerOutput->subMatrix(startRow, mats[i]->getHeight()); - tmpMatrix->copyFrom(*mats[i], HPPL_STREAM_DEFAULT); + tmpMatrix->copyFrom(*mats[i]); startRow += mats[i]->getHeight(); } - if (useGpu_) { - hl_stream_synchronize(HPPL_STREAM_DEFAULT); - } - return layerOutput; } From 695b5a7fcd42e4e5678fdb4288cc8dd23240aac4 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 17 Feb 2017 18:09:55 +0800 Subject: [PATCH 207/370] change topology to layer --- demo/mnist/api_train_v2.py | 5 ++--- python/paddle/v2/parameters.py | 26 +++++++++++++------------- python/paddle/v2/trainer.py | 9 ++++++--- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 59486ed1b3ba49..b5cc74ce67dfc8 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -25,8 +25,7 @@ def main(): act=paddle.activation.Softmax()) cost = paddle.layer.classification_cost(input=inference, label=label) - topology = paddle.layer.parse_network(cost) - parameters = paddle.parameters.create(topology) + 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) @@ -46,7 +45,7 @@ def event_handler(event): trainer = paddle.trainer.SGD(update_equation=adam_optimizer) trainer.train(train_data_reader=train_reader, - topology=topology, + topology=cost, parameters=parameters, event_handler=event_handler, batch_size=32, # batch size should be refactor in Data reader diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index e5b7dabcb8eb3a..ea504d5104716d 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -1,27 +1,27 @@ import numpy as np - -from paddle.proto.ModelConfig_pb2 import ModelConfig -from paddle.proto.ParameterConfig_pb2 import ParameterConfig +from . import layer as v2_layer import py_paddle.swig_paddle as api +from paddle.proto.ParameterConfig_pb2 import ParameterConfig __all__ = ['Parameters', 'create'] -def create(*topologies): +def create(*layers): """ - Create parameter pool by topologies. + Create parameter pool by layers. In paddle, layer can be represent a + model config. - :param topologies: + :param layers: :return: """ - pool = Parameters() - for topo in topologies: - if not isinstance(topo, ModelConfig): + for layer in layers: + if not isinstance(layer, v2_layer.Layer): raise ValueError( - 'create must pass a topologies which type is ModelConfig') - - for param in topo.parameters: - pool.__append_config__(param) + 'create must pass a topologies which type is paddle.layer.Layer') + model_config = v2_layer.parse_network(*layers) + pool = Parameters() + for param in model_config.parameters: + pool.__append_config__(param) return pool diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 9ba13dc5c8a81f..4365bd41e7073b 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -1,12 +1,13 @@ import collections import py_paddle.swig_paddle as api +from paddle.proto.ModelConfig_pb2 import ModelConfig from py_paddle import DataProviderConverter -from paddle.proto.ModelConfig_pb2 import ModelConfig +from . import event as v2_event +from . import layer as v2_layer from . import optimizer as v2_optimizer from . import parameters as v2_parameters -from . import event as v2_event __all__ = ['ITrainer', 'SGD'] @@ -73,7 +74,7 @@ def train(self, Training method. Will train num_passes of input data. :param train_data_reader: - :param topology: Network Topology, a protobuf ModelConfig message. + :param topology: Network Topology, use one or more Layers to represent it. :param parameters: The parameter pools. :param num_passes: The total train passes. :param test_data_reader: @@ -87,6 +88,8 @@ def train(self, if event_handler is None: event_handler = default_event_handler + topology = v2_layer.parse_network(topology) + __check_train_args__(**locals()) gm = api.GradientMachine.createFromConfigProto( From d2dfa70deb08c3c8b13e2154afed6a3e4ce535d7 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Fri, 17 Feb 2017 19:34:11 +0800 Subject: [PATCH 208/370] data converter --- python/paddle/v2/data_converter.py | 240 +++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 python/paddle/v2/data_converter.py diff --git a/python/paddle/v2/data_converter.py b/python/paddle/v2/data_converter.py new file mode 100644 index 00000000000000..5d7b8a736b3596 --- /dev/null +++ b/python/paddle/v2/data_converter.py @@ -0,0 +1,240 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + +import collections +import py_paddle.swig_paddle +import numpy + +__all__ = ['DataConverter'] + + +class IDataConverter(object): + def __init__(self, input_type, pos): + """ + :param input_type: data type + :type input_type: dp2.InputType + :param pos: which input, start from 0 + :type pos: int + """ + self.input_type = input_type + assert isinstance(self.input_type, dp2.InputType) + self.pos = pos + + def convert(self, data, argument): + """ + Conv data to paddle format. + :param data: input data + :param argument: paddle format + """ + pass + + +class DenseConvert(IDataConverter): + def __init__(self, input_type, pos): + IDataConverter.__init__(self, input_type, pos) + + def convert(self, data, argument): + """ + :param data: input data + :type data: list | numpy array + :param argument: the type which paddle is acceptable + :type argument: swig_paddle.Arguments + """ + assert isinstance(argument, swig_paddle.Arguments) + if data.dtype != numpy.float32: + data = data.astype(numpy.float32) + m = swig_paddle.Matrix.createDenseFromNumpy(data, True, False) + argument.setSlotValue(self.pos, m) + + +class SparseBinaryConvert(IDataConverter): + def __init__(self, input_type, pos): + IDataConverter.__init__(self, input_type, pos) + self.__rows__ = [0] + self.__cols__ = [] + self.__height__ = 0 + self.__nnz__ = 0 + self.__value__ = [] + + def fill_csr(self, data): + self.__height__ = len(data) + for x in data: + self.__rows__.append(self.__rows__[-1] + len(x)) + self__cols__ = data.flatten() + + def convert(self, data, argument): + assert isinstance(argument, swig_paddle.Arguments) + + fill_csr(data) + m = swig_paddle.Matrix.createSparse(self.__height__, + self.input_type.dim, + len(self.__cols__), + len(self.__value__) == 0) + assert isinstance(m, swig_paddle.Matrix) + m.sparseCopyFrom(self.__rows__, self.__cols__, self.__value__) + argument.setSlotValue(self.pos, m) + + +class SparseFloatConvert(SparseBinaryConvert): + def __init__(self, input_type, pos): + SparseBinaryConvert.__init__(self, input_type, pos) + + def fill_csr(self, data): + self.__height__ = len(data) + for x in data: + self.__rows__.append(self.__rows__[-1] + len(x)) + self.__cols__.extend((x[0] for x in data)) + self.__value__.extend((x[1] for x in data)) + + +class IndexConvert(IDataConverter): + def __init__(self, input_type, pos): + IDataConverter.__init__(self, input_type, pos) + self.__ids__ = [] + + def convert(self, data, argument): + assert isinstance(argument, swig_paddle.Arguments) + self.__ids__ = data.flatten() + ids = swig_paddle.IVector.create(self.__ids__) + argument.setSlotIds(self.pos, ids) + + +class SequenceConvert(IDataConverter): + def __init__(self, input_type, pos, inner_convert, setter): + """ + :param input_type: the type of input data + :type input_type: dp2.InputType + :param pos: the position of this input + :type pos: int + :param inner_convert: DataConvert type + :type inner_convert: DenseConvert|SparseBinaryConvert| + SparseFloatConvert|IndexConvert + :param setter: + :type setter: + """ + IDataConverter.__init__(self, input_type, pos) + self.__seq__ = [0] + self.__inner_convert__ = inner_convert + self.__setter__ = setter + + def fill_seq(self, data): + for each in data: + self.__seq__.append(self.__seq__[-1] + self.get_size(each)) + + def convert(self, data, argument): + fill_seq(data) + seq = swig_paddle.IVector.create(self.__seq__, False) + self.__setter__(argument, self.pos, seq) + + dat = [] + for each in data: + dat.append(each) + self.__inner_scanner__.convert(dat, argument) + + def get_size(self, data): + if isinstance(self.__inner_scanner__, SequenceConvert): + return sum(self.__inner_scanner__.get_size(item) for item in dat) + else: + return len(data) + + +class DataConverter(object): + def __init__(self, input_mapper): + """ + Usege: + + .. code-block:: python + inputs = [('image', dense_vector), ('label', integer_value)] + cvt = DataConverter(inputs) + arg = cvt.convert(minibatch_data, {'image':0, 'label':1}) + + :param input_mapper: list of (input_name, input_type) + :type input_mapper: list + """ + assert isinstance(self.input_types, collections.Sequence) + self.input_names = [] + self.input_types = [] + for each in self.input_types: + self.input_names.append(each[0]) + self.input_types.append(each[1]) + assert isinstance(each[1], dp2.InputType) + + def convert(self, data, input_dict=None, argument=None): + """ + Convert minibatch data to Paddle's argument. The data is numpy array + or list. + + :param data: input samples, for example, [column0, column1, ...] or + (column0, column1, ...) each column is one minibatch + feature. Note, if only one column featrue, data also + shuld be a list or tupe, [column0] or (column0). + :type data: list|tuple + :param input_dict: a dictionary to specify the correspondence + of data_layer and input data. If None, + the feature order in argument and data is the same. + :type input_dict: dict, like {string:integer, string, integer, ...}|None + :param argument: converted data will be saved in this argument. If None, + it will create a swig_paddle.Arguments firstly. + :param type: swig_paddle.Arguments|None + """ + if argument is None: + argument = swig_paddle.Arguments.createArguments(0) + assert isinstance(argument, swig_paddle.Arguments) + argument.resize(len(self.input_types)) + + converts = [ + DataConverter.create_scanner(i, each_type) + for i, each_type in enumerate(self.input_types) + ] + + for i, cvt in enumerate(converts): + if input_dict is not None: + dat = data[input_dict[self.input_names[i]]] + else: + dat = data[i] + cvt.convert(dat, argument) + + return argument + + def __call__(self, dat, argument=None): + return self.convert(dat, argument) + + @staticmethod + def create_scanner(pos, each): + assert isinstance(each, dp2.InputType) + retv = None + if each.type == dp2.DataType.Dense: + retv = DenseConvert(each, pos) + elif each.type == dp2.DataType.Index: + retv = IndexConvert(each, pos) + elif each.type == dp2.DataType.SparseNonValue: + retv = SparseBinaryConvert(each, pos) + elif each.type == dp2.DataType.SparseValue: + retv = SparseFloatConvert(each, pos) + assert retv is not None + + if each.seq_type == dp2.SequenceType.SUB_SEQUENCE: + retv = SequenceConvert( + each, pos, retv, + lambda arg, pos, seq: arg.setSlotSubSequenceStartPositions(pos, seq) + ) + + if each.seq_type in [ + dp2.SequenceType.SUB_SEQUENCE, dp2.SequenceType.SEQUENCE + ]: + retv = SequenceConvert( + each, pos, retv, + lambda arg, pos, seq: arg.setSlotSequenceStartPositions(pos, seq) + ) + return retv From 733da9b9e62fb20a5adfe12f23834b7fa184dd63 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Fri, 17 Feb 2017 19:45:52 +0800 Subject: [PATCH 209/370] data converter --- python/paddle/v2/data_converter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/paddle/v2/data_converter.py b/python/paddle/v2/data_converter.py index 5d7b8a736b3596..45114b407dae22 100644 --- a/python/paddle/v2/data_converter.py +++ b/python/paddle/v2/data_converter.py @@ -15,6 +15,7 @@ import collections import py_paddle.swig_paddle import numpy +import paddle.trainer.PyDataProvider2 as dp2 __all__ = ['DataConverter'] From 701d02459d36ee254e20f5a934205aa0530478e8 Mon Sep 17 00:00:00 2001 From: Peng Li Date: Fri, 17 Feb 2017 19:58:16 +0800 Subject: [PATCH 210/370] Fix bug in processing input with static parameter in seqconcat layer --- paddle/gserver/layers/SequenceConcatLayer.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/paddle/gserver/layers/SequenceConcatLayer.cpp b/paddle/gserver/layers/SequenceConcatLayer.cpp index b4677687a6cc77..599706eb419ede 100644 --- a/paddle/gserver/layers/SequenceConcatLayer.cpp +++ b/paddle/gserver/layers/SequenceConcatLayer.cpp @@ -168,13 +168,17 @@ void SequenceConcatLayer::backward(const UpdateCallback& callback) { size_t rightNumIns = 0; for (size_t seqId = 0; seqId < numSequences1; ++seqId) { leftNumIns = starts1[seqId + 1] - starts1[seqId]; - inputGrad1->subMatrix(starts1[seqId], leftNumIns) - ->add(*(outputGrad->subMatrix(offset, leftNumIns))); + if (inputGrad1) { + inputGrad1->subMatrix(starts1[seqId], leftNumIns) + ->add(*(outputGrad->subMatrix(offset, leftNumIns))); + } offset += leftNumIns; rightNumIns = starts2[seqId + 1] - starts2[seqId]; - inputGrad2->subMatrix(starts2[seqId], rightNumIns) - ->add(*(outputGrad->subMatrix(offset, rightNumIns))); + if (inputGrad2) { + inputGrad2->subMatrix(starts2[seqId], rightNumIns) + ->add(*(outputGrad->subMatrix(offset, rightNumIns))); + } offset += rightNumIns; } } From f846362927fa9ba6baf0c54db5051e2616af0a39 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Fri, 17 Feb 2017 10:06:59 -0800 Subject: [PATCH 211/370] create buffered data reader decorator and tests --- python/CMakeLists.txt | 1 + python/paddle/reader/__init__.py | 15 +++++ python/paddle/reader/decorator.py | 60 ++++++++++++++++++++ python/paddle/reader/tests/CMakeLists.txt | 4 ++ python/paddle/reader/tests/decorator_test.py | 50 ++++++++++++++++ 5 files changed, 130 insertions(+) create mode 100644 python/paddle/reader/__init__.py create mode 100644 python/paddle/reader/decorator.py create mode 100644 python/paddle/reader/tests/CMakeLists.txt create mode 100644 python/paddle/reader/tests/decorator_test.py diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index ee7a5bff84ca96..357637e20346f8 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -24,6 +24,7 @@ add_custom_target(paddle_python ALL DEPENDS ${OUTPUT_DIR}/.timestamp) add_subdirectory(paddle/trainer_config_helpers/tests) +add_subdirectory(paddle/reader/tests) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dist/ DESTINATION opt/paddle/share/wheels diff --git a/python/paddle/reader/__init__.py b/python/paddle/reader/__init__.py new file mode 100644 index 00000000000000..28a69d8370262d --- /dev/null +++ b/python/paddle/reader/__init__.py @@ -0,0 +1,15 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + +from decorator import * diff --git a/python/paddle/reader/decorator.py b/python/paddle/reader/decorator.py new file mode 100644 index 00000000000000..f0ddb0ff812b15 --- /dev/null +++ b/python/paddle/reader/decorator.py @@ -0,0 +1,60 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + +__all__ = ['buffered'] + +from Queue import Queue +from threading import Thread + + +def buffered(reader, size): + """Creates a buffered data reader. + + The buffered data reader will read and save data entries into a buffer. + Reading from the buffered data reader will proceed as long as the buffer + is not empty. + + Args: + reader: the data reader to read from. + size: max buffer size. + + Returns: + The buffered data reader. + """ + + class EndSignal(): + pass + + end = EndSignal() + + def read_worker(r, q): + for d in r: + q.put(d) + q.put(end) + + def create_reader(): + r = reader() + q = Queue(maxsize=size) + t = Thread( + target=read_worker, args=( + r, + q, )) + t.daemon = True + t.start() + e = q.get() + while e != end: + yield e + e = q.get() + + return create_reader diff --git a/python/paddle/reader/tests/CMakeLists.txt b/python/paddle/reader/tests/CMakeLists.txt new file mode 100644 index 00000000000000..4768d0738b381a --- /dev/null +++ b/python/paddle/reader/tests/CMakeLists.txt @@ -0,0 +1,4 @@ +add_test(NAME reader_decorator_test + COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ + ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/reader/decorator_test.py + WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) diff --git a/python/paddle/reader/tests/decorator_test.py b/python/paddle/reader/tests/decorator_test.py new file mode 100644 index 00000000000000..879d1d9c1d0e06 --- /dev/null +++ b/python/paddle/reader/tests/decorator_test.py @@ -0,0 +1,50 @@ +# Copyright PaddlePaddle contributors. All Rights Reserved +# +# 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. +import unittest +import paddle.reader +import time + + +def reader_10(dur): + for i in range(10): + time.sleep(dur) + yield i + + +class TestBuffered(unittest.TestCase): + def test_read(self): + for size in range(20): + b = paddle.reader.buffered(lambda: reader_10(0), size) + c = 0 + for i in b(): + self.assertEqual(i, c) + c += 1 + self.assertEqual(c, 10) + + def test_buffering(self): + # read have 30ms delay. + b = paddle.reader.buffered(lambda: reader_10(0.03), 10) + last_time = time.time() + for idx, i in enumerate(b()): + elapsed_time = time.time() - last_time + if i == 0: + time.sleep(0.3) + else: + # read time should be short, meaning already buffered. + self.assertLess(elapsed_time, 0.01) + last_time = time.time() + + +if __name__ == '__main__': + unittest.main() From 7c1d10e6cbfd4bfd4f9ac1d0c49418755fab541e Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Fri, 17 Feb 2017 10:46:26 -0800 Subject: [PATCH 212/370] travis ci: cache brew directory Fixes #1365 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 5d82d9729b75ef..4fb2ca938795bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ cache: - $HOME/third_party - $HOME/.ccache - $HOME/.cache/pip + - $HOME/Library/Caches/Homebrew sudo: required dist: trusty os: From 7b50594f6d61b80631b8700d0ba158bb7ef5363a Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Sat, 18 Feb 2017 10:23:22 -0800 Subject: [PATCH 213/370] fix test path --- python/paddle/reader/tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/reader/tests/CMakeLists.txt b/python/paddle/reader/tests/CMakeLists.txt index 4768d0738b381a..502c897d8946a8 100644 --- a/python/paddle/reader/tests/CMakeLists.txt +++ b/python/paddle/reader/tests/CMakeLists.txt @@ -1,4 +1,4 @@ add_test(NAME reader_decorator_test COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ - ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/reader/decorator_test.py + ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/reader/tests/decorator_test.py WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) From b2a969b7b3227a089ac5b482dfd5f9b340a3f483 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Sat, 18 Feb 2017 13:27:25 -0800 Subject: [PATCH 214/370] fix according to comment --- python/paddle/reader/__init__.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/python/paddle/reader/__init__.py b/python/paddle/reader/__init__.py index 28a69d8370262d..493b410e8299eb 100644 --- a/python/paddle/reader/__init__.py +++ b/python/paddle/reader/__init__.py @@ -12,4 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +# It would be too lengthy to require our users to prefix decorators with `decorator`. +# For example, we want the following line +# +# r = paddle.reader.decorator.bufferd(paddle.reader.creator.text("hello.txt")) +# +# to be a shorter version: +# +# r = paddle.reader.buffered(paddle.reader.creator.text("hello.txt")) from decorator import * From d5cfa6fcce622982624274e4e86a6670b29b634d Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sun, 19 Feb 2017 15:17:40 +0800 Subject: [PATCH 215/370] Stash --- paddle/gserver/evaluators/Evaluator.cpp | 19 +++++++++++-- paddle/gserver/evaluators/Evaluator.h | 38 +++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index ae7508e2bb117a..4689222e3ade62 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -449,6 +449,21 @@ double AucEvaluator::calcAuc() const { } } +real AucEvaluator::getValueImpl() const { return calcAuc(); } + +std::string AucEvaluator::getTypeImpl() const { + if (colIdx_ == -1) { + return "last-column-auc"; + } else { + return "auc"; + } +} + +static InitFunction __reg_type_auc__([]() { + Evaluator::registrar_.registerClass("last-column-auc", + [] { return new AucEvaluator(-1); }); +}); + // class RankAucEvaluator REGISTER_EVALUATOR(rankauc, RankAucEvaluator); @@ -873,8 +888,6 @@ Evaluator* Evaluator::create(const EvaluatorConfig& config) { 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()); } @@ -1253,4 +1266,6 @@ class ClassificationErrorPrinter : public ClassificationErrorEvaluator { }; REGISTER_EVALUATOR(classification_error_printer, ClassificationErrorPrinter); +std::string DummyEvaluator::getTypeImpl() const { return "dummy"; } + } // namespace paddle diff --git a/paddle/gserver/evaluators/Evaluator.h b/paddle/gserver/evaluators/Evaluator.h index 5770847309670e..bf08aa07f0ce31 100644 --- a/paddle/gserver/evaluators/Evaluator.h +++ b/paddle/gserver/evaluators/Evaluator.h @@ -19,6 +19,7 @@ limitations under the License. */ #include "paddle/parameter/Argument.h" #include "paddle/pserver/ParameterClient2.h" #include "paddle/utils/ClassRegistrar.h" +#include "paddle/utils/Error.h" namespace paddle { @@ -117,6 +118,34 @@ class Evaluator { static ClassRegistrar registrar_; + virtual void getNames(std::vector* names) { + names->clear(); + names->push_back(config_.name()); + } + + virtual real getValue(const std::string& name, + paddle::Error* err = nullptr) const { + if (name != config_.name() && err != nullptr) { + *err = paddle::Error("no such name of evaluator %s", name.c_str()); + return .0f; + } + return this->getValueImpl(); + } + + virtual std::string getType(const std::string& name, + paddle::Error* err = nullptr) const { + if (name != config_.name() && err != nullptr) { + *err = paddle::Error("no such name of evaluator %s", name.c_str()); + return std::string(); + } + return this->getTypeImpl(); + } + +protected: + virtual real getValueImpl() const { return .0f; } + + virtual std::string getTypeImpl() const { return "base"; } + protected: EvaluatorConfig config_; double numSamples_; @@ -135,6 +164,10 @@ class DummyEvaluator : public Evaluator { } virtual void finish() {} virtual void printStats(std::ostream&) const {} + + // Evaluator interface +protected: + std::string getTypeImpl() const; }; /** * @brief evaluate AUC using colIdx-th column as prediction. @@ -191,6 +224,11 @@ class AucEvaluator : public Evaluator { } double calcAuc() const; + + // Evaluator interface +protected: + real getValueImpl() const; + std::string getTypeImpl() const; }; /** From d2c58907eb552bab046a1fbb7d114149b0fd2916 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sun, 19 Feb 2017 15:22:38 +0800 Subject: [PATCH 216/370] Unify Evaluator::create method * Simplify Evaluator::create logic. Always use ClassRegister to create Evaluator. --- paddle/gserver/evaluators/Evaluator.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index ae7508e2bb117a..a2a5028e8418fd 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -866,21 +866,20 @@ void PnpairEvaluator::calc(std::vector& predictArray) { ClassRegistrar Evaluator::registrar_; Evaluator* Evaluator::create(const EvaluatorConfig& config) { - Evaluator* evaluator = nullptr; - 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* evaluator = registrar_.createByType(config.type()); evaluator->init(config); 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. * From 2c07dd50ab39643ba6da941b021bf34fa48b11c8 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sun, 19 Feb 2017 17:39:52 +0800 Subject: [PATCH 217/370] Unify print layer, ValuePrinter evaluator. --- paddle/gserver/evaluators/Evaluator.cpp | 29 +++++++------------------ paddle/gserver/layers/PrintLayer.cpp | 29 +++++++------------------ paddle/parameter/Argument.cpp | 26 ++++++++++++++++++++++ paddle/parameter/Argument.h | 8 +++++++ 4 files changed, 50 insertions(+), 42 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index ae7508e2bb117a..1a43d3bd996109 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -892,27 +892,14 @@ class ValuePrinter : public Evaluator { virtual void eval(const NeuralNetwork& nn) { for (const std::string& name : config_.input_layers()) { - const Argument& argu = nn.getLayer(name)->getOutput(); - 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(); + auto& argu = nn.getLayer(name)->getOutput(); + std::unordered_map out; + argu.getValueString(&out); + for (auto field : {"value", "id", "sequence pos", "sub-sequence pos"}) { + auto it = out.find(field); + if (it != out.end()) { + LOG(INFO) << "layer=" << name << " " << field << ":\n" << it->second; + } } } } diff --git a/paddle/gserver/layers/PrintLayer.cpp b/paddle/gserver/layers/PrintLayer.cpp index 85f52ad5debd03..f1f3dd412c67a9 100644 --- a/paddle/gserver/layers/PrintLayer.cpp +++ b/paddle/gserver/layers/PrintLayer.cpp @@ -26,28 +26,15 @@ class PrintLayer : public Layer { void PrintLayer::forward(PassType passType) { Layer::forward(passType); for (size_t i = 0; i != inputLayers_.size(); ++i) { - const auto& argu = getInput(i); + auto& argu = getInput(i); const std::string& name = 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(); + std::unordered_map out; + argu.getValueString(&out); + for (auto field : {"value", "id", "sequence pos", "sub-sequence pos"}) { + auto it = out.find(field); + if (it != out.end()) { + LOG(INFO) << "layer=" << name << " " << field << ":\n" << it->second; + } } } } diff --git a/paddle/parameter/Argument.cpp b/paddle/parameter/Argument.cpp index 65d01a15718ae2..e9de0f66987603 100644 --- a/paddle/parameter/Argument.cpp +++ b/paddle/parameter/Argument.cpp @@ -602,6 +602,32 @@ void Argument::degradeSequence(const Argument& input, bool useGpu) { tgtBuf[numSequences] = numSubSequences; } +void Argument::getValueString( + std::unordered_map* out) const { + if (value) { + std::ostringstream os; + value->print(os); + out->insert({"value", os.str()}); + } + if (ids) { + std::ostringstream os; + ids->print(os, ids->getSize()); + out->insert({"ids", os.str()}); + } + if (sequenceStartPositions) { + std::ostringstream os; + sequenceStartPositions->getVector(false)->print( + os, sequenceStartPositions->getSize()); + out->insert({"sequence pos", os.str()}); + } + if (subSequenceStartPositions) { + std::ostringstream os; + subSequenceStartPositions->getVector(false)->print( + os, subSequenceStartPositions->getSize()); + out->insert({"sub-sequence pos", os.str()}); + } +} + void Argument::subArgFrom(const Argument& input, size_t offset, size_t height, diff --git a/paddle/parameter/Argument.h b/paddle/parameter/Argument.h index afd2de0202bf0f..c751dbb855d31d 100644 --- a/paddle/parameter/Argument.h +++ b/paddle/parameter/Argument.h @@ -297,6 +297,14 @@ struct Argument { sequence has sub-sequence degrades to a sequence. */ void degradeSequence(const Argument& input, bool useGpu); + + /** + * @brief getValueString will return the argument's output in string. There + * are several kinds of output. The keys of output dictionary are 'value', + * 'id', 'sequence pos', 'sub-sequence pos'. + * @param out [out]: the return values. + */ + void getValueString(std::unordered_map* out) const; }; } // namespace paddle From 04eaf75c5ea049ec88ba0c34f40176dee930c5ed Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sun, 19 Feb 2017 17:06:36 +0800 Subject: [PATCH 218/370] Add getValue to some evaluators. --- paddle/gserver/evaluators/Evaluator.cpp | 149 +++++++++++++----- paddle/gserver/evaluators/Evaluator.h | 44 +++++- .../gradientmachines/NeuralNetwork.cpp | 38 +++++ .../gserver/gradientmachines/NeuralNetwork.h | 4 + paddle/utils/Error.h | 2 + 5 files changed, 198 insertions(+), 39 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index be4f5f558fb995..b1daa09062fabe 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -538,12 +538,15 @@ double RankAucEvaluator::calcRankAuc(real* outputData, : aucTmp / (clickSum * noClickSum); } +std::string RankAucEvaluator::getTypeImpl() const { return "rankauc"; } + // class PrecisionRecallEvaluator REGISTER_EVALUATOR(precision_recall, PrecisionRecallEvaluator); void PrecisionRecallEvaluator::start() { Evaluator::start(); statsInfo_.clear(); + values_.clear(); } real PrecisionRecallEvaluator::evalImp(std::vector& arguments) { @@ -603,7 +606,9 @@ real PrecisionRecallEvaluator::evalImp(std::vector& arguments) { return 0; } -void PrecisionRecallEvaluator::printStats(std::ostream& os) const { +template +void PrecisionRecallEvaluator::printStatsHelper(T1 labelCallback, + T2 microAvgCallback) const { int label = config_.positive_label(); if (label != -1) { CHECK(label >= 0 && label < (int)statsInfo_.size()) @@ -612,9 +617,7 @@ void PrecisionRecallEvaluator::printStats(std::ostream& os) const { double precision = calcPrecision(statsInfo_[label].TP, statsInfo_[label].FP); double recall = calcRecall(statsInfo_[label].TP, statsInfo_[label].FN); - os << "positive_label=" << label << " precision=" << precision - << " recall=" << recall - << " F1-score=" << calcF1Score(precision, recall); + labelCallback(label, precision, recall, calcF1Score(precision, recall)); return; } @@ -636,21 +639,45 @@ void PrecisionRecallEvaluator::printStats(std::ostream& os) const { macroAvgPrecision /= numLabels; macroAvgRecall /= numLabels; double macroAvgF1Score = calcF1Score(macroAvgPrecision, macroAvgRecall); - os << "macro-average-precision=" << macroAvgPrecision - << " macro-average-recall=" << macroAvgRecall - << " macro-average-F1-score=" << macroAvgF1Score; double microAvgPrecision = calcPrecision(microTotalTP, microTotalFP); double microAvgRecall = calcPrecision(microTotalTP, microTotalFN); double microAvgF1Score = calcF1Score(microAvgPrecision, microAvgRecall); - if (!isMultiBinaryLabel_) { - // precision and recall are equal in this case - os << " micro-average-precision=" << microAvgPrecision; - } else { - os << " micro-average-precision=" << microAvgPrecision - << " micro-average-recall=" << microAvgRecall - << " micro-average-F1-score=" << microAvgF1Score; - } + + microAvgCallback(macroAvgPrecision, + macroAvgRecall, + macroAvgF1Score, + isMultiBinaryLabel_, + microAvgPrecision, + microAvgRecall, + microAvgF1Score); +} + +void PrecisionRecallEvaluator::printStats(std::ostream& os) const { + this->printStatsHelper( + [&os](int label, double precision, double recall, double f1) { + os << "positive_label=" << label << " precision=" << precision + << " recall=" << recall << " F1-score=" << f1; + }, + [&os](double macroAvgPrecision, + double macroAvgRecall, + double macroAvgF1Score, + bool isMultiBinaryLabel, + double microAvgPrecision, + double microAvgRecall, + double microAvgF1Score) { + os << "macro-average-precision=" << macroAvgPrecision + << " macro-average-recall=" << macroAvgRecall + << " macro-average-F1-score=" << macroAvgF1Score; + if (!isMultiBinaryLabel) { + // precision and recall are equal in this case + os << " micro-average-precision=" << microAvgPrecision; + } else { + os << " micro-average-precision=" << microAvgPrecision + << " micro-average-recall=" << microAvgRecall + << " micro-average-F1-score=" << microAvgF1Score; + } + }); } void PrecisionRecallEvaluator::calcStatsInfo(const MatrixPtr& output, @@ -731,6 +758,69 @@ void PrecisionRecallEvaluator::calcStatsInfoMulti(const MatrixPtr& output, } } +void PrecisionRecallEvaluator::storeLocalValues() const { + if (this->values_.size() == 0) { + this->printStatsHelper( + [this](int label, double precision, double recall, double f1) { + values_["positive_label"] = (double)label; + values_["precision"] = precision; + values_["recal"] = recall; + values_["F1-score"] = f1; + }, + [this](double macroAvgPrecision, + double macroAvgRecall, + double macroAvgF1Score, + bool isMultiBinaryLabel, + double microAvgPrecision, + double microAvgRecall, + double microAvgF1Score) { + values_["macro-average-precision"] = macroAvgPrecision; + values_["macro-average-recall"] = macroAvgRecall; + values_["macro-average-F1-score"] = macroAvgF1Score; + if (!isMultiBinaryLabel) { + // precision and recall are equal in this case + values_["micro-average-precision"] = microAvgPrecision; + } else { + values_["micro-average-precision"] = microAvgPrecision; + values_["micro-average-recall"] = microAvgRecall; + values_["micro-average-F1-score"] = microAvgF1Score; + } + }); + } +} + +void PrecisionRecallEvaluator::getNames(std::vector* names) { + this->storeLocalValues(); + names->clear(); + names->reserve(this->values_.size()); + for (auto it = this->values_.begin(); it != this->values_.end(); ++it) { + names->push_back(this->config_.name() + "." + it->first); + } +} + +real PrecisionRecallEvaluator::getValue(const std::string& name, + Error* err) const { + this->storeLocalValues(); + auto it = this->values_.find(name); + if (it != this->values_.end() && err != nullptr) { + *err = Error("No such key %s", name.c_str()); + return .0f; + } + + return it->second; +} + +std::string PrecisionRecallEvaluator::getType(const std::string& name, + Error* err) const { + this->storeLocalValues(); + auto it = this->values_.find(name); + if (it != this->values_.end() && err != nullptr) { + *err = Error("No such key %s", name.c_str()); + return ""; + } + return "precision_recall"; +} + void PrecisionRecallEvaluator::distributeEval(ParameterClient2* client) { size_t size = 4 * statsInfo_.size(); double* buf = new double[size]; @@ -874,6 +964,8 @@ void PnpairEvaluator::calc(std::vector& predictArray) { << " calc total special pair: " << special; } +std::string PnpairEvaluator::getTypeImpl() const { return "pnpair"; } + ClassRegistrar Evaluator::registrar_; Evaluator* Evaluator::create(const EvaluatorConfig& config) { Evaluator* evaluator = registrar_.createByType(config.type()); @@ -901,27 +993,12 @@ class ValuePrinter : public Evaluator { virtual void eval(const NeuralNetwork& nn) { for (const std::string& name : config_.input_layers()) { - const Argument& argu = nn.getLayer(name)->getOutput(); - 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(); + std::vector> out; + auto err = nn.getLayerOutputValue(name, &out); + err.check(); + for (auto& each : out) { + LOG(INFO) << "layer=" << name << std::get<0>(each) << ":\n" + << std::get<1>(each); } } } diff --git a/paddle/gserver/evaluators/Evaluator.h b/paddle/gserver/evaluators/Evaluator.h index bf08aa07f0ce31..bec3d6e66820fa 100644 --- a/paddle/gserver/evaluators/Evaluator.h +++ b/paddle/gserver/evaluators/Evaluator.h @@ -132,6 +132,20 @@ class Evaluator { return this->getValueImpl(); } + virtual std::string getValueStr(const std::string& name, + paddle::Error* err = nullptr) const { + paddle::Error localErr; + if (err == nullptr) { + err = &localErr; + } + real result = this->getValue(name, err); + if (!err->isOK()) { + return ""; + } else { + return std::to_string(result); + } + } + virtual std::string getType(const std::string& name, paddle::Error* err = nullptr) const { if (name != config_.name() && err != nullptr) { @@ -142,7 +156,9 @@ class Evaluator { } protected: - virtual real getValueImpl() const { return .0f; } + virtual real getValueImpl() const { + return numSamples_ != .0 ? totalScore_ / numSamples_ : .0; + } virtual std::string getTypeImpl() const { return "base"; } @@ -261,6 +277,10 @@ class RankAucEvaluator : public Evaluator { real* clickData, real* pvData, size_t size); + + // Evaluator interface +protected: + std::string getTypeImpl() const; }; /** * @brief precision, recall and f1 score Evaluator @@ -310,6 +330,9 @@ class PrecisionRecallEvaluator : public Evaluator { IVectorPtr cpuLabel_; MatrixPtr cpuWeight_; + template + void printStatsHelper(T1 labelCallback, T2 microAvgCallback) const; + void calcStatsInfo(const MatrixPtr& output, const IVectorPtr& label, const MatrixPtr& weight); @@ -341,6 +364,15 @@ class PrecisionRecallEvaluator : public Evaluator { return 0; } } + + mutable std::unordered_map values_; + + void storeLocalValues() const; + // Evaluator interface +public: + void getNames(std::vector* names); + real getValue(const std::string& name, Error* err) const; + std::string getType(const std::string& name, Error* err) const; }; /* @@ -387,8 +419,7 @@ class PnpairEvaluator : public Evaluator { virtual void finish() { calc(predictArray_); } virtual void printStats(std::ostream& os) const { - os << " pos/neg" - << "=" << pairArray_[0] / ((pairArray_[1] <= 0) ? 1.0 : pairArray_[1]); + os << " pos/neg=" << this->getValueImpl(); } virtual void distributeEval(ParameterClient2* client) { @@ -404,6 +435,13 @@ class PnpairEvaluator : public Evaluator { IVectorPtr cpuLabel_; IVectorPtr cpuInfo_; MatrixPtr cpuWeight_; + + // Evaluator interface +protected: + real getValueImpl() const { + return pairArray_[0] / ((pairArray_[1] <= 0) ? 1.0 : pairArray_[1]); + } + std::string getTypeImpl() const; }; } // namespace paddle diff --git a/paddle/gserver/gradientmachines/NeuralNetwork.cpp b/paddle/gserver/gradientmachines/NeuralNetwork.cpp index 22051e07ee0026..bf76830d61f9a3 100644 --- a/paddle/gserver/gradientmachines/NeuralNetwork.cpp +++ b/paddle/gserver/gradientmachines/NeuralNetwork.cpp @@ -405,4 +405,42 @@ NeuralNetwork* NeuralNetwork::newNeuralNetwork(const std::string& name, } } +Error NeuralNetwork::getLayerOutputValue( + const std::string& layerName, + std::vector>* out) const { + auto& layers = this->config_.layers(); + auto it = std::find_if( + layers.begin(), layers.end(), [&layerName](const LayerConfig& conf) { + return conf.name() == layerName; + }); + if (it == layers.end()) { + return Error("Cannot find layer %s", layerName.c_str()); + } + auto& layer = this->getLayer(layerName); + out->reserve(4); + auto& argu = layer->getOutput(); + + if (argu.value) { + std::ostringstream os; + argu.value->print(os); + out->push_back({"value", os.str()}); + } + if (argu.ids) { + std::ostringstream os; + argu.ids->print(os, argu.ids->getSize()); + out->push_back({"ids", os.str()}); + } + if (auto startPos = argu.sequenceStartPositions) { + std::ostringstream os; + startPos->getVector(false)->print(os, startPos->getSize()); + out->push_back({"sequence pos", os.str()}); + } + if (auto subStartPos = argu.subSequenceStartPositions) { + std::ostringstream os; + subStartPos->getVector(false)->print(os, subStartPos->getSize()); + out->push_back({"sub-sequence pos", os.str()}); + } + return Error(); +} + } // namespace paddle diff --git a/paddle/gserver/gradientmachines/NeuralNetwork.h b/paddle/gserver/gradientmachines/NeuralNetwork.h index 25af4abcf81700..4d277d103f143d 100644 --- a/paddle/gserver/gradientmachines/NeuralNetwork.h +++ b/paddle/gserver/gradientmachines/NeuralNetwork.h @@ -128,6 +128,10 @@ class NeuralNetwork : public GradientMachine { static NeuralNetwork* newNeuralNetwork(const std::string& name = "", NeuralNetwork* rootNetwork = nullptr); + inline Error __must_check getLayerOutputValue( + const std::string& layerName, + std::vector>* out) const; + protected: /** * The constructor of NeuralNetwork. diff --git a/paddle/utils/Error.h b/paddle/utils/Error.h index 2b4fbef4e015e7..1ae202890f874c 100644 --- a/paddle/utils/Error.h +++ b/paddle/utils/Error.h @@ -116,6 +116,8 @@ class Error { */ operator bool() const { return msg_ == nullptr; } + bool isOK() const { return *this; } + /** * @brief check this status by glog. * @note It is a temp method used during cleaning Paddle code. It will be From 5b4e7d5cc7efe48d78036621318c6649294071d1 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sun, 19 Feb 2017 18:09:06 +0800 Subject: [PATCH 219/370] complete value printer --- paddle/gserver/evaluators/Evaluator.cpp | 90 ++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 10 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index 97b25b04c459eb..7ea4ed973cfa4f 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -13,9 +13,9 @@ See the License for the specific language governing permissions and limitations under the License. */ #include "paddle/gserver/evaluators/Evaluator.h" -#include "paddle/utils/Stat.h" - #include "paddle/gserver/gradientmachines/NeuralNetwork.h" +#include "paddle/utils/Stat.h" +#include "paddle/utils/StringUtil.h" DECLARE_int32(trainer_id); @@ -801,7 +801,9 @@ void PrecisionRecallEvaluator::getNames(std::vector* names) { real PrecisionRecallEvaluator::getValue(const std::string& name, Error* err) const { this->storeLocalValues(); - auto it = this->values_.find(name); + std::vector buffers; + paddle::str::split(name, '.', &buffers); + auto it = this->values_.find(buffers[buffers.size() - 1]); if (it != this->values_.end() && err != nullptr) { *err = Error("No such key %s", name.c_str()); return .0f; @@ -812,10 +814,12 @@ real PrecisionRecallEvaluator::getValue(const std::string& name, std::string PrecisionRecallEvaluator::getType(const std::string& name, Error* err) const { - this->storeLocalValues(); - auto it = this->values_.find(name); - if (it != this->values_.end() && err != nullptr) { - *err = Error("No such key %s", name.c_str()); + Error localErr; + if (err == nullptr) { + err = &localErr; + } + this->getValue(name, err); + if (!err->isOK()) { return ""; } return "precision_recall"; @@ -989,12 +993,12 @@ static InitFunction __reg_type_auc_sum__([]() { */ class ValuePrinter : public Evaluator { public: - ValuePrinter() {} - virtual void eval(const NeuralNetwork& nn) { + layerOutputs_.clear(); for (const std::string& name : config_.input_layers()) { auto& argu = nn.getLayer(name)->getOutput(); - std::unordered_map out; + layerOutputs_[name] = std::unordered_map(); + auto& out = layerOutputs_[name]; argu.getValueString(&out); for (auto field : {"value", "id", "sequence pos", "sub-sequence pos"}) { auto it = out.find(field); @@ -1008,6 +1012,72 @@ class ValuePrinter : public Evaluator { virtual void updateSamplesNum(const std::vector& arguments) {} virtual real evalImp(std::vector& arguments) { return 0; } + +private: + std::unordered_map> + layerOutputs_; + + // Evaluator interface +public: + void getNames(std::vector* names) { + for (auto layerIt = layerOutputs_.begin(); layerIt != layerOutputs_.end(); + ++layerIt) { + for (auto it = layerIt->second.begin(); it != layerIt->second.end(); + ++it) { + names->push_back(config_.name() + "." + layerIt->first + "." + + it->second); + } + } + } + + real getValue(const std::string& name, Error* err) const { + (void)(name); + if (err != nullptr) { + *err = Error( + "ValuePrinter do not support getValue, use getValueString instead."); + } + return .0f; + } + std::string getValueStr(const std::string& name, Error* err) const { + std::vector buffer; + str::split(name, '.', &buffer); + if (buffer.size() < 2) { + if (err != nullptr) { + *err = Error("No such key %s", name.c_str()); + } + return ""; + } + auto fieldName = buffer[buffer.size() - 1]; + auto layerName = buffer[buffer.size() - 2]; + auto layerIt = layerOutputs_.find(layerName); + if (layerIt == layerOutputs_.end()) { + if (err != nullptr) { + *err = Error("No such layer %s", layerName.c_str()); + } + return ""; + } + + auto fieldIt = layerIt->second.find(fieldName); + if (fieldIt == layerIt->second.end()) { + if (err != nullptr) { + *err = Error("No such value field %s", fieldName.c_str()); + } + return ""; + } + + return fieldIt->second; + } + std::string getType(const std::string& name, Error* err) const { + Error localErr; + if (err == nullptr) { + err = &localErr; + } + this->getValueStr(name, err); + if (!err->isOK()) { + return ""; + } + return "value_printer"; + } }; REGISTER_EVALUATOR(value_printer, ValuePrinter); /** From 5fd49f66657766cac11fd14a270b0b947a92c49d Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sun, 19 Feb 2017 18:12:49 +0800 Subject: [PATCH 220/370] Remove sequence information in GradientPrinter. * it is not necessary, because user could print sequence info by ValuePrinter. --- paddle/gserver/evaluators/Evaluator.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index ae7508e2bb117a..01363b583fa1f1 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -929,8 +929,6 @@ REGISTER_EVALUATOR(value_printer, ValuePrinter); */ class GradientPrinter : public Evaluator { public: - GradientPrinter() {} - virtual void eval(const NeuralNetwork& nn) { for (const std::string& name : config_.input_layers()) { const Argument& argu = nn.getLayer(name)->getOutput(); @@ -939,11 +937,6 @@ class GradientPrinter : public Evaluator { argu.grad->print(os); 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(); - } } } From e6232d82e1650dc2186fa39c93a06a7ef276fc52 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Sun, 19 Feb 2017 18:22:33 +0800 Subject: [PATCH 221/370] testing in mnist --- python/paddle/v2/__init__.py | 3 +- python/paddle/v2/data_converter.py | 50 ++++++++++++++---------------- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index bc064a21ae1502..4ecd0dafd6bc5a 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -20,7 +20,8 @@ import py_paddle.swig_paddle as api __all__ = [ - 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', 'event' + 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', + 'event', 'data_converter' ] diff --git a/python/paddle/v2/data_converter.py b/python/paddle/v2/data_converter.py index 45114b407dae22..afb98a77c5b315 100644 --- a/python/paddle/v2/data_converter.py +++ b/python/paddle/v2/data_converter.py @@ -13,8 +13,8 @@ # limitations under the License. import collections -import py_paddle.swig_paddle -import numpy +import py_paddle.swig_paddle as api +import numpy as np import paddle.trainer.PyDataProvider2 as dp2 __all__ = ['DataConverter'] @@ -50,12 +50,12 @@ def convert(self, data, argument): :param data: input data :type data: list | numpy array :param argument: the type which paddle is acceptable - :type argument: swig_paddle.Arguments + :type argument: Paddle's Arguments """ - assert isinstance(argument, swig_paddle.Arguments) - if data.dtype != numpy.float32: - data = data.astype(numpy.float32) - m = swig_paddle.Matrix.createDenseFromNumpy(data, True, False) + assert isinstance(argument, api.Arguments) + if data.dtype != np.float32: + data = data.astype(np.float32) + m = api.Matrix.createDenseFromNumpy(data, True, False) argument.setSlotValue(self.pos, m) @@ -72,17 +72,16 @@ def fill_csr(self, data): self.__height__ = len(data) for x in data: self.__rows__.append(self.__rows__[-1] + len(x)) - self__cols__ = data.flatten() + self.__cols__ = data.flatten() def convert(self, data, argument): - assert isinstance(argument, swig_paddle.Arguments) + assert isinstance(argument, api.Arguments) fill_csr(data) - m = swig_paddle.Matrix.createSparse(self.__height__, - self.input_type.dim, - len(self.__cols__), - len(self.__value__) == 0) - assert isinstance(m, swig_paddle.Matrix) + m = api.Matrix.createSparse(self.__height__, self.input_type.dim, + len(self.__cols__), + len(self.__value__) == 0) + assert isinstance(m, api.Matrix) m.sparseCopyFrom(self.__rows__, self.__cols__, self.__value__) argument.setSlotValue(self.pos, m) @@ -105,9 +104,9 @@ def __init__(self, input_type, pos): self.__ids__ = [] def convert(self, data, argument): - assert isinstance(argument, swig_paddle.Arguments) + assert isinstance(argument, api.Arguments) self.__ids__ = data.flatten() - ids = swig_paddle.IVector.create(self.__ids__) + ids = api.IVector.create(self.__ids__) argument.setSlotIds(self.pos, ids) @@ -135,7 +134,7 @@ def fill_seq(self, data): def convert(self, data, argument): fill_seq(data) - seq = swig_paddle.IVector.create(self.__seq__, False) + seq = api.IVector.create(self.__seq__, False) self.__setter__(argument, self.pos, seq) dat = [] @@ -151,22 +150,21 @@ def get_size(self, data): class DataConverter(object): - def __init__(self, input_mapper): + def __init__(self, input): """ Usege: .. code-block:: python inputs = [('image', dense_vector), ('label', integer_value)] cvt = DataConverter(inputs) - arg = cvt.convert(minibatch_data, {'image':0, 'label':1}) + arg = cvt(minibatch_data, {'image':0, 'label':1}) :param input_mapper: list of (input_name, input_type) :type input_mapper: list """ - assert isinstance(self.input_types, collections.Sequence) self.input_names = [] self.input_types = [] - for each in self.input_types: + for each in input: self.input_names.append(each[0]) self.input_types.append(each[1]) assert isinstance(each[1], dp2.InputType) @@ -186,16 +184,16 @@ def convert(self, data, input_dict=None, argument=None): the feature order in argument and data is the same. :type input_dict: dict, like {string:integer, string, integer, ...}|None :param argument: converted data will be saved in this argument. If None, - it will create a swig_paddle.Arguments firstly. + it will create a Paddle's Arguments firstly. :param type: swig_paddle.Arguments|None """ if argument is None: - argument = swig_paddle.Arguments.createArguments(0) - assert isinstance(argument, swig_paddle.Arguments) + argument = api.Arguments.createArguments(0) + assert isinstance(argument, api.Arguments) argument.resize(len(self.input_types)) converts = [ - DataConverter.create_scanner(i, each_type) + DataConverter.create_converter(i, each_type) for i, each_type in enumerate(self.input_types) ] @@ -212,7 +210,7 @@ def __call__(self, dat, argument=None): return self.convert(dat, argument) @staticmethod - def create_scanner(pos, each): + def create_converter(pos, each): assert isinstance(each, dp2.InputType) retv = None if each.type == dp2.DataType.Dense: From 6deb33d9dcd3db9203b98de0f6fb0d0e83cc2176 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sun, 19 Feb 2017 20:21:13 +0800 Subject: [PATCH 222/370] Complete combined evaluator --- paddle/gserver/evaluators/Evaluator.cpp | 32 ++++++++++--- paddle/gserver/evaluators/Evaluator.h | 20 ++++++++- .../gradientmachines/NeuralNetwork.cpp | 45 ++++++++++++++++++- 3 files changed, 89 insertions(+), 8 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index cde47f572092f5..29b5284fe59b5d 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -102,6 +102,10 @@ class ClassificationErrorEvaluator : public Evaluator { virtual void distributeEval(ParameterClient2* client) { mergeResultsOfAllClients(client); } + + // Evaluator interface +protected: + std::string getTypeImpl() const { return "classification_error"; } }; /** @@ -140,6 +144,10 @@ class SequenceClassificationErrorEvaluator virtual void distributeEval(ParameterClient2* client) { mergeResultsOfAllClients(client); } + + // Evaluator interface +protected: + std::string getTypeImpl() const { return "seq_classification_error"; } }; REGISTER_EVALUATOR(seq_classification_error, SequenceClassificationErrorEvaluator); @@ -230,6 +238,10 @@ class SumEvaluator : public Evaluator { private: IVectorPtr cpuLabel_; MatrixPtr cpuWeight_; + + // Evaluator interface +protected: + std::string getTypeImpl() const { return "sum"; } }; /** * @brief column sum Evaluator @@ -337,10 +349,18 @@ class ColumnSumEvaluator : public Evaluator { } private: - ColumnSumEvaluator() {} int32_t colIdx_; size_t colNum_; MatrixPtr sum_; /* cpu matrix */ + + // Evaluator interface +protected: + std::string getTypeImpl() const { + if (colIdx_ == -1) + return "last-column-sum"; + else + return "column-sum"; + } }; void AucEvaluator::start() { @@ -791,7 +811,6 @@ void PrecisionRecallEvaluator::storeLocalValues() const { void PrecisionRecallEvaluator::getNames(std::vector* names) { this->storeLocalValues(); - names->clear(); names->reserve(this->values_.size()); for (auto it = this->values_.begin(); it != this->values_.end(); ++it) { names->push_back(this->config_.name() + "." + it->first); @@ -1080,12 +1099,13 @@ class ValuePrinter : public Evaluator { } }; REGISTER_EVALUATOR(value_printer, ValuePrinter); + /** * @brief print gradient of each layer. * * The config file api is gradient_printer_evaluator. */ -class GradientPrinter : public Evaluator { +class GradientPrinter : public NotGetableEvaluator { public: virtual void eval(const NeuralNetwork& nn) { for (const std::string& name : config_.input_layers()) { @@ -1108,7 +1128,7 @@ REGISTER_EVALUATOR(gradient_printer, GradientPrinter); * * The config file api is maxid_printer_evaluator. */ -class MaxIdPrinter : public Evaluator { +class MaxIdPrinter : public NotGetableEvaluator { private: IVectorPtr maxIds_; MatrixPtr maxValues_; @@ -1150,7 +1170,7 @@ REGISTER_EVALUATOR(max_id_printer, MaxIdPrinter); * * The config file api is maxframe_printer_evaluator. */ -class MaxFramePrinter : public Evaluator { +class MaxFramePrinter : public NotGetableEvaluator { private: IVectorPtr maxIds_; MatrixPtr maxValues_; @@ -1237,7 +1257,7 @@ REGISTER_EVALUATOR(max_frame_printer, MaxFramePrinter); * The config file api is seqtext_printer_evaluator. * */ -class SequenceTextPrinter : public Evaluator { +class SequenceTextPrinter : public NotGetableEvaluator { private: /// dict_file, which contains a list of tokens std::vector dict_; diff --git a/paddle/gserver/evaluators/Evaluator.h b/paddle/gserver/evaluators/Evaluator.h index bec3d6e66820fa..d5b2a63e35e157 100644 --- a/paddle/gserver/evaluators/Evaluator.h +++ b/paddle/gserver/evaluators/Evaluator.h @@ -119,7 +119,6 @@ class Evaluator { static ClassRegistrar registrar_; virtual void getNames(std::vector* names) { - names->clear(); names->push_back(config_.name()); } @@ -168,6 +167,25 @@ class Evaluator { double totalScore_; }; +class NotGetableEvaluator : public Evaluator { + // Evaluator interface +public: + void getNames(std::vector* names) {} + + real getValue(const std::string& name, Error* err) const { + if (err != nullptr) { + *err = Error("Not implemented"); + } + return .0f; + } + std::string getType(const std::string& name, Error* err) const { + if (err != nullptr) { + *err = Error("Not implemented"); + } + return ""; + } +}; + class DummyEvaluator : public Evaluator { public: DummyEvaluator() {} diff --git a/paddle/gserver/gradientmachines/NeuralNetwork.cpp b/paddle/gserver/gradientmachines/NeuralNetwork.cpp index 22051e07ee0026..277fb6d8db13ce 100644 --- a/paddle/gserver/gradientmachines/NeuralNetwork.cpp +++ b/paddle/gserver/gradientmachines/NeuralNetwork.cpp @@ -306,7 +306,6 @@ void NeuralNetwork::onPassEnd() { class CombinedEvaluator : public Evaluator { public: - CombinedEvaluator() {} void addEvaluator(std::unique_ptr&& evaluator) { evaluators_.emplace_back(std::move(evaluator)); } @@ -346,6 +345,50 @@ class CombinedEvaluator : public Evaluator { protected: std::vector> evaluators_; + + // Evaluator interface +public: + void getNames(std::vector* names) { + for (auto& eval : evaluators_) { + eval->getNames(names); + } + } + + real getValue(const std::string& name, Error* err) const { + return this->getMethodHelper( + name, err, [&name, err](const std::unique_ptr& eval) { + return eval->getValue(name, err); + }); + } + std::string getValueStr(const std::string& name, Error* err) const { + return this->getMethodHelper( + name, err, [&name, err](const std::unique_ptr& eval) { + return eval->getValueStr(name, err); + }); + } + std::string getType(const std::string& name, Error* err) const { + return this->getMethodHelper( + name, err, [&name, err](const std::unique_ptr& eval) { + return eval->getType(name, err); + }); + } + +private: + template + T getMethodHelper(const std::string& name, + Error* err, + const std::function&)>& + callback) const { + for (auto& eval : evaluators_) { + std::vector names; + eval->getNames(&names); + if (std::find(names.begin(), names.end(), name) != names.end()) { + return callback(eval); + } + } + if (err != nullptr) *err = Error("No such key %s", name.c_str()); + return T(); + } }; Evaluator* NeuralNetwork::makeEvaluator() const { From 1100366803c10aa9cbd7265616d286e1b38681c0 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sun, 19 Feb 2017 20:43:04 +0800 Subject: [PATCH 223/370] Add unittests & fix some bugs. --- paddle/gserver/evaluators/CTCErrorEvaluator.cpp | 2 +- paddle/gserver/evaluators/Evaluator.cpp | 6 ++++-- paddle/gserver/tests/test_Evaluator.cpp | 12 ++++++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/paddle/gserver/evaluators/CTCErrorEvaluator.cpp b/paddle/gserver/evaluators/CTCErrorEvaluator.cpp index 05aa6c012ae2bc..132119015f967c 100644 --- a/paddle/gserver/evaluators/CTCErrorEvaluator.cpp +++ b/paddle/gserver/evaluators/CTCErrorEvaluator.cpp @@ -20,7 +20,7 @@ namespace paddle { /** * calculate sequence-to-sequence edit distance */ -class CTCErrorEvaluator : public Evaluator { +class CTCErrorEvaluator : public NotGetableEvaluator { private: MatrixPtr outActivations_; int numTimes_, numClasses_, numSequences_, blank_; diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index 29b5284fe59b5d..42a877954b6c3e 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -823,8 +823,10 @@ real PrecisionRecallEvaluator::getValue(const std::string& name, std::vector buffers; paddle::str::split(name, '.', &buffers); auto it = this->values_.find(buffers[buffers.size() - 1]); - if (it != this->values_.end() && err != nullptr) { - *err = Error("No such key %s", name.c_str()); + if (it == this->values_.end()) { // not found + if (err != nullptr) { + *err = Error("No such key %s", name.c_str()); + } return .0f; } diff --git a/paddle/gserver/tests/test_Evaluator.cpp b/paddle/gserver/tests/test_Evaluator.cpp index 8165eb82693361..100cf078095092 100644 --- a/paddle/gserver/tests/test_Evaluator.cpp +++ b/paddle/gserver/tests/test_Evaluator.cpp @@ -110,6 +110,18 @@ void testEvaluator(TestConfig testConf, testEvaluator->finish(); LOG(INFO) << *testEvaluator; + std::vector names; + testEvaluator->getNames(&names); + paddle::Error err; + for (auto& name : names) { + auto value = testEvaluator->getValueStr(name, &err); + ASSERT_TRUE(err.isOK()); + LOG(INFO) << name << " " << value; + auto tp = testEvaluator->getType(name, &err); + ASSERT_TRUE(err.isOK()); + ASSERT_EQ(testConf.evaluatorConfig.type(), tp); + } + double totalScore2 = 0.0; if (testConf.testAccumulate) { testEvaluator->start(); From 948218dab96369b24027c801b61cad699db7b4c6 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 20 Feb 2017 14:08:35 +0800 Subject: [PATCH 224/370] Unify PrintLogic in PrintLayer/ValuePrinter. --- paddle/gserver/evaluators/Evaluator.cpp | 13 ++----------- paddle/gserver/layers/PrintLayer.cpp | 24 ++++++++---------------- paddle/parameter/Argument.cpp | 12 ++++++++++++ paddle/parameter/Argument.h | 3 +++ 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index 1a43d3bd996109..1b06519713dbba 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -888,19 +888,10 @@ Evaluator* Evaluator::create(const EvaluatorConfig& config) { */ class ValuePrinter : public Evaluator { public: - ValuePrinter() {} - virtual void eval(const NeuralNetwork& nn) { for (const std::string& name : config_.input_layers()) { - auto& argu = nn.getLayer(name)->getOutput(); - std::unordered_map out; - argu.getValueString(&out); - for (auto field : {"value", "id", "sequence pos", "sub-sequence pos"}) { - auto it = out.find(field); - if (it != out.end()) { - LOG(INFO) << "layer=" << name << " " << field << ":\n" << it->second; - } - } + nn.getLayer(name)->getOutput().printValueString(LOG(INFO), + "layer=" + name + " "); } } diff --git a/paddle/gserver/layers/PrintLayer.cpp b/paddle/gserver/layers/PrintLayer.cpp index f1f3dd412c67a9..de198af111be42 100644 --- a/paddle/gserver/layers/PrintLayer.cpp +++ b/paddle/gserver/layers/PrintLayer.cpp @@ -19,25 +19,17 @@ namespace paddle { class PrintLayer : public Layer { public: explicit PrintLayer(const LayerConfig& config) : Layer(config) {} - void forward(PassType passType) override; - void backward(const UpdateCallback& callback) override {} -}; -void PrintLayer::forward(PassType passType) { - Layer::forward(passType); - for (size_t i = 0; i != inputLayers_.size(); ++i) { - auto& argu = getInput(i); - const std::string& name = inputLayers_[i]->getName(); - std::unordered_map out; - argu.getValueString(&out); - for (auto field : {"value", "id", "sequence pos", "sub-sequence pos"}) { - auto it = out.find(field); - if (it != out.end()) { - LOG(INFO) << "layer=" << name << " " << field << ":\n" << it->second; - } + void forward(PassType passType) override { + Layer::forward(passType); + for (size_t i = 0; i != inputLayers_.size(); ++i) { + getInput(i).printValueString(LOG(INFO), + "layer=" + inputLayers_[i]->getName() + " "); } } -} + + void backward(const UpdateCallback& callback) override {} +}; REGISTER_LAYER(print, PrintLayer); diff --git a/paddle/parameter/Argument.cpp b/paddle/parameter/Argument.cpp index e9de0f66987603..7a343cca33f5b4 100644 --- a/paddle/parameter/Argument.cpp +++ b/paddle/parameter/Argument.cpp @@ -628,6 +628,18 @@ void Argument::getValueString( } } +void Argument::printValueString(std::ostream& stream, + const std::string& prefix) const { + std::unordered_map out; + getValueString(&out); + for (auto field : {"value", "id", "sequence pos", "sub-sequence pos"}) { + auto it = out.find(field); + if (it != out.end()) { + stream << prefix << field << ":\n" << it->second; + } + } +} + void Argument::subArgFrom(const Argument& input, size_t offset, size_t height, diff --git a/paddle/parameter/Argument.h b/paddle/parameter/Argument.h index c751dbb855d31d..e2a8500c3f82a1 100644 --- a/paddle/parameter/Argument.h +++ b/paddle/parameter/Argument.h @@ -305,6 +305,9 @@ struct Argument { * @param out [out]: the return values. */ void getValueString(std::unordered_map* out) const; + + void printValueString(std::ostream& stream, + const std::string& prefix = "") const; }; } // namespace paddle From b5b9a9cfb797db957d51b2dc5fc6a7d45d90e46b Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 20 Feb 2017 14:17:18 +0800 Subject: [PATCH 225/370] Add comments --- paddle/parameter/Argument.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/paddle/parameter/Argument.h b/paddle/parameter/Argument.h index e2a8500c3f82a1..178c068b93ac5f 100644 --- a/paddle/parameter/Argument.h +++ b/paddle/parameter/Argument.h @@ -306,6 +306,12 @@ struct Argument { */ void getValueString(std::unordered_map* out) const; + /** + * @brief printValueString will print the argument's output in order of + * 'value', 'id', 'sequence pos', 'sub-sequence pos'. + * @param stream: Output stream + * @param prefix: line prefix for printing. + */ void printValueString(std::ostream& stream, const std::string& prefix = "") const; }; From f846e8fec2e9c8d16e24e12d6b6b7efc77d3cc83 Mon Sep 17 00:00:00 2001 From: liaogang Date: Mon, 20 Feb 2017 15:13:43 +0800 Subject: [PATCH 226/370] Add const for getLayerOutput --- paddle/gserver/gradientmachines/GradientMachine.h | 2 +- .../gradientmachines/MultiGradientMachine.cpp | 12 ++++++------ .../gserver/gradientmachines/MultiGradientMachine.h | 2 +- paddle/gserver/gradientmachines/NeuralNetwork.cpp | 2 +- paddle/gserver/gradientmachines/NeuralNetwork.h | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/paddle/gserver/gradientmachines/GradientMachine.h b/paddle/gserver/gradientmachines/GradientMachine.h index a814e771d12e3a..5469c0d89f4964 100644 --- a/paddle/gserver/gradientmachines/GradientMachine.h +++ b/paddle/gserver/gradientmachines/GradientMachine.h @@ -134,7 +134,7 @@ class GradientMachine { backward(callback); } - virtual MatrixPtr getLayerOutput(const std::string& layerName) { + virtual MatrixPtr getLayerOutput(const std::string& layerName) const { return nullptr; } diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp index 7e60920376d195..2d42e648302f16 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp @@ -282,7 +282,8 @@ void MultiGradientMachine::forwardBackward(const std::vector& inArgs, backwardImp(callback); } -MatrixPtr MultiGradientMachine::getLayerOutput(const std::string& layerName) { +MatrixPtr MultiGradientMachine::getLayerOutput( + const std::string& layerName) const { // each thread has the same neural network auto nn = threads_[0]->getGradientMachine(); size_t height = 0; @@ -301,11 +302,10 @@ MatrixPtr MultiGradientMachine::getLayerOutput(const std::string& layerName) { // copy one layer output from one trainer thread at each time size_t startRow = 0; - - for (size_t i = 0; i < threads_.size(); i++) { - auto tmpMatrix = layerOutput->subMatrix(startRow, mats[i]->getHeight()); - tmpMatrix->copyFrom(*mats[i]); - startRow += mats[i]->getHeight(); + for (auto& mat : mats) { + auto tmpMatrix = layerOutput->subMatrix(startRow, mat->getHeight()); + tmpMatrix->copyFrom(*mat); + startRow += mat->getHeight(); } return layerOutput; diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.h b/paddle/gserver/gradientmachines/MultiGradientMachine.h index 988d5098179806..a1a2d417062de5 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.h +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.h @@ -189,7 +189,7 @@ class MultiGradientMachine : public GradientMachine { PassType passType, const UpdateCallback& callback); - virtual MatrixPtr getLayerOutput(const std::string& layerName); + virtual MatrixPtr getLayerOutput(const std::string& layerName) const; virtual void onPassEnd(); diff --git a/paddle/gserver/gradientmachines/NeuralNetwork.cpp b/paddle/gserver/gradientmachines/NeuralNetwork.cpp index 1f9ace4f67fdca..00887c81d47687 100644 --- a/paddle/gserver/gradientmachines/NeuralNetwork.cpp +++ b/paddle/gserver/gradientmachines/NeuralNetwork.cpp @@ -293,7 +293,7 @@ void NeuralNetwork::backward(const UpdateCallback& callback) { } } -MatrixPtr NeuralNetwork::getLayerOutput(const std::string& layerName) { +MatrixPtr NeuralNetwork::getLayerOutput(const std::string& layerName) const { auto it = layerMap_.find(layerName); CHECK(it != layerMap_.end()) << "Cannot find layer: " << layerName; return it->second->getOutputValue(); diff --git a/paddle/gserver/gradientmachines/NeuralNetwork.h b/paddle/gserver/gradientmachines/NeuralNetwork.h index bf9ed09327f2f1..6ecc251a409cb9 100644 --- a/paddle/gserver/gradientmachines/NeuralNetwork.h +++ b/paddle/gserver/gradientmachines/NeuralNetwork.h @@ -87,7 +87,7 @@ class NeuralNetwork : public GradientMachine { virtual void backward(const UpdateCallback& callback = nullptr); - virtual MatrixPtr getLayerOutput(const std::string& layerName); + virtual MatrixPtr getLayerOutput(const std::string& layerName) const; const LayerPtr& getLayer(const std::string& layerName) const { auto it = layerMap_.find(layerName); From 27a42c2e3bce8818c55b7ec7e74290151aa5ff96 Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Mon, 20 Feb 2017 14:25:53 +0800 Subject: [PATCH 227/370] add SequenceConcatLayer in trainer_config_helpers --- paddle/gserver/layers/SequenceConcatLayer.cpp | 6 ++- .../paddle/trainer_config_helpers/layers.py | 51 +++++++++++++++++++ .../tests/configs/file_list.sh | 3 +- .../configs/protostr/test_seq_concat.protostr | 39 ++++++++++++++ .../tests/configs/test_seq_concat.py | 9 ++++ 5 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat.protostr create mode 100644 python/paddle/trainer_config_helpers/tests/configs/test_seq_concat.py diff --git a/paddle/gserver/layers/SequenceConcatLayer.cpp b/paddle/gserver/layers/SequenceConcatLayer.cpp index 599706eb419ede..4b24d8f0c852e1 100644 --- a/paddle/gserver/layers/SequenceConcatLayer.cpp +++ b/paddle/gserver/layers/SequenceConcatLayer.cpp @@ -21,9 +21,11 @@ namespace paddle { /** * A layer for concatenating the first sequence with the second sequence - * following the first - * Input: two sequences each containing some instances + * Input: two sequences each containing the same number of instances + * seq1 = [a1, a2, ..., an] + * seq2 = [b1, b2, ..., bn] * Output: a concatenated sequence of the two input sequences + * out = [a1, b1, a2, b2, ..., an, bn] */ class SequenceConcatLayer : public Layer { diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 1fdc4c46236371..ce9213a5c015a3 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -59,6 +59,7 @@ 'img_cmrnorm_layer', 'addto_layer', 'concat_layer', + 'seq_concat_layer', 'lstm_step_layer', 'recurrent_group', 'memory', @@ -144,6 +145,7 @@ class LayerType(object): CONCAT_LAYER = 'concat' CONCAT_PROJ_LAYER = 'concat2' + SEQUENCE_CONCAT_LAYER = 'seqconcat' LSTM_STEP_LAYER = 'lstm_step' GRU_STEP_LAYER = 'gru_step' @@ -2570,6 +2572,55 @@ def __reduce_concat_type__(a, b): size=sz) +@wrap_name_default("seqconcat") +@wrap_act_default(act=IdentityActivation()) +@layer_support() +def seq_concat_layer(a, b, act=None, name=None, layer_attr=None, + bias_attr=None): + """ + Concat sequence a with sequence b. + Inputs: a = [a1, a2, ..., an] + b = [b1, b2, ..., bn] + Note that the length of a and b should be the same. + Output: [a1, b1, a2, b2, ..., an, bn] + + The example usage is: + + .. code-block:: python + + concat = seq_concat_layer(a=layer1, b=layer2) + + :param name: Layer name. + :type name: basestring + :param a: input sequence layer + :type a: LayerOutput + :param b: input sequence layer + :type b: LayerOutput + :param act: Activation type. + :type act: BaseActivation + :param layer_attr: Extra Layer Attribute. + :type layer_attr: ExtraLayerAttribute + :return: LayerOutput object. + :rtype: LayerOutput + """ + assert isinstance(a, LayerOutput) and isinstance(b, LayerOutput) + assert a.size == b.size + Layer( + name=name, + type=LayerType.SEQUENCE_CONCAT_LAYER, + inputs=[a.name, b.name], + active_type=act.name, + bias=ParamAttr.to_bias(bias_attr), + **ExtraLayerAttribute.to_kwargs(layer_attr)) + + return LayerOutput( + name, + layer_type=LayerType.SEQUENCE_CONCAT_LAYER, + parents=[a, b], + activation=act, + size=a.size) + + def memory(name, size, is_seq=False, diff --git a/python/paddle/trainer_config_helpers/tests/configs/file_list.sh b/python/paddle/trainer_config_helpers/tests/configs/file_list.sh index ea46b557a26ce6..55cef6be0c630c 100755 --- a/python/paddle/trainer_config_helpers/tests/configs/file_list.sh +++ b/python/paddle/trainer_config_helpers/tests/configs/file_list.sh @@ -4,6 +4,7 @@ test_sequence_pooling test_lstmemory_layer test_grumemory_layer last_first_seq test_expand_layer test_ntm_layers test_hsigmoid img_layers img_trans_layers util_layers simple_rnn_layers unused_layers test_cost_layers test_rnn_group shared_fc shared_lstm shared_gru test_cost_layers_with_weight -test_spp_layer test_bilinear_interp test_maxout test_bi_grumemory math_ops) +test_spp_layer test_bilinear_interp test_maxout test_bi_grumemory math_ops +test_seq_concat) export whole_configs=(test_split_datasource) diff --git a/python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat.protostr b/python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat.protostr new file mode 100644 index 00000000000000..2fa55e87b5d13c --- /dev/null +++ b/python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat.protostr @@ -0,0 +1,39 @@ +type: "nn" +layers { + name: "data1" + type: "data" + size: 30 + active_type: "" +} +layers { + name: "data2" + type: "data" + size: 30 + active_type: "" +} +layers { + name: "__seqconcat_0__" + type: "seqconcat" + size: 30 + active_type: "" + inputs { + input_layer_name: "data1" + } + inputs { + input_layer_name: "data2" + } +} +input_layer_names: "data1" +input_layer_names: "data2" +output_layer_names: "__seqconcat_0__" +sub_models { + name: "root" + layer_names: "data1" + layer_names: "data2" + layer_names: "__seqconcat_0__" + input_layer_names: "data1" + input_layer_names: "data2" + output_layer_names: "__seqconcat_0__" + is_recurrent_layer_group: false +} + diff --git a/python/paddle/trainer_config_helpers/tests/configs/test_seq_concat.py b/python/paddle/trainer_config_helpers/tests/configs/test_seq_concat.py new file mode 100644 index 00000000000000..193d9d0df9ed80 --- /dev/null +++ b/python/paddle/trainer_config_helpers/tests/configs/test_seq_concat.py @@ -0,0 +1,9 @@ +from paddle.trainer_config_helpers import * + +settings(batch_size=1000, learning_rate=1e-5) + +din1 = data_layer(name='data1', size=30) + +din2 = data_layer(name='data2', size=30) + +outputs(seq_concat_layer(a=din1, b=din2)) From 686b74651d6c123d70dd07157af7ab905d5a4796 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Mon, 20 Feb 2017 16:04:10 +0800 Subject: [PATCH 228/370] filter the illegal sentences. --- demo/sentiment/dataprovider.py | 2 ++ demo/sentiment/predict.py | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/demo/sentiment/dataprovider.py b/demo/sentiment/dataprovider.py index 00f72cecacb454..4b7f5d0e504aef 100755 --- a/demo/sentiment/dataprovider.py +++ b/demo/sentiment/dataprovider.py @@ -32,4 +32,6 @@ def process(settings, file_name): word_slot = [ settings.word_dict[w] for w in words if w in settings.word_dict ] + if not word_slot: + continue yield word_slot, label diff --git a/demo/sentiment/predict.py b/demo/sentiment/predict.py index 8ec490f6469192..64c78e0d6b9297 100755 --- a/demo/sentiment/predict.py +++ b/demo/sentiment/predict.py @@ -138,7 +138,11 @@ def main(): batch = [] 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: predict.batch_predict(batch) batch = [] From 47043fe1d3a511e0c88625ff4382adb1fea0feb8 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 20 Feb 2017 16:15:22 +0800 Subject: [PATCH 229/370] add type to datalayer --- demo/mnist/api_train.py | 4 ++-- python/paddle/v2/layer.py | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/demo/mnist/api_train.py b/demo/mnist/api_train.py index fe39f0bd23f78e..77e6fa89003b6f 100644 --- a/demo/mnist/api_train.py +++ b/demo/mnist/api_train.py @@ -71,8 +71,8 @@ def main(): assert isinstance(updater, api.ParameterUpdater) # define network - images = paddle_v2.layer.data(name='pixel', size=784) - label = paddle_v2.layer.data(name='label', size=10) + images = paddle_v2.layer.data(name='pixel', type=dp.dense_vector(784)) + label = paddle_v2.layer.data(name='label', type=dp.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, diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 0ce4ecd569aa1d..e006b789222c01 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -67,6 +67,7 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. """ import paddle.trainer_config_helpers as conf_helps +import paddle.trainer.PyDataProvider2 as dp from paddle.trainer_config_helpers.config_parser_utils import \ parse_network_config as __parse__ from paddle.trainer_config_helpers.default_decorators import wrap_name_default @@ -157,7 +158,37 @@ def to_proto_impl(self, **kwargs): return V2LayerImpl -data = __convert_to_v2__('data_layer', None, []) +""" +Some layer may need some special config, and can not use __convert_to_v2__ to convert. +So we also need to implement some special LayerV2. +""" + + +class DataLayerV2(Layer): + def __init__(self, name, type, **kwargs): + self.__method_name__ = 'data_layer' + + assert isinstance(type, dp.InputType) + + # get data_size from type.dim + args = dict() + for key in kwargs: + args[key] = kwargs[key] + args['size'] = type.dim + self.__args__ = args + + super(DataLayerV2, self).__init__(name=name, parent_layers=dict()) + + def to_proto_impl(self, **kwargs): + args = dict() + for each in kwargs: + args[each] = kwargs[each] + for each in self.__args__: + args[each] = self.__args__[each] + return getattr(conf_helps, self.__method_name__)(name=self.name, **args) + + +data = DataLayerV2 fc = __convert_to_v2__('fc_layer', name_prefix='fc', parent_names=['input']) max_id = __convert_to_v2__( 'maxid_layer', name_prefix='maxid_layer', parent_names=['input']) @@ -171,8 +202,8 @@ def to_proto_impl(self, **kwargs): parent_names=['input', 'label']) if __name__ == '__main__': - pixel = data(name='pixel', size=784) - label = data(name='label', size=10) + pixel = data(name='pixel', type=dp.dense_vector(784)) + label = data(name='label', type=dp.integer_value(10)) hidden = fc(input=pixel, size=100, act=conf_helps.SigmoidActivation()) inference = fc(input=hidden, size=10, act=conf_helps.SoftmaxActivation()) maxid = max_id(input=inference) From 3b69629d3299543bd4f1f0e08794cd4a335609b9 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 20 Feb 2017 16:18:29 +0800 Subject: [PATCH 230/370] modify api_train_v2 --- demo/mnist/api_train_v2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index b5cc74ce67dfc8..979cc3f1b9eb22 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -16,8 +16,8 @@ def main(): paddle.init(use_gpu=False, trainer_count=1) # define network topology - images = paddle.layer.data(name='pixel', size=784) - label = paddle.layer.data(name='label', size=10) + images = paddle.layer.data(name='pixel', type=dense_vector(784)) + label = paddle.layer.data(name='label', 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, From 772b476b76e0436de286922e8486fb21f928e8fc Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 20 Feb 2017 16:38:08 +0800 Subject: [PATCH 231/370] optimize code --- demo/mnist/api_train.py | 4 ++-- demo/mnist/api_train_v2.py | 4 ++-- python/paddle/v2/layer.py | 24 ++++++++++-------------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/demo/mnist/api_train.py b/demo/mnist/api_train.py index 77e6fa89003b6f..ae00e9f54c3a0e 100644 --- a/demo/mnist/api_train.py +++ b/demo/mnist/api_train.py @@ -71,8 +71,8 @@ def main(): assert isinstance(updater, api.ParameterUpdater) # define network - images = paddle_v2.layer.data(name='pixel', type=dp.dense_vector(784)) - label = paddle_v2.layer.data(name='label', type=dp.integer_value(10)) + images = paddle_v2.layer.data(name='pixel', data_type=dp.dense_vector(784)) + label = paddle_v2.layer.data(name='label', data_type=dp.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, diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 979cc3f1b9eb22..b46cf1c8700ba8 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -16,8 +16,8 @@ def main(): paddle.init(use_gpu=False, trainer_count=1) # define network topology - images = paddle.layer.data(name='pixel', type=dense_vector(784)) - label = paddle.layer.data(name='label', type=integer_value(10)) + images = paddle.layer.data(name='pixel', data_type=dense_vector(784)) + label = paddle.layer.data(name='label', 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, diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index e006b789222c01..511b3e7457c261 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -165,26 +165,22 @@ def to_proto_impl(self, **kwargs): class DataLayerV2(Layer): - def __init__(self, name, type, **kwargs): - self.__method_name__ = 'data_layer' - - assert isinstance(type, dp.InputType) + def __init__(self, name, data_type, **kwargs): + assert isinstance(data_type, dp.InputType) - # get data_size from type.dim - args = dict() - for key in kwargs: - args[key] = kwargs[key] - args['size'] = type.dim - self.__args__ = args + self.__method_name__ = 'data_layer' + self.__kwargs__ = kwargs + self.__data_size__ = data_type.dim super(DataLayerV2, self).__init__(name=name, parent_layers=dict()) def to_proto_impl(self, **kwargs): args = dict() + args['size'] = self.__data_size__ for each in kwargs: args[each] = kwargs[each] - for each in self.__args__: - args[each] = self.__args__[each] + for each in self.__kwargs__: + args[each] = self.__kwargs__[each] return getattr(conf_helps, self.__method_name__)(name=self.name, **args) @@ -202,8 +198,8 @@ def to_proto_impl(self, **kwargs): parent_names=['input', 'label']) if __name__ == '__main__': - pixel = data(name='pixel', type=dp.dense_vector(784)) - label = data(name='label', type=dp.integer_value(10)) + pixel = data(name='pixel', data_type=dp.dense_vector(784)) + label = data(name='label', data_type=dp.integer_value(10)) hidden = fc(input=pixel, size=100, act=conf_helps.SigmoidActivation()) inference = fc(input=hidden, size=10, act=conf_helps.SoftmaxActivation()) maxid = max_id(input=inference) From 89cfb39fe450faeb71fc00d13a6421824a43b646 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 20 Feb 2017 16:44:58 +0800 Subject: [PATCH 232/370] use data_type of data layer --- demo/mnist/api_train.py | 2 +- demo/mnist/api_train_v2.py | 4 ++-- python/paddle/v2/layer.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/demo/mnist/api_train.py b/demo/mnist/api_train.py index ae00e9f54c3a0e..c6993eda38bd02 100644 --- a/demo/mnist/api_train.py +++ b/demo/mnist/api_train.py @@ -99,7 +99,7 @@ def main(): # DataProvider Converter is a utility convert Python Object to Paddle C++ # Input. The input format is as same as Paddle's DataProvider. converter = DataProviderConverter( - input_types=[dp.dense_vector(784), dp.integer_value(10)]) + input_types=[images.data_type, label.data_type]) train_file = './data/raw_data/train' test_file = './data/raw_data/t10k' diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index b46cf1c8700ba8..6bbc3a4ab35a64 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -51,8 +51,8 @@ def event_handler(event): 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': dense_vector(784), - 'label': integer_value(10) + 'pixel': images.data_type, + 'label': label.data_type }) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 511b3e7457c261..f2bc47946b6df8 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -168,15 +168,15 @@ class DataLayerV2(Layer): def __init__(self, name, data_type, **kwargs): assert isinstance(data_type, dp.InputType) + self.data_type = data_type self.__method_name__ = 'data_layer' self.__kwargs__ = kwargs - self.__data_size__ = data_type.dim super(DataLayerV2, self).__init__(name=name, parent_layers=dict()) def to_proto_impl(self, **kwargs): args = dict() - args['size'] = self.__data_size__ + args['size'] = self.data_type.dim for each in kwargs: args[each] = kwargs[each] for each in self.__kwargs__: From bb751b7f2c274879fdc91cb5f84fb1d60b608faf Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 20 Feb 2017 15:20:14 +0800 Subject: [PATCH 233/370] Add documentation for codes. * also remove unused getValueStr --- paddle/gserver/evaluators/Evaluator.h | 71 ++++++++++++++----- .../gradientmachines/NeuralNetwork.cpp | 17 +++-- paddle/gserver/tests/test_Evaluator.cpp | 2 +- 3 files changed, 67 insertions(+), 23 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.h b/paddle/gserver/evaluators/Evaluator.h index d5b2a63e35e157..a5694a088c3c44 100644 --- a/paddle/gserver/evaluators/Evaluator.h +++ b/paddle/gserver/evaluators/Evaluator.h @@ -118,33 +118,55 @@ class Evaluator { static ClassRegistrar registrar_; + /** + * @brief getNames will return all field names of current evaluator. + * + * The format of name is `evaluator_name.evaluator_fields`. If the evaluator + * has multiple field, the name could be `evaluator_name.field1`. For example + * the PrecisionRecallEvaluator contains `precision`, `recall` fields. The get + * names will return `precision_recall_evaluator.precision`, + * `precision_recall.recal`, etc. + * + * Also, if current Evaluator is a combined evaluator. getNames will return + * all names of all evaluators inside the combined evaluator. + * + * @param names [out]: the field names of current evaluator. + * @note Never clear the names parameter inside getNames. + */ virtual void getNames(std::vector* names) { names->push_back(config_.name()); } + /** + * @brief getValue will return the current evaluate value of one field. + * + * @param name: The field name of current evaluator. + * @param err [out]: The error state. nullptr means don't care. + * + * @return The evaluate value(metric). + */ virtual real getValue(const std::string& name, paddle::Error* err = nullptr) const { - if (name != config_.name() && err != nullptr) { - *err = paddle::Error("no such name of evaluator %s", name.c_str()); + if (name != config_.name()) { + if (err != nullptr) { + *err = paddle::Error("no such name of evaluator %s", name.c_str()); + } return .0f; } return this->getValueImpl(); } - virtual std::string getValueStr(const std::string& name, - paddle::Error* err = nullptr) const { - paddle::Error localErr; - if (err == nullptr) { - err = &localErr; - } - real result = this->getValue(name, err); - if (!err->isOK()) { - return ""; - } else { - return std::to_string(result); - } - } - + /** + * @brief getType will return the evaluator type by field name. + * + * Evaluate Type is the current type of evaluator in string. Such as 'auc', + * 'precision_recall'. In combined evaluator, different name may get different + * evaluate type because it could be evaluated by different evaluator inside. + * + * @param name: The field name of current Evaluator. + * @param err: The error state. nullptr means don't care. + * @return the evaluator type string. + */ virtual std::string getType(const std::string& name, paddle::Error* err = nullptr) const { if (name != config_.name() && err != nullptr) { @@ -155,10 +177,22 @@ class Evaluator { } protected: + /** + * @brief getValueImpl The simplest way to define getValue result. If this + * evaluator doesn't contain multiple fields, and do not throw any error, just + * implemented this method to get the evaluate result(metric). + * @return Evaluate result(metric). + */ virtual real getValueImpl() const { return numSamples_ != .0 ? totalScore_ / numSamples_ : .0; } + /** + * @brief getTypeImpl The simplest way to define getType result. If this + * evaluator doesn't combine many evaluators, the get type should only return + * itself type. + * @return Evaluator type. + */ virtual std::string getTypeImpl() const { return "base"; } protected: @@ -167,6 +201,11 @@ class Evaluator { double totalScore_; }; +/** + * @brief The NotGetableEvaluator class is the base class of evaluator that + * cannot get value in runtime. The most NotGetableEvaluator is Printer + * Evaluator, which is only used to debug network configuration. + */ class NotGetableEvaluator : public Evaluator { // Evaluator interface public: diff --git a/paddle/gserver/gradientmachines/NeuralNetwork.cpp b/paddle/gserver/gradientmachines/NeuralNetwork.cpp index 277fb6d8db13ce..4d2bdf0dc992da 100644 --- a/paddle/gserver/gradientmachines/NeuralNetwork.cpp +++ b/paddle/gserver/gradientmachines/NeuralNetwork.cpp @@ -348,24 +348,29 @@ class CombinedEvaluator : public Evaluator { // Evaluator interface public: + /** + * @brief getNames will return all inside evaluators' names. + * @param names [out]: return names. + */ void getNames(std::vector* names) { for (auto& eval : evaluators_) { eval->getNames(names); } } + /** + * @brief getValue could get all inside evaluators' value. + */ real getValue(const std::string& name, Error* err) const { return this->getMethodHelper( name, err, [&name, err](const std::unique_ptr& eval) { return eval->getValue(name, err); }); } - std::string getValueStr(const std::string& name, Error* err) const { - return this->getMethodHelper( - name, err, [&name, err](const std::unique_ptr& eval) { - return eval->getValueStr(name, err); - }); - } + + /** + * @brief getType could get all inside evaluators' type. + */ std::string getType(const std::string& name, Error* err) const { return this->getMethodHelper( name, err, [&name, err](const std::unique_ptr& eval) { diff --git a/paddle/gserver/tests/test_Evaluator.cpp b/paddle/gserver/tests/test_Evaluator.cpp index 100cf078095092..07f486b1f4511b 100644 --- a/paddle/gserver/tests/test_Evaluator.cpp +++ b/paddle/gserver/tests/test_Evaluator.cpp @@ -114,7 +114,7 @@ void testEvaluator(TestConfig testConf, testEvaluator->getNames(&names); paddle::Error err; for (auto& name : names) { - auto value = testEvaluator->getValueStr(name, &err); + auto value = testEvaluator->getValue(name, &err); ASSERT_TRUE(err.isOK()); LOG(INFO) << name << " " << value; auto tp = testEvaluator->getType(name, &err); From f9eddadb3ea29f48d3b93c60e6062f16be0f49a2 Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Mon, 20 Feb 2017 15:02:02 +0800 Subject: [PATCH 234/370] follow comments, add seq_concat_layer in docs --- doc/api/trainer_config_helpers/layers.rst | 6 ++++++ python/paddle/trainer_config_helpers/layers.py | 10 +++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/doc/api/trainer_config_helpers/layers.rst b/doc/api/trainer_config_helpers/layers.rst index 8b0e553eacc932..3685868ffcfdf1 100644 --- a/doc/api/trainer_config_helpers/layers.rst +++ b/doc/api/trainer_config_helpers/layers.rst @@ -279,6 +279,12 @@ concat_layer :members: concat_layer :noindex: +seq_concat_layer +---------------- +.. automodule:: paddle.trainer_config_helpers.layers + :members: seq_concat_layer + :noindex: + Reshaping Layers ================ diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index ce9213a5c015a3..0ff29772356af7 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -2574,14 +2574,18 @@ def __reduce_concat_type__(a, b): @wrap_name_default("seqconcat") @wrap_act_default(act=IdentityActivation()) +@wrap_bias_attr_default(has_bias=False) @layer_support() def seq_concat_layer(a, b, act=None, name=None, layer_attr=None, bias_attr=None): """ Concat sequence a with sequence b. - Inputs: a = [a1, a2, ..., an] - b = [b1, b2, ..., bn] - Note that the length of a and b should be the same. + + Inputs: + - a = [a1, a2, ..., an] + - b = [b1, b2, ..., bn] + - Note that the length of a and b should be the same. + Output: [a1, b1, a2, b2, ..., an, bn] The example usage is: From 984d54d0180729236f660d3af787fff862fdbc74 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 20 Feb 2017 21:51:57 +0800 Subject: [PATCH 235/370] change data_type to type --- demo/mnist/api_train.py | 10 +++++----- demo/mnist/api_train_v2.py | 9 ++++----- python/paddle/v2/__init__.py | 4 +++- python/paddle/v2/data.py | 22 ++++++++++++++++++++++ python/paddle/v2/layer.py | 14 +++++++------- 5 files changed, 41 insertions(+), 18 deletions(-) create mode 100644 python/paddle/v2/data.py diff --git a/demo/mnist/api_train.py b/demo/mnist/api_train.py index c6993eda38bd02..25c25c1fcddd26 100644 --- a/demo/mnist/api_train.py +++ b/demo/mnist/api_train.py @@ -9,7 +9,6 @@ import random import numpy as np -import paddle.trainer.PyDataProvider2 as dp import paddle.v2 as paddle_v2 import py_paddle.swig_paddle as api from paddle.trainer_config_helpers import * @@ -71,8 +70,10 @@ def main(): assert isinstance(updater, api.ParameterUpdater) # define network - images = paddle_v2.layer.data(name='pixel', data_type=dp.dense_vector(784)) - label = paddle_v2.layer.data(name='label', data_type=dp.integer_value(10)) + images = paddle_v2.layer.data( + name='pixel', type=paddle_v2.data.dense_vector(784)) + label = paddle_v2.layer.data( + name='label', type=paddle_v2.data.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, @@ -98,8 +99,7 @@ def main(): # DataProvider Converter is a utility convert Python Object to Paddle C++ # Input. The input format is as same as Paddle's DataProvider. - converter = DataProviderConverter( - input_types=[images.data_type, label.data_type]) + converter = DataProviderConverter(input_types=[images.type, label.type]) train_file = './data/raw_data/train' test_file = './data/raw_data/t10k' diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 6bbc3a4ab35a64..c50a46c4d82447 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -1,6 +1,5 @@ import numpy import paddle.v2 as paddle -from paddle.trainer.PyDataProvider2 import dense_vector, integer_value import mnist_util @@ -16,8 +15,8 @@ def main(): paddle.init(use_gpu=False, trainer_count=1) # define network topology - images = paddle.layer.data(name='pixel', data_type=dense_vector(784)) - label = paddle.layer.data(name='label', data_type=integer_value(10)) + images = paddle.layer.data(name='pixel', type=paddle.data.dense_vector(784)) + label = paddle.layer.data(name='label', type=paddle.data.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, @@ -51,8 +50,8 @@ def event_handler(event): 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.data_type, - 'label': label.data_type + 'pixel': images.type, + 'label': label.type }) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index bc064a21ae1502..cd6dfce0e66765 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -17,10 +17,12 @@ import parameters import trainer import event +import data import py_paddle.swig_paddle as api __all__ = [ - 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', 'event' + 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', + 'event', 'data' ] diff --git a/python/paddle/v2/data.py b/python/paddle/v2/data.py new file mode 100644 index 00000000000000..5b01ba4cd4866c --- /dev/null +++ b/python/paddle/v2/data.py @@ -0,0 +1,22 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + +from paddle.trainer.PyDataProvider2 import \ + InputType, dense_vector, sparse_binary_vector,\ + sparse_vector, integer_value + +__all__ = [ + 'InputType', 'dense_vector', 'sparse_binary_vector', 'sparse_vector', + 'integer_value' +] diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index f2bc47946b6df8..f5a411198e47ab 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -67,7 +67,7 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. """ import paddle.trainer_config_helpers as conf_helps -import paddle.trainer.PyDataProvider2 as dp +from . import data as v2_data from paddle.trainer_config_helpers.config_parser_utils import \ parse_network_config as __parse__ from paddle.trainer_config_helpers.default_decorators import wrap_name_default @@ -165,10 +165,10 @@ def to_proto_impl(self, **kwargs): class DataLayerV2(Layer): - def __init__(self, name, data_type, **kwargs): - assert isinstance(data_type, dp.InputType) + def __init__(self, name, type, **kwargs): + assert isinstance(type, v2_data.InputType) - self.data_type = data_type + self.type = type self.__method_name__ = 'data_layer' self.__kwargs__ = kwargs @@ -176,7 +176,7 @@ def __init__(self, name, data_type, **kwargs): def to_proto_impl(self, **kwargs): args = dict() - args['size'] = self.data_type.dim + args['size'] = self.type.dim for each in kwargs: args[each] = kwargs[each] for each in self.__kwargs__: @@ -198,8 +198,8 @@ def to_proto_impl(self, **kwargs): parent_names=['input', 'label']) if __name__ == '__main__': - pixel = data(name='pixel', data_type=dp.dense_vector(784)) - label = data(name='label', data_type=dp.integer_value(10)) + pixel = data(name='pixel', type=v2_data.dense_vector(784)) + label = data(name='label', type=v2_data.integer_value(10)) hidden = fc(input=pixel, size=100, act=conf_helps.SigmoidActivation()) inference = fc(input=hidden, size=10, act=conf_helps.SoftmaxActivation()) maxid = max_id(input=inference) From bd80549c6525f2f4c20ecab7a2305155c2c06462 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Mon, 20 Feb 2017 09:03:55 -0800 Subject: [PATCH 236/370] fix issue in create custom reader in design doc --- doc/design/reader/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/design/reader/README.md b/doc/design/reader/README.md index 8f7abf12f73354..ff3ee758beeb2f 100644 --- a/doc/design/reader/README.md +++ b/doc/design/reader/README.md @@ -107,7 +107,7 @@ We decided to use dictionary (`{"image":0, "label":1}`) instead of list (`["imag ### How to create custom data reader ```python -def image_reader(image_path, label_path): +def image_reader(image_path, label_path, n): f = open(image_path) l = open(label_path) images = numpy.fromfile( @@ -117,9 +117,10 @@ def image_reader(image_path, label_path): for i in xrange(n): yield images[i, :], labels[i] # a single entry of data is created each time f.close() + l.close() # use python lambda to change image_reader into a function with no parameters. -reader = lambda : image_reader("/path/to/image_file", "/path/to/label_file") +reader = lambda : image_reader("/path/to/image_file", "/path/to/label_file", 1024) paddle.train(reader, {"image":0, "label":1}, ...) ``` From 0a0b5b5b9168eb6dbfac7f932c7f4bc91759db2c Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 21 Feb 2017 09:55:31 +0800 Subject: [PATCH 237/370] change paddle.data to paddle.data_type --- demo/mnist/api_train.py | 4 ++-- demo/mnist/api_train_v2.py | 6 ++++-- python/paddle/v2/__init__.py | 4 ++-- python/paddle/v2/{data.py => data_type.py} | 0 python/paddle/v2/layer.py | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) rename python/paddle/v2/{data.py => data_type.py} (100%) diff --git a/demo/mnist/api_train.py b/demo/mnist/api_train.py index 25c25c1fcddd26..ea1caa7dd9653a 100644 --- a/demo/mnist/api_train.py +++ b/demo/mnist/api_train.py @@ -71,9 +71,9 @@ def main(): # define network images = paddle_v2.layer.data( - name='pixel', type=paddle_v2.data.dense_vector(784)) + name='pixel', type=paddle_v2.data_type.dense_vector(784)) label = paddle_v2.layer.data( - name='label', type=paddle_v2.data.integer_value(10)) + 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, diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index c50a46c4d82447..6fc01ce58be57c 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -15,8 +15,10 @@ def main(): paddle.init(use_gpu=False, trainer_count=1) # define network topology - images = paddle.layer.data(name='pixel', type=paddle.data.dense_vector(784)) - label = paddle.layer.data(name='label', type=paddle.data.integer_value(10)) + 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, diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index cd6dfce0e66765..c0a2bdc4259c3f 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -17,12 +17,12 @@ import parameters import trainer import event -import data +import data_type import py_paddle.swig_paddle as api __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', - 'event', 'data' + 'event', 'data_type.py' ] diff --git a/python/paddle/v2/data.py b/python/paddle/v2/data_type.py similarity index 100% rename from python/paddle/v2/data.py rename to python/paddle/v2/data_type.py diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index f5a411198e47ab..4d052c983c2c07 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -67,7 +67,7 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. """ import paddle.trainer_config_helpers as conf_helps -from . import data as v2_data +from . import data_type as v2_data from paddle.trainer_config_helpers.config_parser_utils import \ parse_network_config as __parse__ from paddle.trainer_config_helpers.default_decorators import wrap_name_default From 07539b2a1c9976b8d4ba5c13b498d16d5288b1f4 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 21 Feb 2017 10:23:23 +0800 Subject: [PATCH 238/370] add-topology --- python/paddle/v2/__init__.py | 3 ++- python/paddle/v2/topology.py | 44 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 python/paddle/v2/topology.py diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index c0a2bdc4259c3f..cf01f37a3324ff 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -18,11 +18,12 @@ import trainer import event import data_type +import topology import py_paddle.swig_paddle as api __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', - 'event', 'data_type.py' + 'event', 'data_type', 'topology' ] diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py new file mode 100644 index 00000000000000..ddba1b2345e5eb --- /dev/null +++ b/python/paddle/v2/topology.py @@ -0,0 +1,44 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + +from . import layer + +__all__ = ['Topology'] + + +class Topology(object): + """ + Topology is used to store the information about all layers + and network configs. + """ + + def __init__(self, cost): + self.cost = cost + self.__model_config__ = layer.parse_network(cost) + + def __call__(self): + return self.__model_config__ + + def get_layer(self, name): + """ + get layer by layer name + :param name: + :return: + """ + pass + + def data_type(self): + """ + """ + pass From 67b8150ff4d04552a5a52cb099bf7e935765e69f Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Tue, 21 Feb 2017 13:27:21 +0800 Subject: [PATCH 239/370] data converter test --- paddle/data_converter_test.py | 92 +++++++++++++++++++++++++ python/paddle/v2/data_converter.py | 19 ++--- python/paddle/v2/data_converter_test.py | 92 +++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 8 deletions(-) create mode 100644 paddle/data_converter_test.py create mode 100644 python/paddle/v2/data_converter_test.py diff --git a/paddle/data_converter_test.py b/paddle/data_converter_test.py new file mode 100644 index 00000000000000..d84ee5172782d9 --- /dev/null +++ b/paddle/data_converter_test.py @@ -0,0 +1,92 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + +import unittest + +import py_paddle.swig_paddle as api +import numpy as np +import paddle.trainer.PyDataProvider2 as dp2 + +from paddle.v2.data_converter import DataConverter + + +class DataConverterTest(unittest.TestCase): + def dense_reader(self, shape): + data = np.random.random(shape) + return data + + def sparse_binary_reader(self, + high, + size_limit, + batch_size, + non_empty=False): + data = [] + for i in xrange(batch_size): + num = np.random.randint(size_limit) # num could be 0 + while non_empty and num == 0: + num = np.random.randint(size_limit) + data.append(np.random.randint(high, size=num).tolist()) + + return data + + def test_dense_vector(self): + def compare(input): + converter = DataConverter([('image', dp2.dense_vector(784))]) + arg = converter([input], {'image': 0}) + output = arg.getSlotValue(0).copyToNumpyMat() + input = np.array(input, dtype='float32') + self.assertAlmostEqual(input.all(), output.all()) + + # test numpy array + data = self.dense_reader(shape=[32, 784]) + compare(data) + + # test list + compare(data.tolist()) + + #def test_sparse_binary(self): + # dim = 100000 + # data = self.sparse_binary_reader(dim, 5, 2) + # converter = DataConverter([('input', dp2.sparse_binary_vector(dim))]) + # arg = converter([data], {'input':0}) + # output = arg.getSlotValue(0) + + #def test_sparse(self): + # dim = 100000 + # v = self.sparse_binary_reader(dim, 5, 2) + # w = [] + # for dat in data: + # x = self.dense_reader(shape=[1, len(dat)]) + # w.append(x.tolist()) + # data = [] + # for each in zip(v, w): + # data.append(zip(each[0], each[1])) + # + # converter = DataConverter([('input', dp2.sparse_binary_vector(dim))]) + # arg = converter([data], {'input':0}) + # output = arg.getSlotValue(0) + + def test_integer(self): + dim = 100 + index = np.random.randint(dim, size=32) + print index + converter = DataConverter([('input', dp2.integer_value(dim))]) + arg = converter([index], {'input': 0}) + print arg.getSlotValue(0) + output = arg.getSlotValue(0).copyToNumpyArray() + print 'output=', output + + +if __name__ == '__main__': + unittest.main() diff --git a/python/paddle/v2/data_converter.py b/python/paddle/v2/data_converter.py index afb98a77c5b315..fcba43e4ba99f9 100644 --- a/python/paddle/v2/data_converter.py +++ b/python/paddle/v2/data_converter.py @@ -53,9 +53,9 @@ def convert(self, data, argument): :type argument: Paddle's Arguments """ assert isinstance(argument, api.Arguments) - if data.dtype != np.float32: - data = data.astype(np.float32) - m = api.Matrix.createDenseFromNumpy(data, True, False) + # TODO: handle data type (float, double, ...) + data = np.array(data, np.float32) + m = api.Matrix.createDenseFromNumpy(data) argument.setSlotValue(self.pos, m) @@ -72,12 +72,12 @@ def fill_csr(self, data): self.__height__ = len(data) for x in data: self.__rows__.append(self.__rows__[-1] + len(x)) - self.__cols__ = data.flatten() + self.__cols__.extend(x) def convert(self, data, argument): assert isinstance(argument, api.Arguments) - fill_csr(data) + self.fill_csr(data) m = api.Matrix.createSparse(self.__height__, self.input_type.dim, len(self.__cols__), len(self.__value__) == 0) @@ -94,8 +94,8 @@ def fill_csr(self, data): self.__height__ = len(data) for x in data: self.__rows__.append(self.__rows__[-1] + len(x)) - self.__cols__.extend((x[0] for x in data)) - self.__value__.extend((x[1] for x in data)) + self.__cols__.extend(x[0]) + self.__value__.extend(x[1]) class IndexConvert(IDataConverter): @@ -105,7 +105,10 @@ def __init__(self, input_type, pos): def convert(self, data, argument): assert isinstance(argument, api.Arguments) - self.__ids__ = data.flatten() + #for x in data: + # self.__ids__.append(x) + self.__ids__.extend(x) + ids = api.IVector.create(self.__ids__) argument.setSlotIds(self.pos, ids) diff --git a/python/paddle/v2/data_converter_test.py b/python/paddle/v2/data_converter_test.py new file mode 100644 index 00000000000000..d84ee5172782d9 --- /dev/null +++ b/python/paddle/v2/data_converter_test.py @@ -0,0 +1,92 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + +import unittest + +import py_paddle.swig_paddle as api +import numpy as np +import paddle.trainer.PyDataProvider2 as dp2 + +from paddle.v2.data_converter import DataConverter + + +class DataConverterTest(unittest.TestCase): + def dense_reader(self, shape): + data = np.random.random(shape) + return data + + def sparse_binary_reader(self, + high, + size_limit, + batch_size, + non_empty=False): + data = [] + for i in xrange(batch_size): + num = np.random.randint(size_limit) # num could be 0 + while non_empty and num == 0: + num = np.random.randint(size_limit) + data.append(np.random.randint(high, size=num).tolist()) + + return data + + def test_dense_vector(self): + def compare(input): + converter = DataConverter([('image', dp2.dense_vector(784))]) + arg = converter([input], {'image': 0}) + output = arg.getSlotValue(0).copyToNumpyMat() + input = np.array(input, dtype='float32') + self.assertAlmostEqual(input.all(), output.all()) + + # test numpy array + data = self.dense_reader(shape=[32, 784]) + compare(data) + + # test list + compare(data.tolist()) + + #def test_sparse_binary(self): + # dim = 100000 + # data = self.sparse_binary_reader(dim, 5, 2) + # converter = DataConverter([('input', dp2.sparse_binary_vector(dim))]) + # arg = converter([data], {'input':0}) + # output = arg.getSlotValue(0) + + #def test_sparse(self): + # dim = 100000 + # v = self.sparse_binary_reader(dim, 5, 2) + # w = [] + # for dat in data: + # x = self.dense_reader(shape=[1, len(dat)]) + # w.append(x.tolist()) + # data = [] + # for each in zip(v, w): + # data.append(zip(each[0], each[1])) + # + # converter = DataConverter([('input', dp2.sparse_binary_vector(dim))]) + # arg = converter([data], {'input':0}) + # output = arg.getSlotValue(0) + + def test_integer(self): + dim = 100 + index = np.random.randint(dim, size=32) + print index + converter = DataConverter([('input', dp2.integer_value(dim))]) + arg = converter([index], {'input': 0}) + print arg.getSlotValue(0) + output = arg.getSlotValue(0).copyToNumpyArray() + print 'output=', output + + +if __name__ == '__main__': + unittest.main() From 4db1c0fe03fdc2dfd726c202958dc1af66f846e4 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Tue, 21 Feb 2017 14:29:42 +0800 Subject: [PATCH 240/370] Fix the unit test bug for api --- paddle/api/test/testMatrix.py | 2 +- paddle/api/test/testVector.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/paddle/api/test/testMatrix.py b/paddle/api/test/testMatrix.py index 37666bdccc9aed..f08fbf3ccdf5d7 100644 --- a/paddle/api/test/testMatrix.py +++ b/paddle/api/test/testMatrix.py @@ -68,7 +68,7 @@ def test_createDenseMat(self): def test_numpyCpu(self): numpy_mat = np.matrix([[1, 2], [3, 4], [5, 6]], dtype="float32") - m = swig_paddle.Matrix.createCpuDenseFromNumpy(numpy_mat, copy=False) + m = swig_paddle.Matrix.createCpuDenseFromNumpy(numpy_mat, False) self.assertEqual((int(m.getHeight()), int(m.getWidth())), numpy_mat.shape) diff --git a/paddle/api/test/testVector.py b/paddle/api/test/testVector.py index 1ab095c1d3d0d2..6339cf8542607b 100644 --- a/paddle/api/test/testVector.py +++ b/paddle/api/test/testVector.py @@ -43,7 +43,7 @@ def test_create(self): def test_cpu_numpy(self): vec = np.array([1, 3, 4, 65, 78, 1, 4], dtype="int32") - iv = swig_paddle.IVector.createCpuVectorFromNumpy(vec, copy=False) + iv = swig_paddle.IVector.createCpuVectorFromNumpy(vec, False) self.assertEqual(vec.shape[0], int(iv.__len__())) vec[4] = 832 for i in xrange(len(iv)): @@ -106,7 +106,7 @@ def testCreate(self): def testCpuNumpy(self): numpy_arr = np.array([1.2, 2.3, 3.4, 4.5], dtype="float32") - vec = swig_paddle.Vector.createCpuVectorFromNumpy(numpy_arr, copy=False) + vec = swig_paddle.Vector.createCpuVectorFromNumpy(numpy_arr, False) assert isinstance(vec, swig_paddle.Vector) numpy_arr[0] = 0.1 for n, v in zip(numpy_arr, vec): From 0b673756f1e366434454bf5215b2f508c02d63ee Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Tue, 21 Feb 2017 15:04:25 +0800 Subject: [PATCH 241/370] add SequenceReshapeLayer in trainer_config_helpers --- doc/api/trainer_config_helpers/layers.rst | 6 ++ .../gserver/layers/SequenceReshapeLayer.cpp | 9 ++- .../paddle/trainer_config_helpers/layers.py | 61 +++++++++++++++++++ .../tests/configs/file_list.sh | 2 +- ...tostr => test_seq_concat_reshape.protostr} | 12 ++++ ...q_concat.py => test_seq_concat_reshape.py} | 7 ++- 6 files changed, 91 insertions(+), 6 deletions(-) rename python/paddle/trainer_config_helpers/tests/configs/protostr/{test_seq_concat.protostr => test_seq_concat_reshape.protostr} (72%) rename python/paddle/trainer_config_helpers/tests/configs/{test_seq_concat.py => test_seq_concat_reshape.py} (57%) diff --git a/doc/api/trainer_config_helpers/layers.rst b/doc/api/trainer_config_helpers/layers.rst index 3685868ffcfdf1..2793d6afd9565e 100644 --- a/doc/api/trainer_config_helpers/layers.rst +++ b/doc/api/trainer_config_helpers/layers.rst @@ -308,6 +308,12 @@ repeat_layer :members: repeat_layer :noindex: +seq_reshape_layer +----------------- +.. automodule:: paddle.trainer_config_helpers.layers + :members: seq_reshape_layer + :noindex: + Math Layers =========== diff --git a/paddle/gserver/layers/SequenceReshapeLayer.cpp b/paddle/gserver/layers/SequenceReshapeLayer.cpp index 66f49159087ab9..433592953b220e 100644 --- a/paddle/gserver/layers/SequenceReshapeLayer.cpp +++ b/paddle/gserver/layers/SequenceReshapeLayer.cpp @@ -20,9 +20,12 @@ limitations under the License. */ namespace paddle { /** - * A layer for reshaping the sequence - * Input: a sequence - * Output: a sequence + * A layer for reshaping the sequence. Assume the input sequence has + * T instances, the dimension of each instance is M, and the input + * 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 { diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 0ff29772356af7..0d3a31b9d39a28 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -37,6 +37,7 @@ "dotmul_projection", "dotmul_operator", "repeat_layer", + "seq_reshape_layer", "table_projection", "mixed_layer", "data_layer", @@ -125,6 +126,7 @@ class LayerType(object): GRUMEMORY = "gated_recurrent" SEQUENCE_LAST_INSTANCE = "seqlastins" SEQUENCE_FIRST_INSTANCE = "seqfirstins" + SEQUENCE_RESHAPE = "seqreshape" POOLING_MAX = "max" POOLING_AVG = 'average' FC_LAYER = "fc" @@ -1450,6 +1452,61 @@ def repeat_layer(input, num_repeats, name=None, layer_attr=None): parents=[input]) +@wrap_name_default("seqreshape") +@wrap_act_default(act=IdentityActivation()) +@wrap_bias_attr_default(has_bias=False) +@layer_support() +def seq_reshape_layer(input, + reshape_size, + act=None, + name=None, + layer_attr=None, + bias_attr=None): + """ + A layer for reshaping the sequence. Assume the input sequence has T instances, + the dimension of each instance is M, and the input reshape_size 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. + + The example usage is: + + .. code-block:: python + + reshape = seq_reshape_layer(input=layer, reshape_size=4) + + :param input: Input layer. + :type input: LayerOutput + :param reshape_size: the size of reshaped sequence. + :type reshape_size: int + :param name: Layer name. + :type name: basestring + :param act: Activation type. + :type act: BaseActivation + :param layer_attr: extra layer attributes. + :type layer_attr: ExtraLayerAttribute. + :param bias_attr: The Bias Attribute. If no bias, then pass False or + something not type of ParameterAttribute. None will get a + default Bias. + :type bias_attr: ParameterAttribute or None or bool + :return: LayerOutput object. + :rtype: LayerOutput + """ + + Layer( + inputs=[input.name], + name=name, + size=reshape_size, + type=LayerType.SEQUENCE_RESHAPE, + bias=ParamAttr.to_bias(bias_attr), + **ExtraAttr.to_kwargs(layer_attr)) + return LayerOutput( + name=name, + size=reshape_size, + layer_type=LayerType.SEQUENCE_RESHAPE, + parents=[input]) + + @wrap_name_default() @layer_support() def interpolation_layer(input, weight, name=None, layer_attr=None): @@ -2604,6 +2661,10 @@ def seq_concat_layer(a, b, act=None, name=None, layer_attr=None, :type act: BaseActivation :param layer_attr: Extra Layer Attribute. :type layer_attr: ExtraLayerAttribute + :param bias_attr: The Bias Attribute. If no bias, then pass False or + something not type of ParameterAttribute. None will get a + default Bias. + :type bias_attr: ParameterAttribute or None or bool :return: LayerOutput object. :rtype: LayerOutput """ diff --git a/python/paddle/trainer_config_helpers/tests/configs/file_list.sh b/python/paddle/trainer_config_helpers/tests/configs/file_list.sh index 55cef6be0c630c..c9178e3c6a46a2 100755 --- a/python/paddle/trainer_config_helpers/tests/configs/file_list.sh +++ b/python/paddle/trainer_config_helpers/tests/configs/file_list.sh @@ -5,6 +5,6 @@ last_first_seq test_expand_layer test_ntm_layers test_hsigmoid img_layers img_trans_layers util_layers simple_rnn_layers unused_layers test_cost_layers test_rnn_group shared_fc shared_lstm shared_gru test_cost_layers_with_weight test_spp_layer test_bilinear_interp test_maxout test_bi_grumemory math_ops -test_seq_concat) +test_seq_concat_reshape) export whole_configs=(test_split_datasource) diff --git a/python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat.protostr b/python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat_reshape.protostr similarity index 72% rename from python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat.protostr rename to python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat_reshape.protostr index 2fa55e87b5d13c..91284b4fb32fcf 100644 --- a/python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat.protostr +++ b/python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat_reshape.protostr @@ -23,17 +23,29 @@ layers { input_layer_name: "data2" } } +layers { + name: "__seqreshape_0__" + type: "seqreshape" + size: 5 + active_type: "linear" + inputs { + input_layer_name: "data1" + } +} input_layer_names: "data1" input_layer_names: "data2" output_layer_names: "__seqconcat_0__" +output_layer_names: "__seqreshape_0__" sub_models { name: "root" layer_names: "data1" layer_names: "data2" layer_names: "__seqconcat_0__" + layer_names: "__seqreshape_0__" input_layer_names: "data1" input_layer_names: "data2" output_layer_names: "__seqconcat_0__" + output_layer_names: "__seqreshape_0__" is_recurrent_layer_group: false } diff --git a/python/paddle/trainer_config_helpers/tests/configs/test_seq_concat.py b/python/paddle/trainer_config_helpers/tests/configs/test_seq_concat_reshape.py similarity index 57% rename from python/paddle/trainer_config_helpers/tests/configs/test_seq_concat.py rename to python/paddle/trainer_config_helpers/tests/configs/test_seq_concat_reshape.py index 193d9d0df9ed80..5c161ba805fb30 100644 --- a/python/paddle/trainer_config_helpers/tests/configs/test_seq_concat.py +++ b/python/paddle/trainer_config_helpers/tests/configs/test_seq_concat_reshape.py @@ -3,7 +3,10 @@ settings(batch_size=1000, learning_rate=1e-5) din1 = data_layer(name='data1', size=30) - din2 = data_layer(name='data2', size=30) -outputs(seq_concat_layer(a=din1, b=din2)) +opts = [] +opts.append(seq_concat_layer(a=din1, b=din2)) +opts.append(seq_reshape_layer(input=din1, reshape_size=5)) + +outputs(opts) From 15180e85acaa400c629a37fadcf4589b7c086c7d Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Tue, 21 Feb 2017 15:50:01 +0800 Subject: [PATCH 242/370] remove some code --- paddle/data_converter_test.py | 92 ----------------------------------- 1 file changed, 92 deletions(-) delete mode 100644 paddle/data_converter_test.py diff --git a/paddle/data_converter_test.py b/paddle/data_converter_test.py deleted file mode 100644 index d84ee5172782d9..00000000000000 --- a/paddle/data_converter_test.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved -# -# 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. - -import unittest - -import py_paddle.swig_paddle as api -import numpy as np -import paddle.trainer.PyDataProvider2 as dp2 - -from paddle.v2.data_converter import DataConverter - - -class DataConverterTest(unittest.TestCase): - def dense_reader(self, shape): - data = np.random.random(shape) - return data - - def sparse_binary_reader(self, - high, - size_limit, - batch_size, - non_empty=False): - data = [] - for i in xrange(batch_size): - num = np.random.randint(size_limit) # num could be 0 - while non_empty and num == 0: - num = np.random.randint(size_limit) - data.append(np.random.randint(high, size=num).tolist()) - - return data - - def test_dense_vector(self): - def compare(input): - converter = DataConverter([('image', dp2.dense_vector(784))]) - arg = converter([input], {'image': 0}) - output = arg.getSlotValue(0).copyToNumpyMat() - input = np.array(input, dtype='float32') - self.assertAlmostEqual(input.all(), output.all()) - - # test numpy array - data = self.dense_reader(shape=[32, 784]) - compare(data) - - # test list - compare(data.tolist()) - - #def test_sparse_binary(self): - # dim = 100000 - # data = self.sparse_binary_reader(dim, 5, 2) - # converter = DataConverter([('input', dp2.sparse_binary_vector(dim))]) - # arg = converter([data], {'input':0}) - # output = arg.getSlotValue(0) - - #def test_sparse(self): - # dim = 100000 - # v = self.sparse_binary_reader(dim, 5, 2) - # w = [] - # for dat in data: - # x = self.dense_reader(shape=[1, len(dat)]) - # w.append(x.tolist()) - # data = [] - # for each in zip(v, w): - # data.append(zip(each[0], each[1])) - # - # converter = DataConverter([('input', dp2.sparse_binary_vector(dim))]) - # arg = converter([data], {'input':0}) - # output = arg.getSlotValue(0) - - def test_integer(self): - dim = 100 - index = np.random.randint(dim, size=32) - print index - converter = DataConverter([('input', dp2.integer_value(dim))]) - arg = converter([index], {'input': 0}) - print arg.getSlotValue(0) - output = arg.getSlotValue(0).copyToNumpyArray() - print 'output=', output - - -if __name__ == '__main__': - unittest.main() From 3e8f232e126e06f6a5266307aada8b1d8e1bac43 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 21 Feb 2017 16:19:42 +0800 Subject: [PATCH 243/370] remove import . to enable run v2/layer.py directly --- python/paddle/v2/__init__.py | 2 +- python/paddle/v2/layer.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index c0a2bdc4259c3f..30d0b2a398bd0e 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -22,7 +22,7 @@ __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', - 'event', 'data_type.py' + 'event', 'data_type' ] diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 4d052c983c2c07..9e999fccadf16d 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -67,7 +67,7 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. """ import paddle.trainer_config_helpers as conf_helps -from . import data_type as v2_data +import data_type as data_type from paddle.trainer_config_helpers.config_parser_utils import \ parse_network_config as __parse__ from paddle.trainer_config_helpers.default_decorators import wrap_name_default @@ -166,7 +166,7 @@ def to_proto_impl(self, **kwargs): class DataLayerV2(Layer): def __init__(self, name, type, **kwargs): - assert isinstance(type, v2_data.InputType) + assert isinstance(type, data_type.InputType) self.type = type self.__method_name__ = 'data_layer' @@ -198,8 +198,8 @@ def to_proto_impl(self, **kwargs): parent_names=['input', 'label']) if __name__ == '__main__': - pixel = data(name='pixel', type=v2_data.dense_vector(784)) - label = data(name='label', type=v2_data.integer_value(10)) + pixel = data(name='pixel', type=data_type.dense_vector(784)) + label = data(name='label', type=data_type.integer_value(10)) hidden = fc(input=pixel, size=100, act=conf_helps.SigmoidActivation()) inference = fc(input=hidden, size=10, act=conf_helps.SoftmaxActivation()) maxid = max_id(input=inference) From e4af5b9228feca57c31ac1bdfacf93cfab6ba217 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 21 Feb 2017 16:23:19 +0800 Subject: [PATCH 244/370] optimize code --- python/paddle/v2/layer.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 9e999fccadf16d..507725ee4ff712 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -66,12 +66,14 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. paddle.v2.parameters.create, no longer exposed to users. """ +import collections + import paddle.trainer_config_helpers as conf_helps -import data_type as data_type from paddle.trainer_config_helpers.config_parser_utils import \ parse_network_config as __parse__ from paddle.trainer_config_helpers.default_decorators import wrap_name_default -import collections + +import data_type __all__ = [ 'parse_network', 'data', 'fc', 'max_id', 'classification_cost', From 7cfe34da7c99c541189cb73165bc022bbc4289c0 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 21 Feb 2017 23:53:42 +0800 Subject: [PATCH 245/370] modify api_train_v2 --- demo/mnist/api_train_v2.py | 20 ++++--- python/paddle/v2/layer.py | 8 ++- python/paddle/v2/parameters.py | 21 ++++---- python/paddle/v2/topology.py | 96 +++++++++++++++++++++++++++++++--- python/paddle/v2/trainer.py | 20 +++---- 5 files changed, 119 insertions(+), 46 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 6fc01ce58be57c..f6edd1f34fe8d1 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -26,7 +26,9 @@ def main(): act=paddle.activation.Softmax()) cost = paddle.layer.classification_cost(input=inference, label=label) - parameters = paddle.parameters.create(cost) + topology = paddle.topology.Topology(cost) + + parameters = paddle.parameters.create(topology) for param_name in parameters.keys(): array = parameters.get(param_name) array[:] = numpy.random.uniform(low=-1.0, high=1.0, size=array.shape) @@ -45,16 +47,12 @@ def event_handler(event): 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 - }) + trainer.train( + train_data_reader=train_reader, + topology=topology, + parameters=parameters, + event_handler=event_handler, + batch_size=32) # batch size should be refactor in Data reader if __name__ == '__main__': diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 4d052c983c2c07..5f146c8c038b95 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -66,12 +66,14 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. paddle.v2.parameters.create, no longer exposed to users. """ +import collections + import paddle.trainer_config_helpers as conf_helps -from . import data_type as v2_data from paddle.trainer_config_helpers.config_parser_utils import \ parse_network_config as __parse__ from paddle.trainer_config_helpers.default_decorators import wrap_name_default -import collections + +import data_type as v2_data __all__ = [ 'parse_network', 'data', 'fc', 'max_id', 'classification_cost', @@ -184,6 +186,8 @@ def to_proto_impl(self, **kwargs): return getattr(conf_helps, self.__method_name__)(name=self.name, **args) +LayerV2 = Layer + data = DataLayerV2 fc = __convert_to_v2__('fc_layer', name_prefix='fc', parent_names=['input']) max_id = __convert_to_v2__( diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index ea504d5104716d..b569afe3a1fc20 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -1,26 +1,23 @@ import numpy as np -from . import layer as v2_layer import py_paddle.swig_paddle as api from paddle.proto.ParameterConfig_pb2 import ParameterConfig +import topology as v2_topology + __all__ = ['Parameters', 'create'] -def create(*layers): +def create(topology): """ - Create parameter pool by layers. In paddle, layer can be represent a - model config. - - :param layers: + Create parameter pool by topology. + :param topology: :return: """ - for layer in layers: - if not isinstance(layer, v2_layer.Layer): - raise ValueError( - 'create must pass a topologies which type is paddle.layer.Layer') - model_config = v2_layer.parse_network(*layers) + if not isinstance(topology, v2_topology.Topology): + raise ValueError( + 'create must pass a topology which type is topology.Topology') pool = Parameters() - for param in model_config.parameters: + for param in topology.proto().parameters: pool.__append_config__(param) return pool diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index ddba1b2345e5eb..6508b3ce881c49 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -12,7 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from . import layer +from paddle.proto.ModelConfig_pb2 import ModelConfig +import paddle.trainer_config_helpers as conf_helps +import layer as v2_layer +import data_type __all__ = ['Topology'] @@ -23,22 +26,101 @@ class Topology(object): and network configs. """ - def __init__(self, cost): - self.cost = cost - self.__model_config__ = layer.parse_network(cost) + def __init__(self, *layers): + for layer in layers: + if not isinstance(layer, v2_layer.LayerV2): + raise ValueError('create must pass a topologies ' + 'which type is paddle.layer.Layer') + self.layers = layers + self.__model_config__ = v2_layer.parse_network(*layers) + assert isinstance(self.__model_config__, ModelConfig) - def __call__(self): + def proto(self): return self.__model_config__ def get_layer(self, name): + """ + get v2.Layer Class instance by layer name + :param name: + :return: + """ + result_layer = [] + + def find_layer_by_name(layer, layer_name): + if layer.name == layer_name and len(result_layer) == 0: + result_layer.append(layer) + for parent_layer in layer.__parent_layers__.values(): + find_layer_by_name(parent_layer, layer_name) + + for layer in self.layers: + find_layer_by_name(layer, name) + + return result_layer[0] + + def get_data_layer(self): + """ + get all data layer + :return: + """ + data_layers = [] + + def find_data_layer(layer): + assert isinstance(layer, layer.LayerV2) + if isinstance(layer, v2_layer.DataLayerV2): + if len( + filter(lambda data_layer: data_layer.name == layer.name, + data_layers)) == 0: + data_layers.append(layer) + for parent_layer in layer.__parent_layers__.values(): + find_data_layer(parent_layer) + + for layer in self.layers: + find_data_layer(layer) + + return data_layers + + def get_layer_proto(self, name): """ get layer by layer name :param name: :return: """ - pass + layers = filter(lambda layer: layer.name == name, + self.__model_config__.layers) + if len(layers) is 1: + return layers[0] + else: + return None def data_type(self): """ + get data_type from proto, such as: + [('image', dense_vector(768)), ('label', integer_value(10))] + the order is the same with __model_config__.input_layer_names """ - pass + data_types_lists = [] + for layer_name in self.__model_config__.input_layer_names: + data_types_lists.append( + (layer_name, self.get_layer(layer_name).type)) + + return data_types_lists + + +if __name__ == '__main__': + pixel = v2_layer.data(name='pixel', type=data_type.dense_vector(784)) + label = v2_layer.data(name='label', type=data_type.integer_value(10)) + hidden = v2_layer.fc(input=pixel, + size=100, + act=conf_helps.SigmoidActivation()) + inference = v2_layer.fc(input=hidden, + size=10, + act=conf_helps.SoftmaxActivation()) + maxid = v2_layer.max_id(input=inference) + cost1 = v2_layer.classification_cost(input=inference, label=label) + cost2 = v2_layer.cross_entropy_cost(input=inference, label=label) + + print Topology(cost1).proto() + print Topology(cost2).proto() + print Topology(cost1, cost2).proto() + print Topology(cost2).proto() + print Topology(inference, maxid).proto() diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 4365bd41e7073b..c8da6e70cf528d 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -1,13 +1,12 @@ import collections import py_paddle.swig_paddle as api -from paddle.proto.ModelConfig_pb2 import ModelConfig from py_paddle import DataProviderConverter from . import event as v2_event -from . import layer as v2_layer from . import optimizer as v2_optimizer from . import parameters as v2_parameters +from . import topology as v2_topology __all__ = ['ITrainer', 'SGD'] @@ -88,12 +87,11 @@ def train(self, if event_handler is None: event_handler = default_event_handler - topology = v2_layer.parse_network(topology) - __check_train_args__(**locals()) gm = api.GradientMachine.createFromConfigProto( - topology, api.CREATE_MODE_NORMAL, self.__optimizer__.enable_types()) + topology.proto(), api.CREATE_MODE_NORMAL, + self.__optimizer__.enable_types()) assert isinstance(gm, api.GradientMachine) parameters.append_gradient_machine(gm) @@ -102,13 +100,7 @@ def train(self, gm.start() out_args = api.Arguments.createArguments(0) - - data_types_lists = [] - for each in topology.input_layer_names: - if each not in data_types: - raise ValueError() - data_types_lists.append(data_types[each]) - + data_types_lists = [data_type[1] for data_type in topology.data_type()] converter = DataProviderConverter(input_types=data_types_lists) for pass_id in xrange(num_passes): @@ -141,7 +133,7 @@ def __data_reader_to_batch__(reader, batch_size, topology): def input_reorder(func): for item in func(): retv = [] - for __layer_name__ in topology.input_layer_names: + for __layer_name__ in topology.proto().input_layer_names: retv.append(item[__layer_name__]) yield retv @@ -178,7 +170,7 @@ def __check_train_args__(train_data_reader, topology, parameters, raise ValueError('test_data_reader should be a function, which can ' 'return a iterator') - if not isinstance(topology, ModelConfig): + if not isinstance(topology, v2_topology.Topology): raise ValueError('topology should be a model config') if not isinstance(parameters, v2_parameters.Parameters): From 9b3cdb12a98d71542de5491504942454782f3901 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Tue, 21 Feb 2017 14:49:31 -0800 Subject: [PATCH 246/370] use terminology *data reader creator* instead of *data reader*, and remove lambda usage from design doc --- doc/design/reader/README.md | 99 +++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 48 deletions(-) diff --git a/doc/design/reader/README.md b/doc/design/reader/README.md index ff3ee758beeb2f..f8f79a75b1db09 100644 --- a/doc/design/reader/README.md +++ b/doc/design/reader/README.md @@ -1,35 +1,35 @@ -# Python Data Reader Design Doc +# Python Data Reading Design Doc -Paddle reads data from data reader during training. It will be passed into `paddle.train` as a parameter. +Paddle reads data from *data reader* during training. *data reader creator* (or *reader creator*) creates a *data reader* when invoked. *reader creator* will be passed into `paddle.train` as a parameter. -## Data Reader Interface +## Data Reader Creator Interface -Data reader is a function with no parameter that creates a iterable (anything can be used in `for x in iterable`): +Data reader creator is a function with no parameter that creates a iterable (anything can be used in `for x in iterable`): ``` -iterable = data_reader() +iterable = data_reader_creator() ``` Element produced for 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: +An example implementation for single item data reader creator: ```python -def data_reader_fake_image(): +def data_reader_creator_fake_image(): while True: yield numpy.random.uniform(-1, 1, size=20*20) ``` -An example implementation for multiple item data reader: +An example implementation for multiple item data reader creator: ```python -def data_reader_fake_image_and_label(): +def data_reader_creator_fake_image_and_label(): while True: yield numpy.random.uniform(-1, 1, size=20*20), False ``` ## Usage -data reader, mapping from item(s) read to data layer, batch size and number of total pass will be passed into `paddle.train`: +data reader creator, 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: @@ -41,11 +41,11 @@ label_layer = paddle.layer.data("label", ...) paddle.train(paddle.dataset.mnist, {"image":0, "label":1}, 128, 10, ...) ``` -## Data Reader Decorators +## Data Reader Creator Decorator -Data reader decorators 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. +*Data reader creator decorator* (or *reader creator decorator*) takes a single or multiple data reader creator, returns a new data reader creator. 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: +Since we have a strict interface for data readers creators (no parameter, return a single data item). Data reader creators can be used flexiable via data reader creator decorators. Following are a few examples: ### Prefetch Data @@ -54,74 +54,77 @@ Since reading data may take time and training can not proceed without data. It i Use `paddle.reader.buffered` to prefetch data: ```python -buffered_reader = paddle.reader.buffered(paddle.dataset.mnist, 100) +buffered_reader_creator = paddle.reader.buffered(paddle.dataset.mnist, 100) ``` -`buffered_reader` will try to buffer (prefetch) `100` data entries. +`buffered_reader_creator` will try to buffer (prefetch) `100` data entries. -### Compose Multiple Data Readers +### Compose Multiple Data Reader Creators For example, we want to use a source of real images (reusing mnist dataset), and a source of fake images as input for [Generative Adversarial Networks](https://arxiv.org/abs/1406.2661). We can do: ```python -def data_reader_fake_image(): +def data_reader_creator_fake_image(): while True: yield numpy.random.uniform(-1, 1, size=20*20) -def data_reader_bool(t): - while True: - yield t +def data_reader_creator_bool(t): + def creator: + while True: + yield t + return creator -true_reader = lambda : data_reader_bool(True) -false_reader = lambda : data_reader_bool(False) +true_reader_creator = data_reader_creator_bool(True) +false_reade_creatorr = data_reader_creator_bool(False) -reader = paddle.reader.combine(paddle.dataset.mnist, data_reader_fake_image, true_reader, false_reader) +reader_creator = paddle.reader.compose(paddle.dataset.mnist, data_reader_creator_fake_image, true_reader_creator, false_reader_creator) # 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}, ...) +paddle.train(reader_creator, {"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. +Given shuffle buffer size `n`, `paddle.reader.shuffle` will return a data reader creator that buffers `n` data entries and shuffle them before a data entry is read. Example: ```python -reader = paddle.reader.shuffle(paddle.dataset.mnist, 512) +reader_creator = 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`. +If a mini batch is returned, data reader creator 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 reader much easier (e.g., if existing data 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). +Practically, always return a single entry make reusing existing data reader creators much easier (e.g., if existing reader creator 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 +### How to create custom data reader creator ```python -def image_reader(image_path, label_path, n): - 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() - -# use python lambda to change image_reader into a function with no parameters. -reader = lambda : image_reader("/path/to/image_file", "/path/to/label_file", 1024) -paddle.train(reader, {"image":0, "label":1}, ...) +def image_reader_creator(image_path, label_path, n): + def reader_creator(): + 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_creator + +reader_creator = image_reader_creator("/path/to/image_file", "/path/to/label_file", 1024) +paddle.train(reader_creator, {"image":0, "label":1}, ...) ``` ### How is `paddle.train` implemented @@ -129,17 +132,17 @@ paddle.train(reader, {"image":0, "label":1}, ...) An example implementation of paddle.train could be: ```python -def minibatch_decorater(reader, minibatch_size): +def minibatch_decorater(reader_creator, minibatch_size): def ret(): - r = reader() + r = reader_creator() 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): +def train(reader_creator, mapping, batch_size, total_pass): for pass_idx in range(total_pass): - for mini_batch in minibatch_decorater(reader): # this loop will never end in online learning. + for mini_batch in minibatch_decorater(reader_creator): # this loop will never end in online learning. do_forward_backward(mini_batch, mapping) ``` From 478b0c8a904b8db0d59d070d4c82db6704d333a7 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Tue, 21 Feb 2017 15:10:42 -0800 Subject: [PATCH 247/370] correct data reader and data reader creator usage --- doc/design/reader/README.md | 73 +++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/doc/design/reader/README.md b/doc/design/reader/README.md index f8f79a75b1db09..230b8c2326b526 100644 --- a/doc/design/reader/README.md +++ b/doc/design/reader/README.md @@ -1,35 +1,35 @@ -# Python Data Reading Design Doc +# Python Data Reader Design Doc -Paddle reads data from *data reader* during training. *data reader creator* (or *reader creator*) creates a *data reader* when invoked. *reader creator* will be passed into `paddle.train` as a parameter. +Paddle reads data from *data reader* during training. *data reader* will be passed into `paddle.train` as a parameter. -## Data Reader Creator Interface +## Data Reader Interface -Data reader creator is a function with no parameter that creates a iterable (anything can be used in `for x in iterable`): +Data reader is a function with no parameter that creates a iterable (anything can be used in `for x in iterable`): ``` -iterable = data_reader_creator() +iterable = data_reader() ``` Element produced for 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: +An example implementation for single item data reader: ```python -def data_reader_creator_fake_image(): +def data_reader_fake_image(): while True: yield numpy.random.uniform(-1, 1, size=20*20) ``` -An example implementation for multiple item data reader creator: +An example implementation for multiple item data reader: ```python -def data_reader_creator_fake_image_and_label(): +def data_reader_fake_image_and_label(): while True: yield numpy.random.uniform(-1, 1, size=20*20), False ``` ## Usage -data reader creator, mapping from item(s) read to data layer, batch size and number of total pass will be passed into `paddle.train`: +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: @@ -41,11 +41,11 @@ label_layer = paddle.layer.data("label", ...) paddle.train(paddle.dataset.mnist, {"image":0, "label":1}, 128, 10, ...) ``` -## Data Reader Creator Decorator +## Data Reader Decorator -*Data reader creator decorator* (or *reader creator decorator*) takes a single or multiple data reader creator, returns a new data reader creator. It is similar to a [python decorator](https://wiki.python.org/moin/PythonDecorators), but it does not use `@` syntax. +*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 creators (no parameter, return a single data item). Data reader creators can be used flexiable via data reader creator decorators. Following are a few examples: +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 @@ -54,63 +54,63 @@ Since reading data may take time and training can not proceed without data. It i Use `paddle.reader.buffered` to prefetch data: ```python -buffered_reader_creator = paddle.reader.buffered(paddle.dataset.mnist, 100) +buffered_reader = paddle.reader.buffered(paddle.dataset.mnist, 100) ``` -`buffered_reader_creator` will try to buffer (prefetch) `100` data entries. +`buffered_reader` will try to buffer (prefetch) `100` data entries. -### Compose Multiple Data Reader Creators +### Compose Multiple Data Readers For example, we want to use a source of real images (reusing mnist dataset), and a source of fake images as input for [Generative Adversarial Networks](https://arxiv.org/abs/1406.2661). We can do: ```python -def data_reader_creator_fake_image(): +def data_reader_fake_image(): while True: yield numpy.random.uniform(-1, 1, size=20*20) def data_reader_creator_bool(t): - def creator: + def reader: while True: yield t - return creator + return reader -true_reader_creator = data_reader_creator_bool(True) -false_reade_creatorr = data_reader_creator_bool(False) +true_reader = data_reader_creator_bool(True) +false_reader = data_reader_creator_bool(False) -reader_creator = paddle.reader.compose(paddle.dataset.mnist, data_reader_creator_fake_image, true_reader_creator, false_reader_creator) +reader = paddle.reader.compose(paddle.dataset.mnist, data_reader_fake_image, 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_creator, {"true_image":0, "fake_image": 2, "true_label": 3, "false_label": 4}, ...) +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 creator that buffers `n` data entries and shuffle them before a data entry is read. +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_creator = paddle.reader.shuffle(paddle.dataset.mnist, 512) +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 creator 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`. +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 reader creators much easier (e.g., if existing reader creator return not a single entry but 3 entries, training code will be more complex because it need to handle cases like batch size 2). +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 +### How to create custom data reader ```python def image_reader_creator(image_path, label_path, n): - def reader_creator(): + def reader(): f = open(image_path) l = open(label_path) images = numpy.fromfile( @@ -121,10 +121,11 @@ def image_reader_creator(image_path, label_path, n): yield images[i, :], labels[i] # a single entry of data is created each time f.close() l.close() - return reader_creator + return reader -reader_creator = image_reader_creator("/path/to/image_file", "/path/to/label_file", 1024) -paddle.train(reader_creator, {"image":0, "label":1}, ...) +# 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 @@ -132,17 +133,17 @@ paddle.train(reader_creator, {"image":0, "label":1}, ...) An example implementation of paddle.train could be: ```python -def minibatch_decorater(reader_creator, minibatch_size): +def minibatch_decorater(reader, minibatch_size): def ret(): - r = reader_creator() + 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_creator, mapping, batch_size, total_pass): +def train(reader, mapping, batch_size, total_pass): for pass_idx in range(total_pass): - for mini_batch in minibatch_decorater(reader_creator): # this loop will never end in online learning. + for mini_batch in minibatch_decorater(reader): # this loop will never end in online learning. do_forward_backward(mini_batch, mapping) ``` From 5688c381084b8070243826304abc046651743e54 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Tue, 21 Feb 2017 15:26:13 -0800 Subject: [PATCH 248/370] fix according to comments --- doc/design/reader/README.md | 44 +++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/doc/design/reader/README.md b/doc/design/reader/README.md index 230b8c2326b526..85efb49bc3a81a 100644 --- a/doc/design/reader/README.md +++ b/doc/design/reader/README.md @@ -1,10 +1,16 @@ # Python Data Reader Design Doc -Paddle reads data from *data reader* during training. *data reader* will be passed into `paddle.train` as a parameter. +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 -Data reader is a function with no parameter that creates a iterable (anything can be used in `for x in iterable`): +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() @@ -15,16 +21,20 @@ Element produced for the iterable should be a **single** entry of data, **not** An example implementation for single item data reader: ```python -def data_reader_fake_image(): - while True: - yield numpy.random.uniform(-1, 1, size=20*20) +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: ```python -def data_reader_fake_image_and_label(): - while True: - yield numpy.random.uniform(-1, 1, size=20*20), False +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 @@ -61,25 +71,27 @@ buffered_reader = paddle.reader.buffered(paddle.dataset.mnist, 100) ### Compose Multiple Data Readers -For example, we want to use a source of real images (reusing mnist dataset), and a source of fake images as input for [Generative Adversarial Networks](https://arxiv.org/abs/1406.2661). +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 data_reader_fake_image(): - while True: - yield numpy.random.uniform(-1, 1, size=20*20) +def reader_creator_random_image(width, height): + def reader(): + while True: + yield numpy.random.uniform(-1, 1, size=width*height) + return reader -def data_reader_creator_bool(t): +def reader_creator_bool(t): def reader: while True: yield t return reader -true_reader = data_reader_creator_bool(True) -false_reader = data_reader_creator_bool(False) +true_reader = reader_creator_bool(True) +false_reader = reader_creator_bool(False) -reader = paddle.reader.compose(paddle.dataset.mnist, data_reader_fake_image, true_reader, false_reader) +reader = paddle.reader.compose(paddle.dataset.mnist, data_reader_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}, ...) From 794c220d49c4588fdd75d2454e6224ba6d91f531 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Tue, 21 Feb 2017 15:32:11 -0800 Subject: [PATCH 249/370] more fixes --- doc/design/reader/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/design/reader/README.md b/doc/design/reader/README.md index 85efb49bc3a81a..17d52b9e20b813 100644 --- a/doc/design/reader/README.md +++ b/doc/design/reader/README.md @@ -16,9 +16,9 @@ Indeed, *data reader* doesn't have to be a function that reads and yields data i iterable = data_reader() ``` -Element produced for 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) +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: +An example implementation for single item data reader creator: ```python def reader_creator_random_image(width, height): @@ -28,7 +28,7 @@ def reader_creator_random_image(width, height): return reader ``` -An example implementation for multiple item data reader: +An example implementation for multiple item data reader creator: ```python def reader_creator_random_imageand_label(widht, height, label): def reader(): @@ -91,7 +91,7 @@ def reader_creator_bool(t): true_reader = reader_creator_bool(True) false_reader = reader_creator_bool(False) -reader = paddle.reader.compose(paddle.dataset.mnist, data_reader_random_image(20, 20), true_reader, false_reader) +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}, ...) @@ -118,7 +118,7 @@ Practically, always return a single entry make reusing existing data readers muc 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 +### How to create custom data reader creator ```python def image_reader_creator(image_path, label_path, n): @@ -145,7 +145,7 @@ paddle.train(reader, {"image":0, "label":1}, ...) An example implementation of paddle.train could be: ```python -def minibatch_decorater(reader, minibatch_size): +def make_minibatch(reader, minibatch_size): def ret(): r = reader() buf = [r.next() for x in xrange(minibatch_size)] @@ -156,6 +156,6 @@ def minibatch_decorater(reader, minibatch_size): def train(reader, mapping, batch_size, total_pass): for pass_idx in range(total_pass): - for mini_batch in minibatch_decorater(reader): # this loop will never end in online learning. + for mini_batch in make_minibatch(reader): # this loop will never end in online learning. do_forward_backward(mini_batch, mapping) ``` From 7fd42b8cce0585d2ff276f2cbd075a6ec5a502d0 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Tue, 21 Feb 2017 14:32:36 -0800 Subject: [PATCH 250/370] create reader creator decorators: shuffle, compose, chain --- python/paddle/reader/decorator.py | 139 +++++++++++++++++-- python/paddle/reader/tests/decorator_test.py | 71 +++++++++- 2 files changed, 193 insertions(+), 17 deletions(-) diff --git a/python/paddle/reader/decorator.py b/python/paddle/reader/decorator.py index f0ddb0ff812b15..dcfaf70587084e 100644 --- a/python/paddle/reader/decorator.py +++ b/python/paddle/reader/decorator.py @@ -12,25 +12,142 @@ # See the License for the specific language governing permissions and # limitations under the License. -__all__ = ['buffered'] +__all__ = ['buffered', 'compose', 'chain', 'shuffle', 'ComposeNotAligned'] from Queue import Queue from threading import Thread +import itertools +import random -def buffered(reader, size): - """Creates a buffered data reader. +def shuffle(reader_creator, buf_size): + """Creates a data reader creator whose data output is suffled. - The buffered data reader will read and save data entries into a buffer. - Reading from the buffered data reader will proceed as long as the buffer - is not empty. + Output from the iterator that created by original reader creator will be + buffered into shuffle buffer, and then shuffled. The size of shuffle buffer + is determined by argument buf_size. + + Args: + reader_creator: the original reader creator whose output will be + shuffled. + buf_size: shuffle buffer size. + + Returns: + the new reader creator whose output is shuffled. + """ + + def create_reader_creator(): + buf = [] + for e in reader_creator(): + buf.append(e) + if len(buf) >= buf_size: + random.shuffle(buf) + for b in buf: + yield b + buf = [] + + if len(buf) > 0: + random.shuffle(buf) + for b in buf: + yield b + + return create_reader_creator + + +def chain(*reader_creators): + """Creates a data reader creator whose output is the outputs of input data + reader creators chained together. + + If input reader creators output following data entries: + [0, 0, 0] + [1, 1, 1] + [2, 2, 2] + The chained reader creator will output: + [0, 0, 0, 1, 1, 1, 2, 2, 2] + + Args: + readers_creators: input reader creators + + Returns: + the new data reader creator. + """ + + def create_reader_creator(): + rs = [] + for r in reader_creators: + rs.append(r()) + + for e in itertools.chain(*rs): + yield e + + return create_reader_creator + + +class ComposeNotAligned: + pass + + +def compose(*reader_creators, **kwargs): + """Creates a data reader creator whose output is the combination of input + readers creators. + + If input reader creators output following data entries: + (1, 2) 3 (4, 5) + The composed reader creator will output: + (1, 2, 3, 4, 5) + + Args: + *reader_creators: reader creators that will be composed together. + check_alignment: If True, will check if input reader creators are aligned + correctly. If False, will not check alignment and trailing outputs + will be discarded. Defaults to True. + + Returns: + the new data reader creator. + + Raises: + ComposeNotAligned: outputs of reader creators are not aligned. + Will not raise when check_alignment is set to False. + """ + check_alignment = kwargs.pop('check_alignment', True) + + def make_tuple(x): + if isinstance(x, tuple): + return x + else: + return (x, ) + + def create_reader_creator(): + rs = [] + for r in reader_creators: + rs.append(r()) + if not check_alignment: + for outputs in itertools.izip(*rs): + yield sum(map(make_tuple, outputs), ()) + else: + for outputs in itertools.izip_longest(*rs): + for o in outputs: + if o is None: + # None will be not be present if compose is aligned + raise ComposeNotAligned + yield sum(map(make_tuple, outputs), ()) + + return create_reader_creator + + +def buffered(reader_creator, size): + """Creates a buffered data reader creator. + + The buffered data reader creator will read and save data entries into a + buffer. Reading from the buffered data reader creator will proceed as long + as the buffer is not empty. Args: - reader: the data reader to read from. + reader_creator: the data reader creator to read from. size: max buffer size. Returns: - The buffered data reader. + The buffered data reader creator. """ class EndSignal(): @@ -43,8 +160,8 @@ def read_worker(r, q): q.put(d) q.put(end) - def create_reader(): - r = reader() + def create_reader_creator(): + r = reader_creator() q = Queue(maxsize=size) t = Thread( target=read_worker, args=( @@ -57,4 +174,4 @@ def create_reader(): yield e e = q.get() - return create_reader + return create_reader_creator diff --git a/python/paddle/reader/tests/decorator_test.py b/python/paddle/reader/tests/decorator_test.py index 879d1d9c1d0e06..2830d41bf0a243 100644 --- a/python/paddle/reader/tests/decorator_test.py +++ b/python/paddle/reader/tests/decorator_test.py @@ -17,15 +17,18 @@ def reader_10(dur): - for i in range(10): - time.sleep(dur) - yield i + def reader(): + for i in range(10): + time.sleep(dur) + yield i + + return reader class TestBuffered(unittest.TestCase): def test_read(self): for size in range(20): - b = paddle.reader.buffered(lambda: reader_10(0), size) + b = paddle.reader.buffered(reader_10(0), size) c = 0 for i in b(): self.assertEqual(i, c) @@ -34,7 +37,7 @@ def test_read(self): def test_buffering(self): # read have 30ms delay. - b = paddle.reader.buffered(lambda: reader_10(0.03), 10) + b = paddle.reader.buffered(reader_10(0.03), 10) last_time = time.time() for idx, i in enumerate(b()): elapsed_time = time.time() - last_time @@ -42,9 +45,65 @@ def test_buffering(self): time.sleep(0.3) else: # read time should be short, meaning already buffered. - self.assertLess(elapsed_time, 0.01) + self.assertLess(elapsed_time, 0.05) last_time = time.time() +class TestCompose(unittest.TestCase): + def test_compse(self): + a = reader_10(0) + b = reader_10(0) + c = paddle.reader.compose(a, b) + for idx, e in enumerate(c()): + self.assertEqual(e, (idx, idx)) + + def test_compose_not_aligned(self): + a = reader_10(0) + b = paddle.reader.chain(a, a) + c = paddle.reader.compose(a, b) + total = 0 + with self.assertRaises(paddle.reader.ComposeNotAligned): + for e in c(): + total += 1 + # expecting 10, not 20 + self.assertEqual(total, 10) + + def test_compose_not_aligned_no_check(self): + a = reader_10(0) + b = paddle.reader.chain(a, a) + c = paddle.reader.compose(a, b, check_alignment=False) + total = 0 + for e in c(): + total += 1 + # expecting 10, not 20 + self.assertEqual(total, 10) + + +class TestChain(unittest.TestCase): + def test_chain(self): + a = reader_10(0) + b = reader_10(0) + c = paddle.reader.chain(a, b) + idx = 0 + for e in c(): + self.assertEqual(e, idx % 10) + idx += 1 + self.assertEqual(idx, 20) + + +class TestShuffle(unittest.TestCase): + def test_shuffle(self): + case = [(0, True), (1, True), (10, False), (100, False)] + a = reader_10(0) + for size, checkEq in case: + s = paddle.reader.shuffle(a, size) + total = 0 + for idx, e in enumerate(s()): + if checkEq: + self.assertEqual(idx, e) + total += 1 + self.assertEqual(total, 10) + + if __name__ == '__main__': unittest.main() From 2a21681c00b740627d6f5c37b89550f2990704f4 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Tue, 21 Feb 2017 16:21:57 -0800 Subject: [PATCH 251/370] fix according to comments --- python/paddle/reader/decorator.py | 77 ++++++++++---------- python/paddle/reader/tests/decorator_test.py | 37 +++++----- 2 files changed, 56 insertions(+), 58 deletions(-) diff --git a/python/paddle/reader/decorator.py b/python/paddle/reader/decorator.py index dcfaf70587084e..1192b5de90f980 100644 --- a/python/paddle/reader/decorator.py +++ b/python/paddle/reader/decorator.py @@ -20,25 +20,25 @@ import random -def shuffle(reader_creator, buf_size): - """Creates a data reader creator whose data output is suffled. +def shuffle(reader, buf_size): + """Creates a data reader whose data output is suffled. - Output from the iterator that created by original reader creator will be + Output from the iterator that created by original reader will be buffered into shuffle buffer, and then shuffled. The size of shuffle buffer is determined by argument buf_size. Args: - reader_creator: the original reader creator whose output will be + reader: the original reader whose output will be shuffled. buf_size: shuffle buffer size. Returns: - the new reader creator whose output is shuffled. + the new reader whose output is shuffled. """ - def create_reader_creator(): + def data_reader(): buf = [] - for e in reader_creator(): + for e in reader(): buf.append(e) if len(buf) >= buf_size: random.shuffle(buf) @@ -51,62 +51,61 @@ def create_reader_creator(): for b in buf: yield b - return create_reader_creator + return data_reader -def chain(*reader_creators): - """Creates a data reader creator whose output is the outputs of input data - reader creators chained together. +def chain(*readers): + """Creates a data reader whose output is the outputs of input data + readers chained together. - If input reader creators output following data entries: + If input readers output following data entries: [0, 0, 0] [1, 1, 1] [2, 2, 2] - The chained reader creator will output: + The chained reader will output: [0, 0, 0, 1, 1, 1, 2, 2, 2] Args: - readers_creators: input reader creators + readerss: input readers. Returns: - the new data reader creator. + the new data reader. """ - def create_reader_creator(): + def reader(): rs = [] - for r in reader_creators: + for r in readers: rs.append(r()) for e in itertools.chain(*rs): yield e - return create_reader_creator + return reader class ComposeNotAligned: pass -def compose(*reader_creators, **kwargs): - """Creates a data reader creator whose output is the combination of input - readers creators. +def compose(*readers, **kwargs): + """Creates a data reader whose output is the combination of input readers. - If input reader creators output following data entries: + If input readers output following data entries: (1, 2) 3 (4, 5) - The composed reader creator will output: + The composed reader will output: (1, 2, 3, 4, 5) Args: - *reader_creators: reader creators that will be composed together. - check_alignment: If True, will check if input reader creators are aligned + *readers: readers that will be composed together. + check_alignment: If True, will check if input readers are aligned correctly. If False, will not check alignment and trailing outputs will be discarded. Defaults to True. Returns: - the new data reader creator. + the new data reader. Raises: - ComposeNotAligned: outputs of reader creators are not aligned. + ComposeNotAligned: outputs of readers are not aligned. Will not raise when check_alignment is set to False. """ check_alignment = kwargs.pop('check_alignment', True) @@ -117,9 +116,9 @@ def make_tuple(x): else: return (x, ) - def create_reader_creator(): + def reader(): rs = [] - for r in reader_creators: + for r in readers: rs.append(r()) if not check_alignment: for outputs in itertools.izip(*rs): @@ -132,22 +131,22 @@ def create_reader_creator(): raise ComposeNotAligned yield sum(map(make_tuple, outputs), ()) - return create_reader_creator + return reader -def buffered(reader_creator, size): - """Creates a buffered data reader creator. +def buffered(reader, size): + """Creates a buffered data reader. - The buffered data reader creator will read and save data entries into a - buffer. Reading from the buffered data reader creator will proceed as long + The buffered data reader will read and save data entries into a + buffer. Reading from the buffered data reader will proceed as long as the buffer is not empty. Args: - reader_creator: the data reader creator to read from. + reader: the data reader to read from. size: max buffer size. Returns: - The buffered data reader creator. + The buffered data reader. """ class EndSignal(): @@ -160,8 +159,8 @@ def read_worker(r, q): q.put(d) q.put(end) - def create_reader_creator(): - r = reader_creator() + def data_reader(): + r = reader() q = Queue(maxsize=size) t = Thread( target=read_worker, args=( @@ -174,4 +173,4 @@ def create_reader_creator(): yield e e = q.get() - return create_reader_creator + return data_reader diff --git a/python/paddle/reader/tests/decorator_test.py b/python/paddle/reader/tests/decorator_test.py index 2830d41bf0a243..46eec44158cee5 100644 --- a/python/paddle/reader/tests/decorator_test.py +++ b/python/paddle/reader/tests/decorator_test.py @@ -16,9 +16,10 @@ import time -def reader_10(dur): +def reader_creator_10(dur): def reader(): for i in range(10): + # this invocation helps testing paddle.reader.buffer time.sleep(dur) yield i @@ -28,7 +29,7 @@ def reader(): class TestBuffered(unittest.TestCase): def test_read(self): for size in range(20): - b = paddle.reader.buffered(reader_10(0), size) + b = paddle.reader.buffered(reader_creator_10(0), size) c = 0 for i in b(): self.assertEqual(i, c) @@ -37,7 +38,7 @@ def test_read(self): def test_buffering(self): # read have 30ms delay. - b = paddle.reader.buffered(reader_10(0.03), 10) + b = paddle.reader.buffered(reader_creator_10(0.03), 10) last_time = time.time() for idx, i in enumerate(b()): elapsed_time = time.time() - last_time @@ -51,29 +52,29 @@ def test_buffering(self): class TestCompose(unittest.TestCase): def test_compse(self): - a = reader_10(0) - b = reader_10(0) - c = paddle.reader.compose(a, b) - for idx, e in enumerate(c()): + reader = paddle.reader.compose( + reader_creator_10(0), reader_creator_10(0)) + for idx, e in enumerate(reader()): self.assertEqual(e, (idx, idx)) def test_compose_not_aligned(self): - a = reader_10(0) - b = paddle.reader.chain(a, a) - c = paddle.reader.compose(a, b) total = 0 + reader = paddle.reader.compose( + paddle.reader.chain(reader_creator_10(0), reader_creator_10(0)), + reader_creator_10(0)) with self.assertRaises(paddle.reader.ComposeNotAligned): - for e in c(): + for e in reader(): total += 1 # expecting 10, not 20 self.assertEqual(total, 10) def test_compose_not_aligned_no_check(self): - a = reader_10(0) - b = paddle.reader.chain(a, a) - c = paddle.reader.compose(a, b, check_alignment=False) total = 0 - for e in c(): + reader = paddle.reader.compose( + paddle.reader.chain(reader_creator_10(0), reader_creator_10(0)), + reader_creator_10(0), + check_alignment=False) + for e in reader(): total += 1 # expecting 10, not 20 self.assertEqual(total, 10) @@ -81,9 +82,7 @@ def test_compose_not_aligned_no_check(self): class TestChain(unittest.TestCase): def test_chain(self): - a = reader_10(0) - b = reader_10(0) - c = paddle.reader.chain(a, b) + c = paddle.reader.chain(reader_creator_10(0), reader_creator_10(0)) idx = 0 for e in c(): self.assertEqual(e, idx % 10) @@ -94,7 +93,7 @@ def test_chain(self): class TestShuffle(unittest.TestCase): def test_shuffle(self): case = [(0, True), (1, True), (10, False), (100, False)] - a = reader_10(0) + a = reader_creator_10(0) for size, checkEq in case: s = paddle.reader.shuffle(a, size) total = 0 From e19134e0cc0b6f143bb31430765c3fad82d2f54f Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Wed, 22 Feb 2017 11:52:37 +0800 Subject: [PATCH 252/370] add cost function in v2.layer --- python/paddle/v2/layer.py | 53 +++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 507725ee4ff712..cd6dd5110a44b2 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -77,7 +77,9 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. __all__ = [ 'parse_network', 'data', 'fc', 'max_id', 'classification_cost', - 'cross_entropy_cost' + 'cross_entropy_cost', 'cross_entropy_with_selfnorm_cost', 'regression_cost', + 'multi_binary_label_cross_entropy_cost', 'rank_cost', 'lambda_cost', + 'sum_cost', 'huber_cost' ] @@ -137,7 +139,8 @@ def __init__(self, name=None, **kwargs): parent_layers = dict() other_kwargs = dict() for pname in parent_names: - parent_layers[pname] = kwargs[pname] + if kwargs.has_key(pname): + parent_layers[pname] = kwargs[pname] for key in kwargs.keys(): if key not in parent_names: @@ -189,27 +192,61 @@ def to_proto_impl(self, **kwargs): data = DataLayerV2 fc = __convert_to_v2__('fc_layer', name_prefix='fc', parent_names=['input']) max_id = __convert_to_v2__( - 'maxid_layer', name_prefix='maxid_layer', parent_names=['input']) + 'maxid_layer', name_prefix='maxid', parent_names=['input']) classification_cost = __convert_to_v2__( 'classification_cost', name_prefix='classification_cost', - parent_names=['input', 'label']) + parent_names=['input', 'label', 'weight']) +regression_cost = __convert_to_v2__( + 'regression_cost', + name_prefix='regression_cost', + parent_names=['input', 'label', 'weight']) cross_entropy_cost = __convert_to_v2__( 'cross_entropy', name_prefix='cross_entropy', parent_names=['input', 'label']) +cross_entropy_with_selfnorm_cost = __convert_to_v2__( + 'cross_entropy_with_selfnorm', + name_prefix='cross_entropy_with_selfnorm', + parent_names=['input', 'label']) +multi_binary_label_cross_entropy_cost = __convert_to_v2__( + 'multi_binary_label_cross_entropy', + name_prefix='multi_binary_label_cross_entropy', + parent_names=['input', 'label']) +rank_cost = __convert_to_v2__( + 'rank_cost', + name_prefix='rank_cost', + parent_names=['left', 'right', 'label', 'weight']) +lambda_cost = __convert_to_v2__( + 'lambda_cost', name_prefix='lambda_cost', parent_names=['input', 'score']) +sum_cost = __convert_to_v2__( + 'sum_cost', name_prefix='sum_cost', parent_names=['input']) +huber_cost = __convert_to_v2__( + 'huber_cost', name_prefix='huber_cost', parent_names=['input', 'label']) if __name__ == '__main__': pixel = data(name='pixel', type=data_type.dense_vector(784)) label = data(name='label', type=data_type.integer_value(10)) + weight = data(name='weight', type=data_type.dense_vector(10)) + score = data(name='score', type=data_type.dense_vector(1)) + hidden = fc(input=pixel, size=100, act=conf_helps.SigmoidActivation()) inference = fc(input=hidden, size=10, act=conf_helps.SoftmaxActivation()) maxid = max_id(input=inference) cost1 = classification_cost(input=inference, label=label) - cost2 = cross_entropy_cost(input=inference, label=label) + cost2 = classification_cost(input=inference, label=label, weight=weight) + cost3 = cross_entropy_cost(input=inference, label=label) + cost4 = cross_entropy_with_selfnorm_cost(input=inference, label=label) + cost5 = regression_cost(input=inference, label=label) + cost6 = regression_cost(input=inference, label=label, weight=weight) + cost7 = multi_binary_label_cross_entropy_cost(input=inference, label=label) + cost8 = rank_cost(left=score, right=score, label=score) + cost9 = lambda_cost(input=inference, score=score) + cost10 = sum_cost(input=inference) + cost11 = huber_cost(input=score, label=label) - print parse_network(cost1) - print parse_network(cost2) print parse_network(cost1, cost2) - print parse_network(cost2) + print parse_network(cost3, cost4) + print parse_network(cost5, cost6) + print parse_network(cost7, cost8, cost9, cost10, cost11) print parse_network(inference, maxid) From e00f06afa44211a68e29018603c6f7ab982ccce3 Mon Sep 17 00:00:00 2001 From: Liang Zhao Date: Tue, 14 Feb 2017 09:51:11 -0800 Subject: [PATCH 253/370] Add top-k error --- paddle/gserver/evaluators/Evaluator.cpp | 61 ++++++++++++++++++- paddle/math/Matrix.cpp | 4 +- paddle/parameter/Parameter.cpp | 4 +- .../trainer_config_helpers/evaluators.py | 1 - 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index 2bf6ead0dc382c..70f2da45ea18c3 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -76,9 +76,55 @@ class ClassificationErrorEvaluator : public Evaluator { 1, /* trans= */ false, useGpu(arguments[0].deviceId)); + const MatrixPtr errorMat2 = Matrix::create(output->getHeight(), + 1, + /* trans= */ false, false); + // useGpu(arguments[0].deviceId)); errorMat->zeroMem(); + if (label != nullptr) { - errorMat->classificationError(*output, *label); + errorMat->classificationError(output, label); // top-1 error + size_t height = output->getHeight(); + size_t width = 5; // config_.num_results(); + + IVector::resizeOrCreate(maxIds_, height * width, + useGpu(arguments[0].deviceId)); + Matrix::resizeOrCreate(maxValues_, height, width, false, + useGpu(arguments[0].deviceId)); + output->rowMax(*maxIds_, *maxValues_); // top-5 values + + int* ids; + int* lbl; + if (useGpu(arguments[0].deviceId)) { + IVectorPtr dest = IVector::create(maxIds_->getSize(), false); + hl_memcpy_device2host((void*)dest->getData(), + (void*)maxIds_->getData(), + sizeof(int) * maxIds_->getSize()); + ids = dest->getData(); + + IVectorPtr dest2 = IVector::create(label->getSize(), false); + hl_memcpy_device2host((void*)dest2->getData(), + (void*)label->getData(), + sizeof(int) * label->getSize()); + lbl = dest2->getData(); + } else { + ids = maxIds_->getData(); + lbl = label->getData(); + } + + // real* result = errorMat->getData(); + real* result2 = errorMat2->getData(); + for (size_t i = 0; i < height; ++i) { + // result[i] = (ids[i * width] != lbl[i]); // top-1 error + result2[i] = (ids[i * width] != lbl[i]); // initialize top-5 error + for (size_t j = 1; j < width; ++j) { + if (result2[i] == 0.0) { + break; + } + result2[i] = (ids[i * width + j] != lbl[i]); // top-5 error + } + } + totalScore2_ = errorMat2->getSum(); } else if (dynamic_cast(multiBinaryLabel.get()) || dynamic_cast(multiBinaryLabel.get())) { errorMat->classificationErrorMulti( @@ -94,6 +140,13 @@ class ClassificationErrorEvaluator : public Evaluator { return errorMat; } + void printStats(std::ostream& os) const { + os << "top_1_error=" + << (numSamples_ ? totalScore_ / numSamples_ : 0) + << " top_5_error=" + << (numSamples_ ? totalScore2_ / numSamples_ : 0); + } + virtual real evalImp(std::vector& arguments) { MatrixPtr errorMat = calcError(arguments); return errorMat->getSum(); @@ -102,6 +155,12 @@ class ClassificationErrorEvaluator : public Evaluator { virtual void distributeEval(ParameterClient2* client) { mergeResultsOfAllClients(client); } + + +private: + IVectorPtr maxIds_; + MatrixPtr maxValues_; + double totalScore2_; }; /** diff --git a/paddle/math/Matrix.cpp b/paddle/math/Matrix.cpp index 1964b2f8bfaebc..446dd30567856f 100644 --- a/paddle/math/Matrix.cpp +++ b/paddle/math/Matrix.cpp @@ -732,6 +732,7 @@ void GpuMatrix::rowMax(IVector& maxIds, Matrix& maxVal) { size_t beam = maxVal.getWidth(); CHECK_EQ(maxIds.getSize(), numSamples * beam); CHECK_EQ(maxVal.getHeight(), numSamples); + CHECK_EQ(maxVal.getWidth(), beam); hl_matrix_top_k(maxVal.getData(), maxVal.getStride(), @@ -3039,7 +3040,7 @@ void CpuMatrix::rowMax(Matrix& max) { max.maxRows(*this); } -/* get beam size of max ids and values */ +/* Get the top k elements of each row of this matrix */ void CpuMatrix::rowMax(IVector& maxIds, Matrix& maxVal) { CHECK(isContiguous()); CHECK(!maxIds.useGpu() && !maxVal.useGpu()) << "Matrix type are not equal"; @@ -3047,6 +3048,7 @@ void CpuMatrix::rowMax(IVector& maxIds, Matrix& maxVal) { size_t beam = maxVal.getWidth(); CHECK_EQ(maxIds.getSize(), numSamples * beam); CHECK_EQ(maxVal.getHeight(), numSamples); + CHECK_EQ(maxVal.getWidth(), beam); real* a = getData(); int* s = maxIds.getData(); diff --git a/paddle/parameter/Parameter.cpp b/paddle/parameter/Parameter.cpp index 29d6e20dc16968..9e7b4ea39d4ea6 100644 --- a/paddle/parameter/Parameter.cpp +++ b/paddle/parameter/Parameter.cpp @@ -375,10 +375,10 @@ bool Parameter::load(const std::string& filename) { std::ifstream fs(filename, std::ios_base::binary); if (!fs) { LOG(INFO) << "missing parameters [" << filename << "] while loading model."; - if (isStatic()) { + /*if (isStatic()) { LOG(FATAL) << getName() << " is static but missing, not allowed."; return false; - } + }*/ if (kMissParameterFail == FLAGS_load_missing_parameter_strategy) { LOG(FATAL) << getName() << " missing, not allowed."; return false; diff --git a/python/paddle/trainer_config_helpers/evaluators.py b/python/paddle/trainer_config_helpers/evaluators.py index bd247ea9af9d8d..236128f1bade11 100644 --- a/python/paddle/trainer_config_helpers/evaluators.py +++ b/python/paddle/trainer_config_helpers/evaluators.py @@ -495,7 +495,6 @@ def gradient_printer_evaluator( """ evaluator_base(name=name, type="gradient_printer", input=input) - @evaluator(EvaluatorAttribute.FOR_PRINT) @wrap_name_default() def maxid_printer_evaluator( From 5250b9b21321da5b5b4aa584aa9e4f75ad314036 Mon Sep 17 00:00:00 2001 From: Liang Zhao Date: Tue, 14 Feb 2017 11:14:21 -0800 Subject: [PATCH 254/370] fix classificationError input --- paddle/gserver/evaluators/Evaluator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index 70f2da45ea18c3..1c202259831c38 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -83,7 +83,7 @@ class ClassificationErrorEvaluator : public Evaluator { errorMat->zeroMem(); if (label != nullptr) { - errorMat->classificationError(output, label); // top-1 error + errorMat->classificationError(*output, *label); // top-1 error size_t height = output->getHeight(); size_t width = 5; // config_.num_results(); From 043859b5db83da51bfb66c9cab5d276321c6e4b6 Mon Sep 17 00:00:00 2001 From: Liang Zhao Date: Tue, 14 Feb 2017 15:32:07 -0800 Subject: [PATCH 255/370] clean up code --- paddle/gserver/evaluators/Evaluator.cpp | 38 +++++++++---------- .../trainer_config_helpers/evaluators.py | 1 + 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index 1c202259831c38..5fbba77b48766d 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -78,45 +78,44 @@ class ClassificationErrorEvaluator : public Evaluator { useGpu(arguments[0].deviceId)); const MatrixPtr errorMat2 = Matrix::create(output->getHeight(), 1, - /* trans= */ false, false); - // useGpu(arguments[0].deviceId)); + /* trans= */ false, + false); + errorMat->zeroMem(); if (label != nullptr) { errorMat->classificationError(*output, *label); // top-1 error size_t height = output->getHeight(); - size_t width = 5; // config_.num_results(); + size_t width = 5; - IVector::resizeOrCreate(maxIds_, height * width, - useGpu(arguments[0].deviceId)); - Matrix::resizeOrCreate(maxValues_, height, width, false, - useGpu(arguments[0].deviceId)); + IVector::resizeOrCreate( + maxIds_, height * width, useGpu(arguments[0].deviceId)); + Matrix::resizeOrCreate( + maxValues_, height, width, false, useGpu(arguments[0].deviceId)); output->rowMax(*maxIds_, *maxValues_); // top-5 values - int* ids; - int* lbl; + int* ids = nullptr; + int* lbl = nullptr; if (useGpu(arguments[0].deviceId)) { IVectorPtr dest = IVector::create(maxIds_->getSize(), false); hl_memcpy_device2host((void*)dest->getData(), - (void*)maxIds_->getData(), - sizeof(int) * maxIds_->getSize()); + (void*)maxIds_->getData(), + sizeof(int) * maxIds_->getSize()); ids = dest->getData(); IVectorPtr dest2 = IVector::create(label->getSize(), false); hl_memcpy_device2host((void*)dest2->getData(), - (void*)label->getData(), - sizeof(int) * label->getSize()); + (void*)label->getData(), + sizeof(int) * label->getSize()); lbl = dest2->getData(); } else { ids = maxIds_->getData(); lbl = label->getData(); } - // real* result = errorMat->getData(); real* result2 = errorMat2->getData(); for (size_t i = 0; i < height; ++i) { - // result[i] = (ids[i * width] != lbl[i]); // top-1 error - result2[i] = (ids[i * width] != lbl[i]); // initialize top-5 error + result2[i] = (ids[i * width] != lbl[i]); // initialize top-5 error for (size_t j = 1; j < width; ++j) { if (result2[i] == 0.0) { break; @@ -141,10 +140,8 @@ class ClassificationErrorEvaluator : public Evaluator { } void printStats(std::ostream& os) const { - os << "top_1_error=" - << (numSamples_ ? totalScore_ / numSamples_ : 0) - << " top_5_error=" - << (numSamples_ ? totalScore2_ / numSamples_ : 0); + os << "top_1_error=" << (numSamples_ ? totalScore_ / numSamples_ : 0) + << " top_5_error=" << (numSamples_ ? totalScore2_ / numSamples_ : 0); } virtual real evalImp(std::vector& arguments) { @@ -156,7 +153,6 @@ class ClassificationErrorEvaluator : public Evaluator { mergeResultsOfAllClients(client); } - private: IVectorPtr maxIds_; MatrixPtr maxValues_; diff --git a/python/paddle/trainer_config_helpers/evaluators.py b/python/paddle/trainer_config_helpers/evaluators.py index 236128f1bade11..bd247ea9af9d8d 100644 --- a/python/paddle/trainer_config_helpers/evaluators.py +++ b/python/paddle/trainer_config_helpers/evaluators.py @@ -495,6 +495,7 @@ def gradient_printer_evaluator( """ evaluator_base(name=name, type="gradient_printer", input=input) + @evaluator(EvaluatorAttribute.FOR_PRINT) @wrap_name_default() def maxid_printer_evaluator( From 413cbb8432255349d9152449597cb3b96d037495 Mon Sep 17 00:00:00 2001 From: Liang Zhao Date: Tue, 14 Feb 2017 16:58:41 -0800 Subject: [PATCH 256/370] fix a variable definition bug --- paddle/gserver/evaluators/Evaluator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index 5fbba77b48766d..1c2479d7280037 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -96,14 +96,14 @@ class ClassificationErrorEvaluator : public Evaluator { int* ids = nullptr; int* lbl = nullptr; + IVectorPtr dest = IVector::create(maxIds_->getSize(), false); + IVectorPtr dest2 = IVector::create(label->getSize(), false); if (useGpu(arguments[0].deviceId)) { - IVectorPtr dest = IVector::create(maxIds_->getSize(), false); hl_memcpy_device2host((void*)dest->getData(), (void*)maxIds_->getData(), sizeof(int) * maxIds_->getSize()); ids = dest->getData(); - IVectorPtr dest2 = IVector::create(label->getSize(), false); hl_memcpy_device2host((void*)dest2->getData(), (void*)label->getData(), sizeof(int) * label->getSize()); From e768721cd9bf2582e391f0b2e7dc4fb790f36e74 Mon Sep 17 00:00:00 2001 From: Liang Zhao Date: Wed, 15 Feb 2017 15:05:35 -0800 Subject: [PATCH 257/370] fix calculating totalScore2_ bug --- paddle/gserver/evaluators/Evaluator.cpp | 95 +++++++++++-------- paddle/gserver/tests/test_Evaluator.cpp | 1 + proto/ModelConfig.proto | 4 + python/paddle/trainer/config_parser.py | 3 + .../trainer_config_helpers/evaluators.py | 10 ++ .../paddle/trainer_config_helpers/layers.py | 17 ++-- 6 files changed, 85 insertions(+), 45 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index 1c2479d7280037..30e91fa222fca5 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -39,6 +39,13 @@ void Evaluator::eval(const NeuralNetwork& nn) { */ class ClassificationErrorEvaluator : public Evaluator { public: + ClassificationErrorEvaluator() : totalScore2_(0) {} + + virtual void start() { + Evaluator::start(); + totalScore2_ = 0; + } + virtual void updateSamplesNum(const std::vector& arguments) { if (3 == arguments.size()) { numSamples_ += arguments[2].value->getSum(); @@ -85,45 +92,47 @@ class ClassificationErrorEvaluator : public Evaluator { if (label != nullptr) { errorMat->classificationError(*output, *label); // top-1 error - size_t height = output->getHeight(); - size_t width = 5; - - IVector::resizeOrCreate( - maxIds_, height * width, useGpu(arguments[0].deviceId)); - Matrix::resizeOrCreate( - maxValues_, height, width, false, useGpu(arguments[0].deviceId)); - output->rowMax(*maxIds_, *maxValues_); // top-5 values - - int* ids = nullptr; - int* lbl = nullptr; - IVectorPtr dest = IVector::create(maxIds_->getSize(), false); - IVectorPtr dest2 = IVector::create(label->getSize(), false); - if (useGpu(arguments[0].deviceId)) { - hl_memcpy_device2host((void*)dest->getData(), - (void*)maxIds_->getData(), - sizeof(int) * maxIds_->getSize()); - ids = dest->getData(); - - hl_memcpy_device2host((void*)dest2->getData(), - (void*)label->getData(), - sizeof(int) * label->getSize()); - lbl = dest2->getData(); - } else { - ids = maxIds_->getData(); - lbl = label->getData(); - } + if (config_.top_k() > 1) { + size_t height = output->getHeight(); + size_t width = config_.top_k(); + + IVector::resizeOrCreate( + maxIds_, height * width, useGpu(arguments[0].deviceId)); + Matrix::resizeOrCreate( + maxValues_, height, width, false, useGpu(arguments[0].deviceId)); + output->rowMax(*maxIds_, *maxValues_); // top-k values + + int* ids = nullptr; + int* lbl = nullptr; + IVectorPtr dest = IVector::create(maxIds_->getSize(), false); + IVectorPtr dest2 = IVector::create(label->getSize(), false); + if (useGpu(arguments[0].deviceId)) { + hl_memcpy_device2host((void*)dest->getData(), + (void*)maxIds_->getData(), + sizeof(int) * maxIds_->getSize()); + ids = dest->getData(); + + hl_memcpy_device2host((void*)dest2->getData(), + (void*)label->getData(), + sizeof(int) * label->getSize()); + lbl = dest2->getData(); + } else { + ids = maxIds_->getData(); + lbl = label->getData(); + } - real* result2 = errorMat2->getData(); - for (size_t i = 0; i < height; ++i) { - result2[i] = (ids[i * width] != lbl[i]); // initialize top-5 error - for (size_t j = 1; j < width; ++j) { - if (result2[i] == 0.0) { - break; + real* result2 = errorMat2->getData(); + for (size_t i = 0; i < height; ++i) { + result2[i] = (ids[i * width] != lbl[i]); // initialize top-k error + for (size_t j = 1; j < width; ++j) { + if (result2[i] == 0.0) { + break; + } + result2[i] = (ids[i * width + j] != lbl[i]); // top-k error } - result2[i] = (ids[i * width + j] != lbl[i]); // top-5 error } + totalScore2_ += errorMat2->getSum(); } - totalScore2_ = errorMat2->getSum(); } else if (dynamic_cast(multiBinaryLabel.get()) || dynamic_cast(multiBinaryLabel.get())) { errorMat->classificationErrorMulti( @@ -140,8 +149,14 @@ class ClassificationErrorEvaluator : public Evaluator { } void printStats(std::ostream& os) const { - os << "top_1_error=" << (numSamples_ ? totalScore_ / numSamples_ : 0) - << " top_5_error=" << (numSamples_ ? totalScore2_ / numSamples_ : 0); + if (config_.top_k() == 1) { + os << config_.name() << "=" + << (numSamples_ ? totalScore_ / numSamples_ : 0); + } else { + os << "top_1_error=" << (numSamples_ ? totalScore_ / numSamples_ : 0) + << " top_" << config_.top_k() + << "_error=" << (numSamples_ ? totalScore2_ / numSamples_ : 0); + } } virtual real evalImp(std::vector& arguments) { @@ -150,7 +165,11 @@ class ClassificationErrorEvaluator : public Evaluator { } virtual void distributeEval(ParameterClient2* client) { - mergeResultsOfAllClients(client); + double data[3] = {totalScore_, totalScore2_, numSamples_}; + client->reduce(data, data, 3, FLAGS_trainer_id, 0); + totalScore_ = data[0]; + totalScore2_ = data[1]; + numSamples_ = data[2]; } private: diff --git a/paddle/gserver/tests/test_Evaluator.cpp b/paddle/gserver/tests/test_Evaluator.cpp index 8165eb82693361..d39c0422715675 100644 --- a/paddle/gserver/tests/test_Evaluator.cpp +++ b/paddle/gserver/tests/test_Evaluator.cpp @@ -129,6 +129,7 @@ void testEvaluatorAll(TestConfig testConf, TEST(Evaluator, classification_error) { TestConfig config; config.evaluatorConfig.set_type("classification_error"); + config.evaluatorConfig.set_top_k(5); config.inputDefs.push_back({INPUT_DATA, "output", 50}); config.inputDefs.push_back({INPUT_LABEL, "label", 50}); diff --git a/proto/ModelConfig.proto b/proto/ModelConfig.proto index be4634d5103c0f..65d5d50277b665 100644 --- a/proto/ModelConfig.proto +++ b/proto/ModelConfig.proto @@ -475,6 +475,10 @@ message EvaluatorConfig { // Used by ChunkEvaluator // chunk of these types are not counted repeated int32 excluded_chunk_types = 12; + + // Used by ClassificationErrorEvaluator + // top # classification error + optional int32 top_k = 13 [default = 1]; } message LinkConfig { diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index d403a6029a3e9d..da937152ee0ce7 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -1253,6 +1253,7 @@ def Evaluator( dict_file=None, result_file=None, num_results=None, + top_k=None, delimited=None, excluded_chunk_types=None, ): evaluator = g_config.model_config.evaluators.add() @@ -1280,6 +1281,8 @@ def Evaluator( evaluator.result_file = result_file if num_results is not None: evaluator.num_results = num_results + if top_k is not None: + evaluator.top_k = top_k if delimited is not None: evaluator.delimited = delimited diff --git a/python/paddle/trainer_config_helpers/evaluators.py b/python/paddle/trainer_config_helpers/evaluators.py index bd247ea9af9d8d..567521ee9dbadb 100644 --- a/python/paddle/trainer_config_helpers/evaluators.py +++ b/python/paddle/trainer_config_helpers/evaluators.py @@ -71,6 +71,7 @@ def evaluator_base( result_file=None, num_results=None, delimited=None, + top_k=None, excluded_chunk_types=None, ): """ Evaluator will evaluate the network status while training/testing. @@ -104,12 +105,15 @@ def evaluator_base( :param weight: An input layer which is a weight for each sample. Each evaluator may calculate differently to use this weight. :type weight: LayerOutput. + :param top_k: number k in top-k error rate + :type top_k: int """ # inputs type assertions. assert classification_threshold is None or isinstance( classification_threshold, float) assert positive_label is None or isinstance(positive_label, int) assert num_results is None or isinstance(num_results, int) + assert top_k is None or isinstance(top_k, int) if not isinstance(input, list): input = [input] @@ -130,6 +134,8 @@ def evaluator_base( dict_file=dict_file, result_file=result_file, delimited=delimited, + num_results=num_results, + top_k=top_k, excluded_chunk_types=excluded_chunk_types, ) @@ -139,6 +145,7 @@ def classification_error_evaluator(input, label, name=None, weight=None, + top_k=None, threshold=None): """ Classification Error Evaluator. It will print error rate for classification. @@ -167,6 +174,8 @@ def classification_error_evaluator(input, then means not set weight. The larger weight it is, the more important this sample is. :type weight: LayerOutput + :param top_k: number k in top-k error rate + :type top_k: int :param threshold: The classification threshold. :type threshold: float :return: None. @@ -178,6 +187,7 @@ def classification_error_evaluator(input, input=input, label=label, weight=weight, + top_k=top_k, classification_threshold=threshold, ) diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 0d3a31b9d39a28..00aef80691fba0 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -2870,8 +2870,8 @@ def gru_step_layer(input, :param name: :param gate_act: :param bias_attr: - :param param_attr: the parameter_attribute for transforming the output_mem - from previous step. + :param param_attr: the parameter_attribute for transforming the output_mem + from previous step. :param layer_attr: :return: LayerOutput object. :rtype: LayerOutput @@ -2882,10 +2882,10 @@ def gru_step_layer(input, Layer( name=name, type=LayerType.GRU_STEP_LAYER, - # The parameter here is for transforming the output_mem. The input has - # already been transformed outside this module so it does not need - # parameter associated with it. - # The parameter here is instead grouped with input is due to + # The parameter here is for transforming the output_mem. The input has + # already been transformed outside this module so it does not need + # parameter associated with it. + # The parameter here is instead grouped with input is due to # backward model compatibility. inputs=[Input(input.name, **param_attr.attr), output_mem.name], bias=ParamAttr.to_bias(bias_attr), @@ -3536,6 +3536,7 @@ def classification_cost(input, label, weight=None, name=None, + top_k=None, evaluator=classification_error_evaluator, layer_attr=None): """ @@ -3550,6 +3551,8 @@ def classification_cost(input, :param weight: The weight affects the cost, namely the scale of cost. It is an optional argument. :type weight: LayerOutput + :param top_k: number k in top-k error rate + :type top_k: int :param evaluator: Evaluator method. :param layer_attr: layer's extra attribute. :type layer_attr: ExtraLayerAttribute @@ -3577,7 +3580,7 @@ def __add_evaluator__(e): assert isinstance(e.for_classification, bool) assert e.for_classification - e(name=e.__name__, input=input, label=label, weight=weight) + e(name=e.__name__, input=input, label=label, weight=weight, top_k=top_k) if not isinstance(evaluator, collections.Sequence): evaluator = [evaluator] From d256512832d734134204ff483504551b3c184a57 Mon Sep 17 00:00:00 2001 From: Liang Zhao Date: Mon, 20 Feb 2017 11:18:22 -0800 Subject: [PATCH 258/370] Rewrite code according to reviewer comments --- paddle/gserver/evaluators/Evaluator.cpp | 34 ++++++++----------------- paddle/parameter/Parameter.cpp | 4 --- 2 files changed, 10 insertions(+), 28 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index 30e91fa222fca5..f2dd5cf8073f6d 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -102,36 +102,22 @@ class ClassificationErrorEvaluator : public Evaluator { maxValues_, height, width, false, useGpu(arguments[0].deviceId)); output->rowMax(*maxIds_, *maxValues_); // top-k values - int* ids = nullptr; - int* lbl = nullptr; IVectorPtr dest = IVector::create(maxIds_->getSize(), false); IVectorPtr dest2 = IVector::create(label->getSize(), false); - if (useGpu(arguments[0].deviceId)) { - hl_memcpy_device2host((void*)dest->getData(), - (void*)maxIds_->getData(), - sizeof(int) * maxIds_->getSize()); - ids = dest->getData(); - - hl_memcpy_device2host((void*)dest2->getData(), - (void*)label->getData(), - sizeof(int) * label->getSize()); - lbl = dest2->getData(); - } else { - ids = maxIds_->getData(); - lbl = label->getData(); - } + dest->copyFrom(*maxIds_); + dest2->copyFrom(*label); + int* ids = dest->getData(); + int* lbl = dest2->getData(); - real* result2 = errorMat2->getData(); for (size_t i = 0; i < height; ++i) { - result2[i] = (ids[i * width] != lbl[i]); // initialize top-k error - for (size_t j = 1; j < width; ++j) { - if (result2[i] == 0.0) { - break; - } - result2[i] = (ids[i * width + j] != lbl[i]); // top-k error + bool contain = false; + for (size_t j = 0; j < width && !contain; ++j) { + contain = (ids[i * width + j] == lbl[i]); + } + if (!contain) { + totalScore2_ += 1.0; // update top-k error } } - totalScore2_ += errorMat2->getSum(); } } else if (dynamic_cast(multiBinaryLabel.get()) || dynamic_cast(multiBinaryLabel.get())) { diff --git a/paddle/parameter/Parameter.cpp b/paddle/parameter/Parameter.cpp index 9e7b4ea39d4ea6..1ccded81879679 100644 --- a/paddle/parameter/Parameter.cpp +++ b/paddle/parameter/Parameter.cpp @@ -375,10 +375,6 @@ bool Parameter::load(const std::string& filename) { std::ifstream fs(filename, std::ios_base::binary); if (!fs) { LOG(INFO) << "missing parameters [" << filename << "] while loading model."; - /*if (isStatic()) { - LOG(FATAL) << getName() << " is static but missing, not allowed."; - return false; - }*/ if (kMissParameterFail == FLAGS_load_missing_parameter_strategy) { LOG(FATAL) << getName() << " missing, not allowed."; return false; From 8fded24c75265a27498eda2f7fdbeb17b969c33a Mon Sep 17 00:00:00 2001 From: Liang Zhao Date: Tue, 21 Feb 2017 15:27:56 -0800 Subject: [PATCH 259/370] implement top k classification error in class matrix --- paddle/cuda/include/hl_matrix.h | 13 ---- paddle/cuda/include/hl_top_k.h | 28 ++++++++- paddle/cuda/src/hl_cuda_matrix.cu | 53 ---------------- paddle/cuda/src/hl_top_k.cu | 78 ++++++++++++++++++++++++ paddle/gserver/evaluators/Evaluator.cpp | 52 ++-------------- paddle/gserver/layers/Layer.h | 1 + paddle/math/Matrix.cpp | 80 +++++++++++++++---------- paddle/math/Matrix.h | 9 ++- 8 files changed, 168 insertions(+), 146 deletions(-) diff --git a/paddle/cuda/include/hl_matrix.h b/paddle/cuda/include/hl_matrix.h index 6f21b82afdc6cd..eb454c59c1e58c 100644 --- a/paddle/cuda/include/hl_matrix.h +++ b/paddle/cuda/include/hl_matrix.h @@ -69,19 +69,6 @@ extern void hl_sequence_softmax_forward(real* A_d, const int* index, int numSequence); -/** - * @brief Matrix classification error. - * - * @param[in] A_d input matrix (M x N). - * @param[in] B_d input vector (M x 1). - * @param[out] C_d output vector (M x 1). - * @param[in] dimM matrix height. - * @param[in] dimN matrix width. - * - */ -extern void hl_matrix_classification_error( - real* A_d, int* B_d, real* C_d, int dimM, int dimN); - /** * @brief Matrix cross entropy. * diff --git a/paddle/cuda/include/hl_top_k.h b/paddle/cuda/include/hl_top_k.h index 77949ed295a6ea..79ae0d0e741de0 100644 --- a/paddle/cuda/include/hl_top_k.h +++ b/paddle/cuda/include/hl_top_k.h @@ -58,4 +58,30 @@ extern void hl_sparse_matrix_top_k(real* topVal, int beamSize, int numSamples); -#endif /* HL_TOP_K_H_ */ +/** + * @brief Matrix classification error. + * + * @param[out] topVal top k element. + * @param[in] ldv leading dimension of topVal. + * @param[out] topIds top k index. + * @param[in] src input value. + * @param[in] lds leading dimension of src. + * @param[in] dim width of input value. + * @param[in] topkSize size of top k element. + * @param[in] numSamples height of input value. + * @param[in] label ground truth label. + * @param[out] recResult top-k classification error. + * + */ +extern void hl_matrix_classification_error(real* topVal, + int ldv, + int* topIds, + real* src, + int lds, + int dim, + int topkSize, + int numSamples, + int* label, + real* recResult); + +#endif // HL_TOP_K_H_ diff --git a/paddle/cuda/src/hl_cuda_matrix.cu b/paddle/cuda/src/hl_cuda_matrix.cu index 96c07d9c3b7a37..9bcc7fb7de44b2 100644 --- a/paddle/cuda/src/hl_cuda_matrix.cu +++ b/paddle/cuda/src/hl_cuda_matrix.cu @@ -265,59 +265,6 @@ void hl_matrix_softmax_derivative(real *grad_d, CHECK_SYNC("hl_matrix_softmax_derivative failed"); } -template -__global__ void KeMatrixClassificationError(real* in_A, - int* in_B, - real* out_C, - int dimN) { - __shared__ real max_s[blockSize]; - __shared__ int max_l[blockSize]; - const int tid = threadIdx.x; - const int rowId = blockIdx.x; - - max_s[tid] = -1e30f; - in_A += rowId * dimN; - real tmp; - for (int colId = tid; colId < dimN; colId += blockSize) { - tmp = in_A[colId]; - if (max_s[tid] < tmp) { - max_s[tid] = tmp; - max_l[tid] = colId; - } - } - __syncthreads(); - - for (int stride = blockSize/2; stride > 0; stride = stride/2) { - if (tid < stride) { - if (max_s[tid] < max_s[tid + stride]) { - max_s[tid] = max_s[tid + stride]; - max_l[tid] = max_l[tid + stride]; - } - } - __syncthreads(); - } - __syncthreads(); - - if (tid == 0) { - out_C[rowId] = (max_l[0] == in_B[rowId] ? 0 : 1.0f); - } -} - -void hl_matrix_classification_error(real* A_d, - int* B_d, - real* C_d, - int dimM, - int dimN) { - CHECK_NOTNULL(A_d); - CHECK_NOTNULL(B_d); - CHECK_NOTNULL(C_d); - - // each sample is calculated by one block - KeMatrixClassificationError<1024><<< dimM, 1024, 0, STREAM_DEFAULT >>> - (A_d, B_d, C_d, dimN); - CHECK_SYNC("hl_matrix_classification_error"); -} - __global__ void KeMatrixMultiBinaryCrossEntropy(real* output, real* entropy, int* row, diff --git a/paddle/cuda/src/hl_top_k.cu b/paddle/cuda/src/hl_top_k.cu index f0ef0cc3c51f9e..4f0bbfcf4e3aa5 100644 --- a/paddle/cuda/src/hl_top_k.cu +++ b/paddle/cuda/src/hl_top_k.cu @@ -384,3 +384,81 @@ void hl_sparse_matrix_top_k(real* topVal, int ldv, CHECK_SYNC("hl_sparse_matrix_top_k failed"); } +/** + * Each block compute one sample. + * In a block: + * 1. every thread get top maxLength value; + * 2. merge to shTopK, block reduce and get max value; + * 3. go to the second setp, until one thread's topK value is null; + * 4. go to the first setp, until get the topK value. + */ +template +__global__ void KeMatrixTopKClassificationError(real* topVal, int ldv, + int * topIds, + real* src, int lds, + int dim, + int beamSize, + int* label, + real* recResult) { + __shared__ Pair shTopK[blockSize]; + __shared__ int maxId[blockSize / 2]; + const int tid = threadIdx.x; + const int warp = threadIdx.x / 32; + src += blockIdx.x * lds; + topVal += blockIdx.x * ldv; + topIds += blockIdx.x * beamSize; + + Pair topK[maxLength]; // NOLINT + int beam = maxLength; + Pair max; + bool isEmpty = false; + bool firstStep = true; + int topkSize = beamSize; + + for (int k = 0; k < maxLength; k++) { + topK[k].set(-HL_FLOAT_MAX, -1); + } + + while (beamSize) { + threadGetTopK + (topK, beam, beamSize, src, firstStep, isEmpty, max, dim, tid); + + shTopK[tid] = topK[0]; + blockReduce + (shTopK, maxId, topK, &topVal, &topIds, beam, beamSize, tid, warp); + } + + __syncthreads(); + if (tid == 0) { + for (int i = 0; i < topkSize; i++) { + if (*--topIds == label[blockIdx.x]) { + recResult[blockIdx.x] = 0; + break; + } + recResult[blockIdx.x] = 1.0f; + } + } +} + +void hl_matrix_classification_error(real* topVal, int ldv, + int* topIds, + real* src, int lds, + int dim, + int topkSize, + int numSamples, + int* label, + real* recResult) { + CHECK_NOTNULL(topVal); + CHECK_NOTNULL(topIds); + CHECK_NOTNULL(src); + + if (topkSize > dim) topkSize = dim; + + dim3 threads(256, 1); + dim3 grid(numSamples, 1); + KeMatrixTopKClassificationError<5, 256> + <<< grid, threads, 0, STREAM_DEFAULT >>> + (topVal, ldv, topIds, src, lds, dim, topkSize, label, recResult); + + CHECK_SYNC("hl_matrix_top_k classification error failed"); +} diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index f2dd5cf8073f6d..cd8d1e9ecbfd83 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -39,12 +39,13 @@ void Evaluator::eval(const NeuralNetwork& nn) { */ class ClassificationErrorEvaluator : public Evaluator { public: + /* ClassificationErrorEvaluator() : totalScore2_(0) {} virtual void start() { Evaluator::start(); totalScore2_ = 0; - } + } */ virtual void updateSamplesNum(const std::vector& arguments) { if (3 == arguments.size()) { @@ -83,42 +84,11 @@ class ClassificationErrorEvaluator : public Evaluator { 1, /* trans= */ false, useGpu(arguments[0].deviceId)); - const MatrixPtr errorMat2 = Matrix::create(output->getHeight(), - 1, - /* trans= */ false, - false); errorMat->zeroMem(); if (label != nullptr) { - errorMat->classificationError(*output, *label); // top-1 error - if (config_.top_k() > 1) { - size_t height = output->getHeight(); - size_t width = config_.top_k(); - - IVector::resizeOrCreate( - maxIds_, height * width, useGpu(arguments[0].deviceId)); - Matrix::resizeOrCreate( - maxValues_, height, width, false, useGpu(arguments[0].deviceId)); - output->rowMax(*maxIds_, *maxValues_); // top-k values - - IVectorPtr dest = IVector::create(maxIds_->getSize(), false); - IVectorPtr dest2 = IVector::create(label->getSize(), false); - dest->copyFrom(*maxIds_); - dest2->copyFrom(*label); - int* ids = dest->getData(); - int* lbl = dest2->getData(); - - for (size_t i = 0; i < height; ++i) { - bool contain = false; - for (size_t j = 0; j < width && !contain; ++j) { - contain = (ids[i * width + j] == lbl[i]); - } - if (!contain) { - totalScore2_ += 1.0; // update top-k error - } - } - } + errorMat->classificationError(*output, *label, config_.top_k()); } else if (dynamic_cast(multiBinaryLabel.get()) || dynamic_cast(multiBinaryLabel.get())) { errorMat->classificationErrorMulti( @@ -139,9 +109,8 @@ class ClassificationErrorEvaluator : public Evaluator { os << config_.name() << "=" << (numSamples_ ? totalScore_ / numSamples_ : 0); } else { - os << "top_1_error=" << (numSamples_ ? totalScore_ / numSamples_ : 0) - << " top_" << config_.top_k() - << "_error=" << (numSamples_ ? totalScore2_ / numSamples_ : 0); + os << " top_" << config_.top_k() + << "_error=" << (numSamples_ ? totalScore_ / numSamples_ : 0); } } @@ -151,17 +120,8 @@ class ClassificationErrorEvaluator : public Evaluator { } virtual void distributeEval(ParameterClient2* client) { - double data[3] = {totalScore_, totalScore2_, numSamples_}; - client->reduce(data, data, 3, FLAGS_trainer_id, 0); - totalScore_ = data[0]; - totalScore2_ = data[1]; - numSamples_ = data[2]; + mergeResultsOfAllClients(client); } - -private: - IVectorPtr maxIds_; - MatrixPtr maxValues_; - double totalScore2_; }; /** diff --git a/paddle/gserver/layers/Layer.h b/paddle/gserver/layers/Layer.h index 6dfd48fb966181..7c4bea072157aa 100644 --- a/paddle/gserver/layers/Layer.h +++ b/paddle/gserver/layers/Layer.h @@ -311,6 +311,7 @@ class Layer { return *output->second; } else { LOG(FATAL) << "No specific output " << str; + return *((Argument*)nullptr); } } } diff --git a/paddle/math/Matrix.cpp b/paddle/math/Matrix.cpp index 446dd30567856f..07450bfb0ef709 100644 --- a/paddle/math/Matrix.cpp +++ b/paddle/math/Matrix.cpp @@ -793,19 +793,32 @@ void GpuMatrix::maxoutBackward(Matrix& a, } /*calulate the error of classification */ -void GpuMatrix::classificationError(Matrix& output, IVector& label) { - auto output_ptr = dynamic_cast(&output); - auto label_ptr = dynamic_cast(&label); - CHECK(output_ptr && label_ptr) << "Invalid argument pointer"; - - CHECK(height_ == output_ptr->height_ && width_ == 1) +void GpuMatrix::classificationError(Matrix& output, + IVector& label, + size_t topkSize) { + auto gpuOutput = dynamic_cast(&output); + auto gpuLabel = dynamic_cast(&label); + size_t numSamples = this->getHeight(); + GpuMatrixPtr gpuTopVal = std::make_shared(numSamples, topkSize); + GpuIVectorPtr gpuTopIds = std::make_shared(numSamples * topkSize); + + CHECK(gpuOutput && gpuLabel) << "Invalid argument pointer"; + CHECK(gpuTopVal && gpuTopIds) << "Allocate GPU memory failed"; + CHECK(gpuLabel->getSize() == numSamples) << "Vector size is not equal"; + CHECK(numSamples == gpuOutput->getHeight() && this->getWidth() == 1) << "Matrix dimensions are not equal"; - hl_matrix_classification_error((real*)output_ptr->data_, - (int*)label_ptr->getData(), - data_, - height_, - output_ptr->width_); + size_t dim = gpuOutput->getWidth(); + hl_matrix_classification_error(gpuTopVal->getData(), + gpuTopVal->getStride(), + gpuTopIds->getData(), + gpuOutput->getData(), + gpuOutput->getStride(), + dim, + topkSize, + numSamples, + gpuLabel->getData(), + this->getData()); } /* copy -log(output[i * width + label]) to this->data[i] */ @@ -3200,32 +3213,39 @@ void CpuMatrix::rowNormalizeL1(Matrix& out) { } /* calulate classification error */ -void CpuMatrix::classificationError(Matrix& output, IVector& label) { - CHECK(dynamic_cast(&output)); - CHECK(dynamic_cast(&label)); +void CpuMatrix::classificationError(Matrix& output, + IVector& label, + size_t topkSize) { + size_t numSamples = this->getHeight(); + auto cpuOutput = dynamic_cast(&output); + auto cpuLabel = dynamic_cast(&label); + IVectorPtr cpuTopIds = std::make_shared(numSamples * topkSize); + MatrixPtr cpuTopVal = std::make_shared(numSamples, topkSize); + + CHECK(cpuOutput && cpuLabel) << "Invalid argument pointer"; + CHECK(cpuTopIds && cpuTopVal) << "Allocate cpu memory failed"; + CHECK(cpuLabel->getSize() == numSamples) << "Vector size is not equal"; + CHECK(cpuOutput->getHeight() == numSamples && this->getWidth() == 1) + << "Matrix dimensions are not equal"; - CHECK_EQ(getWidth(), (size_t)1); - size_t numSamples = getHeight(); - CHECK_EQ(label.getSize(), numSamples); - CHECK_EQ(output.getHeight(), numSamples); + // top k matrix classification + cpuOutput->rowMax(*cpuTopIds, *cpuTopVal); - size_t dim = output.getWidth(); - real* out = output.getData(); - int* lbl = label.getData(); - real maxData = 0.0; - int maxIndex = -1; + size_t dim = cpuOutput->getWidth(); + real* result = this->getData(); + int* ids = cpuTopIds->getData(); + int* lbl = cpuLabel->getData(); for (size_t i = 0; i < numSamples; ++i) { CHECK_GE(lbl[i], 0); CHECK_LT((size_t)lbl[i], dim); - maxData = out[i * dim]; - maxIndex = 0; - for (size_t j = 0; j < dim; ++j) { - if (maxData < out[i * dim + j]) { - maxIndex = j; - maxData = out[i * dim + j]; + + for (size_t j = 0; j < topkSize; ++j) { + if (ids[j + i * topkSize] == lbl[i]) { + result[i] = 0; + break; } + result[i] = 1.0f; } - getData()[i] = (maxIndex != lbl[i]); } } diff --git a/paddle/math/Matrix.h b/paddle/math/Matrix.h index ea4bbb86b057b5..d0ba2e93feabfc 100644 --- a/paddle/math/Matrix.h +++ b/paddle/math/Matrix.h @@ -836,8 +836,11 @@ class Matrix : public BaseMatrix { * output[i] = 1 if row i is an error. * * output[i] = 0 if row i is correct. + * */ - virtual void classificationError(Matrix& output, IVector& label) { + virtual void classificationError(Matrix& output, + IVector& label, + size_t topkSize = 1) { LOG(FATAL) << "Not implemented"; } @@ -1314,7 +1317,7 @@ class GpuMatrix : public Matrix { void check(std::ostream& os, Matrix& refMat, bool printDiff = true); void randomizeUniform(); - void classificationError(Matrix& output, IVector& label); + void classificationError(Matrix& output, IVector& label, size_t topkSize = 1); void convExpand(Matrix& feature, int feaImgHeight, @@ -1739,7 +1742,7 @@ class CpuMatrix : public Matrix { void randomizeUniform(); - void classificationError(Matrix& output, IVector& label); + void classificationError(Matrix& output, IVector& label, size_t topkSize = 1); void addByBitCode(size_t numClasses, const IVector& codes, const Matrix& vec); From 046349dd409c2745f20cecf181d5a58a5b37511f Mon Sep 17 00:00:00 2001 From: Liang Zhao Date: Tue, 21 Feb 2017 22:01:19 -0800 Subject: [PATCH 260/370] Fix definition of hl_matrix_classification_error in hl_matrix_stub.h --- paddle/cuda/include/stub/hl_matrix_stub.h | 12 ++++++++++-- paddle/math/tests/test_matrixCompare.cpp | 19 ++++++++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/paddle/cuda/include/stub/hl_matrix_stub.h b/paddle/cuda/include/stub/hl_matrix_stub.h index f4e6461cdcf198..127cb7e27983e8 100644 --- a/paddle/cuda/include/stub/hl_matrix_stub.h +++ b/paddle/cuda/include/stub/hl_matrix_stub.h @@ -35,8 +35,16 @@ inline void hl_sequence_softmax_forward(real* A_d, inline void hl_matrix_softmax_derivative( real* grad_d, real* output_d, real* sftmaxSum_d, int dimM, int dimN) {} -inline void hl_matrix_classification_error( - real* A_d, int* B_d, real* C_d, int dimM, int dimN) {} +inline void hl_matrix_classification_error(real* topVal, + int ldv, + int* topIds, + real* src, + int lds, + int dim, + int topkSize, + int numSamples, + int* label, + real* recResult) {} inline void hl_matrix_cross_entropy( real* A_d, real* C_d, int* label_d, int dimM, int dimN) {} diff --git a/paddle/math/tests/test_matrixCompare.cpp b/paddle/math/tests/test_matrixCompare.cpp index 6caaea443c1df7..08b64c1bb6f5d3 100644 --- a/paddle/math/tests/test_matrixCompare.cpp +++ b/paddle/math/tests/test_matrixCompare.cpp @@ -764,7 +764,7 @@ TEST(Matrix, paramReluBackwardDiff) { } } -void testClassificationError(int numSamples, int dim) { +void testClassificationError(int numSamples, int dim, int topkSize) { MatrixPtr cpuError = std::make_shared(numSamples, 1); MatrixPtr gpuError = std::make_shared(numSamples, 1); MatrixPtr cpuOutput = std::make_shared(numSamples, dim); @@ -777,17 +777,22 @@ void testClassificationError(int numSamples, int dim) { gpuOutput->copyFrom(*cpuOutput); gpuLabel->copyFrom(*cpuLabel); - cpuError->classificationError(*cpuOutput, *cpuLabel); - gpuError->classificationError(*gpuOutput, *gpuLabel); + cpuError->classificationError(*cpuOutput, *cpuLabel, topkSize); + gpuError->classificationError(*gpuOutput, *gpuLabel, topkSize); TensorCheckEqual(*cpuError, *gpuError); } TEST(Matrix, classificationError) { - for (auto numSamples : {1, 10, 100, 1000, 70000}) { - for (auto dim : {1, 10, 100, 1000}) { - VLOG(3) << " numSamples=" << numSamples << " dim=" << dim; - testClassificationError(numSamples, dim); + for (auto numSamples : {1, 5, 31, 90, 150, 300}) { + for (auto dim : + {1, 5, 8, 10, 15, 64, 80, 120, 256, 300, 1280, 5120, 50000}) { + for (auto topkSize : {1, 5, 10, 20, 40, (int)rand() % dim + 1}) { + if (topkSize > dim) continue; + VLOG(3) << " sample= " << numSamples << " topkSize= " << topkSize + << " dim= " << dim; + testClassificationError(numSamples, dim, topkSize); + } } } } From bb625337e37c06cec40954abb83fde8b2716d44a Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Wed, 22 Feb 2017 15:28:02 +0800 Subject: [PATCH 261/370] add some comments --- python/paddle/v2/data_feeder.py | 41 +++++++++++++++++++++++++++++++++ python/paddle/v2/trainer.py | 1 - 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/python/paddle/v2/data_feeder.py b/python/paddle/v2/data_feeder.py index 2a0b6bbeb563f7..83a4efef9e7a7b 100644 --- a/python/paddle/v2/data_feeder.py +++ b/python/paddle/v2/data_feeder.py @@ -15,5 +15,46 @@ from py_paddle import DataProviderConverter __all__ = ['DataFeeder'] +""" +DataFeeder converts the data returned by paddle.reader into a data structure +of Arguments which is defined in the API. The paddle.reader usually returns +a list of mini-batch data. Each item in the list is a tuple or list, which is +one sample with multiple features. DataFeeder converts this mini-batch data +into Arguments in order to feed it to C++ interface. + +The example usage: + + data_types = [paddle.data_type.dense_vector(784), + paddle.data_type.integer_value(10)] + feeder = DataFeeder(input_types=data_types) + minibatch_data = [ + ( [1.0,2.0,3.0,4.0], 5, [6,7,8] ), # first sample + ( [1.0,2.0,3.0,4.0], 5, [6,7,8] ) # second sample + ] + + # or + # minibatch_data = [ + # [ [1.0,2.0,3.0,4.0], 5, [6,7,8] ], # first sample + # [ [1.0,2.0,3.0,4.0], 5, [6,7,8] ] # second sample + # ] + arg = feeder(minibatch_data) + + +Args: + input_types: A list of input data types. It's length is equal to the length + of data returned by paddle.reader. Each item specifies the type + of each feature. + mintbatch_data: A list of mini-batch data. Each item is a list or tuple, + for example: + [ + (feature_0, feature_1, feature_2, ...), # first sample + (feature_0, feature_1, feature_2, ...), # second sample + ... + ] + +Returns: + An Arguments object contains this mini-batch data with multiple features. + The Arguments definition is in the API. +""" DataFeeder = DataProviderConverter diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 7480a3fb84bbd2..5709c7e886c323 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -89,7 +89,6 @@ def train(self, event_handler = default_event_handler topology = v2_layer.parse_network(topology) - print topology __check_train_args__(**locals()) From fbf864362dc1bd716a8db1f4441afe488fe3d74b Mon Sep 17 00:00:00 2001 From: liaogang Date: Wed, 22 Feb 2017 16:02:58 +0800 Subject: [PATCH 262/370] Update python getLayerOutputs --- demo/image_classification/prediction.py | 2 +- demo/model_zoo/resnet/classify.py | 2 +- paddle/api/Arguments.cpp | 7 ++++ paddle/api/GradientMachine.cpp | 5 ++- paddle/api/PaddleAPI.h | 5 +-- paddle/api/Trainer.cpp | 8 ++--- .../gradientmachines/GradientMachine.h | 4 +-- .../gradientmachines/MultiGradientMachine.cpp | 32 +++++-------------- .../gradientmachines/MultiGradientMachine.h | 4 ++- .../gradientmachines/NeuralNetwork.cpp | 6 ++-- .../gserver/gradientmachines/NeuralNetwork.h | 2 +- paddle/gserver/layers/CosSimLayer.cpp | 2 +- paddle/py_paddle/util.py | 2 +- 13 files changed, 35 insertions(+), 46 deletions(-) diff --git a/demo/image_classification/prediction.py b/demo/image_classification/prediction.py index 9a86aafcb2fa4d..49c0ff600c40e0 100755 --- a/demo/image_classification/prediction.py +++ b/demo/image_classification/prediction.py @@ -126,7 +126,7 @@ def forward(self, data, output_layer): # For oversampling, average predictions across crops. # If not, the shape of output[name]: (1, class_number), # the mean is also applicable. - return output[output_layer].mean(0) + return output[output_layer]['value'].mean(0) def predict(self, image=None, output_layer=None): assert isinstance(image, basestring) diff --git a/demo/model_zoo/resnet/classify.py b/demo/model_zoo/resnet/classify.py index 4631816c43ef48..6074cc1d3a85e1 100755 --- a/demo/model_zoo/resnet/classify.py +++ b/demo/model_zoo/resnet/classify.py @@ -156,7 +156,7 @@ def forward(self, data, output_layer): # For oversampling, average predictions across crops. # If not, the shape of output[name]: (1, class_number), # the mean is also applicable. - res[name] = output[name].mean(0) + res[name] = output[name]['value'].mean(0) return res diff --git a/paddle/api/Arguments.cpp b/paddle/api/Arguments.cpp index 41beed38a87601..a3f4bfffc9f074 100644 --- a/paddle/api/Arguments.cpp +++ b/paddle/api/Arguments.cpp @@ -38,6 +38,13 @@ Arguments* Arguments::createByPaddleArgumentVector(void* ptr) { return args; } +Arguments* Arguments::createByPaddleArgument(const void* ptr) { + auto p = (paddle::Argument*)(ptr); + auto args = new Arguments(); + args->m->outputs.push_back(*p); + return args; +} + Matrix* Arguments::getSlotValue(size_t idx) const throw(RangeError) { auto& a = m->getArg(idx); return Matrix::createByPaddleMatrixPtr(&a.value); diff --git a/paddle/api/GradientMachine.cpp b/paddle/api/GradientMachine.cpp index a44763bfa53ed5..a64e70a6bd563a 100644 --- a/paddle/api/GradientMachine.cpp +++ b/paddle/api/GradientMachine.cpp @@ -144,12 +144,11 @@ Parameter* GradientMachine::getParameter(size_t i) throw(RangeError) { void GradientMachine::randParameters() { m->machine->randParameters(); } -Matrix* GradientMachine::getLayerOutput(const std::string& layerName) const +Arguments* GradientMachine::getLayerOutput(const std::string& layerName) const throw(UnsupportError) { auto nn = m->machine; if (nn) { - auto mat = nn->getLayerOutput(layerName); - return Matrix::createByPaddleMatrixPtr(&mat); + return Arguments::createByPaddleArgument(&nn->getLayerOutput(layerName)); } else { throw UnsupportError(); } diff --git a/paddle/api/PaddleAPI.h b/paddle/api/PaddleAPI.h index f5af8b0035b44d..10569a71708463 100644 --- a/paddle/api/PaddleAPI.h +++ b/paddle/api/PaddleAPI.h @@ -454,6 +454,7 @@ class Arguments { private: static Arguments* createByPaddleArgumentVector(void* ptr); + static Arguments* createByPaddleArgument(const void* ptr); void* getInternalArgumentsPtr() const; private: @@ -769,7 +770,7 @@ class GradientMachine { void randParameters(); - Matrix* getLayerOutput(const std::string& layerName) const + Arguments* getLayerOutput(const std::string& layerName) const throw(UnsupportError); /** @@ -952,7 +953,7 @@ class Trainer { Arguments* getForwardOutput(); - Matrix* getLayerOutput(const std::string& layerName); + Arguments* getLayerOutput(const std::string& layerName); }; /// the N-Best results generated from one input sequence. diff --git a/paddle/api/Trainer.cpp b/paddle/api/Trainer.cpp index d83dc380beeec3..c742614aff97f2 100644 --- a/paddle/api/Trainer.cpp +++ b/paddle/api/Trainer.cpp @@ -131,12 +131,10 @@ void Trainer::testOneDataBatch(size_t batchSize, const Arguments& args) { void TrainerPrivate::finishTestPeriod() { tester_->finishTestPeriod(); } void Trainer::finishTestPeriod() { m->finishTestPeriod(); } -Matrix* Trainer::getLayerOutput(const std::string& layerName) { - auto nn = std::dynamic_pointer_cast( - this->m->getGradientMachine()); +Arguments* Trainer::getLayerOutput(const std::string& layerName) { + auto nn = this->m->getGradientMachine(); CHECK(nn) << "trainerInternal_.getGradientMachine() is not NeuralNetwork"; - auto m = nn->getLayerOutput(layerName); - return Matrix::createByPaddleMatrixPtr(&m); + return Arguments::createByPaddleArgument(&nn->getLayerOutput(layerName)); } void Trainer::forwardOneBatch(size_t batchSize) { diff --git a/paddle/gserver/gradientmachines/GradientMachine.h b/paddle/gserver/gradientmachines/GradientMachine.h index 5469c0d89f4964..ae39783c6b7ea6 100644 --- a/paddle/gserver/gradientmachines/GradientMachine.h +++ b/paddle/gserver/gradientmachines/GradientMachine.h @@ -134,8 +134,8 @@ class GradientMachine { backward(callback); } - virtual MatrixPtr getLayerOutput(const std::string& layerName) const { - return nullptr; + virtual const Argument& getLayerOutput(const std::string& layerName) { + return *((Argument*)nullptr); } // see comment in Layer.h for the function with the same name diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp index 2d42e648302f16..6b11b0155e990d 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp @@ -282,33 +282,17 @@ void MultiGradientMachine::forwardBackward(const std::vector& inArgs, backwardImp(callback); } -MatrixPtr MultiGradientMachine::getLayerOutput( - const std::string& layerName) const { - // each thread has the same neural network - auto nn = threads_[0]->getGradientMachine(); - size_t height = 0; - size_t width = nn->getLayerOutput(layerName)->getWidth(); - std::vector mats; - mats.reserve(threads_.size()); - for (auto& thread : threads_) { - MatrixPtr out = thread->getGradientMachine()->getLayerOutput(layerName); - mats.push_back(out); - height += out->getHeight(); - CHECK_EQ(width, out->getWidth()); - } +const Argument& MultiGradientMachine::getLayerOutput( + const std::string& layerName) { + std::vector args; + args.reserve(threads_.size()); - MatrixPtr layerOutput; - Matrix::resizeOrCreate(layerOutput, height, width, false, false); - - // copy one layer output from one trainer thread at each time - size_t startRow = 0; - for (auto& mat : mats) { - auto tmpMatrix = layerOutput->subMatrix(startRow, mat->getHeight()); - tmpMatrix->copyFrom(*mat); - startRow += mat->getHeight(); + for (auto& thread : threads_) { + args.push_back(thread->getGradientMachine()->getLayerOutput(layerName)); } + outLayerArgs_.concat(args, false /* use_gpu */, outArgStream_, passType_); - return layerOutput; + return outLayerArgs_; } void MultiGradientMachine::backwardImp(const UpdateCallback& callback) { diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.h b/paddle/gserver/gradientmachines/MultiGradientMachine.h index a1a2d417062de5..9083230afd69e2 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.h +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.h @@ -189,7 +189,7 @@ class MultiGradientMachine : public GradientMachine { PassType passType, const UpdateCallback& callback); - virtual MatrixPtr getLayerOutput(const std::string& layerName) const; + virtual const Argument& getLayerOutput(const std::string& layerName); virtual void onPassEnd(); @@ -316,6 +316,8 @@ class MultiGradientMachine : public GradientMachine { std::vector outArgs_; hl_stream_t outArgStream_; + Argument outLayerArgs_; + /// ParameterType which needs to be merged from each GPU std::vector mergeTypes_; int numDevices_; /* number of gpu devices */ diff --git a/paddle/gserver/gradientmachines/NeuralNetwork.cpp b/paddle/gserver/gradientmachines/NeuralNetwork.cpp index 00887c81d47687..d1afde40e1f81e 100644 --- a/paddle/gserver/gradientmachines/NeuralNetwork.cpp +++ b/paddle/gserver/gradientmachines/NeuralNetwork.cpp @@ -293,10 +293,8 @@ void NeuralNetwork::backward(const UpdateCallback& callback) { } } -MatrixPtr NeuralNetwork::getLayerOutput(const std::string& layerName) const { - auto it = layerMap_.find(layerName); - CHECK(it != layerMap_.end()) << "Cannot find layer: " << layerName; - return it->second->getOutputValue(); +const Argument& NeuralNetwork::getLayerOutput(const std::string& layerName) { + return getLayer(layerName)->getOutput(); } void NeuralNetwork::onPassEnd() { diff --git a/paddle/gserver/gradientmachines/NeuralNetwork.h b/paddle/gserver/gradientmachines/NeuralNetwork.h index 6ecc251a409cb9..b4dc38e31b6fae 100644 --- a/paddle/gserver/gradientmachines/NeuralNetwork.h +++ b/paddle/gserver/gradientmachines/NeuralNetwork.h @@ -87,7 +87,7 @@ class NeuralNetwork : public GradientMachine { virtual void backward(const UpdateCallback& callback = nullptr); - virtual MatrixPtr getLayerOutput(const std::string& layerName) const; + virtual const Argument& getLayerOutput(const std::string& layerName); const LayerPtr& getLayer(const std::string& layerName) const { auto it = layerMap_.find(layerName); diff --git a/paddle/gserver/layers/CosSimLayer.cpp b/paddle/gserver/layers/CosSimLayer.cpp index 1501c7437011d5..57ba124e40cbd0 100644 --- a/paddle/gserver/layers/CosSimLayer.cpp +++ b/paddle/gserver/layers/CosSimLayer.cpp @@ -68,7 +68,7 @@ void CosSimLayer::forward(PassType passType) { void CosSimLayer::backward(const UpdateCallback& callback) { /* activation */ { REGISTER_TIMER_INFO("CosBpAtvTimer", getName().c_str()); - CHECK_EQ(backward_.size(), 1) << "Only one backward function needed"; + CHECK_EQ(backward_.size(), 1UL) << "Only one backward function needed"; const auto outG = this->getOutputGrad(); const auto outV = this->getOutputValue(); diff --git a/paddle/py_paddle/util.py b/paddle/py_paddle/util.py index ce105d249aaf3e..a708def1d2d7f6 100644 --- a/paddle/py_paddle/util.py +++ b/paddle/py_paddle/util.py @@ -208,7 +208,7 @@ def getLayerOutputs(self, layerNames): output = dict() for name in layerNames: - output[name] = __matrix_to_numpy__(self.getLayerOutput(name)) + output[name] = __arguments_to_numpy__(0, self.getLayerOutput(name)) return output swig_paddle.GradientMachine.getLayerOutputs = getLayerOutputs From fa67ac98e580115bc6ad22f406b6f1242dbd3d61 Mon Sep 17 00:00:00 2001 From: liaogang Date: Wed, 22 Feb 2017 17:09:18 +0800 Subject: [PATCH 263/370] Specify compiler in setup --- paddle/setup.py.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/paddle/setup.py.in b/paddle/setup.py.in index c79666bc81b6f3..38621af065913c 100644 --- a/paddle/setup.py.in +++ b/paddle/setup.py.in @@ -55,6 +55,9 @@ elif is_osx == True: include_dirs = [np.get_include(), "../"] # include numpy and paddle. +os.environ["CC"] = "@CMAKE_C_COMPILER@" +os.environ["CXX"] = "@CMAKE_CXX_COMPILER@" + setup(name="py_paddle", version="@PADDLE_VERSION@", ext_modules=[ From bbfcee20fd8733c2e9ea5ec49e1963d62e777730 Mon Sep 17 00:00:00 2001 From: liaogang Date: Wed, 22 Feb 2017 17:42:08 +0800 Subject: [PATCH 264/370] Add const for Trainer::getLayerOutput --- paddle/api/PaddleAPI.h | 2 +- paddle/api/Trainer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/paddle/api/PaddleAPI.h b/paddle/api/PaddleAPI.h index 10569a71708463..59798796a249c7 100644 --- a/paddle/api/PaddleAPI.h +++ b/paddle/api/PaddleAPI.h @@ -953,7 +953,7 @@ class Trainer { Arguments* getForwardOutput(); - Arguments* getLayerOutput(const std::string& layerName); + Arguments* getLayerOutput(const std::string& layerName) const; }; /// the N-Best results generated from one input sequence. diff --git a/paddle/api/Trainer.cpp b/paddle/api/Trainer.cpp index c742614aff97f2..29cf2aa4501de3 100644 --- a/paddle/api/Trainer.cpp +++ b/paddle/api/Trainer.cpp @@ -131,7 +131,7 @@ void Trainer::testOneDataBatch(size_t batchSize, const Arguments& args) { void TrainerPrivate::finishTestPeriod() { tester_->finishTestPeriod(); } void Trainer::finishTestPeriod() { m->finishTestPeriod(); } -Arguments* Trainer::getLayerOutput(const std::string& layerName) { +Arguments* Trainer::getLayerOutput(const std::string& layerName) const { auto nn = this->m->getGradientMachine(); CHECK(nn) << "trainerInternal_.getGradientMachine() is not NeuralNetwork"; return Arguments::createByPaddleArgument(&nn->getLayerOutput(layerName)); From 608de7c0e3ea6184c5aa72bca93d10381d4baa1f Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Wed, 22 Feb 2017 11:01:59 -0800 Subject: [PATCH 265/370] fix according to comments --- python/paddle/reader/decorator.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/python/paddle/reader/decorator.py b/python/paddle/reader/decorator.py index 1192b5de90f980..5fc799e61dab95 100644 --- a/python/paddle/reader/decorator.py +++ b/python/paddle/reader/decorator.py @@ -66,7 +66,7 @@ def chain(*readers): [0, 0, 0, 1, 1, 1, 2, 2, 2] Args: - readerss: input readers. + readers: input readers. Returns: the new data reader. @@ -83,7 +83,7 @@ def reader(): return reader -class ComposeNotAligned: +class ComposeNotAligned(ValueError): pass @@ -128,7 +128,8 @@ def reader(): for o in outputs: if o is None: # None will be not be present if compose is aligned - raise ComposeNotAligned + raise ComposeNotAligned( + "outputs of readers are not aligned.") yield sum(map(make_tuple, outputs), ()) return reader From 963de16bfd7deba24af70f0183fd3295d480c863 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Wed, 22 Feb 2017 15:42:55 -0800 Subject: [PATCH 266/370] change from google python style to pep 287 --- python/paddle/reader/decorator.py | 55 ++++++++++++++----------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/python/paddle/reader/decorator.py b/python/paddle/reader/decorator.py index 5fc799e61dab95..d656d5feb4f181 100644 --- a/python/paddle/reader/decorator.py +++ b/python/paddle/reader/decorator.py @@ -21,19 +21,17 @@ def shuffle(reader, buf_size): - """Creates a data reader whose data output is suffled. + """ + Creates a data reader whose data output is suffled. Output from the iterator that created by original reader will be buffered into shuffle buffer, and then shuffled. The size of shuffle buffer is determined by argument buf_size. - Args: - reader: the original reader whose output will be - shuffled. - buf_size: shuffle buffer size. + :param reader: the original reader whose output will be shuffled. + :param buf_size: shuffle buffer size. - Returns: - the new reader whose output is shuffled. + :returns:the new reader whose output is shuffled. """ def data_reader(): @@ -55,8 +53,9 @@ def data_reader(): def chain(*readers): - """Creates a data reader whose output is the outputs of input data - readers chained together. + """ + Creates a data reader whose output is the outputs of input data + readers chained together. If input readers output following data entries: [0, 0, 0] @@ -65,11 +64,8 @@ def chain(*readers): The chained reader will output: [0, 0, 0, 1, 1, 1, 2, 2, 2] - Args: - readers: input readers. - - Returns: - the new data reader. + :param readers: input readers. + :returns: the new data reader. """ def reader(): @@ -88,25 +84,23 @@ class ComposeNotAligned(ValueError): def compose(*readers, **kwargs): - """Creates a data reader whose output is the combination of input readers. + """ + Creates a data reader whose output is the combination of input readers. If input readers output following data entries: (1, 2) 3 (4, 5) The composed reader will output: (1, 2, 3, 4, 5) - Args: - *readers: readers that will be composed together. - check_alignment: If True, will check if input readers are aligned - correctly. If False, will not check alignment and trailing outputs - will be discarded. Defaults to True. + :*readers: readers that will be composed together. + :check_alignment: if True, will check if input readers are aligned + correctly. If False, will not check alignment and trailing outputs + will be discarded. Defaults to True. - Returns: - the new data reader. + :returns: the new data reader. - Raises: - ComposeNotAligned: outputs of readers are not aligned. - Will not raise when check_alignment is set to False. + :raises ComposeNotAligned: outputs of readers are not aligned. + Will not raise when check_alignment is set to False. """ check_alignment = kwargs.pop('check_alignment', True) @@ -136,18 +130,17 @@ def reader(): def buffered(reader, size): - """Creates a buffered data reader. + """ + Creates a buffered data reader. The buffered data reader will read and save data entries into a buffer. Reading from the buffered data reader will proceed as long as the buffer is not empty. - Args: - reader: the data reader to read from. - size: max buffer size. + :param reader: the data reader to read from. + :param size: max buffer size. - Returns: - The buffered data reader. + :returns: the buffered data reader. """ class EndSignal(): From 466935b4ecdc57e314ebec76a647d70c67f4494b Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Wed, 22 Feb 2017 15:57:24 -0800 Subject: [PATCH 267/370] add decorator: map_readers --- python/paddle/reader/decorator.py | 25 +++++++++++++++++++- python/paddle/reader/tests/decorator_test.py | 16 +++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/python/paddle/reader/decorator.py b/python/paddle/reader/decorator.py index d656d5feb4f181..9f4234358f469b 100644 --- a/python/paddle/reader/decorator.py +++ b/python/paddle/reader/decorator.py @@ -12,7 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -__all__ = ['buffered', 'compose', 'chain', 'shuffle', 'ComposeNotAligned'] +__all__ = [ + 'map_readers', 'buffered', 'compose', 'chain', 'shuffle', + 'ComposeNotAligned' +] from Queue import Queue from threading import Thread @@ -20,6 +23,26 @@ import random +def map_readers(func, *readers): + """ + Creates a data reader that outputs return value of function using + output of each data readers as arguments. + + :param func: function to use. + :param *readers: readers whose outputs will be used as arguments of func. + :returns: the created data reader. + """ + + def reader(): + rs = [] + for r in readers: + rs.append(r()) + for e in itertools.imap(func, *rs): + yield e + + return reader + + def shuffle(reader, buf_size): """ Creates a data reader whose data output is suffled. diff --git a/python/paddle/reader/tests/decorator_test.py b/python/paddle/reader/tests/decorator_test.py index 46eec44158cee5..0396a61786539b 100644 --- a/python/paddle/reader/tests/decorator_test.py +++ b/python/paddle/reader/tests/decorator_test.py @@ -26,6 +26,22 @@ def reader(): return reader +class TestMap(unittest.TestCase): + def test_map(self): + d = {"h": 0, "i": 1} + + def tokenize(x): + return d[x] + + def read(): + yield "h" + yield "i" + + r = paddle.reader.map_readers(tokenize, read) + for i, e in enumerate(r()): + self.assertEqual(e, i) + + class TestBuffered(unittest.TestCase): def test_read(self): for size in range(20): From d0dcb3ea34ada48901666283929e35587d1c5c78 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Wed, 22 Feb 2017 15:34:36 -0800 Subject: [PATCH 268/370] create numpy array reader creator and text reader creator --- python/paddle/reader/__init__.py | 2 + python/paddle/reader/creator.py | 52 +++++++++++++++++++ python/paddle/reader/tests/CMakeLists.txt | 5 ++ python/paddle/reader/tests/creator_test.py | 38 ++++++++++++++ .../paddle/reader/tests/test_data_creator.txt | 3 ++ 5 files changed, 100 insertions(+) create mode 100644 python/paddle/reader/creator.py create mode 100644 python/paddle/reader/tests/creator_test.py create mode 100644 python/paddle/reader/tests/test_data_creator.txt diff --git a/python/paddle/reader/__init__.py b/python/paddle/reader/__init__.py index 493b410e8299eb..7373dc461b1d31 100644 --- a/python/paddle/reader/__init__.py +++ b/python/paddle/reader/__init__.py @@ -21,3 +21,5 @@ # # r = paddle.reader.buffered(paddle.reader.creator.text("hello.txt")) from decorator import * + +import creator diff --git a/python/paddle/reader/creator.py b/python/paddle/reader/creator.py new file mode 100644 index 00000000000000..5c840f94b52f16 --- /dev/null +++ b/python/paddle/reader/creator.py @@ -0,0 +1,52 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + +__all__ = ['np_array', 'text_file'] + + +def np_array(x): + """ + Creates a data reader from numpy array. + The highest dimension will be treated as batch dimension to iterate on. + + :param x: the numpy array to create reader from. + :returns: data reader created from x. + """ + + def reader(): + if x.ndim < 1: + yield x + + for e in x: + yield e + + return reader + + +def text_file(path): + """ + Creates a data reader that outputs text line by line from given text file. + Trailing new line ('\n') of each line will be removed. + + :path: path of the text file. + :returns: data reader of text file + """ + + def reader(): + f = open(path, "r") + for l in f: + yield l.rstrip('\n') + f.close() + + return reader diff --git a/python/paddle/reader/tests/CMakeLists.txt b/python/paddle/reader/tests/CMakeLists.txt index 502c897d8946a8..da072fb3dbeed5 100644 --- a/python/paddle/reader/tests/CMakeLists.txt +++ b/python/paddle/reader/tests/CMakeLists.txt @@ -2,3 +2,8 @@ add_test(NAME reader_decorator_test COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/reader/tests/decorator_test.py WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) + +add_test(NAME reader_creator_test + COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ + ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/reader/tests/creator_test.py + WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) diff --git a/python/paddle/reader/tests/creator_test.py b/python/paddle/reader/tests/creator_test.py new file mode 100644 index 00000000000000..eda8ab6715b2be --- /dev/null +++ b/python/paddle/reader/tests/creator_test.py @@ -0,0 +1,38 @@ +# Copyright PaddlePaddle contributors. All Rights Reserved +# +# 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. +import unittest +import paddle.reader.creator +import numpy as np +import os + + +class TestNumpyArray(unittest.TestCase): + def test_numpy_array(self): + l = [[1, 2, 3], [4, 5, 6]] + x = np.array(l, np.int32) + reader = paddle.reader.creator.np_array(x) + for idx, e in enumerate(reader()): + self.assertItemsEqual(e, l[idx]) + + +class TestTextFile(unittest.TestCase): + def test_text_file(self): + path = os.path.join(os.path.dirname(__file__), "test_data_creator.txt") + reader = paddle.reader.creator.text_file(path) + for idx, e in enumerate(reader()): + self.assertEqual(e, str(idx * 2) + " " + str(idx * 2 + 1)) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/paddle/reader/tests/test_data_creator.txt b/python/paddle/reader/tests/test_data_creator.txt new file mode 100644 index 00000000000000..a2a8d47d43868d --- /dev/null +++ b/python/paddle/reader/tests/test_data_creator.txt @@ -0,0 +1,3 @@ +0 1 +2 3 +4 5 From 2715e9de6fb656693843bb4dd254eaedb587ad94 Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Thu, 23 Feb 2017 13:14:32 +0800 Subject: [PATCH 269/370] add ParamAttr in V2 --- python/paddle/v2/__init__.py | 3 ++- python/paddle/v2/attr.py | 23 +++++++++++++++++++++++ python/paddle/v2/layer.py | 9 +++++++-- 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 python/paddle/v2/attr.py diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index 30d0b2a398bd0e..0cf7b8e9039f73 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -18,11 +18,12 @@ import trainer import event import data_type +import attr import py_paddle.swig_paddle as api __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', - 'event', 'data_type' + 'event', 'data_type', 'attr' ] diff --git a/python/paddle/v2/attr.py b/python/paddle/v2/attr.py new file mode 100644 index 00000000000000..40c64f621b443d --- /dev/null +++ b/python/paddle/v2/attr.py @@ -0,0 +1,23 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + +from paddle.trainer_config_helpers.attrs import * + +__all__ = [ + "Param", + "Extra", +] + +Param = ParameterAttribute +Extra = ExtraLayerAttribute diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index cd6dd5110a44b2..3920d4a08fc627 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -74,6 +74,8 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. from paddle.trainer_config_helpers.default_decorators import wrap_name_default import data_type +import activation +import attr __all__ = [ 'parse_network', 'data', 'fc', 'max_id', 'classification_cost', @@ -230,8 +232,11 @@ def to_proto_impl(self, **kwargs): weight = data(name='weight', type=data_type.dense_vector(10)) score = data(name='score', type=data_type.dense_vector(1)) - hidden = fc(input=pixel, size=100, act=conf_helps.SigmoidActivation()) - inference = fc(input=hidden, size=10, act=conf_helps.SoftmaxActivation()) + hidden = fc(input=pixel, + size=100, + act=activation.Sigmoid(), + param_attr=attr.Param(name='hidden')) + inference = fc(input=hidden, size=10, act=activation.Softmax()) maxid = max_id(input=inference) cost1 = classification_cost(input=inference, label=label) cost2 = classification_cost(input=inference, label=label, weight=weight) From 448e60b5fec9e402dd12c7dfc71a6e062d57c12b Mon Sep 17 00:00:00 2001 From: Peng Li Date: Thu, 23 Feb 2017 14:12:11 +0800 Subject: [PATCH 270/370] Fix macro bug in hl_warpctc_warp.cc to support double precision --- paddle/cuda/src/hl_warpctc_wrap.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/paddle/cuda/src/hl_warpctc_wrap.cc b/paddle/cuda/src/hl_warpctc_wrap.cc index 55b940ca67acce..246e7ad8af7368 100644 --- a/paddle/cuda/src/hl_warpctc_wrap.cc +++ b/paddle/cuda/src/hl_warpctc_wrap.cc @@ -54,22 +54,26 @@ DYNAMIC_LOAD_WARPCTC_WRAP(get_workspace_size) #define WARPCTC_GET_VERSION dynload::get_warpctc_version #define WARPCTC_GET_STATUS_STRING dynload::ctcGetStatusString +static int g_warpctcVersion = -1; #ifndef PADDLE_TYPE_DOUBLE #define WARPCTC_COMPUTE_LOSS dynload::compute_ctc_loss #define WARPCTC_GET_WORKSPACE_SIZE dynload::get_workspace_size #else -#define WARPCTC_LOG_FATAL \ - LOG(FATAL) << "warp-ctc [version " << g_warpctcVersion \ - << "] Error: not support double precision." -#define WARPCTC_COMPUTE_LOSS(...) WARPCTC_LOG_FATAL(__VA_ARGS__) -#define WARPCTC_GET_WORKSPACE_SIZE(...) WARPCTC_LOG_FATAL(__VA_ARGS__) +ctcStatus_t fatal(...) { + LOG(FATAL) << "warp-ctc [version " << g_warpctcVersion + << "] Error: not support double precision."; + // both of get_warpctc_version() and get_workspace_size() return an ctcStatus + // type value + return CTC_STATUS_EXECUTION_FAILED; +} +#define WARPCTC_COMPUTE_LOSS fatal +#define WARPCTC_GET_WORKSPACE_SIZE fatal #endif /** * Check build-in warp-ctc function using glog and it also * support << operator for more details error info. */ -static int g_warpctcVersion = -1; #define CHECK_WARPCTC(warpctcStat) \ CHECK_EQ(CTC_STATUS_SUCCESS, warpctcStat) \ << "warp-ctc [version " << g_warpctcVersion \ From 36dbfe86a7dc37d5c04dd1be3ef8adf34414ded1 Mon Sep 17 00:00:00 2001 From: Peng Li Date: Thu, 23 Feb 2017 14:46:54 +0800 Subject: [PATCH 271/370] Change ctcStatus_t to hl_warpctc_status_t to keep consistency --- paddle/cuda/src/hl_warpctc_wrap.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddle/cuda/src/hl_warpctc_wrap.cc b/paddle/cuda/src/hl_warpctc_wrap.cc index 246e7ad8af7368..f57efb2b46797c 100644 --- a/paddle/cuda/src/hl_warpctc_wrap.cc +++ b/paddle/cuda/src/hl_warpctc_wrap.cc @@ -59,7 +59,7 @@ static int g_warpctcVersion = -1; #define WARPCTC_COMPUTE_LOSS dynload::compute_ctc_loss #define WARPCTC_GET_WORKSPACE_SIZE dynload::get_workspace_size #else -ctcStatus_t fatal(...) { +hl_warpctc_status_t fatal(...) { LOG(FATAL) << "warp-ctc [version " << g_warpctcVersion << "] Error: not support double precision."; // both of get_warpctc_version() and get_workspace_size() return an ctcStatus From b1ab8b56cfbad21ba1b70d010392031e72cf5c71 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 23 Feb 2017 15:03:34 +0800 Subject: [PATCH 272/370] Use plain C++ 03 to implement getStatsInfo. --- paddle/gserver/evaluators/Evaluator.cpp | 196 ++++++++++++------------ paddle/gserver/evaluators/Evaluator.h | 13 +- paddle/utils/Error.h | 28 ++-- paddle/utils/tests/test_Error.cpp | 8 +- 4 files changed, 129 insertions(+), 116 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index 89f95438019d8c..8fce8df8a3b0e5 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -626,78 +626,34 @@ real PrecisionRecallEvaluator::evalImp(std::vector& arguments) { return 0; } -template -void PrecisionRecallEvaluator::printStatsHelper(T1 labelCallback, - T2 microAvgCallback) const { - int label = config_.positive_label(); - if (label != -1) { - CHECK(label >= 0 && label < (int)statsInfo_.size()) - << "positive_label [" << label << "] should be in range [0, " - << statsInfo_.size() << ")"; - double precision = - calcPrecision(statsInfo_[label].TP, statsInfo_[label].FP); - double recall = calcRecall(statsInfo_[label].TP, statsInfo_[label].FN); - labelCallback(label, precision, recall, calcF1Score(precision, recall)); - return; - } - - // micro average method: precision = (TP1+TP2)/(TP1+FP1+TP2+FP2) - // macro average method: precision = (precision1+precision2)/2 - double microTotalTP = 0; - double microTotalFP = 0; - double microTotalFN = 0; - double macroAvgPrecision = 0; - double macroAvgRecall = 0; - size_t numLabels = statsInfo_.size(); - for (size_t i = 0; i < numLabels; ++i) { - microTotalTP += statsInfo_[i].TP; - microTotalFP += statsInfo_[i].FP; - microTotalFN += statsInfo_[i].FN; - macroAvgPrecision += calcPrecision(statsInfo_[i].TP, statsInfo_[i].FP); - macroAvgRecall += calcRecall(statsInfo_[i].TP, statsInfo_[i].FN); - } - macroAvgPrecision /= numLabels; - macroAvgRecall /= numLabels; - double macroAvgF1Score = calcF1Score(macroAvgPrecision, macroAvgRecall); - - double microAvgPrecision = calcPrecision(microTotalTP, microTotalFP); - double microAvgRecall = calcPrecision(microTotalTP, microTotalFN); - double microAvgF1Score = calcF1Score(microAvgPrecision, microAvgRecall); - - microAvgCallback(macroAvgPrecision, - macroAvgRecall, - macroAvgF1Score, - isMultiBinaryLabel_, - microAvgPrecision, - microAvgRecall, - microAvgF1Score); -} - void PrecisionRecallEvaluator::printStats(std::ostream& os) const { - this->printStatsHelper( - [&os](int label, double precision, double recall, double f1) { - os << "positive_label=" << label << " precision=" << precision - << " recall=" << recall << " F1-score=" << f1; - }, - [&os](double macroAvgPrecision, - double macroAvgRecall, - double macroAvgF1Score, - bool isMultiBinaryLabel, - double microAvgPrecision, - double microAvgRecall, - double microAvgF1Score) { - os << "macro-average-precision=" << macroAvgPrecision - << " macro-average-recall=" << macroAvgRecall - << " macro-average-F1-score=" << macroAvgF1Score; - if (!isMultiBinaryLabel) { - // precision and recall are equal in this case - os << " micro-average-precision=" << microAvgPrecision; - } else { - os << " micro-average-precision=" << microAvgPrecision - << " micro-average-recall=" << microAvgRecall - << " micro-average-F1-score=" << microAvgF1Score; - } - }); + double precision, recall, f1, macroAvgPrecision, macroAvgRecall, + macroAvgF1Score, microAvgPrecision, microAvgRecall, microAvgF1Score; + bool containMacroMicroInfo = getStatsInfo(&precision, + &recall, + &f1, + ¯oAvgPrecision, + ¯oAvgRecall, + ¯oAvgF1Score, + µAvgPrecision, + µAvgRecall, + µAvgF1Score); + os << "positive_label=" << config_.positive_label() + << " precision=" << precision << " recall=" << recall + << " F1-score=" << f1; + if (containMacroMicroInfo) { + os << "macro-average-precision=" << macroAvgPrecision + << " macro-average-recall=" << macroAvgRecall + << " macro-average-F1-score=" << macroAvgF1Score; + if (!isMultiBinaryLabel_) { + // precision and recall are equal in this case + os << " micro-average-precision=" << microAvgPrecision; + } else { + os << " micro-average-precision=" << microAvgPrecision + << " micro-average-recall=" << microAvgRecall + << " micro-average-F1-score=" << microAvgF1Score; + } + }; } void PrecisionRecallEvaluator::calcStatsInfo(const MatrixPtr& output, @@ -780,32 +736,33 @@ void PrecisionRecallEvaluator::calcStatsInfoMulti(const MatrixPtr& output, void PrecisionRecallEvaluator::storeLocalValues() const { if (this->values_.size() == 0) { - this->printStatsHelper( - [this](int label, double precision, double recall, double f1) { - values_["positive_label"] = (double)label; - values_["precision"] = precision; - values_["recal"] = recall; - values_["F1-score"] = f1; - }, - [this](double macroAvgPrecision, - double macroAvgRecall, - double macroAvgF1Score, - bool isMultiBinaryLabel, - double microAvgPrecision, - double microAvgRecall, - double microAvgF1Score) { - values_["macro-average-precision"] = macroAvgPrecision; - values_["macro-average-recall"] = macroAvgRecall; - values_["macro-average-F1-score"] = macroAvgF1Score; - if (!isMultiBinaryLabel) { - // precision and recall are equal in this case - values_["micro-average-precision"] = microAvgPrecision; - } else { - values_["micro-average-precision"] = microAvgPrecision; - values_["micro-average-recall"] = microAvgRecall; - values_["micro-average-F1-score"] = microAvgF1Score; - } - }); + double precision, recall, f1, macroAvgPrecision, macroAvgRecall, + macroAvgF1Score, microAvgPrecision, microAvgRecall, microAvgF1Score; + bool containMacroMicroInfo = getStatsInfo(&precision, + &recall, + &f1, + ¯oAvgPrecision, + ¯oAvgRecall, + ¯oAvgF1Score, + µAvgPrecision, + µAvgRecall, + µAvgF1Score); + values_["precision"] = precision; + values_["recal"] = recall; + values_["F1-score"] = f1; + if (containMacroMicroInfo) { + values_["macro-average-precision"] = macroAvgPrecision; + values_["macro-average-recall"] = macroAvgRecall; + values_["macro-average-F1-score"] = macroAvgF1Score; + if (!isMultiBinaryLabel_) { + // precision and recall are equal in this case + values_["micro-average-precision"] = microAvgPrecision; + } else { + values_["micro-average-precision"] = microAvgPrecision; + values_["micro-average-recall"] = microAvgRecall; + values_["micro-average-F1-score"] = microAvgF1Score; + } + } } } @@ -865,6 +822,51 @@ void PrecisionRecallEvaluator::distributeEval(ParameterClient2* client) { delete[] buf; } +bool PrecisionRecallEvaluator::getStatsInfo(double* precision, + double* recall, + double* f1, + double* macroAvgPrecision, + double* macroAvgRecall, + double* macroAvgF1Score, + double* microAvgPrecision, + double* microAvgRecall, + double* microAvgF1Score) const { + int label = config_.positive_label(); + if (label != -1) { + CHECK(label >= 0 && label < (int)statsInfo_.size()) + << "positive_label [" << label << "] should be in range [0, " + << statsInfo_.size() << ")"; + *precision = calcPrecision(statsInfo_[label].TP, statsInfo_[label].FP); + *recall = calcRecall(statsInfo_[label].TP, statsInfo_[label].FN); + *f1 = calcF1Score(*precision, *recall); + return false; + } + + // micro average method: precision = (TP1+TP2)/(TP1+FP1+TP2+FP2) + // macro average method: precision = (precision1+precision2)/2 + double microTotalTP = 0; + double microTotalFP = 0; + double microTotalFN = 0; + *macroAvgPrecision = 0; + *macroAvgRecall = 0; + size_t numLabels = statsInfo_.size(); + for (size_t i = 0; i < numLabels; ++i) { + microTotalTP += statsInfo_[i].TP; + microTotalFP += statsInfo_[i].FP; + microTotalFN += statsInfo_[i].FN; + *macroAvgPrecision += calcPrecision(statsInfo_[i].TP, statsInfo_[i].FP); + *macroAvgRecall += calcRecall(statsInfo_[i].TP, statsInfo_[i].FN); + } + *macroAvgPrecision /= numLabels; + *macroAvgRecall /= numLabels; + *macroAvgF1Score = calcF1Score(*macroAvgPrecision, *macroAvgRecall); + + *microAvgPrecision = calcPrecision(microTotalTP, microTotalFP); + *microAvgRecall = calcPrecision(microTotalTP, microTotalFN); + *microAvgF1Score = calcF1Score(*microAvgPrecision, *microAvgRecall); + return true; +} + REGISTER_EVALUATOR(pnpair, PnpairEvaluator); void PnpairEvaluator::start() { Evaluator::start(); diff --git a/paddle/gserver/evaluators/Evaluator.h b/paddle/gserver/evaluators/Evaluator.h index a5694a088c3c44..eb19e6f4dde5d9 100644 --- a/paddle/gserver/evaluators/Evaluator.h +++ b/paddle/gserver/evaluators/Evaluator.h @@ -125,7 +125,7 @@ class Evaluator { * has multiple field, the name could be `evaluator_name.field1`. For example * the PrecisionRecallEvaluator contains `precision`, `recall` fields. The get * names will return `precision_recall_evaluator.precision`, - * `precision_recall.recal`, etc. + * `precision_recall_evaluator.recal`, etc. * * Also, if current Evaluator is a combined evaluator. getNames will return * all names of all evaluators inside the combined evaluator. @@ -387,8 +387,15 @@ class PrecisionRecallEvaluator : public Evaluator { IVectorPtr cpuLabel_; MatrixPtr cpuWeight_; - template - void printStatsHelper(T1 labelCallback, T2 microAvgCallback) const; + bool getStatsInfo(double* precision, + double* recall, + double* f1, + double* macroAvgPrecision, + double* macroAvgRecall, + double* macroAvgF1Score, + double* microAvgPrecision, + double* microAvgRecall, + double* microAvgF1Score) const; void calcStatsInfo(const MatrixPtr& output, const IVectorPtr& label, diff --git a/paddle/utils/Error.h b/paddle/utils/Error.h index 1ae202890f874c..cda1b5c37dada8 100644 --- a/paddle/utils/Error.h +++ b/paddle/utils/Error.h @@ -37,10 +37,10 @@ namespace paddle { * * Error __must_check bar() { * // do something. - * Status s = foo(); // invoke other method return status. - * if (!s) return s; + * Error err = foo(); // invoke other method return status. + * if (err) return err; * // do something else. - * return Status(); + * return Error(); * } * @endcode{cpp} * @@ -53,8 +53,8 @@ namespace paddle { * * int foo(Error* error) { * // Do something. - * Error s = bar(); - * if (!s) { + * Error err = bar(); + * if (err) { * *error = s; * return 0; * } @@ -68,10 +68,10 @@ namespace paddle { * } * * Error foobar() { - * Error s; + * Error err; * // do something. - * foo(&s); - * if (!s) return s; + * foo(&err); + * if (err) return err; * } * @endcode{cpp} * @@ -112,18 +112,22 @@ class Error { } /** - * @brief operator bool, return True if there is no error. + * @brief operator bool, return True if there is something error. */ - operator bool() const { return msg_ == nullptr; } + operator bool() const { return !this->isOK(); } - bool isOK() const { return *this; } + /** + * @brief isOK return True if there is no error. + * @return True if no error. + */ + bool isOK() const { return msg_ == nullptr; } /** * @brief check this status by glog. * @note It is a temp method used during cleaning Paddle code. It will be * removed later. */ - void check() const { CHECK(*this) << msg(); } + void check() const { CHECK(this->isOK()) << msg(); } private: std::shared_ptr msg_; diff --git a/paddle/utils/tests/test_Error.cpp b/paddle/utils/tests/test_Error.cpp index 85156466e2cafd..fdf326b17a1c8b 100644 --- a/paddle/utils/tests/test_Error.cpp +++ b/paddle/utils/tests/test_Error.cpp @@ -18,17 +18,17 @@ limitations under the License. */ TEST(Error, testAll) { paddle::Error error; - ASSERT_TRUE(error); - error = paddle::Error("I'm the error"); ASSERT_FALSE(error); + error = paddle::Error("I'm the error"); + ASSERT_TRUE(error); ASSERT_STREQ("I'm the error", error.msg()); error = paddle::Error("error2"); - ASSERT_FALSE(error); + ASSERT_TRUE(error); ASSERT_STREQ("error2", error.msg()); int i = 3; auto error3 = paddle::Error("error%d", i); - ASSERT_FALSE(error3); + ASSERT_TRUE(error3); ASSERT_STREQ("error3", error3.msg()); } From b6ac64a36bf260780d18dc6722f6ccdd0c96aba0 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 23 Feb 2017 15:06:30 +0800 Subject: [PATCH 273/370] Remove unnecessary error default value. --- paddle/gserver/evaluators/Evaluator.cpp | 8 +------ paddle/gserver/evaluators/Evaluator.h | 21 +++++++------------ .../gradientmachines/NeuralNetwork.cpp | 2 +- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index 8fce8df8a3b0e5..6c1c2f62be273c 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -781,9 +781,7 @@ real PrecisionRecallEvaluator::getValue(const std::string& name, paddle::str::split(name, '.', &buffers); auto it = this->values_.find(buffers[buffers.size() - 1]); if (it == this->values_.end()) { // not found - if (err != nullptr) { - *err = Error("No such key %s", name.c_str()); - } + *err = Error("No such key %s", name.c_str()); return .0f; } @@ -792,10 +790,6 @@ real PrecisionRecallEvaluator::getValue(const std::string& name, std::string PrecisionRecallEvaluator::getType(const std::string& name, Error* err) const { - Error localErr; - if (err == nullptr) { - err = &localErr; - } this->getValue(name, err); if (!err->isOK()) { return ""; diff --git a/paddle/gserver/evaluators/Evaluator.h b/paddle/gserver/evaluators/Evaluator.h index eb19e6f4dde5d9..6a122704ea34ae 100644 --- a/paddle/gserver/evaluators/Evaluator.h +++ b/paddle/gserver/evaluators/Evaluator.h @@ -141,16 +141,13 @@ class Evaluator { * @brief getValue will return the current evaluate value of one field. * * @param name: The field name of current evaluator. - * @param err [out]: The error state. nullptr means don't care. + * @param err [out]: The error state. * * @return The evaluate value(metric). */ - virtual real getValue(const std::string& name, - paddle::Error* err = nullptr) const { + virtual real getValue(const std::string& name, paddle::Error* err) const { if (name != config_.name()) { - if (err != nullptr) { - *err = paddle::Error("no such name of evaluator %s", name.c_str()); - } + *err = paddle::Error("no such name of evaluator %s", name.c_str()); return .0f; } return this->getValueImpl(); @@ -168,8 +165,8 @@ class Evaluator { * @return the evaluator type string. */ virtual std::string getType(const std::string& name, - paddle::Error* err = nullptr) const { - if (name != config_.name() && err != nullptr) { + paddle::Error* err) const { + if (name != config_.name()) { *err = paddle::Error("no such name of evaluator %s", name.c_str()); return std::string(); } @@ -212,15 +209,11 @@ class NotGetableEvaluator : public Evaluator { void getNames(std::vector* names) {} real getValue(const std::string& name, Error* err) const { - if (err != nullptr) { - *err = Error("Not implemented"); - } + *err = Error("Not implemented"); return .0f; } std::string getType(const std::string& name, Error* err) const { - if (err != nullptr) { - *err = Error("Not implemented"); - } + *err = Error("Not implemented"); return ""; } }; diff --git a/paddle/gserver/gradientmachines/NeuralNetwork.cpp b/paddle/gserver/gradientmachines/NeuralNetwork.cpp index 4d2bdf0dc992da..273a9111c35a21 100644 --- a/paddle/gserver/gradientmachines/NeuralNetwork.cpp +++ b/paddle/gserver/gradientmachines/NeuralNetwork.cpp @@ -391,7 +391,7 @@ class CombinedEvaluator : public Evaluator { return callback(eval); } } - if (err != nullptr) *err = Error("No such key %s", name.c_str()); + *err = Error("No such key %s", name.c_str()); return T(); } }; From 2bb7fd817718794eb3fdef87207bf4a7596c606c Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 23 Feb 2017 15:09:09 +0800 Subject: [PATCH 274/370] Remove padde namespace in some code. --- paddle/gserver/evaluators/Evaluator.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.h b/paddle/gserver/evaluators/Evaluator.h index 6a122704ea34ae..c4110ec1c0b57f 100644 --- a/paddle/gserver/evaluators/Evaluator.h +++ b/paddle/gserver/evaluators/Evaluator.h @@ -145,9 +145,9 @@ class Evaluator { * * @return The evaluate value(metric). */ - virtual real getValue(const std::string& name, paddle::Error* err) const { + virtual real getValue(const std::string& name, Error* err) const { if (name != config_.name()) { - *err = paddle::Error("no such name of evaluator %s", name.c_str()); + *err = Error("no such name of evaluator %s", name.c_str()); return .0f; } return this->getValueImpl(); @@ -164,10 +164,9 @@ class Evaluator { * @param err: The error state. nullptr means don't care. * @return the evaluator type string. */ - virtual std::string getType(const std::string& name, - paddle::Error* err) const { + virtual std::string getType(const std::string& name, Error* err) const { if (name != config_.name()) { - *err = paddle::Error("no such name of evaluator %s", name.c_str()); + *err = Error("no such name of evaluator %s", name.c_str()); return std::string(); } return this->getTypeImpl(); From 9087e3a9bb9aac10236b513c5c9a52af1590b3a7 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 23 Feb 2017 16:18:19 +0800 Subject: [PATCH 275/370] Follow comments to use struct get return value. --- paddle/gserver/evaluators/Evaluator.cpp | 108 ++++++++++-------------- paddle/gserver/evaluators/Evaluator.h | 22 +++-- 2 files changed, 56 insertions(+), 74 deletions(-) diff --git a/paddle/gserver/evaluators/Evaluator.cpp b/paddle/gserver/evaluators/Evaluator.cpp index 5911a9ec59a5b8..9db6d252d97bfe 100644 --- a/paddle/gserver/evaluators/Evaluator.cpp +++ b/paddle/gserver/evaluators/Evaluator.cpp @@ -647,33 +647,24 @@ real PrecisionRecallEvaluator::evalImp(std::vector& arguments) { } void PrecisionRecallEvaluator::printStats(std::ostream& os) const { - double precision, recall, f1, macroAvgPrecision, macroAvgRecall, - macroAvgF1Score, microAvgPrecision, microAvgRecall, microAvgF1Score; - bool containMacroMicroInfo = getStatsInfo(&precision, - &recall, - &f1, - ¯oAvgPrecision, - ¯oAvgRecall, - ¯oAvgF1Score, - µAvgPrecision, - µAvgRecall, - µAvgF1Score); + PrintStatsInfo info; + bool containMacroMicroInfo = getStatsInfo(&info); os << "positive_label=" << config_.positive_label() - << " precision=" << precision << " recall=" << recall - << " F1-score=" << f1; + << " precision=" << info.precision << " recall=" << info.recall + << " F1-score=" << info.f1; if (containMacroMicroInfo) { - os << "macro-average-precision=" << macroAvgPrecision - << " macro-average-recall=" << macroAvgRecall - << " macro-average-F1-score=" << macroAvgF1Score; + os << "macro-average-precision=" << info.macroAvgPrecision + << " macro-average-recall=" << info.macroAvgRecall + << " macro-average-F1-score=" << info.macroAvgF1Score; if (!isMultiBinaryLabel_) { // precision and recall are equal in this case - os << " micro-average-precision=" << microAvgPrecision; + os << " micro-average-precision=" << info.microAvgPrecision; } else { - os << " micro-average-precision=" << microAvgPrecision - << " micro-average-recall=" << microAvgRecall - << " micro-average-F1-score=" << microAvgF1Score; + os << " micro-average-precision=" << info.microAvgPrecision + << " micro-average-recall=" << info.microAvgRecall + << " micro-average-F1-score=" << info.microAvgF1Score; } - }; + } } void PrecisionRecallEvaluator::calcStatsInfo(const MatrixPtr& output, @@ -756,31 +747,22 @@ void PrecisionRecallEvaluator::calcStatsInfoMulti(const MatrixPtr& output, void PrecisionRecallEvaluator::storeLocalValues() const { if (this->values_.size() == 0) { - double precision, recall, f1, macroAvgPrecision, macroAvgRecall, - macroAvgF1Score, microAvgPrecision, microAvgRecall, microAvgF1Score; - bool containMacroMicroInfo = getStatsInfo(&precision, - &recall, - &f1, - ¯oAvgPrecision, - ¯oAvgRecall, - ¯oAvgF1Score, - µAvgPrecision, - µAvgRecall, - µAvgF1Score); - values_["precision"] = precision; - values_["recal"] = recall; - values_["F1-score"] = f1; + PrintStatsInfo info; + bool containMacroMicroInfo = getStatsInfo(&info); + values_["precision"] = info.precision; + values_["recal"] = info.recall; + values_["F1-score"] = info.f1; if (containMacroMicroInfo) { - values_["macro-average-precision"] = macroAvgPrecision; - values_["macro-average-recall"] = macroAvgRecall; - values_["macro-average-F1-score"] = macroAvgF1Score; + values_["macro-average-precision"] = info.macroAvgPrecision; + values_["macro-average-recall"] = info.macroAvgRecall; + values_["macro-average-F1-score"] = info.macroAvgF1Score; if (!isMultiBinaryLabel_) { // precision and recall are equal in this case - values_["micro-average-precision"] = microAvgPrecision; + values_["micro-average-precision"] = info.microAvgPrecision; } else { - values_["micro-average-precision"] = microAvgPrecision; - values_["micro-average-recall"] = microAvgRecall; - values_["micro-average-F1-score"] = microAvgF1Score; + values_["micro-average-precision"] = info.microAvgPrecision; + values_["micro-average-recall"] = info.microAvgRecall; + values_["micro-average-F1-score"] = info.microAvgF1Score; } } } @@ -836,23 +818,16 @@ void PrecisionRecallEvaluator::distributeEval(ParameterClient2* client) { delete[] buf; } -bool PrecisionRecallEvaluator::getStatsInfo(double* precision, - double* recall, - double* f1, - double* macroAvgPrecision, - double* macroAvgRecall, - double* macroAvgF1Score, - double* microAvgPrecision, - double* microAvgRecall, - double* microAvgF1Score) const { +bool PrecisionRecallEvaluator::getStatsInfo( + PrecisionRecallEvaluator::PrintStatsInfo* info) const { int label = config_.positive_label(); if (label != -1) { CHECK(label >= 0 && label < (int)statsInfo_.size()) << "positive_label [" << label << "] should be in range [0, " << statsInfo_.size() << ")"; - *precision = calcPrecision(statsInfo_[label].TP, statsInfo_[label].FP); - *recall = calcRecall(statsInfo_[label].TP, statsInfo_[label].FN); - *f1 = calcF1Score(*precision, *recall); + info->precision = calcPrecision(statsInfo_[label].TP, statsInfo_[label].FP); + info->recall = calcRecall(statsInfo_[label].TP, statsInfo_[label].FN); + info->f1 = calcF1Score(info->precision, info->recall); return false; } @@ -861,23 +836,26 @@ bool PrecisionRecallEvaluator::getStatsInfo(double* precision, double microTotalTP = 0; double microTotalFP = 0; double microTotalFN = 0; - *macroAvgPrecision = 0; - *macroAvgRecall = 0; + info->macroAvgPrecision = 0; + info->macroAvgRecall = 0; size_t numLabels = statsInfo_.size(); for (size_t i = 0; i < numLabels; ++i) { microTotalTP += statsInfo_[i].TP; microTotalFP += statsInfo_[i].FP; microTotalFN += statsInfo_[i].FN; - *macroAvgPrecision += calcPrecision(statsInfo_[i].TP, statsInfo_[i].FP); - *macroAvgRecall += calcRecall(statsInfo_[i].TP, statsInfo_[i].FN); + info->macroAvgPrecision += + calcPrecision(statsInfo_[i].TP, statsInfo_[i].FP); + info->macroAvgRecall += calcRecall(statsInfo_[i].TP, statsInfo_[i].FN); } - *macroAvgPrecision /= numLabels; - *macroAvgRecall /= numLabels; - *macroAvgF1Score = calcF1Score(*macroAvgPrecision, *macroAvgRecall); - - *microAvgPrecision = calcPrecision(microTotalTP, microTotalFP); - *microAvgRecall = calcPrecision(microTotalTP, microTotalFN); - *microAvgF1Score = calcF1Score(*microAvgPrecision, *microAvgRecall); + info->macroAvgPrecision /= numLabels; + info->macroAvgRecall /= numLabels; + info->macroAvgF1Score = + calcF1Score(info->macroAvgPrecision, info->macroAvgRecall); + + info->microAvgPrecision = calcPrecision(microTotalTP, microTotalFP); + info->microAvgRecall = calcPrecision(microTotalTP, microTotalFN); + info->microAvgF1Score = + calcF1Score(info->microAvgPrecision, info->microAvgRecall); return true; } diff --git a/paddle/gserver/evaluators/Evaluator.h b/paddle/gserver/evaluators/Evaluator.h index c4110ec1c0b57f..b114500e2b7c1e 100644 --- a/paddle/gserver/evaluators/Evaluator.h +++ b/paddle/gserver/evaluators/Evaluator.h @@ -379,15 +379,19 @@ class PrecisionRecallEvaluator : public Evaluator { IVectorPtr cpuLabel_; MatrixPtr cpuWeight_; - bool getStatsInfo(double* precision, - double* recall, - double* f1, - double* macroAvgPrecision, - double* macroAvgRecall, - double* macroAvgF1Score, - double* microAvgPrecision, - double* microAvgRecall, - double* microAvgF1Score) const; + struct PrintStatsInfo { + double precision; + double recall; + double f1; + double macroAvgPrecision; + double macroAvgRecall; + double macroAvgF1Score; + double microAvgPrecision; + double microAvgRecall; + double microAvgF1Score; + }; + + bool getStatsInfo(PrintStatsInfo* info) const; void calcStatsInfo(const MatrixPtr& output, const IVectorPtr& label, From 51de2ded3ecf674bd5f96a9f3129d6630bfb65a1 Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Thu, 23 Feb 2017 16:59:38 +0800 Subject: [PATCH 276/370] add optimizer in v2 --- python/paddle/v2/optimizer.py | 55 +++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/python/paddle/v2/optimizer.py b/python/paddle/v2/optimizer.py index aa2942bc9faeb2..10e255dc945efb 100644 --- a/python/paddle/v2/optimizer.py +++ b/python/paddle/v2/optimizer.py @@ -3,7 +3,10 @@ import paddle.trainer_config_helpers.config_parser_utils as config_parser_utils import paddle.v2 -__all__ = ['Adam', 'Adamax'] +__all__ = [ + 'Momentum', 'Adam', 'Adamax', 'AdaGrad', 'DecayedAdaGrad', 'AdaDelta', + 'RMSProp', 'ModelAverage', 'L2Regularization' +] class Optimizer(object): @@ -38,6 +41,14 @@ def create_remote_updater(self, pass_num): pass_num) +class Momentum(Optimizer): + def __init__(self, momentum=None, sparse=False, **kwargs): + learning_method = v1_optimizers.MomentumOptimizer( + momentum=None, sparse=False) + super(Momentum, self).__init__( + learning_method=learning_method, **kwargs) + + class Adam(Optimizer): def __init__(self, beta1=0.9, beta2=0.999, epsilon=1e-8, **kwargs): learning_method = v1_optimizers.AdamOptimizer( @@ -52,7 +63,45 @@ def __init__(self, beta1=0.9, beta2=0.999, **kwargs): super(Adamax, self).__init__(learning_method=learning_method, **kwargs) +class AdaGrad(Optimizer): + def __init__(self, **kwargs): + learning_method = v1_optimizers.AdaGradOptimizer() + super(AdaGrad, self).__init__(learning_method=learning_method, **kwargs) + + +class DecayedAdaGrad(Optimizer): + def __init__(self, rho=0.95, epsilon=1e-06, **kwargs): + learning_method = v1_optimizers.DecayedAdaGradOptimizer( + rho=rho, epsilon=epsilon) + super(DecayedAdaGrad, self).__init__( + learning_method=learning_method, **kwargs) + + +class AdaDelta(Optimizer): + def __init__(self, rho=0.95, epsilon=1e-06, **kwargs): + learning_method = v1_optimizers.AdaDeltaOptimizer( + rho=rho, epsilon=epsilon) + super(AdaDelta, self).__init__( + learning_method=learning_method, **kwargs) + + +class RMSProp(Optimizer): + def __init__(self, rho=0.95, epsilon=1e-6, **kwargs): + learning_method = v1_optimizers.RMSPropOptimizer( + rho=rho, epsilon=epsilon) + super(RMSProp, self).__init__(learning_method=learning_method, **kwargs) + + +ModelAverage = v1_optimizers.ModelAverage +L2Regularization = v1_optimizers.L2Regularization + if __name__ == '__main__': swig_api.initPaddle('--use_gpu=false') - opt = paddle.v2.optimizer.Adam() - print opt.enable_types() + for opt in [ + Momentum(), Adam(), Adamax(), AdaGrad(), DecayedAdaGrad(), + AdaDelta(), RMSProp(), Adam( + model_average=ModelAverage(average_window=0.5), + regularization=L2Regularization(rate=0.5), + gradient_clipping_threshold=25) + ]: + print opt, opt.enable_types() From 950b4a312697fe8b5132437d85b919353af15365 Mon Sep 17 00:00:00 2001 From: liaogang Date: Thu, 23 Feb 2017 17:24:01 +0800 Subject: [PATCH 277/370] change return type Argument --- paddle/api/GradientMachine.cpp | 3 ++- paddle/api/Trainer.cpp | 3 ++- paddle/gserver/gradientmachines/GradientMachine.h | 2 +- paddle/gserver/gradientmachines/MultiGradientMachine.cpp | 3 +-- paddle/gserver/gradientmachines/MultiGradientMachine.h | 2 +- paddle/gserver/gradientmachines/NeuralNetwork.cpp | 2 +- paddle/gserver/gradientmachines/NeuralNetwork.h | 2 +- paddle/gserver/layers/CosSimVecMatLayer.cpp | 4 ++-- 8 files changed, 11 insertions(+), 10 deletions(-) diff --git a/paddle/api/GradientMachine.cpp b/paddle/api/GradientMachine.cpp index a64e70a6bd563a..538ca2999f8f05 100644 --- a/paddle/api/GradientMachine.cpp +++ b/paddle/api/GradientMachine.cpp @@ -148,7 +148,8 @@ Arguments* GradientMachine::getLayerOutput(const std::string& layerName) const throw(UnsupportError) { auto nn = m->machine; if (nn) { - return Arguments::createByPaddleArgument(&nn->getLayerOutput(layerName)); + auto arg = nn->getLayerOutput(layerName); + return Arguments::createByPaddleArgument(&arg); } else { throw UnsupportError(); } diff --git a/paddle/api/Trainer.cpp b/paddle/api/Trainer.cpp index 29cf2aa4501de3..84e4ca054abb01 100644 --- a/paddle/api/Trainer.cpp +++ b/paddle/api/Trainer.cpp @@ -134,7 +134,8 @@ void Trainer::finishTestPeriod() { m->finishTestPeriod(); } Arguments* Trainer::getLayerOutput(const std::string& layerName) const { auto nn = this->m->getGradientMachine(); CHECK(nn) << "trainerInternal_.getGradientMachine() is not NeuralNetwork"; - return Arguments::createByPaddleArgument(&nn->getLayerOutput(layerName)); + auto arg = nn->getLayerOutput(layerName); + return Arguments::createByPaddleArgument(&arg); } void Trainer::forwardOneBatch(size_t batchSize) { diff --git a/paddle/gserver/gradientmachines/GradientMachine.h b/paddle/gserver/gradientmachines/GradientMachine.h index ae39783c6b7ea6..bc2f2f8563526a 100644 --- a/paddle/gserver/gradientmachines/GradientMachine.h +++ b/paddle/gserver/gradientmachines/GradientMachine.h @@ -134,7 +134,7 @@ class GradientMachine { backward(callback); } - virtual const Argument& getLayerOutput(const std::string& layerName) { + virtual Argument getLayerOutput(const std::string& layerName) { return *((Argument*)nullptr); } diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp index 6b11b0155e990d..123273f916f5d3 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp @@ -282,8 +282,7 @@ void MultiGradientMachine::forwardBackward(const std::vector& inArgs, backwardImp(callback); } -const Argument& MultiGradientMachine::getLayerOutput( - const std::string& layerName) { +Argument MultiGradientMachine::getLayerOutput(const std::string& layerName) { std::vector args; args.reserve(threads_.size()); diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.h b/paddle/gserver/gradientmachines/MultiGradientMachine.h index 9083230afd69e2..838a52b5153af6 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.h +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.h @@ -189,7 +189,7 @@ class MultiGradientMachine : public GradientMachine { PassType passType, const UpdateCallback& callback); - virtual const Argument& getLayerOutput(const std::string& layerName); + virtual Argument getLayerOutput(const std::string& layerName); virtual void onPassEnd(); diff --git a/paddle/gserver/gradientmachines/NeuralNetwork.cpp b/paddle/gserver/gradientmachines/NeuralNetwork.cpp index d1afde40e1f81e..2f2aa24aaca33a 100644 --- a/paddle/gserver/gradientmachines/NeuralNetwork.cpp +++ b/paddle/gserver/gradientmachines/NeuralNetwork.cpp @@ -293,7 +293,7 @@ void NeuralNetwork::backward(const UpdateCallback& callback) { } } -const Argument& NeuralNetwork::getLayerOutput(const std::string& layerName) { +Argument NeuralNetwork::getLayerOutput(const std::string& layerName) { return getLayer(layerName)->getOutput(); } diff --git a/paddle/gserver/gradientmachines/NeuralNetwork.h b/paddle/gserver/gradientmachines/NeuralNetwork.h index b4dc38e31b6fae..e7b6c438407e7e 100644 --- a/paddle/gserver/gradientmachines/NeuralNetwork.h +++ b/paddle/gserver/gradientmachines/NeuralNetwork.h @@ -87,7 +87,7 @@ class NeuralNetwork : public GradientMachine { virtual void backward(const UpdateCallback& callback = nullptr); - virtual const Argument& getLayerOutput(const std::string& layerName); + virtual Argument getLayerOutput(const std::string& layerName); const LayerPtr& getLayer(const std::string& layerName) const { auto it = layerMap_.find(layerName); diff --git a/paddle/gserver/layers/CosSimVecMatLayer.cpp b/paddle/gserver/layers/CosSimVecMatLayer.cpp index aabafd473aa1e0..0f887d8adfa053 100644 --- a/paddle/gserver/layers/CosSimVecMatLayer.cpp +++ b/paddle/gserver/layers/CosSimVecMatLayer.cpp @@ -112,7 +112,7 @@ bool CosSimVecMatLayer::init(const LayerMap& layerMap, void CosSimVecMatLayer::forward(PassType passType) { Layer::forward(passType); - CHECK_EQ(forward_.size(), 1) << "Only one forward function needed"; + CHECK_EQ(forward_.size(), 1UL) << "Only one forward function needed"; MatrixPtr inV0 = getInputValue(0); MatrixPtr inV1 = getInputValue(1); @@ -145,7 +145,7 @@ void CosSimVecMatLayer::forward(PassType passType) { } void CosSimVecMatLayer::backward(const UpdateCallback& callback) { - CHECK_EQ(backward_.size(), 1) << "Only one forward function needed"; + CHECK_EQ(backward_.size(), 1UL) << "Only one forward function needed"; MatrixPtr inV0 = getInputValue(0); MatrixPtr inV1 = getInputValue(1); From d1ab3c80744a851164dd4dc76a847193eb4c5562 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 23 Feb 2017 19:20:33 +0800 Subject: [PATCH 278/370] MNIST dataset reader implementation --- python/paddle/v2/data_set/__init__.py | 0 python/paddle/v2/data_set/mnist.py | 62 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 python/paddle/v2/data_set/__init__.py create mode 100644 python/paddle/v2/data_set/mnist.py diff --git a/python/paddle/v2/data_set/__init__.py b/python/paddle/v2/data_set/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/python/paddle/v2/data_set/mnist.py b/python/paddle/v2/data_set/mnist.py new file mode 100644 index 00000000000000..34f61bb9f632ea --- /dev/null +++ b/python/paddle/v2/data_set/mnist.py @@ -0,0 +1,62 @@ +import sklearn.datasets.mldata +import sklearn.model_selection +import numpy + +__all__ = ['MNISTReader', 'train_reader_creator', 'test_reader_creator'] + +DATA_HOME = None + + +def __mnist_reader__(data, target): + n_samples = data.shape[0] + for i in xrange(n_samples): + yield data[i].astype(numpy.float32), int(target[i]) + + +class MNISTReader(object): + """ + mnist dataset reader. The `train_reader` and `test_reader` method returns + a iterator of each sample. Each sample is combined by 784-dim float and a + one-dim label + """ + + def __init__(self, random_state): + data = sklearn.datasets.mldata.fetch_mldata( + "MNIST original", data_home=DATA_HOME) + n_train = 60000 + self.X_train, self.X_test, self.y_train, self.y_test = sklearn.model_selection.train_test_split( + data.data / 255.0, + data.target.astype("int"), + train_size=n_train, + random_state=random_state) + + def train_reader(self): + return __mnist_reader__(self.X_train, self.y_train) + + def test_reader(self): + return __mnist_reader__(self.X_test, self.y_test) + + +__default_instance__ = MNISTReader(0) + + +def train_reader_creator(): + """ + Default train set reader creator. + """ + return __default_instance__.train_reader + + +def test_reader_creator(): + """ + Default test set reader creator. + """ + return __default_instance__.test_reader + + +def unittest(): + assert len(list(train_reader_creator()())) == 60000 + + +if __name__ == '__main__': + unittest() From 84b423a89a2a6ece21910c83277f6282b80f6be7 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Thu, 23 Feb 2017 17:35:06 +0800 Subject: [PATCH 279/370] refine data feeder and add unit test --- python/CMakeLists.txt | 1 + python/paddle/v2/data_feeder.py | 110 ++++++++++----- python/paddle/v2/tests/CMakeLists.txt | 2 + python/paddle/v2/tests/run_tests.sh | 36 +++++ python/paddle/v2/tests/test_data_feeder.py | 150 +++++++++++++++++++++ 5 files changed, 264 insertions(+), 35 deletions(-) create mode 100644 python/paddle/v2/tests/CMakeLists.txt create mode 100755 python/paddle/v2/tests/run_tests.sh create mode 100644 python/paddle/v2/tests/test_data_feeder.py diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 357637e20346f8..71af50a9a4ed83 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -25,6 +25,7 @@ add_custom_target(paddle_python ALL DEPENDS add_subdirectory(paddle/trainer_config_helpers/tests) add_subdirectory(paddle/reader/tests) +add_subdirectory(paddle/v2/tests) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dist/ DESTINATION opt/paddle/share/wheels diff --git a/python/paddle/v2/data_feeder.py b/python/paddle/v2/data_feeder.py index 83a4efef9e7a7b..b594643dda6b38 100644 --- a/python/paddle/v2/data_feeder.py +++ b/python/paddle/v2/data_feeder.py @@ -12,49 +12,89 @@ # See the License for the specific language governing permissions and # limitations under the License. +from py_paddle import swig_paddle from py_paddle import DataProviderConverter +import data_type __all__ = ['DataFeeder'] -""" -DataFeeder converts the data returned by paddle.reader into a data structure -of Arguments which is defined in the API. The paddle.reader usually returns -a list of mini-batch data. Each item in the list is a tuple or list, which is -one sample with multiple features. DataFeeder converts this mini-batch data -into Arguments in order to feed it to C++ interface. - -The example usage: - - data_types = [paddle.data_type.dense_vector(784), - paddle.data_type.integer_value(10)] - feeder = DataFeeder(input_types=data_types) - minibatch_data = [ - ( [1.0,2.0,3.0,4.0], 5, [6,7,8] ), # first sample - ( [1.0,2.0,3.0,4.0], 5, [6,7,8] ) # second sample - ] - - # or - # minibatch_data = [ - # [ [1.0,2.0,3.0,4.0], 5, [6,7,8] ], # first sample - # [ [1.0,2.0,3.0,4.0], 5, [6,7,8] ] # second sample - # ] - arg = feeder(minibatch_data) - - -Args: - input_types: A list of input data types. It's length is equal to the length - of data returned by paddle.reader. Each item specifies the type - of each feature. - mintbatch_data: A list of mini-batch data. Each item is a list or tuple, + + +class DataFeeder(DataProviderConverter): + """ + DataFeeder converts the data returned by paddle.reader into a data structure + of Arguments which is defined in the API. The paddle.reader usually returns + a list of mini-batch data. Each item in the list is a list or a tuple, + which is one sample with one or multiple features. DataFeeder converts this + mini-batch data into Arguments in order to feed it to C++ interface. + + The example usage: + + data_types = [('image', paddle.data_type.dense_vector(784)), + ('label', paddle.data_type.integer_value(10))] + reader_dict = {'image':0, 'label':1} + feeder = DataFeeder(data_types=data_types, reader_dict=reader_dict) + minibatch_data = [ + ( [1.0,2.0,3.0,4.0], 5, [6,7,8] ), # first sample + ( [1.0,2.0,3.0,4.0], 5, [6,7,8] ) # second sample + ] + arg = feeder(minibatch_data) + """ + + def __init__(self, data_types, reader_dict): + """ + :param data_types: A list to specify data name and type. Each item is + a tuple of (data_name, data_type). For example: + [('image', paddle.data_type.dense_vector(784)), + ('label', paddle.data_type.integer_value(10))] + + :type data_types: A list of tuple + :param reader_dict: A dictionary to specify the position of each data + in the input data. + :type reader_dict: dict() + """ + self.input_names = [] + self.input_types = [] + self.reader_dict = reader_dict + for each in data_types: + self.input_names.append(each[0]) + self.input_types.append(each[1]) + assert isinstance(each[1], data_type.InputType) + DataProviderConverter.__init__(self, self.input_types) + + def convert(self, dat, argument=None): + """ + :param dat: A list of mini-batch data. Each item is a list or tuple, for example: [ (feature_0, feature_1, feature_2, ...), # first sample (feature_0, feature_1, feature_2, ...), # second sample ... ] + :type dat: List + :param argument: An Arguments object contains this mini-batch data with + one or multiple features. The Arguments definition is + in the API. + :type argument: swig_paddle.Arguments + """ + + if argument is None: + argument = swig_paddle.Arguments.createArguments(0) + assert isinstance(argument, swig_paddle.Arguments) + argument.resize(len(self.input_types)) + + scanners = [ + DataProviderConverter.create_scanner(i, each_type) + for i, each_type in enumerate(self.input_types) + ] + + for each_sample in dat: + for name, scanner in zip(self.input_names, scanners): + scanner.scan(each_sample[self.reader_dict[name]]) + + for scanner in scanners: + scanner.finish_scan(argument) -Returns: - An Arguments object contains this mini-batch data with multiple features. - The Arguments definition is in the API. -""" + return argument -DataFeeder = DataProviderConverter + def __call__(self, dat, argument=None): + return self.convert(dat, argument) diff --git a/python/paddle/v2/tests/CMakeLists.txt b/python/paddle/v2/tests/CMakeLists.txt new file mode 100644 index 00000000000000..5842a716caa757 --- /dev/null +++ b/python/paddle/v2/tests/CMakeLists.txt @@ -0,0 +1,2 @@ +add_test(NAME test_v2_api + COMMAND bash ${PROJ_ROOT}/python/paddle/v2/tests/run_tests.sh ${PYTHON_EXECUTABLE}) diff --git a/python/paddle/v2/tests/run_tests.sh b/python/paddle/v2/tests/run_tests.sh new file mode 100755 index 00000000000000..b96f54fe9cc78a --- /dev/null +++ b/python/paddle/v2/tests/run_tests.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + + +pushd `dirname $0` > /dev/null +SCRIPTPATH=$PWD +popd > /dev/null + +cd $SCRIPTPATH + +$1 -m pip install ../../../../paddle/dist/*.whl + +test_list="test_data_feeder.py" + +export PYTHONPATH=$PWD/../../../../python/ + +for fn in $test_list +do + echo "test $fn" + $1 $fn + if [ $? -ne 0 ]; then + exit 1 + fi +done diff --git a/python/paddle/v2/tests/test_data_feeder.py b/python/paddle/v2/tests/test_data_feeder.py new file mode 100644 index 00000000000000..dcf433d7d8fdce --- /dev/null +++ b/python/paddle/v2/tests/test_data_feeder.py @@ -0,0 +1,150 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + +import unittest + +import py_paddle.swig_paddle as api +import numpy as np + +from paddle.v2 import data_type +from paddle.v2.data_feeder import DataFeeder + + +class DataFeederTest(unittest.TestCase): + def dense_reader(self, size): + data = np.random.random(size) + return data + + def sparse_binary_reader(self, high, size_limit, non_empty=False): + num = np.random.randint(size_limit) # num could be 0 + while non_empty and num == 0: + num = np.random.randint(size_limit) + return np.random.randint(high, size=num).tolist() + + def test_dense_vector(self): + def compare(input): + feeder = DataFeeder([('image', data_type.dense_vector(784))], + {'image': 0}) + arg = feeder([input]) + output = arg.getSlotValue(0).copyToNumpyMat() + input = np.array(input, dtype='float32') + self.assertAlmostEqual(input.all(), output.all()) + + # test numpy array + batch_size = 32 + dim = 784 + data = [] + for i in xrange(batch_size): + data.append(self.dense_reader(784)) + compare(data) + + # test list + data = [] + for i in xrange(batch_size): + data.append(self.dense_reader(784).tolist()) + compare(data) + + def test_sparse_binary(self): + dim = 10000 + batch_size = 32 + data = [] + for i in xrange(batch_size): + data.append([self.sparse_binary_reader(dim, 50)]) + feeder = DataFeeder([('input', data_type.sparse_binary_vector(dim))], + {'input': 0}) + arg = feeder(data) + output = arg.getSlotValue(0) + assert isinstance(output, api.Matrix) + for i in xrange(batch_size): + self.assertEqual(output.getSparseRowCols(i), data[i][0]) + + def test_sparse(self): + dim = 10000 + batch_size = 32 + v = [] + w = [] + data = [] + for dat in xrange(batch_size): + a = self.sparse_binary_reader(dim, 40, non_empty=True) + b = self.dense_reader(len(a)).tolist() + v.append(a) + w.append(b[0]) + data.append([zip(a, b)]) + + feeder = DataFeeder([('input', data_type.sparse_vector(dim))], + {'input': 0}) + arg = feeder(data) + output = arg.getSlotValue(0) + assert isinstance(output, api.Matrix) + for i in xrange(batch_size): + self.assertEqual(output.getSparseRowCols(i), v[i]) + + def test_integer(self): + dim = 100 + batch_size = 32 + index = [] + for i in xrange(batch_size): + index.append([np.random.randint(dim)]) + feeder = DataFeeder([('input', data_type.integer_value(dim))], + {'input': 0}) + arg = feeder(index) + output = arg.getSlotIds(0).copyToNumpyArray() + index = np.array(index, dtype='int') + self.assertEqual(output.all(), index.flatten().all()) + + def test_multiple_slots(self): + batch_size = 2 + data = [] + for i in xrange(batch_size): + each_sample = [] + each_sample.append(np.random.randint(10)) # size of feature 2: 10 + each_sample.append( + self.sparse_binary_reader( + 20000, 40, non_empty=True)) # size of feature 1: 20000 + each_sample.append(self.dense_reader(100)) # size of feature 0: 100 + data.append(each_sample) + + # test multiple features + data_types = [('fea0', data_type.dense_vector(100)), + ('fea1', data_type.sparse_binary_vector(20000)), + ('fea2', data_type.integer_value(10))] + feeder = DataFeeder(data_types, {'fea0': 2, 'fea1': 1, 'fea2': 0}) + arg = feeder(data) + output_dense = arg.getSlotValue(0).copyToNumpyMat() + output_sparse = arg.getSlotValue(1) + output_index = arg.getSlotIds(2).copyToNumpyArray() + for i in xrange(batch_size): + self.assertEqual(output_dense[i].all(), data[i][2].all()) + self.assertEqual(output_sparse.getSparseRowCols(i), data[i][1]) + self.assertEqual(output_index[i], data[i][0]) + + # reader returns 3 featreus, but only use 2 features + data_types = [('fea0', data_type.dense_vector(100)), + ('fea2', data_type.integer_value(10))] + feeder = DataFeeder(data_types, {'fea0': 2, 'fea2': 0}) + arg = feeder(data) + output_dense = arg.getSlotValue(0).copyToNumpyMat() + output_index = arg.getSlotIds(1).copyToNumpyArray() + for i in xrange(batch_size): + self.assertEqual(output_dense[i].all(), data[i][2].all()) + self.assertEqual(output_index[i], data[i][0]) + + +if __name__ == '__main__': + api.initPaddle("--use_gpu=0") + unittest.main() + +if __name__ == '__main__': + api.initPaddle("--use_gpu=0") + unittest.main() From b9dd33f815ed94237ddda930c99db838b76460e1 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Thu, 23 Feb 2017 23:30:17 +0800 Subject: [PATCH 280/370] hide Topology --- demo/mnist/api_train_v2.py | 6 ++---- python/paddle/v2/parameters.py | 8 +++----- python/paddle/v2/topology.py | 14 +++++++++----- python/paddle/v2/trainer.py | 4 +++- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index f6edd1f34fe8d1..cc45229fbd688d 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -26,9 +26,7 @@ def main(): act=paddle.activation.Softmax()) cost = paddle.layer.classification_cost(input=inference, label=label) - topology = paddle.topology.Topology(cost) - - parameters = paddle.parameters.create(topology) + 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) @@ -49,7 +47,7 @@ def event_handler(event): trainer.train( train_data_reader=train_reader, - topology=topology, + topology=[cost], parameters=parameters, event_handler=event_handler, batch_size=32) # batch size should be refactor in Data reader diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index b569afe3a1fc20..b8d4b287032cd3 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -7,15 +7,13 @@ __all__ = ['Parameters', 'create'] -def create(topology): +def create(layers): """ Create parameter pool by topology. - :param topology: + :param layers: :return: """ - if not isinstance(topology, v2_topology.Topology): - raise ValueError( - 'create must pass a topology which type is topology.Topology') + topology = v2_topology.Topology(layers) pool = Parameters() for param in topology.proto().parameters: pool.__append_config__(param) diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index 6508b3ce881c49..bfd7ef171a5fb6 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -12,10 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -from paddle.proto.ModelConfig_pb2 import ModelConfig +import collections + import paddle.trainer_config_helpers as conf_helps -import layer as v2_layer +from paddle.proto.ModelConfig_pb2 import ModelConfig + import data_type +import layer as v2_layer __all__ = ['Topology'] @@ -26,11 +29,12 @@ class Topology(object): and network configs. """ - def __init__(self, *layers): + def __init__(self, layers): + if not isinstance(layers, collections.Sequence): + raise ValueError("input of Topology should be a list of Layer") for layer in layers: if not isinstance(layer, v2_layer.LayerV2): - raise ValueError('create must pass a topologies ' - 'which type is paddle.layer.Layer') + raise ValueError('layer should have type paddle.layer.Layer') self.layers = layers self.__model_config__ = v2_layer.parse_network(*layers) assert isinstance(self.__model_config__, ModelConfig) diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index c8da6e70cf528d..969aa6e0e05935 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -73,7 +73,7 @@ def train(self, Training method. Will train num_passes of input data. :param train_data_reader: - :param topology: Network Topology, use one or more Layers to represent it. + :param topology: cost layers, use one or more Layers to represent it. :param parameters: The parameter pools. :param num_passes: The total train passes. :param test_data_reader: @@ -87,6 +87,8 @@ def train(self, if event_handler is None: event_handler = default_event_handler + topology = v2_topology.Topology(topology) + __check_train_args__(**locals()) gm = api.GradientMachine.createFromConfigProto( From 775f019fa1d9fcd120ae6fc66f5c0caa9333ebca Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Thu, 23 Feb 2017 23:44:57 +0800 Subject: [PATCH 281/370] remove unused get_layer_proto in Topology --- python/paddle/v2/topology.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index bfd7ef171a5fb6..3e07c4106ed142 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -83,19 +83,6 @@ def find_data_layer(layer): return data_layers - def get_layer_proto(self, name): - """ - get layer by layer name - :param name: - :return: - """ - layers = filter(lambda layer: layer.name == name, - self.__model_config__.layers) - if len(layers) is 1: - return layers[0] - else: - return None - def data_type(self): """ get data_type from proto, such as: From b9d4f71c4a1c2a9f6c3593a1990c5becf8377268 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Thu, 23 Feb 2017 14:10:23 -0800 Subject: [PATCH 282/370] fix according to comments --- python/paddle/reader/creator.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/paddle/reader/creator.py b/python/paddle/reader/creator.py index 5c840f94b52f16..5a91bb0b8ef6d1 100644 --- a/python/paddle/reader/creator.py +++ b/python/paddle/reader/creator.py @@ -17,8 +17,9 @@ def np_array(x): """ - Creates a data reader from numpy array. - The highest dimension will be treated as batch dimension to iterate on. + Creates a reader that yields elements of x, if it is a + numpy vector. Or rows of x, if it is a numpy matrix. + Or any sub-hyperplane indexed by the highest dimension. :param x: the numpy array to create reader from. :returns: data reader created from x. From 909bd2690adb96cc68852856b9a6d8643459ca73 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 24 Feb 2017 10:05:35 +0800 Subject: [PATCH 283/370] add topology test --- demo/mnist/api_train_v2.py | 2 +- python/paddle/v2/data_type.py | 4 +- python/paddle/v2/tests/CMakeLists.txt | 4 ++ python/paddle/v2/tests/topology_test.py | 79 +++++++++++++++++++++++++ python/paddle/v2/topology.py | 14 +++-- 5 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 python/paddle/v2/tests/CMakeLists.txt create mode 100644 python/paddle/v2/tests/topology_test.py diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index cc45229fbd688d..99cc344a5ed9c6 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -26,7 +26,7 @@ def main(): act=paddle.activation.Softmax()) cost = paddle.layer.classification_cost(input=inference, label=label) - parameters = paddle.parameters.create([cost]) + 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) diff --git a/python/paddle/v2/data_type.py b/python/paddle/v2/data_type.py index 5b01ba4cd4866c..cd9ce6e51352ae 100644 --- a/python/paddle/v2/data_type.py +++ b/python/paddle/v2/data_type.py @@ -14,9 +14,9 @@ from paddle.trainer.PyDataProvider2 import \ InputType, dense_vector, sparse_binary_vector,\ - sparse_vector, integer_value + sparse_vector, integer_value, DataType __all__ = [ 'InputType', 'dense_vector', 'sparse_binary_vector', 'sparse_vector', - 'integer_value' + 'integer_value', 'DataType' ] diff --git a/python/paddle/v2/tests/CMakeLists.txt b/python/paddle/v2/tests/CMakeLists.txt new file mode 100644 index 00000000000000..3a257af2fc5693 --- /dev/null +++ b/python/paddle/v2/tests/CMakeLists.txt @@ -0,0 +1,4 @@ +add_test(NAME topology_test + COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ + ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/topology_test.py + WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) diff --git a/python/paddle/v2/tests/topology_test.py b/python/paddle/v2/tests/topology_test.py new file mode 100644 index 00000000000000..7360ed8f7b294c --- /dev/null +++ b/python/paddle/v2/tests/topology_test.py @@ -0,0 +1,79 @@ +# Copyright PaddlePaddle contributors. All Rights Reserved +# +# 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. +import unittest +import paddle.v2.layer as layer +import paddle.v2.topology as topology +import paddle.v2.data_type as data_type +import paddle.trainer_config_helpers as conf_helps + + +class TestTopology(unittest.TestCase): + def test_parse(self): + pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) + label = layer.data(name='label', type=data_type.integer_value(10)) + hidden = layer.fc(input=pixel, + size=100, + act=conf_helps.SigmoidActivation()) + inference = layer.fc(input=hidden, + size=10, + act=conf_helps.SoftmaxActivation()) + maxid = layer.max_id(input=inference) + cost1 = layer.classification_cost(input=inference, label=label) + cost2 = layer.cross_entropy_cost(input=inference, label=label) + + print topology.Topology(cost2).proto() + print topology.Topology([cost1]).proto() + print topology.Topology([cost1, cost2]).proto() + print topology.Topology(cost2).proto() + print topology.Topology([inference, maxid]).proto() + + def test_data_type(self): + pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) + label = layer.data(name='label', type=data_type.integer_value(10)) + hidden = layer.fc(input=pixel, + size=100, + act=conf_helps.SigmoidActivation()) + inference = layer.fc(input=hidden, + size=10, + act=conf_helps.SoftmaxActivation()) + cost = layer.classification_cost(input=inference, label=label) + topo = topology.Topology(cost) + type = topo.data_type() + self.assertEqual(len(type), 2) + self.assertEqual(type[0][0], "pixel") + self.assertEqual(type[0][1].type, data_type.DataType.Dense) + self.assertEqual(type[0][1].dim, 784) + self.assertEqual(type[1][0], "label") + self.assertEqual(type[1][1].type, data_type.DataType.Index) + self.assertEqual(type[1][1].dim, 10) + + def test_get_layer(self): + pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) + label = layer.data(name='label', type=data_type.integer_value(10)) + hidden = layer.fc(input=pixel, + size=100, + act=conf_helps.SigmoidActivation()) + inference = layer.fc(input=hidden, + size=10, + act=conf_helps.SoftmaxActivation()) + cost = layer.classification_cost(input=inference, label=label) + topo = topology.Topology(cost) + pixel_layer = topo.get_layer("pixel") + label_layer = topo.get_layer("label") + self.assertEqual(pixel_layer, pixel) + self.assertEqual(label_layer, label) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index 3e07c4106ed142..28cc8892e153b1 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -31,7 +31,8 @@ class Topology(object): def __init__(self, layers): if not isinstance(layers, collections.Sequence): - raise ValueError("input of Topology should be a list of Layer") + __check_layer_type__(layers) + layers = [layers] for layer in layers: if not isinstance(layer, v2_layer.LayerV2): raise ValueError('layer should have type paddle.layer.Layer') @@ -97,6 +98,11 @@ def data_type(self): return data_types_lists +def __check_layer_type__(layer): + if not isinstance(layer, v2_layer.LayerV2): + raise ValueError('layer should have type paddle.layer.Layer') + + if __name__ == '__main__': pixel = v2_layer.data(name='pixel', type=data_type.dense_vector(784)) label = v2_layer.data(name='label', type=data_type.integer_value(10)) @@ -110,8 +116,8 @@ def data_type(self): cost1 = v2_layer.classification_cost(input=inference, label=label) cost2 = v2_layer.cross_entropy_cost(input=inference, label=label) - print Topology(cost1).proto() print Topology(cost2).proto() - print Topology(cost1, cost2).proto() + print Topology([cost1]).proto() + print Topology([cost1, cost2]).proto() print Topology(cost2).proto() - print Topology(inference, maxid).proto() + print Topology([inference, maxid]).proto() From 12cac800acf29c39c717e03f934abe35ad5ab0e7 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 24 Feb 2017 10:13:53 +0800 Subject: [PATCH 284/370] clean topology.py --- python/paddle/v2/tests/topology_test.py | 37 ++++++++++++------------- python/paddle/v2/topology.py | 24 +--------------- 2 files changed, 19 insertions(+), 42 deletions(-) diff --git a/python/paddle/v2/tests/topology_test.py b/python/paddle/v2/tests/topology_test.py index 7360ed8f7b294c..be60a577beac5b 100644 --- a/python/paddle/v2/tests/topology_test.py +++ b/python/paddle/v2/tests/topology_test.py @@ -19,25 +19,6 @@ class TestTopology(unittest.TestCase): - def test_parse(self): - pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) - label = layer.data(name='label', type=data_type.integer_value(10)) - hidden = layer.fc(input=pixel, - size=100, - act=conf_helps.SigmoidActivation()) - inference = layer.fc(input=hidden, - size=10, - act=conf_helps.SoftmaxActivation()) - maxid = layer.max_id(input=inference) - cost1 = layer.classification_cost(input=inference, label=label) - cost2 = layer.cross_entropy_cost(input=inference, label=label) - - print topology.Topology(cost2).proto() - print topology.Topology([cost1]).proto() - print topology.Topology([cost1, cost2]).proto() - print topology.Topology(cost2).proto() - print topology.Topology([inference, maxid]).proto() - def test_data_type(self): pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) label = layer.data(name='label', type=data_type.integer_value(10)) @@ -74,6 +55,24 @@ def test_get_layer(self): self.assertEqual(pixel_layer, pixel) self.assertEqual(label_layer, label) + def test_parse(self): + pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) + label = layer.data(name='label', type=data_type.integer_value(10)) + hidden = layer.fc(input=pixel, + size=100, + act=conf_helps.SigmoidActivation()) + inference = layer.fc(input=hidden, + size=10, + act=conf_helps.SoftmaxActivation()) + maxid = layer.max_id(input=inference) + cost1 = layer.classification_cost(input=inference, label=label) + cost2 = layer.cross_entropy_cost(input=inference, label=label) + + topology.Topology(cost2).proto() + topology.Topology([cost1]).proto() + topology.Topology([cost1, cost2]).proto() + topology.Topology([inference, maxid]).proto() + if __name__ == '__main__': unittest.main() diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index 28cc8892e153b1..20fa891d656548 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -14,10 +14,8 @@ import collections -import paddle.trainer_config_helpers as conf_helps from paddle.proto.ModelConfig_pb2 import ModelConfig -import data_type import layer as v2_layer __all__ = ['Topology'] @@ -62,7 +60,7 @@ def find_layer_by_name(layer, layer_name): return result_layer[0] - def get_data_layer(self): + def data_layer(self): """ get all data layer :return: @@ -101,23 +99,3 @@ def data_type(self): def __check_layer_type__(layer): if not isinstance(layer, v2_layer.LayerV2): raise ValueError('layer should have type paddle.layer.Layer') - - -if __name__ == '__main__': - pixel = v2_layer.data(name='pixel', type=data_type.dense_vector(784)) - label = v2_layer.data(name='label', type=data_type.integer_value(10)) - hidden = v2_layer.fc(input=pixel, - size=100, - act=conf_helps.SigmoidActivation()) - inference = v2_layer.fc(input=hidden, - size=10, - act=conf_helps.SoftmaxActivation()) - maxid = v2_layer.max_id(input=inference) - cost1 = v2_layer.classification_cost(input=inference, label=label) - cost2 = v2_layer.cross_entropy_cost(input=inference, label=label) - - print Topology(cost2).proto() - print Topology([cost1]).proto() - print Topology([cost1, cost2]).proto() - print Topology(cost2).proto() - print Topology([inference, maxid]).proto() From f3c7fbeec4e256585dcf36e08fc2c06da243a045 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Thu, 23 Feb 2017 22:05:59 +0800 Subject: [PATCH 285/370] make minst to run --- demo/mnist/api_train_v2.py | 9 +++++---- python/paddle/v2/__init__.py | 1 + python/paddle/v2/tests/test_data_feeder.py | 22 ++++++++++++++++------ python/paddle/v2/trainer.py | 11 +++-------- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 6fc01ce58be57c..650bf392bbc734 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -50,11 +50,12 @@ def event_handler(event): 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 + data_types=[ # data_types will be removed, It should be in # network topology - 'pixel': images.type, - 'label': label.type - }) + ('pixel', images.type), + ('label', label.type)], + reader_dict={'pixel':0, 'label':1} + ) if __name__ == '__main__': diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index be752731ba232a..bf06b5a7e360e9 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -18,6 +18,7 @@ import trainer import event import data_type +import data_feeder import py_paddle.swig_paddle as api __all__ = [ diff --git a/python/paddle/v2/tests/test_data_feeder.py b/python/paddle/v2/tests/test_data_feeder.py index dcf433d7d8fdce..95a59a5d97fb67 100644 --- a/python/paddle/v2/tests/test_data_feeder.py +++ b/python/paddle/v2/tests/test_data_feeder.py @@ -36,7 +36,7 @@ def test_dense_vector(self): def compare(input): feeder = DataFeeder([('image', data_type.dense_vector(784))], {'image': 0}) - arg = feeder([input]) + arg = feeder(input) output = arg.getSlotValue(0).copyToNumpyMat() input = np.array(input, dtype='float32') self.assertAlmostEqual(input.all(), output.all()) @@ -46,13 +46,17 @@ def compare(input): dim = 784 data = [] for i in xrange(batch_size): - data.append(self.dense_reader(784)) + each_sample = [] + each_sample.append(self.dense_reader(dim)) + data.append(each_sample) compare(data) # test list data = [] for i in xrange(batch_size): - data.append(self.dense_reader(784).tolist()) + each_sample = [] + each_sample.append(self.dense_reader(dim).tolist()) + data.append(each_sample) compare(data) def test_sparse_binary(self): @@ -60,7 +64,9 @@ def test_sparse_binary(self): batch_size = 32 data = [] for i in xrange(batch_size): - data.append([self.sparse_binary_reader(dim, 50)]) + each_sample = [] + each_sample.append(self.sparse_binary_reader(dim, 50)) + data.append(each_sample) feeder = DataFeeder([('input', data_type.sparse_binary_vector(dim))], {'input': 0}) arg = feeder(data) @@ -76,11 +82,13 @@ def test_sparse(self): w = [] data = [] for dat in xrange(batch_size): + each_sample = [] a = self.sparse_binary_reader(dim, 40, non_empty=True) b = self.dense_reader(len(a)).tolist() v.append(a) w.append(b[0]) - data.append([zip(a, b)]) + each_sample.append(zip(a, b)) + data.append(each_sample) feeder = DataFeeder([('input', data_type.sparse_vector(dim))], {'input': 0}) @@ -95,7 +103,9 @@ def test_integer(self): batch_size = 32 index = [] for i in xrange(batch_size): - index.append([np.random.randint(dim)]) + each_sample = [] + each_sample.append(np.random.randint(dim)) + index.append(each_sample) feeder = DataFeeder([('input', data_type.integer_value(dim))], {'input': 0}) arg = feeder(index) diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 5709c7e886c323..023ab5e42d25b9 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -69,7 +69,8 @@ def train(self, test_data_reader=None, event_handler=None, batch_size=32, - data_types=None): + data_types=None, + reader_dict=None): """ Training method. Will train num_passes of input data. @@ -103,13 +104,7 @@ def train(self, gm.start() out_args = api.Arguments.createArguments(0) - data_types_lists = [] - for each in topology.input_layer_names: - if each not in data_types: - raise ValueError() - data_types_lists.append(data_types[each]) - - feeder = DataFeeder(input_types=data_types_lists) + feeder = DataFeeder(data_types, reader_dict) for pass_id in xrange(num_passes): updater.startPass() From 8d3ac7a209eac568ede3f4aa4df3957c87d139cd Mon Sep 17 00:00:00 2001 From: liaogang Date: Fri, 24 Feb 2017 11:37:15 +0800 Subject: [PATCH 286/370] Conditional compile woboq --- paddle/scripts/docker/Dockerfile | 12 ++++--- paddle/scripts/docker/Dockerfile.gpu | 12 ++++--- paddle/scripts/docker/build.sh | 50 +++++++++++++++------------- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile index d4845a72b61833..3b11018901d0ee 100644 --- a/paddle/scripts/docker/Dockerfile +++ b/paddle/scripts/docker/Dockerfile @@ -10,28 +10,30 @@ RUN apt-get update && \ apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ apt-get install -y python-numpy python-matplotlib gcc g++ gfortran && \ - apt-get install -y automake clang-3.8 llvm-3.8 libclang-3.8-dev && \ + apt-get install -y automake && \ apt-get clean -y RUN pip install --upgrade pip && \ - pip install -U protobuf && \ + pip install -U "protobuf==3.1.0" && \ pip install -U wheel pillow BeautifulSoup && \ pip install -U docopt PyYAML sphinx && \ pip install -U sphinx_rtd_theme recommonmark jupyter RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \ - cd cmake-3.4.1 && ./bootstrap && make -j4 && make install && \ + cd cmake-3.4.1 && ./bootstrap && make -j `nproc` && make install && \ cd .. && rm -rf cmake-3.4.1 +ARG BUILD_WOBOQ ARG BUILD_AND_INSTALL ARG WITH_AVX ARG WITH_DOC ARG WITH_STYLE_CHECK -ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-OFF} +ENV BUILD_WOBOQ=${BUILD_WOBOQ:-OFF} +ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-ON} ENV WITH_GPU=OFF ENV WITH_AVX=${WITH_AVX:-ON} -ENV WITH_DOC=${WITH_DOC:-ON} +ENV WITH_DOC=${WITH_DOC:-OFF} ENV WITH_STYLE_CHECK=${WITH_STYLE_CHECK:-OFF} RUN mkdir /paddle diff --git a/paddle/scripts/docker/Dockerfile.gpu b/paddle/scripts/docker/Dockerfile.gpu index da20b2635e10e7..ea277b61e99af7 100644 --- a/paddle/scripts/docker/Dockerfile.gpu +++ b/paddle/scripts/docker/Dockerfile.gpu @@ -10,28 +10,30 @@ RUN apt-get update && \ apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ apt-get install -y python-numpy python-matplotlib gcc g++ gfortran && \ - apt-get install -y automake clang-3.8 llvm-3.8 libclang-3.8-dev && \ + apt-get install -y automake && \ apt-get clean -y RUN pip install --upgrade pip && \ - pip install -U protobuf && \ + pip install -U "protobuf==3.1.0" && \ pip install -U wheel pillow BeautifulSoup && \ pip install -U docopt PyYAML sphinx && \ pip install -U sphinx_rtd_theme recommonmark jupyter RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \ - cd cmake-3.4.1 && ./bootstrap && make -j4 && make install && \ + cd cmake-3.4.1 && ./bootstrap && make -j `nproc` && make install && \ cd .. && rm -rf cmake-3.4.1 +ARG BUILD_WOBOQ ARG BUILD_AND_INSTALL ARG WITH_AVX ARG WITH_DOC ARG WITH_STYLE_CHECK -ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-OFF} +ENV BUILD_WOBOQ=${BUILD_WOBOQ:-OFF} +ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-ON} ENV WITH_GPU=ON ENV WITH_AVX=${WITH_AVX:-ON} -ENV WITH_DOC=${WITH_DOC:-ON} +ENV WITH_DOC=${WITH_DOC:-OFF} ENV WITH_STYLE_CHECK=${WITH_STYLE_CHECK:-OFF} RUN mkdir /paddle diff --git a/paddle/scripts/docker/build.sh b/paddle/scripts/docker/build.sh index 6197b41d6b5f19..a0391dd6b9fabf 100755 --- a/paddle/scripts/docker/build.sh +++ b/paddle/scripts/docker/build.sh @@ -19,7 +19,7 @@ if [[ ${BUILD_AND_INSTALL:-ON} == 'ON' ]]; then mkdir -p /paddle/build # -p means no error if exists cd /paddle/build cmake .. \ - -DWITH_DOC=ON \ + -DWITH_DOC=OFF \ -DWITH_GPU=${WITH_GPU:-OFF} \ -DWITH_AVX=${WITH_AVX:-OFF} \ -DWITH_SWIG_PY=ON \ @@ -29,28 +29,32 @@ if [[ ${BUILD_AND_INSTALL:-ON} == 'ON' ]]; then make -j `nproc` make install - # Install woboq_codebrowser. - git clone https://github.com/woboq/woboq_codebrowser /woboq - cd /woboq - cmake -DLLVM_CONFIG_EXECUTABLE=/usr/bin/llvm-config-3.8 \ - -DCMAKE_BUILD_TYPE=Release \ - . - make - - export WOBOQ_OUT=/usr/share/nginx/html/paddle - export BUILD_DIR=/paddle/build - mkdir -p $WOBOQ_OUT - cp -rv /woboq/data $WOBOQ_OUT/../data - /woboq/generator/codebrowser_generator \ - -b /paddle/build \ - -a \ - -o $WOBOQ_OUT \ - -p paddle:/paddle - /woboq/indexgenerator/codebrowser_indexgenerator $WOBOQ_OUT - cd /woboq - make clean - - pip install /usr/local/opt/paddle/share/wheels/*.whl + if [[ ${BUILD_WOBOQ:-OFF} == 'ON' ]]; then + apt-get install -y clang-3.8 llvm-3.8 libclang-3.8-dev + # Install woboq_codebrowser. + git clone https://github.com/woboq/woboq_codebrowser /woboq + cd /woboq + cmake -DLLVM_CONFIG_EXECUTABLE=/usr/bin/llvm-config-3.8 \ + -DCMAKE_BUILD_TYPE=Release \ + . + make + + export WOBOQ_OUT=/usr/share/nginx/html/paddle + export BUILD_DIR=/paddle/build + mkdir -p $WOBOQ_OUT + cp -rv /woboq/data $WOBOQ_OUT/../data + /woboq/generator/codebrowser_generator \ + -b /paddle/build \ + -a \ + -o $WOBOQ_OUT \ + -p paddle:/paddle + /woboq/indexgenerator/codebrowser_indexgenerator $WOBOQ_OUT + cd /woboq + make clean + fi + + pip install /usr/local/opt/paddle/share/wheels/py_paddle*linux*.whl + pip install /usr/local/opt/paddle/share/wheels/paddle*.whl paddle version fi From 7be8e69990bf8078dd1396c03c46117c49c39215 Mon Sep 17 00:00:00 2001 From: liaogang Date: Fri, 24 Feb 2017 11:42:00 +0800 Subject: [PATCH 287/370] Update WITH_DOC in docker --- paddle/scripts/docker/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddle/scripts/docker/build.sh b/paddle/scripts/docker/build.sh index a0391dd6b9fabf..daea09d3faf08c 100755 --- a/paddle/scripts/docker/build.sh +++ b/paddle/scripts/docker/build.sh @@ -19,7 +19,7 @@ if [[ ${BUILD_AND_INSTALL:-ON} == 'ON' ]]; then mkdir -p /paddle/build # -p means no error if exists cd /paddle/build cmake .. \ - -DWITH_DOC=OFF \ + -DWITH_DOC=${WITH_GPU:-OFF} \ -DWITH_GPU=${WITH_GPU:-OFF} \ -DWITH_AVX=${WITH_AVX:-OFF} \ -DWITH_SWIG_PY=ON \ From 4d3a1ab690c0ae49f785f36f1a6793c8b3353d64 Mon Sep 17 00:00:00 2001 From: liaogang Date: Fri, 24 Feb 2017 12:20:00 +0800 Subject: [PATCH 288/370] Fix env error --- paddle/scripts/docker/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddle/scripts/docker/build.sh b/paddle/scripts/docker/build.sh index daea09d3faf08c..7fbf2821afa418 100755 --- a/paddle/scripts/docker/build.sh +++ b/paddle/scripts/docker/build.sh @@ -19,7 +19,7 @@ if [[ ${BUILD_AND_INSTALL:-ON} == 'ON' ]]; then mkdir -p /paddle/build # -p means no error if exists cd /paddle/build cmake .. \ - -DWITH_DOC=${WITH_GPU:-OFF} \ + -DWITH_DOC=${WITH_DOC:-OFF} \ -DWITH_GPU=${WITH_GPU:-OFF} \ -DWITH_AVX=${WITH_AVX:-OFF} \ -DWITH_SWIG_PY=ON \ From 6415b0771b924f0fc8abb49660ffca20e0d36a44 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Fri, 24 Feb 2017 13:02:09 +0800 Subject: [PATCH 289/370] Add getNames --- paddle/api/Evaluator.cpp | 6 ++++++ paddle/api/PaddleAPI.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/paddle/api/Evaluator.cpp b/paddle/api/Evaluator.cpp index c30e09876397e3..f9656db19a0386 100644 --- a/paddle/api/Evaluator.cpp +++ b/paddle/api/Evaluator.cpp @@ -27,3 +27,9 @@ std::string Evaluator::toString() { m->rawPtr->printStats(sout); return sout.str(); } + +std::vector Evaluator::getNames() const { + std::vector retv; + m->rawPtr->getNames(&retv); + return retv; +} diff --git a/paddle/api/PaddleAPI.h b/paddle/api/PaddleAPI.h index f5af8b0035b44d..f5dcfcf94c658a 100644 --- a/paddle/api/PaddleAPI.h +++ b/paddle/api/PaddleAPI.h @@ -900,6 +900,8 @@ class Evaluator { */ std::string toString(); + std::vector getNames() const; + private: EvaluatorPrivate* m; From b7ce283b18fe28445dc9527fa1c04b1d9b8f36d8 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Fri, 24 Feb 2017 13:25:49 +0800 Subject: [PATCH 290/370] Expose Evaluator's getNames/getValue to SWIG --- paddle/api/Evaluator.cpp | 9 +++++++++ paddle/api/PaddleAPI.h | 2 ++ paddle/api/test/testTrain.py | 7 ++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/paddle/api/Evaluator.cpp b/paddle/api/Evaluator.cpp index f9656db19a0386..681e3a38091233 100644 --- a/paddle/api/Evaluator.cpp +++ b/paddle/api/Evaluator.cpp @@ -33,3 +33,12 @@ std::vector Evaluator::getNames() const { m->rawPtr->getNames(&retv); return retv; } + +double Evaluator::getValue(const std::string name) const { + paddle::Error err; + double v = m->rawPtr->getValue(name, &err); + if (err) { + throw std::runtime_error(err.msg()); + } + return v; +} diff --git a/paddle/api/PaddleAPI.h b/paddle/api/PaddleAPI.h index f5dcfcf94c658a..80c50cdb08bb16 100644 --- a/paddle/api/PaddleAPI.h +++ b/paddle/api/PaddleAPI.h @@ -902,6 +902,8 @@ class Evaluator { std::vector getNames() const; + double getValue(const std::string name) const; + private: EvaluatorPrivate* m; diff --git a/paddle/api/test/testTrain.py b/paddle/api/test/testTrain.py index a90d15c272a3a2..7061a4c43bf011 100644 --- a/paddle/api/test/testTrain.py +++ b/paddle/api/test/testTrain.py @@ -89,9 +89,14 @@ def update_callback(param): except Exception as e: print e + ev = m.makeEvaluator() + ev.start() m.forwardBackward(inArgs, outArgs, swig_paddle.PASS_TRAIN, update_callback) - + m.eval(ev) + ev.finish() + for name in ev.getNames(): + print name, ev.getValue(name) for optimizer in optimizers: optimizer.finishBatch() From 5f626b93f255d2f9d34732856c23aefb150420e8 Mon Sep 17 00:00:00 2001 From: liaogang Date: Fri, 24 Feb 2017 13:46:48 +0800 Subject: [PATCH 291/370] set docker BUILD_AND_INSTALL --- paddle/scripts/docker/Dockerfile | 2 +- paddle/scripts/docker/Dockerfile.gpu | 2 +- paddle/scripts/docker/build.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile index 3b11018901d0ee..27d19dc15c8bd6 100644 --- a/paddle/scripts/docker/Dockerfile +++ b/paddle/scripts/docker/Dockerfile @@ -30,7 +30,7 @@ ARG WITH_DOC ARG WITH_STYLE_CHECK ENV BUILD_WOBOQ=${BUILD_WOBOQ:-OFF} -ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-ON} +ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-OFF} ENV WITH_GPU=OFF ENV WITH_AVX=${WITH_AVX:-ON} ENV WITH_DOC=${WITH_DOC:-OFF} diff --git a/paddle/scripts/docker/Dockerfile.gpu b/paddle/scripts/docker/Dockerfile.gpu index ea277b61e99af7..538233dd0c7bb5 100644 --- a/paddle/scripts/docker/Dockerfile.gpu +++ b/paddle/scripts/docker/Dockerfile.gpu @@ -30,7 +30,7 @@ ARG WITH_DOC ARG WITH_STYLE_CHECK ENV BUILD_WOBOQ=${BUILD_WOBOQ:-OFF} -ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-ON} +ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-OFF} ENV WITH_GPU=ON ENV WITH_AVX=${WITH_AVX:-ON} ENV WITH_DOC=${WITH_DOC:-OFF} diff --git a/paddle/scripts/docker/build.sh b/paddle/scripts/docker/build.sh index 7fbf2821afa418..d9c44f42340323 100755 --- a/paddle/scripts/docker/build.sh +++ b/paddle/scripts/docker/build.sh @@ -11,7 +11,7 @@ set -e # If Dockerfile.* sets BUILD_AND_INSTALL to 'ON', it would have copied # source tree to /paddle, and this scripts should build it into # /paddle/build. -if [[ ${BUILD_AND_INSTALL:-ON} == 'ON' ]]; then +if [[ ${BUILD_AND_INSTALL:-OFF} == 'ON' ]]; then if [[ ${WITH_GPU:-OFF} == 'ON' ]]; then ln -s /usr/lib/x86_64-linux-gnu/libcudnn.so /usr/lib/libcudnn.so fi From 38a792f20ed9e65d2920ded6ad42a5b68f2146ee Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Fri, 24 Feb 2017 13:52:31 +0800 Subject: [PATCH 292/370] Clean mnist code --- python/paddle/v2/data_set/config.py | 8 ++++ python/paddle/v2/data_set/mnist.py | 58 +++++++++++++---------------- 2 files changed, 33 insertions(+), 33 deletions(-) create mode 100644 python/paddle/v2/data_set/config.py diff --git a/python/paddle/v2/data_set/config.py b/python/paddle/v2/data_set/config.py new file mode 100644 index 00000000000000..69e96d65ef1ef8 --- /dev/null +++ b/python/paddle/v2/data_set/config.py @@ -0,0 +1,8 @@ +import os + +__all__ = ['DATA_HOME'] + +DATA_HOME = os.path.expanduser('~/.cache/paddle_data_set') + +if not os.path.exists(DATA_HOME): + os.makedirs(DATA_HOME) diff --git a/python/paddle/v2/data_set/mnist.py b/python/paddle/v2/data_set/mnist.py index 34f61bb9f632ea..6f35acf683686e 100644 --- a/python/paddle/v2/data_set/mnist.py +++ b/python/paddle/v2/data_set/mnist.py @@ -1,61 +1,53 @@ import sklearn.datasets.mldata import sklearn.model_selection import numpy +from config import DATA_HOME -__all__ = ['MNISTReader', 'train_reader_creator', 'test_reader_creator'] +__all__ = ['MNIST', 'train_creator', 'test_creator'] -DATA_HOME = None +def __mnist_reader_creator__(data, target): + def reader(): + n_samples = data.shape[0] + for i in xrange(n_samples): + yield (data[i] / 255.0).astype(numpy.float32), int(target[i]) -def __mnist_reader__(data, target): - n_samples = data.shape[0] - for i in xrange(n_samples): - yield data[i].astype(numpy.float32), int(target[i]) + return reader -class MNISTReader(object): +class MNIST(object): """ mnist dataset reader. The `train_reader` and `test_reader` method returns a iterator of each sample. Each sample is combined by 784-dim float and a one-dim label """ - def __init__(self, random_state): + def __init__(self, random_state=0, test_size=10000, **options): data = sklearn.datasets.mldata.fetch_mldata( "MNIST original", data_home=DATA_HOME) - n_train = 60000 self.X_train, self.X_test, self.y_train, self.y_test = sklearn.model_selection.train_test_split( - data.data / 255.0, - data.target.astype("int"), - train_size=n_train, - random_state=random_state) + data.data, + data.target, + test_size=test_size, + random_state=random_state, + **options) - def train_reader(self): - return __mnist_reader__(self.X_train, self.y_train) + def train_creator(self): + return __mnist_reader_creator__(self.X_train, self.y_train) - def test_reader(self): - return __mnist_reader__(self.X_test, self.y_test) + def test_creator(self): + return __mnist_reader_creator__(self.X_test, self.y_test) -__default_instance__ = MNISTReader(0) - - -def train_reader_creator(): - """ - Default train set reader creator. - """ - return __default_instance__.train_reader - - -def test_reader_creator(): - """ - Default test set reader creator. - """ - return __default_instance__.test_reader +__default_instance__ = MNIST() +train_creator = __default_instance__.train_creator +test_creator = __default_instance__.test_creator def unittest(): - assert len(list(train_reader_creator()())) == 60000 + size = 12045 + mnist = MNIST(test_size=size) + assert len(list(mnist.test_creator()())) == size if __name__ == '__main__': From ef9041c07bdf5d5f86b0b5b12045b4cec3719953 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 23 Feb 2017 19:20:33 +0800 Subject: [PATCH 293/370] MNIST dataset reader implementation --- python/paddle/v2/data_set/__init__.py | 0 python/paddle/v2/data_set/mnist.py | 62 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 python/paddle/v2/data_set/__init__.py create mode 100644 python/paddle/v2/data_set/mnist.py diff --git a/python/paddle/v2/data_set/__init__.py b/python/paddle/v2/data_set/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/python/paddle/v2/data_set/mnist.py b/python/paddle/v2/data_set/mnist.py new file mode 100644 index 00000000000000..34f61bb9f632ea --- /dev/null +++ b/python/paddle/v2/data_set/mnist.py @@ -0,0 +1,62 @@ +import sklearn.datasets.mldata +import sklearn.model_selection +import numpy + +__all__ = ['MNISTReader', 'train_reader_creator', 'test_reader_creator'] + +DATA_HOME = None + + +def __mnist_reader__(data, target): + n_samples = data.shape[0] + for i in xrange(n_samples): + yield data[i].astype(numpy.float32), int(target[i]) + + +class MNISTReader(object): + """ + mnist dataset reader. The `train_reader` and `test_reader` method returns + a iterator of each sample. Each sample is combined by 784-dim float and a + one-dim label + """ + + def __init__(self, random_state): + data = sklearn.datasets.mldata.fetch_mldata( + "MNIST original", data_home=DATA_HOME) + n_train = 60000 + self.X_train, self.X_test, self.y_train, self.y_test = sklearn.model_selection.train_test_split( + data.data / 255.0, + data.target.astype("int"), + train_size=n_train, + random_state=random_state) + + def train_reader(self): + return __mnist_reader__(self.X_train, self.y_train) + + def test_reader(self): + return __mnist_reader__(self.X_test, self.y_test) + + +__default_instance__ = MNISTReader(0) + + +def train_reader_creator(): + """ + Default train set reader creator. + """ + return __default_instance__.train_reader + + +def test_reader_creator(): + """ + Default test set reader creator. + """ + return __default_instance__.test_reader + + +def unittest(): + assert len(list(train_reader_creator()())) == 60000 + + +if __name__ == '__main__': + unittest() From befc3e066b633ae2a9e0c448037a93ede6de4ddf Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Fri, 24 Feb 2017 13:52:31 +0800 Subject: [PATCH 294/370] Clean mnist code --- python/paddle/v2/data_set/config.py | 8 ++++ python/paddle/v2/data_set/mnist.py | 58 +++++++++++++---------------- 2 files changed, 33 insertions(+), 33 deletions(-) create mode 100644 python/paddle/v2/data_set/config.py diff --git a/python/paddle/v2/data_set/config.py b/python/paddle/v2/data_set/config.py new file mode 100644 index 00000000000000..69e96d65ef1ef8 --- /dev/null +++ b/python/paddle/v2/data_set/config.py @@ -0,0 +1,8 @@ +import os + +__all__ = ['DATA_HOME'] + +DATA_HOME = os.path.expanduser('~/.cache/paddle_data_set') + +if not os.path.exists(DATA_HOME): + os.makedirs(DATA_HOME) diff --git a/python/paddle/v2/data_set/mnist.py b/python/paddle/v2/data_set/mnist.py index 34f61bb9f632ea..6f35acf683686e 100644 --- a/python/paddle/v2/data_set/mnist.py +++ b/python/paddle/v2/data_set/mnist.py @@ -1,61 +1,53 @@ import sklearn.datasets.mldata import sklearn.model_selection import numpy +from config import DATA_HOME -__all__ = ['MNISTReader', 'train_reader_creator', 'test_reader_creator'] +__all__ = ['MNIST', 'train_creator', 'test_creator'] -DATA_HOME = None +def __mnist_reader_creator__(data, target): + def reader(): + n_samples = data.shape[0] + for i in xrange(n_samples): + yield (data[i] / 255.0).astype(numpy.float32), int(target[i]) -def __mnist_reader__(data, target): - n_samples = data.shape[0] - for i in xrange(n_samples): - yield data[i].astype(numpy.float32), int(target[i]) + return reader -class MNISTReader(object): +class MNIST(object): """ mnist dataset reader. The `train_reader` and `test_reader` method returns a iterator of each sample. Each sample is combined by 784-dim float and a one-dim label """ - def __init__(self, random_state): + def __init__(self, random_state=0, test_size=10000, **options): data = sklearn.datasets.mldata.fetch_mldata( "MNIST original", data_home=DATA_HOME) - n_train = 60000 self.X_train, self.X_test, self.y_train, self.y_test = sklearn.model_selection.train_test_split( - data.data / 255.0, - data.target.astype("int"), - train_size=n_train, - random_state=random_state) + data.data, + data.target, + test_size=test_size, + random_state=random_state, + **options) - def train_reader(self): - return __mnist_reader__(self.X_train, self.y_train) + def train_creator(self): + return __mnist_reader_creator__(self.X_train, self.y_train) - def test_reader(self): - return __mnist_reader__(self.X_test, self.y_test) + def test_creator(self): + return __mnist_reader_creator__(self.X_test, self.y_test) -__default_instance__ = MNISTReader(0) - - -def train_reader_creator(): - """ - Default train set reader creator. - """ - return __default_instance__.train_reader - - -def test_reader_creator(): - """ - Default test set reader creator. - """ - return __default_instance__.test_reader +__default_instance__ = MNIST() +train_creator = __default_instance__.train_creator +test_creator = __default_instance__.test_creator def unittest(): - assert len(list(train_reader_creator()())) == 60000 + size = 12045 + mnist = MNIST(test_size=size) + assert len(list(mnist.test_creator()())) == size if __name__ == '__main__': From fb45cc3519b23da0862195bd316370d3f6c17f38 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 24 Feb 2017 16:17:54 +0800 Subject: [PATCH 295/370] refine code --- python/paddle/v2/topology.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index 20fa891d656548..9c57f1f8e607bd 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -32,8 +32,7 @@ def __init__(self, layers): __check_layer_type__(layers) layers = [layers] for layer in layers: - if not isinstance(layer, v2_layer.LayerV2): - raise ValueError('layer should have type paddle.layer.Layer') + __check_layer_type__(layer) self.layers = layers self.__model_config__ = v2_layer.parse_network(*layers) assert isinstance(self.__model_config__, ModelConfig) From c2cefd5bb9cea35cadc0939264d638a8a74d88f2 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 24 Feb 2017 16:23:12 +0800 Subject: [PATCH 296/370] add test for v2-layer --- python/paddle/v2/tests/CMakeLists.txt | 4 ++ python/paddle/v2/tests/layer_test.py | 61 +++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 python/paddle/v2/tests/CMakeLists.txt create mode 100644 python/paddle/v2/tests/layer_test.py diff --git a/python/paddle/v2/tests/CMakeLists.txt b/python/paddle/v2/tests/CMakeLists.txt new file mode 100644 index 00000000000000..83b7180ebafd2e --- /dev/null +++ b/python/paddle/v2/tests/CMakeLists.txt @@ -0,0 +1,4 @@ +add_test(NAME v2_layer_test + COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ + ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/layer_test.py + WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) diff --git a/python/paddle/v2/tests/layer_test.py b/python/paddle/v2/tests/layer_test.py new file mode 100644 index 00000000000000..3b2a13ce05bda7 --- /dev/null +++ b/python/paddle/v2/tests/layer_test.py @@ -0,0 +1,61 @@ +# Copyright PaddlePaddle contributors. All Rights Reserved +# +# 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. +import difflib +import unittest + +import paddle.trainer_config_helpers as conf_helps +import paddle.v2.activation as activation +import paddle.v2.attr as attr +import paddle.v2.data_type as data_type +import paddle.v2.layer as layer +from paddle.trainer_config_helpers.config_parser_utils import \ + parse_network_config as parse_network + +pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) +label = layer.data(name='label', type=data_type.integer_value(10)) +weight = layer.data(name='weight', type=data_type.dense_vector(10)) +score = layer.data(name='score', type=data_type.dense_vector(1)) +hidden = layer.fc(input=pixel, + size=100, + act=activation.Sigmoid(), + param_attr=attr.Param(name='hidden')) +inference = layer.fc(input=hidden, size=10, act=activation.Softmax()) + + +class CostLayerTest(unittest.TestCase): + def test_cost_layer(self): + cost1 = layer.classification_cost(input=inference, label=label) + cost2 = layer.classification_cost( + input=inference, label=label, weight=weight) + cost3 = layer.cross_entropy_cost(input=inference, label=label) + cost4 = layer.cross_entropy_with_selfnorm_cost( + input=inference, label=label) + cost5 = layer.regression_cost(input=inference, label=label) + cost6 = layer.regression_cost( + input=inference, label=label, weight=weight) + cost7 = layer.multi_binary_label_cross_entropy_cost( + input=inference, label=label) + cost8 = layer.rank_cost(left=score, right=score, label=score) + cost9 = layer.lambda_cost(input=inference, score=score) + cost10 = layer.sum_cost(input=inference) + cost11 = layer.huber_cost(input=score, label=label) + + print layer.parse_network(cost1, cost2) + print layer.parse_network(cost3, cost4) + print layer.parse_network(cost5, cost6) + print layer.parse_network(cost7, cost8, cost9, cost10, cost11) + + +if __name__ == '__main__': + unittest.main() From 2591167813764097f206337bb5df96d94eed5802 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 24 Feb 2017 16:33:42 +0800 Subject: [PATCH 297/370] add test dir --- python/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 357637e20346f8..71af50a9a4ed83 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -25,6 +25,7 @@ add_custom_target(paddle_python ALL DEPENDS add_subdirectory(paddle/trainer_config_helpers/tests) add_subdirectory(paddle/reader/tests) +add_subdirectory(paddle/v2/tests) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dist/ DESTINATION opt/paddle/share/wheels From 976a6982baa8a5fb4839d036f7f403ef4b22b0c7 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Fri, 24 Feb 2017 16:46:14 +0800 Subject: [PATCH 298/370] Add cifar dataset --- python/paddle/v2/data_set/cifar.py | 173 +++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 python/paddle/v2/data_set/cifar.py diff --git a/python/paddle/v2/data_set/cifar.py b/python/paddle/v2/data_set/cifar.py new file mode 100644 index 00000000000000..54289430d4ce11 --- /dev/null +++ b/python/paddle/v2/data_set/cifar.py @@ -0,0 +1,173 @@ +""" +CIFAR Dataset. + +URL: https://www.cs.toronto.edu/~kriz/cifar.html + +the default train_creator, test_creator used for CIFAR-10 dataset. +""" +from config import DATA_HOME +import os +import hashlib +import urllib2 +import shutil +import tarfile +import cPickle +import itertools +import numpy + +__all__ = ['CIFAR10', 'CIFAR100', 'train_creator', 'test_creator'] + + +def __download_file__(filename, url, md5): + def __file_ok__(): + if not os.path.exists(filename): + return False + md5_hash = hashlib.md5() + with open(filename, 'rb') as f: + for chunk in iter(lambda: f.read(4096), b""): + md5_hash.update(chunk) + + return md5_hash.hexdigest() == md5 + + while not __file_ok__(): + response = urllib2.urlopen(url) + with open(filename, mode='wb') as of: + shutil.copyfileobj(fsrc=response, fdst=of) + + +def __read_one_batch__(batch): + data = batch['data'] + labels = batch.get('labels', batch.get('fine_labels', None)) + assert labels is not None + for sample, label in itertools.izip(data, labels): + yield (sample / 255.0).astype(numpy.float32), int(label) + + +CIFAR10_URL = 'https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz' +CIFAR10_MD5 = 'c58f30108f718f92721af3b95e74349a' +CIFAR100_URL = 'https://www.cs.toronto.edu/~kriz/cifar-100-python.tar.gz' +CIFAR100_MD5 = 'eb9058c3a382ffc7106e4002c42a8d85' + + +class CIFAR(object): + """ + CIFAR dataset reader. The base class for CIFAR-10 and CIFAR-100 + + :param url: Download url. + :param md5: File md5sum + :param meta_filename: Meta file name in package. + :param train_filename: Train file name in package. + :param test_filename: Test file name in package. + """ + + def __init__(self, url, md5, meta_filename, train_filename, test_filename): + filename = os.path.split(url)[-1] + assert DATA_HOME is not None + filepath = os.path.join(DATA_HOME, md5) + if not os.path.exists(filepath): + os.makedirs(filepath) + + self.__full_file__ = os.path.join(filepath, filename) + self.__meta_filename__ = meta_filename + self.__train_filename__ = train_filename + self.__test_filename__ = test_filename + __download_file__(filename=self.__full_file__, url=url, md5=md5) + + def labels(self): + """ + labels get all dataset label in order. + :return: a list of label. + :rtype: list[string] + """ + with tarfile.open(self.__full_file__, mode='r') as f: + name = [ + each_item.name for each_item in f + if self.__meta_filename__ in each_item.name + ][0] + meta_f = f.extractfile(name) + meta = cPickle.load(meta_f) + for key in meta: + if 'label' in key: + return meta[key] + else: + raise RuntimeError("Unexpected branch.") + + def train(self): + """ + Train Reader + """ + return self.__read_batch__(self.__train_filename__) + + def test(self): + """ + Test Reader + """ + return self.__read_batch__(self.__test_filename__) + + def __read_batch__(self, sub_name): + with tarfile.open(self.__full_file__, mode='r') as f: + names = (each_item.name for each_item in f + if sub_name in each_item.name) + + for name in names: + batch = cPickle.load(f.extractfile(name)) + for item in __read_one_batch__(batch): + yield item + + +class CIFAR10(CIFAR): + """ + CIFAR-10 dataset, images are classified in 10 classes. + """ + + def __init__(self): + super(CIFAR10, self).__init__( + CIFAR10_URL, + CIFAR10_MD5, + meta_filename='batches.meta', + train_filename='data_batch', + test_filename='test_batch') + + +class CIFAR100(CIFAR): + """ + CIFAR-100 dataset, images are classified in 100 classes. + """ + + def __init__(self): + super(CIFAR100, self).__init__( + CIFAR100_URL, + CIFAR100_MD5, + meta_filename='meta', + train_filename='train', + test_filename='test') + + +def train_creator(): + """ + Default train reader creator. Use CIFAR-10 dataset. + """ + cifar = CIFAR10() + return cifar.train + + +def test_creator(): + """ + Default test reader creator. Use CIFAR-10 dataset. + """ + cifar = CIFAR10() + return cifar.test + + +def unittest(label_count=100): + cifar = globals()["CIFAR%d" % label_count]() + assert len(cifar.labels()) == label_count + for _ in cifar.test(): + pass + for _ in cifar.train(): + pass + + +if __name__ == '__main__': + unittest(10) + unittest(100) From bf8a6dc4fff40e869236c0634df57bfe16c12d96 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 24 Feb 2017 17:14:38 +0800 Subject: [PATCH 299/370] rename layer_test to test_layer --- python/paddle/v2/tests/CMakeLists.txt | 4 ++-- .../paddle/v2/tests/{layer_test.py => test_layer.py} | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) rename python/paddle/v2/tests/{layer_test.py => test_layer.py} (90%) diff --git a/python/paddle/v2/tests/CMakeLists.txt b/python/paddle/v2/tests/CMakeLists.txt index 83b7180ebafd2e..402ad2e664c773 100644 --- a/python/paddle/v2/tests/CMakeLists.txt +++ b/python/paddle/v2/tests/CMakeLists.txt @@ -1,4 +1,4 @@ -add_test(NAME v2_layer_test +add_test(NAME test_v2_layer COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ - ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/layer_test.py + ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/test_layer.py WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) diff --git a/python/paddle/v2/tests/layer_test.py b/python/paddle/v2/tests/test_layer.py similarity index 90% rename from python/paddle/v2/tests/layer_test.py rename to python/paddle/v2/tests/test_layer.py index 3b2a13ce05bda7..b600e8cf765122 100644 --- a/python/paddle/v2/tests/layer_test.py +++ b/python/paddle/v2/tests/test_layer.py @@ -51,10 +51,12 @@ def test_cost_layer(self): cost10 = layer.sum_cost(input=inference) cost11 = layer.huber_cost(input=score, label=label) - print layer.parse_network(cost1, cost2) - print layer.parse_network(cost3, cost4) - print layer.parse_network(cost5, cost6) - print layer.parse_network(cost7, cost8, cost9, cost10, cost11) + print dir(layer) + layer.parse_network(cost1, cost2) + print dir(layer) + #print layer.parse_network(cost3, cost4) + #print layer.parse_network(cost5, cost6) + #print layer.parse_network(cost7, cost8, cost9, cost10, cost11) if __name__ == '__main__': From 5258bcf3eee7f1ca24af04759b0cf4f21e8b5f0a Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Fri, 24 Feb 2017 17:41:58 +0800 Subject: [PATCH 300/370] implement more layers in v2 --- doc/api/trainer_config_helpers/layers.rst | 36 ++- .../paddle/trainer_config_helpers/layers.py | 214 ++++++++-------- python/paddle/v2/__init__.py | 3 +- python/paddle/v2/layer.py | 235 ++++++++++++++---- python/paddle/v2/pooling.py | 24 ++ 5 files changed, 353 insertions(+), 159 deletions(-) create mode 100644 python/paddle/v2/pooling.py diff --git a/doc/api/trainer_config_helpers/layers.rst b/doc/api/trainer_config_helpers/layers.rst index 2793d6afd9565e..bbea823de4d870 100644 --- a/doc/api/trainer_config_helpers/layers.rst +++ b/doc/api/trainer_config_helpers/layers.rst @@ -139,24 +139,12 @@ lstmemory :members: lstmemory :noindex: -lstm_step_layer ---------------- -.. automodule:: paddle.trainer_config_helpers.layers - :members: lstm_step_layer - :noindex: - grumemory --------- .. automodule:: paddle.trainer_config_helpers.layers :members: grumemory :noindex: -gru_step_layer ---------------- -.. automodule:: paddle.trainer_config_helpers.layers - :members: gru_step_layer - :noindex: - Recurrent Layer Group ===================== @@ -172,6 +160,18 @@ recurrent_group :members: recurrent_group :noindex: +lstm_step_layer +--------------- +.. automodule:: paddle.trainer_config_helpers.layers + :members: lstm_step_layer + :noindex: + +gru_step_layer +--------------- +.. automodule:: paddle.trainer_config_helpers.layers + :members: gru_step_layer + :noindex: + beam_search ------------ .. automodule:: paddle.trainer_config_helpers.layers @@ -308,6 +308,12 @@ repeat_layer :members: repeat_layer :noindex: +rotate_layer +------------ +.. automodule:: paddle.trainer_config_helpers.layers + :members: rotate_layer + :noindex: + seq_reshape_layer ----------------- .. automodule:: paddle.trainer_config_helpers.layers @@ -462,6 +468,12 @@ ctc_layer :members: ctc_layer :noindex: +warp_ctc_layer +-------------- +.. automodule:: paddle.trainer_config_helpers.layers + :members: warp_ctc_layer + :noindex: + nce_layer ----------- .. automodule:: paddle.trainer_config_helpers.layers diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 00aef80691fba0..de903f8c747c97 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -30,88 +30,28 @@ import copy __all__ = [ - "full_matrix_projection", - "AggregateLevel", - "ExpandLevel", - "identity_projection", - "dotmul_projection", - "dotmul_operator", - "repeat_layer", - "seq_reshape_layer", - "table_projection", - "mixed_layer", - "data_layer", - "embedding_layer", - "fc_layer", - "grumemory", - "pooling_layer", - "lstmemory", - "last_seq", - "first_seq", - "cos_sim", - "hsigmoid", - "conv_projection", - "regression_cost", - 'classification_cost', - "LayerOutput", - 'img_conv_layer', - 'img_pool_layer', - 'batch_norm_layer', - 'img_cmrnorm_layer', - 'addto_layer', - 'concat_layer', - 'seq_concat_layer', - 'lstm_step_layer', - 'recurrent_group', - 'memory', - 'StaticInput', - 'expand_layer', - 'scaling_layer', - 'scaling_projection', - 'power_layer', - 'interpolation_layer', - 'bilinear_interp_layer', - 'trans_layer', - 'rotate_layer', - 'sum_to_one_norm_layer', - 'get_output_layer', - 'LayerType', - 'context_projection', - 'beam_search', - 'maxid_layer', - 'GeneratedInput', - 'SubsequenceInput', - 'gru_step_layer', - 'recurrent_layer', - 'BaseGeneratedInput', - 'conv_operator', - 'conv_shift_layer', - 'tensor_layer', - 'selective_fc_layer', - 'sampling_id_layer', - 'slope_intercept_layer', - 'trans_full_matrix_projection', - 'linear_comb_layer', - 'convex_comb_layer', - 'ctc_layer', - 'warp_ctc_layer', - 'crf_layer', - 'crf_decoding_layer', - 'nce_layer', - 'cross_entropy_with_selfnorm', - 'cross_entropy', - 'multi_binary_label_cross_entropy', - 'sum_cost', - 'rank_cost', - 'lambda_cost', - 'huber_cost', - 'block_expand_layer', - 'maxout_layer', - 'out_prod_layer', - 'print_layer', - 'priorbox_layer', - 'spp_layer', - 'pad_layer', + "full_matrix_projection", "AggregateLevel", "ExpandLevel", + "identity_projection", "dotmul_projection", "dotmul_operator", + "repeat_layer", "seq_reshape_layer", "table_projection", "mixed_layer", + "data_layer", "embedding_layer", "fc_layer", "grumemory", "pooling_layer", + "lstmemory", "last_seq", "first_seq", "cos_sim", "hsigmoid", + "conv_projection", "regression_cost", 'classification_cost', "LayerOutput", + 'img_conv_layer', 'img_pool_layer', 'batch_norm_layer', 'img_cmrnorm_layer', + 'addto_layer', 'concat_layer', 'seq_concat_layer', 'lstm_step_layer', + 'recurrent_group', 'memory', 'StaticInput', 'expand_layer', 'scaling_layer', + 'scaling_projection', 'power_layer', 'interpolation_layer', + 'bilinear_interp_layer', 'trans_layer', 'rotate_layer', + 'sum_to_one_norm_layer', 'get_output_layer', 'LayerType', + 'context_projection', 'beam_search', 'maxid_layer', 'GeneratedInput', + 'SubsequenceInput', 'gru_step_layer', 'recurrent_layer', + 'BaseGeneratedInput', 'conv_operator', 'conv_shift_layer', 'tensor_layer', + 'selective_fc_layer', 'sampling_id_layer', 'slope_intercept_layer', + 'trans_full_matrix_projection', 'linear_comb_layer', 'convex_comb_layer', + 'ctc_layer', 'warp_ctc_layer', 'crf_layer', 'crf_decoding_layer', + 'nce_layer', 'cross_entropy_with_selfnorm', 'cross_entropy', + 'multi_binary_label_cross_entropy', 'sum_cost', 'rank_cost', 'lambda_cost', + 'huber_cost', 'block_expand_layer', 'maxout_layer', 'out_prod_layer', + 'print_layer', 'priorbox_layer', 'spp_layer', 'pad_layer', 'eos_layer' ] @@ -1287,6 +1227,12 @@ def last_seq(input, """ Get Last Timestamp Activation of a sequence. + The simple usage is: + + .. code-block:: python + + seq = last_seq(input=layer) + :param agg_level: Aggregated level :param name: Layer name. :type name: basestring @@ -1325,6 +1271,12 @@ def first_seq(input, """ Get First Timestamp Activation of a sequence. + The simple usage is: + + .. code-block:: python + + seq = first_seq(input=layer) + :param agg_level: aggregation level :param name: Layer name. :type name: basestring @@ -1425,7 +1377,7 @@ def repeat_layer(input, num_repeats, name=None, layer_attr=None): .. code-block:: python - expand = repeat_layer(layer, 4) + expand = repeat_layer(input=layer, num_repeats=4) :param input: Input layer :type input: LayerOutput @@ -1797,6 +1749,12 @@ def cos_sim(a, b, scale=1, size=1, name=None, layer_attr=None): Note that the above computation is for one sample. Multiple samples are processed in one batch. + The example usage is: + + .. code-block:: python + + cos = cos_sim(a=layer1, b=layer2, size=3) + :param name: layer name :type name: basestring :param a: input layer a @@ -1958,6 +1916,16 @@ def img_conv_layer(input, pieces. First 256/4 = 64 channels will process by first 32 filters. The rest channels will be processed by rest group of filters. + The example usage is: + + .. code-block:: python + + conv = img_conv_layer(input=data, filter_size=1, filter_size_y=1, + num_channels=8, + num_filters=16, stride=1, + bias_attr=False, + act=ReluActivation()) + :param name: Layer name. :type name: basestring :param input: Layer Input. @@ -2097,6 +2065,34 @@ def img_pool_layer(input, .. _pooling: http://ufldl.stanford.edu/tutorial/supervised/Pooling/ + - ceil_mode=True: + + .. math:: + + w = 1 + int(ceil(input\_width + 2 * padding - pool\_size) / float(stride)) + h = 1 + int(ceil(input\_height + 2 * padding\_y - pool\_size\_y) / float(stride\_y)) + + - ceil_mode=False: + + .. math:: + + w = 1 + int(floor(input\_width + 2 * padding - pool\_size) / float(stride)) + h = 1 + int(floor(input\_height + 2 * padding\_y - pool\_size\_y) / float(stride\_y)) + + The example usage is: + + .. code-block:: python + + maxpool = img_pool_layer(input=conv, + pool_size=3, + pool_size_y=5, + num_channels=8, + stride=1, + stride_y=2, + padding=1, + padding_y=2, + pool_type=MaxPooling()) + :param padding: pooling padding width. :type padding: int :param padding_y: pooling padding height. It's equal to padding by default. @@ -2123,19 +2119,6 @@ def img_pool_layer(input, :param ceil_mode: Wether to use ceil mode to calculate output height and with. Defalut is True. If set false, Otherwise use floor. - - ceil_mode=True: - - .. math:: - - w = 1 + int(ceil(input_width + 2 * padding - pool_size) / float(stride)) - h = 1 + int(ceil(input_height + 2 * padding_y - pool_size_y) / float(stride_y)) - - - ceil_mode=False: - - .. math:: - - w = 1 + int(floor(input_width + 2 * padding - pool_size) / float(stride)) - h = 1 + int(floor(input_height + 2 * padding_y - pool_size_y) / float(stride_y)) :type ceil_mode: bool :return: LayerOutput object. :rtype: LayerOutput @@ -2197,6 +2180,15 @@ def spp_layer(input, The details please refer to `Kaiming He's paper `_. + The example usage is: + + .. code-block:: python + + spp = spp_layer(input=data, + pyramid_height=2, + num_channels=16, + pool_type=MaxPooling()) + :param name: layer name. :type name: basestring :param input: layer's input. @@ -2285,6 +2277,12 @@ def img_cmrnorm_layer(input, The details please refer to `Alex's paper `_. + The example usage is: + + .. code-block:: python + + norm = img_cmrnorm_layer(input=net, size=5) + :param name: layer name. :type name: None|basestring :param input: layer's input. @@ -2340,6 +2338,12 @@ def batch_norm_layer(input, The details of batch normalization please refer to this `paper `_. + The example usage is: + + .. code-block:: python + + norm = batch_norm_layer(input=net, act=ReluActivation()) + :param name: layer name. :type name: basestring :param input: batch normalization input. Better be linear activation. @@ -3903,13 +3907,13 @@ def conv_shift_layer(a, b, name=None, layer_attr=None): .. code-block:: python - conv_shift = conv_shift_layer(input=[layer1, layer2]) + conv_shift = conv_shift_layer(a=layer1, b=layer2) :param name: layer name :type name: basestring :param a: Input layer a. :type a: LayerOutput - :param b: input layer b + :param b: input layer b. :type b: LayerOutput :param layer_attr: layer's extra attribute. :type layer_attr: ExtraLayerAttribute @@ -4001,8 +4005,8 @@ def tensor_layer(a, @wrap_act_default() @layer_support() def selective_fc_layer(input, - select, size, + select=None, act=None, name=None, pass_generation=False, @@ -4029,6 +4033,7 @@ def selective_fc_layer(input, :type input: LayerOutput|list|tuple :param select: The select layer. The output of select layer should be a sparse binary matrix, and treat as the mask of selective fc. + If is None, acts exactly like fc_layer. :type select: LayerOutput :param size: The layer dimension. :type size: int @@ -4257,7 +4262,7 @@ def block_expand_layer(input, .. code-block:: python - block_expand = block_expand_layer(input, + block_expand = block_expand_layer(input=layer, num_channels=128, stride_x=1, stride_y=1, @@ -4461,7 +4466,7 @@ def warp_ctc_layer(input, - You can set 'blank' to any value ranged in [0, num_classes], which should be consistent as that used in your labels. - As a native 'softmax' activation is interated to the warp-ctc library, - 'linear' activation is expected instead in the 'input' layer. + 'linear' activation is expected instead in the 'input' layer. The simple usage: @@ -4594,6 +4599,13 @@ def crf_decoding_layer(input, this layer will also calculate error. output.value[i] is 1 for incorrect decoding or 0 for correct decoding. + The simple usage: + + .. code-block:: python + + crf_decoding = crf_decoding_layer(input=input, + size=label_dim) + :param input: The first input layer. :type input: LayerOutput :param size: size of this layer. diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index 0cf7b8e9039f73..ab352e880e30fb 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -19,11 +19,12 @@ import event import data_type import attr +import pooling import py_paddle.swig_paddle as api __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', - 'event', 'data_type', 'attr' + 'event', 'data_type', 'attr', 'pooling' ] diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 3920d4a08fc627..f4a85e9d038e45 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -76,12 +76,20 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. import data_type import activation import attr +import pooling __all__ = [ - 'parse_network', 'data', 'fc', 'max_id', 'classification_cost', - 'cross_entropy_cost', 'cross_entropy_with_selfnorm_cost', 'regression_cost', + 'parse_network', 'data', 'fc', 'conv_shift', 'img_conv', 'img_pool', 'spp', + 'maxout', 'img_cmrnorm', 'batch_norm', 'sum_to_one_norm', 'recurrent', + 'lstmemory', 'grumemory', 'pool', 'last_seq', 'first_seq', 'concat', + 'seq_concat', 'block_expand', 'expand', 'repeat', 'seq_reshape', 'addto', + 'linear_comb', 'interpolation', 'bilinear_interp', 'power', 'scaling', + 'slope_intercept', 'tensor', 'cos_sim', 'trans', 'max_id', 'sampling_id', + 'pad', 'classification_cost', 'cross_entropy_cost', + 'cross_entropy_with_selfnorm_cost', 'regression_cost', 'multi_binary_label_cross_entropy_cost', 'rank_cost', 'lambda_cost', - 'sum_cost', 'huber_cost' + 'sum_cost', 'huber_cost', 'crf', 'crf_decoding', 'ctc', 'warp_ctc', 'nce', + 'hsigmoid', 'eos' ] @@ -130,11 +138,8 @@ def to_proto_impl(self, **kwargs): raise NotImplementedError() -def __convert_to_v2__(method_name, name_prefix, parent_names): - if name_prefix is not None: - wrapper = wrap_name_default(name_prefix=name_prefix) - else: - wrapper = None +def __convert_to_v2__(method_name, parent_names): + wrapper = wrap_name_default(name_prefix=method_name) class V2LayerImpl(Layer): def __init__(self, name=None, **kwargs): @@ -192,44 +197,92 @@ def to_proto_impl(self, **kwargs): data = DataLayerV2 -fc = __convert_to_v2__('fc_layer', name_prefix='fc', parent_names=['input']) -max_id = __convert_to_v2__( - 'maxid_layer', name_prefix='maxid', parent_names=['input']) -classification_cost = __convert_to_v2__( - 'classification_cost', - name_prefix='classification_cost', - parent_names=['input', 'label', 'weight']) -regression_cost = __convert_to_v2__( - 'regression_cost', - name_prefix='regression_cost', - parent_names=['input', 'label', 'weight']) -cross_entropy_cost = __convert_to_v2__( - 'cross_entropy', - name_prefix='cross_entropy', - parent_names=['input', 'label']) -cross_entropy_with_selfnorm_cost = __convert_to_v2__( - 'cross_entropy_with_selfnorm', - name_prefix='cross_entropy_with_selfnorm', - parent_names=['input', 'label']) -multi_binary_label_cross_entropy_cost = __convert_to_v2__( - 'multi_binary_label_cross_entropy', - name_prefix='multi_binary_label_cross_entropy', - parent_names=['input', 'label']) -rank_cost = __convert_to_v2__( - 'rank_cost', - name_prefix='rank_cost', - parent_names=['left', 'right', 'label', 'weight']) -lambda_cost = __convert_to_v2__( - 'lambda_cost', name_prefix='lambda_cost', parent_names=['input', 'score']) -sum_cost = __convert_to_v2__( - 'sum_cost', name_prefix='sum_cost', parent_names=['input']) -huber_cost = __convert_to_v2__( - 'huber_cost', name_prefix='huber_cost', parent_names=['input', 'label']) +AggregateLevel = conf_helps.layers.AggregateLevel +ExpandLevel = conf_helps.layers.ExpandLevel + +layer_list = [ + # [V2LayerImpl, V1_method_name, parent_names] + # fully connected layers + ['fc', 'fc_layer', ['input']], + # conv layers + ['conv_shift', 'conv_shift_layer', ['a', 'b']], + ['img_conv', 'img_conv_layer', ['input']], + # image pooling layers + ['img_pool', 'img_pool_layer', ['input']], + ['spp', 'spp_layer', ['input']], + ['maxout', 'maxout_layer', ['input']], + # norm layers + ['img_cmrnorm', 'img_cmrnorm_layer', ['input']], + ['batch_norm', 'batch_norm_layer', ['input']], + ['sum_to_one_norm', 'sum_to_one_norm_layer', ['input']], + # recurrent layers + ['recurrent', 'recurrent_layer', ['input']], + ['lstmemory', 'lstmemory', ['input']], + ['grumemory', 'grumemory', ['input']], + # aggregate layers + ['pool', 'pooling_layer', ['input']], + ['last_seq', 'last_seq', ['input']], + ['first_seq', 'first_seq', ['input']], + ['concat', 'concat_layer', ['input']], + ['seq_concat', 'seq_concat_layer', ['a', 'b']], + # reshaping layers + ['block_expand', 'block_expand_layer', ['input']], + ['expand', 'expand_layer', ['input', 'expand_as']], + ['repeat', 'repeat_layer', ['input']], + ['rotate', 'rotate_layer', ['input']], + ['seq_reshape', 'seq_reshape_layer', ['input']], + # math layers + ['addto', 'addto_layer', ['input']], + ['linear_comb', 'linear_comb_layer', ['weights', 'vectors']], + ['interpolation', 'interpolation_layer', ['input', 'weight']], + ['bilinear_interp', 'bilinear_interp_layer', ['input']], + ['power', 'power_layer', ['input', 'weight']], + ['scaling', 'scaling_layer', ['input', 'weight']], + ['slope_intercept', 'slope_intercept_layer', ['input']], + ['tensor', 'tensor_layer', ['a', 'b']], + ['cos_sim', 'cos_sim', ['a', 'b']], + ['trans', 'trans_layer', ['input']], + # sampling layers + ['max_id', 'maxid_layer', ['input']], + ['sampling_id', 'sampling_id_layer', ['input']], + # slicing and joining layers + ['pad', 'pad_layer', ['input']], + # cost layers + [ + 'classification_cost', 'classification_cost', + ['input', 'label', 'weight'] + ], + ['regression_cost', 'regression_cost', ['input', 'label', 'weight']], + ['cross_entropy_cost', 'cross_entropy', ['input', 'label']], + [ + 'cross_entropy_with_selfnorm_cost', 'cross_entropy_with_selfnorm', + ['input', 'label'] + ], + [ + 'multi_binary_label_cross_entropy_cost', + 'multi_binary_label_cross_entropy', ['input', 'label'] + ], + ['rank_cost', 'rank_cost', ['left', 'right', 'label', 'weight']], + ['lambda_cost', 'lambda_cost', ['input', 'score']], + ['sum_cost', 'sum_cost', ['input']], + ['huber_cost', 'huber_cost', ['input', 'label']], + ['crf', 'crf_layer', ['input', 'label']], + ['crf_decoding', 'crf_decoding_layer', ['input']], + ['ctc', 'ctc_layer', ['input', 'label']], + ['warp_ctc', 'warp_ctc_layer', ['input', 'label']], + ['nce', 'nce_layer', ['input', 'label']], + ['hsigmoid', 'hsigmoid', ['input', 'label']], + # check layers + ['eos', 'eos_layer', ['input']] +] +for l in layer_list: + globals()[l[0]] = __convert_to_v2__(l[1], l[2]) if __name__ == '__main__': - pixel = data(name='pixel', type=data_type.dense_vector(784)) + pixel = data(name='pixel', type=data_type.dense_vector(128)) label = data(name='label', type=data_type.integer_value(10)) weight = data(name='weight', type=data_type.dense_vector(10)) + word = data(name='word', type=data_type.integer_value(12)) score = data(name='score', type=data_type.dense_vector(1)) hidden = fc(input=pixel, @@ -237,7 +290,90 @@ def to_proto_impl(self, **kwargs): act=activation.Sigmoid(), param_attr=attr.Param(name='hidden')) inference = fc(input=hidden, size=10, act=activation.Softmax()) + print parse_network(inference) + + # test conv layers + conv1 = conv_shift(a=pixel, b=score) + conv2 = img_conv( + input=pixel, + filter_size=1, + filter_size_y=1, + num_channels=8, + num_filters=16, + act=activation.Linear()) + print parse_network(conv1, conv2) + + # test image pooling layers + maxpool = img_pool( + input=conv2, + pool_size=2, + num_channels=16, + padding=1, + pool_type=pooling.Max()) + spp = spp(input=conv2, + pyramid_height=2, + num_channels=16, + pool_type=pooling.Max()) + maxout = maxout(input=conv2, num_channels=16, groups=4) + print parse_network(maxpool, spp, maxout) + + # test norm layers + norm1 = img_cmrnorm(input=maxpool, size=5) + norm2 = batch_norm(input=maxpool) + norm3 = sum_to_one_norm(input=maxpool) + print parse_network(norm1, norm2, norm3) + + # test recurrent layers + recurrent = recurrent(input=word) + lstm = lstmemory(input=word) + gru = grumemory(input=word) + print parse_network(recurrent, lstm, gru) + + # test aggregate layers + pool = pool( + input=pixel, + pooling_type=pooling.Avg(), + agg_level=AggregateLevel.EACH_SEQUENCE) + last_seq = last_seq(input=pixel) + first_seq = first_seq(input=pixel) + concat = concat(input=[last_seq, first_seq]) + seq_concat = seq_concat(a=last_seq, b=first_seq) + print parse_network(pool, last_seq, first_seq, concat, seq_concat) + + # test reshaping layers + block_expand = block_expand( + input=maxout, num_channels=4, stride_x=1, block_x=1) + expand = expand( + input=last_seq, expand_as=pixel, expand_level=ExpandLevel.FROM_TIMESTEP) + repeat = repeat(input=last_seq, num_repeats=4) + reshape = seq_reshape(input=last_seq, reshape_size=4) + rotate = rotate(input=pixel, height=16, width=49) + print parse_network(block_expand, expand, repeat, reshape, rotate) + + # test math layers + addto = addto(input=[last_seq, first_seq]) + linear_comb = linear_comb(weights=weight, vectors=hidden, size=10) + interpolation = interpolation(input=[hidden, hidden], weight=score) + bilinear = bilinear_interp(input=conv2, out_size_x=4, out_size_y=4) + power = power(input=conv1, weight=score) + scaling = scaling(input=conv1, weight=score) + slope = slope_intercept(input=conv1) + tensor = tensor(a=last_seq, b=first_seq, size=1000) + cos_sim = cos_sim(a=last_seq, b=first_seq) + trans = trans(input=tensor) + print parse_network(addto, linear_comb, interpolation, bilinear, power, + scaling, slope, tensor, cos_sim, trans) + + # test sampling layers maxid = max_id(input=inference) + sampling_id = sampling_id(input=inference) + print parse_network(maxid, sampling_id) + + # test slicing and joining layers + pad = pad(input=maxpool, pad_c=[2, 3], pad_h=[1, 2], pad_w=[3, 1]) + print parse_network(pad) + + # test cost layers cost1 = classification_cost(input=inference, label=label) cost2 = classification_cost(input=inference, label=label, weight=weight) cost3 = cross_entropy_cost(input=inference, label=label) @@ -249,9 +385,18 @@ def to_proto_impl(self, **kwargs): cost9 = lambda_cost(input=inference, score=score) cost10 = sum_cost(input=inference) cost11 = huber_cost(input=score, label=label) - - print parse_network(cost1, cost2) print parse_network(cost3, cost4) print parse_network(cost5, cost6) print parse_network(cost7, cost8, cost9, cost10, cost11) - print parse_network(inference, maxid) + + crf = crf(input=inference, label=label) + crf_decoding = crf_decoding(input=inference, size=3) + ctc = ctc(input=inference, label=label) + warp_ctc = warp_ctc(input=pixel, label=label) + nce = nce(input=inference, label=label, num_classes=3) + hsigmoid = hsigmoid(input=inference, label=label, num_classes=3) + print parse_network(crf, crf_decoding, ctc, warp_ctc, nce, hsigmoid) + + # test check layers + eos = eos(input=maxid, eos_id=5) + print parse_network(eos) diff --git a/python/paddle/v2/pooling.py b/python/paddle/v2/pooling.py new file mode 100644 index 00000000000000..9076a159bb4f2c --- /dev/null +++ b/python/paddle/v2/pooling.py @@ -0,0 +1,24 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + +from paddle.trainer_config_helpers.poolings import * + +__all__ = ["Max", "CudnnMax", "Avg", "CudnnAvg", "Sum", "SquareRootN"] + +Max = MaxPooling +CudnnMax = CudnnMaxPooling +Avg = AvgPooling +CudnnAvg = CudnnAvgPooling +Sum = SumPooling +SquareRootN = SquareRootNPooling From 623d24ad5c201996c66fc2ec48c43fd6a7f75973 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Fri, 24 Feb 2017 19:19:32 +0800 Subject: [PATCH 301/370] convert mixed layer, projection and operator --- .../paddle/trainer_config_helpers/layers.py | 2 + python/paddle/v2/data_type.py | 4 +- python/paddle/v2/layer.py | 248 +++++++++++++++++- 3 files changed, 239 insertions(+), 15 deletions(-) diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 00aef80691fba0..95f0915972cbac 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -112,6 +112,7 @@ 'priorbox_layer', 'spp_layer', 'pad_layer', + 'layer_support', ] @@ -708,6 +709,7 @@ def __exit__(self, *args, **kwargs): # update the size which might be computed inside MixedLayer # according to the operator's output size self.size = ml.config.size + self.finalized = True @wrap_name_default("mixed") diff --git a/python/paddle/v2/data_type.py b/python/paddle/v2/data_type.py index 5b01ba4cd4866c..dd3ebfcb4267e1 100644 --- a/python/paddle/v2/data_type.py +++ b/python/paddle/v2/data_type.py @@ -14,9 +14,9 @@ from paddle.trainer.PyDataProvider2 import \ InputType, dense_vector, sparse_binary_vector,\ - sparse_vector, integer_value + sparse_vector, integer_value, integer_value_sequence __all__ = [ 'InputType', 'dense_vector', 'sparse_binary_vector', 'sparse_vector', - 'integer_value' + 'integer_value', 'integer_value_sequence' ] diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 3920d4a08fc627..0e9e2a249ddb3a 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -72,16 +72,38 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. from paddle.trainer_config_helpers.config_parser_utils import \ parse_network_config as __parse__ from paddle.trainer_config_helpers.default_decorators import wrap_name_default +from paddle.trainer_config_helpers.default_decorators import wrap_act_default +from paddle.trainer_config_helpers.default_decorators import wrap_bias_attr_default +from paddle.trainer_config_helpers.layers import layer_support import data_type import activation import attr +#import pudb;pudb.set_trace() + __all__ = [ - 'parse_network', 'data', 'fc', 'max_id', 'classification_cost', - 'cross_entropy_cost', 'cross_entropy_with_selfnorm_cost', 'regression_cost', - 'multi_binary_label_cross_entropy_cost', 'rank_cost', 'lambda_cost', - 'sum_cost', 'huber_cost' + 'parse_network', + 'data', + 'fc', + 'max_id', + 'classification_cost', + 'cross_entropy_cost', + 'cross_entropy_with_selfnorm_cost', + 'regression_cost', + 'multi_binary_label_cross_entropy_cost', + 'rank_cost', + 'lambda_cost', + 'sum_cost', + 'huber_cost' + 'full_matrix_projection', + 'trans_full_matrix_projection', + 'table_projection', + 'identity_projection', + 'scaling_projection', + 'dotmul_projection', + 'context_projection', + 'conv_projection', ] @@ -101,9 +123,8 @@ def __real_func__(): class Layer(object): - def __init__(self, name, parent_layers): + def __init__(self, name=None, parent_layers=None): assert isinstance(parent_layers, dict) - assert isinstance(name, basestring) self.name = name self.__parent_layers__ = parent_layers @@ -122,6 +143,9 @@ def to_proto(self, context): self.__parent_layers__[layer_name]) kwargs[layer_name] = v1_layer + if self.name is None: + return self.to_proto_impl(**kwargs) + if self.name not in context: context[self.name] = self.to_proto_impl(**kwargs) return context[self.name] @@ -130,7 +154,7 @@ def to_proto_impl(self, **kwargs): raise NotImplementedError() -def __convert_to_v2__(method_name, name_prefix, parent_names): +def __convert_to_v2__(method_name, name_prefix=None, parent_names=None): if name_prefix is not None: wrapper = wrap_name_default(name_prefix=name_prefix) else: @@ -160,7 +184,7 @@ def to_proto_impl(self, **kwargs): args[each] = kwargs[each] for each in self.__other_kwargs__: args[each] = self.__other_kwargs__[each] - return getattr(conf_helps, method_name)(name=self.name, **args) + return getattr(conf_helps, method_name)(**args) return V2LayerImpl @@ -191,6 +215,81 @@ def to_proto_impl(self, **kwargs): return getattr(conf_helps, self.__method_name__)(name=self.name, **args) +class MixedLayerV2(Layer): + """ + This class is use to support `with` grammar. If not, the following code + could convert mixed_layer simply. + + mixed = __convert_to_v2__( + 'mixed_layer', name_prefix='mixed', parent_names=['input']) + """ + + class AddToSealedMixedLayerExceptionV2(Exception): + def __init__(self): + Exception.__init__(self) + + def __init__(self, + size=0, + input=None, + name=None, + act=None, + bias_attr=None, + layer_attr=None): + self.__method_name__ = 'mixed_layer' + self.finalized = False + + self.__parent_layers__ = dict() + other_kwargs = dict() + self.input_name = 'input' + self.__parent_layers__[self.input_name] = [] + if input is not None: + self.__parent_layers__[self.input_name] = input + + self.name = name + other_kwargs['size'] = size + other_kwargs['act'] = act + other_kwargs['bias_attr'] = bias_attr + other_kwargs['layer_attr'] = layer_attr + + Layer.__init__(self, name, self.__parent_layers__) + self.__other_kwargs__ = other_kwargs + + def __iadd__(self, other): + if not self.finalized: + self.__parent_layers__[self.input_name].append(other) + return self + else: + raise MixedLayerTypeV2.AddToSealedMixedLayerExceptionV2() + + def __enter__(self): + assert len(self.__parent_layers__[self.input_name]) == 0 + return self + + def __exit__(self, *args, **kwargs): + self.finalized = True + + def to_proto_impl(self, **kwargs): + args = dict() + for each in kwargs: + args[each] = kwargs[each] + for each in self.__other_kwargs__: + args[each] = self.__other_kwargs__[each] + return getattr(conf_helps, self.__method_name__)(name=self.name, **args) + + +@wrap_name_default("mixed") +@wrap_act_default(act=conf_helps.LinearActivation()) +@wrap_bias_attr_default(has_bias=False) +@layer_support(conf_helps.layers.ERROR_CLIPPING, conf_helps.layers.DROPOUT) +def mixed(size=0, + name=None, + input=None, + act=None, + bias_attr=False, + layer_attr=None): + return MixedLayerV2(size, input, name, act, bias_attr, layer_attr) + + data = DataLayerV2 fc = __convert_to_v2__('fc_layer', name_prefix='fc', parent_names=['input']) max_id = __convert_to_v2__( @@ -226,12 +325,124 @@ def to_proto_impl(self, **kwargs): huber_cost = __convert_to_v2__( 'huber_cost', name_prefix='huber_cost', parent_names=['input', 'label']) -if __name__ == '__main__': - pixel = data(name='pixel', type=data_type.dense_vector(784)) - label = data(name='label', type=data_type.integer_value(10)) - weight = data(name='weight', type=data_type.dense_vector(10)) - score = data(name='score', type=data_type.dense_vector(1)) +# convert projection +projection_list = [ + # [V1_method_name], all the parent_names is `input` + 'full_matrix_projection', + 'trans_full_matrix_projection', + 'table_projection', + 'scaling_projection', + 'dotmul_projection', + 'context_projection', + 'conv_projection', + 'identity_projection', +] +for prj in projection_list: + globals()[prj] = __convert_to_v2__(prj, parent_names=['input']) + +# convert operator +operator_list = [ + # [V1_method_name, parent_names], + ['dotmul_operator', ['a', 'b']], + ['conv_operator', ['img', 'filter']] +] +for op in operator_list: + globals()[op[0]] = __convert_to_v2__(op[0], parent_names=op[1]) + +def test_projection(): + """ + TODO: move to tests file + """ + input = data(name='data', type=data_type.dense_vector(784)) + word = data(name='word', type=data_type.integer_value_sequence(10000)) + fc0 = fc(input=input, size=100, act=conf_helps.SigmoidActivation()) + fc1 = fc(input=input, size=200, act=conf_helps.SigmoidActivation()) + mixed0 = mixed( + size=256, + input=[ + full_matrix_projection(input=fc0), full_matrix_projection(input=fc1) + ]) + with mixed(size=200) as mixed1: + mixed1 += full_matrix_projection(input=fc0) + mixed1 += identity_projection(input=fc1) + + table = table_projection(input=word) + emb0 = mixed(size=512, input=table) + with mixed(size=512) as emb1: + emb1 += table + + scale = scaling_projection(input=fc0) + scale0 = mixed(size=100, input=scale) + with mixed(size=100) as scale1: + scale1 += scale + + dotmul = dotmul_projection(input=fc0) + dotmul0 = mixed(size=100, input=dotmul) + with mixed(size=100) as dotmul1: + dotmul1 += dotmul + + context = context_projection(input=fc0, context_len=5) + context0 = mixed(size=100, input=context) + with mixed(size=100) as context1: + context1 += context + + conv = conv_projection( + input=input, + filter_size=1, + num_channels=1, + num_filters=128, + stride=1, + padding=0) + conv0 = mixed(input=conv, bias_attr=True) + with mixed(bias_attr=True) as conv1: + conv1 += conv + + print parse_network(mixed0) + print parse_network(mixed1) + print parse_network(emb0) + print parse_network(emb1) + print parse_network(scale0) + print parse_network(scale1) + print parse_network(dotmul0) + print parse_network(dotmul1) + print parse_network(conv0) + print parse_network(conv1) + + +def test_operator(): + """ + TODO: move to tests file + """ + ipt0 = data(name='data', type=data_type.dense_vector(784)) + ipt1 = data(name='word', type=data_type.dense_vector(128)) + fc0 = fc(input=ipt0, size=100, act=conf_helps.SigmoidActivation()) + fc1 = fc(input=ipt0, size=100, act=conf_helps.SigmoidActivation()) + + dotmul_op = dotmul_operator(a=fc0, b=fc1) + dotmul0 = mixed(input=dotmul_op) + with mixed() as dotmul1: + dotmul1 += dotmul_op + + conv = conv_operator( + img=ipt0, + filter=ipt1, + filter_size=1, + num_channels=1, + num_filters=128, + stride=1, + padding=0) + conv0 = mixed(input=conv) + with mixed() as conv1: + conv1 += conv + + print parse_network(dotmul0) + print parse_network(dotmul1) + print parse_network(conv0) + print parse_network(conv1) + + +def test_cost(pixel, label, weight, score): hidden = fc(input=pixel, size=100, act=activation.Sigmoid(), @@ -255,3 +466,14 @@ def to_proto_impl(self, **kwargs): print parse_network(cost5, cost6) print parse_network(cost7, cost8, cost9, cost10, cost11) print parse_network(inference, maxid) + + +if __name__ == '__main__': + pixel = data(name='pixel', type=data_type.dense_vector(784)) + label = data(name='label', type=data_type.integer_value(10)) + weight = data(name='weight', type=data_type.dense_vector(10)) + score = data(name='score', type=data_type.dense_vector(1)) + + test_cost(pixel, label, weight, score) + test_projection() + test_operator() From 9b73a602c4aa553888b450373eb31a5a9703c227 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Fri, 24 Feb 2017 19:23:24 +0800 Subject: [PATCH 302/370] remove comments --- python/paddle/v2/layer.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 0e9e2a249ddb3a..618a220240c15d 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -71,6 +71,7 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. import paddle.trainer_config_helpers as conf_helps from paddle.trainer_config_helpers.config_parser_utils import \ parse_network_config as __parse__ + from paddle.trainer_config_helpers.default_decorators import wrap_name_default from paddle.trainer_config_helpers.default_decorators import wrap_act_default from paddle.trainer_config_helpers.default_decorators import wrap_bias_attr_default @@ -80,8 +81,6 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. import activation import attr -#import pudb;pudb.set_trace() - __all__ = [ 'parse_network', 'data', From 4c85f955d78674a3803fab56c5dfd095bc6fde2b Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Fri, 24 Feb 2017 20:47:01 +0800 Subject: [PATCH 303/370] move test module --- python/paddle/v2/layer.py | 129 --------------------------- python/paddle/v2/tests/test_layer.py | 92 ++++++++++++++++++- 2 files changed, 90 insertions(+), 131 deletions(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 618a220240c15d..a3fac6ca67d280 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -347,132 +347,3 @@ def mixed(size=0, ] for op in operator_list: globals()[op[0]] = __convert_to_v2__(op[0], parent_names=op[1]) - - -def test_projection(): - """ - TODO: move to tests file - """ - input = data(name='data', type=data_type.dense_vector(784)) - word = data(name='word', type=data_type.integer_value_sequence(10000)) - fc0 = fc(input=input, size=100, act=conf_helps.SigmoidActivation()) - fc1 = fc(input=input, size=200, act=conf_helps.SigmoidActivation()) - mixed0 = mixed( - size=256, - input=[ - full_matrix_projection(input=fc0), full_matrix_projection(input=fc1) - ]) - with mixed(size=200) as mixed1: - mixed1 += full_matrix_projection(input=fc0) - mixed1 += identity_projection(input=fc1) - - table = table_projection(input=word) - emb0 = mixed(size=512, input=table) - with mixed(size=512) as emb1: - emb1 += table - - scale = scaling_projection(input=fc0) - scale0 = mixed(size=100, input=scale) - with mixed(size=100) as scale1: - scale1 += scale - - dotmul = dotmul_projection(input=fc0) - dotmul0 = mixed(size=100, input=dotmul) - with mixed(size=100) as dotmul1: - dotmul1 += dotmul - - context = context_projection(input=fc0, context_len=5) - context0 = mixed(size=100, input=context) - with mixed(size=100) as context1: - context1 += context - - conv = conv_projection( - input=input, - filter_size=1, - num_channels=1, - num_filters=128, - stride=1, - padding=0) - conv0 = mixed(input=conv, bias_attr=True) - with mixed(bias_attr=True) as conv1: - conv1 += conv - - print parse_network(mixed0) - print parse_network(mixed1) - print parse_network(emb0) - print parse_network(emb1) - print parse_network(scale0) - print parse_network(scale1) - print parse_network(dotmul0) - print parse_network(dotmul1) - print parse_network(conv0) - print parse_network(conv1) - - -def test_operator(): - """ - TODO: move to tests file - """ - ipt0 = data(name='data', type=data_type.dense_vector(784)) - ipt1 = data(name='word', type=data_type.dense_vector(128)) - fc0 = fc(input=ipt0, size=100, act=conf_helps.SigmoidActivation()) - fc1 = fc(input=ipt0, size=100, act=conf_helps.SigmoidActivation()) - - dotmul_op = dotmul_operator(a=fc0, b=fc1) - dotmul0 = mixed(input=dotmul_op) - with mixed() as dotmul1: - dotmul1 += dotmul_op - - conv = conv_operator( - img=ipt0, - filter=ipt1, - filter_size=1, - num_channels=1, - num_filters=128, - stride=1, - padding=0) - conv0 = mixed(input=conv) - with mixed() as conv1: - conv1 += conv - - print parse_network(dotmul0) - print parse_network(dotmul1) - print parse_network(conv0) - print parse_network(conv1) - - -def test_cost(pixel, label, weight, score): - hidden = fc(input=pixel, - size=100, - act=activation.Sigmoid(), - param_attr=attr.Param(name='hidden')) - inference = fc(input=hidden, size=10, act=activation.Softmax()) - maxid = max_id(input=inference) - cost1 = classification_cost(input=inference, label=label) - cost2 = classification_cost(input=inference, label=label, weight=weight) - cost3 = cross_entropy_cost(input=inference, label=label) - cost4 = cross_entropy_with_selfnorm_cost(input=inference, label=label) - cost5 = regression_cost(input=inference, label=label) - cost6 = regression_cost(input=inference, label=label, weight=weight) - cost7 = multi_binary_label_cross_entropy_cost(input=inference, label=label) - cost8 = rank_cost(left=score, right=score, label=score) - cost9 = lambda_cost(input=inference, score=score) - cost10 = sum_cost(input=inference) - cost11 = huber_cost(input=score, label=label) - - print parse_network(cost1, cost2) - print parse_network(cost3, cost4) - print parse_network(cost5, cost6) - print parse_network(cost7, cost8, cost9, cost10, cost11) - print parse_network(inference, maxid) - - -if __name__ == '__main__': - pixel = data(name='pixel', type=data_type.dense_vector(784)) - label = data(name='label', type=data_type.integer_value(10)) - weight = data(name='weight', type=data_type.dense_vector(10)) - score = data(name='score', type=data_type.dense_vector(1)) - - test_cost(pixel, label, weight, score) - test_projection() - test_operator() diff --git a/python/paddle/v2/tests/test_layer.py b/python/paddle/v2/tests/test_layer.py index b600e8cf765122..521bc8b40c5b6b 100644 --- a/python/paddle/v2/tests/test_layer.py +++ b/python/paddle/v2/tests/test_layer.py @@ -19,8 +19,6 @@ import paddle.v2.attr as attr import paddle.v2.data_type as data_type import paddle.v2.layer as layer -from paddle.trainer_config_helpers.config_parser_utils import \ - parse_network_config as parse_network pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) label = layer.data(name='label', type=data_type.integer_value(10)) @@ -58,6 +56,96 @@ def test_cost_layer(self): #print layer.parse_network(cost5, cost6) #print layer.parse_network(cost7, cost8, cost9, cost10, cost11) + def test_projection(self): + input = layer.data(name='data', type=data_type.dense_vector(784)) + word = layer.data( + name='word', type=data_type.integer_value_sequence(10000)) + fc0 = layer.fc(input=input, + size=100, + act=conf_helps.SigmoidActivation()) + fc1 = layer.fc(input=input, + size=200, + act=conf_helps.SigmoidActivation()) + mixed0 = layer.mixed( + size=256, + input=[ + layer.full_matrix_projection(input=fc0), + layer.full_matrix_projection(input=fc1) + ]) + with layer.mixed(size=200) as mixed1: + mixed1 += layer.full_matrix_projection(input=fc0) + mixed1 += layer.identity_projection(input=fc1) + + table = layer.table_projection(input=word) + emb0 = layer.mixed(size=512, input=table) + with layer.mixed(size=512) as emb1: + emb1 += table + + scale = layer.scaling_projection(input=fc0) + scale0 = layer.mixed(size=100, input=scale) + with layer.mixed(size=100) as scale1: + scale1 += scale + + dotmul = layer.dotmul_projection(input=fc0) + dotmul0 = layer.mixed(size=100, input=dotmul) + with layer.mixed(size=100) as dotmul1: + dotmul1 += dotmul + + context = layer.context_projection(input=fc0, context_len=5) + context0 = layer.mixed(size=100, input=context) + with layer.mixed(size=100) as context1: + context1 += context + + conv = layer.conv_projection( + input=input, + filter_size=1, + num_channels=1, + num_filters=128, + stride=1, + padding=0) + conv0 = layer.mixed(input=conv, bias_attr=True) + with layer.mixed(bias_attr=True) as conv1: + conv1 += conv + + print layer.parse_network(mixed0) + print layer.parse_network(mixed1) + print layer.parse_network(emb0) + print layer.parse_network(emb1) + print layer.parse_network(scale0) + print layer.parse_network(scale1) + print layer.parse_network(dotmul0) + print layer.parse_network(dotmul1) + print layer.parse_network(conv0) + print layer.parse_network(conv1) + + def test_operator(self): + ipt0 = layer.data(name='data', type=data_type.dense_vector(784)) + ipt1 = layer.data(name='word', type=data_type.dense_vector(128)) + fc0 = layer.fc(input=ipt0, size=100, act=conf_helps.SigmoidActivation()) + fc1 = layer.fc(input=ipt0, size=100, act=conf_helps.SigmoidActivation()) + + dotmul_op = layer.dotmul_operator(a=fc0, b=fc1) + dotmul0 = layer.mixed(input=dotmul_op) + with layer.mixed() as dotmul1: + dotmul1 += dotmul_op + + conv = layer.conv_operator( + img=ipt0, + filter=ipt1, + filter_size=1, + num_channels=1, + num_filters=128, + stride=1, + padding=0) + conv0 = layer.mixed(input=conv) + with layer.mixed() as conv1: + conv1 += conv + + print layer.parse_network(dotmul0) + print layer.parse_network(dotmul1) + print layer.parse_network(conv0) + print layer.parse_network(conv1) + if __name__ == '__main__': unittest.main() From bb7db754208a7484ced25eb879bd77e7f6fae6c9 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Sat, 25 Feb 2017 10:07:15 +0800 Subject: [PATCH 304/370] add testing for duplicate item --- python/paddle/v2/tests/test_data_feeder.py | 23 +++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/python/paddle/v2/tests/test_data_feeder.py b/python/paddle/v2/tests/test_data_feeder.py index 4d5df6e8931640..5f67da6a5b32d7 100644 --- a/python/paddle/v2/tests/test_data_feeder.py +++ b/python/paddle/v2/tests/test_data_feeder.py @@ -176,7 +176,7 @@ def test_multiple_features(self): self.assertEqual(output_sparse.getSparseRowCols(i), data[i][1]) self.assertEqual(output_index[i], data[i][0]) - # reader returns 3 featreus, but only use 2 features + # reader returns 3 features, but only use 2 features data_types = [('fea0', data_type.dense_vector(100)), ('fea2', data_type.integer_value(10))] feeder = DataFeeder(data_types, {'fea0': 2, 'fea2': 0}) @@ -187,6 +187,27 @@ def test_multiple_features(self): self.assertEqual(output_dense[i].all(), data[i][2].all()) self.assertEqual(output_index[i], data[i][0]) + # reader returns 3 featreus, one is duplicate data + data_types = [('fea0', data_type.dense_vector(100)), + ('fea1', data_type.sparse_binary_vector(20000)), + ('fea2', data_type.integer_value(10)), + ('fea3', data_type.dense_vector(100))] + feeder = DataFeeder(data_types, + {'fea0': 2, + 'fea1': 1, + 'fea2': 0, + 'fea3': 2}) + arg = feeder(data) + fea0 = arg.getSlotValue(0).copyToNumpyMat() + fea1 = arg.getSlotValue(1) + fea2 = arg.getSlotIds(2).copyToNumpyArray() + fea3 = arg.getSlotValue(3).copyToNumpyMat() + for i in xrange(batch_size): + self.assertEqual(fea0[i].all(), data[i][2].all()) + self.assertEqual(fea1.getSparseRowCols(i), data[i][1]) + self.assertEqual(fea2[i], data[i][0]) + self.assertEqual(fea3[i].all(), data[i][2].all()) + def test_multiple_features_tuple(self): batch_size = 2 data = [] From a6028d79dcaba69f6f95c7ebf9c12c33ad42b82e Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 10:39:17 +0800 Subject: [PATCH 305/370] Clean mnist reader --- python/paddle/v2/data_set/mnist.py | 35 +++++++++--------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/python/paddle/v2/data_set/mnist.py b/python/paddle/v2/data_set/mnist.py index 6f35acf683686e..4b392af400ad31 100644 --- a/python/paddle/v2/data_set/mnist.py +++ b/python/paddle/v2/data_set/mnist.py @@ -15,39 +15,24 @@ def reader(): return reader -class MNIST(object): - """ - mnist dataset reader. The `train_reader` and `test_reader` method returns - a iterator of each sample. Each sample is combined by 784-dim float and a - one-dim label - """ +TEST_SIZE = 10000 - def __init__(self, random_state=0, test_size=10000, **options): - data = sklearn.datasets.mldata.fetch_mldata( - "MNIST original", data_home=DATA_HOME) - self.X_train, self.X_test, self.y_train, self.y_test = sklearn.model_selection.train_test_split( - data.data, - data.target, - test_size=test_size, - random_state=random_state, - **options) +data = sklearn.datasets.mldata.fetch_mldata( + "MNIST original", data_home=DATA_HOME) +X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split( + data.data, data.target, test_size=TEST_SIZE, random_state=0) - def train_creator(self): - return __mnist_reader_creator__(self.X_train, self.y_train) - def test_creator(self): - return __mnist_reader_creator__(self.X_test, self.y_test) +def train_creator(): + return __mnist_reader_creator__(X_train, y_train) -__default_instance__ = MNIST() -train_creator = __default_instance__.train_creator -test_creator = __default_instance__.test_creator +def test_creator(): + return __mnist_reader_creator__(X_test, y_test) def unittest(): - size = 12045 - mnist = MNIST(test_size=size) - assert len(list(mnist.test_creator()())) == size + assert len(list(test_creator()())) == TEST_SIZE if __name__ == '__main__': From 173a81b56b60567eb4e30f66331ebab4e004ead7 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 23 Feb 2017 16:01:20 +0800 Subject: [PATCH 306/370] Complete Event, Add Metric to Event. --- demo/mnist/api_train_v2.py | 14 ++++------ python/paddle/v2/event.py | 55 +++++++++++++++++++++++++++++++++---- python/paddle/v2/trainer.py | 22 +++++++++++++-- 3 files changed, 75 insertions(+), 16 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 6fc01ce58be57c..6b0cfa0b05c966 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -27,19 +27,14 @@ def main(): 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()) - + if event.batch_id % 100 == 0: + print "Pass %d, Batch %d, Cost %f, %s" % ( + event.pass_id, event.batch_id, event.cost, event.metrics) else: pass @@ -49,7 +44,8 @@ def event_handler(event): topology=cost, parameters=parameters, event_handler=event_handler, - batch_size=32, # batch size should be refactor in Data reader + num_passes=100, + batch_size=200, # batch size should be refactor in Data reader data_types={ # data_types will be removed, It should be in # network topology 'pixel': images.type, diff --git a/python/paddle/v2/event.py b/python/paddle/v2/event.py index a16cfa91f062a6..835e28e6218df2 100644 --- a/python/paddle/v2/event.py +++ b/python/paddle/v2/event.py @@ -3,8 +3,6 @@ There are: -* BeginTraining -* EndTraining * BeginIteration * EndIteration * BeginPass @@ -12,15 +10,62 @@ TODO(yuyang18): Complete it! """ -__all__ = ['EndIteration'] +import py_paddle.swig_paddle as api +__all__ = ['EndIteration', 'BeginIteration', 'BeginPass', 'EndPass'] -class EndIteration(object): +class WithMetric(object): + def __init__(self, evaluator): + if not isinstance(evaluator, api.Evaluator): + raise TypeError("Evaluator should be api.Evaluator type") + self.__evaluator__ = evaluator + + @property + def metrics(self): + names = self.__evaluator__.getNames() + retv = dict() + for each_name in names: + val = self.__evaluator__.getValue(each_name) + retv[each_name] = val + return retv + + +class BeginPass(object): + """ + Event On One Pass Training Start. + """ + + def __init__(self, pass_id): + self.pass_id = pass_id + + +class EndPass(WithMetric): + """ + Event On One Pass Training Complete. + """ + + def __init__(self, pass_id, evaluator): + self.pass_id = pass_id + WithMetric.__init__(self, evaluator) + + +class BeginIteration(object): + """ + Event On One Batch Training Start. + """ + + def __init__(self, pass_id, batch_id): + self.pass_id = pass_id + self.batch_id = batch_id + + +class EndIteration(WithMetric): """ Event On One Batch Training Complete. """ - def __init__(self, pass_id, batch_id, cost): + def __init__(self, pass_id, batch_id, cost, evaluator): self.pass_id = pass_id self.batch_id = batch_id self.cost = cost + WithMetric.__init__(self, evaluator) diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 4365bd41e7073b..0acfcee2cee9ee 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -96,11 +96,15 @@ def train(self, topology, api.CREATE_MODE_NORMAL, self.__optimizer__.enable_types()) assert isinstance(gm, api.GradientMachine) parameters.append_gradient_machine(gm) - + gm.randParameters() updater = self.__optimizer__.create_local_updater() updater.init(gm) gm.start() + batch_evaluator = gm.makeEvaluator() + assert isinstance(batch_evaluator, api.Evaluator) + pass_evaluator = gm.makeEvaluator() + assert isinstance(pass_evaluator, api.Evaluator) out_args = api.Arguments.createArguments(0) data_types_lists = [] @@ -112,12 +116,20 @@ def train(self, converter = DataProviderConverter(input_types=data_types_lists) for pass_id in xrange(num_passes): + event_handler(v2_event.BeginPass(pass_id)) + pass_evaluator.start() updater.startPass() for batch_id, data_batch in enumerate( __data_reader_to_batch__(train_data_reader, batch_size, topology)): + batch_evaluator.start() + event_handler( + v2_event.BeginIteration( + pass_id=pass_id, batch_id=batch_id)) pass_type = updater.startBatch(len(data_batch)) gm.forwardBackward(converter(data_batch), out_args, pass_type) + gm.eval(pass_evaluator) + gm.eval(batch_evaluator) for each_param in gm.getParameters(): updater.update(each_param) # Get cost. We use numpy to calculate total cost for this batch. @@ -125,11 +137,17 @@ def train(self, cost_vec = cost_vec.copyToNumpyMat() cost = cost_vec.sum() / len(data_batch) updater.finishBatch(cost) + batch_evaluator.finish() event_handler( v2_event.EndIteration( - pass_id=pass_id, batch_id=batch_id, cost=cost)) + pass_id=pass_id, + batch_id=batch_id, + cost=cost, + evaluator=batch_evaluator)) updater.finishPass() + pass_evaluator.finish() + event_handler(v2_event.EndPass(pass_id, evaluator=pass_evaluator)) gm.finish() From 72c1327832b1b75057a19d98387546bb2f765ff4 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Mon, 27 Feb 2017 13:28:36 +0800 Subject: [PATCH 307/370] follow comments --- python/paddle/v2/data_feeder.py | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/python/paddle/v2/data_feeder.py b/python/paddle/v2/data_feeder.py index 74ee112f46efd7..632f1760ab5ff2 100644 --- a/python/paddle/v2/data_feeder.py +++ b/python/paddle/v2/data_feeder.py @@ -62,8 +62,8 @@ def __init__(self, data_types, reader_dict): self.reader_dict = reader_dict for each in data_types: self.input_names.append(each[0]) - self.input_types.append(each[1]) assert isinstance(each[1], data_type.InputType) + self.input_types.append(each[1]) DataProviderConverter.__init__(self, self.input_types) def convert(self, dat, argument=None): @@ -88,24 +88,16 @@ def convert(self, dat, argument=None): :type argument: swig_paddle.Arguments """ - if argument is None: - argument = swig_paddle.Arguments.createArguments(0) - assert isinstance(argument, swig_paddle.Arguments) - argument.resize(len(self.input_types)) - - scanners = [ - DataProviderConverter.create_scanner(i, each_type) - for i, each_type in enumerate(self.input_types) - ] - - for each_sample in dat: - for name, scanner in zip(self.input_names, scanners): - scanner.scan(each_sample[self.reader_dict[name]]) - - for scanner in scanners: - scanner.finish_scan(argument) + def reorder_data(data): + retv = [] + for each in data: + reorder = [] + for name in self.input_names: + reorder.append(each[self.reader_dict[name]]) + retv.append(reorder) + return retv - return argument + return DataProviderConverter.convert(self, reorder_data(dat), argument) def __call__(self, dat, argument=None): return self.convert(dat, argument) From aa92f0b673906edd3b585d5db645c0a3e075cc06 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Mon, 27 Feb 2017 10:32:30 +0800 Subject: [PATCH 308/370] follow comments --- python/paddle/v2/layer.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index a3fac6ca67d280..b9400ab26bdee2 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -105,6 +105,13 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. 'conv_projection', ] +__projection_names__ = filter(lambda x: x.endswith('_projection'), + dir(conf_helps)) +__all__ += __projection_names__ + +__operator_names__ = filter(lambda x: x.endswith('_operator'), dir(conf_helps)) +__all__ += __operator_names__ + def parse_network(*outputs): """ @@ -224,8 +231,7 @@ class MixedLayerV2(Layer): """ class AddToSealedMixedLayerExceptionV2(Exception): - def __init__(self): - Exception.__init__(self) + pass def __init__(self, size=0, @@ -277,7 +283,7 @@ def to_proto_impl(self, **kwargs): @wrap_name_default("mixed") -@wrap_act_default(act=conf_helps.LinearActivation()) +@wrap_act_default(act=activation.Linear()) @wrap_bias_attr_default(has_bias=False) @layer_support(conf_helps.layers.ERROR_CLIPPING, conf_helps.layers.DROPOUT) def mixed(size=0, From 5d7e7bc042e3118e9cf4a1899bc08dd44a1cf34c Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Mon, 27 Feb 2017 13:37:53 +0800 Subject: [PATCH 309/370] add test_layer for v2 --- python/paddle/v2/layer.py | 126 --------------------------- python/paddle/v2/tests/test_layer.py | 122 ++++++++++++++++++++++++-- 2 files changed, 115 insertions(+), 133 deletions(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index f4a85e9d038e45..f0e4f972feb260 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -74,9 +74,6 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. from paddle.trainer_config_helpers.default_decorators import wrap_name_default import data_type -import activation -import attr -import pooling __all__ = [ 'parse_network', 'data', 'fc', 'conv_shift', 'img_conv', 'img_pool', 'spp', @@ -277,126 +274,3 @@ def to_proto_impl(self, **kwargs): ] for l in layer_list: globals()[l[0]] = __convert_to_v2__(l[1], l[2]) - -if __name__ == '__main__': - pixel = data(name='pixel', type=data_type.dense_vector(128)) - label = data(name='label', type=data_type.integer_value(10)) - weight = data(name='weight', type=data_type.dense_vector(10)) - word = data(name='word', type=data_type.integer_value(12)) - score = data(name='score', type=data_type.dense_vector(1)) - - hidden = fc(input=pixel, - size=100, - act=activation.Sigmoid(), - param_attr=attr.Param(name='hidden')) - inference = fc(input=hidden, size=10, act=activation.Softmax()) - print parse_network(inference) - - # test conv layers - conv1 = conv_shift(a=pixel, b=score) - conv2 = img_conv( - input=pixel, - filter_size=1, - filter_size_y=1, - num_channels=8, - num_filters=16, - act=activation.Linear()) - print parse_network(conv1, conv2) - - # test image pooling layers - maxpool = img_pool( - input=conv2, - pool_size=2, - num_channels=16, - padding=1, - pool_type=pooling.Max()) - spp = spp(input=conv2, - pyramid_height=2, - num_channels=16, - pool_type=pooling.Max()) - maxout = maxout(input=conv2, num_channels=16, groups=4) - print parse_network(maxpool, spp, maxout) - - # test norm layers - norm1 = img_cmrnorm(input=maxpool, size=5) - norm2 = batch_norm(input=maxpool) - norm3 = sum_to_one_norm(input=maxpool) - print parse_network(norm1, norm2, norm3) - - # test recurrent layers - recurrent = recurrent(input=word) - lstm = lstmemory(input=word) - gru = grumemory(input=word) - print parse_network(recurrent, lstm, gru) - - # test aggregate layers - pool = pool( - input=pixel, - pooling_type=pooling.Avg(), - agg_level=AggregateLevel.EACH_SEQUENCE) - last_seq = last_seq(input=pixel) - first_seq = first_seq(input=pixel) - concat = concat(input=[last_seq, first_seq]) - seq_concat = seq_concat(a=last_seq, b=first_seq) - print parse_network(pool, last_seq, first_seq, concat, seq_concat) - - # test reshaping layers - block_expand = block_expand( - input=maxout, num_channels=4, stride_x=1, block_x=1) - expand = expand( - input=last_seq, expand_as=pixel, expand_level=ExpandLevel.FROM_TIMESTEP) - repeat = repeat(input=last_seq, num_repeats=4) - reshape = seq_reshape(input=last_seq, reshape_size=4) - rotate = rotate(input=pixel, height=16, width=49) - print parse_network(block_expand, expand, repeat, reshape, rotate) - - # test math layers - addto = addto(input=[last_seq, first_seq]) - linear_comb = linear_comb(weights=weight, vectors=hidden, size=10) - interpolation = interpolation(input=[hidden, hidden], weight=score) - bilinear = bilinear_interp(input=conv2, out_size_x=4, out_size_y=4) - power = power(input=conv1, weight=score) - scaling = scaling(input=conv1, weight=score) - slope = slope_intercept(input=conv1) - tensor = tensor(a=last_seq, b=first_seq, size=1000) - cos_sim = cos_sim(a=last_seq, b=first_seq) - trans = trans(input=tensor) - print parse_network(addto, linear_comb, interpolation, bilinear, power, - scaling, slope, tensor, cos_sim, trans) - - # test sampling layers - maxid = max_id(input=inference) - sampling_id = sampling_id(input=inference) - print parse_network(maxid, sampling_id) - - # test slicing and joining layers - pad = pad(input=maxpool, pad_c=[2, 3], pad_h=[1, 2], pad_w=[3, 1]) - print parse_network(pad) - - # test cost layers - cost1 = classification_cost(input=inference, label=label) - cost2 = classification_cost(input=inference, label=label, weight=weight) - cost3 = cross_entropy_cost(input=inference, label=label) - cost4 = cross_entropy_with_selfnorm_cost(input=inference, label=label) - cost5 = regression_cost(input=inference, label=label) - cost6 = regression_cost(input=inference, label=label, weight=weight) - cost7 = multi_binary_label_cross_entropy_cost(input=inference, label=label) - cost8 = rank_cost(left=score, right=score, label=score) - cost9 = lambda_cost(input=inference, score=score) - cost10 = sum_cost(input=inference) - cost11 = huber_cost(input=score, label=label) - print parse_network(cost3, cost4) - print parse_network(cost5, cost6) - print parse_network(cost7, cost8, cost9, cost10, cost11) - - crf = crf(input=inference, label=label) - crf_decoding = crf_decoding(input=inference, size=3) - ctc = ctc(input=inference, label=label) - warp_ctc = warp_ctc(input=pixel, label=label) - nce = nce(input=inference, label=label, num_classes=3) - hsigmoid = hsigmoid(input=inference, label=label, num_classes=3) - print parse_network(crf, crf_decoding, ctc, warp_ctc, nce, hsigmoid) - - # test check layers - eos = eos(input=maxid, eos_id=5) - print parse_network(eos) diff --git a/python/paddle/v2/tests/test_layer.py b/python/paddle/v2/tests/test_layer.py index b600e8cf765122..2f139866e8096a 100644 --- a/python/paddle/v2/tests/test_layer.py +++ b/python/paddle/v2/tests/test_layer.py @@ -19,18 +19,106 @@ import paddle.v2.attr as attr import paddle.v2.data_type as data_type import paddle.v2.layer as layer +import paddle.v2.pooling as pooling from paddle.trainer_config_helpers.config_parser_utils import \ parse_network_config as parse_network -pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) +pixel = layer.data(name='pixel', type=data_type.dense_vector(128)) label = layer.data(name='label', type=data_type.integer_value(10)) weight = layer.data(name='weight', type=data_type.dense_vector(10)) score = layer.data(name='score', type=data_type.dense_vector(1)) + hidden = layer.fc(input=pixel, size=100, act=activation.Sigmoid(), param_attr=attr.Param(name='hidden')) inference = layer.fc(input=hidden, size=10, act=activation.Softmax()) +conv = layer.img_conv( + input=pixel, + filter_size=1, + filter_size_y=1, + num_channels=8, + num_filters=16, + act=activation.Linear()) + + +class ImageLayerTest(unittest.TestCase): + def test_conv_layer(self): + conv_shift = layer.conv_shift(a=pixel, b=score) + print layer.parse_network(conv, conv_shift) + + def test_pooling_layer(self): + maxpool = layer.img_pool( + input=conv, + pool_size=2, + num_channels=16, + padding=1, + pool_type=pooling.Max()) + spp = layer.spp(input=conv, + pyramid_height=2, + num_channels=16, + pool_type=pooling.Max()) + maxout = layer.maxout(input=conv, num_channels=16, groups=4) + print layer.parse_network(maxpool, spp, maxout) + + def test_norm_layer(self): + norm1 = layer.img_cmrnorm(input=conv, size=5) + norm2 = layer.batch_norm(input=conv) + norm3 = layer.sum_to_one_norm(input=conv) + print layer.parse_network(norm1, norm2, norm3) + + +class AggregateLayerTest(unittest.TestCase): + def test_aggregate_layer(self): + pool = layer.pool( + input=pixel, + pooling_type=pooling.Avg(), + agg_level=layer.AggregateLevel.EACH_SEQUENCE) + last_seq = layer.last_seq(input=pixel) + first_seq = layer.first_seq(input=pixel) + concat = layer.concat(input=[last_seq, first_seq]) + seq_concat = layer.seq_concat(a=last_seq, b=first_seq) + print layer.parse_network(pool, last_seq, first_seq, concat, seq_concat) + + +class MathLayerTest(unittest.TestCase): + def test_math_layer(self): + addto = layer.addto(input=[pixel, pixel]) + linear_comb = layer.linear_comb(weights=weight, vectors=hidden, size=10) + interpolation = layer.interpolation( + input=[hidden, hidden], weight=score) + bilinear = layer.bilinear_interp(input=conv, out_size_x=4, out_size_y=4) + power = layer.power(input=pixel, weight=score) + scaling = layer.scaling(input=pixel, weight=score) + slope = layer.slope_intercept(input=pixel) + tensor = layer.tensor(a=pixel, b=pixel, size=1000) + cos_sim = layer.cos_sim(a=pixel, b=pixel) + trans = layer.trans(input=tensor) + print layer.parse_network(addto, linear_comb, interpolation, power, + scaling, slope, tensor, cos_sim, trans) + + +class ReshapeLayerTest(unittest.TestCase): + def test_reshape_layer(self): + block_expand = layer.block_expand( + input=conv, num_channels=4, stride_x=1, block_x=1) + expand = layer.expand( + input=weight, + expand_as=pixel, + expand_level=layer.ExpandLevel.FROM_TIMESTEP) + repeat = layer.repeat(input=pixel, num_repeats=4) + reshape = layer.seq_reshape(input=pixel, reshape_size=4) + rotate = layer.rotate(input=pixel, height=16, width=49) + print layer.parse_network(block_expand, expand, repeat, reshape, rotate) + + +class RecurrentLayerTest(unittest.TestCase): + def test_recurrent_layer(self): + word = layer.data(name='word', type=data_type.integer_value(12)) + recurrent = layer.recurrent(input=word) + lstm = layer.lstmemory(input=word) + gru = layer.grumemory(input=word) + print layer.parse_network(recurrent, lstm, gru) class CostLayerTest(unittest.TestCase): @@ -51,12 +139,32 @@ def test_cost_layer(self): cost10 = layer.sum_cost(input=inference) cost11 = layer.huber_cost(input=score, label=label) - print dir(layer) - layer.parse_network(cost1, cost2) - print dir(layer) - #print layer.parse_network(cost3, cost4) - #print layer.parse_network(cost5, cost6) - #print layer.parse_network(cost7, cost8, cost9, cost10, cost11) + print layer.parse_network(cost1, cost2) + print layer.parse_network(cost3, cost4) + print layer.parse_network(cost5, cost6) + print layer.parse_network(cost7, cost8, cost9, cost10, cost11) + + crf = layer.crf(input=inference, label=label) + crf_decoding = layer.crf_decoding(input=inference, size=3) + ctc = layer.ctc(input=inference, label=label) + warp_ctc = layer.warp_ctc(input=pixel, label=label) + nce = layer.nce(input=inference, label=label, num_classes=3) + hsigmoid = layer.hsigmoid(input=inference, label=label, num_classes=3) + + print layer.parse_network(crf, crf_decoding, ctc, warp_ctc, nce, + hsigmoid) + + +class OtherLayerTest(unittest.TestCase): + def test_sampling_layer(self): + maxid = layer.max_id(input=inference) + sampling_id = layer.sampling_id(input=inference) + eos = layer.eos(input=maxid, eos_id=5) + print layer.parse_network(maxid, sampling_id, eos) + + def test_slicing_joining_layer(self): + pad = layer.pad(input=conv, pad_c=[2, 3], pad_h=[1, 2], pad_w=[3, 1]) + print layer.parse_network(pad) if __name__ == '__main__': From bc074d0e581bb0804d11246c3d87ccaa1a5abc50 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Mon, 27 Feb 2017 13:43:41 +0800 Subject: [PATCH 310/370] minor change --- python/paddle/v2/data_feeder.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/python/paddle/v2/data_feeder.py b/python/paddle/v2/data_feeder.py index 632f1760ab5ff2..2a16d46dda47f8 100644 --- a/python/paddle/v2/data_feeder.py +++ b/python/paddle/v2/data_feeder.py @@ -58,13 +58,13 @@ def __init__(self, data_types, reader_dict): :type reader_dict: dict() """ self.input_names = [] - self.input_types = [] + input_types = [] self.reader_dict = reader_dict for each in data_types: self.input_names.append(each[0]) assert isinstance(each[1], data_type.InputType) - self.input_types.append(each[1]) - DataProviderConverter.__init__(self, self.input_types) + input_types.append(each[1]) + DataProviderConverter.__init__(self, input_types) def convert(self, dat, argument=None): """ @@ -98,6 +98,3 @@ def reorder_data(data): return retv return DataProviderConverter.convert(self, reorder_data(dat), argument) - - def __call__(self, dat, argument=None): - return self.convert(dat, argument) From a219455516f77b735c93621db16d26e8f230f5e7 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 13:45:47 +0800 Subject: [PATCH 311/370] Rise type error because of python. --- python/paddle/v2/trainer.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 023ab5e42d25b9..f65c631f7bfdd4 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -164,20 +164,20 @@ def __check_train_args__(train_data_reader, topology, parameters, """ if not callable(train_data_reader) or not isinstance(train_data_reader(), collections.Iterator): - raise ValueError('train_data_reader should be a function, ' - 'which can return a iterator') + raise TypeError('train_data_reader should be a function, ' + 'which can return a iterator') if test_data_reader is not None: if not callable(test_data_reader) or not isinstance( test_data_reader(), collections.Iterator): - raise ValueError('test_data_reader should be a function, which can ' - 'return a iterator') + raise TypeError('test_data_reader should be a function, which can ' + 'return a iterator') if not isinstance(topology, ModelConfig): - raise ValueError('topology should be a model config') + raise TypeError('topology should be a model config') if not isinstance(parameters, v2_parameters.Parameters): - raise ValueError('parameters should be a parameter pool') + raise TypeError('parameters should be a parameter pool') if not callable(event_handler): - raise ValueError('event handler should be a function') + raise TypeError('event handler should be a function') From c26431bacf25a6053999af791ab66d17d3c62c1b Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 14:03:34 +0800 Subject: [PATCH 312/370] Reordered package for feature usage. --- python/CMakeLists.txt | 4 +-- python/paddle/v2/__init__.py | 3 ++- python/paddle/v2/dataset/__init__.py | 3 +++ python/paddle/{ => v2}/reader/__init__.py | 0 python/paddle/{ => v2}/reader/creator.py | 0 python/paddle/{ => v2}/reader/decorator.py | 0 .../{ => v2}/reader/tests/CMakeLists.txt | 0 python/paddle/v2/reader/tests/__init__.py | 0 .../{ => v2}/reader/tests/creator_test.py | 10 ++++--- .../{ => v2}/reader/tests/decorator_test.py | 27 ++++++++++--------- .../reader/tests/test_data_creator.txt | 0 python/paddle/v2/trainer.py | 6 ++--- python/setup.py.in | 4 ++- 13 files changed, 33 insertions(+), 24 deletions(-) rename python/paddle/{ => v2}/reader/__init__.py (100%) rename python/paddle/{ => v2}/reader/creator.py (100%) rename python/paddle/{ => v2}/reader/decorator.py (100%) rename python/paddle/{ => v2}/reader/tests/CMakeLists.txt (100%) create mode 100644 python/paddle/v2/reader/tests/__init__.py rename python/paddle/{ => v2}/reader/tests/creator_test.py (89%) rename python/paddle/{ => v2}/reader/tests/decorator_test.py (81%) rename python/paddle/{ => v2}/reader/tests/test_data_creator.txt (100%) diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 71af50a9a4ed83..48e0a1993d07f8 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -4,7 +4,7 @@ set(OUTPUT_DIR file(GLOB TRAINER_PY_FILES . ./paddle/trainer/*.py) file(GLOB HELPERS_PY_FILES . ./paddle/trainer_config_helpers/*.py) file(GLOB UTILS_PY_FILES . ./paddle/utils/*.py) -file(GLOB V2_PY_FILES . ./paddle/v2/*.py) +file(GLOB_RECURSE V2_PY_FILES ./paddle/v2/ *.py) set(PY_FILES paddle/__init__.py ${TRAINER_PY_FILES} @@ -24,7 +24,7 @@ add_custom_target(paddle_python ALL DEPENDS ${OUTPUT_DIR}/.timestamp) add_subdirectory(paddle/trainer_config_helpers/tests) -add_subdirectory(paddle/reader/tests) +add_subdirectory(paddle/v2/reader/tests) add_subdirectory(paddle/v2/tests) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dist/ diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index 49d1983a2a422b..1122bcb5e45727 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -19,12 +19,13 @@ import event import data_type import data_feeder +from . import dataset import attr import py_paddle.swig_paddle as api __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', - 'event', 'data_type', 'attr', 'data_feeder' + 'event', 'data_type', 'attr', 'data_feeder', 'dataset' ] diff --git a/python/paddle/v2/dataset/__init__.py b/python/paddle/v2/dataset/__init__.py index e69de29bb2d1d6..9647e9850332b7 100644 --- a/python/paddle/v2/dataset/__init__.py +++ b/python/paddle/v2/dataset/__init__.py @@ -0,0 +1,3 @@ +import mnist + +__all__ = ['mnist'] diff --git a/python/paddle/reader/__init__.py b/python/paddle/v2/reader/__init__.py similarity index 100% rename from python/paddle/reader/__init__.py rename to python/paddle/v2/reader/__init__.py diff --git a/python/paddle/reader/creator.py b/python/paddle/v2/reader/creator.py similarity index 100% rename from python/paddle/reader/creator.py rename to python/paddle/v2/reader/creator.py diff --git a/python/paddle/reader/decorator.py b/python/paddle/v2/reader/decorator.py similarity index 100% rename from python/paddle/reader/decorator.py rename to python/paddle/v2/reader/decorator.py diff --git a/python/paddle/reader/tests/CMakeLists.txt b/python/paddle/v2/reader/tests/CMakeLists.txt similarity index 100% rename from python/paddle/reader/tests/CMakeLists.txt rename to python/paddle/v2/reader/tests/CMakeLists.txt diff --git a/python/paddle/v2/reader/tests/__init__.py b/python/paddle/v2/reader/tests/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/python/paddle/reader/tests/creator_test.py b/python/paddle/v2/reader/tests/creator_test.py similarity index 89% rename from python/paddle/reader/tests/creator_test.py rename to python/paddle/v2/reader/tests/creator_test.py index eda8ab6715b2be..9f8d7133b8694a 100644 --- a/python/paddle/reader/tests/creator_test.py +++ b/python/paddle/v2/reader/tests/creator_test.py @@ -11,17 +11,19 @@ # 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. +import os import unittest -import paddle.reader.creator + import numpy as np -import os + +import paddle.v2.reader.creator class TestNumpyArray(unittest.TestCase): def test_numpy_array(self): l = [[1, 2, 3], [4, 5, 6]] x = np.array(l, np.int32) - reader = paddle.reader.creator.np_array(x) + reader = paddle.v2.reader.creator.np_array(x) for idx, e in enumerate(reader()): self.assertItemsEqual(e, l[idx]) @@ -29,7 +31,7 @@ def test_numpy_array(self): class TestTextFile(unittest.TestCase): def test_text_file(self): path = os.path.join(os.path.dirname(__file__), "test_data_creator.txt") - reader = paddle.reader.creator.text_file(path) + reader = paddle.v2.reader.creator.text_file(path) for idx, e in enumerate(reader()): self.assertEqual(e, str(idx * 2) + " " + str(idx * 2 + 1)) diff --git a/python/paddle/reader/tests/decorator_test.py b/python/paddle/v2/reader/tests/decorator_test.py similarity index 81% rename from python/paddle/reader/tests/decorator_test.py rename to python/paddle/v2/reader/tests/decorator_test.py index 0396a61786539b..734154b9790a4d 100644 --- a/python/paddle/reader/tests/decorator_test.py +++ b/python/paddle/v2/reader/tests/decorator_test.py @@ -11,9 +11,10 @@ # 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. -import unittest -import paddle.reader import time +import unittest + +import paddle.v2.reader def reader_creator_10(dur): @@ -37,7 +38,7 @@ def read(): yield "h" yield "i" - r = paddle.reader.map_readers(tokenize, read) + r = paddle.v2.reader.map_readers(tokenize, read) for i, e in enumerate(r()): self.assertEqual(e, i) @@ -45,7 +46,7 @@ def read(): class TestBuffered(unittest.TestCase): def test_read(self): for size in range(20): - b = paddle.reader.buffered(reader_creator_10(0), size) + b = paddle.v2.reader.buffered(reader_creator_10(0), size) c = 0 for i in b(): self.assertEqual(i, c) @@ -54,7 +55,7 @@ def test_read(self): def test_buffering(self): # read have 30ms delay. - b = paddle.reader.buffered(reader_creator_10(0.03), 10) + b = paddle.v2.reader.buffered(reader_creator_10(0.03), 10) last_time = time.time() for idx, i in enumerate(b()): elapsed_time = time.time() - last_time @@ -68,17 +69,17 @@ def test_buffering(self): class TestCompose(unittest.TestCase): def test_compse(self): - reader = paddle.reader.compose( + reader = paddle.v2.reader.compose( reader_creator_10(0), reader_creator_10(0)) for idx, e in enumerate(reader()): self.assertEqual(e, (idx, idx)) def test_compose_not_aligned(self): total = 0 - reader = paddle.reader.compose( - paddle.reader.chain(reader_creator_10(0), reader_creator_10(0)), + reader = paddle.v2.reader.compose( + paddle.v2.reader.chain(reader_creator_10(0), reader_creator_10(0)), reader_creator_10(0)) - with self.assertRaises(paddle.reader.ComposeNotAligned): + with self.assertRaises(paddle.v2.reader.ComposeNotAligned): for e in reader(): total += 1 # expecting 10, not 20 @@ -86,8 +87,8 @@ def test_compose_not_aligned(self): def test_compose_not_aligned_no_check(self): total = 0 - reader = paddle.reader.compose( - paddle.reader.chain(reader_creator_10(0), reader_creator_10(0)), + reader = paddle.v2.reader.compose( + paddle.v2.reader.chain(reader_creator_10(0), reader_creator_10(0)), reader_creator_10(0), check_alignment=False) for e in reader(): @@ -98,7 +99,7 @@ def test_compose_not_aligned_no_check(self): class TestChain(unittest.TestCase): def test_chain(self): - c = paddle.reader.chain(reader_creator_10(0), reader_creator_10(0)) + c = paddle.v2.reader.chain(reader_creator_10(0), reader_creator_10(0)) idx = 0 for e in c(): self.assertEqual(e, idx % 10) @@ -111,7 +112,7 @@ def test_shuffle(self): case = [(0, True), (1, True), (10, False), (100, False)] a = reader_creator_10(0) for size, checkEq in case: - s = paddle.reader.shuffle(a, size) + s = paddle.v2.reader.shuffle(a, size) total = 0 for idx, e in enumerate(s()): if checkEq: diff --git a/python/paddle/reader/tests/test_data_creator.txt b/python/paddle/v2/reader/tests/test_data_creator.txt similarity index 100% rename from python/paddle/reader/tests/test_data_creator.txt rename to python/paddle/v2/reader/tests/test_data_creator.txt diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index f65c631f7bfdd4..89415787eb2e36 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -62,7 +62,7 @@ def __init__(self, update_equation): self.__optimizer__ = update_equation def train(self, - train_data_reader, + train_reader_creator, topology, parameters, num_passes=1, @@ -74,7 +74,7 @@ def train(self, """ Training method. Will train num_passes of input data. - :param train_data_reader: + :param train_reader_creator: :param topology: Network Topology, use one or more Layers to represent it. :param parameters: The parameter pools. :param num_passes: The total train passes. @@ -109,7 +109,7 @@ def train(self, for pass_id in xrange(num_passes): updater.startPass() for batch_id, data_batch in enumerate( - __data_reader_to_batch__(train_data_reader, batch_size, + __data_reader_to_batch__(train_reader_creator, batch_size, topology)): pass_type = updater.startBatch(len(data_batch)) gm.forwardBackward(feeder(data_batch), out_args, pass_type) diff --git a/python/setup.py.in b/python/setup.py.in index 1e1324eea825ab..68ca35265cf132 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -5,7 +5,9 @@ packages=['paddle', 'paddle.trainer', 'paddle.trainer_config_helpers', 'paddle.utils', - 'paddle.v2'] + 'paddle.v2', + 'paddle.v2.dataset', + 'paddle.v2.reader'] setup(name='paddle', version='${PADDLE_VERSION}', From 46d2ca575b98fef6d2506a66651c51400f189617 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 14:44:59 +0800 Subject: [PATCH 313/370] Combine Reader=>Feeder together. --- demo/mnist/api_train_v2.py | 38 +++++++++--------- python/paddle/v2/__init__.py | 3 +- python/paddle/v2/reader/decorator.py | 24 ++++++++++- python/paddle/v2/trainer.py | 59 +++++----------------------- 4 files changed, 52 insertions(+), 72 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 650bf392bbc734..67e36e6b201f38 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -1,15 +1,6 @@ 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) @@ -45,17 +36,24 @@ def event_handler(event): 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)], - reader_dict={'pixel':0, 'label':1} - ) + reader = paddle.reader.batched( + paddle.reader.shuffle( + paddle.dataset.mnist.train_creator(), buf_size=8192), + batch_size=32) + + trainer.train( + train_reader=paddle.reader.batched( + paddle.reader.shuffle(paddle.dataset.mnist.train_creator(), + buf_size=8192), batch_size=32), + topology=cost, + parameters=parameters, + event_handler=event_handler, + data_types=[ # data_types will be removed, It should be in + # network topology + ('pixel', images.type), + ('label', label.type)], + reader_dict={'pixel': 0, 'label': 1} + ) if __name__ == '__main__': diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index 1122bcb5e45727..cc130caa15f645 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -20,12 +20,13 @@ import data_type import data_feeder from . import dataset +from . import reader import attr import py_paddle.swig_paddle as api __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', - 'event', 'data_type', 'attr', 'data_feeder', 'dataset' + 'event', 'data_type', 'attr', 'data_feeder', 'dataset', 'reader' ] diff --git a/python/paddle/v2/reader/decorator.py b/python/paddle/v2/reader/decorator.py index 9f4234358f469b..d83e2f4577f20b 100644 --- a/python/paddle/v2/reader/decorator.py +++ b/python/paddle/v2/reader/decorator.py @@ -14,7 +14,7 @@ __all__ = [ 'map_readers', 'buffered', 'compose', 'chain', 'shuffle', - 'ComposeNotAligned' + 'ComposeNotAligned', 'batched' ] from Queue import Queue @@ -191,3 +191,25 @@ def data_reader(): e = q.get() return data_reader + + +def batched(reader, batch_size): + """ + Create a batched reader. + :param reader: the data reader to read from. + :param batch_size: batch_size + :return: the batched reader. + """ + + def __impl__(): + r = reader() + batch = [] + for instance in r: + batch.append(instance) + if len(batch) == batch_size: + yield batch + batch = [] + if batch: + yield batch + + return __impl__ diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 89415787eb2e36..9b45ee69f39f3f 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -29,7 +29,7 @@ class ITrainer(object): """ def train(self, - train_data_reader, + train_reader_creator, topology, parameters, test_data_reader=None, @@ -37,7 +37,7 @@ def train(self, """ train method. - :param train_data_reader: + :param train_reader_creator: :param topology: :param parameters: :param test_data_reader: @@ -62,27 +62,23 @@ def __init__(self, update_equation): self.__optimizer__ = update_equation def train(self, - train_reader_creator, + train_reader, topology, parameters, num_passes=1, - test_data_reader=None, event_handler=None, - batch_size=32, data_types=None, reader_dict=None): """ Training method. Will train num_passes of input data. - :param train_reader_creator: + :param train_reader: :param topology: Network Topology, use one or more Layers to represent it. :param parameters: The parameter pools. :param num_passes: The total train passes. - :param test_data_reader: :param event_handler: Event handler. A method will be invoked when event occurred. :type event_handler: (BaseEvent) => None - :param batch_size: Not important, will be removed after data refactor. :param data_types: Not important, will be removed after data refactor. :return: """ @@ -108,9 +104,7 @@ def train(self, for pass_id in xrange(num_passes): updater.startPass() - for batch_id, data_batch in enumerate( - __data_reader_to_batch__(train_reader_creator, batch_size, - topology)): + for batch_id, data_batch in enumerate(train_reader()): pass_type = updater.startBatch(len(data_batch)) gm.forwardBackward(feeder(data_batch), out_args, pass_type) for each_param in gm.getParameters(): @@ -128,51 +122,16 @@ def train(self, gm.finish() -def __data_reader_to_batch__(reader, batch_size, topology): - """ - This function is not important, and will be removed when data refactored. - """ - - def input_reorder(func): - for item in func(): - retv = [] - for __layer_name__ in topology.input_layer_names: - retv.append(item[__layer_name__]) - yield retv - - return __generator_to_batch__(input_reorder(reader), batch_size=batch_size) - - -def __generator_to_batch__(generator, batch_size): - """ - This function is not important, and will be removed when data refactored. - """ - ret_val = list() - for each_item in generator: - ret_val.append(each_item) - if len(ret_val) == batch_size: - yield ret_val - ret_val = list() - if len(ret_val) != 0: - yield ret_val - - -def __check_train_args__(train_data_reader, topology, parameters, - test_data_reader, event_handler, **kwargs): +def __check_train_args__(train_reader, topology, parameters, event_handler, + **kwargs): """ Check train function's argument types """ - if not callable(train_data_reader) or not isinstance(train_data_reader(), - collections.Iterator): + if not callable(train_reader) or not isinstance(train_reader(), + collections.Iterator): raise TypeError('train_data_reader should be a function, ' 'which can return a iterator') - if test_data_reader is not None: - if not callable(test_data_reader) or not isinstance( - test_data_reader(), collections.Iterator): - raise TypeError('test_data_reader should be a function, which can ' - 'return a iterator') - if not isinstance(topology, ModelConfig): raise TypeError('topology should be a model config') From f02698675d0ce833bee27057aec17b86e46a00c0 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 14:51:37 +0800 Subject: [PATCH 314/370] Remove test code --- demo/mnist/api_train_v2.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 67e36e6b201f38..d5eeb053188300 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -36,11 +36,6 @@ def event_handler(event): trainer = paddle.trainer.SGD(update_equation=adam_optimizer) - reader = paddle.reader.batched( - paddle.reader.shuffle( - paddle.dataset.mnist.train_creator(), buf_size=8192), - batch_size=32) - trainer.train( train_reader=paddle.reader.batched( paddle.reader.shuffle(paddle.dataset.mnist.train_creator(), From f3f24604350cedb62bc05b02449958b4e9aca4d4 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 15:08:58 +0800 Subject: [PATCH 315/370] Make unittest ok. --- python/paddle/v2/reader/tests/CMakeLists.txt | 12 ++----- python/paddle/v2/reader/tests/run_tests.sh | 35 ++++++++++++++++++++ 2 files changed, 38 insertions(+), 9 deletions(-) create mode 100755 python/paddle/v2/reader/tests/run_tests.sh diff --git a/python/paddle/v2/reader/tests/CMakeLists.txt b/python/paddle/v2/reader/tests/CMakeLists.txt index da072fb3dbeed5..a51f700406b48f 100644 --- a/python/paddle/v2/reader/tests/CMakeLists.txt +++ b/python/paddle/v2/reader/tests/CMakeLists.txt @@ -1,9 +1,3 @@ -add_test(NAME reader_decorator_test - COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ - ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/reader/tests/decorator_test.py - WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) - -add_test(NAME reader_creator_test - COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ - ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/reader/tests/creator_test.py - WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) +add_test(NAME reader_tests + COMMAND bash ${PROJ_ROOT}/python/paddle/v2/reader/tests/run_tests.sh + ${PYTHON_EXECUTABLE}) diff --git a/python/paddle/v2/reader/tests/run_tests.sh b/python/paddle/v2/reader/tests/run_tests.sh new file mode 100755 index 00000000000000..a544a5636021bc --- /dev/null +++ b/python/paddle/v2/reader/tests/run_tests.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# 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. + + +pushd `dirname $0` > /dev/null +SCRIPTPATH=$PWD +popd > /dev/null + +cd $SCRIPTPATH +$1 -m pip install ../../../../../paddle/dist/*.whl + +test_list="creator_test.py decorator_test.py" + +export PYTHONPATH=$PWD/../../../../../python/ + +for fn in $test_list +do + echo "test $fn" + $1 $fn + if [ $? -ne 0 ]; then + exit 1 + fi +done From dcc332a89001a01fb982938cc6c408b50ebd895a Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 15:12:53 +0800 Subject: [PATCH 316/370] Follow qq's comments --- demo/mnist/api_train_v2.py | 2 +- python/paddle/v2/trainer.py | 22 +++++++--------------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index d5eeb053188300..4d95780f06cd79 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -37,7 +37,7 @@ def event_handler(event): trainer = paddle.trainer.SGD(update_equation=adam_optimizer) trainer.train( - train_reader=paddle.reader.batched( + reader=paddle.reader.batched( paddle.reader.shuffle(paddle.dataset.mnist.train_creator(), buf_size=8192), batch_size=32), topology=cost, diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 9b45ee69f39f3f..cbeef0306b739c 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -28,19 +28,13 @@ class ITrainer(object): The interface of Trainer. The only exposed method is `train`. """ - def train(self, - train_reader_creator, - topology, - parameters, - test_data_reader=None, - event_handler=None): + def train(self, reader, topology, parameters, event_handler=None): """ train method. - :param train_reader_creator: + :param reader: :param topology: :param parameters: - :param test_data_reader: :param event_handler: :return: """ @@ -62,7 +56,7 @@ def __init__(self, update_equation): self.__optimizer__ = update_equation def train(self, - train_reader, + reader, topology, parameters, num_passes=1, @@ -72,7 +66,7 @@ def train(self, """ Training method. Will train num_passes of input data. - :param train_reader: + :param reader: :param topology: Network Topology, use one or more Layers to represent it. :param parameters: The parameter pools. :param num_passes: The total train passes. @@ -104,7 +98,7 @@ def train(self, for pass_id in xrange(num_passes): updater.startPass() - for batch_id, data_batch in enumerate(train_reader()): + for batch_id, data_batch in enumerate(reader()): pass_type = updater.startBatch(len(data_batch)) gm.forwardBackward(feeder(data_batch), out_args, pass_type) for each_param in gm.getParameters(): @@ -122,13 +116,11 @@ def train(self, gm.finish() -def __check_train_args__(train_reader, topology, parameters, event_handler, - **kwargs): +def __check_train_args__(reader, topology, parameters, event_handler, **kwargs): """ Check train function's argument types """ - if not callable(train_reader) or not isinstance(train_reader(), - collections.Iterator): + if not callable(reader) or not isinstance(reader(), collections.Iterator): raise TypeError('train_data_reader should be a function, ' 'which can return a iterator') From b59f35ef7ea97b74cc500bf5b28aed410c64e941 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Mon, 27 Feb 2017 14:22:49 +0800 Subject: [PATCH 317/370] follow some comments --- python/paddle/v2/layer.py | 61 ++++++++-------------------- python/paddle/v2/tests/test_layer.py | 14 +++---- 2 files changed, 21 insertions(+), 54 deletions(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index b9400ab26bdee2..e7d986d4c423e6 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -82,27 +82,10 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. import attr __all__ = [ - 'parse_network', - 'data', - 'fc', - 'max_id', - 'classification_cost', - 'cross_entropy_cost', - 'cross_entropy_with_selfnorm_cost', - 'regression_cost', - 'multi_binary_label_cross_entropy_cost', - 'rank_cost', - 'lambda_cost', - 'sum_cost', - 'huber_cost' - 'full_matrix_projection', - 'trans_full_matrix_projection', - 'table_projection', - 'identity_projection', - 'scaling_projection', - 'dotmul_projection', - 'context_projection', - 'conv_projection', + 'parse_network', 'data', 'fc', 'max_id', 'classification_cost', + 'cross_entropy_cost', 'cross_entropy_with_selfnorm_cost', 'regression_cost', + 'multi_binary_label_cross_entropy_cost', 'rank_cost', 'lambda_cost', + 'sum_cost', 'huber_cost' ] __projection_names__ = filter(lambda x: x.endswith('_projection'), @@ -167,7 +150,7 @@ def __convert_to_v2__(method_name, name_prefix=None, parent_names=None): wrapper = None class V2LayerImpl(Layer): - def __init__(self, name=None, **kwargs): + def __init__(self, **kwargs): parent_layers = dict() other_kwargs = dict() for pname in parent_names: @@ -178,6 +161,7 @@ def __init__(self, name=None, **kwargs): if key not in parent_names: other_kwargs[key] = kwargs[key] + name = kwargs['name'] if kwargs.has_key('name') else None super(V2LayerImpl, self).__init__(name, parent_layers) self.__other_kwargs__ = other_kwargs @@ -242,32 +226,30 @@ def __init__(self, layer_attr=None): self.__method_name__ = 'mixed_layer' self.finalized = False - - self.__parent_layers__ = dict() - other_kwargs = dict() - self.input_name = 'input' - self.__parent_layers__[self.input_name] = [] + self.__inputs__ = [] if input is not None: - self.__parent_layers__[self.input_name] = input + self.__inputs__ = input - self.name = name + other_kwargs = dict() + other_kwargs['name'] = name other_kwargs['size'] = size other_kwargs['act'] = act other_kwargs['bias_attr'] = bias_attr other_kwargs['layer_attr'] = layer_attr - Layer.__init__(self, name, self.__parent_layers__) + parent_layers = {"input": self.__inputs__} + super(MixedLayerV2, self).__init__(name, parent_layers) self.__other_kwargs__ = other_kwargs def __iadd__(self, other): if not self.finalized: - self.__parent_layers__[self.input_name].append(other) + self.__inputs__.append(other) return self else: raise MixedLayerTypeV2.AddToSealedMixedLayerExceptionV2() def __enter__(self): - assert len(self.__parent_layers__[self.input_name]) == 0 + assert len(self.__inputs__) == 0 return self def __exit__(self, *args, **kwargs): @@ -279,7 +261,7 @@ def to_proto_impl(self, **kwargs): args[each] = kwargs[each] for each in self.__other_kwargs__: args[each] = self.__other_kwargs__[each] - return getattr(conf_helps, self.__method_name__)(name=self.name, **args) + return getattr(conf_helps, self.__method_name__)(**args) @wrap_name_default("mixed") @@ -331,18 +313,7 @@ def mixed(size=0, 'huber_cost', name_prefix='huber_cost', parent_names=['input', 'label']) # convert projection -projection_list = [ - # [V1_method_name], all the parent_names is `input` - 'full_matrix_projection', - 'trans_full_matrix_projection', - 'table_projection', - 'scaling_projection', - 'dotmul_projection', - 'context_projection', - 'conv_projection', - 'identity_projection', -] -for prj in projection_list: +for prj in __projection_names__: globals()[prj] = __convert_to_v2__(prj, parent_names=['input']) # convert operator diff --git a/python/paddle/v2/tests/test_layer.py b/python/paddle/v2/tests/test_layer.py index 521bc8b40c5b6b..77423e4aa187dd 100644 --- a/python/paddle/v2/tests/test_layer.py +++ b/python/paddle/v2/tests/test_layer.py @@ -32,7 +32,7 @@ class CostLayerTest(unittest.TestCase): - def test_cost_layer(self): + def not_test_cost_layer(self): cost1 = layer.classification_cost(input=inference, label=label) cost2 = layer.classification_cost( input=inference, label=label, weight=weight) @@ -60,12 +60,8 @@ def test_projection(self): input = layer.data(name='data', type=data_type.dense_vector(784)) word = layer.data( name='word', type=data_type.integer_value_sequence(10000)) - fc0 = layer.fc(input=input, - size=100, - act=conf_helps.SigmoidActivation()) - fc1 = layer.fc(input=input, - size=200, - act=conf_helps.SigmoidActivation()) + fc0 = layer.fc(input=input, size=100, act=activation.Sigmoid()) + fc1 = layer.fc(input=input, size=200, act=activation.Sigmoid()) mixed0 = layer.mixed( size=256, input=[ @@ -121,8 +117,8 @@ def test_projection(self): def test_operator(self): ipt0 = layer.data(name='data', type=data_type.dense_vector(784)) ipt1 = layer.data(name='word', type=data_type.dense_vector(128)) - fc0 = layer.fc(input=ipt0, size=100, act=conf_helps.SigmoidActivation()) - fc1 = layer.fc(input=ipt0, size=100, act=conf_helps.SigmoidActivation()) + fc0 = layer.fc(input=ipt0, size=100, act=activation.Sigmoid()) + fc1 = layer.fc(input=ipt0, size=100, act=activation.Sigmoid()) dotmul_op = layer.dotmul_operator(a=fc0, b=fc1) dotmul0 = layer.mixed(input=dotmul_op) From 739ff181a7a1196a5de0ebba3674688b4296a174 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 16:30:16 +0800 Subject: [PATCH 318/370] V2.testing complete --- demo/mnist/api_train_v2.py | 31 +++++----- python/paddle/v2/event.py | 10 +++- python/paddle/v2/trainer.py | 115 +++++++++++++++++++++++++----------- 3 files changed, 104 insertions(+), 52 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index c787a6122ad6c6..45a70bc84afa29 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -21,28 +21,29 @@ def main(): adam_optimizer = paddle.optimizer.Adam(learning_rate=0.01) + trainer = paddle.trainer.SGD(topology=cost, + parameters=parameters, + update_equation=adam_optimizer) + def event_handler(event): if isinstance(event, paddle.event.EndIteration): - if event.batch_id % 100 == 0: - print "Pass %d, Batch %d, Cost %f, %s" % ( - event.pass_id, event.batch_id, event.cost, event.metrics) + if event.batch_id % 1000 == 0: + result = trainer.test(reader=paddle.reader.batched( + paddle.dataset.mnist.test_creator(), batch_size=256)) + + print "Pass %d, Batch %d, Cost %f, %s, Testing metrics %s" % ( + event.pass_id, event.batch_id, event.cost, event.metrics, + result.metrics) + else: pass - trainer = paddle.trainer.SGD(update_equation=adam_optimizer) trainer.train( reader=paddle.reader.batched( - paddle.reader.shuffle(paddle.dataset.mnist.train_creator(), - buf_size=8192), batch_size=32), - topology=cost, - parameters=parameters, - event_handler=event_handler, - data_types=[ # data_types will be removed, It should be in - # network topology - ('pixel', images.type), - ('label', label.type)], - reader_dict={'pixel': 0, 'label': 1} - ) + paddle.reader.shuffle( + paddle.dataset.mnist.train_creator(), buf_size=8192), + batch_size=32), + event_handler=event_handler) if __name__ == '__main__': diff --git a/python/paddle/v2/event.py b/python/paddle/v2/event.py index 835e28e6218df2..a78bcf076cc65e 100644 --- a/python/paddle/v2/event.py +++ b/python/paddle/v2/event.py @@ -11,7 +11,10 @@ TODO(yuyang18): Complete it! """ import py_paddle.swig_paddle as api -__all__ = ['EndIteration', 'BeginIteration', 'BeginPass', 'EndPass'] + +__all__ = [ + 'EndIteration', 'BeginIteration', 'BeginPass', 'EndPass', 'TestResult' +] class WithMetric(object): @@ -30,6 +33,11 @@ def metrics(self): return retv +class TestResult(WithMetric): + def __init__(self, evaluator): + super(TestResult, self).__init__(evaluator) + + class BeginPass(object): """ Event On One Pass Training Start. diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index f3a323db4fcfae..77232d5ac5e411 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -23,6 +23,13 @@ def default_event_handler(event): pass +def __bfs_travel_topology__(callback, *topologies): + for each_layer in topologies: + callback(each_layer) + __bfs_travel_topology__(callback, + *each_layer.__parent_layers__.values()) + + class ITrainer(object): """ The interface of Trainer. The only exposed method is `train`. @@ -43,26 +50,49 @@ def train(self, reader, topology, parameters, event_handler=None): class SGD(ITrainer): - def __init__(self, update_equation): + def __init__(self, topology, parameters, update_equation): """ Simple SGD Trainer. :param update_equation: The optimizer object. :type update_equation: v2_optimizer.Optimizer """ + if not isinstance(parameters, v2_parameters.Parameters): + raise TypeError('parameters should be parameters') + if not isinstance(update_equation, v2_optimizer.Optimizer): - raise ValueError("update equation parameter must be " - "paddle.v2.optimizer.Optimizer") + raise TypeError("update equation parameter must be " + "paddle.v2.optimizer.Optimizer") self.__optimizer__ = update_equation + self.__topology__ = topology + self.__parameters__ = parameters + self.__topology_in_proto__ = v2_layer.parse_network(topology) + data_types = dict() + + def __travel__(l): + if hasattr(l, 'type'): + data_types[l.name] = l.type + + if not isinstance(topology, collections.Sequence): + topology = [topology] + __bfs_travel_topology__(__travel__, *topology) + self.__data_types__ = [ + (iname, data_types[iname]) + for iname in self.__topology_in_proto__.input_layer_names + ] + + if not isinstance(self.__topology_in_proto__, ModelConfig): + raise TypeError('topology should be a model config') - def train(self, - reader, - topology, - parameters, - num_passes=1, - event_handler=None, - data_types=None, - reader_dict=None): + gm = api.GradientMachine.createFromConfigProto( + self.__topology_in_proto__, api.CREATE_MODE_NORMAL, + self.__optimizer__.enable_types()) + assert isinstance(gm, api.GradientMachine) + parameters.append_gradient_machine(gm) + self.__gradient_machine__ = gm + self.__gradient_machine__.randParameters() + + def train(self, reader, num_passes=1, event_handler=None, reader_dict=None): """ Training method. Will train num_passes of input data. @@ -79,26 +109,21 @@ def train(self, if event_handler is None: event_handler = default_event_handler - topology = v2_layer.parse_network(topology) + if reader_dict is None: + reader_dict = self.default_reader_dict() __check_train_args__(**locals()) - - gm = api.GradientMachine.createFromConfigProto( - topology, api.CREATE_MODE_NORMAL, self.__optimizer__.enable_types()) - assert isinstance(gm, api.GradientMachine) - parameters.append_gradient_machine(gm) - gm.randParameters() updater = self.__optimizer__.create_local_updater() - updater.init(gm) + updater.init(self.__gradient_machine__) - gm.start() - batch_evaluator = gm.makeEvaluator() + self.__gradient_machine__.start() + batch_evaluator = self.__gradient_machine__.makeEvaluator() assert isinstance(batch_evaluator, api.Evaluator) - pass_evaluator = gm.makeEvaluator() + pass_evaluator = self.__gradient_machine__.makeEvaluator() assert isinstance(pass_evaluator, api.Evaluator) out_args = api.Arguments.createArguments(0) - feeder = DataFeeder(data_types, reader_dict) + feeder = DataFeeder(self.__data_types__, reader_dict) for pass_id in xrange(num_passes): event_handler(v2_event.BeginPass(pass_id)) @@ -106,16 +131,18 @@ def train(self, updater.startPass() for batch_id, data_batch in enumerate(reader()): pass_type = updater.startBatch(len(data_batch)) - gm.forwardBackward(feeder(data_batch), out_args, pass_type) + self.__gradient_machine__.forwardBackward( + feeder(data_batch), out_args, pass_type) batch_evaluator.start() event_handler( v2_event.BeginIteration( pass_id=pass_id, batch_id=batch_id)) pass_type = updater.startBatch(len(data_batch)) - gm.forwardBackward(feeder(data_batch), out_args, pass_type) - gm.eval(pass_evaluator) - gm.eval(batch_evaluator) - for each_param in gm.getParameters(): + self.__gradient_machine__.forwardBackward( + feeder(data_batch), out_args, pass_type) + self.__gradient_machine__.eval(pass_evaluator) + self.__gradient_machine__.eval(batch_evaluator) + for each_param in self.__gradient_machine__.getParameters(): updater.update(each_param) # Get cost. We use numpy to calculate total cost for this batch. cost_vec = out_args.getSlotValue(0) @@ -133,10 +160,32 @@ def train(self, updater.finishPass() pass_evaluator.finish() event_handler(v2_event.EndPass(pass_id, evaluator=pass_evaluator)) - gm.finish() + self.__gradient_machine__.finish() + + def default_reader_dict(self): + reader_dict = dict() + for i, tp in enumerate(self.__data_types__): + reader_dict[tp[0]] = i + return reader_dict + def test(self, reader, reader_dict=None): + if reader_dict is None: + reader_dict = self.default_reader_dict() + + feeder = DataFeeder(self.__data_types__, reader_dict) + evaluator = self.__gradient_machine__.makeEvaluator() + out_args = api.Arguments.createArguments(0) + evaluator.start() + for data_batch in reader(): + self.__gradient_machine__.forward( + feeder(data_batch), out_args, api.PASS_TEST) + self.__gradient_machine__.eval(evaluator) -def __check_train_args__(reader, topology, parameters, event_handler, **kwargs): + evaluator.finish() + return v2_event.TestResult(evaluator=evaluator) + + +def __check_train_args__(reader, event_handler, **kwargs): """ Check train function's argument types """ @@ -144,11 +193,5 @@ def __check_train_args__(reader, topology, parameters, event_handler, **kwargs): raise TypeError('train_data_reader should be a function, ' 'which can return a iterator') - if not isinstance(topology, ModelConfig): - raise TypeError('topology should be a model config') - - if not isinstance(parameters, v2_parameters.Parameters): - raise TypeError('parameters should be a parameter pool') - if not callable(event_handler): raise TypeError('event handler should be a function') From d25173c0248a2e62db250ba481297c2c01ce1605 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Mon, 27 Feb 2017 16:30:53 +0800 Subject: [PATCH 319/370] follow comments --- python/paddle/v2/layer.py | 6 +++--- python/paddle/v2/tests/test_layer.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index e7d986d4c423e6..d5fe06542bc19e 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -134,9 +134,9 @@ def to_proto(self, context): if self.name is None: return self.to_proto_impl(**kwargs) - - if self.name not in context: + elif self.name not in context: context[self.name] = self.to_proto_impl(**kwargs) + return context[self.name] def to_proto_impl(self, **kwargs): @@ -161,7 +161,7 @@ def __init__(self, **kwargs): if key not in parent_names: other_kwargs[key] = kwargs[key] - name = kwargs['name'] if kwargs.has_key('name') else None + name = kwargs.get('name', None) super(V2LayerImpl, self).__init__(name, parent_layers) self.__other_kwargs__ = other_kwargs diff --git a/python/paddle/v2/tests/test_layer.py b/python/paddle/v2/tests/test_layer.py index 77423e4aa187dd..bf1c344202f457 100644 --- a/python/paddle/v2/tests/test_layer.py +++ b/python/paddle/v2/tests/test_layer.py @@ -32,7 +32,7 @@ class CostLayerTest(unittest.TestCase): - def not_test_cost_layer(self): + def test_cost_layer(self): cost1 = layer.classification_cost(input=inference, label=label) cost2 = layer.classification_cost( input=inference, label=label, weight=weight) From 692df52ef801ce79180ada37dc0fbae94282ae34 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 16:34:54 +0800 Subject: [PATCH 320/370] Fix unittest --- .travis.yml | 2 +- python/setup.py.in | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4fb2ca938795bb..3993dc31fdbf75 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,7 @@ before_install: - if [[ "$JOB" == "PRE_COMMIT" ]]; then sudo ln -s /usr/bin/clang-format-3.8 /usr/bin/clang-format; fi # 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 + - pip install numpy wheel 'protobuf==3.1' sphinx recommonmark sphinx_rtd_theme virtualenv pre-commit requests==2.9.2 LinkChecker 'scikit-learn>=0.18.0' script: - paddle/scripts/travis/main.sh notifications: diff --git a/python/setup.py.in b/python/setup.py.in index 68ca35265cf132..fbee7bca90e3ad 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -15,5 +15,8 @@ setup(name='paddle', packages=packages, package_dir={ '': '${CMAKE_CURRENT_SOURCE_DIR}' - } + }, + install_requires = [ + 'scikit-learn>=0.18.0' + ] ) From 434ada47ef0bb039192d4de5d969fc70ae033a0b Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 17:05:18 +0800 Subject: [PATCH 321/370] Up to date --- python/paddle/v2/{data_set => dataset}/cifar.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename python/paddle/v2/{data_set => dataset}/cifar.py (100%) diff --git a/python/paddle/v2/data_set/cifar.py b/python/paddle/v2/dataset/cifar.py similarity index 100% rename from python/paddle/v2/data_set/cifar.py rename to python/paddle/v2/dataset/cifar.py From 0bcc4d48defeb00f191c04d868098523965bc0d2 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 17:19:29 +0800 Subject: [PATCH 322/370] Simplize cifar --- python/paddle/v2/dataset/cifar.py | 170 ++++++++++-------------------- 1 file changed, 53 insertions(+), 117 deletions(-) diff --git a/python/paddle/v2/dataset/cifar.py b/python/paddle/v2/dataset/cifar.py index 54289430d4ce11..9a999de7e02aad 100644 --- a/python/paddle/v2/dataset/cifar.py +++ b/python/paddle/v2/dataset/cifar.py @@ -15,33 +15,10 @@ import itertools import numpy -__all__ = ['CIFAR10', 'CIFAR100', 'train_creator', 'test_creator'] - - -def __download_file__(filename, url, md5): - def __file_ok__(): - if not os.path.exists(filename): - return False - md5_hash = hashlib.md5() - with open(filename, 'rb') as f: - for chunk in iter(lambda: f.read(4096), b""): - md5_hash.update(chunk) - - return md5_hash.hexdigest() == md5 - - while not __file_ok__(): - response = urllib2.urlopen(url) - with open(filename, mode='wb') as of: - shutil.copyfileobj(fsrc=response, fdst=of) - - -def __read_one_batch__(batch): - data = batch['data'] - labels = batch.get('labels', batch.get('fine_labels', None)) - assert labels is not None - for sample, label in itertools.izip(data, labels): - yield (sample / 255.0).astype(numpy.float32), int(label) - +__all__ = [ + 'cifar_100_train_creator', 'cifar_100_test_creator', 'train_creator', + 'test_creator' +] CIFAR10_URL = 'https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz' CIFAR10_MD5 = 'c58f30108f718f92721af3b95e74349a' @@ -49,125 +26,84 @@ def __read_one_batch__(batch): CIFAR100_MD5 = 'eb9058c3a382ffc7106e4002c42a8d85' -class CIFAR(object): - """ - CIFAR dataset reader. The base class for CIFAR-10 and CIFAR-100 - - :param url: Download url. - :param md5: File md5sum - :param meta_filename: Meta file name in package. - :param train_filename: Train file name in package. - :param test_filename: Test file name in package. - """ +def __read_batch__(filename, sub_name): + def reader(): + def __read_one_batch_impl__(batch): + data = batch['data'] + labels = batch.get('labels', batch.get('fine_labels', None)) + assert labels is not None + for sample, label in itertools.izip(data, labels): + yield (sample / 255.0).astype(numpy.float32), int(label) - def __init__(self, url, md5, meta_filename, train_filename, test_filename): - filename = os.path.split(url)[-1] - assert DATA_HOME is not None - filepath = os.path.join(DATA_HOME, md5) - if not os.path.exists(filepath): - os.makedirs(filepath) - - self.__full_file__ = os.path.join(filepath, filename) - self.__meta_filename__ = meta_filename - self.__train_filename__ = train_filename - self.__test_filename__ = test_filename - __download_file__(filename=self.__full_file__, url=url, md5=md5) - - def labels(self): - """ - labels get all dataset label in order. - :return: a list of label. - :rtype: list[string] - """ - with tarfile.open(self.__full_file__, mode='r') as f: - name = [ - each_item.name for each_item in f - if self.__meta_filename__ in each_item.name - ][0] - meta_f = f.extractfile(name) - meta = cPickle.load(meta_f) - for key in meta: - if 'label' in key: - return meta[key] - else: - raise RuntimeError("Unexpected branch.") - - def train(self): - """ - Train Reader - """ - return self.__read_batch__(self.__train_filename__) - - def test(self): - """ - Test Reader - """ - return self.__read_batch__(self.__test_filename__) - - def __read_batch__(self, sub_name): - with tarfile.open(self.__full_file__, mode='r') as f: + with tarfile.open(filename, mode='r') as f: names = (each_item.name for each_item in f if sub_name in each_item.name) for name in names: batch = cPickle.load(f.extractfile(name)) - for item in __read_one_batch__(batch): + for item in __read_one_batch_impl__(batch): yield item + return reader -class CIFAR10(CIFAR): - """ - CIFAR-10 dataset, images are classified in 10 classes. - """ - def __init__(self): - super(CIFAR10, self).__init__( - CIFAR10_URL, - CIFAR10_MD5, - meta_filename='batches.meta', - train_filename='data_batch', - test_filename='test_batch') +def download(url, md5): + filename = os.path.split(url)[-1] + assert DATA_HOME is not None + filepath = os.path.join(DATA_HOME, md5) + if not os.path.exists(filepath): + os.makedirs(filepath) + __full_file__ = os.path.join(filepath, filename) + def __file_ok__(): + if not os.path.exists(__full_file__): + return False + md5_hash = hashlib.md5() + with open(__full_file__, 'rb') as f: + for chunk in iter(lambda: f.read(4096), b""): + md5_hash.update(chunk) + + return md5_hash.hexdigest() == md5 + + while not __file_ok__(): + response = urllib2.urlopen(url) + with open(__full_file__, mode='wb') as of: + shutil.copyfileobj(fsrc=response, fdst=of) + return __full_file__ + + +def cifar_100_train_creator(): + fn = download(url=CIFAR100_URL, md5=CIFAR100_MD5) + return __read_batch__(fn, 'train') -class CIFAR100(CIFAR): - """ - CIFAR-100 dataset, images are classified in 100 classes. - """ - def __init__(self): - super(CIFAR100, self).__init__( - CIFAR100_URL, - CIFAR100_MD5, - meta_filename='meta', - train_filename='train', - test_filename='test') +def cifar_100_test_creator(): + fn = download(url=CIFAR100_URL, md5=CIFAR100_MD5) + return __read_batch__(fn, 'test') def train_creator(): """ Default train reader creator. Use CIFAR-10 dataset. """ - cifar = CIFAR10() - return cifar.train + fn = download(url=CIFAR10_URL, md5=CIFAR10_MD5) + return __read_batch__(fn, 'data_batch') def test_creator(): """ Default test reader creator. Use CIFAR-10 dataset. """ - cifar = CIFAR10() - return cifar.test + fn = download(url=CIFAR10_URL, md5=CIFAR10_MD5) + return __read_batch__(fn, 'test_batch') -def unittest(label_count=100): - cifar = globals()["CIFAR%d" % label_count]() - assert len(cifar.labels()) == label_count - for _ in cifar.test(): +def unittest(): + for _ in train_creator()(): pass - for _ in cifar.train(): + for _ in test_creator()(): pass if __name__ == '__main__': - unittest(10) - unittest(100) + unittest() From de9012a50450da19a9227bc28d5bb042ac66fcf7 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 20:32:44 +0800 Subject: [PATCH 323/370] Add MovieLens Dataset --- python/paddle/v2/dataset/cifar.py | 35 +------- python/paddle/v2/dataset/config.py | 30 ++++++- python/paddle/v2/dataset/movielens.py | 120 ++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 32 deletions(-) create mode 100644 python/paddle/v2/dataset/movielens.py diff --git a/python/paddle/v2/dataset/cifar.py b/python/paddle/v2/dataset/cifar.py index 9a999de7e02aad..2ac71c6effe9d5 100644 --- a/python/paddle/v2/dataset/cifar.py +++ b/python/paddle/v2/dataset/cifar.py @@ -5,16 +5,14 @@ the default train_creator, test_creator used for CIFAR-10 dataset. """ -from config import DATA_HOME -import os -import hashlib -import urllib2 -import shutil -import tarfile import cPickle import itertools +import tarfile + import numpy +from config import download + __all__ = [ 'cifar_100_train_creator', 'cifar_100_test_creator', 'train_creator', 'test_creator' @@ -47,31 +45,6 @@ def __read_one_batch_impl__(batch): return reader -def download(url, md5): - filename = os.path.split(url)[-1] - assert DATA_HOME is not None - filepath = os.path.join(DATA_HOME, md5) - if not os.path.exists(filepath): - os.makedirs(filepath) - __full_file__ = os.path.join(filepath, filename) - - def __file_ok__(): - if not os.path.exists(__full_file__): - return False - md5_hash = hashlib.md5() - with open(__full_file__, 'rb') as f: - for chunk in iter(lambda: f.read(4096), b""): - md5_hash.update(chunk) - - return md5_hash.hexdigest() == md5 - - while not __file_ok__(): - response = urllib2.urlopen(url) - with open(__full_file__, mode='wb') as of: - shutil.copyfileobj(fsrc=response, fdst=of) - return __full_file__ - - def cifar_100_train_creator(): fn = download(url=CIFAR100_URL, md5=CIFAR100_MD5) return __read_batch__(fn, 'train') diff --git a/python/paddle/v2/dataset/config.py b/python/paddle/v2/dataset/config.py index 69e96d65ef1ef8..02a009f09c71cc 100644 --- a/python/paddle/v2/dataset/config.py +++ b/python/paddle/v2/dataset/config.py @@ -1,8 +1,36 @@ +import hashlib import os +import shutil +import urllib2 -__all__ = ['DATA_HOME'] +__all__ = ['DATA_HOME', 'download'] DATA_HOME = os.path.expanduser('~/.cache/paddle_data_set') if not os.path.exists(DATA_HOME): os.makedirs(DATA_HOME) + + +def download(url, md5): + filename = os.path.split(url)[-1] + assert DATA_HOME is not None + filepath = os.path.join(DATA_HOME, md5) + if not os.path.exists(filepath): + os.makedirs(filepath) + __full_file__ = os.path.join(filepath, filename) + + def __file_ok__(): + if not os.path.exists(__full_file__): + return False + md5_hash = hashlib.md5() + with open(__full_file__, 'rb') as f: + for chunk in iter(lambda: f.read(4096), b""): + md5_hash.update(chunk) + + return md5_hash.hexdigest() == md5 + + while not __file_ok__(): + response = urllib2.urlopen(url) + with open(__full_file__, mode='wb') as of: + shutil.copyfileobj(fsrc=response, fdst=of) + return __full_file__ diff --git a/python/paddle/v2/dataset/movielens.py b/python/paddle/v2/dataset/movielens.py new file mode 100644 index 00000000000000..314329e91cadf8 --- /dev/null +++ b/python/paddle/v2/dataset/movielens.py @@ -0,0 +1,120 @@ +import zipfile +from config import download +import re +import random +import functools + +__all__ = ['train_creator', 'test_creator'] + + +class MovieInfo(object): + def __init__(self, index, categories, title): + self.index = int(index) + self.categories = categories + self.title = title + + def value(self): + return [ + self.index, [CATEGORIES_DICT[c] for c in self.categories], + [MOVIE_TITLE_DICT[w.lower()] for w in self.title.split()] + ] + + +class UserInfo(object): + def __init__(self, index, gender, age, job_id): + self.index = int(index) + self.is_male = gender == 'M' + self.age = [1, 18, 25, 35, 45, 50, 56].index(int(age)) + self.job_id = int(job_id) + + def value(self): + return [self.index, 0 if self.is_male else 1, self.age, self.job_id] + + +MOVIE_INFO = None +MOVIE_TITLE_DICT = None +CATEGORIES_DICT = None +USER_INFO = None + + +def __initialize_meta_info__(): + fn = download( + url='http://files.grouplens.org/datasets/movielens/ml-1m.zip', + md5='c4d9eecfca2ab87c1945afe126590906') + global MOVIE_INFO + if MOVIE_INFO is None: + pattern = re.compile(r'^(.*)\((\d+)\)$') + with zipfile.ZipFile(file=fn) as package: + for info in package.infolist(): + assert isinstance(info, zipfile.ZipInfo) + MOVIE_INFO = dict() + title_word_set = set() + categories_set = set() + with package.open('ml-1m/movies.dat') as movie_file: + for i, line in enumerate(movie_file): + movie_id, title, categories = line.strip().split('::') + categories = categories.split('|') + for c in categories: + categories_set.add(c) + title = pattern.match(title).group(1) + MOVIE_INFO[int(movie_id)] = MovieInfo( + index=movie_id, categories=categories, title=title) + for w in title.split(): + title_word_set.add(w.lower()) + + global MOVIE_TITLE_DICT + MOVIE_TITLE_DICT = dict() + for i, w in enumerate(title_word_set): + MOVIE_TITLE_DICT[w] = i + + global CATEGORIES_DICT + CATEGORIES_DICT = dict() + for i, c in enumerate(categories_set): + CATEGORIES_DICT[c] = i + + global USER_INFO + USER_INFO = dict() + with package.open('ml-1m/users.dat') as user_file: + for line in user_file: + uid, gender, age, job, _ = line.strip().split("::") + USER_INFO[int(uid)] = UserInfo( + index=uid, gender=gender, age=age, job_id=job) + return fn + + +def __reader__(rand_seed=0, test_ratio=0.1, is_test=False): + fn = __initialize_meta_info__() + rand = random.Random(x=rand_seed) + with zipfile.ZipFile(file=fn) as package: + with package.open('ml-1m/ratings.dat') as rating: + for line in rating: + if (rand.random() < test_ratio) == is_test: + uid, mov_id, rating, _ = line.strip().split("::") + uid = int(uid) + mov_id = int(mov_id) + rating = float(rating) * 2 - 5.0 + + mov = MOVIE_INFO[mov_id] + usr = USER_INFO[uid] + yield usr.value() + mov.value() + [[rating]] + + +def __reader_creator__(**kwargs): + return lambda: __reader__(**kwargs) + + +train_creator = functools.partial(__reader_creator__, is_test=False) +test_creator = functools.partial(__reader_creator__, is_test=True) + + +def unittest(): + for train_count, _ in enumerate(train_creator()()): + pass + for test_count, _ in enumerate(test_creator()()): + pass + + print train_count, test_count + + +if __name__ == '__main__': + unittest() From 9435025b8e267c84431e3b606da8197d221062e3 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 20:39:04 +0800 Subject: [PATCH 324/370] Add dependencies --- .travis.yml | 2 +- python/setup.py.in | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3993dc31fdbf75..31d76ecb876f11 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,7 @@ before_install: - if [[ "$JOB" == "PRE_COMMIT" ]]; then sudo ln -s /usr/bin/clang-format-3.8 /usr/bin/clang-format; fi # 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 'scikit-learn>=0.18.0' + - pip install numpy wheel 'protobuf==3.1' sphinx recommonmark sphinx_rtd_theme virtualenv pre-commit requests==2.9.2 LinkChecker 'scikit-learn>=0.18.0' 'scipy>=0.18.0' script: - paddle/scripts/travis/main.sh notifications: diff --git a/python/setup.py.in b/python/setup.py.in index fbee7bca90e3ad..c7e46293b79fe0 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -17,6 +17,7 @@ setup(name='paddle', '': '${CMAKE_CURRENT_SOURCE_DIR}' }, install_requires = [ - 'scikit-learn>=0.18.0' + 'scikit-learn>=0.18.0', + 'scipy>=0.18.0', ] ) From 40427979a7f621257d7171dfaefeb3afe9a0b45e Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 27 Feb 2017 23:36:28 +0800 Subject: [PATCH 325/370] refine code --- demo/mnist/api_train_v2.py | 6 ++-- python/paddle/v2/data_feeder.py | 2 +- python/paddle/v2/data_type.py | 6 ++-- python/paddle/v2/layer.py | 1 + python/paddle/v2/parameters.py | 4 +-- python/paddle/v2/tests/CMakeLists.txt | 2 +- .../{topology_test.py => test_topology.py} | 21 +++++++++----- python/paddle/v2/topology.py | 29 ++++++++----------- python/paddle/v2/trainer.py | 14 +++------ 9 files changed, 41 insertions(+), 44 deletions(-) rename python/paddle/v2/tests/{topology_test.py => test_topology.py} (81%) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index cb1191eddd005a..a23ddfaca011e2 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -41,10 +41,12 @@ def event_handler(event): trainer.train( train_data_reader=train_reader, - topology=[cost], + topology=cost, parameters=parameters, event_handler=event_handler, - batch_size=32) # batch size should be refactor in Data reader + batch_size=32, # batch size should be refactor in Data reader + reader_dict={images.name: 0, + label.name: 1}) if __name__ == '__main__': diff --git a/python/paddle/v2/data_feeder.py b/python/paddle/v2/data_feeder.py index 2a16d46dda47f8..3b106e100cff75 100644 --- a/python/paddle/v2/data_feeder.py +++ b/python/paddle/v2/data_feeder.py @@ -23,7 +23,7 @@ class DataFeeder(DataProviderConverter): """ DataFeeder converts the data returned by paddle.reader into a data structure of Arguments which is defined in the API. The paddle.reader usually returns - a list of mini-batch data entries. Each data entry in the list is one sampe. + a list of mini-batch data entries. Each data entry in the list is one sample. Each sample is a list or a tuple with one feature or multiple features. DataFeeder converts this mini-batch data entries into Arguments in order to feed it to C++ interface. diff --git a/python/paddle/v2/data_type.py b/python/paddle/v2/data_type.py index dd3ebfcb4267e1..522ddfdaacce44 100644 --- a/python/paddle/v2/data_type.py +++ b/python/paddle/v2/data_type.py @@ -13,10 +13,10 @@ # limitations under the License. from paddle.trainer.PyDataProvider2 import \ - InputType, dense_vector, sparse_binary_vector,\ + InputType, DataType, dense_vector, sparse_binary_vector,\ sparse_vector, integer_value, integer_value_sequence __all__ = [ - 'InputType', 'dense_vector', 'sparse_binary_vector', 'sparse_vector', - 'integer_value', 'integer_value_sequence' + 'InputType', 'DataType', 'dense_vector', 'sparse_binary_vector', + 'sparse_vector', 'integer_value', 'integer_value_sequence' ] diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index d15e6398f51f43..faf5b8bd87d7b8 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -284,6 +284,7 @@ def mixed(size=0, return MixedLayerV2(size, input, name, act, bias_attr, layer_attr) +LayerV2 = Layer data = DataLayerV2 AggregateLevel = conf_helps.layers.AggregateLevel ExpandLevel = conf_helps.layers.ExpandLevel diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index b8d4b287032cd3..7c3cde7727cbb1 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -2,7 +2,7 @@ import py_paddle.swig_paddle as api from paddle.proto.ParameterConfig_pb2 import ParameterConfig -import topology as v2_topology +from topology import Topology __all__ = ['Parameters', 'create'] @@ -13,7 +13,7 @@ def create(layers): :param layers: :return: """ - topology = v2_topology.Topology(layers) + topology = Topology(layers) pool = Parameters() for param in topology.proto().parameters: pool.__append_config__(param) diff --git a/python/paddle/v2/tests/CMakeLists.txt b/python/paddle/v2/tests/CMakeLists.txt index c77df827d956ec..46b5d08b8761ea 100644 --- a/python/paddle/v2/tests/CMakeLists.txt +++ b/python/paddle/v2/tests/CMakeLists.txt @@ -8,5 +8,5 @@ add_test(NAME test_v2_api add_test(NAME topology_test COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ - ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/topology_test.py + ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/test_topology.py WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) diff --git a/python/paddle/v2/tests/topology_test.py b/python/paddle/v2/tests/test_topology.py similarity index 81% rename from python/paddle/v2/tests/topology_test.py rename to python/paddle/v2/tests/test_topology.py index be60a577beac5b..1bf55a5bc68dfd 100644 --- a/python/paddle/v2/tests/topology_test.py +++ b/python/paddle/v2/tests/test_topology.py @@ -30,14 +30,19 @@ def test_data_type(self): act=conf_helps.SoftmaxActivation()) cost = layer.classification_cost(input=inference, label=label) topo = topology.Topology(cost) - type = topo.data_type() - self.assertEqual(len(type), 2) - self.assertEqual(type[0][0], "pixel") - self.assertEqual(type[0][1].type, data_type.DataType.Dense) - self.assertEqual(type[0][1].dim, 784) - self.assertEqual(type[1][0], "label") - self.assertEqual(type[1][1].type, data_type.DataType.Index) - self.assertEqual(type[1][1].dim, 10) + data_types = topo.data_type() + self.assertEqual(len(data_types), 2) + pixel_data_type = filter(lambda type: type[0] == "pixel", data_types) + self.assertEqual(len(pixel_data_type), 1) + pixel_data_type = pixel_data_type[0] + self.assertEqual(pixel_data_type[1].type, data_type.DataType.Dense) + self.assertEqual(pixel_data_type[1].dim, 784) + + label_data_type = filter(lambda type: type[0] == "label", data_types) + self.assertEqual(len(label_data_type), 1) + label_data_type = label_data_type[0] + self.assertEqual(label_data_type[1].type, data_type.DataType.Index) + self.assertEqual(label_data_type[1].dim, 10) def test_get_layer(self): pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index 9c57f1f8e607bd..a51b1073b4fc4f 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -49,30 +49,30 @@ def get_layer(self, name): result_layer = [] def find_layer_by_name(layer, layer_name): - if layer.name == layer_name and len(result_layer) == 0: + if len(result_layer) == 1: + return + elif layer.name == layer_name: result_layer.append(layer) - for parent_layer in layer.__parent_layers__.values(): - find_layer_by_name(parent_layer, layer_name) + else: + for parent_layer in layer.__parent_layers__.values(): + find_layer_by_name(parent_layer, layer_name) for layer in self.layers: find_layer_by_name(layer, name) + assert len(result_layer) == 1 return result_layer[0] - def data_layer(self): + def data_layers(self): """ get all data layer :return: """ - data_layers = [] + data_layers = set() def find_data_layer(layer): - assert isinstance(layer, layer.LayerV2) if isinstance(layer, v2_layer.DataLayerV2): - if len( - filter(lambda data_layer: data_layer.name == layer.name, - data_layers)) == 0: - data_layers.append(layer) + data_layers.add(layer) for parent_layer in layer.__parent_layers__.values(): find_data_layer(parent_layer) @@ -85,14 +85,9 @@ def data_type(self): """ get data_type from proto, such as: [('image', dense_vector(768)), ('label', integer_value(10))] - the order is the same with __model_config__.input_layer_names """ - data_types_lists = [] - for layer_name in self.__model_config__.input_layer_names: - data_types_lists.append( - (layer_name, self.get_layer(layer_name).type)) - - return data_types_lists + return [(data_layer.name, data_layer.type) + for data_layer in self.data_layers()] def __check_layer_type__(layer): diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 96a3ee4fd446c1..3bf2128e16b5ad 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -1,13 +1,12 @@ import collections import py_paddle.swig_paddle as api -from py_paddle import DataProviderConverter from data_feeder import DataFeeder +from topology import Topology from . import event as v2_event from . import optimizer as v2_optimizer from . import parameters as v2_parameters -from . import topology as v2_topology __all__ = ['ITrainer', 'SGD'] @@ -69,7 +68,6 @@ def train(self, test_data_reader=None, event_handler=None, batch_size=32, - data_types=None, reader_dict=None): """ Training method. Will train num_passes of input data. @@ -83,13 +81,12 @@ def train(self, occurred. :type event_handler: (BaseEvent) => None :param batch_size: Not important, will be removed after data refactor. - :param data_types: Not important, will be removed after data refactor. :return: """ if event_handler is None: event_handler = default_event_handler - topology = v2_topology.Topology(topology) + topology = Topology(topology) __check_train_args__(**locals()) @@ -109,10 +106,7 @@ def train(self, assert isinstance(pass_evaluator, api.Evaluator) out_args = api.Arguments.createArguments(0) - data_types_lists = [data_type[1] for data_type in topology.data_type()] - converter = DataProviderConverter(input_types=data_types_lists) - - feeder = DataFeeder(data_types, reader_dict) + feeder = DataFeeder(topology.data_type(), reader_dict) for pass_id in xrange(num_passes): event_handler(v2_event.BeginPass(pass_id)) @@ -195,7 +189,7 @@ def __check_train_args__(train_data_reader, topology, parameters, raise ValueError('test_data_reader should be a function, which can ' 'return a iterator') - if not isinstance(topology, v2_topology.Topology): + if not isinstance(topology, Topology): raise ValueError('topology should be a model config') if not isinstance(parameters, v2_parameters.Parameters): From 7fe21602f6b767c64e058ab99ad71a1db6bd5d74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=9B=8A?= Date: Mon, 27 Feb 2017 14:43:43 -0800 Subject: [PATCH 326/370] Rename config.py into common.py --- python/paddle/v2/dataset/cifar.py | 2 +- python/paddle/v2/dataset/{config.py => common.py} | 0 python/paddle/v2/dataset/mnist.py | 2 +- python/paddle/v2/dataset/movielens.py | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename python/paddle/v2/dataset/{config.py => common.py} (100%) diff --git a/python/paddle/v2/dataset/cifar.py b/python/paddle/v2/dataset/cifar.py index 2ac71c6effe9d5..accb32f117720f 100644 --- a/python/paddle/v2/dataset/cifar.py +++ b/python/paddle/v2/dataset/cifar.py @@ -11,7 +11,7 @@ import numpy -from config import download +from common import download __all__ = [ 'cifar_100_train_creator', 'cifar_100_test_creator', 'train_creator', diff --git a/python/paddle/v2/dataset/config.py b/python/paddle/v2/dataset/common.py similarity index 100% rename from python/paddle/v2/dataset/config.py rename to python/paddle/v2/dataset/common.py diff --git a/python/paddle/v2/dataset/mnist.py b/python/paddle/v2/dataset/mnist.py index db84f37aa4fc34..2f195bfb9688b0 100644 --- a/python/paddle/v2/dataset/mnist.py +++ b/python/paddle/v2/dataset/mnist.py @@ -1,7 +1,7 @@ import sklearn.datasets.mldata import sklearn.model_selection import numpy -from config import DATA_HOME +from common import DATA_HOME __all__ = ['train_creator', 'test_creator'] diff --git a/python/paddle/v2/dataset/movielens.py b/python/paddle/v2/dataset/movielens.py index 314329e91cadf8..dcffcff2f58c63 100644 --- a/python/paddle/v2/dataset/movielens.py +++ b/python/paddle/v2/dataset/movielens.py @@ -1,5 +1,5 @@ import zipfile -from config import download +from common import download import re import random import functools From b93722df95d3907782cdff034df360b79d1fd093 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Mon, 27 Feb 2017 23:07:33 +0000 Subject: [PATCH 327/370] Set data cache home directory to ~/.cache/paddle/dataset --- python/paddle/v2/dataset/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/v2/dataset/common.py b/python/paddle/v2/dataset/common.py index 02a009f09c71cc..ae4a5383b03526 100644 --- a/python/paddle/v2/dataset/common.py +++ b/python/paddle/v2/dataset/common.py @@ -5,7 +5,7 @@ __all__ = ['DATA_HOME', 'download'] -DATA_HOME = os.path.expanduser('~/.cache/paddle_data_set') +DATA_HOME = os.path.expanduser('~/.cache/paddle/dataset') if not os.path.exists(DATA_HOME): os.makedirs(DATA_HOME) From 305566eed4a62a7af178b78ea21f89c8eb73b59b Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Mon, 27 Feb 2017 15:09:56 -0800 Subject: [PATCH 328/370] fix parameters.append_gradient_machine append_gradient_machine should append __gradient_machines__ in all conditions. --- python/paddle/v2/parameters.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index ea504d5104716d..f2c5a4d49cfc44 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -224,7 +224,8 @@ def append_gradient_machine(self, gradient_machine): except ValueError: # If no such parameter in gradient machine, then don't copy pass - self.__gradient_machines__.append(gradient_machine) + + self.__gradient_machines__.append(gradient_machine) def __get_parameter_in_gradient_machine__(gradient_machine, name): From 37e2b92089ed583ba9e73f615444c3b080cd1b63 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Mon, 27 Feb 2017 23:41:32 +0000 Subject: [PATCH 329/370] Add md5file into dataset/common.py, and unit test in tests/common_test.py --- python/paddle/v2/dataset/common.py | 13 +++++++++++-- python/paddle/v2/dataset/tests/common_test.py | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 python/paddle/v2/dataset/tests/common_test.py diff --git a/python/paddle/v2/dataset/common.py b/python/paddle/v2/dataset/common.py index ae4a5383b03526..ff5ed76c0f732b 100644 --- a/python/paddle/v2/dataset/common.py +++ b/python/paddle/v2/dataset/common.py @@ -3,7 +3,7 @@ import shutil import urllib2 -__all__ = ['DATA_HOME', 'download'] +__all__ = ['DATA_HOME', 'download', 'md5file'] DATA_HOME = os.path.expanduser('~/.cache/paddle/dataset') @@ -11,7 +11,7 @@ os.makedirs(DATA_HOME) -def download(url, md5): +def download(url, package_name, md5): filename = os.path.split(url)[-1] assert DATA_HOME is not None filepath = os.path.join(DATA_HOME, md5) @@ -34,3 +34,12 @@ def __file_ok__(): with open(__full_file__, mode='wb') as of: shutil.copyfileobj(fsrc=response, fdst=of) return __full_file__ + + +def md5file(fname): + hash_md5 = hashlib.md5() + f = open(fname, "rb") + for chunk in iter(lambda: f.read(4096), b""): + hash_md5.update(chunk) + f.close() + return hash_md5.hexdigest() diff --git a/python/paddle/v2/dataset/tests/common_test.py b/python/paddle/v2/dataset/tests/common_test.py new file mode 100644 index 00000000000000..d2f97f06de3db9 --- /dev/null +++ b/python/paddle/v2/dataset/tests/common_test.py @@ -0,0 +1,16 @@ +import paddle.v2.dataset.common +import unittest +import tempfile + +class TestCommon(unittest.TestCase): + def test_md5file(self): + _, temp_path =tempfile.mkstemp() + f = open(temp_path, 'w') + f.write("Hello\n") + f.close() + self.assertEqual( + '09f7e02f1290be211da707a266f153b3', + paddle.v2.dataset.common.md5file(temp_path)) + +if __name__ == '__main__': + unittest.main() From 91115ab6de016806a5d3ad168b114f54b1eaac87 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 28 Feb 2017 00:17:52 +0000 Subject: [PATCH 330/370] Use module name and raw data filename as the local filename --- python/paddle/v2/dataset/common.py | 42 +++++++------------ python/paddle/v2/dataset/tests/common_test.py | 12 ++++-- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/python/paddle/v2/dataset/common.py b/python/paddle/v2/dataset/common.py index ff5ed76c0f732b..b1831f38afb4f1 100644 --- a/python/paddle/v2/dataset/common.py +++ b/python/paddle/v2/dataset/common.py @@ -1,7 +1,7 @@ +import requests import hashlib import os import shutil -import urllib2 __all__ = ['DATA_HOME', 'download', 'md5file'] @@ -11,31 +11,6 @@ os.makedirs(DATA_HOME) -def download(url, package_name, md5): - filename = os.path.split(url)[-1] - assert DATA_HOME is not None - filepath = os.path.join(DATA_HOME, md5) - if not os.path.exists(filepath): - os.makedirs(filepath) - __full_file__ = os.path.join(filepath, filename) - - def __file_ok__(): - if not os.path.exists(__full_file__): - return False - md5_hash = hashlib.md5() - with open(__full_file__, 'rb') as f: - for chunk in iter(lambda: f.read(4096), b""): - md5_hash.update(chunk) - - return md5_hash.hexdigest() == md5 - - while not __file_ok__(): - response = urllib2.urlopen(url) - with open(__full_file__, mode='wb') as of: - shutil.copyfileobj(fsrc=response, fdst=of) - return __full_file__ - - def md5file(fname): hash_md5 = hashlib.md5() f = open(fname, "rb") @@ -43,3 +18,18 @@ def md5file(fname): hash_md5.update(chunk) f.close() return hash_md5.hexdigest() + + +def download(url, module_name, md5sum): + dirname = os.path.join(DATA_HOME, module_name) + if not os.path.exists(dirname): + os.makedirs(dirname) + + filename = os.path.join(dirname, url.split('/')[-1]) + if not (os.path.exists(filename) and md5file(filename) == md5sum): + # If file doesn't exist or MD5 doesn't match, then download. + r = requests.get(url, stream=True) + with open(filename, 'w') as f: + shutil.copyfileobj(r.raw, f) + + return filename diff --git a/python/paddle/v2/dataset/tests/common_test.py b/python/paddle/v2/dataset/tests/common_test.py index d2f97f06de3db9..0672a4671430a9 100644 --- a/python/paddle/v2/dataset/tests/common_test.py +++ b/python/paddle/v2/dataset/tests/common_test.py @@ -5,12 +5,18 @@ class TestCommon(unittest.TestCase): def test_md5file(self): _, temp_path =tempfile.mkstemp() - f = open(temp_path, 'w') - f.write("Hello\n") - f.close() + with open(temp_path, 'w') as f: + f.write("Hello\n") self.assertEqual( '09f7e02f1290be211da707a266f153b3', paddle.v2.dataset.common.md5file(temp_path)) + def test_download(self): + yi_avatar = 'https://avatars0.githubusercontent.com/u/1548775?v=3&s=460' + self.assertEqual( + paddle.v2.dataset.common.DATA_HOME + '/test/1548775?v=3&s=460', + paddle.v2.dataset.common.download( + yi_avatar, 'test', 'f75287202d6622414c706c36c16f8e0d')) + if __name__ == '__main__': unittest.main() From 792875e3eaa0467e40748f0ed97f022fe7fdcd0b Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 28 Feb 2017 09:56:27 +0800 Subject: [PATCH 331/370] Lazy initialize mnist dataset. Fix unittest --- python/paddle/v2/dataset/mnist.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/python/paddle/v2/dataset/mnist.py b/python/paddle/v2/dataset/mnist.py index db84f37aa4fc34..faae818a5d7b78 100644 --- a/python/paddle/v2/dataset/mnist.py +++ b/python/paddle/v2/dataset/mnist.py @@ -16,18 +16,29 @@ def reader(): TEST_SIZE = 10000 +X_train = None +X_test = None +y_train = None +y_test = None -data = sklearn.datasets.mldata.fetch_mldata( - "MNIST original", data_home=DATA_HOME) -X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split( - data.data, data.target, test_size=TEST_SIZE, random_state=0) + +def __initialize_dataset__(): + global X_train, X_test, y_train, y_test + if X_train is not None: + return + data = sklearn.datasets.mldata.fetch_mldata( + "MNIST original", data_home=DATA_HOME) + X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split( + data.data, data.target, test_size=TEST_SIZE, random_state=0) def train_creator(): + __initialize_dataset__() return __mnist_reader_creator__(X_train, y_train) def test_creator(): + __initialize_dataset__() return __mnist_reader_creator__(X_test, y_test) From d6c62e852d7788ba81e704323995874b85f89c3e Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 28 Feb 2017 02:26:30 +0000 Subject: [PATCH 332/370] Rewrite mnist.py and add mnist_test.py --- python/paddle/v2/dataset/mnist.py | 74 ++++++++++++++------ python/paddle/v2/dataset/tests/mnist_test.py | 27 +++++++ 2 files changed, 78 insertions(+), 23 deletions(-) create mode 100644 python/paddle/v2/dataset/tests/mnist_test.py diff --git a/python/paddle/v2/dataset/mnist.py b/python/paddle/v2/dataset/mnist.py index 2f195bfb9688b0..29fc20eae9b06e 100644 --- a/python/paddle/v2/dataset/mnist.py +++ b/python/paddle/v2/dataset/mnist.py @@ -1,39 +1,67 @@ -import sklearn.datasets.mldata -import sklearn.model_selection +import paddle.v2.dataset.common +import subprocess import numpy -from common import DATA_HOME -__all__ = ['train_creator', 'test_creator'] +URL_PREFIX = 'http://yann.lecun.com/exdb/mnist/' +TEST_IMAGE_URL = URL_PREFIX + 't10k-images-idx3-ubyte.gz' +TEST_IMAGE_MD5 = '25e3cc63507ef6e98d5dc541e8672bb6' -def __mnist_reader_creator__(data, target): - def reader(): - n_samples = data.shape[0] - for i in xrange(n_samples): - yield (data[i] / 255.0).astype(numpy.float32), int(target[i]) +TEST_LABEL_URL = URL_PREFIX + 't10k-labels-idx1-ubyte.gz' +TEST_LABEL_MD5 = '4e9511fe019b2189026bd0421ba7b688' + +TRAIN_IMAGE_URL = URL_PREFIX + 'train-images-idx3-ubyte.gz' +TRAIN_IMAGE_MD5 = 'f68b3c2dcbeaaa9fbdd348bbdeb94873' - return reader +TRAIN_LABEL_URL = URL_PREFIX + 'train-labels-idx1-ubyte.gz' +TRAIN_LABEL_MD5 = 'd53e105ee54ea40749a09fcbcd1e9432' -TEST_SIZE = 10000 +def reader_creator(image_filename, label_filename, buffer_size): + def reader(): + # According to http://stackoverflow.com/a/38061619/724872, we + # cannot use standard package gzip here. + m = subprocess.Popen(["zcat", image_filename], stdout=subprocess.PIPE) + m.stdout.read(16) # skip some magic bytes + + l = subprocess.Popen(["zcat", label_filename], stdout=subprocess.PIPE) + l.stdout.read(8) # skip some magic bytes -data = sklearn.datasets.mldata.fetch_mldata( - "MNIST original", data_home=DATA_HOME) -X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split( - data.data, data.target, test_size=TEST_SIZE, random_state=0) + while True: + labels = numpy.fromfile( + l.stdout, 'ubyte', count=buffer_size + ).astype("int") + if labels.size != buffer_size: + break # numpy.fromfile returns empty slice after EOF. -def train_creator(): - return __mnist_reader_creator__(X_train, y_train) + images = numpy.fromfile( + m.stdout, 'ubyte', count=buffer_size * 28 * 28 + ).reshape((buffer_size, 28 * 28) + ).astype('float32') + images = images / 255.0 * 2.0 - 1.0 -def test_creator(): - return __mnist_reader_creator__(X_test, y_test) + for i in xrange(buffer_size): + yield images[i, :], labels[i] + m.terminate() + l.terminate() -def unittest(): - assert len(list(test_creator()())) == TEST_SIZE + return reader() +def train(): + return reader_creator( + paddle.v2.dataset.common.download( + TRAIN_IMAGE_URL, 'mnist', TRAIN_IMAGE_MD5), + paddle.v2.dataset.common.download( + TRAIN_LABEL_URL, 'mnist', TRAIN_LABEL_MD5), + 100) -if __name__ == '__main__': - unittest() +def test(): + return reader_creator( + paddle.v2.dataset.common.download( + TEST_IMAGE_URL, 'mnist', TEST_IMAGE_MD5), + paddle.v2.dataset.common.download( + TEST_LABEL_URL, 'mnist', TEST_LABEL_MD5), + 100) diff --git a/python/paddle/v2/dataset/tests/mnist_test.py b/python/paddle/v2/dataset/tests/mnist_test.py new file mode 100644 index 00000000000000..23ed2eaba8a761 --- /dev/null +++ b/python/paddle/v2/dataset/tests/mnist_test.py @@ -0,0 +1,27 @@ +import paddle.v2.dataset.mnist +import unittest + +class TestMNIST(unittest.TestCase): + def check_reader(self, reader): + sum = 0 + for l in reader: + self.assertEqual(l[0].size, 784) + self.assertEqual(l[1].size, 1) + self.assertLess(l[1], 10) + self.assertGreaterEqual(l[1], 0) + sum += 1 + return sum + + def test_train(self): + self.assertEqual( + self.check_reader(paddle.v2.dataset.mnist.train()), + 60000) + + def test_test(self): + self.assertEqual( + self.check_reader(paddle.v2.dataset.mnist.test()), + 10000) + + +if __name__ == '__main__': + unittest.main() From 20d9220c9145e937da9f0fb9b99323a06b6983bc Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 28 Feb 2017 10:27:46 +0800 Subject: [PATCH 333/370] change the parameter topology of trainer to cost --- demo/mnist/api_train_v2.py | 2 +- python/paddle/v2/trainer.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index a23ddfaca011e2..8a612cbc66d54b 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -41,7 +41,7 @@ def event_handler(event): trainer.train( train_data_reader=train_reader, - topology=cost, + cost=cost, parameters=parameters, event_handler=event_handler, batch_size=32, # batch size should be refactor in Data reader diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 3bf2128e16b5ad..be33b910807ff3 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -62,7 +62,7 @@ def __init__(self, update_equation): def train(self, train_data_reader, - topology, + cost, parameters, num_passes=1, test_data_reader=None, @@ -73,7 +73,7 @@ def train(self, Training method. Will train num_passes of input data. :param train_data_reader: - :param topology: cost layers, use one or more Layers to represent it. + :param cost: cost layers, to be optimized. :param parameters: The parameter pools. :param num_passes: The total train passes. :param test_data_reader: @@ -86,7 +86,7 @@ def train(self, if event_handler is None: event_handler = default_event_handler - topology = Topology(topology) + topology = Topology(cost) __check_train_args__(**locals()) From 5f5e5c32e50099df02e516647192c5a07b588f99 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 28 Feb 2017 10:33:46 +0800 Subject: [PATCH 334/370] modify train in ITrainer --- python/paddle/v2/trainer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index be33b910807ff3..2aeddaff89748e 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -29,7 +29,7 @@ class ITrainer(object): def train(self, train_data_reader, - topology, + cost, parameters, test_data_reader=None, event_handler=None): @@ -37,7 +37,7 @@ def train(self, train method. :param train_data_reader: - :param topology: + :param cost: :param parameters: :param test_data_reader: :param event_handler: From dcbfbb15338e0ca0f195e12ce0e0275995622ca1 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 28 Feb 2017 02:46:31 +0000 Subject: [PATCH 335/370] yapf format --- python/paddle/v2/dataset/mnist.py | 34 +++++++++---------- python/paddle/v2/dataset/tests/common_test.py | 9 ++--- python/paddle/v2/dataset/tests/mnist_test.py | 7 ++-- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/python/paddle/v2/dataset/mnist.py b/python/paddle/v2/dataset/mnist.py index 29fc20eae9b06e..ec334d39e6c049 100644 --- a/python/paddle/v2/dataset/mnist.py +++ b/python/paddle/v2/dataset/mnist.py @@ -22,23 +22,21 @@ def reader(): # According to http://stackoverflow.com/a/38061619/724872, we # cannot use standard package gzip here. m = subprocess.Popen(["zcat", image_filename], stdout=subprocess.PIPE) - m.stdout.read(16) # skip some magic bytes + m.stdout.read(16) # skip some magic bytes l = subprocess.Popen(["zcat", label_filename], stdout=subprocess.PIPE) - l.stdout.read(8) # skip some magic bytes + l.stdout.read(8) # skip some magic bytes while True: labels = numpy.fromfile( - l.stdout, 'ubyte', count=buffer_size - ).astype("int") + l.stdout, 'ubyte', count=buffer_size).astype("int") if labels.size != buffer_size: - break # numpy.fromfile returns empty slice after EOF. + break # numpy.fromfile returns empty slice after EOF. images = numpy.fromfile( - m.stdout, 'ubyte', count=buffer_size * 28 * 28 - ).reshape((buffer_size, 28 * 28) - ).astype('float32') + m.stdout, 'ubyte', count=buffer_size * 28 * 28).reshape( + (buffer_size, 28 * 28)).astype('float32') images = images / 255.0 * 2.0 - 1.0 @@ -50,18 +48,18 @@ def reader(): return reader() + def train(): return reader_creator( - paddle.v2.dataset.common.download( - TRAIN_IMAGE_URL, 'mnist', TRAIN_IMAGE_MD5), - paddle.v2.dataset.common.download( - TRAIN_LABEL_URL, 'mnist', TRAIN_LABEL_MD5), - 100) + paddle.v2.dataset.common.download(TRAIN_IMAGE_URL, 'mnist', + TRAIN_IMAGE_MD5), + paddle.v2.dataset.common.download(TRAIN_LABEL_URL, 'mnist', + TRAIN_LABEL_MD5), 100) + def test(): return reader_creator( - paddle.v2.dataset.common.download( - TEST_IMAGE_URL, 'mnist', TEST_IMAGE_MD5), - paddle.v2.dataset.common.download( - TEST_LABEL_URL, 'mnist', TEST_LABEL_MD5), - 100) + paddle.v2.dataset.common.download(TEST_IMAGE_URL, 'mnist', + TEST_IMAGE_MD5), + paddle.v2.dataset.common.download(TEST_LABEL_URL, 'mnist', + TEST_LABEL_MD5), 100) diff --git a/python/paddle/v2/dataset/tests/common_test.py b/python/paddle/v2/dataset/tests/common_test.py index 0672a4671430a9..7d8406171b8478 100644 --- a/python/paddle/v2/dataset/tests/common_test.py +++ b/python/paddle/v2/dataset/tests/common_test.py @@ -2,14 +2,14 @@ import unittest import tempfile + class TestCommon(unittest.TestCase): def test_md5file(self): - _, temp_path =tempfile.mkstemp() + _, temp_path = tempfile.mkstemp() with open(temp_path, 'w') as f: f.write("Hello\n") - self.assertEqual( - '09f7e02f1290be211da707a266f153b3', - paddle.v2.dataset.common.md5file(temp_path)) + self.assertEqual('09f7e02f1290be211da707a266f153b3', + paddle.v2.dataset.common.md5file(temp_path)) def test_download(self): yi_avatar = 'https://avatars0.githubusercontent.com/u/1548775?v=3&s=460' @@ -18,5 +18,6 @@ def test_download(self): paddle.v2.dataset.common.download( yi_avatar, 'test', 'f75287202d6622414c706c36c16f8e0d')) + if __name__ == '__main__': unittest.main() diff --git a/python/paddle/v2/dataset/tests/mnist_test.py b/python/paddle/v2/dataset/tests/mnist_test.py index 23ed2eaba8a761..e4f0b33d5207b2 100644 --- a/python/paddle/v2/dataset/tests/mnist_test.py +++ b/python/paddle/v2/dataset/tests/mnist_test.py @@ -1,6 +1,7 @@ import paddle.v2.dataset.mnist import unittest + class TestMNIST(unittest.TestCase): def check_reader(self, reader): sum = 0 @@ -14,13 +15,11 @@ def check_reader(self, reader): def test_train(self): self.assertEqual( - self.check_reader(paddle.v2.dataset.mnist.train()), - 60000) + self.check_reader(paddle.v2.dataset.mnist.train()), 60000) def test_test(self): self.assertEqual( - self.check_reader(paddle.v2.dataset.mnist.test()), - 10000) + self.check_reader(paddle.v2.dataset.mnist.test()), 10000) if __name__ == '__main__': From 6bc82c8eb8478e2fe0911a8e43ddc7ed3539a372 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 28 Feb 2017 02:56:48 +0000 Subject: [PATCH 336/370] Add __all__ to mnist.py --- python/paddle/v2/dataset/mnist.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/python/paddle/v2/dataset/mnist.py b/python/paddle/v2/dataset/mnist.py index ec334d39e6c049..8ba11ca5ec7943 100644 --- a/python/paddle/v2/dataset/mnist.py +++ b/python/paddle/v2/dataset/mnist.py @@ -2,17 +2,16 @@ import subprocess import numpy +__all__ = ['train', 'test'] + URL_PREFIX = 'http://yann.lecun.com/exdb/mnist/' TEST_IMAGE_URL = URL_PREFIX + 't10k-images-idx3-ubyte.gz' TEST_IMAGE_MD5 = '25e3cc63507ef6e98d5dc541e8672bb6' - TEST_LABEL_URL = URL_PREFIX + 't10k-labels-idx1-ubyte.gz' TEST_LABEL_MD5 = '4e9511fe019b2189026bd0421ba7b688' - TRAIN_IMAGE_URL = URL_PREFIX + 'train-images-idx3-ubyte.gz' TRAIN_IMAGE_MD5 = 'f68b3c2dcbeaaa9fbdd348bbdeb94873' - TRAIN_LABEL_URL = URL_PREFIX + 'train-labels-idx1-ubyte.gz' TRAIN_LABEL_MD5 = 'd53e105ee54ea40749a09fcbcd1e9432' From 7664f78fd9b75f96f011f67a034fc28148791adb Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Tue, 28 Feb 2017 11:28:39 +0800 Subject: [PATCH 337/370] fix dead link --- doc/howto/usage/cluster/cluster_train_cn.md | 2 +- doc/howto/usage/cluster/cluster_train_en.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/howto/usage/cluster/cluster_train_cn.md b/doc/howto/usage/cluster/cluster_train_cn.md index acdcfa1c0047ce..274452fbf0c595 100644 --- a/doc/howto/usage/cluster/cluster_train_cn.md +++ b/doc/howto/usage/cluster/cluster_train_cn.md @@ -6,7 +6,7 @@ 在本文中,我们将阐释如何在集群上运行分布式 Paddle 训练作业。我们将以[推荐系统](https://github.com/baidu/Paddle/tree/develop/demo/recommendation)为例创建分布式的单进程训练。 -在本文中使用的[脚本](https://github.com/baidu/Paddle/tree/develop/paddle/scripts/cluster_train)通过 SSH 运行分布式作业。 它们还可以供那些运行更复杂的集群管理系统(如 MPI 和 [Kubernetes](https://github.com/PaddlePaddle/Paddle/tree/develop/doc/howto/usage/cluster/k8s) )的用户参考。 +在本文中使用的[脚本](https://github.com/baidu/Paddle/tree/develop/paddle/scripts/cluster_train)通过 SSH 运行分布式作业。 它们还可以供那些运行更复杂的集群管理系统(如 MPI 和 [Kubernetes](https://github.com/PaddlePaddle/Paddle/tree/develop/doc/howto/usage/k8s) )的用户参考。 ## 前提条件 diff --git a/doc/howto/usage/cluster/cluster_train_en.md b/doc/howto/usage/cluster/cluster_train_en.md index 30963dcd927250..c60876721cbf55 100644 --- a/doc/howto/usage/cluster/cluster_train_en.md +++ b/doc/howto/usage/cluster/cluster_train_en.md @@ -2,7 +2,7 @@ In this article, we explain how to run distributed Paddle training jobs on clusters. We will create the distributed version of the single-process training example, [recommendation](https://github.com/baidu/Paddle/tree/develop/demo/recommendation). -[Scripts](https://github.com/baidu/Paddle/tree/develop/paddle/scripts/cluster_train) used in this article launch distributed jobs via SSH. They also work as a reference for users running more sophisticated cluster management systems like MPI and [Kubernetes](https://github.com/PaddlePaddle/Paddle/tree/develop/doc/howto/usage/cluster/k8s). +[Scripts](https://github.com/baidu/Paddle/tree/develop/paddle/scripts/cluster_train) used in this article launch distributed jobs via SSH. They also work as a reference for users running more sophisticated cluster management systems like MPI and [Kubernetes](https://github.com/PaddlePaddle/Paddle/tree/develop/doc/howto/usage/k8s). ## Prerequisite From 4eb54c2437aef7c857151a2a3e4fd24aa51d5336 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 28 Feb 2017 04:30:30 +0000 Subject: [PATCH 338/370] Debug unit tests --- python/paddle/v2/dataset/cifar.py | 85 ++++++++------------ python/paddle/v2/dataset/common.py | 1 - python/paddle/v2/dataset/mnist.py | 10 ++- python/paddle/v2/dataset/tests/cifar_test.py | 42 ++++++++++ python/paddle/v2/dataset/tests/mnist_test.py | 22 ++--- 5 files changed, 93 insertions(+), 67 deletions(-) create mode 100644 python/paddle/v2/dataset/tests/cifar_test.py diff --git a/python/paddle/v2/dataset/cifar.py b/python/paddle/v2/dataset/cifar.py index accb32f117720f..77c54bd268b5d9 100644 --- a/python/paddle/v2/dataset/cifar.py +++ b/python/paddle/v2/dataset/cifar.py @@ -1,82 +1,61 @@ """ -CIFAR Dataset. - -URL: https://www.cs.toronto.edu/~kriz/cifar.html - -the default train_creator, test_creator used for CIFAR-10 dataset. +CIFAR dataset: https://www.cs.toronto.edu/~kriz/cifar.html """ import cPickle import itertools -import tarfile - import numpy +import paddle.v2.dataset.common +import tarfile -from common import download - -__all__ = [ - 'cifar_100_train_creator', 'cifar_100_test_creator', 'train_creator', - 'test_creator' -] +__all__ = ['train100', 'test100', 'train10', 'test10'] -CIFAR10_URL = 'https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz' +URL_PREFIX = 'https://www.cs.toronto.edu/~kriz/' +CIFAR10_URL = URL_PREFIX + 'cifar-10-python.tar.gz' CIFAR10_MD5 = 'c58f30108f718f92721af3b95e74349a' -CIFAR100_URL = 'https://www.cs.toronto.edu/~kriz/cifar-100-python.tar.gz' +CIFAR100_URL = URL_PREFIX + 'cifar-100-python.tar.gz' CIFAR100_MD5 = 'eb9058c3a382ffc7106e4002c42a8d85' -def __read_batch__(filename, sub_name): - def reader(): - def __read_one_batch_impl__(batch): - data = batch['data'] - labels = batch.get('labels', batch.get('fine_labels', None)) - assert labels is not None - for sample, label in itertools.izip(data, labels): - yield (sample / 255.0).astype(numpy.float32), int(label) +def reader_creator(filename, sub_name): + def read_batch(batch): + data = batch['data'] + labels = batch.get('labels', batch.get('fine_labels', None)) + assert labels is not None + for sample, label in itertools.izip(data, labels): + yield (sample / 255.0).astype(numpy.float32), int(label) + def reader(): with tarfile.open(filename, mode='r') as f: names = (each_item.name for each_item in f if sub_name in each_item.name) for name in names: batch = cPickle.load(f.extractfile(name)) - for item in __read_one_batch_impl__(batch): + for item in read_batch(batch): yield item return reader -def cifar_100_train_creator(): - fn = download(url=CIFAR100_URL, md5=CIFAR100_MD5) - return __read_batch__(fn, 'train') - - -def cifar_100_test_creator(): - fn = download(url=CIFAR100_URL, md5=CIFAR100_MD5) - return __read_batch__(fn, 'test') - - -def train_creator(): - """ - Default train reader creator. Use CIFAR-10 dataset. - """ - fn = download(url=CIFAR10_URL, md5=CIFAR10_MD5) - return __read_batch__(fn, 'data_batch') +def train100(): + return reader_creator( + paddle.v2.dataset.common.download(CIFAR100_URL, 'cifar', CIFAR100_MD5), + 'train') -def test_creator(): - """ - Default test reader creator. Use CIFAR-10 dataset. - """ - fn = download(url=CIFAR10_URL, md5=CIFAR10_MD5) - return __read_batch__(fn, 'test_batch') +def test100(): + return reader_creator( + paddle.v2.dataset.common.download(CIFAR100_URL, 'cifar', CIFAR100_MD5), + 'test') -def unittest(): - for _ in train_creator()(): - pass - for _ in test_creator()(): - pass +def train10(): + return reader_creator( + paddle.v2.dataset.common.download(CIFAR10_URL, 'cifar', CIFAR10_MD5), + 'data_batch') -if __name__ == '__main__': - unittest() +def test10(): + return reader_creator( + paddle.v2.dataset.common.download(CIFAR10_URL, 'cifar', CIFAR10_MD5), + 'test_batch') diff --git a/python/paddle/v2/dataset/common.py b/python/paddle/v2/dataset/common.py index b1831f38afb4f1..a5ffe25a116e9b 100644 --- a/python/paddle/v2/dataset/common.py +++ b/python/paddle/v2/dataset/common.py @@ -27,7 +27,6 @@ def download(url, module_name, md5sum): filename = os.path.join(dirname, url.split('/')[-1]) if not (os.path.exists(filename) and md5file(filename) == md5sum): - # If file doesn't exist or MD5 doesn't match, then download. r = requests.get(url, stream=True) with open(filename, 'w') as f: shutil.copyfileobj(r.raw, f) diff --git a/python/paddle/v2/dataset/mnist.py b/python/paddle/v2/dataset/mnist.py index 8ba11ca5ec7943..a36c20e3fa3734 100644 --- a/python/paddle/v2/dataset/mnist.py +++ b/python/paddle/v2/dataset/mnist.py @@ -1,11 +1,13 @@ +""" +MNIST dataset. +""" +import numpy import paddle.v2.dataset.common import subprocess -import numpy __all__ = ['train', 'test'] URL_PREFIX = 'http://yann.lecun.com/exdb/mnist/' - TEST_IMAGE_URL = URL_PREFIX + 't10k-images-idx3-ubyte.gz' TEST_IMAGE_MD5 = '25e3cc63507ef6e98d5dc541e8672bb6' TEST_LABEL_URL = URL_PREFIX + 't10k-labels-idx1-ubyte.gz' @@ -40,12 +42,12 @@ def reader(): images = images / 255.0 * 2.0 - 1.0 for i in xrange(buffer_size): - yield images[i, :], labels[i] + yield images[i, :], int(labels[i]) m.terminate() l.terminate() - return reader() + return reader def train(): diff --git a/python/paddle/v2/dataset/tests/cifar_test.py b/python/paddle/v2/dataset/tests/cifar_test.py new file mode 100644 index 00000000000000..a2af45ecf50846 --- /dev/null +++ b/python/paddle/v2/dataset/tests/cifar_test.py @@ -0,0 +1,42 @@ +import paddle.v2.dataset.cifar +import unittest + + +class TestCIFAR(unittest.TestCase): + def check_reader(self, reader): + sum = 0 + label = 0 + for l in reader(): + self.assertEqual(l[0].size, 3072) + if l[1] > label: + label = l[1] + sum += 1 + return sum, label + + def test_test10(self): + instances, max_label_value = self.check_reader( + paddle.v2.dataset.cifar.test10()) + self.assertEqual(instances, 10000) + self.assertEqual(max_label_value, 9) + + def test_train10(self): + instances, max_label_value = self.check_reader( + paddle.v2.dataset.cifar.train10()) + self.assertEqual(instances, 50000) + self.assertEqual(max_label_value, 9) + + def test_test100(self): + instances, max_label_value = self.check_reader( + paddle.v2.dataset.cifar.test100()) + self.assertEqual(instances, 10000) + self.assertEqual(max_label_value, 99) + + def test_train100(self): + instances, max_label_value = self.check_reader( + paddle.v2.dataset.cifar.train100()) + self.assertEqual(instances, 50000) + self.assertEqual(max_label_value, 99) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/paddle/v2/dataset/tests/mnist_test.py b/python/paddle/v2/dataset/tests/mnist_test.py index e4f0b33d5207b2..b4408cc2f590d4 100644 --- a/python/paddle/v2/dataset/tests/mnist_test.py +++ b/python/paddle/v2/dataset/tests/mnist_test.py @@ -5,21 +5,25 @@ class TestMNIST(unittest.TestCase): def check_reader(self, reader): sum = 0 - for l in reader: + label = 0 + for l in reader(): self.assertEqual(l[0].size, 784) - self.assertEqual(l[1].size, 1) - self.assertLess(l[1], 10) - self.assertGreaterEqual(l[1], 0) + if l[1] > label: + label = l[1] sum += 1 - return sum + return sum, label def test_train(self): - self.assertEqual( - self.check_reader(paddle.v2.dataset.mnist.train()), 60000) + instances, max_label_value = self.check_reader( + paddle.v2.dataset.mnist.train()) + self.assertEqual(instances, 60000) + self.assertEqual(max_label_value, 9) def test_test(self): - self.assertEqual( - self.check_reader(paddle.v2.dataset.mnist.test()), 10000) + instances, max_label_value = self.check_reader( + paddle.v2.dataset.mnist.test()) + self.assertEqual(instances, 10000) + self.assertEqual(max_label_value, 9) if __name__ == '__main__': From 375899339330d00852433ced1b7f02663040c7fb Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 28 Feb 2017 13:29:24 +0800 Subject: [PATCH 339/370] Simplify layer.v2 --- .../default_decorators.py | 4 + .../paddle/trainer_config_helpers/layers.py | 6 + python/paddle/v2/layer.py | 143 ++++++------------ python/paddle/v2/tests/test_layer.py | 6 +- 4 files changed, 61 insertions(+), 98 deletions(-) diff --git a/python/paddle/trainer_config_helpers/default_decorators.py b/python/paddle/trainer_config_helpers/default_decorators.py index ad3efcbf369411..2f25579fcdd979 100644 --- a/python/paddle/trainer_config_helpers/default_decorators.py +++ b/python/paddle/trainer_config_helpers/default_decorators.py @@ -52,6 +52,10 @@ def __wrapper__(*args, **kwargs): kwargs[name] = default_factory(func) return func(*args, **kwargs) + if hasattr(func, 'argspec'): + __wrapper__.argspec = func.argspec + else: + __wrapper__.argspec = inspect.getargspec(func) return __wrapper__ return __impl__ diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 1bb1a01d509e64..b68460b6a3ab62 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -14,6 +14,7 @@ import functools import collections +import inspect from paddle.trainer.config_parser import * from .activations import LinearActivation, SigmoidActivation, TanhActivation, \ @@ -316,6 +317,11 @@ def wrapper(*args, **kwargs): val.check(method.__name__) return method(*args, **kwargs) + if hasattr(method, 'argspec'): + wrapper.argspec = method.argspec + else: + wrapper.argspec = inspect.getargspec(method) + return wrapper return decorator diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index d15e6398f51f43..d68b66cf02ce89 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -67,6 +67,7 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. """ import collections +import inspect import paddle.trainer_config_helpers as conf_helps from paddle.trainer_config_helpers.config_parser_utils import \ @@ -74,26 +75,14 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. from paddle.trainer_config_helpers.default_decorators import wrap_name_default from paddle.trainer_config_helpers.default_decorators import wrap_act_default -from paddle.trainer_config_helpers.default_decorators import wrap_bias_attr_default +from paddle.trainer_config_helpers.default_decorators import \ + wrap_bias_attr_default from paddle.trainer_config_helpers.layers import layer_support import data_type import activation -import attr - -__all__ = [ - 'parse_network', 'data', 'fc', 'conv_shift', 'img_conv', 'img_pool', 'spp', - 'maxout', 'img_cmrnorm', 'batch_norm', 'sum_to_one_norm', 'recurrent', - 'lstmemory', 'grumemory', 'pool', 'last_seq', 'first_seq', 'concat', - 'seq_concat', 'block_expand', 'expand', 'repeat', 'seq_reshape', 'addto', - 'linear_comb', 'interpolation', 'bilinear_interp', 'power', 'scaling', - 'slope_intercept', 'tensor', 'cos_sim', 'trans', 'max_id', 'sampling_id', - 'pad', 'classification_cost', 'cross_entropy_cost', - 'cross_entropy_with_selfnorm_cost', 'regression_cost', - 'multi_binary_label_cross_entropy_cost', 'rank_cost', 'lambda_cost', - 'sum_cost', 'huber_cost', 'crf', 'crf_decoding', 'ctc', 'warp_ctc', 'nce', - 'hsigmoid', 'eos' -] + +__all__ = ['parse_network', 'data'] __projection_names__ = filter(lambda x: x.endswith('_projection'), dir(conf_helps)) @@ -288,83 +277,51 @@ def mixed(size=0, AggregateLevel = conf_helps.layers.AggregateLevel ExpandLevel = conf_helps.layers.ExpandLevel -layer_list = [ - # [V2LayerImpl, V1_method_name, parent_names] - # fully connected layers - ['fc', 'fc_layer', ['input']], - # conv layers - ['conv_shift', 'conv_shift_layer', ['a', 'b']], - ['img_conv', 'img_conv_layer', ['input']], - # image pooling layers - ['img_pool', 'img_pool_layer', ['input']], - ['spp', 'spp_layer', ['input']], - ['maxout', 'maxout_layer', ['input']], - # norm layers - ['img_cmrnorm', 'img_cmrnorm_layer', ['input']], - ['batch_norm', 'batch_norm_layer', ['input']], - ['sum_to_one_norm', 'sum_to_one_norm_layer', ['input']], - # recurrent layers - ['recurrent', 'recurrent_layer', ['input']], - ['lstmemory', 'lstmemory', ['input']], - ['grumemory', 'grumemory', ['input']], - # aggregate layers - ['pool', 'pooling_layer', ['input']], - ['last_seq', 'last_seq', ['input']], - ['first_seq', 'first_seq', ['input']], - ['concat', 'concat_layer', ['input']], - ['seq_concat', 'seq_concat_layer', ['a', 'b']], - # reshaping layers - ['block_expand', 'block_expand_layer', ['input']], - ['expand', 'expand_layer', ['input', 'expand_as']], - ['repeat', 'repeat_layer', ['input']], - ['rotate', 'rotate_layer', ['input']], - ['seq_reshape', 'seq_reshape_layer', ['input']], - # math layers - ['addto', 'addto_layer', ['input']], - ['linear_comb', 'linear_comb_layer', ['weights', 'vectors']], - ['interpolation', 'interpolation_layer', ['input', 'weight']], - ['bilinear_interp', 'bilinear_interp_layer', ['input']], - ['power', 'power_layer', ['input', 'weight']], - ['scaling', 'scaling_layer', ['input', 'weight']], - ['slope_intercept', 'slope_intercept_layer', ['input']], - ['tensor', 'tensor_layer', ['a', 'b']], - ['cos_sim', 'cos_sim', ['a', 'b']], - ['trans', 'trans_layer', ['input']], - # sampling layers - ['max_id', 'maxid_layer', ['input']], - ['sampling_id', 'sampling_id_layer', ['input']], - # slicing and joining layers - ['pad', 'pad_layer', ['input']], - # cost layers - [ - 'classification_cost', 'classification_cost', - ['input', 'label', 'weight'] - ], - ['regression_cost', 'regression_cost', ['input', 'label', 'weight']], - ['cross_entropy_cost', 'cross_entropy', ['input', 'label']], - [ - 'cross_entropy_with_selfnorm_cost', 'cross_entropy_with_selfnorm', - ['input', 'label'] - ], - [ - 'multi_binary_label_cross_entropy_cost', - 'multi_binary_label_cross_entropy', ['input', 'label'] - ], - ['rank_cost', 'rank_cost', ['left', 'right', 'label', 'weight']], - ['lambda_cost', 'lambda_cost', ['input', 'score']], - ['sum_cost', 'sum_cost', ['input']], - ['huber_cost', 'huber_cost', ['input', 'label']], - ['crf', 'crf_layer', ['input', 'label']], - ['crf_decoding', 'crf_decoding_layer', ['input']], - ['ctc', 'ctc_layer', ['input', 'label']], - ['warp_ctc', 'warp_ctc_layer', ['input', 'label']], - ['nce', 'nce_layer', ['input', 'label']], - ['hsigmoid', 'hsigmoid', ['input', 'label']], - # check layers - ['eos', 'eos_layer', ['input']] -] -for l in layer_list: - globals()[l[0]] = __convert_to_v2__(l[1], l[2]) + +def __layer_name_mapping__(inname): + if inname in ['data_layer', 'memory', 'mixed_layer']: + # Do Not handle these layers + return + elif inname == 'maxid_layer': + return 'max_id' + elif inname.endswith('memory') or inname.endswith( + '_seq') or inname.endswith('_sim') or inname == 'hsigmoid': + return inname + elif inname in [ + 'cross_entropy', 'multi_binary_label_cross_entropy', + 'cross_entropy_with_selfnorm' + ]: + return inname + "_cost" + elif inname.endswith('_cost'): + return inname + elif inname.endswith("_layer"): + return inname[:-len("_layer")] + + +def __layer_name_mapping_parent_names__(inname): + all_args = getattr(conf_helps, inname).argspec.args + return filter( + lambda x: x in ['input1', 'input2','label', 'input', 'a', 'b', 'expand_as', + 'weights', 'vectors', 'weight', 'score', 'left', 'right'], + all_args) + + +def __convert_layer__(_new_name_, _old_name_, _parent_names_): + global __all__ + __all__.append(_new_name_) + globals()[new_name] = __convert_to_v2__(_old_name_, _parent_names_) + + +for each_layer_name in dir(conf_helps): + new_name = __layer_name_mapping__(each_layer_name) + if new_name is not None: + parent_names = __layer_name_mapping_parent_names__(each_layer_name) + assert len(parent_names) != 0, each_layer_name + __convert_layer__(new_name, each_layer_name, parent_names) + +del parent_names +del new_name +del each_layer_name # convert projection for prj in __projection_names__: diff --git a/python/paddle/v2/tests/test_layer.py b/python/paddle/v2/tests/test_layer.py index bb0099ea2fbb78..b138ddbbe6c0a4 100644 --- a/python/paddle/v2/tests/test_layer.py +++ b/python/paddle/v2/tests/test_layer.py @@ -11,17 +11,13 @@ # 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. -import difflib import unittest -import paddle.trainer_config_helpers as conf_helps import paddle.v2.activation as activation import paddle.v2.attr as attr import paddle.v2.data_type as data_type import paddle.v2.layer as layer import paddle.v2.pooling as pooling -from paddle.trainer_config_helpers.config_parser_utils import \ - parse_network_config as parse_network pixel = layer.data(name='pixel', type=data_type.dense_vector(128)) label = layer.data(name='label', type=data_type.integer_value(10)) @@ -70,7 +66,7 @@ def test_norm_layer(self): class AggregateLayerTest(unittest.TestCase): def test_aggregate_layer(self): - pool = layer.pool( + pool = layer.pooling( input=pixel, pooling_type=pooling.Avg(), agg_level=layer.AggregateLevel.EACH_SEQUENCE) From 0432e9073984d0c7ce3329043cb3d6fe6ef65a8a Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 28 Feb 2017 13:44:38 +0800 Subject: [PATCH 340/370] remove unused python package in TravisCI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 31d76ecb876f11..4fb2ca938795bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,7 @@ before_install: - if [[ "$JOB" == "PRE_COMMIT" ]]; then sudo ln -s /usr/bin/clang-format-3.8 /usr/bin/clang-format; fi # 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 'scikit-learn>=0.18.0' 'scipy>=0.18.0' + - pip install numpy wheel 'protobuf==3.1' sphinx recommonmark sphinx_rtd_theme virtualenv pre-commit requests==2.9.2 LinkChecker script: - paddle/scripts/travis/main.sh notifications: From 01ad3bfdb9daf494967a0789bcad09057c11bdb6 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 28 Feb 2017 13:52:57 +0800 Subject: [PATCH 341/370] Fix reader creator in mnist --- demo/mnist/api_train_v2.py | 2 +- python/paddle/v2/dataset/mnist.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index c9fd7c72df8794..1c2c831bec18ef 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -33,7 +33,7 @@ def event_handler(event): trainer.train( reader=paddle.reader.batched( paddle.reader.shuffle( - paddle.dataset.mnist.train_creator(), buf_size=8192), + paddle.dataset.mnist.train(), buf_size=8192), batch_size=32), cost=cost, parameters=parameters, diff --git a/python/paddle/v2/dataset/mnist.py b/python/paddle/v2/dataset/mnist.py index 8ba11ca5ec7943..653c91aacde661 100644 --- a/python/paddle/v2/dataset/mnist.py +++ b/python/paddle/v2/dataset/mnist.py @@ -45,7 +45,7 @@ def reader(): m.terminate() l.terminate() - return reader() + return reader def train(): From c852003d6b2e11c8d0f75d5c0adf9d332dc429f1 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 28 Feb 2017 14:00:22 +0800 Subject: [PATCH 342/370] Fix errors in mnist dataset --- demo/mnist/api_train_v2.py | 1 - python/paddle/v2/dataset/mnist.py | 12 ++++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 1c2c831bec18ef..612b0d218fc0be 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -38,7 +38,6 @@ def event_handler(event): cost=cost, parameters=parameters, event_handler=event_handler, - batch_size=32, # batch size should be refactor in Data reader reader_dict={images.name: 0, label.name: 1}) diff --git a/python/paddle/v2/dataset/mnist.py b/python/paddle/v2/dataset/mnist.py index 653c91aacde661..045bcfcc805ec0 100644 --- a/python/paddle/v2/dataset/mnist.py +++ b/python/paddle/v2/dataset/mnist.py @@ -1,6 +1,7 @@ import paddle.v2.dataset.common import subprocess import numpy +import platform __all__ = ['train', 'test'] @@ -18,12 +19,19 @@ def reader_creator(image_filename, label_filename, buffer_size): def reader(): + if platform.system() == 'Darwin': + zcat_cmd = 'gzcat' + elif platform.system() == 'Linux': + zcat_cmd = 'zcat' + else: + raise NotImplementedError() + # According to http://stackoverflow.com/a/38061619/724872, we # cannot use standard package gzip here. - m = subprocess.Popen(["zcat", image_filename], stdout=subprocess.PIPE) + m = subprocess.Popen([zcat_cmd, image_filename], stdout=subprocess.PIPE) m.stdout.read(16) # skip some magic bytes - l = subprocess.Popen(["zcat", label_filename], stdout=subprocess.PIPE) + l = subprocess.Popen([zcat_cmd, label_filename], stdout=subprocess.PIPE) l.stdout.read(8) # skip some magic bytes while True: From faa43e3682a993450653904c9a66ad7f37c182f3 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 28 Feb 2017 14:02:09 +0800 Subject: [PATCH 343/370] Remove unused dependencies --- python/setup.py.in | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/python/setup.py.in b/python/setup.py.in index c7e46293b79fe0..68ca35265cf132 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -15,9 +15,5 @@ setup(name='paddle', packages=packages, package_dir={ '': '${CMAKE_CURRENT_SOURCE_DIR}' - }, - install_requires = [ - 'scikit-learn>=0.18.0', - 'scipy>=0.18.0', - ] + } ) From 43d92fa8335dc61d5337e9de12c7e6f48dedd71c Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 28 Feb 2017 14:49:48 +0800 Subject: [PATCH 344/370] Make api_train_v2 runnable --- demo/mnist/api_train_v2.py | 4 ++-- python/paddle/v2/dataset/mnist.py | 4 ++-- python/paddle/v2/trainer.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 19e273ebfd96d7..a59b30ccdb2edd 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -20,7 +20,7 @@ def main(): adam_optimizer = paddle.optimizer.Adam(learning_rate=0.01) - trainer = paddle.trainer.SGD(topology=cost, + trainer = paddle.trainer.SGD(cost=cost, parameters=parameters, update_equation=adam_optimizer) @@ -28,7 +28,7 @@ def event_handler(event): if isinstance(event, paddle.event.EndIteration): if event.batch_id % 1000 == 0: result = trainer.test(reader=paddle.reader.batched( - paddle.dataset.mnist.test_creator(), batch_size=256)) + paddle.dataset.mnist.test(), batch_size=256)) print "Pass %d, Batch %d, Cost %f, %s, Testing metrics %s" % ( event.pass_id, event.batch_id, event.cost, event.metrics, diff --git a/python/paddle/v2/dataset/mnist.py b/python/paddle/v2/dataset/mnist.py index f1315b35cd55c5..1512a3c3189de4 100644 --- a/python/paddle/v2/dataset/mnist.py +++ b/python/paddle/v2/dataset/mnist.py @@ -9,9 +9,9 @@ URL_PREFIX = 'http://yann.lecun.com/exdb/mnist/' TEST_IMAGE_URL = URL_PREFIX + 't10k-images-idx3-ubyte.gz' -TEST_IMAGE_MD5 = '25e3cc63507ef6e98d5dc541e8672bb6' +TEST_IMAGE_MD5 = '9fb629c4189551a2d022fa330f9573f3' TEST_LABEL_URL = URL_PREFIX + 't10k-labels-idx1-ubyte.gz' -TEST_LABEL_MD5 = '4e9511fe019b2189026bd0421ba7b688' +TEST_LABEL_MD5 = 'ec29112dd5afa0611ce80d1b7f02629c' TRAIN_IMAGE_URL = URL_PREFIX + 'train-images-idx3-ubyte.gz' TRAIN_IMAGE_MD5 = 'f68b3c2dcbeaaa9fbdd348bbdeb94873' TRAIN_LABEL_URL = URL_PREFIX + 'train-labels-idx1-ubyte.gz' diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index b7d69ddb5d9071..5003f55f3e0d15 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -61,7 +61,7 @@ def __init__(self, cost, parameters, update_equation): self.__topology__ = topology self.__parameters__ = parameters self.__topology_in_proto__ = topology.proto() - self.__data_types__ = topology.data_layers() + self.__data_types__ = topology.data_type() gm = api.GradientMachine.createFromConfigProto( self.__topology_in_proto__, api.CREATE_MODE_NORMAL, self.__optimizer__.enable_types()) From eee1320b873f4dcfd78857d80aa06a99cca90916 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 28 Feb 2017 14:55:09 +0800 Subject: [PATCH 345/370] Change code style --- python/paddle/v2/reader/decorator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/paddle/v2/reader/decorator.py b/python/paddle/v2/reader/decorator.py index d83e2f4577f20b..5687f118ce2779 100644 --- a/python/paddle/v2/reader/decorator.py +++ b/python/paddle/v2/reader/decorator.py @@ -201,7 +201,7 @@ def batched(reader, batch_size): :return: the batched reader. """ - def __impl__(): + def batched_reader(): r = reader() batch = [] for instance in r: @@ -212,4 +212,4 @@ def __impl__(): if batch: yield batch - return __impl__ + return batched_reader From b18d5a846fc60ab958acebabb6c53e6a4f300d8d Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Tue, 28 Feb 2017 15:15:36 +0800 Subject: [PATCH 346/370] fix compile error --- paddle/function/CosSimOpGpu.cu | 1 - 1 file changed, 1 deletion(-) diff --git a/paddle/function/CosSimOpGpu.cu b/paddle/function/CosSimOpGpu.cu index 1dd733674fa054..c62ab39551f022 100644 --- a/paddle/function/CosSimOpGpu.cu +++ b/paddle/function/CosSimOpGpu.cu @@ -92,7 +92,6 @@ void CosSimForward(GpuMatrix& out_mat, 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(); From d312352a2f1d99806be2259ae12340464127c124 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Tue, 28 Feb 2017 17:04:53 +0800 Subject: [PATCH 347/370] fix dataprovider_converter when using only one gpu --- paddle/api/PaddleAPI.h | 3 +++ paddle/api/Util.cpp | 2 ++ paddle/py_paddle/dataprovider_converter.py | 21 +++++++++++++++------ python/paddle/v2/tests/test_data_feeder.py | 5 +++++ 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/paddle/api/PaddleAPI.h b/paddle/api/PaddleAPI.h index 1831b8e170087c..0223dec4f42efe 100644 --- a/paddle/api/PaddleAPI.h +++ b/paddle/api/PaddleAPI.h @@ -47,6 +47,9 @@ void setUseGpu(bool useGpu); /// Return true if this py_paddle is compiled in GPU Version bool isGpuVersion(); +/// Return FLAGS_use_gpu +int getTrainerCount(); + /// The Error of IO Operation. Such as file not found, etc. class IOError {}; diff --git a/paddle/api/Util.cpp b/paddle/api/Util.cpp index 54d67aa62f4d87..d369df5d4e04b4 100644 --- a/paddle/api/Util.cpp +++ b/paddle/api/Util.cpp @@ -54,5 +54,7 @@ bool isGpuVersion() { #endif } +int getTrainerCount() { return FLAGS_trainer_count; } + static_assert(NUM_PARAMETER_TYPES == paddle::NUM_PARAMETER_TYPES, "The Parameter Type should be same in core/api and core/common"); diff --git a/paddle/py_paddle/dataprovider_converter.py b/paddle/py_paddle/dataprovider_converter.py index 2690cafe1d8d32..8d5c57e10fd358 100644 --- a/paddle/py_paddle/dataprovider_converter.py +++ b/paddle/py_paddle/dataprovider_converter.py @@ -33,6 +33,11 @@ def scan(self, dat): def finish_scan(self, argument): pass + def use_gpu(self): + gpu = True if swig_paddle.isUsingGpu() and ( + swig_paddle.getTrainerCount() == 1) else False + return gpu + class DenseScanner(IScanner): """ @@ -53,7 +58,8 @@ def finish_scan(self, argument): assert isinstance(argument, swig_paddle.Arguments) if self.__mat__.dtype != numpy.float32: self.__mat__ = self.__mat__.astype(numpy.float32) - m = swig_paddle.Matrix.createDenseFromNumpy(self.__mat__, True, False) + m = swig_paddle.Matrix.createDenseFromNumpy(self.__mat__, True, + self.use_gpu()) argument.setSlotValue(self.pos, m) @@ -75,10 +81,13 @@ def extend_cols(self, dat): def finish_scan(self, argument): assert isinstance(argument, swig_paddle.Arguments) - m = swig_paddle.Matrix.createSparse(self.__height__, - self.input_type.dim, - len(self.__cols__), - len(self.__value__) == 0) + m = swig_paddle.Matrix.createSparse( + self.__height__, + self.input_type.dim, + len(self.__cols__), + len(self.__value__) == 0, + False, # trans + False) # TODO supoort GPU assert isinstance(m, swig_paddle.Matrix) m.sparseCopyFrom(self.__rows__, self.__cols__, self.__value__) argument.setSlotValue(self.pos, m) @@ -102,7 +111,7 @@ def scan(self, dat): self.__ids__.append(dat) def finish_scan(self, argument): - ids = swig_paddle.IVector.create(self.__ids__) + ids = swig_paddle.IVector.create(self.__ids__, self.use_gpu()) assert isinstance(argument, swig_paddle.Arguments) argument.setSlotIds(self.pos, ids) diff --git a/python/paddle/v2/tests/test_data_feeder.py b/python/paddle/v2/tests/test_data_feeder.py index 5f67da6a5b32d7..916d3aa4cdcbca 100644 --- a/python/paddle/v2/tests/test_data_feeder.py +++ b/python/paddle/v2/tests/test_data_feeder.py @@ -235,4 +235,9 @@ def test_multiple_features_tuple(self): if __name__ == '__main__': api.initPaddle("--use_gpu=0") + suite = unittest.TestLoader().loadTestsFromTestCase(DataFeederTest) + unittest.TextTestRunner().run(suite) + if api.isGpuVersion(): + api.setUseGpu(True) + unittest.main() unittest.main() From 60e0df0eeff0ba4155077f2fce93a55c30884028 Mon Sep 17 00:00:00 2001 From: "yi.wu" Date: Tue, 28 Feb 2017 17:19:00 +0800 Subject: [PATCH 348/370] refine k8s distributed training doc --- doc/howto/usage/k8s/k8s_basis.md | 77 +++++++ doc/howto/usage/k8s/k8s_distributed_cn.md | 241 +++++++++----------- doc/howto/usage/k8s/src/k8s-paddle-arch.png | Bin 22084 -> 530508 bytes 3 files changed, 182 insertions(+), 136 deletions(-) create mode 100644 doc/howto/usage/k8s/k8s_basis.md diff --git a/doc/howto/usage/k8s/k8s_basis.md b/doc/howto/usage/k8s/k8s_basis.md new file mode 100644 index 00000000000000..e296d69dceb416 --- /dev/null +++ b/doc/howto/usage/k8s/k8s_basis.md @@ -0,0 +1,77 @@ +# Kubernetes 简介 + +[*Kubernetes*](http://kubernetes.io/)是Google开源的容器集群管理系统,其提供应用部署、维护、 扩展机制等功能,利用Kubernetes能方便地管理跨机器运行容器化的应用。Kubernetes可以在物理机或虚拟机上运行,且支持部署到[AWS](http://kubernetes.io/docs/getting-started-guides/aws),[Azure](http://kubernetes.io/docs/getting-started-guides/azure/),[GCE](http://kubernetes.io/docs/getting-started-guides/gce)等多种公有云环境。介绍分布式训练之前,需要对[Kubernetes](http://kubernetes.io/)有一个基本的认识,下面先简要介绍一下本文用到的几个Kubernetes概念。 + +- [*Node*](http://kubernetes.io/docs/admin/node/) 表示一个Kubernetes集群中的一个工作节点,这个节点可以是物理机或者虚拟机,Kubernetes集群就是由node节点与master节点组成的。 + +- [*Pod*](http://kubernetes.io/docs/user-guide/pods/) 是一组(一个或多个)容器,pod是Kubernetes的最小调度单元,一个pod中的所有容器会被调度到同一个node上。Pod中的容器共享NET,PID,IPC,UTS等Linux namespace。由于容器之间共享NET namespace,所以它们使用同一个IP地址,可以通过*localhost*互相通信。不同pod之间可以通过IP地址访问。 + +- [*Job*](http://kubernetes.io/docs/user-guide/jobs/) 描述Kubernetes上运行的作业,一次作业称为一个job,通常每个job包括一个或者多个pods,job启动后会创建这些pod并开始执行一个程序,等待这个程序执行成功并返回0则成功退出,如果执行失败,也可以配置不同的重试机制。 + +- [*Volume*](http://kubernetes.io/docs/user-guide/volumes/) 存储卷,是pod内的容器都可以访问的共享目录,也是容器与node之间共享文件的方式,因为容器内的文件都是暂时存在的,当容器因为各种原因被销毁时,其内部的文件也会随之消失。通过volume,就可以将这些文件持久化存储。Kubernetes支持多种volume,例如hostPath(宿主机目录),gcePersistentDisk,awsElasticBlockStore等。 + +- [*Namespaces*](https://kubernetes.io/docs/user-guide/namespaces/) 命名空间,在kubernetes中创建的所有资源对象(例如上文的pod,job)等都属于一个命名空间,在同一个命名空间中,资源对象的名字是唯一的,不同空间的资源名可以重复,命名空间主要为了对象进行逻辑上的分组便于管理。本文只使用了默认命名空间。 + +- [*PersistentVolume*]() + +- [*PersistentVolumeClaim*]() + +# 部署Kubernetes集群 + +Kubernetes提供了多种集群部署的方案,本文档内不重复介绍。这里给出集中常见的部署方法: + +- [*minikube*](https://kubernetes.io/docs/getting-started-guides/minikube/): 快速在本地启动一个单机的kubernetes服务器,便于本地验证和测试。 +- [*kubeadm*](http://kubernetes.io/docs/getting-started-guides/kubeadm/): 在不同操作系统,不同主机(Bare-Metal, AWS, GCE)条件下,快速部署集群。 +- [*AWS EC2*](https://kubernetes.io/docs/getting-started-guides/aws/): 在aws上快速部署集群。 +- [*Bare-Metal*](https://kubernetes.io/docs/getting-started-guides/centos/centos_manual_config/): 在物理机上手动部署。 + +可以参考[这个表格](https://kubernetes.io/docs/getting-started-guides/#table-of-solutions)选择适合您的场景的合适方案。 + +# 选择存储方案 + +容器不会保留在运行时生成的数据,job或者应用程序在容器中运行时生成的数据会在容器销毁时消失。为了完成分布式机器学习训练任务,需要有一个外部的存储服务来保存训练所需数据和训练输出。 +常见的可选存储服务包括: + +- [*NFS*](https://github.com/kubernetes/kubernetes/tree/master/examples/volumes/nfs): 可以将磁盘上某个目录共享给网络中其他机器访问。部署和配置比较简单,可以用于小量数据的验证。不提供分布式存储,高可用,冗余等功能。NFS的部署方法可以参考[这里](http://www.tecmint.com/how-to-setup-nfs-server-in-linux/)。 +- [*GlusterFS*](http://gluster.readthedocs.io/en/latest/Quick-Start-Guide/Quickstart/): 网络分布式文件系统,可以在Kubernetes中按照[这个](https://github.com/kubernetes/kubernetes/tree/master/examples/volumes/glusterfs)例子使用。 +- [*Ceph*](http://docs.ceph.com/docs/master/): 分布式文件系统,支持rbd,POSIX API接口(ceph fs)和对象存储API,参考[这里](https://kubernetes.io/docs/user-guide/volumes/#rbd)。 +- [*MooseFS*](https://moosefs.com/documentation.html): 一个分布式的存储系统。需要先挂载到服务器Node上再通过kubernetes hostPath Volume挂载到容器中。 + +# 配置kubectl + +## 安装kubectl +``` +# OS X +curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl + +# Linux +curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl + +# Windows +curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/windows/amd64/kubectl.exe +``` + +## 配置kubectl访问你的kubernetes集群 + +编辑`~/.kube/config`这个配置文件,修改`Master-IP`的地址。如果使用SSL认证,则需要配置`certificate-authority`和`users`中的用户证书。如果是使用非SSL方式访问(比如通过8080都安口),也可以去掉这些证书的配置。 +``` +apiVersion: v1 +clusters: +- cluster: + certificate-authority: /path/to/ca.crt + server: https://[Master-IP]:443 + name: minikube +contexts: +- context: + cluster: minikube + user: minikube + name: minikube +current-context: minikube +kind: Config +preferences: {} +users: +- name: minikube + user: + client-certificate: /path/to/apiserver.crt + client-key: /Users/wuyi/.minikube/apiserver.key +``` diff --git a/doc/howto/usage/k8s/k8s_distributed_cn.md b/doc/howto/usage/k8s/k8s_distributed_cn.md index 2063b98ca8aab9..cfc3086036f014 100644 --- a/doc/howto/usage/k8s/k8s_distributed_cn.md +++ b/doc/howto/usage/k8s/k8s_distributed_cn.md @@ -1,169 +1,51 @@ -# Kubernetes分布式训练 +# 使用Paddle在Kubernetes集群上完成分布式训练 前一篇文章介绍了如何在Kubernetes集群上启动一个单机PaddlePaddle训练作业 (Job)。在这篇文章里,我们介绍如何在Kubernetes集群上进行分布式PaddlePaddle训练作业。关于PaddlePaddle的分布式训练,文章 [Cluster Training](https://github.com/baidu/Paddle/blob/develop/doc/cluster/opensource/cluster_train.md)介绍了一种通过SSH远程分发任务,进行分布式训练的方法,与此不同的是,本文将介绍在Kubernetes容器管理平台上快速构建PaddlePaddle容器集群,进行分布式训练的方案。 -## Kubernetes 基本概念 - -[*Kubernetes*](http://kubernetes.io/)是Google开源的容器集群管理系统,其提供应用部署、维护、 扩展机制等功能,利用Kubernetes能方便地管理跨机器运行容器化的应用。Kubernetes可以在物理机或虚拟机上运行,且支持部署到[AWS](http://kubernetes.io/docs/getting-started-guides/aws),[Azure](http://kubernetes.io/docs/getting-started-guides/azure/),[GCE](http://kubernetes.io/docs/getting-started-guides/gce)等多种公有云环境。介绍分布式训练之前,需要对[Kubernetes](http://kubernetes.io/)有一个基本的认识,下面先简要介绍一下本文用到的几个Kubernetes概念。 - -- [*Node*](http://kubernetes.io/docs/admin/node/) 表示一个Kubernetes集群中的一个工作节点,这个节点可以是物理机或者虚拟机,Kubernetes集群就是由node节点与master节点组成的。 - -- [*Pod*](http://kubernetes.io/docs/user-guide/pods/) 是一组(一个或多个)容器,pod是Kubernetes的最小调度单元,一个pod中的所有容器会被调度到同一个node上。Pod中的容器共享NET,PID,IPC,UTS等Linux namespace。由于容器之间共享NET namespace,所以它们使用同一个IP地址,可以通过*localhost*互相通信。不同pod之间可以通过IP地址访问。 - -- [*Job*](http://kubernetes.io/docs/user-guide/jobs/) 是Kubernetes上运行的作业,一次作业称为一个job,通常每个job包括一个或者多个pods。 - -- [*Volume*](http://kubernetes.io/docs/user-guide/volumes/) 存储卷,是pod内的容器都可以访问的共享目录,也是容器与node之间共享文件的方式,因为容器内的文件都是暂时存在的,当容器因为各种原因被销毁时,其内部的文件也会随之消失。通过volume,就可以将这些文件持久化存储。Kubernetes支持多种volume,例如hostPath(宿主机目录),gcePersistentDisk,awsElasticBlockStore等。 - -- [*Namespaces*](http://kubernetes.io/docs/user-guide/volumes/) 命名空间,在kubernetes中创建的所有资源对象(例如上文的pod,job)等都属于一个命名空间,在同一个命名空间中,资源对象的名字是唯一的,不同空间的资源名可以重复,命名空间主要为了对象进行逻辑上的分组便于管理。本文只使用了默认命名空间。 +有关Kubernetes相关概念以及如何搭建和配置Kubernetes集群,可以参考[k8s_basis](./k8s_basis.md)。 ## 整体方案 -### 部署Kubernetes集群 - -首先,我们需要拥有一个Kubernetes集群,在这个集群中所有node与pod都可以互相通信。关于Kubernetes集群搭建,可以参考[官方文档](http://kubernetes.io/docs/getting-started-guides/kubeadm/),在以后的文章中我们也会介绍AWS上搭建的方案。本文假设大家能找到几台物理机,并且可以按照官方文档在上面部署Kubernetes。在本文的环境中,Kubernetes集群中所有node都挂载了一个[MFS](http://moosefs.org/)(Moose filesystem,一种分布式文件系统)共享目录,我们通过这个目录来存放训练文件与最终输出的模型。关于MFS的安装部署,可以参考[MooseFS documentation](https://moosefs.com/documentation.html)。在训练之前,用户将配置与训练数据切分好放在MFS目录中,训练时,程序从此目录拷贝文件到容器内进行训练,将结果保存到此目录里。整体的结构图如下: +在训练之前,用户将配置与训练数据切分好放在MFS目录中,训练时,程序从此目录拷贝文件到容器内进行训练,将结果保存到此目录里。整体的结构图如下: ![paddle on kubernetes结构图](src/k8s-paddle-arch.png) -上图描述了一个3节点的分布式训练场景,Kubernetes集群的每个node上都挂载了一个MFS目录,这个目录可以通过volume的形式挂载到容器中。Kubernetes为这次训练创建了3个pod并且调度到了3个node上运行,每个pod包含一个PaddlePaddle容器。在容器创建后,会启动pserver与trainer进程,读取volume中的数据进行这次分布式训练。 - -### 使用 Job - -我们使用Kubernetes中的job这个概念来代表一次分布式训练。Job表示一次性作业,在作业完成后,Kubernetes会销毁job产生的容器并且释放相关资源。 - -在Kubernetes中,可以通过编写一个YAML文件,来描述这个job,在这个文件中,主要包含了一些配置信息,例如PaddlePaddle的节点个数,`paddle pserver`开放的端口个数与端口号,使用的网卡设备等,这些信息通过环境变量的形式传递给容器内的程序使用。 +上图描述了一个3节点的分布式训练场景,在每个Pod上都通过volume方式挂载分布式文件系统的一个目录用于保存训练数据和输出结果。Kubernetes为这次训练创建了3个pod并且调度到了3个node上运行,每个pod包含一个PaddlePaddle容器。在容器创建后,会启动pserver与trainer进程,读取volume中的数据进行这次分布式训练。 -在一次分布式训练中,用户确定好本次训练需要的PaddlePaddle节点个数,将切分好的训练数据与配置文件上传到MFS共享目录中。然后编写这次训练的job YAML文件,提交给Kubernetes集群创建并开始作业。 +根据前文的描述,要在已有的Kubernetes集群上进行PaddlePaddle的分布式训练,按照下面步骤即可: -### 创建PaddlePaddle节点 - -当Kubernetes master收到请求,解析完YAML文件后,会创建出多个pod(个数为PaddlePaddle节点数),Kubernetes会把这些pod调度到集群的node上运行。一个pod就代表一个PaddlePaddle节点,当pod被成功分配到一台物理/虚拟机上后,Kubernetes会启动pod内的容器,这个容器会根据YAML文件中的环境变量,启动`paddle pserver`与`paddle train`进程。 - -### 启动训练 - -在容器启动后,会通过脚本来启动这次分布式训练,我们知道`paddle train`进程启动时需要知道其他节点的IP地址以及本节点的trainer_id,由于PaddlePaddle本身不提供类似服务发现的功能,所以在本文的启动脚本中,每个节点会根据job name向Kubernetes apiserver查询这个job对应的所有pod信息(Kubernetes默认会在每个容器的环境变量中写入apiserver的地址)。 - -根据这些pod信息,就可以通过某种方式,为每个pod分配一个唯一的trainer_id。本文把所有pod的IP地址进行排序,将顺序作为每个PaddlePaddle节点的trainer_id。启动脚本的工作流程大致如下: - - 1. 查询Kubernetes apiserver获取pod信息,根据IP分配trainer_id - 1. 从MFS共享目录中拷贝训练文件到容器内 - 1. 根据环境变量,解析出`paddle pserver`与`paddle train`的启动参数,启动进程 - 1. 训练时,PaddlePaddle会自动将结果保存在trainer_id为0的节点上,将输出路径设置为MFS目录,保存输出的文件 - - -## 搭建过程 - -根据前文的描述,要在已有的Kubernetes集群上进行PaddlePaddle的分布式训练,主要分为以下几个步骤: - -1. 制作PaddlePaddle镜像 -1. 将训练文件与切分好的数据上传到共享存储 -1. 编写本次训练的YAML文件,创建一个Kubernetes job -1. 训练结束后查看输出结果 +1. [制作PaddlePaddle镜像](#制作镜像) +1. [将训练文件与切分好的数据上传到共享存储](#上传训练文件) +1. [编写本次训练的YAML文件,创建一个Kubernetes job](#创建Job) +1. [训练结束后查看输出结果](#查看输出) 下面就根据这几个步骤分别介绍。 - ### 制作镜像 PaddlePaddle镜像需要提供`paddle pserver`与`paddle train`进程的运行环境,用这个镜像创建的容器需要有以下两个功能: - 拷贝训练文件到容器内 - - 生成`paddle pserver`与`paddle train`进程的启动参数,并且启动训练 -因为官方镜像 `paddledev/paddle:cpu-latest` 内已经包含PaddlePaddle的执行程序但是还没上述功能,所以我们可以在这个基础上,添加启动脚本,制作新镜像来完成以上的工作。镜像的*Dockerfile*如下: - -```Dockerfile -FROM paddledev/paddle:cpu-latest - -MAINTAINER zjsxzong89@gmail.com - -COPY start.sh /root/ -COPY start_paddle.py /root/ -CMD ["bash"," -c","/root/start.sh"] -``` - -[start.sh](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/usage/cluster/k8s/start.sh)文件拷贝训练文件到容器内,然后执行[start_paddle.py](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/usage/cluster/k8s/start_paddle.py)脚本启动训练,前文提到的获取其他节点IP地址,分配`trainer_id`等都在`start_paddle.py`脚本中完成。 - -`start_paddle.py`脚本开始时,会先进行参数的初始化与解析。 - -```python -parser = argparse.ArgumentParser(prog="start_paddle.py", - description='simple tool for k8s') - args, train_args_list = parser.parse_known_args() - train_args = refine_unknown_args(train_args_list) - train_args_dict = dict(zip(train_args[:-1:2], train_args[1::2])) - podlist = getPodList() -``` - -然后通过函数`getPodList()`访问Kubernetes的接口来查询此job对应的所有pod信息。当所有pod都处于running状态(容器运行都运行)时,再通过函数`getIdMap(podlist)`获取trainer_id。 - -```python - podlist = getPodList() - # need to wait until all pods are running - while not isPodAllRunning(podlist): - time.sleep(10) - podlist = getPodList() - idMap = getIdMap(podlist) -``` - -在函数`getIdMap(podlist)`内部,我们通过读取`podlist`中每个pod的IP地址,将IP排序生成的序号作为trainer_id。 - -```python -def getIdMap(podlist): - ''' - generate tainer_id by ip - ''' - ips = [] - for pod in podlist["items"]: - ips.append(pod["status"]["podIP"]) - ips.sort() - idMap = {} - for i in range(len(ips)): - idMap[ips[i]] = i - return idMap -``` - -在得到`idMap`后,通过函数`startPaddle(idMap, train_args_dict)`构造`paddle pserver`与`paddle train`的启动参数并执行进程。 - -在函数`startPaddle`中,最主要的工作就是解析出`paddle pserver`与`paddle train`的启动参数。例如`paddle train`参数的解析,解析环境变量得到`PADDLE_NIC`,`PADDLE_PORT`,`PADDLE_PORTS_NUM`等参数,然后通过自身的IP地址在`idMap`中获取`trainerId`。 - -```python - program = 'paddle train' - args = " --nics=" + PADDLE_NIC - args += " --port=" + str(PADDLE_PORT) - args += " --ports_num=" + str(PADDLE_PORTS_NUM) - args += " --comment=" + "paddle_process_by_paddle" - ip_string = "" - for ip in idMap.keys(): - ip_string += (ip + ",") - ip_string = ip_string.rstrip(",") - args += " --pservers=" + ip_string - args_ext = "" - for key, value in train_args_dict.items(): - args_ext += (' --' + key + '=' + value) - localIP = socket.gethostbyname(socket.gethostname()) - trainerId = idMap[localIP] - args += " " + args_ext + " --trainer_id=" + \ - str(trainerId) + " --save_dir=" + JOB_PATH_OUTPUT -``` - -使用 `docker build` 构建镜像: +因为官方镜像 `paddledev/paddle:cpu-latest` 内已经包含PaddlePaddle的执行程序但是还没上述功能,所以我们可以在这个基础上,添加启动脚本,制作新镜像来完成以上的工作。参考镜像的[*Dockerfile*]((https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/usage/cluster/k8s/src/k8s_train/Dockerfile)。 ```bash -docker build -t your_repo/paddle:mypaddle . +$ cd doc/howto/usage/k8s/src/k8s_train +$ docker build -t [YOUR_REPO]/paddle:mypaddle . ``` 然后将构建成功的镜像上传到镜像仓库。 ```bash -docker push your_repo/paddle:mypaddle +docker push [YOUR_REPO]/paddle:mypaddle ``` -注意上述命令中`your_repo`表示读者所使用的Docker镜像仓库地址,读者需要替换成自己使用的仓库地址。下文使用`your_repo/paddle:mypaddle`这个地址来表示此步骤所构建出的镜像。 +注意上述命令中`[YOUR_REPO]`表示读者所使用的Docker镜像仓库地址,读者需要替换成自己使用的仓库地址。下文使用`[YOUR_REPO]/paddle:mypaddle`这个地址来表示此步骤所构建出的镜像。 ### 上传训练文件 -本文使用PaddlePaddle官方的[recommendation demo](http://www.paddlepaddle.org/doc/demo/index.html#recommendation)作为这次训练的内容,我们将训练文件与数据放在一个job name命名的目录中,上传到MFS共享存储。完成后MFS上的文件内容大致如下: +本文使用PaddlePaddle官方的[recommendation demo](http://www.paddlepaddle.org/doc/demo/index.html#recommendation)作为这次训练的内容,我们将训练文件与数据放在一个job name命名的目录中,上传到volume所在的共享存储(使用不同分布式存储会有不同的挂载方式,需要要先挂载这个目录,然后拷贝数据)。完成后volume中的文件内容大致如下: ```bash [root@paddle-kubernetes-node0 mfs]# tree -d @@ -205,7 +87,7 @@ spec: path: /home/work/mfs containers: - name: trainer - image: your_repo/paddle:mypaddle + image: [YOUR_REPO]/paddle:mypaddle command: ["bin/bash", "-c", "/root/start.sh"] env: - name: JOB_NAME @@ -289,8 +171,8 @@ I1116 09:10:17.123121 50 Util.cpp:155] commandline: --ports_num=2 --comment=paddle_process_by_paddle --pservers=192.168.129.66,192.168.223.143,192.168.129.71 --ports_num_for_sparse=2 --config=./trainer_config.py - --trainer_count=4 --num_passes=10 --use_gpu=0 - --log_period=50 --dot_period=10 --saving_period=1 + --trainer_count=4 --num_passes=10 --use_gpu=0 + --log_period=50 --dot_period=10 --saving_period=1 --local=0 --trainer_id=0 --save_dir=/home/jobpath/paddle-cluster-job/output I1116 09:10:17.123440 50 Util.cpp:130] Calling runInitFunctions @@ -310,3 +192,90 @@ I1116 09:10:18.019492 50 ParameterClient2.cpp:122] pserver 3 192.168.223.143: I1116 09:10:18.019716 50 ParameterClient2.cpp:122] pserver 4 192.168.129.71:7164 I1116 09:10:18.019836 50 ParameterClient2.cpp:122] pserver 5 192.168.129.71:7165 ``` + + +## 一些细节的补充 + +### 使用环境变量 + +使用容器方式运行训练任务的Kubernetes Job,通常会使用环境变量配置Job的配置信息`start_paddle.py`提供了一个启动脚本,将环境变量转换成paddle的命令行参数: +``` +API = "/api/v1/namespaces/" +JOBSELECTOR = "labelSelector=job-name=" +JOB_PATH = os.getenv("JOB_PATH") + "/" + os.getenv("JOB_NAME") +JOB_PATH_OUTPUT = JOB_PATH + "/output" +JOBNAME = os.getenv("JOB_NAME") +NAMESPACE = os.getenv("JOB_NAMESPACE") +PADDLE_NIC = os.getenv("CONF_PADDLE_NIC") +PADDLE_PORT = os.getenv("CONF_PADDLE_PORT") +PADDLE_PORTS_NUM = os.getenv("CONF_PADDLE_PORTS_NUM") +PADDLE_PORTS_NUM_SPARSE = os.getenv("CONF_PADDLE_PORTS_NUM_SPARSE") +PADDLE_SERVER_NUM = os.getenv("CONF_PADDLE_GRADIENT_NUM") +``` + +### Pod间通信 +`start_paddle.py`脚本开始时,会先进行参数的初始化与解析。 + +```python +parser = argparse.ArgumentParser(prog="start_paddle.py", + description='simple tool for k8s') + args, train_args_list = parser.parse_known_args() + train_args = refine_unknown_args(train_args_list) + train_args_dict = dict(zip(train_args[:-1:2], train_args[1::2])) + podlist = getPodList() +``` + +然后通过函数`getPodList()`访问Kubernetes的接口来查询此job对应的所有pod信息。当所有pod都处于running状态(容器运行都运行)时,再通过函数`getIdMap(podlist)`获取trainer_id。 + +```python + podlist = getPodList() + # need to wait until all pods are running + while not isPodAllRunning(podlist): + time.sleep(10) + podlist = getPodList() + idMap = getIdMap(podlist) +``` +* *注意*: `getPodList()`会获取当前namespace下的所有pod,如果已经有pod运行,可能会导致出错。这种集群节点管理方式会在将来使用[statfulsets](https://kubernetes.io/docs/concepts/abstractions/controllers/statefulsets/)代替。 + +在函数`getIdMap(podlist)`内部,我们通过读取`podlist`中每个pod的IP地址,将IP排序生成的序号作为trainer_id。 + +```python +def getIdMap(podlist): + ''' + generate tainer_id by ip + ''' + ips = [] + for pod in podlist["items"]: + ips.append(pod["status"]["podIP"]) + ips.sort() + idMap = {} + for i in range(len(ips)): + idMap[ips[i]] = i + return idMap +``` + +在得到`idMap`后,通过函数`startPaddle(idMap, train_args_dict)`构造`paddle pserver`与`paddle train`的启动参数并执行进程。 + +### 启动任务 + +在函数`startPaddle`中,最主要的工作就是解析出`paddle pserver`与`paddle train`的启动参数。例如`paddle train`参数的解析,解析环境变量得到`PADDLE_NIC`,`PADDLE_PORT`,`PADDLE_PORTS_NUM`等参数,然后通过自身的IP地址在`idMap`中获取`trainerId`。 + +```python + program = 'paddle train' + args = " --nics=" + PADDLE_NIC + args += " --port=" + str(PADDLE_PORT) + args += " --ports_num=" + str(PADDLE_PORTS_NUM) + args += " --comment=" + "paddle_process_by_paddle" + ip_string = "" + for ip in idMap.keys(): + ip_string += (ip + ",") + ip_string = ip_string.rstrip(",") + args += " --pservers=" + ip_string + args_ext = "" + for key, value in train_args_dict.items(): + args_ext += (' --' + key + '=' + value) + localIP = socket.gethostbyname(socket.gethostname()) + trainerId = idMap[localIP] + args += " " + args_ext + " --trainer_id=" + \ + str(trainerId) + " --save_dir=" + JOB_PATH_OUTPUT +``` diff --git a/doc/howto/usage/k8s/src/k8s-paddle-arch.png b/doc/howto/usage/k8s/src/k8s-paddle-arch.png index a8c64550b1fa7f41de1eaa9a037c65cddc0cd30e..c41a62392978eb94ceeb0ff24f23964055f5e06c 100644 GIT binary patch literal 530508 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%0AYvh?PDi8XbWbg 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 diff --git a/doc/howto/usage/k8s/src/job.yaml b/doc/howto/usage/k8s/src/job.yaml deleted file mode 100644 index 488aad0bede4f9..00000000000000 --- a/doc/howto/usage/k8s/src/job.yaml +++ /dev/null @@ -1,43 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: paddle-cluster-job -spec: - parallelism: 3 - completions: 3 - template: - metadata: - name: paddle-cluster-job - spec: - volumes: - - name: jobpath - hostPath: - path: /home/work/paddle_output - containers: - - name: trainer - image: registry.baidu.com/public/paddle:mypaddle - command: ["bin/bash", "-c", "/root/start.sh"] - env: - - name: JOB_NAME - value: paddle-cluster-job - - name: JOB_PATH - value: /home/jobpath - - name: JOB_NAMESPACE - value: default - - name: TRAIN_CONFIG_DIR - value: recommendation - - name: CONF_PADDLE_NIC - value: eth0 - - name: CONF_PADDLE_PORT - value: "7164" - - name: CONF_PADDLE_PORTS_NUM - value: "2" - - name: CONF_PADDLE_PORTS_NUM_SPARSE - value: "2" - - name: CONF_PADDLE_GRADIENT_NUM - value: "3" - volumeMounts: - - name: jobpath - mountPath: /home/jobpath - restartPolicy: Never - diff --git a/doc/howto/usage/k8s/src/k8s_data/Dockerfile b/doc/howto/usage/k8s/src/k8s_data/Dockerfile new file mode 100644 index 00000000000000..6d3a12ae393aa5 --- /dev/null +++ b/doc/howto/usage/k8s/src/k8s_data/Dockerfile @@ -0,0 +1,7 @@ +FROM alpine + +RUN apk update && apk upgrade && apk add coreutils +ADD quick_start /quick_start +ADD get_data.sh /bin/ +RUN chmod +x /bin/get_data.sh +ENTRYPOINT ["/bin/get_data.sh"] diff --git a/doc/howto/usage/k8s/src/k8s_data/README.md b/doc/howto/usage/k8s/src/k8s_data/README.md new file mode 100644 index 00000000000000..ed1abcab5cd8d7 --- /dev/null +++ b/doc/howto/usage/k8s/src/k8s_data/README.md @@ -0,0 +1,6 @@ +To build PaddlePaddle data preparation image in tutorial [Distributed PaddlePaddle Training on AWS with Kubernetes](../k8s_aws_en.md), run following commands: + +``` +cp -r ../../../../../../demo/quick_start . +docker build . -t prepare-data-image-name +``` diff --git a/doc/howto/usage/k8s/src/k8s_data/get_data.sh b/doc/howto/usage/k8s/src/k8s_data/get_data.sh new file mode 100755 index 00000000000000..d187ba5ac8d03f --- /dev/null +++ b/doc/howto/usage/k8s/src/k8s_data/get_data.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +out_dir=$OUT_DIR +split_count=$SPLIT_COUNT + +set -e + +mkdir -p $out_dir +cp -r /quick_start $out_dir/ + +mkdir -p $out_dir/0/data +cd $out_dir/0/data +wget http://paddlepaddle.bj.bcebos.com/demo/quick_start_preprocessed_data/preprocessed_data.tar.gz +tar zxvf preprocessed_data.tar.gz +rm preprocessed_data.tar.gz + +split -d --number=l/$split_count -a 5 train.txt train. +mv train.00000 train.txt + +cd $out_dir +end=$(expr $split_count - 1) +for i in $(seq 1 $end); do + mkdir -p $i/data + cp -r 0/data/* $i/data + mv $i/data/train.`printf %05d $i` $i/data/train.txt +done; diff --git a/doc/howto/usage/k8s/src/k8s_train/Dockerfile b/doc/howto/usage/k8s/src/k8s_train/Dockerfile new file mode 100644 index 00000000000000..c0fca1f9a94592 --- /dev/null +++ b/doc/howto/usage/k8s/src/k8s_train/Dockerfile @@ -0,0 +1,6 @@ +FROM paddledev/paddle:cpu-latest + +COPY start.sh /root/ +COPY start_paddle.py /root/ +RUN chmod +x /root/start.sh +CMD ["bash"," -c","/root/start.sh"] diff --git a/doc/howto/usage/k8s/src/k8s_train/README.md b/doc/howto/usage/k8s/src/k8s_train/README.md new file mode 100644 index 00000000000000..68724ac2725418 --- /dev/null +++ b/doc/howto/usage/k8s/src/k8s_train/README.md @@ -0,0 +1,5 @@ +To build PaddlePaddle training image in tutorial [Distributed PaddlePaddle Training on AWS with Kubernetes](../k8s_aws_en.md), run following command: + +``` +docker build . -t train-image-name +``` diff --git a/doc/howto/usage/k8s/src/start.sh b/doc/howto/usage/k8s/src/k8s_train/start.sh similarity index 55% rename from doc/howto/usage/k8s/src/start.sh rename to doc/howto/usage/k8s/src/k8s_train/start.sh index b3a1334174a20b..12dfe1e6386885 100755 --- a/doc/howto/usage/k8s/src/start.sh +++ b/doc/howto/usage/k8s/src/k8s_train/start.sh @@ -1,19 +1,19 @@ #!/bin/sh + set -eu jobconfig=${JOB_PATH}"/"${JOB_NAME}"/"${TRAIN_CONFIG_DIR} cd /root -cp -rf $jobconfig . -cd $TRAIN_CONFIG_DIR - +cp -rf $jobconfig/* . python /root/start_paddle.py \ --dot_period=10 \ - --ports_num_for_sparse=$CONF_PADDLE_PORTS_NUM \ + --ports_num=$CONF_PADDLE_PORTS_NUM \ + --ports_num_for_sparse=$CONF_PADDLE_PORTS_NUM_SPARSE \ --log_period=50 \ --num_passes=10 \ - --trainer_count=4 \ + --trainer_count=$TRAINER_COUNT \ --saving_period=1 \ --local=0 \ - --config=./trainer_config.py \ + --config=trainer_config.lr.py \ --use_gpu=0 diff --git a/doc/howto/usage/k8s/src/start_paddle.py b/doc/howto/usage/k8s/src/k8s_train/start_paddle.py similarity index 84% rename from doc/howto/usage/k8s/src/start_paddle.py rename to doc/howto/usage/k8s/src/k8s_train/start_paddle.py index df00d82919faa2..f1a770ccb54fbd 100755 --- a/doc/howto/usage/k8s/src/start_paddle.py +++ b/doc/howto/usage/k8s/src/k8s_train/start_paddle.py @@ -23,7 +23,6 @@ API = "/api/v1/namespaces/" JOBSELECTOR = "labelSelector=job-name=" JOB_PATH = os.getenv("JOB_PATH") + "/" + os.getenv("JOB_NAME") -JOB_PATH_DATA = JOB_PATH + "/data" JOB_PATH_OUTPUT = JOB_PATH + "/output" JOBNAME = os.getenv("JOB_NAME") NAMESPACE = os.getenv("JOB_NAMESPACE") @@ -33,6 +32,8 @@ PADDLE_PORTS_NUM_SPARSE = os.getenv("CONF_PADDLE_PORTS_NUM_SPARSE") PADDLE_SERVER_NUM = os.getenv("CONF_PADDLE_GRADIENT_NUM") +tokenpath = '/var/run/secrets/kubernetes.io/serviceaccount/token' + def refine_unknown_args(cmd_args): ''' @@ -64,6 +65,7 @@ def isPodAllRunning(podlist): for pod in podlist["items"]: if pod["status"]["phase"] == "Running": running += 1 + print "waiting for pods running, require:", require, "running:", running if require == running: return True return False @@ -79,8 +81,17 @@ def getPodList(): pod = API + NAMESPACE + "/pods?" job = JOBNAME - return requests.get(apiserver + pod + JOBSELECTOR + job, - verify=False).json() + if os.path.isfile(tokenpath): + tokenfile = open(tokenpath, mode='r') + token = tokenfile.read() + Bearer = "Bearer " + token + headers = {"Authorization": Bearer} + return requests.get(apiserver + pod + JOBSELECTOR + job, + headers=headers, + verify=False).json() + else: + return requests.get(apiserver + pod + JOBSELECTOR + job, + verify=False).json() def getIdMap(podlist): @@ -122,8 +133,8 @@ def startPaddle(idMap={}, train_args_dict=None): if not os.path.exists(JOB_PATH_OUTPUT): os.makedirs(JOB_PATH_OUTPUT) os.mkdir(logDir) - copyCommand = 'cp -rf ' + JOB_PATH_DATA + \ - "/" + str(trainerId) + " ./data" + copyCommand = 'cp -rf ' + JOB_PATH + \ + "/" + str(trainerId) + "/data/*" + " ./data/" os.system(copyCommand) startPserver = 'nohup paddle pserver' + \ " --port=" + str(PADDLE_PORT) + \ @@ -136,9 +147,9 @@ def startPaddle(idMap={}, train_args_dict=None): print startPserver os.system(startPserver) # wait until pservers completely start - time.sleep(10) - startTrainer = program + args + " > " + \ - logDir + "/train.log 2>&1 < /dev/null" + time.sleep(20) + startTrainer = program + args + " 2>&1 | tee " + \ + logDir + "/train.log" print startTrainer os.system(startTrainer) @@ -152,7 +163,7 @@ def startPaddle(idMap={}, train_args_dict=None): podlist = getPodList() # need to wait until all pods are running while not isPodAllRunning(podlist): - time.sleep(10) + time.sleep(20) podlist = getPodList() idMap = getIdMap(podlist) startPaddle(idMap, train_args_dict) diff --git a/doc/howto/usage/k8s/src/worker_security_group.png b/doc/howto/usage/k8s/src/worker_security_group.png new file mode 100644 index 0000000000000000000000000000000000000000..57eb0265a34ad4223b69600d2a3dd355482e0bf5 GIT binary patch literal 89208 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 aXPTGak*)X6Zt{}>U-xtk@04lVMf@MKrFu00 literal 0 HcmV?d00001 From 17867fb6c70e01ae96c10bc3d4f6f28ef321a74d Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Thu, 26 Jan 2017 11:19:19 -0800 Subject: [PATCH 109/370] fix README.md reference problem --- doc/howto/usage/k8s/k8s_aws_en.md | 4 ++-- doc/howto/usage/k8s/src/k8s_data/README.md | 2 +- doc/howto/usage/k8s/src/k8s_train/README.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/howto/usage/k8s/k8s_aws_en.md b/doc/howto/usage/k8s/k8s_aws_en.md index 7930807969c0e9..8a15a9583eb4ff 100644 --- a/doc/howto/usage/k8s/k8s_aws_en.md +++ b/doc/howto/usage/k8s/k8s_aws_en.md @@ -489,7 +489,7 @@ NAME DESIRED SUCCESSFUL AGE paddle-data 1 1 6m ``` -Data preparation is done by docker image `paddledev/paddle-tutorial:k8s_data`, see [here](src/k8s_data/) for how to build this docker image and source code. +Data preparation is done by docker image `paddledev/paddle-tutorial:k8s_data`, see [here](src/k8s_data/README.md) for how to build this docker image and source code. #### Start Training @@ -584,7 +584,7 @@ kubectl --kubeconfig=kubeconfig log -f POD_NAME Run `kubectl --kubeconfig=kubeconfig describe job paddle-cluster-job` to check training job status. It will complete in around 20 minutes. -The details for start `pserver` and `trainer` are hidden inside docker image `paddledev/paddle-tutorial:k8s_train`, see [here](src/k8s_train/) for how to build the docker image and source code. +The details for start `pserver` and `trainer` are hidden inside docker image `paddledev/paddle-tutorial:k8s_train`, see [here](src/k8s_train/README.md) for how to build the docker image and source code. #### Inspect Training Output diff --git a/doc/howto/usage/k8s/src/k8s_data/README.md b/doc/howto/usage/k8s/src/k8s_data/README.md index ed1abcab5cd8d7..83cef7affd0ac4 100644 --- a/doc/howto/usage/k8s/src/k8s_data/README.md +++ b/doc/howto/usage/k8s/src/k8s_data/README.md @@ -1,4 +1,4 @@ -To build PaddlePaddle data preparation image in tutorial [Distributed PaddlePaddle Training on AWS with Kubernetes](../k8s_aws_en.md), run following commands: +To build PaddlePaddle data preparation image in tutorial [Distributed PaddlePaddle Training on AWS with Kubernetes](../../k8s_aws_en.md), run following commands: ``` cp -r ../../../../../../demo/quick_start . diff --git a/doc/howto/usage/k8s/src/k8s_train/README.md b/doc/howto/usage/k8s/src/k8s_train/README.md index 68724ac2725418..96bf65497ffa23 100644 --- a/doc/howto/usage/k8s/src/k8s_train/README.md +++ b/doc/howto/usage/k8s/src/k8s_train/README.md @@ -1,4 +1,4 @@ -To build PaddlePaddle training image in tutorial [Distributed PaddlePaddle Training on AWS with Kubernetes](../k8s_aws_en.md), run following command: +To build PaddlePaddle training image in tutorial [Distributed PaddlePaddle Training on AWS with Kubernetes](../../k8s_aws_en.md), run following command: ``` docker build . -t train-image-name From cfe0e086636abdcbb2aea76a68f044d54b111e27 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Thu, 26 Jan 2017 11:45:06 -0800 Subject: [PATCH 110/370] change english documentation for parameter ports_num and ports_num_for_sparse --- paddle/utils/Flags.cpp | 11 +++++++---- proto/ParameterServerConfig.proto | 11 +++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/paddle/utils/Flags.cpp b/paddle/utils/Flags.cpp index 59d6cbdc513660..e8f31bc811ac30 100644 --- a/paddle/utils/Flags.cpp +++ b/paddle/utils/Flags.cpp @@ -33,12 +33,15 @@ DEFINE_int32(port, 20134, "Listening port for pserver"); DEFINE_int32(data_server_port, 21134, "Listening port for dserver"); DEFINE_int32(ports_num, 1, - "The ports number for parameter send," - " increment based on default port number"); + "Number of ports for sending dense parameter," + " following ports on parameter server will be visited" + " for sending dense parameter: [port, port+ports_num-1]"); DEFINE_int32(ports_num_for_sparse, 0, - "The ports number for parameter send," - " increment based on default (port + ports_num)"); + "Number of ports for sending sparse parameter," + " following ports on parameter server will be visited" + " for sending sparse parameter:" + " [port+ports_num, port+ports_num+ports_num_for_sparse-1]"); DEFINE_string(nics, "xgbe0,xgbe1", "network device name for pservers"); DEFINE_string(rdma_tcp, "tcp", "use rdma or tcp rdma transport protocol"); DEFINE_int32(trainer_id, diff --git a/proto/ParameterServerConfig.proto b/proto/ParameterServerConfig.proto index 3068bba8b10d89..404f9613792653 100644 --- a/proto/ParameterServerConfig.proto +++ b/proto/ParameterServerConfig.proto @@ -27,11 +27,14 @@ message ParameterClientConfig { * Configuration structure for ParameterServer2. */ message ParameterServerConfig { - // The ports number for parameter send, - // increment based on default port number + // Number of ports for sending dense parameter, + // following ports on parameter server will be visited + // for sending dense parameter: [port, port+ports_num-1] required int32 ports_num = 1 [default = 1]; - // The ports number for parameter send, - // increment based on default (port + ports_num + // Number of ports for sending sparse parameter, + // following ports on parameter server will be visited + // for sending sparse parameter: + // [port+ports_num, port+ports_num+ports_num_for_sparse-1] required int32 ports_num_for_sparse = 2 [default = 0]; // network device name for pservers required string nics = 3 [default = "xgbe0,xgbe1"]; From 7712fd58c256935fca7555543b0211d612eb022c Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Thu, 26 Jan 2017 14:40:55 -0800 Subject: [PATCH 111/370] fix docker build I am getting following error without this commit when doing docker build. File "", line 1, in File "/usr/local/lib/python2.7/dist-packages/setuptools/__init__.py", line 12, in import setuptools.version File "/usr/local/lib/python2.7/dist-packages/setuptools/version.py", line 1, in import pkg_resources File "/usr/local/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 70, in import packaging.version ImportError: No module named packaging.version No idea why this change fix the problem, but it does fix. --- paddle/scripts/docker/Dockerfile | 4 ++-- paddle/scripts/docker/Dockerfile.gpu | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile index 79c4efbed0b856..341bdde8c60533 100644 --- a/paddle/scripts/docker/Dockerfile +++ b/paddle/scripts/docker/Dockerfile @@ -13,8 +13,8 @@ RUN apt-get update && \ apt-get install -y automake clang-3.8 llvm-3.8 libclang-3.8-dev && \ apt-get clean -y -RUN pip install --upgrade pip && \ - pip install 'protobuf==3.1.0.post1' && \ +RUN pip install --upgrade pip +RUN pip install 'protobuf==3.1.0.post1' && \ pip install -U wheel pillow BeautifulSoup && \ pip install -U docopt PyYAML sphinx && \ pip install -U sphinx_rtd_theme recommonmark jupyter diff --git a/paddle/scripts/docker/Dockerfile.gpu b/paddle/scripts/docker/Dockerfile.gpu index 6c1c2225d1a304..400e2c9037750b 100644 --- a/paddle/scripts/docker/Dockerfile.gpu +++ b/paddle/scripts/docker/Dockerfile.gpu @@ -13,8 +13,8 @@ RUN apt-get update && \ apt-get install -y automake clang-3.8 llvm-3.8 libclang-3.8-dev && \ apt-get clean -y -RUN pip install --upgrade pip && \ - pip install 'protobuf==3.1.0.post1' && \ +RUN pip install --upgrade pip +RUN pip install 'protobuf==3.1.0.post1' && \ pip install -U wheel pillow BeautifulSoup && \ pip install -U docopt PyYAML sphinx && \ pip install -U sphinx_rtd_theme recommonmark jupyter From ca31db97a467bfabb6050d4ef41ec63e0552499d Mon Sep 17 00:00:00 2001 From: xichen Date: Thu, 26 Jan 2017 14:56:22 -0800 Subject: [PATCH 112/370] added region check step, route53 config. --- doc/howto/usage/k8s/k8s_aws_en.md | 39 ++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/doc/howto/usage/k8s/k8s_aws_en.md b/doc/howto/usage/k8s/k8s_aws_en.md index a6422b9be00e21..227b6dee869724 100644 --- a/doc/howto/usage/k8s/k8s_aws_en.md +++ b/doc/howto/usage/k8s/k8s_aws_en.md @@ -1,4 +1,9 @@ # Kubernetes on AWS +## Choose AWS Service Region +This tutorial requires several AWS services work in the same region. Before we create anything in AWS, please check the following link +https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/ +Choose a region which has the following services available: EC2, EFS, VPS, CloudFormation, KMS, VPC, S3. +In this tutorial, we use "Oregon(us-west-2)" as example. ## Create AWS Account and IAM Account @@ -35,7 +40,8 @@ Here we will show you step by step on how to run PaddlePaddle training on AWS cl #### kube-aws [kube-aws](https://github.com/coreos/kube-aws) is a CLI tool to automate cluster deployment to AWS. - +##### Verify integrity of kube-aws downloaded +Note: if you are using a non-official release (e.g RC release) kube-aws, you can skip this setp. Import the CoreOS Application Signing Public Key: ``` @@ -60,7 +66,7 @@ PLATFORM=darwin-amd64 gpg2 --verify kube-aws-${PLATFORM}.tar.gz.sig kube-aws-${PLATFORM}.tar.gz ``` - +##### Install kube-aws Extract the binary: ``` @@ -201,14 +207,15 @@ paste into following inline policies: ] } ``` - +`Version` : Its value has to be exactly "2012-10-17". `AWS_ACCOUNT_ID`: You can get it from following command line: ``` aws sts get-caller-identity --output text --query Account ``` -`MY_CLUSTER_NAME`: Pick a MY_CLUSTER_NAME that you like, you will use it later as well. +`MY_CLUSTER_NAME`: Pick a MY_CLUSTER_NAME that you like, you will use it later as well. +Please note, stack name must satisfy regular expression pattern: [a-zA-Z][-a-zA-Z0-9*]*, which means no "_" or "-" in stack name, or kube-aws will throw error in later steps. #### External DNS name @@ -216,7 +223,7 @@ When the cluster is created, the controller will expose the TLS-secured API on a The A record of that DNS name needs to be point to the cluster ip address. -We will need to use DNS name later in tutorial. If you don't already own one, you can choose any DNS name (e.g., `paddle`) and modify `/etc/hosts` to associate cluster ip with that DNS name. +We will need to use DNS name later in tutorial. If you don't already own one, you can choose any DNS name (e.g., `paddle`) and modify `/etc/hosts` to associate cluster ip with that DNS name. We will find the ip to map to `paddle` in later steps. Also in this case, will have to add name service (route53) in aws cluster in later step. #### S3 bucket @@ -346,7 +353,27 @@ paddle-cl-ElbAPISe-EEOI3EZPR86C-531251350.us-west-1.elb.amazonaws.com. 59 IN A 5 In the above output, both ip `54.241.164.52`, `54.67.102.112` will work. -If you own a DNS name, set the A record to any of the above ip. Otherwise you can edit `/etc/hosts` to associate ip with the DNS name. +*If you own a DNS name*, set the A record to any of the above ip. Then you can skip to the step "Access the cluster". + +*If you do not own a DNS name*: +##### Update local DNS association +Edit `/etc/hosts` to associate above ip with the DNS name. +##### Add Route53 private name service in VPC + - Open Route53 web console + - Create hosted zone with following config + - Domain name: "paddle" + - Type: "Private hosted zone for amazon VPC" + - VPC ID: + - Add A record + - Click on the zone "paddle" just created + - Click the button "Create record set" + - Name : leave blank + - type: "A" + - Value: + - Verify name service + - Connect to any instance created by kube-aws via ssh + - Run command "host paddle", see if the ip returned is the private ip of kube-controller + #### Access the cluster From 8c9716f7d4ea5c58414266cf89c9a5ed72af605a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=9B=8A?= Date: Thu, 26 Jan 2017 15:06:34 -0800 Subject: [PATCH 113/370] Allow users to build a Docker image as development environment from Dockerfile{.gpu} --- paddle/scripts/docker/Dockerfile | 10 ++-- paddle/scripts/docker/Dockerfile.dev | 62 --------------------- paddle/scripts/docker/Dockerfile.gpu | 10 ++-- paddle/scripts/docker/build.sh | 80 +++++++++++++++------------- 4 files changed, 52 insertions(+), 110 deletions(-) delete mode 100644 paddle/scripts/docker/Dockerfile.dev diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile index 79c4efbed0b856..d4845a72b61833 100644 --- a/paddle/scripts/docker/Dockerfile +++ b/paddle/scripts/docker/Dockerfile @@ -13,8 +13,8 @@ RUN apt-get update && \ apt-get install -y automake clang-3.8 llvm-3.8 libclang-3.8-dev && \ apt-get clean -y -RUN pip install --upgrade pip && \ - pip install 'protobuf==3.1.0.post1' && \ +RUN pip install --upgrade pip && \ + pip install -U protobuf && \ pip install -U wheel pillow BeautifulSoup && \ pip install -U docopt PyYAML sphinx && \ pip install -U sphinx_rtd_theme recommonmark jupyter @@ -23,10 +23,12 @@ RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \ cd cmake-3.4.1 && ./bootstrap && make -j4 && make install && \ cd .. && rm -rf cmake-3.4.1 +ARG BUILD_AND_INSTALL ARG WITH_AVX ARG WITH_DOC ARG WITH_STYLE_CHECK +ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-OFF} ENV WITH_GPU=OFF ENV WITH_AVX=${WITH_AVX:-ON} ENV WITH_DOC=${WITH_DOC:-ON} @@ -37,10 +39,6 @@ COPY . /paddle/ RUN /paddle/paddle/scripts/docker/build.sh VOLUME ["/usr/share/nginx/html/data", "/usr/share/nginx/html/paddle"] -RUN echo 'export LD_LIBRARY_PATH=/usr/lib64:${LD_LIBRARY_PATH}' >> /etc/profile -RUN pip install /usr/local/opt/paddle/share/wheels/*.whl -RUN paddle version # print version after build - # Configure OpenSSH server. c.f. https://docs.docker.com/engine/examples/running_ssh_service RUN mkdir /var/run/sshd RUN echo 'root:root' | chpasswd diff --git a/paddle/scripts/docker/Dockerfile.dev b/paddle/scripts/docker/Dockerfile.dev deleted file mode 100644 index 2f245e2580f486..00000000000000 --- a/paddle/scripts/docker/Dockerfile.dev +++ /dev/null @@ -1,62 +0,0 @@ -FROM ubuntu:16.04 -MAINTAINER PaddlePaddle Authors - -ARG DEBIAN_FRONTEND=noninteractive -ARG UBUNTU_MIRROR -RUN /bin/bash -c 'if [[ -n ${UBUNTU_MIRROR} ]]; then sed -i 's#http://archive.ubuntu.com#${UBUNTU_MIRROR}#g' /etc/apt/sources.list; fi' - -RUN apt-get update - -# Paddle development tools. -RUN apt-get install -y coreutils git cmake g++ m4 python-pip swig - -# Paddle data tools. -RUN apt-get install -y wget unzip tar xz-utils bzip2 gzip sed grep graphviz - -# Paddle documentation tools. -RUN apt-get install -y doxygen - -# Paddle code auto-reformat tools. -RUN apt-get install -y clang-3.8 llvm-3.8 libclang-3.8-dev clang-format-3.8 clang-tidy-3.8 - -# Paddle prerequisites. -RUN apt-get install -y \ - libprotobuf-dev protobuf-compiler \ - libgoogle-glog-dev libgflags-dev libgtest-dev \ - libatlas-dev libatlas3-base \ - python-protobuf python-numpy python-dev python-matplotlib \ - libjpeg-dev zlib1g-dev - -# Development environment: -RUN apt-get install -y openssh-server - -RUN apt-get clean -y - -# Build Google test -RUN cd /usr/src/gtest && cmake . && make && cp *.a /usr/lib - -# Python dependencies. -RUN pip install -U BeautifulSoup docopt PyYAML pillow \ - sphinx sphinx_rtd_theme recommonmark jupyter - -ARG WITH_AVX -ARG WITH_DOC -ARG WITH_SWIG_PY -ARG WITH_STYLE_CHECK - -ENV WITH_GPU=OFF -ENV WITH_AVX=${WITH_AVX:-ON} -ENV WITH_DOC=${WITH_DOC:-ON} -ENV WITH_SWIG_PY=${WITH_SWIG_PY:-ON} -ENV WITH_STYLE_CHECK=${WITH_STYLE_CHECK:-OFF} - -RUN echo 'export LD_LIBRARY_PATH=/usr/lib64:${LD_LIBRARY_PATH}' >> /etc/profile - -# Configure OpenSSH server. c.f. https://docs.docker.com/engine/examples/running_ssh_service -RUN mkdir /var/run/sshd -RUN echo 'root:root' | chpasswd -RUN sed -ri 's/^PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config -RUN sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config -EXPOSE 22 - -CMD ["/usr/sbin/sshd", "-D"] diff --git a/paddle/scripts/docker/Dockerfile.gpu b/paddle/scripts/docker/Dockerfile.gpu index 6c1c2225d1a304..da20b2635e10e7 100644 --- a/paddle/scripts/docker/Dockerfile.gpu +++ b/paddle/scripts/docker/Dockerfile.gpu @@ -13,8 +13,8 @@ RUN apt-get update && \ apt-get install -y automake clang-3.8 llvm-3.8 libclang-3.8-dev && \ apt-get clean -y -RUN pip install --upgrade pip && \ - pip install 'protobuf==3.1.0.post1' && \ +RUN pip install --upgrade pip && \ + pip install -U protobuf && \ pip install -U wheel pillow BeautifulSoup && \ pip install -U docopt PyYAML sphinx && \ pip install -U sphinx_rtd_theme recommonmark jupyter @@ -23,10 +23,12 @@ RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \ cd cmake-3.4.1 && ./bootstrap && make -j4 && make install && \ cd .. && rm -rf cmake-3.4.1 +ARG BUILD_AND_INSTALL ARG WITH_AVX ARG WITH_DOC ARG WITH_STYLE_CHECK +ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-OFF} ENV WITH_GPU=ON ENV WITH_AVX=${WITH_AVX:-ON} ENV WITH_DOC=${WITH_DOC:-ON} @@ -37,10 +39,6 @@ COPY . /paddle/ RUN /paddle/paddle/scripts/docker/build.sh VOLUME ["/usr/share/nginx/html/data", "/usr/share/nginx/html/paddle"] -RUN echo 'export LD_LIBRARY_PATH=/usr/lib64:${LD_LIBRARY_PATH}' >> /etc/profile -RUN pip install /usr/local/opt/paddle/share/wheels/*.whl -RUN paddle version # print version after build - # Configure OpenSSH server. c.f. https://docs.docker.com/engine/examples/running_ssh_service RUN mkdir /var/run/sshd RUN echo 'root:root' | chpasswd diff --git a/paddle/scripts/docker/build.sh b/paddle/scripts/docker/build.sh index 7edba3dd09cdc5..6197b41d6b5f19 100755 --- a/paddle/scripts/docker/build.sh +++ b/paddle/scripts/docker/build.sh @@ -8,42 +8,50 @@ function abort(){ trap 'abort' 0 set -e -if [ ${WITH_GPU} == 'ON' ]; then - ln -s /usr/lib/x86_64-linux-gnu/libcudnn.so /usr/lib/libcudnn.so +# If Dockerfile.* sets BUILD_AND_INSTALL to 'ON', it would have copied +# source tree to /paddle, and this scripts should build it into +# /paddle/build. +if [[ ${BUILD_AND_INSTALL:-ON} == 'ON' ]]; then + if [[ ${WITH_GPU:-OFF} == 'ON' ]]; then + ln -s /usr/lib/x86_64-linux-gnu/libcudnn.so /usr/lib/libcudnn.so + fi + + mkdir -p /paddle/build # -p means no error if exists + cd /paddle/build + cmake .. \ + -DWITH_DOC=ON \ + -DWITH_GPU=${WITH_GPU:-OFF} \ + -DWITH_AVX=${WITH_AVX:-OFF} \ + -DWITH_SWIG_PY=ON \ + -DCUDNN_ROOT=/usr/ \ + -DWITH_STYLE_CHECK=OFF \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + make -j `nproc` + make install + + # Install woboq_codebrowser. + git clone https://github.com/woboq/woboq_codebrowser /woboq + cd /woboq + cmake -DLLVM_CONFIG_EXECUTABLE=/usr/bin/llvm-config-3.8 \ + -DCMAKE_BUILD_TYPE=Release \ + . + make + + export WOBOQ_OUT=/usr/share/nginx/html/paddle + export BUILD_DIR=/paddle/build + mkdir -p $WOBOQ_OUT + cp -rv /woboq/data $WOBOQ_OUT/../data + /woboq/generator/codebrowser_generator \ + -b /paddle/build \ + -a \ + -o $WOBOQ_OUT \ + -p paddle:/paddle + /woboq/indexgenerator/codebrowser_indexgenerator $WOBOQ_OUT + cd /woboq + make clean + + pip install /usr/local/opt/paddle/share/wheels/*.whl + paddle version fi -mkdir -p /paddle/build # -p means no error if exists -cd /paddle/build -cmake .. \ - -DWITH_DOC=ON \ - -DWITH_GPU=${WITH_GPU} \ - -DWITH_AVX=${WITH_AVX} \ - -DWITH_SWIG_PY=ON \ - -DCUDNN_ROOT=/usr/ \ - -DWITH_STYLE_CHECK=OFF \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -make -j `nproc` -make install - -# Install woboq_codebrowser. -git clone https://github.com/woboq/woboq_codebrowser /woboq -cd /woboq -cmake -DLLVM_CONFIG_EXECUTABLE=/usr/bin/llvm-config-3.8 \ - -DCMAKE_BUILD_TYPE=Release \ - . -make - -export WOBOQ_OUT=/usr/share/nginx/html/paddle -export BUILD_DIR=/paddle/build -mkdir -p $WOBOQ_OUT -cp -rv /woboq/data $WOBOQ_OUT/../data -/woboq/generator/codebrowser_generator \ - -b /paddle/build \ - -a \ - -o $WOBOQ_OUT \ - -p paddle:/paddle -/woboq/indexgenerator/codebrowser_indexgenerator $WOBOQ_OUT -cd /woboq -make clean -rm -rf /paddle/build trap : 0 From 3f02edeeeae64943cc652a865c600eec384e645f Mon Sep 17 00:00:00 2001 From: xichen Date: Fri, 27 Jan 2017 11:40:11 -0800 Subject: [PATCH 114/370] wording update after pr review --- doc/howto/usage/k8s/k8s_aws_en.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/doc/howto/usage/k8s/k8s_aws_en.md b/doc/howto/usage/k8s/k8s_aws_en.md index 46c4f5582dbd81..ce5ccbca5ee33b 100644 --- a/doc/howto/usage/k8s/k8s_aws_en.md +++ b/doc/howto/usage/k8s/k8s_aws_en.md @@ -3,12 +3,6 @@ We will show you step by step on how to run distributed PaddlePaddle training on AWS cluster with Kubernetes. Let's start from core concepts. -## Choose AWS Service Region -This tutorial requires several AWS services work in the same region. Before we create anything in AWS, please check the following link -https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/ -Choose a region which has the following services available: EC2, EFS, VPS, CloudFormation, KMS, VPC, S3. -In this tutorial, we use "Oregon(us-west-2)" as example. - ## Distributed PaddlePaddle Training Core Concepts ### Distributed Training Job @@ -50,6 +44,12 @@ We rank each pod by sorting them by their ips. The rank of each pod could be the ## PaddlePaddle on AWS with Kubernetes +### Choose AWS Service Region +This tutorial requires several AWS services work in the same region. Before we create anything in AWS, please check the following link +https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/ +Choose a region which has the following services available: EC2, EFS, VPS, CloudFormation, KMS, VPC, S3. +In this tutorial, we use "Oregon(us-west-2)" as example. + ### Create AWS Account and IAM Account Under each AWS account, we can create multiple [IAM](http://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html) users. This allows us to grant some privileges to each IAM user and to create/operate AWS clusters as an IAM user. @@ -80,7 +80,7 @@ Please be aware that this tutorial needs the following privileges for the user i #### kube-aws [kube-aws](https://github.com/coreos/kube-aws) is a CLI tool to automate cluster deployment to AWS. -##### Verify integrity of kube-aws downloaded +##### Verify kube-aws integrity Note: if you are using a non-official release (e.g RC release) kube-aws, you can skip this setp. Import the CoreOS Application Signing Public Key: @@ -265,10 +265,7 @@ When the cluster is created, the controller will expose the TLS-secured API on a DNS name should have a CNAME points to cluster DNS name or an A record points to the cluster IP address. - -We will need to use DNS name later in tutorial. If you don't already own one, you can choose any DNS name (e.g., `paddle`) and modify `/etc/hosts` to associate cluster ip with that DNS name. We will find the ip to map to `paddle` in later steps. Also in this case, will have to add name service (route53) in aws cluster in later step. -======= -We will need to use DNS name later in tutorial. +We will need to use DNS name later in tutorial. If you don't already own one, you can choose any DNS name (e.g., `paddle`) and modify `/etc/hosts` to associate cluster IP with that DNS name for your local machine. And add name service (route53) in aws to associate the IP to paddle for cluster. We will find the cluster IP in later steps. #### S3 bucket @@ -382,7 +379,7 @@ In the above output, both ip `54.241.164.52`, `54.67.102.112` will work. ##### Update local DNS association Edit `/etc/hosts` to associate above ip with the DNS name. ##### Add Route53 private name service in VPC - - Open Route53 web console + - Open [Route53 Console](https://console.aws.amazon.com/route53/home) - Create hosted zone with following config - Domain name: "paddle" - Type: "Private hosted zone for amazon VPC" From 6911b848e34282cb71312e31d39ba1b7af9cb228 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Fri, 27 Jan 2017 15:16:57 -0800 Subject: [PATCH 115/370] remove `allow_inefficient_sparse_update` since it's only defined but never used. --- doc/howto/usage/cmd_parameter/arguments_cn.md | 5 ----- doc/howto/usage/cmd_parameter/arguments_en.md | 5 ----- .../usage/cmd_parameter/detail_introduction_cn.md | 4 ---- .../usage/cmd_parameter/detail_introduction_en.md | 4 ---- paddle/math/SparseRowMatrix.cpp | 4 ---- paddle/math/SparseRowMatrix.h | 11 ++++------- 6 files changed, 4 insertions(+), 29 deletions(-) diff --git a/doc/howto/usage/cmd_parameter/arguments_cn.md b/doc/howto/usage/cmd_parameter/arguments_cn.md index 833e21dd19ef3c..2e2a2fcc54a09f 100644 --- a/doc/howto/usage/cmd_parameter/arguments_cn.md +++ b/doc/howto/usage/cmd_parameter/arguments_cn.md @@ -127,11 +127,6 @@ √√ - -allow_inefficient_sparse_update -√√ - - start_pass √√ diff --git a/doc/howto/usage/cmd_parameter/arguments_en.md b/doc/howto/usage/cmd_parameter/arguments_en.md index 013edbc9047817..e5546f0ddc78a9 100644 --- a/doc/howto/usage/cmd_parameter/arguments_en.md +++ b/doc/howto/usage/cmd_parameter/arguments_en.md @@ -127,11 +127,6 @@ It looks like there are a lot of arguments. However, most of them are for develo √√ - -allow_inefficient_sparse_update -√√ - - start_pass √√ diff --git a/doc/howto/usage/cmd_parameter/detail_introduction_cn.md b/doc/howto/usage/cmd_parameter/detail_introduction_cn.md index dbf7c6f00b8ba5..3b573a324d541b 100644 --- a/doc/howto/usage/cmd_parameter/detail_introduction_cn.md +++ b/doc/howto/usage/cmd_parameter/detail_introduction_cn.md @@ -306,10 +306,6 @@ - 指示是否显示参数服务器上的稀疏参数分布的日志细节. - 类型: bool (默认: 0). -* `--allow_inefficient_sparse_update` - - 指示是否允许低效率的稀疏更新. - - 类型: bool (默认: 0). - * `--check_sparse_distribution_batches` - 每运行多少个批次执行一次稀疏参数分布的检查. - 类型: int32 (默认: 100). diff --git a/doc/howto/usage/cmd_parameter/detail_introduction_en.md b/doc/howto/usage/cmd_parameter/detail_introduction_en.md index aa69a3bd5423c4..33b7ec0d51a96e 100644 --- a/doc/howto/usage/cmd_parameter/detail_introduction_en.md +++ b/doc/howto/usage/cmd_parameter/detail_introduction_en.md @@ -310,10 +310,6 @@ - show log details for sparse parameter distribution in pserver. - type: bool (default: 0). -* `--allow_inefficient_sparse_update` - - Whether to allow inefficient sparse update. - - type: bool (default: 0). - * `--check_sparse_distribution_batches` - Running sparse parameter distribution check every so many batches. - type: int32 (default: 100). diff --git a/paddle/math/SparseRowMatrix.cpp b/paddle/math/SparseRowMatrix.cpp index b61c6b2d49ccea..b8c781ca1fd46c 100644 --- a/paddle/math/SparseRowMatrix.cpp +++ b/paddle/math/SparseRowMatrix.cpp @@ -24,10 +24,6 @@ limitations under the License. */ #include "paddle/utils/Thread.h" #include "paddle/utils/Util.h" -DEFINE_bool(allow_inefficient_sparse_update, - false, - "Whether to allow inefficient sparse update"); - namespace paddle { const unsigned int SparseRowCpuMatrix::kUnusedId_ = -1U; diff --git a/paddle/math/SparseRowMatrix.h b/paddle/math/SparseRowMatrix.h index c05fc98ff9fe73..1ccbf97b25922a 100644 --- a/paddle/math/SparseRowMatrix.h +++ b/paddle/math/SparseRowMatrix.h @@ -21,8 +21,6 @@ limitations under the License. */ #include "RowBuffer.h" #include "paddle/utils/Util.h" -DECLARE_bool(allow_inefficient_sparse_update); - namespace paddle { /** @@ -183,11 +181,10 @@ class SparseRowCpuMatrix : public CpuMatrix { inline void checkStoreSize() { if (buf_->isAutoGrowth()) { if (buf_->getRowCount() > 0.5 * height_) { - LOG(WARNING) - << "There are more than 0.5*height (" << localIndices_->size() - << ") rows are used for sparse " - << "update, which is not efficient. Considering not use " - << "sparse_update or set --allow_inefficient_sparse_update=true"; + LOG(WARNING) << "There are more than 0.5*height (" + << localIndices_->size() << ") rows are used for sparse " + << "update, which is not efficient. Considering not use " + << "sparse_update."; } } else { CHECK_LE(localIndices_->size(), buf_->getRowCount()); From 6da7283475355537be2a0775bd9df670351eb1c5 Mon Sep 17 00:00:00 2001 From: wangyang59 Date: Fri, 27 Jan 2017 16:11:53 -0800 Subject: [PATCH 116/370] make gru_group parameters sharable --- paddle/gserver/layers/GruStepLayer.cpp | 4 +- python/paddle/trainer/config_parser.py | 2 +- python/paddle/trainer/recurrent_units.py | 3 + .../paddle/trainer_config_helpers/layers.py | 4 +- .../paddle/trainer_config_helpers/networks.py | 6 + .../tests/configs/file_list.sh | 2 +- .../configs/protostr/shared_gru.protostr | 295 ++++++++++++++++++ .../configs/protostr/test_rnn_group.protostr | 8 +- .../tests/configs/shared_gru.py | 40 +++ 9 files changed, 355 insertions(+), 9 deletions(-) create mode 100644 python/paddle/trainer_config_helpers/tests/configs/protostr/shared_gru.protostr create mode 100644 python/paddle/trainer_config_helpers/tests/configs/shared_gru.py diff --git a/paddle/gserver/layers/GruStepLayer.cpp b/paddle/gserver/layers/GruStepLayer.cpp index 4a1006aa941f39..ce692c490881c9 100644 --- a/paddle/gserver/layers/GruStepLayer.cpp +++ b/paddle/gserver/layers/GruStepLayer.cpp @@ -68,8 +68,8 @@ bool GruStepLayer::init(const LayerMap& layerMap, if (!Layer::init(layerMap, parameterMap)) return false; CHECK_EQ(2U, inputLayers_.size()); - CHECK_EQ(getSize() * getSize() * 3, parameters_[0]->getSize()); - weight_.reset(new Weight(getSize(), getSize() * 3, parameters_[0])); + CHECK_EQ(getSize() * getSize() * 3, parameters_[1]->getSize()); + weight_.reset(new Weight(getSize(), getSize() * 3, parameters_[1])); if (biasParameter_.get() != NULL) { CHECK_EQ(getSize() * 3, biasParameter_->getSize()); diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index 6701eced60d068..4fbf076ae98c4d 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -2996,7 +2996,7 @@ def __init__(self, config_assert(input_layer1.size == size, 'input_layer1.size != layer.size') self.config.active_gate_type = active_gate_type - self.create_input_parameter(0, size * size * 3, [size, size * 3]) + self.create_input_parameter(1, size * size * 3, [size, size * 3]) self.create_bias_parameter(bias, size * 3) diff --git a/python/paddle/trainer/recurrent_units.py b/python/paddle/trainer/recurrent_units.py index edca279dcadef4..ff7e8932dcad79 100644 --- a/python/paddle/trainer/recurrent_units.py +++ b/python/paddle/trainer/recurrent_units.py @@ -19,6 +19,9 @@ # to use these units, import this module in your config_file: # import trainer.recurrent_units # +# The modules in this file are DEPRECATED. +# If you would like to use lstm/gru +# please use the functions defined in paddle.trainer_config_helpers. from paddle.trainer.config_parser import * diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 85a28e14aeb8eb..f0b5d7c3b4f26a 100644 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -2682,6 +2682,7 @@ def lstm_step_layer(input, @wrap_bias_attr_default() +@wrap_param_attr_default() @wrap_act_default(param_names=['gate_act'], act=SigmoidActivation()) @wrap_act_default(act=TanhActivation()) @wrap_name_default('gru_step') @@ -2693,6 +2694,7 @@ def gru_step_layer(input, name=None, gate_act=None, bias_attr=None, + param_attr=None, layer_attr=None): """ @@ -2714,7 +2716,7 @@ def gru_step_layer(input, Layer( name=name, type=LayerType.GRU_STEP_LAYER, - inputs=[input.name, output_mem.name], + inputs=[input.name, Input(output_mem.name, **param_attr.attr)], bias=ParamAttr.to_bias(bias_attr), size=size, active_type=act.name, diff --git a/python/paddle/trainer_config_helpers/networks.py b/python/paddle/trainer_config_helpers/networks.py index 375bea34e8aa0a..88e188cb2b1da6 100644 --- a/python/paddle/trainer_config_helpers/networks.py +++ b/python/paddle/trainer_config_helpers/networks.py @@ -822,6 +822,7 @@ def gru_unit(input, size=None, name=None, gru_bias_attr=None, + gru_param_attr=None, act=None, gate_act=None, gru_layer_attr=None): @@ -862,6 +863,7 @@ def gru_unit(input, output_mem=out_mem, size=size, bias_attr=gru_bias_attr, + param_attr=gru_param_attr, act=act, gate_act=gate_act, layer_attr=gru_layer_attr) @@ -874,6 +876,7 @@ def gru_group(input, name=None, reverse=False, gru_bias_attr=None, + gru_param_attr=None, act=None, gate_act=None, gru_layer_attr=None): @@ -922,6 +925,7 @@ def __gru_step__(ipt): name=name, size=size, gru_bias_attr=gru_bias_attr, + gru_param_attr=gru_param_attr, act=act, gate_act=gate_act, gru_layer_attr=gru_layer_attr) @@ -942,6 +946,7 @@ def simple_gru(input, mixed_bias_param_attr=None, mixed_layer_attr=None, gru_bias_attr=None, + gru_param_attr=None, act=None, gate_act=None, gru_layer_attr=None): @@ -1010,6 +1015,7 @@ def simple_gru(input, input=m, reverse=reverse, gru_bias_attr=gru_bias_attr, + gru_param_attr=gru_param_attr, act=act, gate_act=gate_act, gru_layer_attr=gru_layer_attr) diff --git a/python/paddle/trainer_config_helpers/tests/configs/file_list.sh b/python/paddle/trainer_config_helpers/tests/configs/file_list.sh index 3f1d99701afe54..ea46b557a26ce6 100755 --- a/python/paddle/trainer_config_helpers/tests/configs/file_list.sh +++ b/python/paddle/trainer_config_helpers/tests/configs/file_list.sh @@ -3,7 +3,7 @@ export configs=(test_fc layer_activations projections test_print_layer test_sequence_pooling test_lstmemory_layer test_grumemory_layer last_first_seq test_expand_layer test_ntm_layers test_hsigmoid img_layers img_trans_layers util_layers simple_rnn_layers unused_layers test_cost_layers -test_rnn_group shared_fc shared_lstm test_cost_layers_with_weight +test_rnn_group shared_fc shared_lstm shared_gru test_cost_layers_with_weight test_spp_layer test_bilinear_interp test_maxout test_bi_grumemory math_ops) export whole_configs=(test_split_datasource) diff --git a/python/paddle/trainer_config_helpers/tests/configs/protostr/shared_gru.protostr b/python/paddle/trainer_config_helpers/tests/configs/protostr/shared_gru.protostr new file mode 100644 index 00000000000000..c0868713ebbbc1 --- /dev/null +++ b/python/paddle/trainer_config_helpers/tests/configs/protostr/shared_gru.protostr @@ -0,0 +1,295 @@ +type: "recurrent_nn" +layers { + name: "data_a" + type: "data" + size: 100 + active_type: "" +} +layers { + name: "data_b" + type: "data" + size: 100 + active_type: "" +} +layers { + name: "__simple_gru_0___transform" + type: "mixed" + size: 600 + active_type: "" + inputs { + input_layer_name: "data_a" + input_parameter_name: "mixed_param" + proj_conf { + type: "fc" + name: "___simple_gru_0___transform.w0" + input_size: 100 + output_size: 600 + } + } +} +layers { + name: "__simple_gru_0___recurrent_group" + type: "recurrent_layer_group" + active_type: "" +} +layers { + name: "__simple_gru_0___transform@__simple_gru_0___recurrent_group" + type: "scatter_agent" + size: 600 + active_type: "" +} +layers { + name: "__simple_gru_0__+delay1@__simple_gru_0___recurrent_group" + type: "agent" + size: 200 + active_type: "" +} +layers { + name: "__simple_gru_0__@__simple_gru_0___recurrent_group" + type: "gru_step" + size: 200 + active_type: "tanh" + inputs { + input_layer_name: "__simple_gru_0___transform@__simple_gru_0___recurrent_group" + } + inputs { + input_layer_name: "__simple_gru_0__+delay1@__simple_gru_0___recurrent_group" + input_parameter_name: "gru_param" + } + bias_parameter_name: "gru_bias" + active_gate_type: "sigmoid" +} +layers { + name: "__simple_gru_0__" + type: "gather_agent" + size: 200 + active_type: "" +} +layers { + name: "__simple_gru_1___transform" + type: "mixed" + size: 600 + active_type: "" + inputs { + input_layer_name: "data_b" + input_parameter_name: "mixed_param" + proj_conf { + type: "fc" + name: "___simple_gru_1___transform.w0" + input_size: 100 + output_size: 600 + } + } +} +layers { + name: "__simple_gru_1___recurrent_group" + type: "recurrent_layer_group" + active_type: "" +} +layers { + name: "__simple_gru_1___transform@__simple_gru_1___recurrent_group" + type: "scatter_agent" + size: 600 + active_type: "" +} +layers { + name: "__simple_gru_1__+delay1@__simple_gru_1___recurrent_group" + type: "agent" + size: 200 + active_type: "" +} +layers { + name: "__simple_gru_1__@__simple_gru_1___recurrent_group" + type: "gru_step" + size: 200 + active_type: "tanh" + inputs { + input_layer_name: "__simple_gru_1___transform@__simple_gru_1___recurrent_group" + } + inputs { + input_layer_name: "__simple_gru_1__+delay1@__simple_gru_1___recurrent_group" + input_parameter_name: "gru_param" + } + bias_parameter_name: "gru_bias" + active_gate_type: "sigmoid" +} +layers { + name: "__simple_gru_1__" + type: "gather_agent" + size: 200 + active_type: "" +} +layers { + name: "__last_seq_0__" + type: "seqlastins" + size: 200 + active_type: "linear" + inputs { + input_layer_name: "__simple_gru_0__" + } + trans_type: "non-seq" +} +layers { + name: "__last_seq_1__" + type: "seqlastins" + size: 200 + active_type: "linear" + inputs { + input_layer_name: "__simple_gru_1__" + } + trans_type: "non-seq" +} +layers { + name: "__fc_layer_0__" + type: "fc" + size: 10 + active_type: "softmax" + inputs { + input_layer_name: "__last_seq_0__" + input_parameter_name: "softmax_param" + } + inputs { + input_layer_name: "__last_seq_1__" + input_parameter_name: "softmax_param" + } +} +layers { + name: "label" + type: "data" + size: 10 + active_type: "" +} +layers { + name: "__cost_0__" + type: "multi-class-cross-entropy" + size: 1 + active_type: "" + inputs { + input_layer_name: "__fc_layer_0__" + } + inputs { + input_layer_name: "label" + } + coeff: 1.0 +} +parameters { + name: "mixed_param" + size: 60000 + initial_mean: 0.0 + initial_std: 0.1 + dims: 100 + dims: 600 + initial_strategy: 0 + initial_smart: true +} +parameters { + name: "gru_param" + size: 120000 + initial_mean: 0.0 + initial_std: 0.0707106781187 + dims: 200 + dims: 600 + initial_strategy: 0 + initial_smart: true +} +parameters { + name: "gru_bias" + size: 600 + initial_mean: 0.0 + initial_std: 0.0 + dims: 1 + dims: 600 + initial_strategy: 0 + initial_smart: false +} +parameters { + name: "softmax_param" + size: 2000 + initial_mean: 0.0 + initial_std: 0.0707106781187 + dims: 200 + dims: 10 + initial_strategy: 0 + initial_smart: true +} +input_layer_names: "data_a" +input_layer_names: "data_b" +input_layer_names: "label" +output_layer_names: "__cost_0__" +evaluators { + name: "classification_error_evaluator" + type: "classification_error" + input_layers: "__fc_layer_0__" + input_layers: "label" +} +sub_models { + name: "root" + layer_names: "data_a" + layer_names: "data_b" + layer_names: "__simple_gru_0___transform" + layer_names: "__simple_gru_0___recurrent_group" + layer_names: "__simple_gru_0__" + layer_names: "__simple_gru_1___transform" + layer_names: "__simple_gru_1___recurrent_group" + layer_names: "__simple_gru_1__" + layer_names: "__last_seq_0__" + layer_names: "__last_seq_1__" + layer_names: "__fc_layer_0__" + layer_names: "label" + layer_names: "__cost_0__" + input_layer_names: "data_a" + input_layer_names: "data_b" + input_layer_names: "label" + output_layer_names: "__cost_0__" + evaluator_names: "classification_error_evaluator" + is_recurrent_layer_group: false +} +sub_models { + name: "__simple_gru_0___recurrent_group" + layer_names: "__simple_gru_0___transform@__simple_gru_0___recurrent_group" + layer_names: "__simple_gru_0__+delay1@__simple_gru_0___recurrent_group" + layer_names: "__simple_gru_0__@__simple_gru_0___recurrent_group" + is_recurrent_layer_group: true + reversed: false + memories { + layer_name: "__simple_gru_0__@__simple_gru_0___recurrent_group" + link_name: "__simple_gru_0__+delay1@__simple_gru_0___recurrent_group" + is_sequence: false + } + in_links { + layer_name: "__simple_gru_0___transform" + link_name: "__simple_gru_0___transform@__simple_gru_0___recurrent_group" + has_subseq: false + } + out_links { + layer_name: "__simple_gru_0__@__simple_gru_0___recurrent_group" + link_name: "__simple_gru_0__" + has_subseq: false + } + target_inlinkid: -1 +} +sub_models { + name: "__simple_gru_1___recurrent_group" + layer_names: "__simple_gru_1___transform@__simple_gru_1___recurrent_group" + layer_names: "__simple_gru_1__+delay1@__simple_gru_1___recurrent_group" + layer_names: "__simple_gru_1__@__simple_gru_1___recurrent_group" + is_recurrent_layer_group: true + reversed: false + memories { + layer_name: "__simple_gru_1__@__simple_gru_1___recurrent_group" + link_name: "__simple_gru_1__+delay1@__simple_gru_1___recurrent_group" + is_sequence: false + } + in_links { + layer_name: "__simple_gru_1___transform" + link_name: "__simple_gru_1___transform@__simple_gru_1___recurrent_group" + has_subseq: false + } + out_links { + layer_name: "__simple_gru_1__@__simple_gru_1___recurrent_group" + link_name: "__simple_gru_1__" + has_subseq: false + } + target_inlinkid: -1 +} + diff --git a/python/paddle/trainer_config_helpers/tests/configs/protostr/test_rnn_group.protostr b/python/paddle/trainer_config_helpers/tests/configs/protostr/test_rnn_group.protostr index 41d2e2f2671f5c..c1d39f77295892 100644 --- a/python/paddle/trainer_config_helpers/tests/configs/protostr/test_rnn_group.protostr +++ b/python/paddle/trainer_config_helpers/tests/configs/protostr/test_rnn_group.protostr @@ -307,10 +307,10 @@ layers { active_type: "tanh" inputs { input_layer_name: "__mixed_1__@__gru_group_0___recurrent_group" - input_parameter_name: "___gru_group_0__@__gru_group_0___recurrent_group.w0" } inputs { input_layer_name: "__gru_group_0__+delay1@__gru_group_0___recurrent_group" + input_parameter_name: "___gru_group_0__@__gru_group_0___recurrent_group.w1" } bias_parameter_name: "___gru_group_0__@__gru_group_0___recurrent_group.wbias" active_gate_type: "sigmoid" @@ -462,14 +462,14 @@ parameters { initial_smart: false } parameters { - name: "___gru_group_0__@__gru_group_0___recurrent_group.w0" + name: "___gru_group_0__@__gru_group_0___recurrent_group.w1" size: 30000 initial_mean: 0.0 - initial_std: 0.01 + initial_std: 0.1 dims: 100 dims: 300 initial_strategy: 0 - initial_smart: false + initial_smart: true } parameters { name: "___gru_group_0__@__gru_group_0___recurrent_group.wbias" diff --git a/python/paddle/trainer_config_helpers/tests/configs/shared_gru.py b/python/paddle/trainer_config_helpers/tests/configs/shared_gru.py new file mode 100644 index 00000000000000..c19bb9685aa24c --- /dev/null +++ b/python/paddle/trainer_config_helpers/tests/configs/shared_gru.py @@ -0,0 +1,40 @@ +from paddle.trainer_config_helpers import * + +settings(learning_rate=1e-4, batch_size=1000) + +data_1 = data_layer(name='data_a', size=100) +data_2 = data_layer(name='data_b', size=100) + +mixed_param = ParamAttr(name='mixed_param') + +gru_param = ParamAttr(name='gru_param') +gru_bias = ParamAttr(name='gru_bias', initial_mean=0., initial_std=0.) + +gru1 = simple_gru( + input=data_1, + size=200, + mixed_param_attr=mixed_param, + mixed_bias_param_attr=False, + gru_bias_attr=gru_bias, + gru_param_attr=gru_param) + +gru2 = simple_gru( + input=data_2, + size=200, + mixed_param_attr=mixed_param, + mixed_bias_param_attr=False, + gru_bias_attr=gru_bias, + gru_param_attr=gru_param) + +softmax_param = ParamAttr(name='softmax_param') + +predict = fc_layer( + input=[last_seq(input=gru1), last_seq(input=gru2)], + size=10, + param_attr=[softmax_param, softmax_param], + bias_attr=False, + act=SoftmaxActivation()) +outputs( + classification_cost( + input=predict, label=data_layer( + name='label', size=10))) From 0bd67524b1b7e14554f3fd0367180071099e88b0 Mon Sep 17 00:00:00 2001 From: wangyang59 Date: Mon, 30 Jan 2017 11:26:47 -0800 Subject: [PATCH 117/370] switch the parameter index in GruStepLayer in test_LayerGrad --- paddle/gserver/tests/test_LayerGrad.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paddle/gserver/tests/test_LayerGrad.cpp b/paddle/gserver/tests/test_LayerGrad.cpp index 8c8e876bd64fb9..813a99d8cdae2e 100644 --- a/paddle/gserver/tests/test_LayerGrad.cpp +++ b/paddle/gserver/tests/test_LayerGrad.cpp @@ -1404,9 +1404,9 @@ TEST(Layer, GruStepLayer) { config.biasSize = 12; config.inputDefs.push_back( - {INPUT_DATA, "layer_0", /* dim= */ 12, /* paraSize= */ 48}); + {INPUT_DATA, "layer_0", /* dim= */ 12, /* paraSize= */ 0}); config.inputDefs.push_back( - {INPUT_DATA, "layer_1", /* dim= */ 4, /* paraSize= */ 0}); + {INPUT_DATA, "layer_1", /* dim= */ 4, /* paraSize= */ 48}); config.layerConfig.add_inputs(); config.layerConfig.add_inputs(); From 9664322cfe23d775e9ac57ef4ee02096fda0fc5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=9B=8A?= Date: Mon, 30 Jan 2017 12:56:01 -0800 Subject: [PATCH 118/370] Update English document --- .../build_and_install/docker_install_en.rst | 78 +++++++++---------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/doc/getstarted/build_and_install/docker_install_en.rst b/doc/getstarted/build_and_install/docker_install_en.rst index 51a1a11674d987..fa19297238084f 100644 --- a/doc/getstarted/build_and_install/docker_install_en.rst +++ b/doc/getstarted/build_and_install/docker_install_en.rst @@ -16,70 +16,66 @@ Developers can work on PaddlePaddle using Docker. This allows developers to work on different platforms -- Linux, Mac OS X, and Windows -- in a consistent way. -The general development workflow with Docker and CMake is as follows: - -1. Get the source code of Paddle: +1. Build the Development Environment as a Docker Image .. code-block:: bash - git clone https://github.com/PaddlePaddle/Paddle.git + git clone --recursive https://github.com/PaddlePaddle/Paddle + cd Paddle + docker build -t paddle:dev -f paddle/scripts/docker/Dockerfile . -2. Build a development Docker image :code:`paddle:dev` from the source - code. This image contains all the development tools and - dependencies of PaddlePaddle. + Note that by default :code:`docker build` wouldn't import source + tree into the image and build it. If we want to do that, we need + to set a build arg: .. code-block:: bash - cd paddle - docker build -t paddle:dev -f paddle/scripts/docker/Dockerfile . - - Sometimes docker build might suffer from a slow network connection to the official Ubuntu apt-source servers. In such case, we can specify an apt-source mirror server that is geologically nearer to us. In the following example, we specified an apt-source server that responds fast in China.You can specify the UBUNTU MIRROR with :code:`--build-arg UBUNTU_MIRROR` like the example below. - - .. code-block:: bash + docker build -t paddle:dev -f paddle/scripts/docker/Dockerfile --build-arg BUILD_AND_INSTALL=ON . - docker build \ - --build-arg UBUNTU_MIRROR="http://mirrors.163.com" \ - -t paddle:dev \ - -f paddle/scripts/docker/Dockerfile . +1. Run the Development Environment -3. Run the image as a container and mounting local source code - directory into the container. This allows us to change the code on - the host and build it within the container. + Once we got the image :code:`paddle:dev`, we can use it to develop + Paddle by mounting the local source code tree into a container that + runs the image: .. code-block:: bash + docker run -d -p 2202:22 -v $PWD:/paddle paddle:dev - docker run \ - -d \ - --name paddle \ - -p 2022:22 \ - -v $PWD:/paddle \ - paddle:dev + This runs a container of the development environment Docker image + with the local source tree mounted to :code:`/paddle` of the + container. - where :code:`-d` makes the container running in background, - :code:`--name paddle` allows us to run a nginx container to serve - documents in this container, :code:`-p 2022:22` allows us to SSH - into this container, :code:`-v $PWD:/paddle` shares the source code - on the host with the container. + Note that the default entry-point of :code:`paddle:dev` is + :code:`sshd`, and above :code:`docker run` commands actually starts + an SSHD server listening on port 2202. This allows us to log into + this container with: -4. SSH into the container: + .. code-block:: bash + ssh root@localhost -p 2202 + + Usually, I run above commands on my Mac. I can also run them on a + GPU server :code:`xxx.yyy.zzz.www` and ssh from my Mac to it: .. code-block:: bash + my-mac$ ssh root@xxx.yyy.zzz.www -p 2202 - ssh root@localhost -p 2022 +1. Build and Install Using the Development Environment -5. We can edit the source code in the container or on this host. Then - we can build using cmake + Once I am in the container, I can use + :code:`paddle/scripts/docker/build.sh` to build, install, and test + Paddle: .. code-block:: bash + /paddle/paddle/scripts/docker/build.sh - cd /paddle # where paddle source code has been mounted into the container - mkdir -p build - cd build - cmake -DWITH_TESTING=ON .. - make -j `nproc` - CTEST_OUTPUT_ON_FAILURE=1 ctest + This builds everything about Paddle in :code:`/paddle/build`. And + we can run unit tests there: + + .. code-block:: bash + cd /paddle/build + ctest CPU-only and GPU Images From 909a9dd72aee4ba3212811599e9fee72ade0acf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=9B=8A?= Date: Mon, 30 Jan 2017 12:58:41 -0800 Subject: [PATCH 119/370] Update indentation of rst file --- doc/getstarted/build_and_install/docker_install_en.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/getstarted/build_and_install/docker_install_en.rst b/doc/getstarted/build_and_install/docker_install_en.rst index fa19297238084f..0bc313e4388ac6 100644 --- a/doc/getstarted/build_and_install/docker_install_en.rst +++ b/doc/getstarted/build_and_install/docker_install_en.rst @@ -20,9 +20,9 @@ Windows -- in a consistent way. .. code-block:: bash - git clone --recursive https://github.com/PaddlePaddle/Paddle - cd Paddle - docker build -t paddle:dev -f paddle/scripts/docker/Dockerfile . + git clone --recursive https://github.com/PaddlePaddle/Paddle + cd Paddle + docker build -t paddle:dev -f paddle/scripts/docker/Dockerfile . Note that by default :code:`docker build` wouldn't import source From 3afbd1c948f2b6871b55205d8d24dbb2cb1b9fd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=9B=8A?= Date: Mon, 30 Jan 2017 13:01:18 -0800 Subject: [PATCH 120/370] Update code indentation in rst files --- .../build_and_install/docker_install_en.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/getstarted/build_and_install/docker_install_en.rst b/doc/getstarted/build_and_install/docker_install_en.rst index 0bc313e4388ac6..cb6723d1ff9423 100644 --- a/doc/getstarted/build_and_install/docker_install_en.rst +++ b/doc/getstarted/build_and_install/docker_install_en.rst @@ -31,7 +31,7 @@ Windows -- in a consistent way. .. code-block:: bash - docker build -t paddle:dev -f paddle/scripts/docker/Dockerfile --build-arg BUILD_AND_INSTALL=ON . + docker build -t paddle:dev -f paddle/scripts/docker/Dockerfile --build-arg BUILD_AND_INSTALL=ON . 1. Run the Development Environment @@ -41,7 +41,7 @@ Windows -- in a consistent way. runs the image: .. code-block:: bash - docker run -d -p 2202:22 -v $PWD:/paddle paddle:dev + docker run -d -p 2202:22 -v $PWD:/paddle paddle:dev This runs a container of the development environment Docker image with the local source tree mounted to :code:`/paddle` of the @@ -53,13 +53,13 @@ Windows -- in a consistent way. this container with: .. code-block:: bash - ssh root@localhost -p 2202 + ssh root@localhost -p 2202 Usually, I run above commands on my Mac. I can also run them on a GPU server :code:`xxx.yyy.zzz.www` and ssh from my Mac to it: .. code-block:: bash - my-mac$ ssh root@xxx.yyy.zzz.www -p 2202 + my-mac$ ssh root@xxx.yyy.zzz.www -p 2202 1. Build and Install Using the Development Environment @@ -68,14 +68,14 @@ Windows -- in a consistent way. Paddle: .. code-block:: bash - /paddle/paddle/scripts/docker/build.sh + /paddle/paddle/scripts/docker/build.sh This builds everything about Paddle in :code:`/paddle/build`. And we can run unit tests there: .. code-block:: bash - cd /paddle/build - ctest + cd /paddle/build + ctest CPU-only and GPU Images From 891dadff0578a35ac9b097f0a65fc0c39311d26f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=9B=8A?= Date: Mon, 30 Jan 2017 13:02:07 -0800 Subject: [PATCH 121/370] Update code indentation in rst files --- doc/getstarted/build_and_install/docker_install_en.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/getstarted/build_and_install/docker_install_en.rst b/doc/getstarted/build_and_install/docker_install_en.rst index cb6723d1ff9423..3a322b2159a491 100644 --- a/doc/getstarted/build_and_install/docker_install_en.rst +++ b/doc/getstarted/build_and_install/docker_install_en.rst @@ -41,6 +41,7 @@ Windows -- in a consistent way. runs the image: .. code-block:: bash + docker run -d -p 2202:22 -v $PWD:/paddle paddle:dev This runs a container of the development environment Docker image @@ -53,12 +54,14 @@ Windows -- in a consistent way. this container with: .. code-block:: bash + ssh root@localhost -p 2202 Usually, I run above commands on my Mac. I can also run them on a GPU server :code:`xxx.yyy.zzz.www` and ssh from my Mac to it: .. code-block:: bash + my-mac$ ssh root@xxx.yyy.zzz.www -p 2202 1. Build and Install Using the Development Environment @@ -68,12 +71,14 @@ Windows -- in a consistent way. Paddle: .. code-block:: bash + /paddle/paddle/scripts/docker/build.sh This builds everything about Paddle in :code:`/paddle/build`. And we can run unit tests there: .. code-block:: bash + cd /paddle/build ctest From cc9484909e0886b1442e7118807ecc76893545fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=9B=8A?= Date: Mon, 30 Jan 2017 13:03:11 -0800 Subject: [PATCH 122/370] Update enumerators in rst files --- doc/getstarted/build_and_install/docker_install_en.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/getstarted/build_and_install/docker_install_en.rst b/doc/getstarted/build_and_install/docker_install_en.rst index 3a322b2159a491..5a1056e859a0c9 100644 --- a/doc/getstarted/build_and_install/docker_install_en.rst +++ b/doc/getstarted/build_and_install/docker_install_en.rst @@ -34,7 +34,7 @@ Windows -- in a consistent way. docker build -t paddle:dev -f paddle/scripts/docker/Dockerfile --build-arg BUILD_AND_INSTALL=ON . -1. Run the Development Environment +2. Run the Development Environment Once we got the image :code:`paddle:dev`, we can use it to develop Paddle by mounting the local source code tree into a container that @@ -64,7 +64,7 @@ Windows -- in a consistent way. my-mac$ ssh root@xxx.yyy.zzz.www -p 2202 -1. Build and Install Using the Development Environment +3. Build and Install Using the Development Environment Once I am in the container, I can use :code:`paddle/scripts/docker/build.sh` to build, install, and test From e1d074abdb6d4301d49b060f7684f50487f95123 Mon Sep 17 00:00:00 2001 From: zhanghaichao Date: Mon, 30 Jan 2017 17:41:58 -0800 Subject: [PATCH 123/370] updated comments for gru_group and lstm_group in networks.py --- python/paddle/trainer_config_helpers/networks.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/python/paddle/trainer_config_helpers/networks.py b/python/paddle/trainer_config_helpers/networks.py index 375bea34e8aa0a..48655b9ebc1773 100644 --- a/python/paddle/trainer_config_helpers/networks.py +++ b/python/paddle/trainer_config_helpers/networks.py @@ -737,12 +737,12 @@ def lstmemory_group(input, lstm_layer_attr=None, get_output_layer_attr=None): """ - lstm_group is a recurrent layer group version Long Short Term Memory. It + lstm_group is a recurrent layer group version of Long Short Term Memory. It does exactly the same calculation as the lstmemory layer (see lstmemory in layers.py for the maths) does. A promising benefit is that LSTM memory - cell states, or hidden states in every time step are accessible to for the + cell states, or hidden states in every time step are accessible to the user. This is especially useful in attention model. If you do not need to - access to the internal states of the lstm, but merely use its outputs, + access the internal states of the lstm, but merely use its outputs, it is recommended to use the lstmemory, which is relatively faster than lstmemory_group. @@ -878,11 +878,11 @@ def gru_group(input, gate_act=None, gru_layer_attr=None): """ - gru_group is a recurrent layer group version Gated Recurrent Unit. It + gru_group is a recurrent layer group version of Gated Recurrent Unit. It does exactly the same calculation as the grumemory layer does. A promising - benefit is that gru hidden sates are accessible to for the user. This is - especially useful in attention model. If you do not need to access to - any internal state, but merely use the outputs of a GRU, it is recommanded + benefit is that gru hidden states are accessible to the user. This is + especially useful in attention model. If you do not need to access + any internal state, but merely use the outputs of a GRU, it is recommended to use the grumemory, which is relatively faster. Please see grumemory in layers.py for more detail about the maths. From 19514f58bf1ec06efdffb3dcf6f5139bfd26b5c8 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Wed, 1 Feb 2017 07:46:49 -0800 Subject: [PATCH 124/370] fix paddle docker hub path (paddledev/paddle not paddle-dev/paddle) --- doc/getstarted/build_and_install/docker_install_cn.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/getstarted/build_and_install/docker_install_cn.rst b/doc/getstarted/build_and_install/docker_install_cn.rst index 35234e0eb3ece3..6b132d2a4d31ab 100644 --- a/doc/getstarted/build_and_install/docker_install_cn.rst +++ b/doc/getstarted/build_and_install/docker_install_cn.rst @@ -12,7 +12,7 @@ PaddlePaddle项目提供官方 `Docker `_ 镜像。Dock PaddlePaddle提供的Docker镜像版本 -------------------------------- -我们提供了12个 `Docker image `_ ,他们的image name都是 :code:`paddle-dev/paddle` ,tag分别为 +我们提供了12个 `Docker image `_ ,他们的image name都是 :code:`paddledev/paddle` ,tag分别为 +-----------------+------------------+------------------------+-----------------------+ | | normal | devel | demo | @@ -45,7 +45,7 @@ PaddlePaddle提供的Docker镜像版本 if cat /proc/cpuinfo | grep -q avx ; then echo "Support AVX"; else echo "Not support AVX"; fi -如果输出 :code:`Support AVX`,则可以选择上表中的AVX版本PaddlePaddle。否则需要选择非AVX的PaddlePaddle。选择普通CPU版本的devel版本的image,则可以使用 :code:`paddle-dev/paddle:cpu-devel-latest` 来引用这个image。 +如果输出 :code:`Support AVX`,则可以选择上表中的AVX版本PaddlePaddle。否则需要选择非AVX的PaddlePaddle。选择普通CPU版本的devel版本的image,则可以使用 :code:`paddledev/paddle:cpu-devel-latest` 来引用这个image。 PaddlePaddle提供的镜像并不包含任何命令运行,想要运行PaddlePaddle,您需要进入镜像运行PaddlePaddle 程序或者自定义一个含有启动脚本的image。具体请参考注意事项中的 :code:`使用ssh访问PaddlePaddle镜像` From 04b5daf92d69a9cce32af59fa5cf62610ef44f24 Mon Sep 17 00:00:00 2001 From: wangyang59 Date: Wed, 1 Feb 2017 13:44:00 -0800 Subject: [PATCH 125/370] change the parameter position of gru_step_layer from 1 back to 0 --- paddle/gserver/layers/GruStepLayer.cpp | 4 ++-- paddle/gserver/tests/test_LayerGrad.cpp | 4 ++-- python/paddle/trainer/config_parser.py | 2 +- python/paddle/trainer_config_helpers/layers.py | 5 ++++- .../tests/configs/protostr/shared_gru.protostr | 4 ++-- .../tests/configs/protostr/test_rnn_group.protostr | 4 ++-- 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/paddle/gserver/layers/GruStepLayer.cpp b/paddle/gserver/layers/GruStepLayer.cpp index ce692c490881c9..4a1006aa941f39 100644 --- a/paddle/gserver/layers/GruStepLayer.cpp +++ b/paddle/gserver/layers/GruStepLayer.cpp @@ -68,8 +68,8 @@ bool GruStepLayer::init(const LayerMap& layerMap, if (!Layer::init(layerMap, parameterMap)) return false; CHECK_EQ(2U, inputLayers_.size()); - CHECK_EQ(getSize() * getSize() * 3, parameters_[1]->getSize()); - weight_.reset(new Weight(getSize(), getSize() * 3, parameters_[1])); + CHECK_EQ(getSize() * getSize() * 3, parameters_[0]->getSize()); + weight_.reset(new Weight(getSize(), getSize() * 3, parameters_[0])); if (biasParameter_.get() != NULL) { CHECK_EQ(getSize() * 3, biasParameter_->getSize()); diff --git a/paddle/gserver/tests/test_LayerGrad.cpp b/paddle/gserver/tests/test_LayerGrad.cpp index 813a99d8cdae2e..8c8e876bd64fb9 100644 --- a/paddle/gserver/tests/test_LayerGrad.cpp +++ b/paddle/gserver/tests/test_LayerGrad.cpp @@ -1404,9 +1404,9 @@ TEST(Layer, GruStepLayer) { config.biasSize = 12; config.inputDefs.push_back( - {INPUT_DATA, "layer_0", /* dim= */ 12, /* paraSize= */ 0}); + {INPUT_DATA, "layer_0", /* dim= */ 12, /* paraSize= */ 48}); config.inputDefs.push_back( - {INPUT_DATA, "layer_1", /* dim= */ 4, /* paraSize= */ 48}); + {INPUT_DATA, "layer_1", /* dim= */ 4, /* paraSize= */ 0}); config.layerConfig.add_inputs(); config.layerConfig.add_inputs(); diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index 4fbf076ae98c4d..6701eced60d068 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -2996,7 +2996,7 @@ def __init__(self, config_assert(input_layer1.size == size, 'input_layer1.size != layer.size') self.config.active_gate_type = active_gate_type - self.create_input_parameter(1, size * size * 3, [size, size * 3]) + self.create_input_parameter(0, size * size * 3, [size, size * 3]) self.create_bias_parameter(bias, size * 3) diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index f0b5d7c3b4f26a..770d6303c13587 100644 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -2706,6 +2706,9 @@ def gru_step_layer(input, :param name: :param gate_act: :param bias_attr: + :param param_attr: the parameter_attribute for transforming the output_mem + from previous step. It is instead grouped with input due + to backward model compatibility. :param layer_attr: :return: LayerOutput object. :rtype: LayerOutput @@ -2716,7 +2719,7 @@ def gru_step_layer(input, Layer( name=name, type=LayerType.GRU_STEP_LAYER, - inputs=[input.name, Input(output_mem.name, **param_attr.attr)], + inputs=[Input(input.name, **param_attr.attr), output_mem.name], bias=ParamAttr.to_bias(bias_attr), size=size, active_type=act.name, diff --git a/python/paddle/trainer_config_helpers/tests/configs/protostr/shared_gru.protostr b/python/paddle/trainer_config_helpers/tests/configs/protostr/shared_gru.protostr index c0868713ebbbc1..b6905824f0cb09 100644 --- a/python/paddle/trainer_config_helpers/tests/configs/protostr/shared_gru.protostr +++ b/python/paddle/trainer_config_helpers/tests/configs/protostr/shared_gru.protostr @@ -51,10 +51,10 @@ layers { active_type: "tanh" inputs { input_layer_name: "__simple_gru_0___transform@__simple_gru_0___recurrent_group" + input_parameter_name: "gru_param" } inputs { input_layer_name: "__simple_gru_0__+delay1@__simple_gru_0___recurrent_group" - input_parameter_name: "gru_param" } bias_parameter_name: "gru_bias" active_gate_type: "sigmoid" @@ -105,10 +105,10 @@ layers { active_type: "tanh" inputs { input_layer_name: "__simple_gru_1___transform@__simple_gru_1___recurrent_group" + input_parameter_name: "gru_param" } inputs { input_layer_name: "__simple_gru_1__+delay1@__simple_gru_1___recurrent_group" - input_parameter_name: "gru_param" } bias_parameter_name: "gru_bias" active_gate_type: "sigmoid" diff --git a/python/paddle/trainer_config_helpers/tests/configs/protostr/test_rnn_group.protostr b/python/paddle/trainer_config_helpers/tests/configs/protostr/test_rnn_group.protostr index c1d39f77295892..3e9d28416ed506 100644 --- a/python/paddle/trainer_config_helpers/tests/configs/protostr/test_rnn_group.protostr +++ b/python/paddle/trainer_config_helpers/tests/configs/protostr/test_rnn_group.protostr @@ -307,10 +307,10 @@ layers { active_type: "tanh" inputs { input_layer_name: "__mixed_1__@__gru_group_0___recurrent_group" + input_parameter_name: "___gru_group_0__@__gru_group_0___recurrent_group.w0" } inputs { input_layer_name: "__gru_group_0__+delay1@__gru_group_0___recurrent_group" - input_parameter_name: "___gru_group_0__@__gru_group_0___recurrent_group.w1" } bias_parameter_name: "___gru_group_0__@__gru_group_0___recurrent_group.wbias" active_gate_type: "sigmoid" @@ -462,7 +462,7 @@ parameters { initial_smart: false } parameters { - name: "___gru_group_0__@__gru_group_0___recurrent_group.w1" + name: "___gru_group_0__@__gru_group_0___recurrent_group.w0" size: 30000 initial_mean: 0.0 initial_std: 0.1 From 781b85b5fc58aa45d163b0d9e78f8a757f2dbd25 Mon Sep 17 00:00:00 2001 From: Haonan Date: Thu, 1 Dec 2016 19:49:30 -0800 Subject: [PATCH 126/370] rotate_layer and flip_layer * added getMin and getMax for GpuMatrix * gru_step_layer parameter name --- paddle/gserver/layers/TransLayer.h | 2 +- paddle/gserver/tests/test_LayerGrad.cpp | 15 +++ paddle/math/CpuSparseMatrix.cpp | 2 +- paddle/math/CpuSparseMatrix.h | 2 +- paddle/math/Matrix.cpp | 58 ++++++++++- paddle/math/Matrix.h | 27 +++-- paddle/math/SparseMatrix.cpp | 2 +- paddle/math/SparseMatrix.h | 2 +- paddle/math/tests/test_SparseMatrix.cpp | 6 +- paddle/math/tests/test_matrixCompare.cpp | 17 +++- proto/ModelConfig.proto | 8 +- python/paddle/trainer/config_parser.py | 18 +++- python/paddle/trainer/recurrent_units.py | 10 +- .../paddle/trainer_config_helpers/layers.py | 99 +++++++++++++++++-- .../paddle/trainer_config_helpers/networks.py | 12 +-- .../tests/layers_test_config.py | 6 +- 16 files changed, 242 insertions(+), 44 deletions(-) mode change 100644 => 100755 python/paddle/trainer/recurrent_units.py mode change 100644 => 100755 python/paddle/trainer_config_helpers/layers.py mode change 100644 => 100755 python/paddle/trainer_config_helpers/networks.py diff --git a/paddle/gserver/layers/TransLayer.h b/paddle/gserver/layers/TransLayer.h index b43fa1ebfb0032..1d5a370b3414bf 100644 --- a/paddle/gserver/layers/TransLayer.h +++ b/paddle/gserver/layers/TransLayer.h @@ -20,7 +20,7 @@ limitations under the License. */ namespace paddle { /** - * A layer for transposition. + * A layer for transposing a minibatch matrix. * \f[ y = x^\mathrm{T} * \f] diff --git a/paddle/gserver/tests/test_LayerGrad.cpp b/paddle/gserver/tests/test_LayerGrad.cpp index 813a99d8cdae2e..f7a6c672de2016 100644 --- a/paddle/gserver/tests/test_LayerGrad.cpp +++ b/paddle/gserver/tests/test_LayerGrad.cpp @@ -1316,6 +1316,21 @@ TEST(Layer, ResizeLayer) { } } +TEST(Layer, RotateLayer) { + TestConfig config; + config.biasSize = 0; + config.layerConfig.set_type("rotate"); + const int INPUT_SIZE = 64; // height * width + config.layerConfig.set_size(INPUT_SIZE); + config.layerConfig.set_height(32); + config.inputDefs.push_back({INPUT_DATA, "layer_0", INPUT_SIZE, 0}); + config.layerConfig.add_inputs(); + + for (auto useGpu : {false, true}) { + testLayerGrad(config, "rotate", 100, false, useGpu); + } +} + TEST(Layer, NCELayer) { TestConfig config; size_t numClasses = 4; diff --git a/paddle/math/CpuSparseMatrix.cpp b/paddle/math/CpuSparseMatrix.cpp index 82a482f7014812..bf62229c03bb1d 100644 --- a/paddle/math/CpuSparseMatrix.cpp +++ b/paddle/math/CpuSparseMatrix.cpp @@ -372,7 +372,7 @@ MatrixPtr CpuSparseMatrix::subMatrix(size_t startRow, size_t numRows) { } /* mem MUST be alloced outside (memAlloc=false) */ -void CpuSparseMatrix::transpose(MatrixPtr matTrans, bool memAlloc) { +void CpuSparseMatrix::transpose(MatrixPtr& matTrans, bool memAlloc) { CHECK(!memAlloc); CpuSparseMatrix* mat = dynamic_cast(matTrans.get()); if (format_ == SPARSE_CSR) { diff --git a/paddle/math/CpuSparseMatrix.h b/paddle/math/CpuSparseMatrix.h index d3e8871cb5b320..860cad1047fc34 100644 --- a/paddle/math/CpuSparseMatrix.h +++ b/paddle/math/CpuSparseMatrix.h @@ -201,7 +201,7 @@ class CpuSparseMatrix : public Matrix { void zeroMem(); /// mem MUST be alloced outside (memAlloc=false) - void transpose(MatrixPtr matTrans, bool memAlloc); + void transpose(MatrixPtr& matTrans, bool memAlloc); void mul(const Matrix& A, const Matrix& B, real alpha, real beta); diff --git a/paddle/math/Matrix.cpp b/paddle/math/Matrix.cpp index 3ae237bc7de895..3c09f010bbf64c 100644 --- a/paddle/math/Matrix.cpp +++ b/paddle/math/Matrix.cpp @@ -274,6 +274,18 @@ real GpuMatrix::getSum() { return sum; } +real GpuMatrix::getMin() { + CHECK(isContiguous()); + auto vec = GpuVector(height_ * width_, data_); + return vec.getMin(); +} + +real GpuMatrix::getMax() { + CHECK(isContiguous()); + auto vec = GpuVector(height_ * width_, data_); + return vec.getMax(); +} + void GpuMatrix::accumulateColSum(Matrix& src) { CHECK_EQ(getWidth(), src.getWidth()); CHECK_EQ(getHeight(), (size_t)1); @@ -371,7 +383,7 @@ MatrixPtr GpuMatrix::getTranspose() { } } -void GpuMatrix::transpose(MatrixPtr matTrans, bool memAlloc) { +void GpuMatrix::transpose(MatrixPtr& matTrans, bool memAlloc) { if (memAlloc) { matTrans = std::make_shared(width_, height_); } else { @@ -385,13 +397,29 @@ void GpuMatrix::transpose(MatrixPtr matTrans, bool memAlloc) { hl_matrix_transpose(data, dataTrans, height_, width_, lda, ldc); } +void GpuMatrix::rotate(MatrixPtr& matRot, bool memAlloc, bool clockWise) { + if (memAlloc) { + matRot = std::make_shared(width_, height_); + } else { + CHECK(matRot != NULL); + } + + MatrixPtr cpuMat = std::make_shared(height_, width_); + cpuMat->copyFrom(*this); + + MatrixPtr cpuMatRot = std::make_shared(width_, height_); + cpuMat->rotate(cpuMatRot, false, clockWise); + + matRot->copyFrom(*cpuMatRot); +} + MatrixPtr GpuMatrix::getInverse() { MatrixPtr matInv; inverse(matInv, true); return matInv; } -void GpuMatrix::inverse(MatrixPtr matInv, bool memAlloc) { +void GpuMatrix::inverse(MatrixPtr& matInv, bool memAlloc) { CHECK_EQ(height_, width_); if (memAlloc) { @@ -1690,7 +1718,7 @@ MatrixPtr CpuMatrix::getTranspose() { } } -void CpuMatrix::transpose(MatrixPtr matTrans, bool memAlloc) { +void CpuMatrix::transpose(MatrixPtr& matTrans, bool memAlloc) { if (memAlloc) { matTrans = std::make_shared(width_, height_); } else { @@ -1708,13 +1736,35 @@ void CpuMatrix::transpose(MatrixPtr matTrans, bool memAlloc) { } } +void CpuMatrix::rotate(MatrixPtr& matRot, bool memAlloc, bool clockWise) { + if (memAlloc) { + matRot = std::make_shared(width_, height_); + } else { + CHECK(matRot != NULL); + } + real* dataRot = matRot->getData(); + real* data = getData(); + int lda = getStride(); + int ldc = matRot->getStride(); + + for (size_t i = 0; i < height_; i++) { + for (size_t j = 0; j < width_; j++) { + if (clockWise) { + dataRot[j * ldc + i] = data[(height_ - i - 1) * lda + j]; + } else { + dataRot[j * ldc + i] = data[i * lda + (width_ - j - 1)]; + } + } + } +} + MatrixPtr CpuMatrix::getInverse() { MatrixPtr matInv; inverse(matInv, true); return matInv; } -void CpuMatrix::inverse(MatrixPtr matInv, bool memAlloc) { +void CpuMatrix::inverse(MatrixPtr& matInv, bool memAlloc) { CHECK_EQ(height_, width_); if (memAlloc) { diff --git a/paddle/math/Matrix.h b/paddle/math/Matrix.h index 57c0c2fe40a95d..d123f827c91079 100644 --- a/paddle/math/Matrix.h +++ b/paddle/math/Matrix.h @@ -372,7 +372,17 @@ class Matrix : public BaseMatrix { * allocate matTrans' memory outside, then set memAlloc as false; * else set as true. */ - virtual void transpose(MatrixPtr matTrans, bool memAlloc) { + virtual void transpose(MatrixPtr& matTrans, bool memAlloc) { + LOG(FATAL) << "Not implemented"; + } + + /** + * @brief rotate clock-wise. + * + * allocate matTrans' memory outside, then set memAlloc as false; + * else set as true. + */ + virtual void rotate(MatrixPtr& matRot, bool memAlloc, bool clockWise) { LOG(FATAL) << "Not implemented"; } @@ -387,7 +397,7 @@ class Matrix : public BaseMatrix { * if allocate matInv's memory outside, then set memAlloc as false; * else set as true. */ - virtual void inverse(MatrixPtr matInv, bool memAlloc) { + virtual void inverse(MatrixPtr& matInv, bool memAlloc) { LOG(FATAL) << "Not implemented"; } @@ -1169,11 +1179,15 @@ class GpuMatrix : public Matrix { void accumulateColSum(Matrix& src); real getAbsSum(); + real getMin(); + real getMax(); + MatrixPtr getTranspose(); - void transpose(MatrixPtr matTrans, bool memAlloc); + void transpose(MatrixPtr& matTrans, bool memAlloc); + void rotate(MatrixPtr& matRot, bool memAlloc, bool clockWise); MatrixPtr getInverse(); - void inverse(MatrixPtr matInv, bool memAlloc); + void inverse(MatrixPtr& matInv, bool memAlloc); /// add b to each sample of this. void addBias(Matrix& b, real scale); @@ -1485,10 +1499,11 @@ class CpuMatrix : public Matrix { real getAbsSum(); MatrixPtr getTranspose(); - void transpose(MatrixPtr matTrans, bool memAlloc); + void transpose(MatrixPtr& matTrans, bool memAlloc); + void rotate(MatrixPtr& matRot, bool memAlloc, bool clockWise); MatrixPtr getInverse(); - void inverse(MatrixPtr matInv, bool memAlloc); + void inverse(MatrixPtr& matInv, bool memAlloc); void copyFrom(const Matrix& src); diff --git a/paddle/math/SparseMatrix.cpp b/paddle/math/SparseMatrix.cpp index 3bae6d373f240f..6370c77386688a 100644 --- a/paddle/math/SparseMatrix.cpp +++ b/paddle/math/SparseMatrix.cpp @@ -497,7 +497,7 @@ void GpuSparseMatrix::setRow(size_t row, SparseValueType GpuSparseMatrix::getValueType() const { return valueType_; } -void GpuSparseMatrix::transpose(MatrixPtr matTrans, bool memAlloc) { +void GpuSparseMatrix::transpose(MatrixPtr& matTrans, bool memAlloc) { CHECK_EQ(format_, SPARSE_CSC); int nnz = sMatrix_->nnz; if (memAlloc) { diff --git a/paddle/math/SparseMatrix.h b/paddle/math/SparseMatrix.h index 1d3801548e03a6..f6cd5df338965b 100644 --- a/paddle/math/SparseMatrix.h +++ b/paddle/math/SparseMatrix.h @@ -109,7 +109,7 @@ class GpuSparseMatrix : public Matrix { MatrixPtr getTranspose(); /// B = A' - void transpose(MatrixPtr matTrans, bool memAlloc); + void transpose(MatrixPtr& matTrans, bool memAlloc); void copyFrom(const Matrix& src); void copyFrom(const Matrix& src, hl_stream_t stream); diff --git a/paddle/math/tests/test_SparseMatrix.cpp b/paddle/math/tests/test_SparseMatrix.cpp index 9d3fbaef43d719..c0572dfdbf738a 100644 --- a/paddle/math/tests/test_SparseMatrix.cpp +++ b/paddle/math/tests/test_SparseMatrix.cpp @@ -248,11 +248,13 @@ TEST(Matrix, SparseMatrixTranspose) { /*dense matrix transpose*/ CpuMatrixPtr matC(new CpuMatrix(height, width)); matC->copyFrom(*matA); - CpuMatrixPtr matD(new CpuMatrix(width, height)); + MatrixPtr matD(new CpuMatrix(width, height)); matC->transpose(matD, false); + /*check result*/ checkSMatrixEqual2Dense( - std::dynamic_pointer_cast(matB), matD); + std::dynamic_pointer_cast(matB), + std::dynamic_pointer_cast(matD)); } } } diff --git a/paddle/math/tests/test_matrixCompare.cpp b/paddle/math/tests/test_matrixCompare.cpp index f0c49791d7e2a6..c062ca10809ac6 100644 --- a/paddle/math/tests/test_matrixCompare.cpp +++ b/paddle/math/tests/test_matrixCompare.cpp @@ -105,6 +105,21 @@ void testMatrixGetSum(int height, int width) { EXPECT_LE(fabs(cpuSum - gpuSum), err); } +void testMatrixGetMinMax(int height, int width) { + MatrixPtr cpuInput = std::make_shared(height, width); + MatrixPtr gpuInput = std::make_shared(height, width); + cpuInput->randomizeUniform(); + gpuInput->copyFrom(*cpuInput); + + real cpuMin = cpuInput->getMin(); + real gpuMin = gpuInput->getMin(); + real cpuMax = cpuInput->getMax(); + real gpuMax = gpuInput->getMax(); + + EXPECT_EQ(cpuMin, gpuMin); + EXPECT_EQ(cpuMax, gpuMax); +} + void testMatrixZeroAtOffset(int height, int width) { MatrixPtr cpuA = std::make_shared(height, width); MatrixPtr gpuA = std::make_shared(height, width); @@ -181,7 +196,7 @@ void testMatrixInverse(int height) { cpu->add(*outputCheck); gpu->copyFrom(*cpu); - cpu->inverse(cpuI, false); + cpu->inverse(cpuI, true); gpu->inverse(gpuI, false); TensorCheckErr(*cpuI, *gpuI); diff --git a/proto/ModelConfig.proto b/proto/ModelConfig.proto index 0456404832c301..be4634d5103c0f 100644 --- a/proto/ModelConfig.proto +++ b/proto/ModelConfig.proto @@ -427,14 +427,14 @@ message LayerConfig { // bias size optional uint32 bias_size = 48 [default = 0]; - // this parameter can be used as a user-defined parameter when necessary, + // this parameter can be used as a user-defined parameter when necessary, // without changing the proto file. - // e.g., when a new layer with a user-defined parameter is implemented, + // e.g., when a new layer with a user-defined parameter is implemented, // it can be used to pass that parameter, without modifying the proto file. // string type is used for flexibility: different types can be converted - // to string and reinterpreted in the user's own layer implementation. + // to string and reinterpreted in the user's own layer implementation. optional string user_arg = 49; - + // to indicate rectangle image data optional uint64 height = 50; optional uint64 width = 51; diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index 4fbf076ae98c4d..97744ed32ecbda 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -830,7 +830,6 @@ def __init__( channels, size_x, size_y=None, - img_width=None, start=None, stride=None, # 1 by defalut in protobuf stride_y=None, @@ -1834,6 +1833,7 @@ def __init__(self, name, inputs, ceil_mode=True, **xargs): pool_conf.channels) + @config_layer('spp') class SpatialPyramidPoolLayer(LayerBase): def __init__(self, name, inputs, **xargs): @@ -1927,8 +1927,8 @@ def __init__(self, image_conf = self.config.inputs[0].image_conf parse_image(self.inputs[0].image, input_layer.name, image_conf) - # Only pass the width and height of input to batch_norm layer - # when either of it is non-zero. + # Only pass the width and height of input to batch_norm layer + # when either of it is non-zero. if input_layer.width != 0 or input_layer.height != 0: self.set_cnn_layer(name, image_conf.img_size_y, image_conf.img_size, image_conf.channels, False) @@ -1968,6 +1968,18 @@ def __init__(self, name, size, inputs, **xargs): 'ResizeLayer must have one and only one input') +@config_layer('rotate') +class RotateLayer(LayerBase): + def __init__(self, name, inputs, height, device=None): + super(RotateLayer, self).__init__( + name, 'rotate', 0, inputs=inputs, device=device) + config_assert( + len(self.inputs) == 1, + 'RotateLayer must have one and only one input') + self.config.height = height + self.set_layer_size(self.get_input_layer(0).size) + + @config_layer('blockexpand') class BlockExpandLayer(LayerBase): def __init__(self, name, inputs, **xargs): diff --git a/python/paddle/trainer/recurrent_units.py b/python/paddle/trainer/recurrent_units.py old mode 100644 new mode 100755 index ff7e8932dcad79..ef92107a1093d2 --- a/python/paddle/trainer/recurrent_units.py +++ b/python/paddle/trainer/recurrent_units.py @@ -15,10 +15,10 @@ # recurrent_units.py # Version 2.0 # -# Some recurrent units can be used in recurrent layer group, +# Some recurrent units can be used in recurrent layer group, # to use these units, import this module in your config_file: -# import trainer.recurrent_units -# +# import trainer.recurrent_units +# # The modules in this file are DEPRECATED. # If you would like to use lstm/gru # please use the functions defined in paddle.trainer_config_helpers. @@ -29,7 +29,7 @@ # long short term memory, can be used in recurrent machine # *inputs* must be a list of Projections, for example: # inputs = [FullMatrixProjection("input_layer_name")], -# *para_prefix* defines parameter names, if the *para_prefix* of +# *para_prefix* defines parameter names, if the *para_prefix* of # two LstmRecurrentUnit is same, they share same parameters # *out_memory* can be defined outside if it's used outside def LstmRecurrentUnit(name, @@ -197,7 +197,7 @@ def LstmRecurrentLayerGroup(name, # gated recurrent unit, can be used in recurrent machine # *inputs* should be a list of Projections, for example: # inputs = [FullMatrixProjection("input_layer_name")], -# *para_prefix* defines parameter names, if the *para_prefix* of +# *para_prefix* defines parameter names, if the *para_prefix* of # two GatedRecurrentUnit is same, they share same parameters # *out_memory* can be defined outside if it's used outside diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py old mode 100644 new mode 100755 index f0b5d7c3b4f26a..c502885cf9efbd --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -70,6 +70,8 @@ 'interpolation_layer', 'bilinear_interp_layer', 'trans_layer', + 'rotate_layer', + 'flip_layer', 'sum_to_one_norm_layer', 'get_output_layer', 'LayerType', @@ -154,6 +156,7 @@ class LayerType(object): POWER_LAYER = 'power' SCALING_LAYER = 'scaling' TRANS_LAYER = 'trans' + ROTATE_LAYER = 'rotate' OUT_PROD_LAYER = 'out_prod' FEATURE_MAP_EXPAND_LAYER = 'featmap_expand' @@ -1642,7 +1645,7 @@ def scaling_layer(input, weight, name=None, layer_attr=None): @layer_support() def trans_layer(input, name=None, layer_attr=None): """ - A layer for transposition. + A layer for transposing a minibatch matrix. .. math:: y = x^\mathrm{T} @@ -1673,6 +1676,87 @@ def trans_layer(input, name=None, layer_attr=None): name, LayerType.TRANS_LAYER, parents=[input], size=input.size) +@wrap_name_default() +@layer_support() +def rotate_layer(input, height, name=None, layer_attr=None): + """ + A layer for rotation (clock-wise), usually used when the input sample + is some image or map. + + .. math:: + y(j,i) = x(M-i-1,j) + + where :math:`x` is (M x N) input, and :math:`y` is (N x M) output. + + The example usage is: + + .. code-block:: python + + rot = rotate_layer(input=layer, + height=100) + + :param input: Input layer. + :type input: LayerOutput + :param height: The height of the sample matrix + :type height: int + :param name: Layer name. + :type name: basestring + :param layer_attr: extra layer attributes. + :type layer_attr: ExtraLayerAttribute. + :return: LayerOutput object. + :rtype: LayerOutput + """ + assert isinstance(input, LayerOutput) + l = Layer(name=name, + height=height, + type=LayerType.ROTATE_LAYER, + inputs=[input.name], + **ExtraLayerAttribute.to_kwargs(layer_attr)) + return LayerOutput(name=name, + layer_type=LayerType.ROTATE_LAYER, + parents=[input], + size=l.config.size) + + +@wrap_name_default() +@layer_support() +def flip_layer(input, height, name=None, layer_attr=None): + """ + A layer for flipping the matrix w.r.t the matrix center. + It's essentially rotating the matrix twice. + Used for input as image or map. + + .. math:: + y(i,j) = x(M-i-1, N-j-1) + + where :math:`x` is (M x N) input, and :math:`y` is (M x N) output. + + The example usage is: + + .. code-block:: python + + flip = flip_layer(input=layer, + height=100) + + :param input: Input layer. + :type input: LayerOutput + :param height: The height of the sample matrix + :type height: int + :param name: Layer name. + :type name: basestring + :param layer_attr: extra layer attributes. + :type layer_attr: ExtraLayerAttribute. + :return: LayerOutput object. + :rtype: LayerOutput + """ + assert isinstance(input, LayerOutput) + return rotate_layer(input=rotate_layer(input=input, + height=height), + height=height, + name=name, + layer_attr=layer_attr) + + @wrap_name_default() @layer_support() def cos_sim(a, b, scale=1, size=1, name=None, layer_attr=None): @@ -1826,14 +1910,14 @@ def img_conv_layer(input, trans=False, layer_type=None): """ - Convolution layer for image. Paddle can support both square and non-square + Convolution layer for image. Paddle can support both square and non-square input currently. The details of convolution layer, please refer UFLDL's `convolution `_ . - Convolution Transpose (deconv) layer for image. Paddle can support both square + Convolution Transpose (deconv) layer for image. Paddle can support both square and non-square input currently. The details of convolution transpose layer, @@ -1892,7 +1976,7 @@ def img_conv_layer(input, :param trans: true if it is a convTransLayer, false if it is a convLayer :type trans: bool :param layer_type: specify the layer_type, default is None. If trans=True, - layer_type has to be "exconvt", otherwise layer_type + layer_type has to be "exconvt", otherwise layer_type has to be either "exconv" or "cudnn_conv" :type layer_type: String :return: LayerOutput object. @@ -3619,9 +3703,9 @@ def pad_layer(input, input data and 3 zeros after the input data in channel dimension. pad_h means padding zeros in height dimension. pad_w means padding zeros in width dimension. - + For example, - + .. code-block:: input(2,2,2,3) = [ @@ -3630,7 +3714,7 @@ def pad_layer(input, [ [[4,3,1], [1,8,7]], [[3,8,9], [2,3,5]] ] ] - + pad_c=[1,1], pad_h=[0,0], pad_w=[0,0] output(2,4,2,3) = [ [ [[0,0,0], [0,0,0]], @@ -4739,6 +4823,7 @@ def cross_entropy_with_selfnorm(input, layer_attr=None): """ A loss layer for multi class entropy with selfnorm. + Input should be a vector of positive numbers, without normalization. .. code-block:: python diff --git a/python/paddle/trainer_config_helpers/networks.py b/python/paddle/trainer_config_helpers/networks.py old mode 100644 new mode 100755 index d0cbe3891f60f4..cadde11ff81658 --- a/python/paddle/trainer_config_helpers/networks.py +++ b/python/paddle/trainer_config_helpers/networks.py @@ -957,22 +957,22 @@ def simple_gru(input, use one complete layer to implement rnn (including simple rnn, gru and lstm) with multiple time steps, such as recurrent_layer, lstmemory, grumemory. But, the multiplication operation :math:`W x_t` is not computed in these layers. - See details in their interfaces in layers.py. + See details in their interfaces in layers.py. The other implementation is to use an recurrent group which can ensemble a series of layers to compute rnn step by step. This way is flexible for attenion mechanism or other complex connections. - gru_step_layer: only compute rnn by one step. It needs an memory as input and can be used in recurrent group. - - gru_unit: a wrapper of gru_step_layer with memory. + - gru_unit: a wrapper of gru_step_layer with memory. - gru_group: a GRU cell implemented by a combination of multiple layers in recurrent group. - But :math:`W x_t` is not done in group. + But :math:`W x_t` is not done in group. - gru_memory: a GRU cell implemented by one layer, which does same calculation - with gru_group and is faster than gru_group. - - simple_gru: a complete GRU implementation inlcuding :math:`W x_t` and + with gru_group and is faster than gru_group. + - simple_gru: a complete GRU implementation inlcuding :math:`W x_t` and gru_group. :math:`W` contains :math:`W_r`, :math:`W_z` and :math:`W`, see - formula in grumemory. + formula in grumemory. The computational speed is that, grumemory is relatively better than gru_group, and gru_group is relatively better than simple_gru. diff --git a/python/paddle/trainer_config_helpers/tests/layers_test_config.py b/python/paddle/trainer_config_helpers/tests/layers_test_config.py index ae275735aa2b85..10b7358d929b75 100644 --- a/python/paddle/trainer_config_helpers/tests/layers_test_config.py +++ b/python/paddle/trainer_config_helpers/tests/layers_test_config.py @@ -39,6 +39,10 @@ assert z1.size > 0 y2 = fc_layer(input=y, size=15) +z2 = rotate_layer(input=y2, + height=5) +z3 = flip_layer(input=y2, + height=3) cos1 = cos_sim(a=x1, b=y1) cos3 = cos_sim(a=x1, b=y2, size=3) @@ -46,7 +50,7 @@ linear_comb = linear_comb_layer(weights=x1, vectors=y2, size=3) out = fc_layer( - input=[cos1, cos3, linear_comb, z, z1], + input=[cos1, cos3, linear_comb, z, z1, z2, z3], size=num_classes, act=SoftmaxActivation()) From f5995300c59c33c134ee2bd428174d38d4b8af30 Mon Sep 17 00:00:00 2001 From: Haonan Date: Thu, 26 Jan 2017 12:49:27 -0800 Subject: [PATCH 127/370] rotate layer cpp files --- paddle/gserver/layers/RotateLayer.cpp | 94 +++++++++++++++++++++++++++ paddle/gserver/layers/RotateLayer.h | 49 ++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 paddle/gserver/layers/RotateLayer.cpp create mode 100644 paddle/gserver/layers/RotateLayer.h diff --git a/paddle/gserver/layers/RotateLayer.cpp b/paddle/gserver/layers/RotateLayer.cpp new file mode 100644 index 00000000000000..10195193316eae --- /dev/null +++ b/paddle/gserver/layers/RotateLayer.cpp @@ -0,0 +1,94 @@ +/* Copyright (c) 2016 Baidu, Inc. 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 "RotateLayer.h" + +namespace paddle { + +REGISTER_LAYER(rotate, RotateLayer); + +bool RotateLayer::init(const LayerMap& layerMap, + const ParameterMap& parameterMap) { + Layer::init(layerMap, parameterMap); + + CHECK_EQ(inputLayers_.size(), 1UL); + sampleHeight_ = config_.height(); + return true; +} + +void RotateLayer::forward(PassType passType) { + Layer::forward(passType); + + MatrixPtr input = getInputValue(0); + batchSize_ = input->getHeight(); + sampleSize_ = input->getWidth(); + sampleWidth_ = sampleSize_ / sampleHeight_; + CHECK_EQ(sampleSize_ % sampleHeight_, 0); + + resizeOutput(batchSize_, sampleSize_); + + MatrixPtr outV = getOutputValue(); + + for (int b = 0; b < batchSize_; b ++) { + MatrixPtr inputSample + = Matrix::create(input->getData() + b * sampleSize_, + sampleHeight_, + sampleWidth_, + false, + useGpu_); + MatrixPtr outputSample + = Matrix::create(outV->getData() + b * sampleSize_, + sampleWidth_, + sampleHeight_, + false, + useGpu_); + inputSample->rotate(outputSample, false, true); + } + + if (getInputGrad(0)) { + zeroGrad(); + } +} + +void RotateLayer::backward(const UpdateCallback& callback) { + (void)callback; + + MatrixPtr outputGrad = getOutputGrad(); + if (outputGrad == NULL) { + return; + } + // the grad should be rotated in the reverse direction + MatrixPtr preGrad = getInputGrad(0); + + for (int b = 0; b < batchSize_; b ++) { + MatrixPtr inputSampleGrad + = Matrix::create(preGrad->getData() + b * sampleSize_, + sampleHeight_, + sampleWidth_, + false, + useGpu_); + MatrixPtr outputSampleGrad + = Matrix::create(outputGrad->getData() + b * sampleSize_, + sampleWidth_, + sampleHeight_, + false, + useGpu_); + MatrixPtr tmpGrad + = Matrix::create(sampleHeight_, sampleWidth_, false, useGpu_); + outputSampleGrad->rotate(tmpGrad, false, false); + inputSampleGrad->add(*tmpGrad); + } +} + +} // namespace paddle diff --git a/paddle/gserver/layers/RotateLayer.h b/paddle/gserver/layers/RotateLayer.h new file mode 100644 index 00000000000000..c8eca7c5066b18 --- /dev/null +++ b/paddle/gserver/layers/RotateLayer.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2016 Baidu, Inc. 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 "Layer.h" +#include "paddle/math/Matrix.h" + +namespace paddle { +/** + * A layer for rotating an input sample (assume it's a matrix) + * The rotation is in clock-wise + * \f[ + * y(j,i) = x(M-i-1,j) + * \f] + * where \f$x\f$ is (M x N) input, and \f$y\f$ is (N x M) output. + * + * The config file api is rotate_layer + * +*/ + +class RotateLayer : public Layer { +public: + explicit RotateLayer(const LayerConfig& config) : Layer(config) {} + + bool init(const LayerMap& layerMap, const ParameterMap& parameterMap); + + void forward(PassType passType); + void backward(const UpdateCallback& callback = nullptr); + +private: + int batchSize_; + int sampleSize_; + int sampleHeight_; + int sampleWidth_; +}; + +} // namespace paddle From 55eb2fcffa5081967e61eeb62ada4c994492e634 Mon Sep 17 00:00:00 2001 From: Haonan Date: Thu, 26 Jan 2017 16:12:48 -0800 Subject: [PATCH 128/370] format correction --- paddle/gserver/layers/RotateLayer.cpp | 54 +++++++++---------- python/paddle/trainer/config_parser.py | 1 - .../paddle/trainer_config_helpers/layers.py | 31 ++++++----- .../tests/layers_test_config.py | 6 +-- 4 files changed, 45 insertions(+), 47 deletions(-) diff --git a/paddle/gserver/layers/RotateLayer.cpp b/paddle/gserver/layers/RotateLayer.cpp index 10195193316eae..269ad43b3180bd 100644 --- a/paddle/gserver/layers/RotateLayer.cpp +++ b/paddle/gserver/layers/RotateLayer.cpp @@ -40,19 +40,17 @@ void RotateLayer::forward(PassType passType) { MatrixPtr outV = getOutputValue(); - for (int b = 0; b < batchSize_; b ++) { - MatrixPtr inputSample - = Matrix::create(input->getData() + b * sampleSize_, - sampleHeight_, - sampleWidth_, - false, - useGpu_); - MatrixPtr outputSample - = Matrix::create(outV->getData() + b * sampleSize_, - sampleWidth_, - sampleHeight_, - false, - useGpu_); + for (int b = 0; b < batchSize_; b++) { + MatrixPtr inputSample = Matrix::create(input->getData() + b * sampleSize_, + sampleHeight_, + sampleWidth_, + false, + useGpu_); + MatrixPtr outputSample = Matrix::create(outV->getData() + b * sampleSize_, + sampleWidth_, + sampleHeight_, + false, + useGpu_); inputSample->rotate(outputSample, false, true); } @@ -71,21 +69,21 @@ void RotateLayer::backward(const UpdateCallback& callback) { // the grad should be rotated in the reverse direction MatrixPtr preGrad = getInputGrad(0); - for (int b = 0; b < batchSize_; b ++) { - MatrixPtr inputSampleGrad - = Matrix::create(preGrad->getData() + b * sampleSize_, - sampleHeight_, - sampleWidth_, - false, - useGpu_); - MatrixPtr outputSampleGrad - = Matrix::create(outputGrad->getData() + b * sampleSize_, - sampleWidth_, - sampleHeight_, - false, - useGpu_); - MatrixPtr tmpGrad - = Matrix::create(sampleHeight_, sampleWidth_, false, useGpu_); + for (int b = 0; b < batchSize_; b++) { + MatrixPtr inputSampleGrad = + Matrix::create(preGrad->getData() + b * sampleSize_, + sampleHeight_, + sampleWidth_, + false, + useGpu_); + MatrixPtr outputSampleGrad = + Matrix::create(outputGrad->getData() + b * sampleSize_, + sampleWidth_, + sampleHeight_, + false, + useGpu_); + MatrixPtr tmpGrad = + Matrix::create(sampleHeight_, sampleWidth_, false, useGpu_); outputSampleGrad->rotate(tmpGrad, false, false); inputSampleGrad->add(*tmpGrad); } diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index 97744ed32ecbda..62efe5fca0caca 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -1833,7 +1833,6 @@ def __init__(self, name, inputs, ceil_mode=True, **xargs): pool_conf.channels) - @config_layer('spp') class SpatialPyramidPoolLayer(LayerBase): def __init__(self, name, inputs, **xargs): diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index c502885cf9efbd..c506977ca4e405 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -1707,15 +1707,17 @@ def rotate_layer(input, height, name=None, layer_attr=None): :rtype: LayerOutput """ assert isinstance(input, LayerOutput) - l = Layer(name=name, - height=height, - type=LayerType.ROTATE_LAYER, - inputs=[input.name], - **ExtraLayerAttribute.to_kwargs(layer_attr)) - return LayerOutput(name=name, - layer_type=LayerType.ROTATE_LAYER, - parents=[input], - size=l.config.size) + l = Layer( + name=name, + height=height, + type=LayerType.ROTATE_LAYER, + inputs=[input.name], + **ExtraLayerAttribute.to_kwargs(layer_attr)) + return LayerOutput( + name=name, + layer_type=LayerType.ROTATE_LAYER, + parents=[input], + size=l.config.size) @wrap_name_default() @@ -1750,11 +1752,12 @@ def flip_layer(input, height, name=None, layer_attr=None): :rtype: LayerOutput """ assert isinstance(input, LayerOutput) - return rotate_layer(input=rotate_layer(input=input, - height=height), - height=height, - name=name, - layer_attr=layer_attr) + return rotate_layer( + input=rotate_layer( + input=input, height=height), + height=height, + name=name, + layer_attr=layer_attr) @wrap_name_default() diff --git a/python/paddle/trainer_config_helpers/tests/layers_test_config.py b/python/paddle/trainer_config_helpers/tests/layers_test_config.py index 10b7358d929b75..3d417a00601d56 100644 --- a/python/paddle/trainer_config_helpers/tests/layers_test_config.py +++ b/python/paddle/trainer_config_helpers/tests/layers_test_config.py @@ -39,10 +39,8 @@ assert z1.size > 0 y2 = fc_layer(input=y, size=15) -z2 = rotate_layer(input=y2, - height=5) -z3 = flip_layer(input=y2, - height=3) +z2 = rotate_layer(input=y2, height=5) +z3 = flip_layer(input=y2, height=3) cos1 = cos_sim(a=x1, b=y1) cos3 = cos_sim(a=x1, b=y2, size=3) From b4c1d17580777fcc5118efa26b230432c0221b6a Mon Sep 17 00:00:00 2001 From: Haonan Date: Thu, 26 Jan 2017 17:52:47 -0800 Subject: [PATCH 129/370] remove flip_layer --- .../paddle/trainer_config_helpers/layers.py | 41 ------------------- .../tests/layers_test_config.py | 3 +- 2 files changed, 1 insertion(+), 43 deletions(-) diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index c506977ca4e405..19f7ec3186596f 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -71,7 +71,6 @@ 'bilinear_interp_layer', 'trans_layer', 'rotate_layer', - 'flip_layer', 'sum_to_one_norm_layer', 'get_output_layer', 'LayerType', @@ -1720,46 +1719,6 @@ def rotate_layer(input, height, name=None, layer_attr=None): size=l.config.size) -@wrap_name_default() -@layer_support() -def flip_layer(input, height, name=None, layer_attr=None): - """ - A layer for flipping the matrix w.r.t the matrix center. - It's essentially rotating the matrix twice. - Used for input as image or map. - - .. math:: - y(i,j) = x(M-i-1, N-j-1) - - where :math:`x` is (M x N) input, and :math:`y` is (M x N) output. - - The example usage is: - - .. code-block:: python - - flip = flip_layer(input=layer, - height=100) - - :param input: Input layer. - :type input: LayerOutput - :param height: The height of the sample matrix - :type height: int - :param name: Layer name. - :type name: basestring - :param layer_attr: extra layer attributes. - :type layer_attr: ExtraLayerAttribute. - :return: LayerOutput object. - :rtype: LayerOutput - """ - assert isinstance(input, LayerOutput) - return rotate_layer( - input=rotate_layer( - input=input, height=height), - height=height, - name=name, - layer_attr=layer_attr) - - @wrap_name_default() @layer_support() def cos_sim(a, b, scale=1, size=1, name=None, layer_attr=None): diff --git a/python/paddle/trainer_config_helpers/tests/layers_test_config.py b/python/paddle/trainer_config_helpers/tests/layers_test_config.py index 3d417a00601d56..1964e6f113e642 100644 --- a/python/paddle/trainer_config_helpers/tests/layers_test_config.py +++ b/python/paddle/trainer_config_helpers/tests/layers_test_config.py @@ -40,7 +40,6 @@ y2 = fc_layer(input=y, size=15) z2 = rotate_layer(input=y2, height=5) -z3 = flip_layer(input=y2, height=3) cos1 = cos_sim(a=x1, b=y1) cos3 = cos_sim(a=x1, b=y2, size=3) @@ -48,7 +47,7 @@ linear_comb = linear_comb_layer(weights=x1, vectors=y2, size=3) out = fc_layer( - input=[cos1, cos3, linear_comb, z, z1, z2, z3], + input=[cos1, cos3, linear_comb, z, z1, z2], size=num_classes, act=SoftmaxActivation()) From 2558c3f15a9d4bd340d0d50492a185231bb2627a Mon Sep 17 00:00:00 2001 From: Haonan Date: Wed, 1 Feb 2017 14:37:54 -0800 Subject: [PATCH 130/370] revisions according to reviews --- paddle/cuda/include/hl_matrix.h | 12 ++++ paddle/cuda/include/stub/hl_matrix_stub.h | 4 ++ paddle/cuda/src/hl_cuda_matrix.cu | 25 ++++++++ paddle/gserver/layers/RotateLayer.cpp | 77 ++++++++++++----------- paddle/gserver/layers/RotateLayer.h | 16 ++--- paddle/gserver/tests/test_LayerGrad.cpp | 7 ++- paddle/math/Matrix.cpp | 24 +++---- paddle/math/Matrix.h | 14 ++++- paddle/math/tests/test_matrixCompare.cpp | 21 ++++++- 9 files changed, 142 insertions(+), 58 deletions(-) diff --git a/paddle/cuda/include/hl_matrix.h b/paddle/cuda/include/hl_matrix.h index abd5eb3a0cf338..40828dd5cc76f4 100644 --- a/paddle/cuda/include/hl_matrix.h +++ b/paddle/cuda/include/hl_matrix.h @@ -267,4 +267,16 @@ extern void hl_matrix_collect_shared_bias(real* B_d, const int dimN, real scale); +/** + * @brief Matrix rotation in 90 degrees + * + * @param[in] mat input matrix (M x N). + * @param[out] matRot output matrix (N x M). + * @param[in] dimM input matrix height. + * @param[in] dimN input matrix width. + * @param[in] clockWise rotation direction + */ +extern void hl_matrix_rotate( + real* mat, real* matRot, int dimM, int dimN, bool clockWise); + #endif /* HL_MATRIX_H_ */ diff --git a/paddle/cuda/include/stub/hl_matrix_stub.h b/paddle/cuda/include/stub/hl_matrix_stub.h index 0b669f6735cb97..1309c5974fc3e1 100644 --- a/paddle/cuda/include/stub/hl_matrix_stub.h +++ b/paddle/cuda/include/stub/hl_matrix_stub.h @@ -106,4 +106,8 @@ inline void hl_matrix_collect_shared_bias(real* B_d, const int dimM, const int dimN, real scale) {} + +inline void hl_matrix_rotate( + real* mat, real* matRot, int dimM, int dimN, bool clockWise); + #endif // HL_MATRIX_STUB_H_ diff --git a/paddle/cuda/src/hl_cuda_matrix.cu b/paddle/cuda/src/hl_cuda_matrix.cu index 2b4c6f7c39cff7..cd23bd31057c5c 100644 --- a/paddle/cuda/src/hl_cuda_matrix.cu +++ b/paddle/cuda/src/hl_cuda_matrix.cu @@ -840,3 +840,28 @@ void hl_matrix_collect_shared_bias(real* B_d, (B_d, A_d, channel, dimM, dimN, dim, limit, scale); CHECK_SYNC("hl_matrix_collect_shared_bias failed"); } + +__global__ void keMatrixRotate(real* mat, real* matRot, + int dimM, int dimN, bool clockWise) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < dimM * dimN) { + int i = idx / dimN; + int j = idx % dimN; + if (clockWise) { + matRot[j * dimM + i] = mat[(dimM - i - 1) * dimN + j]; + } else { + matRot[j * dimM + i] = mat[i * dimN + (dimN - j - 1)]; + } + } +} + +void hl_matrix_rotate(real *mat, real* matRot, + int dimM, int dimN, bool clockWise) { + CHECK_NOTNULL(mat); + CHECK_NOTNULL(matRot); + const int threads = 512; + const int blocks = DIVUP(dimM * dimN, threads); + keMatrixRotate<<< blocks, threads, 0, STREAM_DEFAULT >>> + (mat, matRot, dimM, dimN, clockWise); + CHECK_SYNC("hl_matrix_rotate failed"); +} diff --git a/paddle/gserver/layers/RotateLayer.cpp b/paddle/gserver/layers/RotateLayer.cpp index 269ad43b3180bd..1cdd8366d5ddff 100644 --- a/paddle/gserver/layers/RotateLayer.cpp +++ b/paddle/gserver/layers/RotateLayer.cpp @@ -23,7 +23,8 @@ bool RotateLayer::init(const LayerMap& layerMap, Layer::init(layerMap, parameterMap); CHECK_EQ(inputLayers_.size(), 1UL); - sampleHeight_ = config_.height(); + height_ = config_.height(); + width_ = config_.width(); return true; } @@ -32,26 +33,31 @@ void RotateLayer::forward(PassType passType) { MatrixPtr input = getInputValue(0); batchSize_ = input->getHeight(); - sampleSize_ = input->getWidth(); - sampleWidth_ = sampleSize_ / sampleHeight_; - CHECK_EQ(sampleSize_ % sampleHeight_, 0); + size_ = input->getWidth(); + CHECK_GE(size_, height_ * width_); + CHECK_EQ(size_ % (height_ * width_), 0) + << "The input's depth should be an int"; + channels_ = size_ / (height_ * width_); - resizeOutput(batchSize_, sampleSize_); + resizeOutput(batchSize_, size_); MatrixPtr outV = getOutputValue(); - - for (int b = 0; b < batchSize_; b++) { - MatrixPtr inputSample = Matrix::create(input->getData() + b * sampleSize_, - sampleHeight_, - sampleWidth_, - false, - useGpu_); - MatrixPtr outputSample = Matrix::create(outV->getData() + b * sampleSize_, - sampleWidth_, - sampleHeight_, - false, - useGpu_); - inputSample->rotate(outputSample, false, true); + for (int b = 0; b < batchSize_; b++) { // for each input feat map + for (int c = 0; c < channels_; c++) { // for each feat channel + MatrixPtr inputSample = + Matrix::create(input->getData() + b * size_ + c * height_ * width_, + height_, + width_, + false, + useGpu_); + MatrixPtr outputSample = + Matrix::create(outV->getData() + b * size_ + c * height_ * width_, + width_, + height_, + false, + useGpu_); + inputSample->rotate(outputSample, false, true /* clock-wise */); + } } if (getInputGrad(0)) { @@ -69,23 +75,24 @@ void RotateLayer::backward(const UpdateCallback& callback) { // the grad should be rotated in the reverse direction MatrixPtr preGrad = getInputGrad(0); - for (int b = 0; b < batchSize_; b++) { - MatrixPtr inputSampleGrad = - Matrix::create(preGrad->getData() + b * sampleSize_, - sampleHeight_, - sampleWidth_, - false, - useGpu_); - MatrixPtr outputSampleGrad = - Matrix::create(outputGrad->getData() + b * sampleSize_, - sampleWidth_, - sampleHeight_, - false, - useGpu_); - MatrixPtr tmpGrad = - Matrix::create(sampleHeight_, sampleWidth_, false, useGpu_); - outputSampleGrad->rotate(tmpGrad, false, false); - inputSampleGrad->add(*tmpGrad); + for (int b = 0; b < batchSize_; b++) { // for each input feat map + for (int c = 0; c < channels_; c++) { // for each feat channel + MatrixPtr inputSampleGrad = + Matrix::create(preGrad->getData() + b * size_ + c * height_ * width_, + height_, + width_, + false, + useGpu_); + MatrixPtr outputSampleGrad = Matrix::create( + outputGrad->getData() + b * size_ + c * height_ * width_, + width_, + height_, + false, + useGpu_); + MatrixPtr tmpGrad = nullptr; + outputSampleGrad->rotate(tmpGrad, true, false /* anti clock-wise */); + inputSampleGrad->add(*tmpGrad); + } } } diff --git a/paddle/gserver/layers/RotateLayer.h b/paddle/gserver/layers/RotateLayer.h index c8eca7c5066b18..a6f565a7e5dcfa 100644 --- a/paddle/gserver/layers/RotateLayer.h +++ b/paddle/gserver/layers/RotateLayer.h @@ -19,12 +19,13 @@ limitations under the License. */ namespace paddle { /** - * A layer for rotating an input sample (assume it's a matrix) - * The rotation is in clock-wise + * A layer for rotating a multi-channel feature map (M x N x C) in the spatial + * domain + * The rotation is 90 degrees in clock-wise * \f[ - * y(j,i) = x(M-i-1,j) + * y(j,i,:) = x(M-i-1,j,:) * \f] - * where \f$x\f$ is (M x N) input, and \f$y\f$ is (N x M) output. + * where \f$x\f$ is (M x N x C) input, and \f$y\f$ is (N x M x C) output. * * The config file api is rotate_layer * @@ -41,9 +42,10 @@ class RotateLayer : public Layer { private: int batchSize_; - int sampleSize_; - int sampleHeight_; - int sampleWidth_; + int size_; + int height_; + int width_; + int channels_; }; } // namespace paddle diff --git a/paddle/gserver/tests/test_LayerGrad.cpp b/paddle/gserver/tests/test_LayerGrad.cpp index f7a6c672de2016..685d2ca542b242 100644 --- a/paddle/gserver/tests/test_LayerGrad.cpp +++ b/paddle/gserver/tests/test_LayerGrad.cpp @@ -1320,9 +1320,12 @@ TEST(Layer, RotateLayer) { TestConfig config; config.biasSize = 0; config.layerConfig.set_type("rotate"); - const int INPUT_SIZE = 64; // height * width + const int INPUT_SIZE = 64; // height * width * depth + const int HEIGHT = 8; + const int WIDTH = 4; config.layerConfig.set_size(INPUT_SIZE); - config.layerConfig.set_height(32); + config.layerConfig.set_height(HEIGHT); + config.layerConfig.set_width(WIDTH); config.inputDefs.push_back({INPUT_DATA, "layer_0", INPUT_SIZE, 0}); config.layerConfig.add_inputs(); diff --git a/paddle/math/Matrix.cpp b/paddle/math/Matrix.cpp index 3c09f010bbf64c..a8b53e2105b053 100644 --- a/paddle/math/Matrix.cpp +++ b/paddle/math/Matrix.cpp @@ -388,6 +388,8 @@ void GpuMatrix::transpose(MatrixPtr& matTrans, bool memAlloc) { matTrans = std::make_shared(width_, height_); } else { CHECK(matTrans != NULL); + CHECK_EQ(matTrans->getHeight(), width_); + CHECK_EQ(matTrans->getWidth(), height_); } real* dataTrans = matTrans->getData(); real* data = getData(); @@ -402,15 +404,13 @@ void GpuMatrix::rotate(MatrixPtr& matRot, bool memAlloc, bool clockWise) { matRot = std::make_shared(width_, height_); } else { CHECK(matRot != NULL); + CHECK_EQ(matRot->getHeight(), width_); + CHECK_EQ(matRot->getWidth(), height_); } - MatrixPtr cpuMat = std::make_shared(height_, width_); - cpuMat->copyFrom(*this); - - MatrixPtr cpuMatRot = std::make_shared(width_, height_); - cpuMat->rotate(cpuMatRot, false, clockWise); - - matRot->copyFrom(*cpuMatRot); + real* dataRot = matRot->getData(); + real* data = getData(); + hl_matrix_rotate(data, dataRot, height_, width_, clockWise); } MatrixPtr GpuMatrix::getInverse() { @@ -1723,6 +1723,8 @@ void CpuMatrix::transpose(MatrixPtr& matTrans, bool memAlloc) { matTrans = std::make_shared(width_, height_); } else { CHECK(matTrans != NULL); + CHECK_EQ(matTrans->getHeight(), width_); + CHECK_EQ(matTrans->getWidth(), height_); } real* dataTrans = matTrans->getData(); real* data = getData(); @@ -1741,18 +1743,18 @@ void CpuMatrix::rotate(MatrixPtr& matRot, bool memAlloc, bool clockWise) { matRot = std::make_shared(width_, height_); } else { CHECK(matRot != NULL); + CHECK_EQ(matRot->getHeight(), width_); + CHECK_EQ(matRot->getWidth(), height_); } real* dataRot = matRot->getData(); real* data = getData(); - int lda = getStride(); - int ldc = matRot->getStride(); for (size_t i = 0; i < height_; i++) { for (size_t j = 0; j < width_; j++) { if (clockWise) { - dataRot[j * ldc + i] = data[(height_ - i - 1) * lda + j]; + dataRot[j * height_ + i] = data[(height_ - i - 1) * width_ + j]; } else { - dataRot[j * ldc + i] = data[i * lda + (width_ - j - 1)]; + dataRot[j * height_ + i] = data[i * width_ + (width_ - j - 1)]; } } } diff --git a/paddle/math/Matrix.h b/paddle/math/Matrix.h index d123f827c91079..c92c0a272d5a72 100644 --- a/paddle/math/Matrix.h +++ b/paddle/math/Matrix.h @@ -377,9 +377,19 @@ class Matrix : public BaseMatrix { } /** - * @brief rotate clock-wise. + * @brief rotate 90 degrees in clock-wise if clockWise=true; + * otherwise rotate in anti clock-wise + * clock-wise: + * \f[ + * y(j,i) = x(M-i-1,j) + * \f] + * anti clock-wise: + * \f[ + * y(j,i) = x(i, N-1-j) + * \f] + * where \f$x\f$ is (M x N) input, and \f$y\f$ is (N x M) output. * - * allocate matTrans' memory outside, then set memAlloc as false; + * allocate matRot' memory outside, then set memAlloc as false; * else set as true. */ virtual void rotate(MatrixPtr& matRot, bool memAlloc, bool clockWise) { diff --git a/paddle/math/tests/test_matrixCompare.cpp b/paddle/math/tests/test_matrixCompare.cpp index c062ca10809ac6..e024f2cf1b913f 100644 --- a/paddle/math/tests/test_matrixCompare.cpp +++ b/paddle/math/tests/test_matrixCompare.cpp @@ -176,11 +176,29 @@ void testMatrixTranspose(int height, int width) { cpu->randomizeUniform(); gpu->copyFrom(*cpu); cpu->transpose(cpuT, false); - gpu->transpose(gpuT, false); + gpu->transpose(gpuT, true); TensorCheckEqual(*cpuT, *gpuT); } +void testMatrixRotate(int height, int width) { + MatrixPtr cpu = std::make_shared(height, width); + MatrixPtr gpu = std::make_shared(height, width); + MatrixPtr cpuR = std::make_shared(width, height); + MatrixPtr gpuR = std::make_shared(width, height); + + cpu->randomizeUniform(); + gpu->copyFrom(*cpu); + + cpu->rotate(cpuR, false, true); + gpu->rotate(gpuR, true, true); + TensorCheckEqual(*cpuR, *gpuR); + + cpu->rotate(cpuR, true, false); + gpu->rotate(gpuR, false, false); + TensorCheckEqual(*cpuR, *gpuR); +} + void testMatrixInverse(int height) { MatrixPtr cpu = std::make_shared(height, height); MatrixPtr gpu = std::make_shared(height, height); @@ -215,6 +233,7 @@ TEST(Matrix, unary) { testMatrixZeroAtOffset(height, width); testMatrixGetSum(height, width); testMatrixTranspose(height, width); + testMatrixRotate(height, width); } // inverse testMatrixInverse(height); From 7f4042ec86980811c32a698448f9920162770f91 Mon Sep 17 00:00:00 2001 From: Haonan Date: Wed, 1 Feb 2017 14:56:30 -0800 Subject: [PATCH 131/370] fix stub error --- paddle/cuda/include/stub/hl_matrix_stub.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddle/cuda/include/stub/hl_matrix_stub.h b/paddle/cuda/include/stub/hl_matrix_stub.h index 1309c5974fc3e1..a1712d1e4d2a5d 100644 --- a/paddle/cuda/include/stub/hl_matrix_stub.h +++ b/paddle/cuda/include/stub/hl_matrix_stub.h @@ -108,6 +108,6 @@ inline void hl_matrix_collect_shared_bias(real* B_d, real scale) {} inline void hl_matrix_rotate( - real* mat, real* matRot, int dimM, int dimN, bool clockWise); + real* mat, real* matRot, int dimM, int dimN, bool clockWise) {} #endif // HL_MATRIX_STUB_H_ From 9c42d904689ea71f57f17b802ae7006d6bf37816 Mon Sep 17 00:00:00 2001 From: wangyang59 Date: Wed, 1 Feb 2017 15:02:12 -0800 Subject: [PATCH 132/370] add comments in gru_step_layer of layers.py to explain the parameter location --- python/paddle/trainer_config_helpers/layers.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 770d6303c13587..14035ce3fd8aab 100644 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -2707,8 +2707,7 @@ def gru_step_layer(input, :param gate_act: :param bias_attr: :param param_attr: the parameter_attribute for transforming the output_mem - from previous step. It is instead grouped with input due - to backward model compatibility. + from previous step. :param layer_attr: :return: LayerOutput object. :rtype: LayerOutput @@ -2719,6 +2718,11 @@ def gru_step_layer(input, Layer( name=name, type=LayerType.GRU_STEP_LAYER, + # The parameter here is for transforming the output_mem. The input has + # already been transformed outside this module so it does not need + # parameter associated with it. + # The parameter here is instead grouped with input is due to + # backward model compatibility. inputs=[Input(input.name, **param_attr.attr), output_mem.name], bias=ParamAttr.to_bias(bias_attr), size=size, From 4420929339f2a7736353f5fc1e95c1d2b9060caf Mon Sep 17 00:00:00 2001 From: xichen Date: Wed, 1 Feb 2017 15:45:51 -0800 Subject: [PATCH 133/370] add images for route53 config --- doc/howto/usage/k8s/k8s_aws_en.md | 6 ++++-- .../usage/k8s/src/route53_create_recordset.png | Bin 0 -> 114396 bytes .../usage/k8s/src/route53_create_zone.png | Bin 0 -> 177965 bytes 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 doc/howto/usage/k8s/src/route53_create_recordset.png create mode 100644 doc/howto/usage/k8s/src/route53_create_zone.png diff --git a/doc/howto/usage/k8s/k8s_aws_en.md b/doc/howto/usage/k8s/k8s_aws_en.md index ce5ccbca5ee33b..eda2b639e2f5d9 100644 --- a/doc/howto/usage/k8s/k8s_aws_en.md +++ b/doc/howto/usage/k8s/k8s_aws_en.md @@ -383,13 +383,15 @@ Edit `/etc/hosts` to associate above ip with the DNS name. - Create hosted zone with following config - Domain name: "paddle" - Type: "Private hosted zone for amazon VPC" - - VPC ID: + - VPC ID: `` + -