layers.h 9.71 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
// Copyright (C) 2015  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.
#ifndef DLIB_DNn_LAYERS_H_
#define DLIB_DNn_LAYERS_H_

#include "layers_abstract.h"
#include "tensor.h"
#include "core.h"
#include <iostream>
#include <string>
Davis King's avatar
Davis King committed
11
12
#include "../rand.h"
#include "../string.h"
13
#include "tensor_tools.h"
14
15
16
17
18
19
20
21
22
23
24
25
26


namespace dlib
{

// ----------------------------------------------------------------------------------------

    class con_
    {
    public:
        con_()
        {}

Davis King's avatar
Davis King committed
27
28
        template <typename SUBNET>
        void setup (const SUBNET& sub)
29
30
31
32
        {
            // TODO
        }

Davis King's avatar
Davis King committed
33
34
        template <typename SUBNET>
        void forward(const SUBNET& sub, resizable_tensor& output)
35
36
37
38
        {
            // TODO
        } 

Davis King's avatar
Davis King committed
39
        template <typename SUBNET>
40
        void backward(const tensor& gradient_input, SUBNET& sub, tensor& params_grad)
41
42
43
44
45
46
47
48
49
50
51
52
        {
            // TODO
        }

        const tensor& get_layer_params() const { return params; }
        tensor& get_layer_params() { return params; }

    private:

        resizable_tensor params;
    };

Davis King's avatar
Davis King committed
53
54
    template <typename SUBNET>
    using con = add_layer<con_, SUBNET>;
55

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// ----------------------------------------------------------------------------------------

    class bn_
    {
    public:
        bn_()
        {}

        template <typename SUBNET>
        void setup (const SUBNET& sub)
        {
            // TODO
        }

        template <typename SUBNET>
        void forward(const SUBNET& sub, resizable_tensor& output)
        {
            // TODO
        } 

        template <typename SUBNET>
        void backward(const tensor& gradient_input, SUBNET& sub, tensor& params_grad)
        {
            // TODO
        }

        const tensor& get_layer_params() const { return params; }
        tensor& get_layer_params() { return params; }

    private:

        resizable_tensor params;
    };

    template <typename SUBNET>
    using bn = add_layer<bn_, SUBNET>;

93
94
95
96
97
// ----------------------------------------------------------------------------------------

    class fc_
    {
    public:
Davis King's avatar
Davis King committed
98
        fc_() : num_outputs(1), num_inputs(0)
99
100
101
        {
        }

102
103
        explicit fc_(
            unsigned long num_outputs_
Davis King's avatar
Davis King committed
104
        ) : num_outputs(num_outputs_), num_inputs(0)
105
106
107
108
109
110
        {
        }

        unsigned long get_num_outputs (
        ) const { return num_outputs; }

Davis King's avatar
Davis King committed
111
112
        template <typename SUBNET>
        void setup (const SUBNET& sub)
113
114
115
116
        {
            num_inputs = sub.get_output().nr()*sub.get_output().nc()*sub.get_output().k();
            params.set_size(num_inputs, num_outputs);

117
            dlib::rand rnd("fc_"+cast_to_string(num_outputs));
118
119
120
            randomize_parameters(params, num_inputs+num_outputs, rnd);
        }

Davis King's avatar
Davis King committed
121
122
        template <typename SUBNET>
        void forward(const SUBNET& sub, resizable_tensor& output)
123
        {
124
            output.set_size(sub.get_output().num_samples(), num_outputs);
125

126
            tt::gemm(0,output, 1,sub.get_output(),false, params,false);
127
128
        } 

Davis King's avatar
Davis King committed
129
        template <typename SUBNET>
130
        void backward(const tensor& gradient_input, SUBNET& sub, tensor& params_grad)
131
132
        {
            // compute the gradient of the parameters.  
133
            tt::gemm(0,params_grad, 1,sub.get_output(),true, gradient_input,false);
134
135

            // compute the gradient for the data
136
            tt::gemm(1,sub.get_gradient_input(), 1,gradient_input,false, params,true);
137
138
139
140
141
        }

        const tensor& get_layer_params() const { return params; }
        tensor& get_layer_params() { return params; }

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
        friend void serialize(const fc_& item, std::ostream& out)
        {
            serialize("fc_", out);
            serialize(item.num_outputs, out);
            serialize(item.num_inputs, out);
            serialize(item.params, out);
        }

        friend void deserialize(fc_& item, std::istream& in)
        {
            std::string version;
            deserialize(version, in);
            if (version != "fc_")
                throw serialization_error("Unexpected version found while deserializing dlib::fc_.");
            deserialize(item.num_outputs, in);
            deserialize(item.num_inputs, in);
            deserialize(item.params, in);
        }

161
162
163
164
165
166
167
168
    private:

        unsigned long num_outputs;
        unsigned long num_inputs;
        resizable_tensor params;
    };


Davis King's avatar
Davis King committed
169
170
    template <typename SUBNET>
    using fc = add_layer<fc_, SUBNET>;
171
172
173
174
175
176
177
178
179
180

// ----------------------------------------------------------------------------------------

