From e1ee5ff5cb3a20ccd8307eb1cdc9bb077ce869f6 Mon Sep 17 00:00:00 2001 From: Aidan Gomez Date: Tue, 18 Aug 2015 11:19:30 -0700 Subject: [PATCH] Update kernel generators --- include/caffe/util/assign_conv_weights.h | 90 +++++++++++++++++++++--- src/caffe/proto/caffe.proto | 7 +- 2 files changed, 83 insertions(+), 14 deletions(-) diff --git a/include/caffe/util/assign_conv_weights.h b/include/caffe/util/assign_conv_weights.h index da17e3d91fe..284009a7a69 100644 --- a/include/caffe/util/assign_conv_weights.h +++ b/include/caffe/util/assign_conv_weights.h @@ -9,6 +9,7 @@ #include "caffe/solver.hpp" #include "caffe/util/fft.hpp" #include "caffe/util/read_audio.hpp" +#include "caffe/util/rng.hpp" namespace caffe { @@ -87,22 +88,34 @@ class ThinKernel : public KernelGen { const auto numKernels = KernelGen::kNumKernels; const auto kernelSize = KernelGen::kKernelSize; - auto step = static_cast(kernelSize) / numKernels; auto kernelWeights = std::valarray(kernelSize * numKernels); - for (auto kernel = 0; kernel < numKernels; ++kernel) { - auto peakLocation = step * kernel / kernelSize; - for (auto position = 0; position < kernelSize; ++position) { - auto x = static_cast(position) / kernelSize; - kernelWeights[(kernel * kernelSize) + position] = KernelGen::curve(x, peakLocation, kB); + T scale = 0.1; + caffe_rng_uniform(numKernels * kernelSize, -scale, scale, + std::begin(kernelWeights)); + + std::normal_distribution<> random_distribution(0, 0.5); + std::function variate_generator = std::bind(random_distribution, std::ref(*caffe_rng())); + + for (auto n = 0; n < numKernels; n += 1) { + auto ng = 2 * (variate_generator() + 0.5); + for (auto g = 0; g < ng; g += 1) { + auto height = variate_generator(); + auto mid = kernelSize/2 + variate_generator()*kernelSize; + auto width = 1 + variate_generator(); + for (auto i = 0; i < kernelSize; i += 1) { + auto offset = n * kernelSize + i; + kernelWeights[offset] += gaussian(i, height, mid, width); + } } } return kernelWeights; } - -protected: - double kB = -0.0005; + inline T gaussian(T x, T height, T mid, T width) { + x -= mid; + return height * std::exp(-x*x / (2*width*width)); + } }; template @@ -129,8 +142,12 @@ class FFTKernel : public KernelGen { auto fft = caffe::FastFourierTransform(2 * kernelSize, options); fft.process(std::begin(fftBuffer), 2 * kernelSize); - - std::move(std::begin(fftBuffer), std::begin(fftBuffer) + kernelSize, std::begin(data) + (i * kernelSize)); + + std::transform(std::begin(fftBuffer), std::begin(fftBuffer) + 2 * kernelSize, std::begin(fftBuffer), [kernelSize](const T& a){ + return a / (2 * kernelSize); + }); + + std::move(std::begin(fftBuffer), std::begin(fftBuffer) + kernelSize, std::begin(data) + (i * kernelSize)); } else { auto dataStart = std::begin(data) + ((i % 84) * kernelSize); std::move_backward(dataStart, dataStart + kernelSize, std::begin(data) + (i * kernelSize)); @@ -141,6 +158,51 @@ class FFTKernel : public KernelGen { } }; +template +class WaveletKernel : public KernelGen { +public: + WaveletKernel(int numKernels, int kernelSize) : KernelGen(numKernels, kernelSize) {} + WaveletKernel(WaveletKernel& other) : KernelGen(other) {} + ~WaveletKernel(){} + +protected: + inline std::valarray kernelGen() { + const auto numKernels = KernelGen::kNumKernels; + const auto kernelSize = KernelGen::kKernelSize; + + auto data = std::valarray(numKernels * kernelSize); + + T scale = 0.1; + caffe_rng_uniform(numKernels * kernelSize, -scale, scale, + std::begin(data)); + + std::uniform_real_distribution<> fdistribution(20, 20000); + std::function fgenerator = std::bind(fdistribution, std::ref(*caffe_rng())); + + std::uniform_real_distribution<> pdistribution(-M_PI/2, M_PI/2); + std::function pgenerator = std::bind(pdistribution, std::ref(*caffe_rng())); + + const auto width = kernelSize; + for (auto n = 0; n < numKernels; n += 1) { + const auto f = fgenerator(); + const auto p = pgenerator(); + const auto offset = n * kernelSize; + generate(f, p, std::begin(data) + offset, width); + } + + return data; + } + inline void generate(T frequency, T phase, T* data, int capacity) { + const auto sampleRate = 44100.0; + const auto dt = 1.0 / sampleRate; + auto time = 0.0; + for (std::size_t i = 0; i < capacity; i += 1) { + data[i] = std::sin(2 * M_PI * frequency * time + phase); + time += dt; + } + } +}; + template std::shared_ptr> generateKernel(int numKernels, int kernelSize); template @@ -173,6 +235,9 @@ template case caffe::FillerParameter_PeakType_THIN: kernel = std::make_shared>(numKernels, kernelSize); break; + case caffe::FillerParameter_PeakType_WAVELET: + kernel = std::make_shared>(numKernels, kernelSize); + break; } auto data = static_cast(layer->blobs()[0]->data()->mutable_cpu_data()); // first blob is weights, second is biases @@ -195,6 +260,9 @@ inline void assignConvolutionWeights(T* data, int numKernels, int kernelSize, ca case caffe::FillerParameter_PeakType_THIN: kernel = std::make_shared>(numKernels, kernelSize); break; + case caffe::FillerParameter_PeakType_WAVELET: + kernel = std::make_shared>(numKernels, kernelSize); + break; } kernel->generateKernel(data); } diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 2f5272c681c..38e998ee12b 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -58,9 +58,10 @@ message FillerParameter { } optional VarianceNorm variance_norm = 8 [default = FAN_IN]; enum PeakType { - THICK = 0; - THIN = 1; - FFT = 2; + THICK = 0; + THIN = 1; + FFT = 2; + WAVELET = 3; } optional PeakType peak_type = 9 [default = THIN]; }