1# Licensed to the Apache Software Foundation (ASF) under one
2# or more contributor license agreements.  See the NOTICE file
3# distributed with this work for additional information
4# regarding copyright ownership.  The ASF licenses this file
5# to you under the Apache License, Version 2.0 (the
6# "License"); you may not use this file except in compliance
7# with the License.  You may obtain a copy of the License at
8#
9#   http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing,
12# software distributed under the License is distributed on an
13# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14# KIND, either express or implied.  See the License for the
15# specific language governing permissions and limitations
16# under the License.
17# pylint: disable=import-self, invalid-name, unused-argument
18"""
19Caffe testcases
20====================
21This article is a test script to test Caffe operator with Relay.
22"""
23import os
24
25os.environ["GLOG_minloglevel"] = "2"
26import sys
27import logging
28
29logging.basicConfig(level=logging.ERROR)
30
31import numpy as np
32from google.protobuf import text_format
33import caffe
34from caffe import layers as L, params as P
35from caffe.proto import caffe_pb2 as pb
36
37import tvm
38from tvm import relay
39from tvm.contrib import util, graph_runtime
40from tvm.contrib.download import download_testdata
41
42CURRENT_DIR = os.path.join(os.path.expanduser("~"), ".tvm_test_data", "caffe_test")
43
44#######################################################################
45# Generic functions for TVM & Caffe
46# ------------------------------------------
47
48
49def _create_dir(d_path):
50    """ If the directory is not existed, create it"""
51    if not (os.path.exists(d_path) and os.path.isdir(d_path)):
52        os.makedirs(d_path)
53
54
55def _list_to_str(ll):
56    """ Convert list or tuple to str, separated by underline. """
57    if isinstance(ll, (tuple, list)):
58        tmp = [str(i) for i in ll]
59        return "_".join(tmp)
60
61
62def _gen_filename_str(op_name, data_shape, *args, **kwargs):
63    """ Combining the filename according to the op_name, shape and other args. """
64    file_dir = os.path.join(CURRENT_DIR, op_name)
65    _create_dir(file_dir)
66    res = op_name + "_"
67    shape_str = _list_to_str(list(data_shape))
68    res += shape_str
69    for arg in args:
70        if isinstance(arg, (tuple, list)):
71            res += "_" + _list_to_str(arg)
72        elif isinstance(arg, (int, float, str)):
73            res += "_" + str(arg)
74    for _, v in kwargs.items():
75        if isinstance(v, (tuple, list)):
76            res += "_" + _list_to_str(v)
77        elif isinstance(v, (int, float, str)):
78            res += "_" + str(v)
79    res = res.replace(".", "_")
80    res = res.replace("-", "_")
81    proto_file = os.path.join(file_dir, res + ".prototxt")
82    blob_file = os.path.join(file_dir, res + ".caffemodel")
83    solver_file = os.path.join(file_dir, res + "_solver.prototxt")
84
85    return (proto_file, blob_file, solver_file)
86
87
88def _save_prototxt(n_netspec, f_path):
89    """ Generate .prototxt file according to caffe.NetSpec"""
90    s = n_netspec.to_proto()
91    with open(f_path, "w") as f:
92        f.write(str(s))
93
94
95def _save_solver(solver_file, proto_file, blob_file):
96    """ Define a solver proto, you can change the configs."""
97    blob_file_prefix = blob_file.split(".caffemodel")[0]
98    s = pb.SolverParameter()
99    s.train_net = proto_file
100    s.base_lr = 0.01
101    s.momentum = 0.9
102    s.weight_decay = 0.0005
103    s.lr_policy = "inv"
104    s.gamma = 0.0001
105    s.power = 0.75
106    s.display = 1
107    s.max_iter = 100000
108    s.snapshot = 100000
109    s.snapshot_prefix = blob_file_prefix
110
111    with open(solver_file, "w") as f:
112        f.write(str(s))
113
114
115def _save_caffemodel(solver_file, blob_file):
116    """ Generate .caffemodel file."""
117    solver = caffe.SGDSolver(solver_file)
118    solver.net.save(blob_file)
119
120
121def _gen_model_files(n_netspec, proto_file, blob_file, solver_file):
122    _save_prototxt(n_netspec, proto_file)
123    _save_solver(solver_file, proto_file, blob_file)
124    _save_caffemodel(solver_file, blob_file)
125
126
127def _siso_op(data, func, *args, **kwargs):
128    """ Create single input and single output Caffe op """
129    n = caffe.NetSpec()
130    n.data = L.Input(input_param={"shape": {"dim": list(data.shape)}})
131    n.output = func(n.data, *args, **kwargs)
132    return n
133
134
135def _miso_op(data_list, func, *args, **kwargs):
136    """ Create multi input and single output Caffe op """
137    n = caffe.NetSpec()
138    if not isinstance(data_list, (tuple, list)):
139        raise TypeError("Need tuple or list but get {}".format(type(data_list)))
140    input_list = list()
141    for idx, data in enumerate(data_list):
142        n["data" + str(idx)] = L.Input(input_param={"shape": {"dim": list(data.shape)}})
143        input_list.append(n["data" + str(idx)])
144    n.output = func(*input_list, *args, **kwargs)
145    return n
146
147
148def _simo_op(data, func, *args, **kwargs):
149    """ Create single input and multi output Caffe op """
150    n = caffe.NetSpec()
151    n.data = L.Input(input_param={"shape": {"dim": list(data.shape)}})
152    output_list = func(n.data, *args, **kwargs)
153    for idx, out in enumerate(output_list):
154        n["output" + str(idx)] = out
155    return n
156
157
158def _run_caffe(data, proto_file, blob_file):
159    """ Run caffe model by Caffe according to .caffemodel and .prototxt"""
160    net = caffe.Net(proto_file, blob_file, caffe.TEST)
161    if isinstance(data, (list, tuple)):
162        for idx, d in enumerate(data):
163            net.blobs["data" + str(idx)].data[...] = d
164    else:
165        net.blobs["data"].data[...] = data
166    out = net.forward()
167
168    caffe_output = list()
169    for i in range(len(out.keys())):
170        if "output" + str(i) not in out.keys():
171            caffe_output.clear()
172            return list(out.values())
173        caffe_output.append(out["output" + str(i)])
174    return caffe_output
175
176
177def _run_tvm(data, proto_file, blob_file):
178    """ Run caffe model by TVM according to .caffemodel and .prototxt"""
179    init_net = pb.NetParameter()
180    predict_net = pb.NetParameter()
181
182    # load model
183    with open(proto_file, "r") as f:
184        text_format.Merge(f.read(), predict_net)
185    # load blob
186    with open(blob_file, "rb") as f:
187        init_net.ParseFromString(f.read())
188
189    shape_dict = dict()
190    dtype_dict = dict()
191    if isinstance(data, (tuple, list)):
192        for idx, d in enumerate(data):
193            shape_dict["data" + str(idx)] = d.shape
194            dtype_dict["data" + str(idx)] = "float32"
195    else:
196        shape_dict = {"data": data.shape}
197        dtype_dict = {"data": "float32"}
198
199    mod, params = relay.frontend.from_caffe(init_net, predict_net, shape_dict, dtype_dict)
200
201    target = "llvm"
202    target_host = "llvm"
203
204    ctx = tvm.cpu(0)
205    with tvm.transform.PassContext(opt_level=3):
206        lib = relay.build(mod, target=target, target_host=target_host, params=params)
207    dtype = "float32"
208    m = graph_runtime.GraphModule(lib["default"](ctx))
209    if isinstance(data, (tuple, list)):
210        for idx, d in enumerate(data):
211            m.set_input("data" + str(idx), tvm.nd.array(d.astype(dtype)))
212    else:
213        m.set_input("data", tvm.nd.array(data.astype(dtype)))
214    # execute
215    m.run()
216    tvm_output = list()
217    # get outputs
218    for i in range(m.get_num_outputs()):
219        tvm_output.append(m.get_output(i).asnumpy())
220    return tvm_output
221
222
223def _compare_caffe_tvm(caffe_out, tvm_out, is_network=False):
224    for i in range(len(caffe_out)):
225        if is_network:
226            caffe_out[i] = caffe_out[i][:1]
227        tvm.testing.assert_allclose(caffe_out[i], tvm_out[i], rtol=1e-5, atol=1e-5)
228
229
230def _test_op(data, func_op, op_name, **kwargs):
231    """ Single op testing pipline. """
232    shape_list = list()
233    if isinstance(data, (list, tuple)):
234        n = _miso_op(data, func_op, **kwargs)
235        for d in data:
236            shape_list.extend(list(d.shape))
237    else:
238        output_num = 1
239        if "ntop" in kwargs.keys():
240            output_num = kwargs["ntop"]
241        if output_num == 1:
242            n = _siso_op(data, func_op, **kwargs)
243        else:
244            n = _simo_op(data, func_op, **kwargs)
245        shape_list = list(data.shape)
246
247    # obtain the .caffemodel file and .prototxt file
248    (proto_file, blob_file, solver_file) = _gen_filename_str(op_name, shape_list, **kwargs)
249    _gen_model_files(n, proto_file, blob_file, solver_file)
250    # run model in Caffe
251    caffe_out = _run_caffe(data, proto_file, blob_file)
252    # run model in TVM
253    tvm_out = _run_tvm(data, proto_file, blob_file)
254    _compare_caffe_tvm(caffe_out, tvm_out)
255
256
257def _test_network(data, proto_file, blob_file):
258    # run model in Caffe
259    caffe_out = _run_caffe(data, proto_file, blob_file)
260    # run model in TVM
261    tvm_out = _run_tvm(data, proto_file, blob_file)
262    _compare_caffe_tvm(caffe_out, tvm_out, is_network=True)
263
264
265#######################################################################
266# BatchNorm
267# -----------
268
269
270def _test_batchnorm(data, moving_average_fraction=0.999, eps=1e-5):
271    """ One iteration of BatchNorm """
272    _test_op(
273        data, L.BatchNorm, "BatchNorm", moving_average_fraction=moving_average_fraction, eps=eps
274    )
275
276
277def test_forward_BatchNorm():
278    """ BatchNorm """
279    data = np.random.rand(1, 3, 10, 10).astype(np.float32)
280    _test_batchnorm(data)
281    _test_batchnorm(data, moving_average_fraction=0.88, eps=1e-4)
282
283
284#######################################################################
285# Concat
286# -----------
287
288
289def _test_concat(data_list, axis=1):
290    """ One iteration of Concat """
291    _test_op(data_list, L.Concat, "Concat", axis=axis)
292
293
294def test_forward_Concat():
295    """ Concat """
296    _test_concat([np.random.rand(1, 3, 10, 10), np.random.rand(1, 2, 10, 10)], axis=1)
297    _test_concat([np.random.rand(3, 10, 10), np.random.rand(2, 10, 10)], axis=0)
298    _test_concat([np.random.rand(3, 10), np.random.rand(2, 10)], axis=0)
299
300
301#######################################################################
302# Convolution
303# -----------
304
305
306def _test_convolution(data, **kwargs):
307    """ One iteration of Convolution """
308    _test_op(data, L.Convolution, "Convolution", **kwargs)
309
310
311def test_forward_Convolution():
312    """ Convolution """
313    data = np.random.rand(1, 3, 10, 10).astype(np.float32)
314    _test_convolution(
315        data,
316        num_output=20,
317        bias_term=True,
318        pad=0,
319        kernel_size=3,
320        stride=2,
321        dilation=1,
322        weight_filler=dict(type="xavier"),
323        bias_filler=dict(type="xavier"),
324    )
325    _test_convolution(
326        data,
327        num_output=20,
328        bias_term=False,
329        pad=[1, 2],
330        kernel_size=3,
331        stride=2,
332        dilation=1,
333        weight_filler=dict(type="xavier"),
334        bias_filler=dict(type="xavier"),
335    )
336    _test_convolution(
337        data,
338        num_output=20,
339        bias_term=True,
340        pad=[1, 2],
341        kernel_size=[3, 5],
342        stride=[2, 1],
343        dilation=[1, 2],
344        weight_filler=dict(type="xavier"),
345        bias_filler=dict(type="xavier"),
346    )
347    _test_convolution(
348        np.random.rand(1, 2, 10, 10).astype(np.float32),
349        num_output=20,
350        bias_term=True,
351        pad=[1, 2],
352        kernel_size=[3, 5],
353        stride=[2, 1],
354        dilation=[1, 2],
355        weight_filler=dict(type="xavier"),
356        bias_filler=dict(type="xavier"),
357        group=2,
358    )
359    _test_convolution(
360        data,
361        num_output=20,
362        bias_term=True,
363        pad_h=1,
364        pad_w=2,
365        kernel_h=3,
366        kernel_w=5,
367        stride_h=2,
368        stride_w=1,
369        dilation=[1, 2],
370        weight_filler=dict(type="xavier"),
371        bias_filler=dict(type="xavier"),
372    )
373
374
375#######################################################################
376# Crop
377# -----------
378
379
380def _test_crop(data, **kwargs):
381    """ One iteration of Crop """
382    _test_op(data, L.Crop, "Crop", **kwargs)
383
384
385def test_forward_Crop():
386    """ Crop """
387    _test_crop([np.random.rand(10, 10, 120, 120), np.random.rand(10, 5, 50, 60)])
388    _test_crop([np.random.rand(10, 10, 120, 120), np.random.rand(10, 5, 50, 60)], axis=1)
389    _test_crop([np.random.rand(10, 10, 120, 120), np.random.rand(10, 5, 50, 60)], axis=1, offset=2)
390    _test_crop(
391        [np.random.rand(10, 10, 120, 120), np.random.rand(10, 5, 50, 60)], axis=1, offset=[1, 2, 4]
392    )
393    _test_crop(
394        [np.random.rand(10, 10, 120, 120), np.random.rand(10, 5, 50, 60)], axis=2, offset=[2, 4]
395    )
396    _test_crop([np.random.rand(10, 120, 120), np.random.rand(5, 50, 60)], axis=1, offset=[2, 4])
397    _test_crop([np.random.rand(120, 120), np.random.rand(50, 60)], axis=0, offset=[2, 4])
398
399
400#######################################################################
401# Deconvolution
402# -----------
403
404
405def _test_deconvolution(data, **kwargs):
406    """ One iteration of Deconvolution """
407    _test_op(data, L.Deconvolution, "Deconvolution", **kwargs)
408
409
410def test_forward_Deconvolution():
411    """ Deconvolution """
412    data = np.random.rand(1, 16, 32, 32).astype(np.float32)
413    _test_deconvolution(
414        data,
415        convolution_param=dict(
416            num_output=20,
417            bias_term=True,
418            pad=0,
419            kernel_size=3,
420            stride=2,
421            dilation=1,
422            weight_filler=dict(type="xavier"),
423            bias_filler=dict(type="xavier"),
424        ),
425    )
426    _test_deconvolution(
427        data,
428        convolution_param=dict(
429            num_output=20,
430            bias_term=False,
431            pad=[1, 2],
432            kernel_size=3,
433            stride=2,
434            dilation=1,
435            weight_filler=dict(type="xavier"),
436            bias_filler=dict(type="xavier"),
437        ),
438    )
439    _test_deconvolution(
440        data,
441        convolution_param=dict(
442            num_output=20,
443            bias_term=True,
444            pad_h=1,
445            pad_w=2,
446            kernel_h=3,
447            kernel_w=5,
448            stride_h=2,
449            stride_w=1,
450            dilation=1,
451            weight_filler=dict(type="xavier"),
452            bias_filler=dict(type="xavier"),
453        ),
454    )
455
456
457#######################################################################
458# Dropout
459# -----------
460
461
462def _test_dropout(data, **kwargs):
463    """ One iteration of Dropout """
464    _test_op(data, L.Dropout, "Dropout", **kwargs)
465
466
467def test_forward_Dropout():
468    """ Dropout """
469    data = np.random.rand(1, 3, 10, 10).astype(np.float32)
470    _test_dropout(data)
471    _test_dropout(data, dropout_ratio=0.7)
472
473
474#######################################################################
475# Eltwise
476# -----------
477
478
479def _test_eltwise(data_list, **kwargs):
480    """ One iteration of Eltwise """
481    _test_op(data_list, L.Eltwise, "Eltwise", **kwargs)
482
483
484def test_forward_Eltwise():
485    """ Eltwise """
486    _test_eltwise(
487        [
488            np.random.rand(1, 3, 10, 11).astype(np.float32),
489            np.random.rand(1, 3, 10, 11).astype(np.float32),
490        ],
491        operation=0,
492    )
493    _test_eltwise(
494        [
495            np.random.rand(1, 3, 10, 11).astype(np.float32),
496            np.random.rand(1, 3, 10, 11).astype(np.float32),
497        ],
498        operation=1,
499    )
500    _test_eltwise(
501        [
502            np.random.rand(1, 3, 10, 11).astype(np.float32),
503            np.random.rand(1, 3, 10, 11).astype(np.float32),
504        ],
505        operation=2,
506    )
507    _test_eltwise(
508        [
509            np.random.rand(1, 3, 10, 11).astype(np.float32),
510            np.random.rand(1, 3, 10, 11).astype(np.float32),
511        ],
512        operation=1,
513        coeff=[0.5, 1],
514    )
515
516
517#######################################################################
518# Flatten
519# -----------
520
521
522def _test_flatten(data, axis=1):
523    """ One iteration of Flatten """
524    _test_op(data, L.Flatten, "Flatten", axis=axis)
525
526
527def test_forward_Flatten():
528    """ Flatten """
529    data = np.random.rand(1, 3, 10, 10).astype(np.float32)
530    _test_flatten(data)
531    _test_flatten(data, axis=1)
532
533
534#######################################################################
535# Flatten
536# -----------
537
538
539def _test_inner_product(data, **kwargs):
540    """ One iteration of InnerProduct"""
541    _test_op(data, L.InnerProduct, "InnerProduct", **kwargs)
542
543
544def test_forward_InnerProduct():
545    """ InnerProduct """
546    data = np.random.rand(1, 3, 10, 10)
547    _test_inner_product(data, num_output=20, bias_term=False, weight_filler=dict(type="xavier"))
548    _test_inner_product(
549        data,
550        num_output=20,
551        bias_term=True,
552        weight_filler=dict(type="xavier"),
553        bias_filler=dict(type="xavier"),
554    )
555    _test_inner_product(
556        np.random.rand(20, 10).astype(np.float32),
557        num_output=30,
558        bias_term=True,
559        weight_filler=dict(type="xavier"),
560        bias_filler=dict(type="xavier"),
561    )
562
563
564#######################################################################
565# LRN
566# -----------
567
568
569def _test_lrn(data, local_size=5, alpha=1.0, beta=0.75, k=1.0):
570    """ One iteration of LRN """
571    _test_op(data, L.LRN, "LRN", local_size=local_size, alpha=alpha, beta=beta, k=k)
572
573
574def test_forward_LRN():
575    """ LRN """
576    data = np.random.rand(1, 3, 10, 10).astype(np.float32)
577    _test_lrn(data)
578    _test_lrn(data, local_size=3)
579    _test_lrn(data, local_size=3, alpha=2.0)
580    _test_lrn(
581        data,
582        local_size=3,
583        alpha=2.0,
584        beta=0.5,
585    )
586    _test_lrn(data, local_size=3, alpha=2.0, beta=0.5, k=2.0)
587
588
589#######################################################################
590# Pooling
591# -----------
592
593
594def _test_pooling(data, **kwargs):
595    """ One iteration of Pooling. """
596    _test_op(data, L.Pooling, "Pooling", **kwargs)
597
598
599def test_forward_Pooling():
600    """ Pooing """
601    data = np.random.rand(1, 3, 10, 10).astype(np.float32)
602    # MAX Pooling
603    _test_pooling(data, kernel_size=2, stride=2, pad=0, pool=P.Pooling.MAX)
604    _test_pooling(
605        data, kernel_h=2, kernel_w=3, stride_h=2, stride_w=1, pad_h=1, pad_w=2, pool=P.Pooling.MAX
606    )
607    _test_pooling(data, pool=P.Pooling.MAX, global_pooling=True)
608
609    # AVE Pooing
610    _test_pooling(data, kernel_size=2, stride=2, pad=0, pool=P.Pooling.AVE)
611    _test_pooling(
612        data, kernel_h=2, kernel_w=3, stride_h=2, stride_w=1, pad_h=1, pad_w=2, pool=P.Pooling.AVE
613    )
614    _test_pooling(data, pool=P.Pooling.AVE, global_pooling=True)
615
616
617#######################################################################
618# PReLU
619# -----------
620
621
622def _test_prelu(data, **kwargs):
623    """ One iteration of PReLU. """
624    _test_op(data, L.PReLU, "PReLU", **kwargs)
625
626
627def test_forward_PReLU():
628    """ PReLU """
629    data = np.random.rand(1, 3, 10, 10).astype(np.float32)
630    _test_prelu(data, filler=dict(type="constant", value=0.5))
631    _test_prelu(data)
632    _test_prelu(np.random.rand(10, 20).astype(np.float32))
633
634
635#######################################################################
636# ReLU
637# -----------
638
639
640def _test_relu(data, **kwargs):
641    """ One iteration of ReLU. """
642    _test_op(data, L.ReLU, "ReLU", **kwargs)
643
644
645def test_forward_ReLU():
646    """ ReLU """
647    data = np.random.rand(1, 3, 10, 10).astype(np.float32)
648    _test_relu(data)
649    _test_relu(np.random.rand(10, 20).astype(np.float32))
650
651
652#######################################################################
653# Reshape
654# -----------
655
656
657def _test_reshape(data, **kwargs):
658    """ One iteration of Reshape. """
659    _test_op(data, L.Reshape, "Reshape", **kwargs)
660
661
662def test_forward_Reshape():
663    """ Reshape """
664    data = np.random.rand(1, 8, 6).astype(np.float32)
665    _test_reshape(data, reshape_param={"shape": {"dim": [4, 3, 4]}})
666    _test_reshape(data, reshape_param={"shape": {"dim": [2, 0, 3]}})
667    _test_reshape(data, reshape_param={"shape": {"dim": [2, 0, -1]}})
668    _test_reshape(data, reshape_param={"shape": {"dim": [0, -1]}})
669
670    _test_reshape(data, reshape_param={"shape": {"dim": [2, 3]}, "axis": 2})
671    _test_reshape(data, reshape_param={"shape": {"dim": [4, 3, 4]}, "axis": 1})
672    _test_reshape(data, reshape_param={"shape": {"dim": [4, 3, 4]}, "axis": -3})
673
674    _test_reshape(data, reshape_param={"shape": {"dim": [2, 4]}, "axis": 1, "num_axes": 1})
675    _test_reshape(data, reshape_param={"shape": {"dim": [3, 16]}, "axis": 1, "num_axes": 2})
676
677
678#######################################################################
679# Scale
680# -----------
681
682
683def _test_scale(data, **kwargs):
684    """ One iteration of Scale. """
685    _test_op(data, L.Scale, "Scale", **kwargs)
686
687
688def test_forward_Scale():
689    """ Scale """
690    data = np.random.rand(1, 3, 10, 10).astype(np.float32)
691    _test_scale(data, filler=dict(type="xavier"))
692    _test_scale(data, filler=dict(type="xavier"), bias_term=True, bias_filler=dict(type="xavier"))
693
694
695#######################################################################
696# Sigmoid
697# -----------
698
699
700def _test_sigmoid(data, **kwargs):
701    """ One iteration of Sigmoid. """
702    _test_op(data, L.Sigmoid, "Sigmoid", **kwargs)
703
704
705def test_forward_Sigmoid():
706    """ Sigmoid """
707    data = np.random.rand(1, 3, 10, 10).astype(np.float32)
708    _test_sigmoid(data)
709
710
711#######################################################################
712# Slice
713# -----------
714
715
716def _test_slice(data, **kwargs):
717    """ One iteration of Slice """
718    _test_op(data, L.Slice, "Slice", **kwargs)
719
720
721def test_forward_Slice():
722    """ Slice """
723    data = np.random.rand(1, 3, 10, 10).astype(np.float32)
724    _test_slice(data, ntop=2, slice_param=dict(axis=1, slice_point=[1]))
725    _test_slice(data, ntop=2, slice_param=dict(axis=-1, slice_point=[1]))
726    _test_slice(data, ntop=3, slice_param=dict(axis=2, slice_point=[1, 6]))
727    _test_slice(data, ntop=3)
728
729
730#######################################################################
731# Softmax
732# -----------
733
734
735def _test_softmax(data, **kwargs):
736    """ One iteration of Softmax """
737    _test_op(data, L.Softmax, "Softmax", **kwargs)
738
739
740def test_forward_Softmax():
741    """ Softmax"""
742    _test_softmax(np.random.rand(1, 3, 10, 10).astype(np.float32))
743    _test_softmax(np.random.rand(1, 3, 10, 10).astype(np.float32), axis=2)
744    _test_softmax(np.random.rand(10, 10).astype(np.float32), axis=0)
745    _test_softmax(np.random.rand(2, 10, 10).astype(np.float32), axis=1)
746
747
748#######################################################################
749# TanH
750# -----------
751
752
753def _test_tanh(data, **kwargs):
754    """ One iteration of TanH """
755    _test_op(data, L.TanH, "TanH", **kwargs)
756
757
758def test_forward_TanH():
759    """ TanH """
760    _test_tanh(np.random.rand(1, 3, 10, 10).astype(np.float32))
761    _test_tanh(np.random.rand(3, 10, 10).astype(np.float32))
762    _test_tanh(np.random.rand(10, 10).astype(np.float32))
763    _test_tanh(np.random.rand(10).astype(np.float32))
764
765
766#######################################################################
767# Mobilenetv2
768# -----------
769
770
771def _test_mobilenetv2(data):
772    """ One iteration of Mobilenetv2 """
773    mean_val = np.array([103.939, 116.779, 123.68], dtype=np.float32)
774    mean_val = np.reshape(mean_val, (1, 3, 1, 1))
775    mean_val = np.tile(mean_val, (1, 1, 224, 224))
776    data_process = data - mean_val
777    data_process = data_process / 58.8
778    data_process = data_process.astype(np.float32)
779
780    proto_file_url = (
781        "https://github.com/shicai/MobileNet-Caffe/raw/" "master/mobilenet_v2_deploy.prototxt"
782    )
783    blob_file_url = (
784        "https://github.com/shicai/MobileNet-Caffe/blob/" "master/mobilenet_v2.caffemodel?raw=true"
785    )
786    proto_file = download_testdata(proto_file_url, "mobilenetv2.prototxt", module="model")
787    blob_file = download_testdata(blob_file_url, "mobilenetv2.caffemodel", module="model")
788    _test_network(data_process, proto_file, blob_file)
789
790
791def test_forward_Mobilenetv2():
792    """ Mobilenetv2 """
793    data = np.random.randint(0, 256, size=(1, 3, 224, 224)).astype(np.float32)
794    _test_mobilenetv2(data)
795
796
797#######################################################################
798# Alexnet
799# -----------
800
801
802def _test_alexnet(data):
803    """ One iteration of Alexnet """
804    mean_val = np.array([103.939, 116.779, 123.68], dtype=np.float32)
805    mean_val = np.reshape(mean_val, (1, 3, 1, 1))
806    mean_val = np.tile(mean_val, (1, 1, 227, 227))
807    data_process = data - mean_val
808    data_process = data_process.astype(np.float32)
809
810    proto_file_url = (
811        "https://github.com/BVLC/caffe/raw/master/models/" "bvlc_alexnet/deploy.prototxt"
812    )
813    blob_file_url = "http://dl.caffe.berkeleyvision.org/bvlc_alexnet.caffemodel"
814    proto_file = download_testdata(proto_file_url, "alexnet.prototxt", module="model")
815    blob_file = download_testdata(blob_file_url, "alexnet.caffemodel", module="model")
816    _test_network(data_process, proto_file, blob_file)
817
818
819def test_forward_Alexnet():
820    """ Alexnet """
821    data = np.random.randint(0, 256, size=(1, 3, 227, 227)).astype(np.float32)
822    _test_alexnet(data)
823
824
825#######################################################################
826# Resnet50
827# -----------
828
829
830def _test_resnet50(data):
831    """ One iteration of Resnet50 """
832    mean_val = np.array([103.939, 116.779, 123.68], dtype=np.float32)
833    mean_val = np.reshape(mean_val, (1, 3, 1, 1))
834    mean_val = np.tile(mean_val, (1, 1, 224, 224))
835    data_process = data - mean_val
836    data_process = data_process.astype(np.float32)
837
838    proto_file_url = (
839        "https://github.com/fernchen/CaffeModels/raw/" "master/resnet/ResNet-50-deploy.prototxt"
840    )
841    blob_file_url = (
842        "https://github.com/fernchen/CaffeModels/raw/" "master/resnet/ResNet-50-model.caffemodel"
843    )
844
845    proto_file = download_testdata(proto_file_url, "resnet50.prototxt", module="model")
846    blob_file = download_testdata(blob_file_url, "resnet50.caffemodel", module="model")
847
848    _test_network(data_process, proto_file, blob_file)
849
850
851def test_forward_Resnet50():
852    """ Resnet50 """
853    data = np.random.randint(0, 256, size=(1, 3, 224, 224)).astype(np.float32)
854    _test_resnet50(data)
855
856
857#######################################################################
858# Inceptionv4
859# -----------
860
861
862def _test_inceptionv1(data):
863    """ One iteration of Inceptionv4 """
864    mean_val = np.array([103.939, 116.779, 123.68], dtype=np.float32)
865    mean_val = np.reshape(mean_val, (1, 3, 1, 1))
866    mean_val = np.tile(mean_val, (1, 1, 224, 224))
867    data_process = data - mean_val
868    data_process = data_process / 58.8
869    data_process = data_process.astype(np.float32)
870
871    proto_file_url = (
872        "https://github.com/BVLC/caffe/raw/master/models" "/bvlc_googlenet/deploy.prototxt"
873    )
874    blob_file_url = "http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel"
875    proto_file = download_testdata(proto_file_url, "inceptionv1.prototxt", module="model")
876    blob_file = download_testdata(blob_file_url, "inceptionv1.caffemodel", module="model")
877    _test_network(data_process, proto_file, blob_file)
878
879
880def test_forward_Inceptionv1():
881    """ Inceptionv4 """
882    data = np.random.randint(0, 256, size=(1, 3, 224, 224)).astype(np.float32)
883    _test_inceptionv1(data)
884
885
886if __name__ == "__main__":
887    # NN
888    test_forward_Convolution()
889    test_forward_Deconvolution()
890    test_forward_Dropout()
891    test_forward_LRN()
892    test_forward_Pooling()
893    test_forward_Scale()
894    test_forward_InnerProduct()
895    test_forward_BatchNorm()
896
897    # Elemwise
898    test_forward_Eltwise()
899
900    # Activation
901    test_forward_PReLU()
902    test_forward_ReLU()
903    test_forward_Sigmoid()
904    test_forward_Softmax()
905    test_forward_TanH()
906
907    # Reshape
908    test_forward_Reshape()
909    test_forward_Flatten()
910
911    # Math
912    test_forward_Concat()
913    test_forward_Crop()
914    test_forward_Slice()
915
916    # End to End
917    test_forward_Mobilenetv2()
918    test_forward_Alexnet()
919    test_forward_Resnet50()
920    test_forward_Inceptionv1()
921