    class relu_
    {
    public:
        relu_() 
        {
        }

Davis King's avatar
Davis King committed
181
182
        template <typename SUBNET>
        void setup (const SUBNET& sub)
183
184
185
        {
        }

186
        void forward_inplace(const tensor& input, tensor& output)
187
        {
188
            tt::relu(output, input);
189
190
        } 

191
192
193
194
        void backward_inplace(
            const tensor& computed_output,
            const tensor& gradient_input, 
            tensor& data_grad, 
195
            tensor& 
196
        )
197
        {
198
            tt::relu_gradient(data_grad, computed_output, gradient_input);
199
200
201
202
203
        }

        const tensor& get_layer_params() const { return params; }
        tensor& get_layer_params() { return params; }

Davis King's avatar
Davis King committed
204
        friend void serialize(const relu_& , std::ostream& out)
205
        {
206
            serialize("relu_", out);
207
208
        }

Davis King's avatar
Davis King committed
209
        friend void deserialize(relu_& , std::istream& in)
210
        {
211
212
213
214
            std::string version;
            deserialize(version, in);
            if (version != "relu_")
                throw serialization_error("Unexpected version found while deserializing dlib::relu_.");
215
216
        }

217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
    private:
        resizable_tensor params;
    };


    template <typename SUBNET>
    using relu = add_layer<relu_, SUBNET>;

// ----------------------------------------------------------------------------------------

    class sig_
    {
    public:
        sig_() 
        {
        }

        template <typename SUBNET>
        void setup (const SUBNET& sub)
        {
        }

        void forward_inplace(const tensor& input, tensor& output)
        {
            tt::sigmoid(output, input);
        } 

        void backward_inplace(
            const tensor& computed_output,
            const tensor& gradient_input, 
            tensor& data_grad, 
            tensor& 
        )
        {
            tt::sigmoid_gradient(data_grad, computed_output, gradient_input);
        }

        const tensor& get_layer_params() const { return params; }
        tensor& get_layer_params() { return params; }

        friend void serialize(const sig_& , std::ostream& out)
        {
            serialize("sig_", out);
        }

        friend void deserialize(sig_& , std::istream& in)
        {
            std::string version;
            deserialize(version, in);
            if (version != "sig_")
                throw serialization_error("Unexpected version found while deserializing dlib::sig_.");
        }
269
270

    private:
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
        resizable_tensor params;
    };


    template <typename SUBNET>
    using sig = add_layer<sig_, SUBNET>;

// ----------------------------------------------------------------------------------------

    class htan_
    {
    public:
        htan_() 
        {
        }

        template <typename SUBNET>
        void setup (const SUBNET& sub)
        {
        }

        void forward_inplace(const tensor& input, tensor& output)
        {
            tt::tanh(output, input);
        } 
296

297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
        void backward_inplace(
            const tensor& computed_output,
            const tensor& gradient_input, 
            tensor& data_grad, 
            tensor& 
        )
        {
            tt::tanh_gradient(data_grad, computed_output, gradient_input);
        }

        const tensor& get_layer_params() const { return params; }
        tensor& get_layer_params() { return params; }

        friend void serialize(const htan_& , std::ostream& out)
        {
            serialize("htan_", out);
        }

        friend void deserialize(htan_& , std::istream& in)
        {
            std::string version;
            deserialize(version, in);
            if (version != "htan_")
                throw serialization_error("Unexpected version found while deserializing dlib::htan_.");
        }

    private:
324
325
326
        resizable_tensor params;
    };

327

Davis King's avatar
Davis King committed
328
    template <typename SUBNET>
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
    using htan = add_layer<htan_, SUBNET>;

// ----------------------------------------------------------------------------------------

    class softmax_
    {
    public:
        softmax_() 
        {
        }

        template <typename SUBNET>
        void setup (const SUBNET& sub)
        {
        }

        void forward_inplace(const tensor& input, tensor& output)
        {
            tt::softmax(output, input);
        } 

        void backward_inplace(
            const tensor& computed_output,
            const tensor& gradient_input, 
            tensor& data_grad, 
            tensor& 
        )
        {
            tt::softmax_gradient(data_grad, computed_output, gradient_input);
        }

        const tensor& get_layer_params() const { return params; }
        tensor& get_layer_params() { return params; }

        friend void serialize(const softmax_& , std::ostream& out)
        {
            serialize("softmax_", out);
        }

        friend void deserialize(softmax_& , std::istream& in)
        {
            std::string version;
            deserialize(version, in);
            if (version != "softmax_")
                throw serialization_error("Unexpected version found while deserializing dlib::softmax_.");
        }

    private:
        resizable_tensor params;
    };

    template <typename SUBNET>
    using softmax = add_layer<softmax_, SUBNET>;
382
383
384
385
386

// ----------------------------------------------------------------------------------------

}

387
#endif // DLIB_DNn_LAYERS_H_
388
389