From: @yonibaehr_admin Reviewed-by: @HilbertDavid,@ddwsky Signed-off-by: @HilbertDavidtags/v1.2.0-rc1
| @@ -113,6 +113,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) | |||||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/kernel/arm) | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/kernel/arm) | ||||
| include_directories(${TOP_DIR}/third_party) | include_directories(${TOP_DIR}/third_party) | ||||
| include_directories(${CMAKE_BINARY_DIR}) | include_directories(${CMAKE_BINARY_DIR}) | ||||
| include_directories(${CCSRC_DIR}/minddata/dataset/liteapi) | |||||
| include(${TOP_DIR}/cmake/utils.cmake) | include(${TOP_DIR}/cmake/utils.cmake) | ||||
| include(${TOP_DIR}/cmake/dependency_utils.cmake) | include(${TOP_DIR}/cmake/dependency_utils.cmake) | ||||
| @@ -0,0 +1,7 @@ | |||||
| *.mindir | |||||
| *.ms | |||||
| *.bin | |||||
| *.ckpt | |||||
| export_result.txt | |||||
| mindir | |||||
| train_io | |||||
| @@ -0,0 +1,81 @@ | |||||
| # Copyright 2021 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """NetworkInNetwork.""" | |||||
| import numpy as np | |||||
| import mindspore.nn as nn | |||||
| import mindspore.ops as ops | |||||
| from mindspore import Tensor | |||||
| # NiN block | |||||
| class NiN(nn.Cell): | |||||
| """class NiN""" | |||||
| def __init__(self, num_classes=10, num_channel=3): | |||||
| super().__init__() | |||||
| self.size = ops.Size() | |||||
| self.block0 = nn.SequentialCell( | |||||
| # block 0 | |||||
| nn.Conv2d(in_channels=num_channel, out_channels=192, kernel_size=5, stride=1, has_bias=False), | |||||
| nn.ReLU(), | |||||
| nn.Conv2d(in_channels=192, out_channels=160, kernel_size=1, stride=1, has_bias=True), | |||||
| nn.ReLU(), | |||||
| nn.Conv2d(in_channels=160, out_channels=96, kernel_size=1, stride=1, has_bias=True), | |||||
| nn.ReLU(), | |||||
| nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same'), | |||||
| nn.Dropout(1.0) | |||||
| ) | |||||
| self.block1 = nn.SequentialCell( | |||||
| # block 1 | |||||
| nn.Conv2d(in_channels=96, out_channels=192, kernel_size=5, stride=1, has_bias=False), | |||||
| nn.ReLU(), | |||||
| nn.Conv2d(in_channels=192, out_channels=192, kernel_size=1, stride=1, has_bias=True), | |||||
| nn.ReLU(), | |||||
| nn.Conv2d(in_channels=192, out_channels=192, kernel_size=1, stride=1, has_bias=True), | |||||
| nn.ReLU(), | |||||
| nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same'), | |||||
| nn.Dropout(1.0) | |||||
| ) | |||||
| self.block2 = nn.SequentialCell( | |||||
| # block 2 | |||||
| nn.Conv2d(in_channels=192, out_channels=192, kernel_size=3, stride=1, has_bias=False), | |||||
| nn.ReLU(), | |||||
| nn.Conv2d(in_channels=192, out_channels=192, kernel_size=1, stride=1, has_bias=True), | |||||
| nn.ReLU(), | |||||
| nn.Conv2d(in_channels=192, out_channels=num_classes, kernel_size=1, stride=1, has_bias=True), | |||||
| nn.ReLU(), | |||||
| nn.AvgPool2d(kernel_size=8, stride=1, pad_mode='valid') | |||||
| ) | |||||
| # flatten | |||||
| self.flatten = nn.Flatten() | |||||
| self._initialize_weights() | |||||
| def _initialize_weights(self): | |||||
| self.init_parameters_data() | |||||
| for _, m in self.cells_and_names(): | |||||
| if isinstance(m, (nn.Conv2d)): | |||||
| n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels | |||||
| m.weight.set_data(Tensor(np.random.normal(0, np.sqrt(2. / n), | |||||
| m.weight.data.shape).astype("float32"))) | |||||
| if m.bias is not None: | |||||
| m.bias.set_data( | |||||
| Tensor(np.zeros(m.bias.data.shape, dtype="float32"))) | |||||
| def construct(self, x): | |||||
| out = self.block0(x) | |||||
| out = self.block1(out) | |||||
| out = self.block2(out) | |||||
| out = self.flatten(out) | |||||
| return out | |||||
| @@ -0,0 +1,39 @@ | |||||
| # Copyright 2021 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """densenet_train_export.""" | |||||
| import sys | |||||
| import numpy as np | |||||
| from train_utils import SaveInOut, TrainWrap | |||||
| from official.cv.densenet121.src.network.densenet import DenseNet121 | |||||
| import mindspore.common.dtype as mstype | |||||
| from mindspore import context, Tensor, nn | |||||
| from mindspore.train.serialization import export | |||||
| context.set_context(mode=context.PYNATIVE_MODE, device_target="GPU", save_graphs=False) | |||||
| n = DenseNet121(num_classes=10) | |||||
| loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False) | |||||
| optimizer = nn.SGD(n.trainable_params(), learning_rate=0.001, momentum=0.9, dampening=0.0, weight_decay=0.0, | |||||
| nesterov=True, loss_scale=0.9) | |||||
| net = TrainWrap(n, loss_fn, optimizer) | |||||
| batch = 2 | |||||
| x = Tensor(np.random.randn(batch, 3, 224, 224), mstype.float32) | |||||
| label = Tensor(np.zeros([batch, 10]).astype(np.float32)) | |||||
| export(net, x, label, file_name="mindir/densenet_train", file_format='MINDIR') | |||||
| if len(sys.argv) > 1: | |||||
| SaveInOut(sys.argv[1] + "densenet", x, label, n, net) | |||||
| @@ -0,0 +1,315 @@ | |||||
| # Copyright 2021 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """effnet.""" | |||||
| import numpy as np | |||||
| import mindspore.nn as nn | |||||
| from mindspore.ops import operations as P | |||||
| from mindspore.common.initializer import TruncatedNormal | |||||
| from mindspore import Tensor | |||||
| def weight_variable(): | |||||
| """weight initial""" | |||||
| return TruncatedNormal(0.02) | |||||
| def _make_divisible(v, divisor, min_value=None): | |||||
| """ | |||||
| This function is taken from the original tf repo. | |||||
| It ensures that all layers have a channel number that is divisible by 8 | |||||
| It can be seen here: | |||||
| https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py | |||||
| :param v: | |||||
| :param divisor: | |||||
| iparam min_value: | |||||
| :return: | |||||
| """ | |||||
| if min_value is None: | |||||
| min_value = divisor | |||||
| new_v = max(min_value, int(v + divisor / 2) // divisor * divisor) | |||||
| # Make sure that round down does not go down by more than 10%. | |||||
| if new_v < 0.9 * v: | |||||
| new_v += divisor | |||||
| return new_v | |||||
| class Swish(nn.Cell): | |||||
| def __init__(self): | |||||
| super().__init__() | |||||
| self.sigmoid = nn.Sigmoid() | |||||
| def construct(self, x): | |||||
| s = self.sigmoid(x) | |||||
| m = x*s | |||||
| return m | |||||
| #return x * (1/(1+self.exp(-x))) | |||||
| class AdaptiveAvgPool(nn.Cell): | |||||
| def __init__(self, output_size=None): | |||||
| super().__init__() | |||||
| self.mean = P.ReduceMean(keep_dims=True) | |||||
| self.output_size = output_size | |||||
| def construct(self, x): | |||||
| return self.mean(x, (2, 3)) ## This is not a general case | |||||
| class SELayer(nn.Cell): | |||||
| """SELayer""" | |||||
| def __init__(self, channel, reduction=4): | |||||
| super().__init__() | |||||
| reduced_chs = _make_divisible(channel/reduction, 1) | |||||
| self.avg_pool = AdaptiveAvgPool(output_size=(1, 1)) | |||||
| weight = weight_variable() | |||||
| self.conv_reduce = nn.Conv2d(in_channels=channel, out_channels=reduced_chs, kernel_size=1, has_bias=True, | |||||
| weight_init=weight) | |||||
| self.act1 = Swish() | |||||
| self.conv_expand = nn.Conv2d(in_channels=reduced_chs, out_channels=channel, kernel_size=1, has_bias=True) | |||||
| self.act2 = nn.Sigmoid() | |||||
| def construct(self, x): | |||||
| #b, c, _, _ = x.shape() | |||||
| o = self.avg_pool(x) #.view(b,c) | |||||
| o = self.conv_reduce(o) | |||||
| o = self.act1(o) | |||||
| o = self.conv_expand(o) | |||||
| o = self.act2(o) #.view(b, c, 1,1) | |||||
| return x * o | |||||
| class DepthwiseSeparableConv(nn.Cell): | |||||
| """DepthwiseSeparableConv""" | |||||
| def __init__(self, in_chs, out_chs, dw_kernel_size=3, stride=1, noskip=False, se_ratio=0.0, drop_connect_rate=0.0): | |||||
| super().__init__() | |||||
| assert stride in [1, 2] | |||||
| self.has_residual = (stride == 1 and in_chs == out_chs) and not noskip | |||||
| self.drop_connect_rate = drop_connect_rate | |||||
| self.conv_dw = nn.Conv2d(in_channels=in_chs, out_channels=in_chs, kernel_size=dw_kernel_size, stride=stride, | |||||
| pad_mode="pad", padding=1, has_bias=False, group=in_chs) | |||||
| self.bn1 = nn.BatchNorm2d(in_chs, eps=0.001) #,momentum=0.1) | |||||
| self.act1 = Swish() | |||||
| # Squeeze-and-excitation | |||||
| if se_ratio is not None and se_ratio > 0.: | |||||
| self.se = SELayer(in_chs, reduction=se_ratio) | |||||
| else: | |||||
| print("ERRRRRORRRR -- not prepared for this one\n") | |||||
| self.conv_pw = nn.Conv2d(in_channels=in_chs, out_channels=out_chs, kernel_size=1, stride=stride, has_bias=False) | |||||
| self.bn2 = nn.BatchNorm2d(out_chs, eps=0.001) #,momentum=0.1) | |||||
| def construct(self, x): | |||||
| """construct""" | |||||
| residual = x | |||||
| x = self.conv_dw(x) | |||||
| x = self.bn1(x) | |||||
| x = self.act1(x) | |||||
| x = self.se(x) | |||||
| x = self.conv_pw(x) | |||||
| x = self.bn2(x) | |||||
| if self.has_residual: | |||||
| # if self.drop_connect_rate > 0.: | |||||
| # x = x | |||||
| # x = drop_connect(x, self.training, self.drop_connect_rate) | |||||
| x += residual | |||||
| return x | |||||
| def conv_3x3_bn(inp, oup, stride): | |||||
| weight = weight_variable() | |||||
| return nn.SequentialCell([ | |||||
| nn.Conv2d(in_channels=inp, out_channels=oup, kernel_size=3, stride=stride, padding=1, weight_init=weight, | |||||
| has_bias=False, pad_mode='pad'), | |||||
| nn.BatchNorm2d(oup, eps=0.001), #, momentum=0.1), | |||||
| nn.HSwish()]) | |||||
| def conv_1x1_bn(inp, oup): | |||||
| weight = weight_variable() | |||||
| return nn.SequentialCell([ | |||||
| nn.Conv2d(in_channels=inp, out_channels=oup, kernel_size=1, stride=1, padding=0, weight_init=weight, | |||||
| has_bias=False), | |||||
| nn.BatchNorm2d(oup, eps=0.001), | |||||
| nn.HSwish()]) | |||||
| class InvertedResidual(nn.Cell): | |||||
| """InvertedResidual""" | |||||
| def __init__(self, in_chs, out_chs, kernel_size, stride, padding, expansion, se_ratio): | |||||
| super().__init__() | |||||
| assert stride in [1, 2] | |||||
| mid_chs: int = _make_divisible(in_chs * expansion, 1) | |||||
| self.has_residual = (in_chs == out_chs and stride == 1) | |||||
| self.drop_connect_rate = 0 | |||||
| # Point-wise expansion | |||||
| self.conv_pw = nn.Conv2d(in_channels=in_chs, out_channels=mid_chs, kernel_size=1, stride=1, has_bias=False) | |||||
| self.bn1 = nn.BatchNorm2d(mid_chs, eps=0.001) | |||||
| self.act1 = Swish() | |||||
| # Depth-wise convolution | |||||
| if stride > 1: | |||||
| self.conv_dw = nn.Conv2d(in_channels=mid_chs, out_channels=mid_chs, kernel_size=kernel_size, stride=stride, | |||||
| padding=padding, has_bias=False, group=mid_chs, pad_mode='same') | |||||
| else: | |||||
| self.conv_dw = nn.Conv2d(in_channels=mid_chs, out_channels=mid_chs, kernel_size=kernel_size, stride=stride, | |||||
| padding=padding, has_bias=False, group=mid_chs, pad_mode='pad') | |||||
| self.bn2 = nn.BatchNorm2d(mid_chs, eps=0.001) | |||||
| self.act2 = Swish() | |||||
| # Squeeze-and-excitation | |||||
| if se_ratio is not None and se_ratio > 0.: | |||||
| self.se = SELayer(mid_chs, reduction=se_ratio) | |||||
| else: | |||||
| print("ERRRRRORRRR -- not prepared for this one\n") | |||||
| # Point-wise linear projection | |||||
| self.conv_pwl = nn.Conv2d(in_channels=mid_chs, out_channels=out_chs, kernel_size=1, stride=1, has_bias=False) | |||||
| self.bn3 = nn.BatchNorm2d(out_chs, eps=0.001) | |||||
| def construct(self, x): | |||||
| """construct""" | |||||
| residual = x | |||||
| # Point-wise expansion | |||||
| x = self.conv_pw(x) | |||||
| x = self.bn1(x) | |||||
| x = self.act1(x) | |||||
| # Depth-wise convolution | |||||
| x = self.conv_dw(x) | |||||
| x = self.bn2(x) | |||||
| x = self.act2(x) | |||||
| # Squeeze-and-excitation | |||||
| x = self.se(x) | |||||
| # Point-wise linear projection | |||||
| x = self.conv_pwl(x) | |||||
| x = self.bn3(x) | |||||
| if self.has_residual: | |||||
| # if self.drop_connect_rate > 0.: | |||||
| # x = x | |||||
| x += residual | |||||
| return x | |||||
| class EfficientNet(nn.Cell): | |||||
| """EfficientNet""" | |||||
| def __init__(self, cfgs, num_classes=1000): | |||||
| super().__init__() | |||||
| # setting of inverted residual blocks | |||||
| self.cfgs = cfgs | |||||
| stem_size = 32 | |||||
| self.num_classes_ = num_classes | |||||
| self.num_features_ = 1280 | |||||
| self.conv_stem = nn.Conv2d(in_channels=3, out_channels=stem_size, kernel_size=3, stride=2, has_bias=False) | |||||
| self.bn1 = nn.BatchNorm2d(stem_size, eps=0.001) #momentum=0.1) | |||||
| self.act1 = Swish() | |||||
| in_chs = stem_size | |||||
| layers = [nn.SequentialCell([DepthwiseSeparableConv(in_chs, 16, 3, 1, se_ratio=4)]), | |||||
| nn.SequentialCell([InvertedResidual(16, 24, 3, 2, 0, 6, se_ratio=24), | |||||
| InvertedResidual(24, 24, 3, 1, 1, 6, se_ratio=24)]), | |||||
| nn.SequentialCell([InvertedResidual(24, 40, 5, 2, 0, 6, se_ratio=24), | |||||
| InvertedResidual(40, 40, 5, 1, 2, 6, se_ratio=24)]), | |||||
| nn.SequentialCell([InvertedResidual(40, 80, 3, 2, 0, 6, se_ratio=24), | |||||
| InvertedResidual(80, 80, 3, 1, 1, 6, se_ratio=24), | |||||
| InvertedResidual(80, 80, 3, 1, 1, 6, se_ratio=24)]), | |||||
| nn.SequentialCell([InvertedResidual(80, 112, 5, 1, 2, 6, se_ratio=24), | |||||
| InvertedResidual(112, 112, 5, 1, 2, 6, se_ratio=24), | |||||
| InvertedResidual(112, 112, 5, 1, 2, 6, se_ratio=24)]), | |||||
| nn.SequentialCell([InvertedResidual(112, 192, 5, 2, 0, 6, se_ratio=24), | |||||
| InvertedResidual(192, 192, 5, 1, 2, 6, se_ratio=24), | |||||
| InvertedResidual(192, 192, 5, 1, 2, 6, se_ratio=24), | |||||
| InvertedResidual(192, 192, 5, 1, 2, 6, se_ratio=24)]), | |||||
| nn.SequentialCell([InvertedResidual(192, 320, 3, 1, 1, 6, se_ratio=24)]) | |||||
| ] | |||||
| self.blocks = nn.SequentialCell(layers) | |||||
| self.conv_head = nn.Conv2d(in_channels=320, out_channels=self.num_features_, kernel_size=1) | |||||
| self.bn2 = nn.BatchNorm2d(self.num_features_, eps=0.001) #,momentum=0.1) | |||||
| self.act2 = Swish() | |||||
| self.global_pool = AdaptiveAvgPool(output_size=(1, 1)) | |||||
| self.classifier = nn.Dense(self.num_features_, num_classes) | |||||
| self._initialize_weights() | |||||
| def construct(self, x): | |||||
| """construct""" | |||||
| x = self.conv_stem(x) | |||||
| x = self.bn1(x) | |||||
| x = self.act1(x) | |||||
| x = self.blocks(x) | |||||
| x = self.conv_head(x) | |||||
| x = self.bn2(x) | |||||
| x = self.act2(x) | |||||
| x = self.global_pool(x) | |||||
| x = P.Reshape()(x, (-1, self.num_features_)) | |||||
| x = self.classifier(x) | |||||
| return x | |||||
| def _initialize_weights(self): | |||||
| """_initialize_weights""" | |||||
| def init_linear_weight(m): | |||||
| m.weight.set_data(Tensor(np.random.normal(0, 0.01, m.weight.data.shape).astype("float32"))) | |||||
| if m.bias is not None: | |||||
| m.bias.set_data(Tensor(np.zeros(m.bias.data.shape, dtype="float32"))) | |||||
| for m in self.cells(): | |||||
| if isinstance(m, nn.Conv2d): | |||||
| n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels | |||||
| m.weight.set_data(Tensor(np.random.normal(0, np.sqrt(2. / n), m.weight.data.shape).astype("float32"))) | |||||
| if m.bias is not None: | |||||
| m.bias.data.zero_() | |||||
| m.weight.requires_grad = True | |||||
| elif isinstance(m, nn.BatchNorm2d): | |||||
| m.gamma.set_data(Tensor(np.ones(m.gamma.data.shape, dtype="float32"))) | |||||
| m.beta.set_data(Tensor(np.zeros(m.beta.data.shape, dtype="float32"))) | |||||
| elif isinstance(m, nn.Dense): | |||||
| init_linear_weight(m) | |||||
| def effnet(**kwargs): | |||||
| """ | |||||
| Constructs a EfficientNet model | |||||
| """ | |||||
| cfgs = [ | |||||
| # k, t, c, SE, HS, s | |||||
| [3, 1, 16, 1, 0, 2], | |||||
| [3, 4.5, 24, 0, 0, 2], | |||||
| [3, 3.67, 24, 0, 0, 1], | |||||
| [5, 4, 40, 1, 1, 2], | |||||
| [5, 6, 40, 1, 1, 1], | |||||
| [5, 6, 40, 1, 1, 1], | |||||
| [5, 3, 48, 1, 1, 1], | |||||
| [5, 3, 48, 1, 1, 1], | |||||
| [5, 6, 96, 1, 1, 2], | |||||
| [5, 6, 96, 1, 1, 1], | |||||
| [5, 6, 96, 1, 1, 1], | |||||
| ] | |||||
| return EfficientNet(cfgs, **kwargs) | |||||
| @@ -0,0 +1,38 @@ | |||||
| # Copyright 2020 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """effnet_train_export.""" | |||||
| import sys | |||||
| import numpy as np | |||||
| from train_utils import SaveInOut, TrainWrap | |||||
| from effnet import effnet | |||||
| import mindspore.common.dtype as mstype | |||||
| from mindspore import context, Tensor, nn | |||||
| from mindspore.train.serialization import export | |||||
| context.set_context(mode=context.PYNATIVE_MODE, device_target="GPU", save_graphs=False) | |||||
| n = effnet(num_classes=10) | |||||
| loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False) | |||||
| optimizer = nn.SGD(n.trainable_params(), learning_rate=0.01, momentum=0.9, dampening=0.0, weight_decay=0.0, | |||||
| nesterov=True, loss_scale=1.0) | |||||
| net = TrainWrap(n, loss_fn, optimizer) | |||||
| x = Tensor(np.random.randn(2, 3, 224, 224), mstype.float32) | |||||
| label = Tensor(np.zeros([2, 10]).astype(np.float32)) | |||||
| export(net, x, label, file_name="mindir/effnet_train", file_format='MINDIR') | |||||
| if len(sys.argv) > 1: | |||||
| SaveInOut(sys.argv[1] + "effnet", x, label, n, net) | |||||
| @@ -0,0 +1,83 @@ | |||||
| # Copyright 2021 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """effnet_tune_train_export.""" | |||||
| import sys | |||||
| from os import path | |||||
| import numpy as np | |||||
| from train_utils import TrainWrap, SaveT | |||||
| from effnet import effnet | |||||
| import mindspore.common.dtype as mstype | |||||
| from mindspore import context, Tensor, nn | |||||
| from mindspore.train.serialization import export, load_checkpoint | |||||
| from mindspore.common.parameter import ParameterTuple | |||||
| context.set_context(mode=context.PYNATIVE_MODE, device_target="GPU", save_graphs=False) | |||||
| class TransferNet(nn.Cell): | |||||
| def __init__(self, backbone, head): | |||||
| super().__init__(TransferNet) | |||||
| self.backbone = backbone | |||||
| self.head = head | |||||
| def construct(self, x): | |||||
| x = self.backbone(x) | |||||
| x = self.head(x) | |||||
| return x | |||||
| CHECKPOINT_WEIGHT_FILE = "efficient_net_b0.ckpt" | |||||
| if not path.exists(CHECKPOINT_WEIGHT_FILE): | |||||
| import subprocess | |||||
| print("weight file is missing, downloading from hub") | |||||
| url = "https://download.mindspore.cn/model_zoo/official/lite/efficient_net/" + CHECKPOINT_WEIGHT_FILE | |||||
| subprocess.run(["wget", url], check=True) | |||||
| BACKBONE = effnet(num_classes=1000) | |||||
| load_checkpoint(CHECKPOINT_WEIGHT_FILE, BACKBONE) | |||||
| HEAD = nn.Dense(1000, 10) | |||||
| HEAD.weight.set_data(Tensor(np.random.normal( | |||||
| 0, 0.1, HEAD.weight.data.shape).astype("float32"))) | |||||
| HEAD.bias.set_data(Tensor(np.zeros(HEAD.bias.data.shape, dtype="float32"))) | |||||
| n = TransferNet(BACKBONE, HEAD) | |||||
| trainable_weights_list = [] | |||||
| trainable_weights_list.extend(n.head.trainable_params()) | |||||
| trainable_weights = ParameterTuple(trainable_weights_list) | |||||
| sgd = nn.SGD(trainable_weights, learning_rate=0.01, momentum=0.9, | |||||
| dampening=0.01, weight_decay=0.0, nesterov=False, loss_scale=1.0) | |||||
| net = TrainWrap(n, optimizer=sgd, weights=trainable_weights) | |||||
| BATCH_SIZE = 8 | |||||
| X = Tensor(np.random.randn(BATCH_SIZE, 3, 224, 224), mstype.float32) | |||||
| label = Tensor(np.zeros([BATCH_SIZE, 10]).astype(np.float32)) | |||||
| export(net, X, label, file_name="mindir/effnet_tune_train", file_format='MINDIR') | |||||
| if len(sys.argv) > 1: | |||||
| name_prefix = sys.argv[1] + "effnet_tune" | |||||
| x_name = name_prefix + "_input1.bin" | |||||
| SaveT(Tensor(X.asnumpy().transpose(0, 2, 3, 1)), x_name) | |||||
| l_name = name_prefix + "_input2.bin" | |||||
| SaveT(label, l_name) | |||||
| #train network | |||||
| n.head.set_train(True) | |||||
| n.backbone.set_train(False) | |||||
| net(X, label) | |||||
| #save Y after training | |||||
| n.set_train(False) | |||||
| y = n(X) | |||||
| y_name = name_prefix + "_output1.bin" | |||||
| SaveT(y, y_name) | |||||
| @@ -0,0 +1,39 @@ | |||||
| # Copyright 2021 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """googlenet_train_export.""" | |||||
| import sys | |||||
| import numpy as np | |||||
| from train_utils import SaveInOut, TrainWrap | |||||
| from official.cv.googlenet.src.googlenet import GoogleNet | |||||
| import mindspore.common.dtype as mstype | |||||
| from mindspore import context, Tensor, nn | |||||
| from mindspore.train.serialization import export | |||||
| context.set_context(mode=context.PYNATIVE_MODE, device_target="GPU", save_graphs=False) | |||||
| n = GoogleNet(num_classes=10) | |||||
| loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False) | |||||
| optimizer = nn.SGD(n.trainable_params(), learning_rate=0.01, momentum=0.9, dampening=0.0, weight_decay=5e-4, | |||||
| nesterov=True, loss_scale=0.9) | |||||
| net = TrainWrap(n, loss_fn, optimizer) | |||||
| batch = 2 | |||||
| x = Tensor(np.random.randn(batch, 3, 224, 224), mstype.float32) | |||||
| label = Tensor(np.zeros([batch, 10]).astype(np.float32)) | |||||
| export(net, x, label, file_name="mindir/googlenet_train", file_format='MINDIR') | |||||
| if len(sys.argv) > 1: | |||||
| SaveInOut(sys.argv[1] + "googlenet", x, label, n, net) | |||||
| @@ -0,0 +1,39 @@ | |||||
| # Copyright 2021 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """lenet_train_export.""" | |||||
| import sys | |||||
| import numpy as np | |||||
| from train_utils import SaveInOut, TrainWrap | |||||
| from official.cv.lenet.src.lenet import LeNet5 | |||||
| import mindspore.common.dtype as mstype | |||||
| from mindspore import context, Tensor, nn | |||||
| from mindspore.train.serialization import export | |||||
| context.set_context(mode=context.PYNATIVE_MODE, device_target="GPU", save_graphs=False) | |||||
| n = LeNet5() | |||||
| loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False) | |||||
| loss_fn = nn.MSELoss() | |||||
| optimizer = nn.Adam(n.trainable_params(), learning_rate=1e-2, beta1=0.5, beta2=0.7, eps=1e-2, use_locking=True, | |||||
| use_nesterov=False, weight_decay=0.0, loss_scale=0.3) | |||||
| net = TrainWrap(n, loss_fn, optimizer) | |||||
| x = Tensor(np.random.randn(32, 1, 32, 32), mstype.float32) | |||||
| label = Tensor(np.zeros([32, 10]).astype(np.float32)) | |||||
| export(net, x, label, file_name="mindir/lenet_train", file_format='MINDIR') | |||||
| if len(sys.argv) > 1: | |||||
| SaveInOut(sys.argv[1] + "lenet", x, label, n, net, sparse=False) | |||||
| @@ -0,0 +1,66 @@ | |||||
| # Copyright 2021 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """mini_alexnet.""" | |||||
| import mindspore.nn as nn | |||||
| from mindspore.ops import operations as P | |||||
| def conv(in_channels, out_channels, kernel_size, stride=1, padding=0, pad_mode="valid", has_bias=True): | |||||
| return nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size, stride=stride, padding=padding, | |||||
| has_bias=has_bias, pad_mode=pad_mode) | |||||
| def fc_with_initialize(input_channels, out_channels, has_bias=True): | |||||
| return nn.Dense(input_channels, out_channels, has_bias=has_bias) | |||||
| class AlexNet(nn.Cell): | |||||
| """ | |||||
| Alexnet | |||||
| """ | |||||
| def __init__(self, num_classes=10, channel=1, phase='train', include_top=True): | |||||
| super().__init__() | |||||
| self.conv1 = conv(channel, 12, 11, stride=2, pad_mode="same", has_bias=True) | |||||
| self.conv2 = conv(12, 20, 3, pad_mode="same", has_bias=True) | |||||
| self.relu = P.ReLU() | |||||
| self.max_pool2d = nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='valid') | |||||
| self.include_top = include_top | |||||
| if self.include_top: | |||||
| dropout_ratio = 0.65 | |||||
| if phase == 'test': | |||||
| dropout_ratio = 1.0 | |||||
| self.flatten = nn.Flatten() | |||||
| self.fc1 = fc_with_initialize(20*3*3, 1024) | |||||
| self.fc2 = fc_with_initialize(1024, 1024) | |||||
| self.fc3 = fc_with_initialize(1024, num_classes) | |||||
| self.dropout = nn.Dropout(dropout_ratio) | |||||
| def construct(self, x): | |||||
| """define network""" | |||||
| x = self.conv1(x) | |||||
| x = self.relu(x) | |||||
| x = self.max_pool2d(x) | |||||
| x = self.conv2(x) | |||||
| x = self.relu(x) | |||||
| x = self.max_pool2d(x) | |||||
| if not self.include_top: | |||||
| return x | |||||
| x = self.flatten(x) | |||||
| x = self.fc1(x) | |||||
| x = self.relu(x) | |||||
| x = self.dropout(x) | |||||
| x = self.fc2(x) | |||||
| x = self.relu(x) | |||||
| x = self.dropout(x) | |||||
| x = self.fc3(x) | |||||
| return x | |||||
| @@ -0,0 +1,41 @@ | |||||
| # Copyright 2021 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """mini_alexnet_train_export.""" | |||||
| import sys | |||||
| import numpy as np | |||||
| from train_utils import SaveInOut, TrainWrap | |||||
| from mini_alexnet import AlexNet | |||||
| from mindspore import context, Tensor, nn | |||||
| from mindspore.train.serialization import export | |||||
| context.set_context(mode=context.PYNATIVE_MODE, device_target="GPU", save_graphs=False) | |||||
| # Mini alexnet is designed for MNIST data | |||||
| batch = 2 | |||||
| number_of_classes = 10 | |||||
| n = AlexNet(phase='test') | |||||
| loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False) | |||||
| optimizer = nn.Adam(n.trainable_params(), learning_rate=1e-3, beta1=0.9, beta2=0.999, eps=1e-8, use_locking=False, | |||||
| use_nesterov=False, weight_decay=0.0, loss_scale=1.0) | |||||
| net = TrainWrap(n, loss_fn, optimizer) | |||||
| x = Tensor(np.ones([batch, 1, 32, 32]).astype(np.float32) * 0.01) | |||||
| label = Tensor(np.zeros([batch, number_of_classes]).astype(np.float32)) | |||||
| export(net, x, label, file_name="mindir/mini_alexnet_train", file_format='MINDIR') | |||||
| if len(sys.argv) > 1: | |||||
| SaveInOut(sys.argv[1] + "mini_alexnet", x, label, n, net, sparse=False) | |||||
| @@ -0,0 +1,40 @@ | |||||
| # Copyright 2021 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """mobilenetv1_train_export.""" | |||||
| import sys | |||||
| import numpy as np | |||||
| from train_utils import SaveInOut, TrainWrap | |||||
| from official.cv.mobilenetv1.src.mobilenet_v1 import MobileNetV1 | |||||
| import mindspore.common.dtype as mstype | |||||
| from mindspore import context, Tensor, nn | |||||
| from mindspore.train.serialization import export | |||||
| context.set_context(mode=context.PYNATIVE_MODE, device_target="GPU", save_graphs=False) | |||||
| n = MobileNetV1(10) | |||||
| loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False) | |||||
| optimizer = nn.SGD(n.trainable_params(), learning_rate=1e-2, momentum=0.9, dampening=0.1, weight_decay=0.0, | |||||
| nesterov=False, loss_scale=1.0) | |||||
| net = TrainWrap(n, loss_fn, optimizer) | |||||
| batch = 2 | |||||
| x = Tensor(np.random.randn(batch, 3, 224, 224), mstype.float32) | |||||
| label = Tensor(np.zeros([batch, 10]).astype(np.float32)) | |||||
| export(net, x, label, file_name="mindir/mobilenetv1_train", file_format='MINDIR') | |||||
| if len(sys.argv) > 1: | |||||
| SaveInOut(sys.argv[1] + "mobilenetv1", x, label, n, net) | |||||
| @@ -0,0 +1,42 @@ | |||||
| # Copyright 2021 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """mobilenetv2_train_export.""" | |||||
| import sys | |||||
| import numpy as np | |||||
| from train_utils import SaveInOut, TrainWrap | |||||
| from official.cv.mobilenetv2.src.mobilenetV2 import MobileNetV2Backbone, MobileNetV2Head, mobilenet_v2 | |||||
| import mindspore.common.dtype as mstype | |||||
| from mindspore import context, Tensor, nn | |||||
| from mindspore.train.serialization import export | |||||
| context.set_context(mode=context.PYNATIVE_MODE, device_target="GPU", save_graphs=False) | |||||
| batch = 16 | |||||
| #n = MobileNetV2() | |||||
| backbone_net = MobileNetV2Backbone() | |||||
| head_net = MobileNetV2Head(input_channel=backbone_net.out_channels, num_classes=10) | |||||
| n = mobilenet_v2(backbone_net, head_net) | |||||
| loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False) | |||||
| optimizer = nn.Momentum(n.trainable_params(), 0.01, 0.9, use_nesterov=False) | |||||
| net = TrainWrap(n, loss_fn, optimizer) | |||||
| x = Tensor(np.random.randn(batch, 3, 224, 224), mstype.float32) | |||||
| label = Tensor(np.zeros([batch, 10]).astype(np.float32)) | |||||
| export(net, x, label, file_name="mindir/mobilenetv2_train", file_format='MINDIR') | |||||
| if len(sys.argv) > 1: | |||||
| SaveInOut(sys.argv[1] + "mobilenetv2", x, label, n, net, sparse=False) | |||||
| @@ -0,0 +1,39 @@ | |||||
| # Copyright 2020 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """mobilenetv3_train_export.""" | |||||
| import sys | |||||
| import numpy as np | |||||
| from train_utils import SaveInOut, TrainWrap | |||||
| from official.cv.mobilenetv3.src.mobilenetV3 import mobilenet_v3_small | |||||
| import mindspore.common.dtype as mstype | |||||
| from mindspore import context, Tensor, nn | |||||
| from mindspore.train.serialization import export | |||||
| context.set_context(mode=context.PYNATIVE_MODE, device_target="GPU", save_graphs=False) | |||||
| n = mobilenet_v3_small(num_classes=10) | |||||
| loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False, reduction='mean') | |||||
| optimizer = nn.Adam(n.trainable_params(), learning_rate=1e-2, beta1=0.5, beta2=0.7, eps=1e-2, use_locking=True, | |||||
| use_nesterov=False, weight_decay=0.1, loss_scale=0.3) | |||||
| net = TrainWrap(n, loss_fn, optimizer) | |||||
| batch = 2 | |||||
| x = Tensor(np.random.randn(batch, 3, 224, 224), mstype.float32) | |||||
| label = Tensor(np.zeros([batch, 10]).astype(np.float32)) | |||||
| export(net, x, label, file_name="mindir/mobilenetv3_train", file_format='MINDIR') | |||||
| if len(sys.argv) > 1: | |||||
| SaveInOut(sys.argv[1] + "mobilenetv3", x, label, n, net, sparse=False) | |||||
| @@ -0,0 +1,39 @@ | |||||
| # Copyright 2021 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """nin_train_export.""" | |||||
| import sys | |||||
| import numpy as np | |||||
| from train_utils import SaveInOut, TrainWrap | |||||
| from NetworkInNetwork import NiN | |||||
| import mindspore.common.dtype as mstype | |||||
| from mindspore import context, Tensor, nn | |||||
| from mindspore.train.serialization import export | |||||
| context.set_context(mode=context.PYNATIVE_MODE, device_target="GPU", save_graphs=False) | |||||
| n = NiN(num_classes=10) | |||||
| loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False) | |||||
| optimizer = nn.SGD(n.trainable_params(), learning_rate=0.01, momentum=0.9, dampening=0.0, weight_decay=5e-4, | |||||
| nesterov=True, loss_scale=0.9) | |||||
| net = TrainWrap(n, loss_fn, optimizer) | |||||
| batch = 2 | |||||
| x = Tensor(np.random.randn(batch, 3, 32, 32), mstype.float32) | |||||
| label = Tensor(np.zeros([batch, 10]).astype(np.float32)) | |||||
| export(net, x, label, file_name="mindir/nin_train", file_format='MINDIR') | |||||
| if len(sys.argv) > 1: | |||||
| SaveInOut(sys.argv[1] + "nin", x, label, n, net) | |||||
| @@ -0,0 +1,39 @@ | |||||
| # Copyright 2020 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """mobilenetv2_train_export.""" | |||||
| import sys | |||||
| import numpy as np | |||||
| from train_utils import SaveInOut, TrainWrap | |||||
| from official.cv.resnet.src.resnet import resnet50 | |||||
| import mindspore.common.dtype as mstype | |||||
| from mindspore import context, Tensor, nn | |||||
| from mindspore.train.serialization import export | |||||
| context.set_context(mode=context.PYNATIVE_MODE, device_target="GPU", save_graphs=False) | |||||
| batch = 4 | |||||
| n = resnet50(class_num=10) | |||||
| loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False) | |||||
| optimizer = nn.SGD(n.trainable_params(), learning_rate=0.01, momentum=0.9, dampening=0.0, weight_decay=0.0, | |||||
| nesterov=True, loss_scale=1.0) | |||||
| net = TrainWrap(n, loss_fn, optimizer) | |||||
| x = Tensor(np.random.randn(batch, 3, 224, 224), mstype.float32) | |||||
| label = Tensor(np.zeros([batch, 10]).astype(np.float32)) | |||||
| export(net, x, label, file_name="mindir/resnet_train", file_format='MINDIR') | |||||
| if len(sys.argv) > 1: | |||||
| SaveInOut(sys.argv[1] + "resnet", x, label, n, net) | |||||
| @@ -0,0 +1,39 @@ | |||||
| # Copyright 2021 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """shufflenetv2_train_export.""" | |||||
| import sys | |||||
| import numpy as np | |||||
| from train_utils import SaveInOut, TrainWrap | |||||
| from official.cv.shufflenetv2.src.shufflenetv2 import ShuffleNetV2 | |||||
| import mindspore.common.dtype as mstype | |||||
| from mindspore import context, Tensor, nn | |||||
| from mindspore.train.serialization import export | |||||
| context.set_context(mode=context.PYNATIVE_MODE, device_target="GPU", save_graphs=False) | |||||
| n = ShuffleNetV2(n_class=10) | |||||
| loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False) | |||||
| optimizer = nn.Momentum(n.trainable_params(), 0.01, 0.9, use_nesterov=False) | |||||
| net = TrainWrap(n, loss_fn, optimizer) | |||||
| batch = 2 | |||||
| x = Tensor(np.random.randn(batch, 3, 224, 224), mstype.float32) | |||||
| label = Tensor(np.zeros([batch, 10]).astype(np.float32)) | |||||
| export(net, x, label, file_name="mindir/shufflenetv2_train", file_format='MINDIR') | |||||
| if len(sys.argv) > 1: | |||||
| SaveInOut(sys.argv[1] + "shufflenetv2", x, label, n, net) | |||||
| @@ -0,0 +1,71 @@ | |||||
| # Copyright 2021 Huawei Technologies Co., Ltd | |||||
| # | |||||
| # 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. | |||||
| # ============================================================================ | |||||
| """train_utils.""" | |||||
| from mindspore import nn, Tensor | |||||
| from mindspore.common.parameter import ParameterTuple | |||||
| def TrainWrap(net, loss_fn=None, optimizer=None, weights=None): | |||||
| """TrainWrap""" | |||||
| if loss_fn is None: | |||||
| loss_fn = nn.SoftmaxCrossEntropyWithLogits() | |||||
| loss_net = nn.WithLossCell(net, loss_fn) | |||||
| loss_net.set_train() | |||||
| if weights is None: | |||||
| weights = ParameterTuple(net.trainable_params()) | |||||
| if optimizer is None: | |||||
| optimizer = nn.Adam(weights, learning_rate=1e-3, beta1=0.9, beta2=0.999, eps=1e-8, use_locking=False, | |||||
| use_nesterov=False, weight_decay=0.0, loss_scale=1.0) | |||||
| train_net = nn.TrainOneStepCell(loss_net, optimizer) | |||||
| return train_net | |||||
| def SaveT(t, file): | |||||
| x = t.asnumpy() | |||||
| x.tofile(file) | |||||
| def SaveInOut(name, x, l, net, net_train, sparse=False, epoch=1): | |||||
| """SaveInOut""" | |||||
| x_name = name + "_input1.bin" | |||||
| if sparse: | |||||
| x_name = name + "_input2.bin" | |||||
| SaveT(Tensor(x.asnumpy().transpose(0, 2, 3, 1)), x_name) | |||||
| l_name = name + "_input2.bin" | |||||
| if sparse: | |||||
| l_name = name + "_input1.bin" | |||||
| SaveT(l, l_name) | |||||
| net.set_train(False) | |||||
| y = net(x) | |||||
| #train network | |||||
| net.set_train(True) | |||||
| for i in range(epoch): | |||||
| net_train(x, l) | |||||
| net.set_train(False) | |||||
| y = net(x) | |||||
| if isinstance(y, tuple): | |||||
| i = 1 | |||||
| for t in y: | |||||
| with open(name + "_output" + str(i) + ".bin", 'w') as f: | |||||
| for j in t.asnumpy().flatten(): | |||||
| f.write(str(j)+' ') | |||||
| i = i + 1 | |||||
| else: | |||||
| y_name = name + "_output1.bin" | |||||
| SaveT(y, y_name) | |||||
| @@ -0,0 +1,12 @@ | |||||
| mini_alexnet | |||||
| mobilenetv1 | |||||
| mobilenetv2 | |||||
| mobilenetv3 | |||||
| lenet | |||||
| effnet | |||||
| effnet_tune | |||||
| resnet | |||||
| googlenet | |||||
| nin | |||||
| #shufflenetv2 | |||||
| #densenet | |||||
| @@ -0,0 +1,97 @@ | |||||
| #!/bin/bash | |||||
| display_usage() | |||||
| { | |||||
| echo "Usage: prepare.sh [-d mindspore_docker] [-r release.tar.gz] [-i]" | |||||
| echo "Options:" | |||||
| echo " -d docker where mindspore is installed. If no docker is provided script will use local python" | |||||
| echo " -r release tarball" | |||||
| echo " -i create input and output files" | |||||
| } | |||||
| checkopts() | |||||
| { | |||||
| DOCKER="" | |||||
| TRAIN_IO="" | |||||
| while getopts 'd:r:i' opt | |||||
| do | |||||
| case "${opt}" in | |||||
| d) | |||||
| DOCKER=$OPTARG | |||||
| ;; | |||||
| r) | |||||
| TARBALL=$OPTARG | |||||
| ;; | |||||
| i) | |||||
| TRAIN_IO="train_io/" | |||||
| ;; | |||||
| *) | |||||
| echo "Unknown option ${opt}!" | |||||
| display_usage | |||||
| exit 1 | |||||
| esac | |||||
| done | |||||
| } | |||||
| function MS_PRINT_TESTCASE_END_MSG() { | |||||
| echo -e "-----------------------------------------------------------------------------------------------------------------------------------" | |||||
| } | |||||
| function Print_Result() { | |||||
| MS_PRINT_TESTCASE_END_MSG | |||||
| while read line; do | |||||
| arr=("${line}") | |||||
| if [ ! -z "${arr[0]}" ]; then | |||||
| printf "%-8s %-10s %-40s %-7s\n" ${arr[0]} ${arr[1]} ${arr[2]} ${arr[3]} | |||||
| fi | |||||
| done < $1 | |||||
| MS_PRINT_TESTCASE_END_MSG | |||||
| } | |||||
| export_result_file=export_result.txt | |||||
| echo ' ' > ${export_result_file} | |||||
| CLOUD_MODEL_ZOO=../../../../model_zoo/ | |||||
| checkopts "$@" | |||||
| if [ "$TARBALL" == "" ]; then | |||||
| file=$(ls ../../../../output/mindspore-lite-*-train-linux-x64.tar.gz) | |||||
| if [ -f ${file} ]; then | |||||
| TARBALL=${file} | |||||
| else | |||||
| echo "release.tar.gz was not found" | |||||
| display_usage | |||||
| exit 1 | |||||
| fi | |||||
| fi | |||||
| if [ -z "${DOCKER}" ]; then | |||||
| echo "MindSpore docker was not provided, attempting to run locally" | |||||
| fi | |||||
| mkdir -p mindir | |||||
| if [ ! -z "${TRAIN_IO}" ]; then | |||||
| mkdir -p ${TRAIN_IO} | |||||
| fi | |||||
| while read line; do | |||||
| model_name=${line} | |||||
| if [[ $model_name == \#* ]]; then | |||||
| continue | |||||
| fi | |||||
| echo 'exporting' ${model_name} | |||||
| if [ ! -z "${DOCKER}" ]; then | |||||
| docker run -w $PWD --runtime=nvidia -v /home/$USER:/home/$USER --privileged=true ${DOCKER} /bin/bash -c "PYTHONPATH=${CLOUD_MODEL_ZOO} python models/${model_name}_train_export.py ${TRAIN_IO} && chmod 444 mindir/${model_name}_train.mindir" | |||||
| else | |||||
| PYTHONPATH=${CLOUD_MODEL_ZOO} python models/${model_name}_train_export.py ${TRAIN_IO} | |||||
| fi | |||||
| if [ $? = 0 ]; then | |||||
| export_result='export mindspore '${model_name}'_train_export pass';echo ${export_result} >> ${export_result_file} | |||||
| else | |||||
| export_result='export mindspore '${model_name}'_train_export failed';echo ${export_result} >> ${export_result_file} | |||||
| fi | |||||
| done < models_train.cfg | |||||
| Print_Result ${export_result_file} | |||||
| rm ${export_result_file} | |||||
| @@ -0,0 +1,4 @@ | |||||
| *.mindir | |||||
| *.ms | |||||
| msl | |||||
| package-* | |||||
| @@ -1,14 +1,17 @@ | |||||
| BASE_DIR=$(realpath ../../../../) | BASE_DIR=$(realpath ../../../../) | ||||
| APP:=bin/net_runner | APP:=bin/net_runner | ||||
| MSLIB:=mindspore-lite | MSLIB:=mindspore-lite | ||||
| LMDLIB:=-lminddata-lite -ljpeg | |||||
| LHIAILIB:=-lhiai_ir_build -lhiai_ir -lhiai | |||||
| MSDIR:=$(realpath package-$(TARGET)/lib) | MSDIR:=$(realpath package-$(TARGET)/lib) | ||||
| SRC:=src/net_runner.cc src/dataset.cc src/data_callbacks.cc | |||||
| SRC:=src/net_runner.cc | |||||
| OBJ:=$(SRC:.cc=.o) | OBJ:=$(SRC:.cc=.o) | ||||
| CFLAGS := -Ofast -std=c++17 \ | CFLAGS := -Ofast -std=c++17 \ | ||||
| -I . \ | -I . \ | ||||
| -I ./msl \ | -I ./msl \ | ||||
| -I ./msl/minddata \ | |||||
| -I ./msl/third_party/flatbuffers/include | -I ./msl/third_party/flatbuffers/include | ||||
| @@ -16,10 +19,10 @@ ifeq ($(TARGET),arm64) | |||||
| CXX := ${ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ | CXX := ${ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ | ||||
| CFLAGS += --target=aarch64-none-linux-android21 --gcc-toolchain=${ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=${ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fdata-sections -ffunction-sections | CFLAGS += --target=aarch64-none-linux-android21 --gcc-toolchain=${ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=${ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fdata-sections -ffunction-sections | ||||
| LDFLAGS := --target=aarch64-none-linux-android21 --gcc-toolchain=${ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=${ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64/sysroot -Wl,--gc-sections | LDFLAGS := --target=aarch64-none-linux-android21 --gcc-toolchain=${ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=${ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64/sysroot -Wl,--gc-sections | ||||
| LDFLAGS += -L$(MSDIR) -l$(MSLIB) -pthread -llog -latomic -lm | |||||
| LDFLAGS += -L$(MSDIR) -l$(MSLIB) $(LMDLIB) -pthread -llog -latomic -lm $(LHIAILIB) | |||||
| else | else | ||||
| CFLAGS += -g | CFLAGS += -g | ||||
| LDFLAGS := -L$(MSDIR) -l$(MSLIB) -lpthread -Wl,-rpath,$(MSDIR) | |||||
| LDFLAGS := -L$(MSDIR) -l$(MSLIB) $(LMDLIB) -lpthread -Wl,-rpath,$(MSDIR) | |||||
| endif | endif | ||||
| LD := ${CXX} | LD := ${CXX} | ||||
| @@ -21,14 +21,13 @@ from mindspore.train.serialization import export | |||||
| from lenet import LeNet5 | from lenet import LeNet5 | ||||
| from train_utils import TrainWrap | from train_utils import TrainWrap | ||||
| n = LeNet5() | n = LeNet5() | ||||
| n.set_train() | n.set_train() | ||||
| context.set_context(mode=context.PYNATIVE_MODE, device_target="CPU", save_graphs=False) | |||||
| context.set_context(mode=context.PYNATIVE_MODE, device_target="GPU", save_graphs=False) | |||||
| BATCH_SIZE = 32 | BATCH_SIZE = 32 | ||||
| x = Tensor(np.ones((BATCH_SIZE, 1, 32, 32)), mstype.float32) | x = Tensor(np.ones((BATCH_SIZE, 1, 32, 32)), mstype.float32) | ||||
| label = Tensor(np.zeros([BATCH_SIZE, 10]).astype(np.float32)) | |||||
| label = Tensor(np.zeros([BATCH_SIZE]).astype(np.int32)) | |||||
| net = TrainWrap(n) | net = TrainWrap(n) | ||||
| export(net, x, label, file_name="lenet_tod", file_format='MINDIR') | export(net, x, label, file_name="lenet_tod", file_format='MINDIR') | ||||
| @@ -22,7 +22,7 @@ def TrainWrap(net, loss_fn=None, optimizer=None, weights=None): | |||||
| TrainWrap | TrainWrap | ||||
| """ | """ | ||||
| if loss_fn is None: | if loss_fn is None: | ||||
| loss_fn = nn.SoftmaxCrossEntropyWithLogits(reduction='mean') | |||||
| loss_fn = nn.SoftmaxCrossEntropyWithLogits(reduction='mean', sparse=True) | |||||
| loss_net = nn.WithLossCell(net, loss_fn) | loss_net = nn.WithLossCell(net, loss_fn) | ||||
| loss_net.set_train() | loss_net.set_train() | ||||
| if weights is None: | if weights is None: | ||||
| @@ -79,9 +79,15 @@ cp model/*.ms ${PACKAGE}/model || exit 1 | |||||
| cp scripts/*.sh ${PACKAGE}/ | cp scripts/*.sh ${PACKAGE}/ | ||||
| # Copy the shared MindSpore ToD library | # Copy the shared MindSpore ToD library | ||||
| tar -xzf ${TARBALL} --wildcards --no-anchored libmindspore-lite.so | |||||
| tar -xzf ${TARBALL} --wildcards --no-anchored include | |||||
| tar -xzf ${TARBALL} | |||||
| mv mindspore-*/lib ${PACKAGE}/ | mv mindspore-*/lib ${PACKAGE}/ | ||||
| mv mindspore-*/minddata/lib/* ${PACKAGE}/lib/ | |||||
| mv mindspore-*/minddata/third_party/libjpeg-turbo/lib/* ${PACKAGE}/lib/ | |||||
| if [ "${TARGET}" == "arm64" ]; then | |||||
| tar -xzf ${TARBALL} --wildcards --no-anchored hiai_ddk | |||||
| mv mindspore-*/third_party/hiai_ddk/lib/* ${PACKAGE}/lib/ | |||||
| fi | |||||
| rm -rf msl | rm -rf msl | ||||
| mkdir msl | mkdir msl | ||||
| mv mindspore-*/* msl/ | mv mindspore-*/* msl/ | ||||
| @@ -15,4 +15,4 @@ | |||||
| # ============================================================================ | # ============================================================================ | ||||
| # an simple tutorial as follows, more parameters can be setting | # an simple tutorial as follows, more parameters can be setting | ||||
| LD_LIBRARY_PATH=./lib/ bin/net_runner -f model/lenet_tod_trained_3000.ms -e 0 -d dataset | |||||
| LD_LIBRARY_PATH=./lib/ bin/net_runner -f model/lenet_tod_trained.ms -e 0 -d dataset | |||||
| @@ -15,4 +15,4 @@ | |||||
| # ============================================================================ | # ============================================================================ | ||||
| # an simple tutorial as follows, more parameters can be setting | # an simple tutorial as follows, more parameters can be setting | ||||
| LD_LIBRARY_PATH=./lib/ bin/net_runner -f model/lenet_tod.ms -e 3000 -d dataset | |||||
| LD_LIBRARY_PATH=./lib/ bin/net_runner -f model/lenet_tod.ms -e 3 -d dataset | |||||
| @@ -1,103 +0,0 @@ | |||||
| /** | |||||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * 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 <math.h> | |||||
| #include <getopt.h> | |||||
| #include <cstring> | |||||
| #include <iostream> | |||||
| #include <fstream> | |||||
| #include <utility> | |||||
| #include "src/net_runner.h" | |||||
| #include "include/context.h" | |||||
| #include "src/utils.h" | |||||
| #include "src/data_loader.h" | |||||
| #include "src/accuracy_monitor.h" | |||||
| static unsigned int seed = time(NULL); | |||||
| std::vector<int> FillInputDataUtil(const mindspore::session::TrainLoopCallBackData &cb_data, | |||||
| const std::vector<DataLabelTuple> &dataset, bool serially) { | |||||
| static unsigned int idx = 1; | |||||
| int total_size = dataset.size(); | |||||
| std::vector<int> labels_vec; | |||||
| auto inputs = cb_data.session_->GetInputs(); | |||||
| char *input_data = reinterpret_cast<char *>(inputs.at(0)->MutableData()); | |||||
| auto labels = reinterpret_cast<float *>(inputs.at(1)->MutableData()); | |||||
| int batch_size = inputs.at(0)->shape()[0]; | |||||
| int num_of_classes = inputs.at(1)->shape()[1]; | |||||
| int data_size = inputs.at(0)->Size() / batch_size; | |||||
| MS_ASSERT(total_size > 0); | |||||
| MS_ASSERT(input_data != nullptr); | |||||
| std::fill(labels, labels + inputs.at(1)->ElementsNum(), 0.f); | |||||
| for (int i = 0; i < batch_size; i++) { | |||||
| if (serially) { | |||||
| idx = ++idx % total_size; | |||||
| } else { | |||||
| idx = rand_r(&seed) % total_size; | |||||
| } | |||||
| int label = 0; | |||||
| char *data = nullptr; | |||||
| std::tie(data, label) = dataset[idx]; | |||||
| std::copy(data, data + data_size, input_data + i * data_size); | |||||
| labels[i * num_of_classes + label] = 1.0; // Model expects labels in onehot representation | |||||
| labels_vec.push_back(label); | |||||
| } | |||||
| return labels_vec; | |||||
| } | |||||
| void DataLoader::StepBegin(const mindspore::session::TrainLoopCallBackData &cb_data) { | |||||
| FillInputDataUtil(cb_data, ds_->train_data(), false); | |||||
| } | |||||
| int AccuracyMonitor::EpochEnd(const mindspore::session::TrainLoopCallBackData &cb_data) { | |||||
| if ((cb_data.epoch_ + 1) % check_every_n_ != 0) return mindspore::session::RET_CONTINUE; | |||||
| float accuracy = 0.0; | |||||
| auto inputs = cb_data.session_->GetInputs(); | |||||
| int batch_size = inputs.at(0)->shape()[0]; | |||||
| int num_of_classes = ds_->num_of_classes(); | |||||
| int tests = ds_->test_data().size() / batch_size; | |||||
| if (max_steps_ != -1 && tests > max_steps_) tests = max_steps_; | |||||
| cb_data.session_->Eval(); | |||||
| for (int i = 0; i < tests; i++) { | |||||
| auto labels = FillInputDataUtil(cb_data, ds_->test_data(), false); | |||||
| cb_data.session_->RunGraph(); | |||||
| auto outputs = cb_data.session_->GetPredictions(); | |||||
| for (auto it = outputs.begin(); it != outputs.end(); ++it) { | |||||
| if (it->second->ElementsNum() == batch_size * num_of_classes) { | |||||
| auto scores = reinterpret_cast<float *>(it->second->MutableData()); | |||||
| for (int b = 0; b < batch_size; b++) { | |||||
| int max_idx = 0; | |||||
| float max_score = scores[num_of_classes * b]; | |||||
| for (int c = 1; c < num_of_classes; c++) { | |||||
| if (scores[num_of_classes * b + c] > max_score) { | |||||
| max_score = scores[num_of_classes * b + c]; | |||||
| max_idx = c; | |||||
| } | |||||
| } | |||||
| if (labels[b] == max_idx) accuracy += 1.0; | |||||
| } | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| accuracy /= static_cast<float>(batch_size * tests); | |||||
| accuracies_.push_back(std::make_pair(cb_data.epoch_, accuracy)); | |||||
| std::cout << cb_data.epoch_ + 1 << ":\tAccuracy is " << accuracy << std::endl; | |||||
| cb_data.session_->Train(); | |||||
| return mindspore::session::RET_CONTINUE; | |||||
| } | |||||
| @@ -1,150 +0,0 @@ | |||||
| /** | |||||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * 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 "src/dataset.h" | |||||
| #include <arpa/inet.h> | |||||
| #include <map> | |||||
| #include <iostream> | |||||
| #include <fstream> | |||||
| #include <memory> | |||||
| #include "src/utils.h" | |||||
| using LabelId = std::map<std::string, int>; | |||||
| char *ReadFile(const std::string &file, size_t *size) { | |||||
| MS_ASSERT(size != nullptr); | |||||
| std::string realPath(file); | |||||
| std::ifstream ifs(realPath); | |||||
| if (!ifs.good()) { | |||||
| std::cerr << "file: " << realPath << " does not exist"; | |||||
| return nullptr; | |||||
| } | |||||
| if (!ifs.is_open()) { | |||||
| std::cerr << "file: " << realPath << " open failed"; | |||||
| return nullptr; | |||||
| } | |||||
| ifs.seekg(0, std::ios::end); | |||||
| *size = ifs.tellg(); | |||||
| std::unique_ptr<char[]> buf(new (std::nothrow) char[*size]); | |||||
| if (buf == nullptr) { | |||||
| std::cerr << "malloc buf failed, file: " << realPath; | |||||
| ifs.close(); | |||||
| return nullptr; | |||||
| } | |||||
| ifs.seekg(0, std::ios::beg); | |||||
| ifs.read(buf.get(), *size); | |||||
| ifs.close(); | |||||
| return buf.release(); | |||||
| } | |||||
| DataSet::~DataSet() { | |||||
| for (auto itr = train_data_.begin(); itr != train_data_.end(); ++itr) { | |||||
| auto ptr = std::get<0>(*itr); | |||||
| delete[] ptr; | |||||
| } | |||||
| for (auto itr = test_data_.begin(); itr != test_data_.end(); ++itr) { | |||||
| auto ptr = std::get<0>(*itr); | |||||
| delete[] ptr; | |||||
| } | |||||
| } | |||||
| int DataSet::Init(const std::string &data_base_directory, database_type type) { | |||||
| InitializeMNISTDatabase(data_base_directory); | |||||
| return 0; | |||||
| } | |||||
| void DataSet::InitializeMNISTDatabase(std::string dpath) { | |||||
| num_of_classes_ = 10; | |||||
| ReadMNISTFile(dpath + "/train/train-images-idx3-ubyte", dpath + "/train/train-labels-idx1-ubyte", &train_data_); | |||||
| ReadMNISTFile(dpath + "/test/t10k-images-idx3-ubyte", dpath + "/test/t10k-labels-idx1-ubyte", &test_data_); | |||||
| } | |||||
| int DataSet::ReadMNISTFile(const std::string &ifile_name, const std::string &lfile_name, | |||||
| std::vector<DataLabelTuple> *dataset) { | |||||
| std::ifstream lfile(lfile_name, std::ios::binary); | |||||
| if (!lfile.is_open()) { | |||||
| std::cerr << "Cannot open label file " << lfile_name << std::endl; | |||||
| return 0; | |||||
| } | |||||
| std::ifstream ifile(ifile_name, std::ios::binary); | |||||
| if (!ifile.is_open()) { | |||||
| std::cerr << "Cannot open data file " << ifile_name << std::endl; | |||||
| return 0; | |||||
| } | |||||
| int magic_number = 0; | |||||
| lfile.read(reinterpret_cast<char *>(&magic_number), sizeof(magic_number)); | |||||
| magic_number = ntohl(magic_number); | |||||
| if (magic_number != 2049) { | |||||
| std::cout << "Invalid MNIST label file!" << std::endl; | |||||
| return 0; | |||||
| } | |||||
| int number_of_labels = 0; | |||||
| lfile.read(reinterpret_cast<char *>(&number_of_labels), sizeof(number_of_labels)); | |||||
| number_of_labels = ntohl(number_of_labels); | |||||
| ifile.read(reinterpret_cast<char *>(&magic_number), sizeof(magic_number)); | |||||
| magic_number = ntohl(magic_number); | |||||
| if (magic_number != 2051) { | |||||
| std::cout << "Invalid MNIST image file!" << std::endl; | |||||
| return 0; | |||||
| } | |||||
| int number_of_images = 0; | |||||
| ifile.read(reinterpret_cast<char *>(&number_of_images), sizeof(number_of_images)); | |||||
| number_of_images = ntohl(number_of_images); | |||||
| int n_rows = 0; | |||||
| ifile.read(reinterpret_cast<char *>(&n_rows), sizeof(n_rows)); | |||||
| n_rows = ntohl(n_rows); | |||||
| int n_cols = 0; | |||||
| ifile.read(reinterpret_cast<char *>(&n_cols), sizeof(n_cols)); | |||||
| n_cols = ntohl(n_cols); | |||||
| if (number_of_labels != number_of_images) { | |||||
| std::cout << "number of records in labels and images files does not match" << std::endl; | |||||
| return 0; | |||||
| } | |||||
| int image_size = n_rows * n_cols; | |||||
| unsigned char labels[number_of_labels]; | |||||
| unsigned char data[image_size]; | |||||
| lfile.read(reinterpret_cast<char *>(labels), number_of_labels); | |||||
| for (int i = 0; i < number_of_labels; ++i) { | |||||
| std::unique_ptr<float[]> hwc_bin_image(new (std::nothrow) float[32 * 32]); | |||||
| ifile.read(reinterpret_cast<char *>(data), image_size); | |||||
| for (size_t r = 0; r < 32; r++) { | |||||
| for (size_t c = 0; c < 32; c++) { | |||||
| if (r < 2 || r > 29 || c < 2 || c > 29) | |||||
| hwc_bin_image[r * 32 + c] = 0.0; | |||||
| else | |||||
| hwc_bin_image[r * 32 + c] = (static_cast<float>(data[(r - 2) * 28 + (c - 2)])) / 255.0; | |||||
| } | |||||
| } | |||||
| DataLabelTuple data_entry = std::make_tuple(reinterpret_cast<char *>(hwc_bin_image.release()), labels[i]); | |||||
| dataset->push_back(data_entry); | |||||
| } | |||||
| return number_of_labels; | |||||
| } | |||||
| @@ -1,54 +0,0 @@ | |||||
| /** | |||||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * 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. | |||||
| */ | |||||
| #ifndef MINDSPORE_LITE_EXAMPLES_TRAIN_LENET_SRC_DATASET_H_ | |||||
| #define MINDSPORE_LITE_EXAMPLES_TRAIN_LENET_SRC_DATASET_H_ | |||||
| #include <tuple> | |||||
| #include <string> | |||||
| #include <vector> | |||||
| using DataLabelTuple = std::tuple<char *, int>; | |||||
| using FileTuple = std::tuple<int, std::string>; | |||||
| enum database_type { DS_CIFAR10_BINARY = 0, DS_MNIST_BINARY, DS_OTHER }; | |||||
| char *ReadFile(const std::string &file, size_t *size); // utility function | |||||
| class DataSet { | |||||
| public: | |||||
| DataSet() {} | |||||
| ~DataSet(); | |||||
| int Init(const std::string &data_base_directory, database_type type = DS_OTHER); | |||||
| const std::vector<DataLabelTuple> &train_data() const { return train_data_; } | |||||
| const std::vector<DataLabelTuple> &test_data() const { return test_data_; } | |||||
| unsigned int num_of_classes() { return num_of_classes_; } | |||||
| void set_expected_data_size(unsigned int expected_data_size) { expected_data_size_ = expected_data_size; } | |||||
| unsigned int expected_data_size() { return expected_data_size_; } | |||||
| private: | |||||
| int ReadMNISTFile(const std::string &ifile, const std::string &lfile, std::vector<DataLabelTuple> *dataset); | |||||
| void InitializeMNISTDatabase(std::string dpath); | |||||
| std::vector<DataLabelTuple> train_data_; | |||||
| std::vector<DataLabelTuple> test_data_; | |||||
| unsigned int num_of_classes_ = 0; | |||||
| unsigned int expected_data_size_ = 0; | |||||
| }; | |||||
| #endif // MINDSPORE_LITE_EXAMPLES_TRAIN_LENET_SRC_DATASET_H_ | |||||
| @@ -25,17 +25,37 @@ | |||||
| #include "include/train/loss_monitor.h" | #include "include/train/loss_monitor.h" | ||||
| #include "include/train/ckpt_saver.h" | #include "include/train/ckpt_saver.h" | ||||
| #include "include/train/lr_scheduler.h" | #include "include/train/lr_scheduler.h" | ||||
| #include "include/train/accuracy_metrics.h" | |||||
| #include "include/train/classification_train_accuracy_monitor.h" | #include "include/train/classification_train_accuracy_monitor.h" | ||||
| #include "src/utils.h" | #include "src/utils.h" | ||||
| #include "src/data_loader.h" | |||||
| #include "src/accuracy_monitor.h" | |||||
| #include "include/datasets.h" | |||||
| #include "include/vision_lite.h" | |||||
| #include "include/transforms.h" | |||||
| using mindspore::dataset::Dataset; | |||||
| using mindspore::dataset::Mnist; | |||||
| using mindspore::dataset::TensorOperation; | |||||
| using mindspore::dataset::vision::Normalize; | |||||
| using mindspore::lite::AccuracyMetrics; | |||||
| using mindspore::session::TrainLoopCallBack; | using mindspore::session::TrainLoopCallBack; | ||||
| using mindspore::session::TrainLoopCallBackData; | using mindspore::session::TrainLoopCallBackData; | ||||
| static unsigned int seed = time(NULL); | |||||
| class Rescaler : public mindspore::session::TrainLoopCallBack { | |||||
| public: | |||||
| explicit Rescaler(float scale) : scale_(scale) { | |||||
| if (scale_ == 0) scale_ = 1.0; | |||||
| } | |||||
| void StepBegin(const mindspore::session::TrainLoopCallBackData &cb_data) override { | |||||
| auto inputs = cb_data.session_->GetInputs(); | |||||
| auto *input_data = reinterpret_cast<float *>(inputs.at(0)->MutableData()); | |||||
| for (int k = 0; k < inputs.at(0)->ElementsNum(); k++) input_data[k] /= scale_; | |||||
| } | |||||
| // Definition of callback function after forwarding operator. | |||||
| private: | |||||
| float scale_ = 1.0; | |||||
| }; | |||||
| // Definition of verbose callback function after forwarding operator. | |||||
| bool after_callback(const std::vector<mindspore::tensor::MSTensor *> &after_inputs, | bool after_callback(const std::vector<mindspore::tensor::MSTensor *> &after_inputs, | ||||
| const std::vector<mindspore::tensor::MSTensor *> &after_outputs, | const std::vector<mindspore::tensor::MSTensor *> &after_outputs, | ||||
| const mindspore::CallBackParam &call_param) { | const mindspore::CallBackParam &call_param) { | ||||
| @@ -79,46 +99,68 @@ void NetRunner::InitAndFigureInputs() { | |||||
| session_ = loop_->train_session(); | session_ = loop_->train_session(); | ||||
| MS_ASSERT(nullptr != session_); | MS_ASSERT(nullptr != session_); | ||||
| acc_metrics_ = std::shared_ptr<AccuracyMetrics>(new AccuracyMetrics); | |||||
| loop_->Init({acc_metrics_.get()}); | |||||
| auto inputs = session_->GetInputs(); | auto inputs = session_->GetInputs(); | ||||
| MS_ASSERT(inputs.size() > 1); | MS_ASSERT(inputs.size() > 1); | ||||
| data_index_ = 0; | |||||
| label_index_ = 1; | |||||
| batch_size_ = inputs[data_index_]->shape()[0]; | |||||
| data_size_ = inputs[data_index_]->Size() / batch_size_; // in bytes | |||||
| if (verbose_) { | |||||
| std::cout << "data size: " << data_size_ << std::endl << "batch size: " << batch_size_ << std::endl; | |||||
| } | |||||
| } | } | ||||
| float NetRunner::CalculateAccuracy(int max_tests) { | float NetRunner::CalculateAccuracy(int max_tests) { | ||||
| AccuracyMonitor test_am(&ds_, 1, max_tests); | |||||
| test_am.EpochEnd(TrainLoopCallBackData(true, 0, session_, loop_)); | |||||
| test_ds_ = Mnist(data_dir_ + "/test", "all"); | |||||
| std::shared_ptr<TensorOperation> typecast_f = mindspore::dataset::transforms::TypeCast("float32"); | |||||
| std::shared_ptr<TensorOperation> resize = mindspore::dataset::vision::Resize({32, 32}); | |||||
| test_ds_ = test_ds_->Map({resize, typecast_f}, {"image"}); | |||||
| std::shared_ptr<TensorOperation> typecast = mindspore::dataset::transforms::TypeCast("int32"); | |||||
| test_ds_ = test_ds_->Map({typecast}, {"label"}); | |||||
| test_ds_ = test_ds_->Batch(32, true); | |||||
| Rescaler rescale(255.0); | |||||
| loop_->Eval(test_ds_.get(), std::vector<TrainLoopCallBack *>{&rescale}); | |||||
| std::cout << "Eval Accuracy is " << acc_metrics_->Eval() << std::endl; | |||||
| return 0.0; | return 0.0; | ||||
| } | } | ||||
| int NetRunner::InitDB() { | int NetRunner::InitDB() { | ||||
| if (data_size_ != 0) ds_.set_expected_data_size(data_size_); | |||||
| int ret = ds_.Init(data_dir_, DS_MNIST_BINARY); | |||||
| num_of_classes_ = ds_.num_of_classes(); | |||||
| if (ds_.test_data().size() == 0) { | |||||
| train_ds_ = Mnist(data_dir_ + "/train", "all"); | |||||
| std::shared_ptr<TensorOperation> typecast_f = mindspore::dataset::transforms::TypeCast("float32"); | |||||
| std::shared_ptr<TensorOperation> resize = mindspore::dataset::vision::Resize({32, 32}); | |||||
| // std::shared_ptr<TensorOperation> rescale_op = Normalize({0.0, 0.0, 0.0}, {255.0, 255.0, 255.0}); | |||||
| // std::shared_ptr<TensorOperation> rescale_op = mindspore::dataset::vision::Rescale(255.0, 0.0); | |||||
| train_ds_ = train_ds_->Map({resize, typecast_f}, {"image"}); | |||||
| std::shared_ptr<TensorOperation> typecast = mindspore::dataset::transforms::TypeCast("int32"); | |||||
| train_ds_ = train_ds_->Map({typecast}, {"label"}); | |||||
| train_ds_ = train_ds_->Shuffle(2); | |||||
| train_ds_ = train_ds_->Batch(32, true); | |||||
| if (verbose_) { | |||||
| std::cout << "DatasetSize is " << train_ds_->GetDatasetSize() << std::endl; | |||||
| } | |||||
| if (train_ds_->GetDatasetSize() == 0) { | |||||
| std::cout << "No relevant data was found in " << data_dir_ << std::endl; | std::cout << "No relevant data was found in " << data_dir_ << std::endl; | ||||
| MS_ASSERT(ds_.test_data().size() != 0); | |||||
| MS_ASSERT(train_ds_->GetDatasetSize() != 0); | |||||
| } | } | ||||
| return ret; | |||||
| return 0; | |||||
| } | } | ||||
| int NetRunner::TrainLoop() { | int NetRunner::TrainLoop() { | ||||
| struct mindspore::lite::StepLRLambda step_lr_lambda(100, 0.9); | |||||
| struct mindspore::lite::StepLRLambda step_lr_lambda(1, 0.9); | |||||
| mindspore::lite::LRScheduler step_lr_sched(mindspore::lite::StepLRLambda, static_cast<void *>(&step_lr_lambda), 100); | mindspore::lite::LRScheduler step_lr_sched(mindspore::lite::StepLRLambda, static_cast<void *>(&step_lr_lambda), 100); | ||||
| mindspore::lite::LossMonitor lm(100); | mindspore::lite::LossMonitor lm(100); | ||||
| // mindspore::lite::ClassificationTrainAccuracyMonitor am(10); | |||||
| mindspore::lite::ClassificationTrainAccuracyMonitor am(1); | |||||
| mindspore::lite::CkptSaver cs(1000, std::string("lenet")); | mindspore::lite::CkptSaver cs(1000, std::string("lenet")); | ||||
| AccuracyMonitor test_am(&ds_, 500, 10); | |||||
| DataLoader dl(&ds_); | |||||
| Rescaler rescale(255.0); | |||||
| loop_->Train(cycles_, std::vector<TrainLoopCallBack *>{&dl, &lm, &test_am, &cs, &step_lr_sched}); | |||||
| loop_->Train(epochs_, train_ds_.get(), std::vector<TrainLoopCallBack *>{&rescale, &lm, &cs, &am, &step_lr_sched}); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -131,15 +173,15 @@ int NetRunner::Main() { | |||||
| CalculateAccuracy(); | CalculateAccuracy(); | ||||
| if (cycles_ > 0) { | |||||
| auto trained_fn = ms_file_.substr(0, ms_file_.find_last_of('.')) + "_trained_" + std::to_string(cycles_) + ".ms"; | |||||
| if (epochs_ > 0) { | |||||
| auto trained_fn = ms_file_.substr(0, ms_file_.find_last_of('.')) + "_trained.ms"; | |||||
| session_->SaveToFile(trained_fn); | session_->SaveToFile(trained_fn); | ||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| void NetRunner::Usage() { | void NetRunner::Usage() { | ||||
| std::cout << "Usage: net_runner -f <.ms model file> -d <data_dir> [-c <num of training cycles>] " | |||||
| std::cout << "Usage: net_runner -f <.ms model file> -d <data_dir> [-e <num of training epochs>] " | |||||
| << "[-v (verbose mode)] [-s <save checkpoint every X iterations>]" << std::endl; | << "[-v (verbose mode)] [-s <save checkpoint every X iterations>]" << std::endl; | ||||
| } | } | ||||
| @@ -151,7 +193,7 @@ bool NetRunner::ReadArgs(int argc, char *argv[]) { | |||||
| ms_file_ = std::string(optarg); | ms_file_ = std::string(optarg); | ||||
| break; | break; | ||||
| case 'e': | case 'e': | ||||
| cycles_ = atoi(optarg); | |||||
| epochs_ = atoi(optarg); | |||||
| break; | break; | ||||
| case 'd': | case 'd': | ||||
| data_dir_ = std::string(optarg); | data_dir_ = std::string(optarg); | ||||
| @@ -21,11 +21,16 @@ | |||||
| #include <iomanip> | #include <iomanip> | ||||
| #include <map> | #include <map> | ||||
| #include <vector> | #include <vector> | ||||
| #include <memory> | |||||
| #include <string> | #include <string> | ||||
| #include "include/train_session.h" | #include "include/train_session.h" | ||||
| #include "include/train/train_loop.h" | #include "include/train/train_loop.h" | ||||
| #include "include/train/accuracy_metrics.h" | |||||
| #include "include/ms_tensor.h" | #include "include/ms_tensor.h" | ||||
| #include "src/dataset.h" | |||||
| #include "include/datasets.h" | |||||
| using mindspore::dataset::Dataset; | |||||
| using mindspore::lite::AccuracyMetrics; | |||||
| class NetRunner { | class NetRunner { | ||||
| public: | public: | ||||
| @@ -38,26 +43,22 @@ class NetRunner { | |||||
| void InitAndFigureInputs(); | void InitAndFigureInputs(); | ||||
| int InitDB(); | int InitDB(); | ||||
| int TrainLoop(); | int TrainLoop(); | ||||
| std::vector<int> FillInputData(const std::vector<DataLabelTuple> &dataset, bool is_train_set = false) const; | |||||
| float CalculateAccuracy(int max_tests = -1); | |||||
| float CalculateAccuracy(int max_tests = 0); | |||||
| float GetLoss() const; | float GetLoss() const; | ||||
| mindspore::tensor::MSTensor *SearchOutputsForSize(size_t size) const; | mindspore::tensor::MSTensor *SearchOutputsForSize(size_t size) const; | ||||
| DataSet ds_; | |||||
| mindspore::session::TrainSession *session_ = nullptr; | mindspore::session::TrainSession *session_ = nullptr; | ||||
| mindspore::session::TrainLoop *loop_ = nullptr; | mindspore::session::TrainLoop *loop_ = nullptr; | ||||
| std::shared_ptr<Dataset> train_ds_; | |||||
| std::shared_ptr<Dataset> test_ds_; | |||||
| std::shared_ptr<AccuracyMetrics> acc_metrics_; | |||||
| std::string ms_file_ = ""; | std::string ms_file_ = ""; | ||||
| std::string data_dir_ = ""; | std::string data_dir_ = ""; | ||||
| size_t data_size_ = 0; | |||||
| size_t batch_size_ = 0; | |||||
| unsigned int cycles_ = 100; | |||||
| int data_index_ = 0; | |||||
| int label_index_ = -1; | |||||
| int num_of_classes_ = 0; | |||||
| unsigned int epochs_ = 10; | |||||
| bool verbose_ = false; | bool verbose_ = false; | ||||
| int save_checkpoint_ = 0; | int save_checkpoint_ = 0; | ||||
| static unsigned int seed_; | |||||
| }; | }; | ||||
| #endif // MINDSPORE_LITE_EXAMPLES_TRAIN_LENET_SRC_NET_RUNNER_H_ | #endif // MINDSPORE_LITE_EXAMPLES_TRAIN_LENET_SRC_NET_RUNNER_H_ | ||||
| @@ -8,7 +8,7 @@ fi | |||||
| echo "============Exporting==========" | echo "============Exporting==========" | ||||
| if [ -n "$1" ]; then | if [ -n "$1" ]; then | ||||
| DOCKER_IMG=$1 | DOCKER_IMG=$1 | ||||
| docker run -w $PWD --runtime=nvidia -v /home/$USER:/home/$USER --privileged=true ${DOCKER_IMG} /bin/bash -c "python transfer_learning_export.py; chmod 444 transfer_learning_tod.mindir; rm -rf __pycache__" | |||||
| docker run -w $PWD --runtime=nvidia -v /home/$USER:/home/$USER --privileged=true ${DOCKER_IMG} /bin/bash -c "python transfer_learning_export.py; chmod 444 transfer_learning_tod*.mindir; rm -rf __pycache__" | |||||
| else | else | ||||
| echo "MindSpore docker was not provided, attempting to run locally" | echo "MindSpore docker was not provided, attempting to run locally" | ||||
| python transfer_learning_export.py | python transfer_learning_export.py | ||||
| @@ -32,4 +32,6 @@ if [ ! -f "$CONVERTER" ]; then | |||||
| fi | fi | ||||
| echo "============Converting=========" | echo "============Converting=========" | ||||
| LD_LIBRARY_PATH=./ $CONVERTER --fmk=MINDIR --trainModel=true --modelFile=transfer_learning_tod.mindir --outputFile=transfer_learning_tod | |||||
| pwd | |||||
| LD_LIBRARY_PATH=./ $CONVERTER --fmk=MINDIR --trainModel=false --modelFile=transfer_learning_tod_backbone.mindir --outputFile=transfer_learning_tod_backbone | |||||
| LD_LIBRARY_PATH=./ $CONVERTER --fmk=MINDIR --trainModel=true --modelFile=transfer_learning_tod_head.mindir --outputFile=transfer_learning_tod_head | |||||
| @@ -17,9 +17,7 @@ | |||||
| import numpy as np | import numpy as np | ||||
| import mindspore as M | import mindspore as M | ||||
| from mindspore.nn import Cell | from mindspore.nn import Cell | ||||
| from mindspore.train.serialization import load_checkpoint | |||||
| from mindspore.common.parameter import ParameterTuple | |||||
| from mindspore.train.serialization import export | |||||
| from mindspore.train.serialization import load_checkpoint, export | |||||
| from effnet import effnet | from effnet import effnet | ||||
| from train_utils import TrainWrap | from train_utils import TrainWrap | ||||
| @@ -38,26 +36,23 @@ class TransferNet(Cell): | |||||
| BACKBONE = effnet(num_classes=1000) | BACKBONE = effnet(num_classes=1000) | ||||
| load_checkpoint("efficient_net_b0.ckpt", BACKBONE) | load_checkpoint("efficient_net_b0.ckpt", BACKBONE) | ||||
| HEAD = M.nn.Dense(1000, 10) | |||||
| HEAD.weight.set_data(M.Tensor(np.random.normal( | |||||
| 0, 0.1, HEAD.weight.data.shape).astype("float32"))) | |||||
| HEAD.bias.set_data(M.Tensor(np.zeros(HEAD.bias.data.shape, dtype="float32"))) | |||||
| n = TransferNet(BACKBONE, HEAD) | |||||
| trainable_weights_list = [] | |||||
| trainable_weights_list.extend(n.head.trainable_params()) | |||||
| trainable_weights = ParameterTuple(trainable_weights_list) | |||||
| M.context.set_context(mode=M.context.PYNATIVE_MODE, | M.context.set_context(mode=M.context.PYNATIVE_MODE, | ||||
| device_target="GPU", save_graphs=False) | device_target="GPU", save_graphs=False) | ||||
| BATCH_SIZE = 16 | BATCH_SIZE = 16 | ||||
| X = M.Tensor(np.ones((BATCH_SIZE, 3, 224, 224)), M.float32) | X = M.Tensor(np.ones((BATCH_SIZE, 3, 224, 224)), M.float32) | ||||
| export(BACKBONE, X, file_name="transfer_learning_tod_backbone", file_format='MINDIR') | |||||
| label = M.Tensor(np.zeros([BATCH_SIZE, 10]).astype(np.float32)) | label = M.Tensor(np.zeros([BATCH_SIZE, 10]).astype(np.float32)) | ||||
| HEAD = M.nn.Dense(1000, 10) | |||||
| HEAD.weight.set_data(M.Tensor(np.random.normal( | |||||
| 0, 0.1, HEAD.weight.data.shape).astype("float32"))) | |||||
| HEAD.bias.set_data(M.Tensor(np.zeros(HEAD.bias.data.shape, dtype="float32"))) | |||||
| sgd = M.nn.SGD(trainable_weights, learning_rate=0.01, momentum=0.9, | |||||
| sgd = M.nn.SGD(HEAD.trainable_params(), learning_rate=0.01, momentum=0.9, | |||||
| dampening=0.01, weight_decay=0.0, nesterov=False, loss_scale=1.0) | dampening=0.01, weight_decay=0.0, nesterov=False, loss_scale=1.0) | ||||
| net = TrainWrap(n, optimizer=sgd, weights=trainable_weights) | |||||
| export(net, X, label, file_name="transfer_learning_tod", file_format='MINDIR') | |||||
| net = TrainWrap(HEAD, optimizer=sgd) | |||||
| backbone_out = M.Tensor(np.zeros([BATCH_SIZE, 1000]).astype(np.float32)) | |||||
| export(net, backbone_out, label, file_name="transfer_learning_tod_head", file_format='MINDIR') | |||||
| print("Exported") | print("Exported") | ||||
| @@ -14,4 +14,4 @@ | |||||
| # limitations under the License. | # limitations under the License. | ||||
| # ============================================================================ | # ============================================================================ | ||||
| LD_LIBRARY_PATH=./lib/ bin/net_runner -f model/transfer_learning_tod_trained.ms -e 0 -d dataset | |||||
| LD_LIBRARY_PATH=./lib/ bin/net_runner -b model/transfer_learning_tod_backbone.ms -f model/transfer_learning_tod_head_trained.ms -e 0 -d dataset | |||||
| @@ -14,4 +14,4 @@ | |||||
| # limitations under the License. | # limitations under the License. | ||||
| # ============================================================================ | # ============================================================================ | ||||
| LD_LIBRARY_PATH=./lib/ bin/net_runner -f model/transfer_learning_tod.ms -e 0 -d dataset | |||||
| LD_LIBRARY_PATH=./lib/ bin/net_runner -b model/transfer_learning_tod_backbone.ms -f model/transfer_learning_tod_head.ms -e 0 -d dataset | |||||
| @@ -14,4 +14,4 @@ | |||||
| # limitations under the License. | # limitations under the License. | ||||
| # ============================================================================ | # ============================================================================ | ||||
| LD_LIBRARY_PATH=./lib/ bin/net_runner -f model/transfer_learning_tod.ms -e 100 -d dataset -s 20 | |||||
| LD_LIBRARY_PATH=./lib/ bin/net_runner -b model/transfer_learning_tod_backbone.ms -f model/transfer_learning_tod_head.ms -e 100 -d dataset -s 20 | |||||
| @@ -70,7 +70,7 @@ void NetRunner::InitAndFigureInputs() { | |||||
| context.device_list_[0].device_info_.cpu_device_info_.cpu_bind_mode_ = mindspore::lite::NO_BIND; | context.device_list_[0].device_info_.cpu_device_info_.cpu_bind_mode_ = mindspore::lite::NO_BIND; | ||||
| context.thread_num_ = 1; | context.thread_num_ = 1; | ||||
| session_ = mindspore::session::TrainSession::CreateSession(ms_file_, &context); | |||||
| session_ = mindspore::session::TrainSession::CreateTransferSession(ms_backbone_file_, ms_head_file_, &context); | |||||
| MS_ASSERT(nullptr != session_); | MS_ASSERT(nullptr != session_); | ||||
| auto inputs = session_->GetInputs(); | auto inputs = session_->GetInputs(); | ||||
| @@ -185,7 +185,8 @@ int NetRunner::TrainLoop() { | |||||
| if (min_loss > loss) min_loss = loss; | if (min_loss > loss) min_loss = loss; | ||||
| if (save_checkpoint_ != 0 && (i + 1) % save_checkpoint_ == 0) { | if (save_checkpoint_ != 0 && (i + 1) % save_checkpoint_ == 0) { | ||||
| auto cpkt_fn = ms_file_.substr(0, ms_file_.find_last_of('.')) + "_trained_" + std::to_string(i + 1) + ".ms"; | |||||
| auto cpkt_fn = | |||||
| ms_head_file_.substr(0, ms_head_file_.find_last_of('.')) + "_trained_" + std::to_string(i + 1) + ".ms"; | |||||
| session_->SaveToFile(cpkt_fn); | session_->SaveToFile(cpkt_fn); | ||||
| } | } | ||||
| @@ -211,23 +212,27 @@ int NetRunner::Main() { | |||||
| std::cout << "accuracy on validation data = " << acc << std::endl; | std::cout << "accuracy on validation data = " << acc << std::endl; | ||||
| if (cycles_ > 0) { | if (cycles_ > 0) { | ||||
| auto trained_fn = ms_file_.substr(0, ms_file_.find_last_of('.')) + "_trained.ms"; | |||||
| auto trained_fn = ms_head_file_.substr(0, ms_head_file_.find_last_of('.')) + "_trained.ms"; | |||||
| session_->SaveToFile(trained_fn); | session_->SaveToFile(trained_fn); | ||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| void NetRunner::Usage() { | void NetRunner::Usage() { | ||||
| std::cout << "Usage: net_runner -f <.ms model file> -d <data_dir> [-c <num of training cycles>] " | |||||
| << "[-v (verbose mode)] [-s <save checkpoint every X iterations>]" << std::endl; | |||||
| std::cout << "Usage: net_runner -f <.ms head model file> -b <.ms backbone model file> -d <data_dir> " | |||||
| << "[-c <num of training cycles>] [-v (verbose mode)] " | |||||
| << "[-s <save checkpoint every X iterations>]" << std::endl; | |||||
| } | } | ||||
| bool NetRunner::ReadArgs(int argc, char *argv[]) { | bool NetRunner::ReadArgs(int argc, char *argv[]) { | ||||
| int opt; | int opt; | ||||
| while ((opt = getopt(argc, argv, "f:e:d:s:ihc:v")) != -1) { | |||||
| while ((opt = getopt(argc, argv, "b:f:e:d:s:ihc:v")) != -1) { | |||||
| switch (opt) { | switch (opt) { | ||||
| case 'b': | |||||
| ms_backbone_file_ = std::string(optarg); | |||||
| break; | |||||
| case 'f': | case 'f': | ||||
| ms_file_ = std::string(optarg); | |||||
| ms_head_file_ = std::string(optarg); | |||||
| break; | break; | ||||
| case 'e': | case 'e': | ||||
| cycles_ = atoi(optarg); | cycles_ = atoi(optarg); | ||||
| @@ -45,7 +45,8 @@ class NetRunner { | |||||
| DataSet ds_; | DataSet ds_; | ||||
| mindspore::session::TrainSession *session_ = nullptr; | mindspore::session::TrainSession *session_ = nullptr; | ||||
| std::string ms_file_ = ""; | |||||
| std::string ms_backbone_file_ = ""; | |||||
| std::string ms_head_file_ = ""; | |||||
| std::string data_dir_ = ""; | std::string data_dir_ = ""; | ||||
| size_t data_size_ = 0; | size_t data_size_ = 0; | ||||
| size_t batch_size_ = 0; | size_t batch_size_ = 0; | ||||
| @@ -0,0 +1,48 @@ | |||||
| /** | |||||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * 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. | |||||
| */ | |||||
| #ifndef MINDSPORE_LITE_INCLUDE_TRAIN_ACCURACY_METRICS_H_ | |||||
| #define MINDSPORE_LITE_INCLUDE_TRAIN_ACCURACY_METRICS_H_ | |||||
| #include <vector> | |||||
| #include "include/train/metrics.h" | |||||
| using mindspore::session::Metrics; | |||||
| namespace mindspore { | |||||
| namespace lite { | |||||
| constexpr int METRICS_CLASSIFICATION = 0; | |||||
| constexpr int METRICS_MULTILABLE = 1; | |||||
| class AccuracyMetrics : public Metrics { | |||||
| public: | |||||
| explicit AccuracyMetrics(int accuracy_metrics = METRICS_CLASSIFICATION, const std::vector<int> &input_indexes = {1}, | |||||
| const std::vector<int> &output_indexes = {0}); | |||||
| virtual ~AccuracyMetrics() = default; | |||||
| void Clear() override { total_accuracy_ = total_steps_ = 0.0; } | |||||
| float Eval() override; | |||||
| void Update(std::vector<tensor::MSTensor *> inputs, std::vector<tensor::MSTensor *> outputs) override; | |||||
| protected: | |||||
| int accuracy_metrics_ = METRICS_CLASSIFICATION; | |||||
| std::vector<int> input_indexes_ = {1}; | |||||
| std::vector<int> output_indexes_ = {0}; | |||||
| float total_accuracy_ = 0.0; | |||||
| float total_steps_ = 0.0; | |||||
| }; | |||||
| } // namespace lite | |||||
| } // namespace mindspore | |||||
| #endif // MINDSPORE_LITE_INCLUDE_TRAIN_ACCURACY_METRICS_H_ | |||||
| @@ -13,31 +13,35 @@ | |||||
| * See the License for the specific language governing permissions and | * See the License for the specific language governing permissions and | ||||
| * limitations under the License. | * limitations under the License. | ||||
| */ | */ | ||||
| #ifndef MINDSPORE_LITE_EXAMPLES_TRAIN_LENET_SRC_ACCURACY_MONITOR_H_ | |||||
| #define MINDSPORE_LITE_EXAMPLES_TRAIN_LENET_SRC_ACCURACY_MONITOR_H_ | |||||
| #ifndef MINDSPORE_LITE_INCLUDE_TRAIN_ACCURACY_MONITOR_H_ | |||||
| #define MINDSPORE_LITE_INCLUDE_TRAIN_ACCURACY_MONITOR_H_ | |||||
| #include <vector> | #include <vector> | ||||
| #include <string> | #include <string> | ||||
| #include <utility> | #include <utility> | ||||
| #include <unordered_map> | #include <unordered_map> | ||||
| #include "include/train/train_loop.h" | #include "include/train/train_loop.h" | ||||
| #include "src/dataset.h" | |||||
| using GraphPoint = std::pair<int, float>; | using GraphPoint = std::pair<int, float>; | ||||
| class AccuracyMonitor : public mindspore::session::TrainLoopCallBack { | |||||
| namespace mindspore { | |||||
| namespace lite { | |||||
| class AccuracyMonitor : public session::TrainLoopCallBack { | |||||
| public: | public: | ||||
| explicit AccuracyMonitor(DataSet *dataset, int check_every_n, int max_steps = -1) | |||||
| explicit AccuracyMonitor(mindspore::dataset::Dataset *dataset, int check_every_n, int max_steps = -1) | |||||
| : ds_(dataset), check_every_n_(check_every_n), max_steps_(max_steps) {} | : ds_(dataset), check_every_n_(check_every_n), max_steps_(max_steps) {} | ||||
| void Begin(const session::TrainLoopCallBackData &cb_data) override; | |||||
| int EpochEnd(const mindspore::session::TrainLoopCallBackData &cb_data) override; | int EpochEnd(const mindspore::session::TrainLoopCallBackData &cb_data) override; | ||||
| const std::vector<GraphPoint> &GetAccuracyPoints() const { return accuracies_; } | const std::vector<GraphPoint> &GetAccuracyPoints() const { return accuracies_; } | ||||
| private: | private: | ||||
| DataSet *ds_; | |||||
| mindspore::dataset::Dataset *ds_; | |||||
| std::vector<GraphPoint> accuracies_; | std::vector<GraphPoint> accuracies_; | ||||
| int check_every_n_; | int check_every_n_; | ||||
| int max_steps_; | int max_steps_; | ||||
| }; | }; | ||||
| #endif // MINDSPORE_LITE_EXAMPLES_TRAIN_LENET_SRC_ACCURACY_MONITOR_H_ | |||||
| } // namespace lite | |||||
| } // namespace mindspore | |||||
| #endif // MINDSPORE_LITE_INCLUDE_TRAIN_ACCURACY_MONITOR_H_ | |||||
| @@ -21,6 +21,7 @@ | |||||
| #include <climits> | #include <climits> | ||||
| #include <unordered_map> | #include <unordered_map> | ||||
| #include "include/train/train_loop.h" | #include "include/train/train_loop.h" | ||||
| #include "include/train/accuracy_metrics.h" | |||||
| using GraphPoint = std::pair<int, float>; | using GraphPoint = std::pair<int, float>; | ||||
| @@ -29,9 +30,12 @@ namespace lite { | |||||
| class ClassificationTrainAccuracyMonitor : public session::TrainLoopCallBack { | class ClassificationTrainAccuracyMonitor : public session::TrainLoopCallBack { | ||||
| public: | public: | ||||
| explicit ClassificationTrainAccuracyMonitor(int print_every_n = INT_MAX) : print_every_n_(print_every_n) {} | |||||
| explicit ClassificationTrainAccuracyMonitor(int print_every_n = INT_MAX, | |||||
| int accuracy_metrics = METRICS_CLASSIFICATION, | |||||
| const std::vector<int> &input_indexes = {1}, | |||||
| const std::vector<int> &output_indexes = {0}); | |||||
| virtual ~ClassificationTrainAccuracyMonitor() = default; | virtual ~ClassificationTrainAccuracyMonitor() = default; | ||||
| void Begin(const session::TrainLoopCallBackData &cb_data) override; | void Begin(const session::TrainLoopCallBackData &cb_data) override; | ||||
| void EpochBegin(const session::TrainLoopCallBackData &cb_data) override; | void EpochBegin(const session::TrainLoopCallBackData &cb_data) override; | ||||
| int EpochEnd(const session::TrainLoopCallBackData &cb_data) override; | int EpochEnd(const session::TrainLoopCallBackData &cb_data) override; | ||||
| @@ -40,6 +44,9 @@ class ClassificationTrainAccuracyMonitor : public session::TrainLoopCallBack { | |||||
| private: | private: | ||||
| std::vector<GraphPoint> accuracies_; | std::vector<GraphPoint> accuracies_; | ||||
| int accuracy_metrics_ = METRICS_CLASSIFICATION; | |||||
| std::vector<int> input_indexes_ = {1}; | |||||
| std::vector<int> output_indexes_ = {0}; | |||||
| int print_every_n_ = 0; | int print_every_n_ = 0; | ||||
| }; | }; | ||||
| @@ -29,7 +29,16 @@ namespace lite { | |||||
| class LossMonitor : public session::TrainLoopCallBack { | class LossMonitor : public session::TrainLoopCallBack { | ||||
| public: | public: | ||||
| explicit LossMonitor(int print_every_n = INT_MAX) : print_every_n_(print_every_n) {} | |||||
| /// \brief constructor | |||||
| /// | |||||
| /// \param[in] print_every_n_steps prints loss into stdout every n_steps. | |||||
| // print_every_n_steps=0 means never print | |||||
| // print_every_n_steps=INT_MAX will print every epoch | |||||
| /// \param[in] dataset Pointer to MindData Dataset object | |||||
| /// \param[in] cbs A vector of TrainLoopCallBack objects | |||||
| /// | |||||
| /// \return 0 on success or -1 in case of error | |||||
| explicit LossMonitor(int print_every_n_steps = INT_MAX) : print_every_n_(print_every_n_steps) {} | |||||
| virtual ~LossMonitor() = default; | virtual ~LossMonitor() = default; | ||||
| void Begin(const session::TrainLoopCallBackData &cb_data) override; | void Begin(const session::TrainLoopCallBackData &cb_data) override; | ||||
| void EpochBegin(const session::TrainLoopCallBackData &cb_data) override; | void EpochBegin(const session::TrainLoopCallBackData &cb_data) override; | ||||
| @@ -13,22 +13,25 @@ | |||||
| * See the License for the specific language governing permissions and | * See the License for the specific language governing permissions and | ||||
| * limitations under the License. | * limitations under the License. | ||||
| */ | */ | ||||
| #ifndef MINDSPORE_LITE_EXAMPLES_TRAIN_LENET_SRC_DATA_LOADER_H_ | |||||
| #define MINDSPORE_LITE_EXAMPLES_TRAIN_LENET_SRC_DATA_LOADER_H_ | |||||
| #ifndef MINDSPORE_LITE_INCLUDE_TRAIN_METRICS_H_ | |||||
| #define MINDSPORE_LITE_INCLUDE_TRAIN_METRICS_H_ | |||||
| #include <vector> | #include <vector> | ||||
| #include <string> | #include <string> | ||||
| #include <utility> | |||||
| #include <tuple> | |||||
| #include <unordered_map> | #include <unordered_map> | ||||
| #include "include/train/train_loop.h" | |||||
| #include "src/dataset.h" | |||||
| #include "include/ms_tensor.h" | |||||
| class DataLoader : public mindspore::session::TrainLoopCallBack { | |||||
| public: | |||||
| explicit DataLoader(DataSet *dataset) : ds_(dataset) {} | |||||
| void StepBegin(const mindspore::session::TrainLoopCallBackData &cb_data) override; | |||||
| namespace mindspore { | |||||
| namespace session { | |||||
| private: | |||||
| DataSet *ds_; | |||||
| class Metrics { | |||||
| public: | |||||
| virtual ~Metrics() = default; | |||||
| virtual void Clear() {} | |||||
| virtual float Eval() { return 0.0; } | |||||
| virtual void Update(std::vector<tensor::MSTensor *> inputs, std::vector<tensor::MSTensor *> outputs) = 0; | |||||
| }; | }; | ||||
| #endif // MINDSPORE_LITE_EXAMPLES_TRAIN_LENET_SRC_DATA_LOADER_H_ | |||||
| } // namespace session | |||||
| } // namespace mindspore | |||||
| #endif // MINDSPORE_LITE_INCLUDE_TRAIN_METRICS_H_ | |||||
| @@ -18,11 +18,22 @@ | |||||
| #include <vector> | #include <vector> | ||||
| #include <string> | #include <string> | ||||
| #include <tuple> | #include <tuple> | ||||
| #include <climits> | |||||
| #include <unordered_map> | #include <unordered_map> | ||||
| #include "include/train/train_loop_callback.h" | #include "include/train/train_loop_callback.h" | ||||
| #include "include/train/metrics.h" | |||||
| #include "include/train_session.h" | #include "include/train_session.h" | ||||
| namespace mindspore { | namespace mindspore { | ||||
| class MSTensor; | |||||
| namespace dataset { | |||||
| class Dataset; | |||||
| using MSTensorVec = std::vector<mindspore::MSTensor>; | |||||
| } // namespace dataset | |||||
| using LoadDataFunc = std::function<int(std::vector<tensor::MSTensor *> inputs, dataset::MSTensorVec *dataset_vec)>; | |||||
| namespace session { | namespace session { | ||||
| class TrainLoop { | class TrainLoop { | ||||
| @@ -48,6 +59,18 @@ class TrainLoop { | |||||
| /// \return pointer of the train_session | /// \return pointer of the train_session | ||||
| virtual session::TrainSession *train_session() = 0; | virtual session::TrainSession *train_session() = 0; | ||||
| /// \brief Initialize object with metrics | |||||
| /// | |||||
| /// \param[in] verctor of metrics | |||||
| /// | |||||
| /// \return 0 on success or -1 in case of error | |||||
| virtual int Init(std::vector<mindspore::session::Metrics *> metrics) = 0; | |||||
| /// \brief Accessor to TrainLoop metric objects | |||||
| /// | |||||
| /// \return vector of metrics | |||||
| virtual std::vector<mindspore::session::Metrics *> GetMetrics() = 0; | |||||
| /// \brief Accessor to the Session KernelCallbacks | /// \brief Accessor to the Session KernelCallbacks | ||||
| /// | /// | ||||
| /// \param[in] before Define a call_back_function to be called before running each node. | /// \param[in] before Define a call_back_function to be called before running each node. | ||||
| @@ -59,10 +82,24 @@ class TrainLoop { | |||||
| /// \brief Performs the training Loop | /// \brief Performs the training Loop | ||||
| /// | /// | ||||
| /// \param[in] epoch The number of epochs to run | /// \param[in] epoch The number of epochs to run | ||||
| /// \param[in] dataset Pointer to MindData Dataset object | |||||
| /// \param[in] cbs A vector of TrainLoopCallBack objects | |||||
| /// \param[in] load_func a function that load (and can manipulate) data from Minddata Dataset array into model | |||||
| /// | |||||
| /// \return 0 on success or -1 in case of error | |||||
| virtual int Train(int epochs, mindspore::dataset::Dataset *dataset, std::vector<TrainLoopCallBack *> cbs, | |||||
| LoadDataFunc load_func = nullptr) = 0; | |||||
| /// \brief Performs loop over all data in Eval Mode | |||||
| /// | |||||
| /// \param[in] dataset Pointer to MindData Dataset object | |||||
| /// \param[in] cbs A vector of TrainLoopCallBack objects | /// \param[in] cbs A vector of TrainLoopCallBack objects | ||||
| /// \param[in] load_func a function that load (and can manipulate) data from Minddata Dataset array into model | |||||
| /// \param[in] max_steps (with default = INT_MAX the method iterates all dataset) | |||||
| /// | /// | ||||
| /// \return 0 on success or -1 in case of error | /// \return 0 on success or -1 in case of error | ||||
| virtual int Train(int epochs, std::vector<TrainLoopCallBack *> cbs) = 0; | |||||
| virtual int Eval(mindspore::dataset::Dataset *dataset, std::vector<TrainLoopCallBack *> cbs, | |||||
| LoadDataFunc load_func = nullptr, int max_steps = INT_MAX) = 0; | |||||
| }; | }; | ||||
| } // namespace session | } // namespace session | ||||
| } // namespace mindspore | } // namespace mindspore | ||||
| @@ -18,7 +18,6 @@ | |||||
| #include <vector> | #include <vector> | ||||
| #include <string> | #include <string> | ||||
| #include <tuple> | #include <tuple> | ||||
| #include <unordered_map> | |||||
| #include "include/lite_session.h" | #include "include/lite_session.h" | ||||
| namespace mindspore { | namespace mindspore { | ||||
| @@ -50,6 +49,31 @@ class TrainSession : public session::LiteSession { | |||||
| /// \return Pointer of MindSpore Lite TrainSession | /// \return Pointer of MindSpore Lite TrainSession | ||||
| static TrainSession *CreateSession(const std::string &filename, lite::Context *context, bool train_mode = false); | static TrainSession *CreateSession(const std::string &filename, lite::Context *context, bool train_mode = false); | ||||
| /// \brief Static method to create a transfer lernning support TrainSession object | |||||
| /// | |||||
| /// \param[in] model_buf_backbone A buffer that was read from a backbone MS model file | |||||
| /// \param[in] size_backbone Length of the backbone net buffer | |||||
| /// \param[in] model_buf_head A buffer that was read from a head MS model file | |||||
| /// \param[in] size_head Length of the head net buffer | |||||
| /// \param[in] context Defines the context of the session to be created | |||||
| /// \param[in] train_mode training mode to initialize Session with | |||||
| /// | |||||
| /// \return Pointer of MindSpore Lite TrainSession | |||||
| static TrainSession *CreateTransferSession(const char *model_buf_backbone, size_t size_backbone, | |||||
| const char *model_buf_head, size_t size_head, lite::Context *context, | |||||
| bool train_mode = false); | |||||
| /// \brief Static method to create a TrainSession object | |||||
| /// | |||||
| /// \param[in] filename_backbone Filename to read backbone net flatbuffer from | |||||
| /// \param[in] filename_head Filename to read head net flatbuffer from | |||||
| /// \param[in] context Defines the context of the session to be created | |||||
| /// \param[in] train_mode training mode to initialize Session with | |||||
| /// | |||||
| /// \return Pointer of MindSpore Lite TrainSession | |||||
| static TrainSession *CreateTransferSession(const std::string &filename_backbone, const std::string &filename_head, | |||||
| lite::Context *context, bool train_mode = false); | |||||
| /// \brief Export the trained model into a buffer | /// \brief Export the trained model into a buffer | ||||
| /// | /// | ||||
| /// \param[in] buf The buffer to Export into. If equal to nullptr, buf will be allocated | /// \param[in] buf The buffer to Export into. If equal to nullptr, buf will be allocated | ||||
| @@ -95,13 +119,30 @@ class TrainSession : public session::LiteSession { | |||||
| /// \return learning rate. 0.0 if no optimizer was found | /// \return learning rate. 0.0 if no optimizer was found | ||||
| virtual float GetLearningRate() = 0; | virtual float GetLearningRate() = 0; | ||||
| /// \brief Setup training with virtual batches | |||||
| /// | |||||
| /// \param[in] virtual_batch_multiplier - virtual batch multiplier, use any number < 1 to disable | |||||
| /// \param[in] lr - learning rate to use for virtual batch, -1 for internal configuration | |||||
| /// \param[in] momentum - batch norm momentum to use for virtual batch, -1 for internal configuration | |||||
| /// \return STATUS as an error code of the set operation, STATUS is defined in errorcode.h | |||||
| virtual int SetupVirtualBatch(int virtual_batch_multiplier, float lr = -1.0f, float momentum = -1.0f) = 0; | |||||
| /// \brief Get output MindSpore Lite MSTensors of Training model prediction | /// \brief Get output MindSpore Lite MSTensors of Training model prediction | ||||
| /// | /// | ||||
| /// \return The map of output tensor name and MindSpore Lite MSTensor. | |||||
| virtual std::unordered_map<std::string, mindspore::tensor::MSTensor *> GetPredictions() const = 0; | |||||
| /// \return a vector of output tensors (MindSpore Lite MSTensor). | |||||
| virtual std::vector<tensor::MSTensor *> GetPredictions() const = 0; | |||||
| /// \brief Set part of the name that identify a loss kernel | |||||
| /// \param[in] loss_name Identifucation name for loss kernels | |||||
| void SetLossName(std::string loss_name) { loss_name_ = loss_name; } | |||||
| protected: | protected: | ||||
| bool train_mode_ = false; | bool train_mode_ = false; | ||||
| std::string get_loss_name() const { return loss_name_; } | |||||
| private: | |||||
| std::string loss_name_ = "_loss_fn"; | |||||
| }; | }; | ||||
| } // namespace session | } // namespace session | ||||
| } // namespace mindspore | } // namespace mindspore | ||||
| @@ -17,6 +17,7 @@ | |||||
| #include "nnacl/fp32_grad/arithmetic_grad.h" | #include "nnacl/fp32_grad/arithmetic_grad.h" | ||||
| #include <string.h> | #include <string.h> | ||||
| #include "nnacl/fp32_grad/utils.h" | #include "nnacl/fp32_grad/utils.h" | ||||
| #include "nnacl/errorcode.h" | |||||
| void ElementDivNegSquare(const float *nom, const float *denom, float *output, int element_size) { | void ElementDivNegSquare(const float *nom, const float *denom, float *output, int element_size) { | ||||
| for (int i = 0; i < element_size; i++) { | for (int i = 0; i < element_size; i++) { | ||||
| @@ -30,6 +31,13 @@ void ElementMulAndDivNegSquare(const float *a, const float *b, const float *deno | |||||
| } | } | ||||
| } | } | ||||
| int ElementAbsGrad(const float *in1, const float *in2, float *out, int element_size) { | |||||
| for (int i = 0; i < element_size; i++) { | |||||
| out[i] = (in1[i] < 0.f) ? -in2[i] : ((in1[i] > 0.f) ? in2[i] : 0); | |||||
| } | |||||
| return NNACL_OK; | |||||
| } | |||||
| void MaximumByAxes(const float *input0, const float *input1, const float *dy, const int *input0_dims, | void MaximumByAxes(const float *input0, const float *input1, const float *dy, const int *input0_dims, | ||||
| const int *input1_dims, const int *dy_dims, float *output0, float *output1, int num_dims) { | const int *input1_dims, const int *dy_dims, float *output0, float *output1, int num_dims) { | ||||
| int num_output0 = 1; | int num_output0 = 1; | ||||
| @@ -23,6 +23,7 @@ extern "C" { | |||||
| #endif | #endif | ||||
| void ElementDivNegSquare(const float *nom, const float *denom, float *output, int element_size); | void ElementDivNegSquare(const float *nom, const float *denom, float *output, int element_size); | ||||
| void ElementMulAndDivNegSquare(const float *a, const float *b, const float *denom, float *output, int element_size); | void ElementMulAndDivNegSquare(const float *a, const float *b, const float *denom, float *output, int element_size); | ||||
| int ElementAbsGrad(const float *in1, const float *in2, float *out, int element_size); | |||||
| void MaximumByAxes(const float *input0, const float *input1, const float *dy, const int *input0_dims, | void MaximumByAxes(const float *input0, const float *input1, const float *dy, const int *input0_dims, | ||||
| const int *input1_dims, const int *dy_dims, float *output0, float *output1, int num_dims); | const int *input1_dims, const int *dy_dims, float *output0, float *output1, int num_dims); | ||||
| void MinimumByAxes(const float *input0, const float *input1, const float *dy, const int *input0_dims, | void MinimumByAxes(const float *input0, const float *input1, const float *dy, const int *input0_dims, | ||||
| @@ -277,7 +277,8 @@ union PrimitiveType { | |||||
| IsFinite, | IsFinite, | ||||
| BatchMatMul, | BatchMatMul, | ||||
| LinSpace, | LinSpace, | ||||
| UniformReal | |||||
| UniformReal, | |||||
| AbsGrad | |||||
| } | } | ||||
| enum QuantType: int { | enum QuantType: int { | ||||
| @@ -1281,14 +1281,18 @@ table IsFinite { | |||||
| } | } | ||||
| table BatchMatMul { | table BatchMatMul { | ||||
| transpose_a :bool; | |||||
| transpose_b :bool; | |||||
| transpose_a :bool; | |||||
| transpose_b :bool; | |||||
| } | } | ||||
| table LinSpace { | table LinSpace { | ||||
| } | } | ||||
| table UniformReal { | table UniformReal { | ||||
| seed : int; | seed : int; | ||||
| seed2 : int; | seed2 : int; | ||||
| } | |||||
| table AbsGrad { | |||||
| transpose_a :bool; | |||||
| } | } | ||||
| @@ -94,10 +94,14 @@ if(SUPPORT_TRAIN) | |||||
| ${ANF_SRC} | ${ANF_SRC} | ||||
| ${CMAKE_CURRENT_SOURCE_DIR}/train/train_populate_parameter.cc | ${CMAKE_CURRENT_SOURCE_DIR}/train/train_populate_parameter.cc | ||||
| ${CMAKE_CURRENT_SOURCE_DIR}/train/train_session.cc | ${CMAKE_CURRENT_SOURCE_DIR}/train/train_session.cc | ||||
| ${CMAKE_CURRENT_SOURCE_DIR}/train/transfer_session.cc | |||||
| ${CMAKE_CURRENT_SOURCE_DIR}/train/train_model.cc | ${CMAKE_CURRENT_SOURCE_DIR}/train/train_model.cc | ||||
| ${CMAKE_CURRENT_SOURCE_DIR}/train/train_loop.cc | ${CMAKE_CURRENT_SOURCE_DIR}/train/train_loop.cc | ||||
| ${CMAKE_CURRENT_SOURCE_DIR}/train/train_utils.cc | |||||
| ${CMAKE_CURRENT_SOURCE_DIR}/train/loss_monitor.cc | ${CMAKE_CURRENT_SOURCE_DIR}/train/loss_monitor.cc | ||||
| ${CMAKE_CURRENT_SOURCE_DIR}/train/lr_scheduler.cc | ${CMAKE_CURRENT_SOURCE_DIR}/train/lr_scheduler.cc | ||||
| ${CMAKE_CURRENT_SOURCE_DIR}/train/accuracy_metrics.cc | |||||
| ${CMAKE_CURRENT_SOURCE_DIR}/train/accuracy_monitor.cc | |||||
| ${CMAKE_CURRENT_SOURCE_DIR}/train/classification_train_accuracy_monitor.cc | ${CMAKE_CURRENT_SOURCE_DIR}/train/classification_train_accuracy_monitor.cc | ||||
| ) | ) | ||||
| endif() | endif() | ||||
| @@ -141,6 +145,10 @@ if(BUILD_MINDDATA STREQUAL "lite") | |||||
| target_link_libraries(mindspore-lite minddata_eager_mid minddata-lite) | target_link_libraries(mindspore-lite minddata_eager_mid minddata-lite) | ||||
| target_link_libraries(mindspore-lite_static minddata_eager_mid) | target_link_libraries(mindspore-lite_static minddata_eager_mid) | ||||
| endif() | endif() | ||||
| if(SUPPORT_TRAIN) | |||||
| target_link_libraries(mindspore-lite minddata-lite) | |||||
| endif() | |||||
| if(PLATFORM_ARM) | if(PLATFORM_ARM) | ||||
| set(NDK_STRIP | set(NDK_STRIP | ||||
| @@ -0,0 +1,69 @@ | |||||
| /** | |||||
| * Copyright 2019-2020 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * 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 "src/ops/abs_grad.h" | |||||
| #ifndef PRIMITIVE_WRITEABLE | |||||
| #include "src/ops/ops_register.h" | |||||
| #endif | |||||
| #include "src/ops/arithmetic_self.h" | |||||
| namespace mindspore { | |||||
| namespace lite { | |||||
| #ifdef PRIMITIVE_WRITEABLE | |||||
| int AbsGrad::UnPackAttr(const Primitive &prim, const std::vector<AnfNodePtr> &inputs) { | |||||
| if (this->primitive_ == nullptr) { | |||||
| this->primitive_ = new (std::nothrow) schema::PrimitiveT; | |||||
| if (this->primitive_ == nullptr) { | |||||
| MS_LOG(ERROR) << "new primitiveT failed"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| this->primitive_->value.type = schema::PrimitiveType_AbsGrad; | |||||
| } | |||||
| if (this->primitive_->value.type != schema::PrimitiveType_AbsGrad) { | |||||
| MS_LOG(ERROR) << "Primitive type is error :" << this->primitive_->value.type; | |||||
| return RET_ERROR; | |||||
| } | |||||
| if (this->primitive_->value.value == nullptr) { | |||||
| this->primitive_->value.value = new (std::nothrow) schema::AbsGradT(); | |||||
| if (this->primitive_->value.value == nullptr) { | |||||
| MS_LOG(ERROR) << "new primitiveT value failed"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| #else | |||||
| int AbsGrad::UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) { | |||||
| MS_ASSERT(primitive != nullptr); | |||||
| MS_ASSERT(fbb != nullptr); | |||||
| auto attr = primitive->value_as_AbsGrad(); | |||||
| if (attr == nullptr) { | |||||
| MS_LOG(ERROR) << "value_as_AbsGrad return nullptr"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| auto val_offset = schema::CreateAbsGrad(*fbb); | |||||
| auto prim_offset = schema::CreatePrimitive(*fbb, schema::PrimitiveType_AbsGrad, val_offset.o); | |||||
| fbb->Finish(prim_offset); | |||||
| return RET_OK; | |||||
| } | |||||
| PrimitiveC *AbsGradCreator(const schema::Primitive *primitive) { return PrimitiveC::NewPrimitiveC<AbsGrad>(primitive); } | |||||
| Registry AbsGradRegistry(schema::PrimitiveType_AbsGrad, AbsGradCreator); | |||||
| #endif | |||||
| } // namespace lite | |||||
| } // namespace mindspore | |||||
| @@ -0,0 +1,42 @@ | |||||
| /** | |||||
| * Copyright 2019-2020 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * 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. | |||||
| */ | |||||
| #ifndef MINDSPORE_LITE_SRC_OPS_ABS_GRAD_H_ | |||||
| #define MINDSPORE_LITE_SRC_OPS_ABS_GRAD_H_ | |||||
| #include <vector> | |||||
| #include <set> | |||||
| #include <cmath> | |||||
| #include "src/ops/primitive_c.h" | |||||
| namespace mindspore { | |||||
| namespace lite { | |||||
| class AbsGrad : public PrimitiveC { | |||||
| public: | |||||
| AbsGrad() = default; | |||||
| ~AbsGrad() = default; | |||||
| #ifdef PRIMITIVE_WRITEABLE | |||||
| MS_DECLARE_PARENT(AbsGrad, PrimitiveC); | |||||
| explicit AbsGrad(schema::PrimitiveT *primitive) : PrimitiveC(primitive) {} | |||||
| int UnPackAttr(const Primitive &prim, const std::vector<AnfNodePtr> &inputs) override; | |||||
| #else | |||||
| int UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) override; | |||||
| #endif | |||||
| }; | |||||
| } // namespace lite | |||||
| } // namespace mindspore | |||||
| #endif // MINDSPORE_LITE_SRC_OPS_ABS_GRAD_H_ | |||||
| @@ -22,7 +22,30 @@ | |||||
| namespace mindspore { | namespace mindspore { | ||||
| namespace lite { | namespace lite { | ||||
| #ifndef PRIMITIVE_WRITEABLE | |||||
| #ifdef PRIMITIVE_WRITEABLE | |||||
| int FloorDiv::UnPackAttr(const Primitive &prim, const std::vector<AnfNodePtr> &inputs) { | |||||
| if (this->primitive_ == nullptr) { | |||||
| this->primitive_ = new (std::nothrow) schema::PrimitiveT; | |||||
| if (this->primitive_ == nullptr) { | |||||
| MS_LOG(ERROR) << "new primitiveT failed"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| this->primitive_->value.type = schema::PrimitiveType_FloorDiv; | |||||
| } | |||||
| if (this->primitive_->value.type != schema::PrimitiveType_FloorDiv) { | |||||
| MS_LOG(ERROR) << "Primitive type is error :" << this->primitive_->value.type; | |||||
| return RET_ERROR; | |||||
| } | |||||
| if (this->primitive_->value.value == nullptr) { | |||||
| this->primitive_->value.value = new (std::nothrow) schema::FloorDivT(); | |||||
| if (this->primitive_->value.value == nullptr) { | |||||
| MS_LOG(ERROR) << "new primitiveT value failed"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| #else | |||||
| int FloorDiv::UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) { | int FloorDiv::UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) { | ||||
| MS_ASSERT(nullptr != primitive); | MS_ASSERT(nullptr != primitive); | ||||
| @@ -14,8 +14,8 @@ | |||||
| * limitations under the License. | * limitations under the License. | ||||
| */ | */ | ||||
| #ifndef LITE_MINDSPORE_LITE_C_OPS_FLOOR_DIV_H_ | |||||
| #define LITE_MINDSPORE_LITE_C_OPS_FLOOR_DIV_H_ | |||||
| #ifndef MINDSPORE_LITE_SRC_OPS_FLOOR_DIV_H_ | |||||
| #define MINDSPORE_LITE_SRC_OPS_FLOOR_DIV_H_ | |||||
| #include <vector> | #include <vector> | ||||
| #include <set> | #include <set> | ||||
| @@ -31,6 +31,7 @@ class FloorDiv : public Arithmetic { | |||||
| #ifdef PRIMITIVE_WRITEABLE | #ifdef PRIMITIVE_WRITEABLE | ||||
| MS_DECLARE_PARENT(FloorDiv, Arithmetic); | MS_DECLARE_PARENT(FloorDiv, Arithmetic); | ||||
| explicit FloorDiv(schema::PrimitiveT *primitive) : Arithmetic(primitive) {} | explicit FloorDiv(schema::PrimitiveT *primitive) : Arithmetic(primitive) {} | ||||
| int UnPackAttr(const Primitive &prim, const std::vector<AnfNodePtr> &inputs) override; | |||||
| #else | #else | ||||
| int UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) override; | int UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) override; | ||||
| #endif | #endif | ||||
| @@ -38,4 +39,4 @@ class FloorDiv : public Arithmetic { | |||||
| } // namespace lite | } // namespace lite | ||||
| } // namespace mindspore | } // namespace mindspore | ||||
| #endif // LITE_MINDSPORE_LITE_C_OPS_FLOOR_DIV_H_ | |||||
| #endif // MINDSPORE_LITE_SRC_OPS_FLOOR_DIV_H_ | |||||
| @@ -40,6 +40,7 @@ Registry LogParameterRegistry(schema::PrimitiveType_Log, PopulateArithmeticSelf) | |||||
| Registry NegParameterRegistry(schema::PrimitiveType_Neg, PopulateArithmeticSelf); | Registry NegParameterRegistry(schema::PrimitiveType_Neg, PopulateArithmeticSelf); | ||||
| Registry NegGradParameterRegistry(schema::PrimitiveType_NegGrad, PopulateArithmeticSelf); | Registry NegGradParameterRegistry(schema::PrimitiveType_NegGrad, PopulateArithmeticSelf); | ||||
| Registry LogGradParameterRegistry(schema::PrimitiveType_LogGrad, PopulateArithmeticSelf); | Registry LogGradParameterRegistry(schema::PrimitiveType_LogGrad, PopulateArithmeticSelf); | ||||
| Registry AbsGradParameterRegistry(schema::PrimitiveType_AbsGrad, PopulateArithmeticSelf); | |||||
| Registry SqrtParameterRegistry(schema::PrimitiveType_Sqrt, PopulateArithmeticSelf); | Registry SqrtParameterRegistry(schema::PrimitiveType_Sqrt, PopulateArithmeticSelf); | ||||
| Registry SquareParameterRegistry(schema::PrimitiveType_Square, PopulateArithmeticSelf); | Registry SquareParameterRegistry(schema::PrimitiveType_Square, PopulateArithmeticSelf); | ||||
| Registry RsqrtParameterRegistry(schema::PrimitiveType_Rsqrt, PopulateArithmeticSelf); | Registry RsqrtParameterRegistry(schema::PrimitiveType_Rsqrt, PopulateArithmeticSelf); | ||||
| @@ -193,6 +193,7 @@ | |||||
| #include "src/ops/depend.h" | #include "src/ops/depend.h" | ||||
| #include "src/ops/flatten_grad.h" | #include "src/ops/flatten_grad.h" | ||||
| #include "src/ops/log_grad.h" | #include "src/ops/log_grad.h" | ||||
| #include "src/ops/abs_grad.h" | |||||
| #include "src/ops/sgd.h" | #include "src/ops/sgd.h" | ||||
| #include "src/ops/adam.h" | #include "src/ops/adam.h" | ||||
| #include "src/ops/assign.h" | #include "src/ops/assign.h" | ||||
| @@ -552,9 +553,11 @@ std::shared_ptr<PrimitiveC> PrimitiveC::Create(const Primitive &prim, const std: | |||||
| return NewPrimitiveC<Dequant>(prim, inputs, quantType); | return NewPrimitiveC<Dequant>(prim, inputs, quantType); | ||||
| } else if (op_type == "Flatten") { | } else if (op_type == "Flatten") { | ||||
| return NewPrimitiveC<Flatten>(prim, inputs, quantType); | return NewPrimitiveC<Flatten>(prim, inputs, quantType); | ||||
| } else if (op_type == "FloorDiv") { | |||||
| return NewPrimitiveC<FloorDiv>(prim, inputs, quantType); | |||||
| } else if ((op_type == "FusedBatchNorm") || (op_type == "FusedBatchNormEx")) { | } else if ((op_type == "FusedBatchNorm") || (op_type == "FusedBatchNormEx")) { | ||||
| return NewPrimitiveC<FusedBatchNorm>(prim, inputs, quantType); | return NewPrimitiveC<FusedBatchNorm>(prim, inputs, quantType); | ||||
| } else if (op_type == "make_tuple") { | |||||
| } else if ((op_type == "make_tuple") || (op_type == "MakeTuple")) { | |||||
| return NewPrimitiveC<MakeTuple>(prim, inputs, quantType); | return NewPrimitiveC<MakeTuple>(prim, inputs, quantType); | ||||
| } else if (op_type == "MatMul" || op_type == "BatchMatMul") { | } else if (op_type == "MatMul" || op_type == "BatchMatMul") { | ||||
| return NewPrimitiveC<MatMul>(prim, inputs, quantType); | return NewPrimitiveC<MatMul>(prim, inputs, quantType); | ||||
| @@ -582,6 +585,8 @@ std::shared_ptr<PrimitiveC> PrimitiveC::Create(const Primitive &prim, const std: | |||||
| return NewPrimitiveC<Reduce>(prim, inputs, quantType); | return NewPrimitiveC<Reduce>(prim, inputs, quantType); | ||||
| } else if (op_type == "Reshape") { | } else if (op_type == "Reshape") { | ||||
| return NewPrimitiveC<Reshape>(prim, inputs, quantType); | return NewPrimitiveC<Reshape>(prim, inputs, quantType); | ||||
| } else if (op_type == "Rsqrt") { | |||||
| return NewPrimitiveC<Rsqrt>(prim, inputs, quantType); | |||||
| } else if (op_type == "Sin") { | } else if (op_type == "Sin") { | ||||
| return NewPrimitiveC<Sin>(prim, inputs, quantType); | return NewPrimitiveC<Sin>(prim, inputs, quantType); | ||||
| } else if (op_type == "Slice") { | } else if (op_type == "Slice") { | ||||
| @@ -739,6 +744,8 @@ std::shared_ptr<PrimitiveC> PrimitiveC::Create(const Primitive &prim, const std: | |||||
| return NewPrimitiveC<Pad>(prim, inputs, quantType); | return NewPrimitiveC<Pad>(prim, inputs, quantType); | ||||
| } else if (op_type == "StridedSliceGrad") { | } else if (op_type == "StridedSliceGrad") { | ||||
| return NewPrimitiveC<StridedSliceGrad>(prim, inputs, quantType); | return NewPrimitiveC<StridedSliceGrad>(prim, inputs, quantType); | ||||
| } else if (op_type == "AbsGrad") { | |||||
| return NewPrimitiveC<AbsGrad>(prim, inputs, quantType); | |||||
| #else | #else | ||||
| } else if (op_type == "Conv2DBackpropInput") { | } else if (op_type == "Conv2DBackpropInput") { | ||||
| return NewPrimitiveC<DeConv2D>(prim, inputs, quantType); | return NewPrimitiveC<DeConv2D>(prim, inputs, quantType); | ||||
| @@ -1097,6 +1104,8 @@ PrimitiveC *PrimitiveC::Create(mindspore::schema::PrimitiveT *primitive) { | |||||
| return new (std::nothrow) NegGrad(primitive); | return new (std::nothrow) NegGrad(primitive); | ||||
| case schema::PrimitiveType_LogGrad: | case schema::PrimitiveType_LogGrad: | ||||
| return new (std::nothrow) LogGrad(primitive); | return new (std::nothrow) LogGrad(primitive); | ||||
| case schema::PrimitiveType_AbsGrad: | |||||
| return new (std::nothrow) AbsGrad(primitive); | |||||
| case schema::PrimitiveType_Sgd: | case schema::PrimitiveType_Sgd: | ||||
| return new (std::nothrow) Sgd(primitive); | return new (std::nothrow) Sgd(primitive); | ||||
| case schema::PrimitiveType_Adam: | case schema::PrimitiveType_Adam: | ||||
| @@ -23,6 +23,28 @@ | |||||
| namespace mindspore { | namespace mindspore { | ||||
| namespace lite { | namespace lite { | ||||
| #ifdef PRIMITIVE_WRITEABLE | #ifdef PRIMITIVE_WRITEABLE | ||||
| int Rsqrt::UnPackAttr(const Primitive &prim, const std::vector<AnfNodePtr> &inputs) { | |||||
| if (this->primitive_ == nullptr) { | |||||
| this->primitive_ = new (std::nothrow) schema::PrimitiveT; | |||||
| if (this->primitive_ == nullptr) { | |||||
| MS_LOG(ERROR) << "new primitiveT failed"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| this->primitive_->value.type = schema::PrimitiveType_Rsqrt; | |||||
| } | |||||
| if (this->primitive_->value.type != schema::PrimitiveType_Rsqrt) { | |||||
| MS_LOG(ERROR) << "Primitive type is error :" << this->primitive_->value.type; | |||||
| return RET_ERROR; | |||||
| } | |||||
| if (this->primitive_->value.value == nullptr) { | |||||
| this->primitive_->value.value = new (std::nothrow) schema::RsqrtT(); | |||||
| if (this->primitive_->value.value == nullptr) { | |||||
| MS_LOG(ERROR) << "new primitiveT value failed"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| #else | #else | ||||
| int Rsqrt::UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) { | int Rsqrt::UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) { | ||||
| MS_ASSERT(nullptr != primitive); | MS_ASSERT(nullptr != primitive); | ||||
| @@ -14,8 +14,8 @@ | |||||
| * limitations under the License. | * limitations under the License. | ||||
| */ | */ | ||||
| #ifndef LITE_MINDSPORE_LITE_C_OPS_RSQRT_H_ | |||||
| #define LITE_MINDSPORE_LITE_C_OPS_RSQRT_H_ | |||||
| #ifndef MINDSPORE_LITE_SRC_OPS_RSQRT_H_ | |||||
| #define MINDSPORE_LITE_SRC_OPS_RSQRT_H_ | |||||
| #include <vector> | #include <vector> | ||||
| #include <set> | #include <set> | ||||
| @@ -32,6 +32,7 @@ class Rsqrt : public ArithmeticSelf { | |||||
| #ifdef PRIMITIVE_WRITEABLE | #ifdef PRIMITIVE_WRITEABLE | ||||
| MS_DECLARE_PARENT(Rsqrt, ArithmeticSelf); | MS_DECLARE_PARENT(Rsqrt, ArithmeticSelf); | ||||
| explicit Rsqrt(schema::PrimitiveT *primitive) : ArithmeticSelf(primitive) {} | explicit Rsqrt(schema::PrimitiveT *primitive) : ArithmeticSelf(primitive) {} | ||||
| int UnPackAttr(const Primitive &prim, const std::vector<AnfNodePtr> &inputs) override; | |||||
| #else | #else | ||||
| int UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) override; | int UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) override; | ||||
| #endif | #endif | ||||
| @@ -39,4 +40,4 @@ class Rsqrt : public ArithmeticSelf { | |||||
| } // namespace lite | } // namespace lite | ||||
| } // namespace mindspore | } // namespace mindspore | ||||
| #endif // LITE_MINDSPORE_LITE_C_OPS_RSQRT_H_ | |||||
| #endif // MINDSPORE_LITE_SRC_OPS_RSQRT_H_ | |||||
| @@ -236,11 +236,11 @@ int StridedSliceGrad::InferShape(std::vector<lite::Tensor *> inputs, std::vector | |||||
| shrink_axis_mask_.resize(ndim_); | shrink_axis_mask_.resize(ndim_); | ||||
| for (size_t i = 0; i < ndim_; i++) { | for (size_t i = 0; i < ndim_; i++) { | ||||
| begins_mask_.at(i) = static_cast<uint32_t>(GetBeginMask()) & (1 << i); | |||||
| ends_mask_.at(i) = static_cast<uint32_t>(GetEndMask()) & (1 << i); | |||||
| ellipsis_mask_.at(i) = static_cast<uint32_t>(GetEllipsisMask()) & (1 << i); | |||||
| new_axis_mask_.at(i) = static_cast<uint32_t>(GetNewAxisMask()) & (1 << i); | |||||
| shrink_axis_mask_.at(i) = static_cast<uint32_t>(GetShrinkAxisMask()) & (1 << i); | |||||
| begins_mask_.at(i) = static_cast<bool>(GetBeginMask()) & (1 << i); | |||||
| ends_mask_.at(i) = static_cast<bool>(GetEndMask()) & (1 << i); | |||||
| ellipsis_mask_.at(i) = static_cast<bool>(GetEllipsisMask()) & (1 << i); | |||||
| new_axis_mask_.at(i) = static_cast<bool>(GetNewAxisMask()) & (1 << i); | |||||
| shrink_axis_mask_.at(i) = static_cast<bool>(GetShrinkAxisMask()) & (1 << i); | |||||
| } | } | ||||
| ApplyNewAxisMask(); | ApplyNewAxisMask(); | ||||
| @@ -56,6 +56,9 @@ void BatchnormCPUKernel::FillParam() { | |||||
| for (size_t i = 0; i < n_dim - 1; i++) { | for (size_t i = 0; i < n_dim - 1; i++) { | ||||
| param->unit_ *= input_shapes[i]; | param->unit_ *= input_shapes[i]; | ||||
| } | } | ||||
| if (default_momentum_ < 0.0f) { | |||||
| default_momentum_ = param->momentum_; | |||||
| } | |||||
| } | } | ||||
| int BatchnormCPUKernel::InitConstTensor() { | int BatchnormCPUKernel::InitConstTensor() { | ||||
| @@ -94,5 +97,22 @@ int BatchNormRun(void *cdata, int task_id) { | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| int BatchnormCPUKernel::set_momentum(float momentum) { | |||||
| auto param = reinterpret_cast<BatchNormParameter *>(op_parameter_); | |||||
| param->momentum_ = momentum; | |||||
| return RET_OK; | |||||
| } | |||||
| float BatchnormCPUKernel::get_momentum() { | |||||
| auto param = reinterpret_cast<BatchNormParameter *>(op_parameter_); | |||||
| return param->momentum_; | |||||
| } | |||||
| int BatchnormCPUKernel::RestoreDefaultMomentum() { | |||||
| set_momentum(default_momentum_); | |||||
| return RET_OK; | |||||
| } | |||||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_BatchNorm, LiteKernelCreator<BatchnormCPUKernel>) | REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_BatchNorm, LiteKernelCreator<BatchnormCPUKernel>) | ||||
| } // namespace mindspore::kernel | } // namespace mindspore::kernel | ||||
| @@ -14,8 +14,8 @@ | |||||
| * limitations under the License. | * limitations under the License. | ||||
| */ | */ | ||||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_BATCHNORM_H_ | |||||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_BATCHNORM_H_ | |||||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_BATCHNORM_FP32_H_ | |||||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_BATCHNORM_FP32_H_ | |||||
| #include <vector> | #include <vector> | ||||
| #include "src/lite_kernel.h" | #include "src/lite_kernel.h" | ||||
| @@ -40,15 +40,19 @@ class BatchnormCPUKernel : public LiteKernel { | |||||
| int Run() override; | int Run() override; | ||||
| virtual int InitConstTensor(); | virtual int InitConstTensor(); | ||||
| virtual int DoExecute(int task_id); | virtual int DoExecute(int task_id); | ||||
| virtual int set_momentum(float momentum); | |||||
| virtual float get_momentum(); | |||||
| virtual int RestoreDefaultMomentum(); | |||||
| protected: | protected: | ||||
| void FillParam(); | void FillParam(); | ||||
| void FreeMeanAndVariance(); | void FreeMeanAndVariance(); | ||||
| void *mean_ = nullptr; | void *mean_ = nullptr; | ||||
| void *variance_ = nullptr; | void *variance_ = nullptr; | ||||
| float default_momentum_ = -1.0f; | |||||
| }; | }; | ||||
| int BatchNormRun(void *cdata, int task_id); | int BatchNormRun(void *cdata, int task_id); | ||||
| } // namespace mindspore::kernel | } // namespace mindspore::kernel | ||||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_BATCHNORM_H_ | |||||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_BATCHNORM_FP32_H_ | |||||
| @@ -233,7 +233,7 @@ int Convolution1x1CPUKernel::Run() { | |||||
| MS_LOG(ERROR) << "Conv1x1 Malloc pack_input_ error!"; | MS_LOG(ERROR) << "Conv1x1 Malloc pack_input_ error!"; | ||||
| return RET_MEMORY_FAILED; | return RET_MEMORY_FAILED; | ||||
| } | } | ||||
| if (IsTrain()) { | |||||
| if (IsTrain() && is_trainable()) { | |||||
| PackWeight(); | PackWeight(); | ||||
| } | } | ||||
| @@ -283,7 +283,9 @@ void Convolution1x1CPUKernel::PackWeight() { | |||||
| int Convolution1x1CPUKernel::Eval() { | int Convolution1x1CPUKernel::Eval() { | ||||
| LiteKernel::Eval(); | LiteKernel::Eval(); | ||||
| PackWeight(); | |||||
| if (is_trainable()) { | |||||
| PackWeight(); | |||||
| } | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| @@ -55,6 +55,10 @@ class ConvolutionDelegateCPUKernel : public LiteKernel { | |||||
| LiteKernel::Train(); | LiteKernel::Train(); | ||||
| return conv_kernel_->Train(); | return conv_kernel_->Train(); | ||||
| } | } | ||||
| void set_trainable(bool trainable) override { | |||||
| LiteKernel::set_trainable(trainable); | |||||
| return conv_kernel_->set_trainable(trainable); | |||||
| } | |||||
| protected: | protected: | ||||
| bool need_free_weight_ = false; | bool need_free_weight_ = false; | ||||
| @@ -127,7 +127,7 @@ int ConvolutionDepthwise3x3CPUKernel::Run() { | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| if (IsTrain()) { | |||||
| if (IsTrain() && is_trainable()) { | |||||
| PackWeight(); | PackWeight(); | ||||
| } | } | ||||
| @@ -160,7 +160,9 @@ void ConvolutionDepthwise3x3CPUKernel::PackWeight() { | |||||
| int ConvolutionDepthwise3x3CPUKernel::Eval() { | int ConvolutionDepthwise3x3CPUKernel::Eval() { | ||||
| LiteKernel::Eval(); | LiteKernel::Eval(); | ||||
| PackWeight(); | |||||
| if (is_trainable()) { | |||||
| PackWeight(); | |||||
| } | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| @@ -105,7 +105,7 @@ int ConvDwRun(void *cdata, int task_id) { | |||||
| } | } | ||||
| int ConvolutionDepthwiseCPUKernel::Run() { | int ConvolutionDepthwiseCPUKernel::Run() { | ||||
| if (IsTrain()) { | |||||
| if (IsTrain() && is_trainable()) { | |||||
| PackWeight(); | PackWeight(); | ||||
| } | } | ||||
| @@ -132,7 +132,9 @@ void ConvolutionDepthwiseCPUKernel::PackWeight() { | |||||
| int ConvolutionDepthwiseCPUKernel::Eval() { | int ConvolutionDepthwiseCPUKernel::Eval() { | ||||
| LiteKernel::Eval(); | LiteKernel::Eval(); | ||||
| PackWeight(); | |||||
| if (is_trainable()) { | |||||
| PackWeight(); | |||||
| } | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| @@ -190,7 +190,7 @@ int ConvolutionDepthwiseIndirectCPUKernel::Run() { | |||||
| packed_input_ = input_ptr; | packed_input_ = input_ptr; | ||||
| } | } | ||||
| if (IsTrain()) { | |||||
| if (IsTrain() && is_trainable()) { | |||||
| PackWeight(); | PackWeight(); | ||||
| } | } | ||||
| @@ -224,7 +224,9 @@ void ConvolutionDepthwiseIndirectCPUKernel::PackWeight() { | |||||
| int ConvolutionDepthwiseIndirectCPUKernel::Eval() { | int ConvolutionDepthwiseIndirectCPUKernel::Eval() { | ||||
| LiteKernel::Eval(); | LiteKernel::Eval(); | ||||
| PackWeight(); | |||||
| if (is_trainable()) { | |||||
| PackWeight(); | |||||
| } | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| @@ -146,7 +146,7 @@ int ConvolutionDepthwiseSWCPUKernel::Run() { | |||||
| return RET_ERROR; | return RET_ERROR; | ||||
| } | } | ||||
| if (IsTrain()) { | |||||
| if (IsTrain() && is_trainable()) { | |||||
| PackWeight(); | PackWeight(); | ||||
| } | } | ||||
| @@ -198,7 +198,9 @@ void ConvolutionDepthwiseSWCPUKernel::PackWeight() { | |||||
| int ConvolutionDepthwiseSWCPUKernel::Eval() { | int ConvolutionDepthwiseSWCPUKernel::Eval() { | ||||
| LiteKernel::Eval(); | LiteKernel::Eval(); | ||||
| PackWeight(); | |||||
| if (is_trainable()) { | |||||
| PackWeight(); | |||||
| } | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| @@ -150,7 +150,7 @@ int ConvolutionCPUKernel::Run() { | |||||
| FreeTmpBuffer(); | FreeTmpBuffer(); | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| } | } | ||||
| if (IsTrain()) { | |||||
| if (IsTrain() && is_trainable()) { | |||||
| PackWeight(); | PackWeight(); | ||||
| } | } | ||||
| @@ -190,7 +190,9 @@ void ConvolutionCPUKernel::PackWeight() { | |||||
| int ConvolutionCPUKernel::Eval() { | int ConvolutionCPUKernel::Eval() { | ||||
| LiteKernel::Eval(); | LiteKernel::Eval(); | ||||
| PackWeight(); | |||||
| if (is_trainable()) { | |||||
| PackWeight(); | |||||
| } | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| @@ -221,7 +221,7 @@ int ConvolutionWinogradCPUKernel::Run() { | |||||
| FreeTmpBuffer(); | FreeTmpBuffer(); | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| } | } | ||||
| if (IsTrain()) { | |||||
| if (IsTrain() && is_trainable()) { | |||||
| InitWeightBias(); | InitWeightBias(); | ||||
| } | } | ||||
| @@ -236,7 +236,9 @@ int ConvolutionWinogradCPUKernel::Run() { | |||||
| int ConvolutionWinogradCPUKernel::Eval() { | int ConvolutionWinogradCPUKernel::Eval() { | ||||
| LiteKernel::Eval(); | LiteKernel::Eval(); | ||||
| InitWeightBias(); | |||||
| if (is_trainable()) { | |||||
| InitWeightBias(); | |||||
| } | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| @@ -32,25 +32,8 @@ namespace mindspore::kernel { | |||||
| int AdamCPUKernel::ReSize() { return RET_OK; } | int AdamCPUKernel::ReSize() { return RET_OK; } | ||||
| int AdamCPUKernel::Execute(int task_id) { | |||||
| auto weight = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | |||||
| auto m = reinterpret_cast<float *>(in_tensors_.at(1)->MutableData()); | |||||
| auto v = reinterpret_cast<float *>(in_tensors_.at(2)->MutableData()); | |||||
| auto beta1_power = reinterpret_cast<float *>(in_tensors_.at(3)->MutableData())[0]; | |||||
| auto beta2_power = reinterpret_cast<float *>(in_tensors_.at(4)->MutableData())[0]; | |||||
| auto learning_rate = reinterpret_cast<float *>(in_tensors_.at(5)->MutableData())[0]; | |||||
| auto beta1 = reinterpret_cast<float *>(in_tensors_.at(6)->MutableData())[0]; | |||||
| auto beta2 = reinterpret_cast<float *>(in_tensors_.at(7)->MutableData())[0]; | |||||
| auto eps = reinterpret_cast<float *>(in_tensors_.at(8)->MutableData())[0]; | |||||
| auto gradient = reinterpret_cast<float *>(in_tensors_.at(9)->MutableData()); | |||||
| size_t length = in_tensors_.at(0)->ElementsNum(); | |||||
| size_t stride = UP_DIV(length, thread_count_); | |||||
| size_t count = MSMIN(stride, length - stride * task_id); | |||||
| size_t start = stride * task_id; | |||||
| size_t end = start + count; | |||||
| int DoAdam(float *m, float *v, float *gradient, float *weight, float beta1, float beta2, float beta1_power, | |||||
| float beta2_power, float eps, float learning_rate, bool nesterov, size_t start, size_t end) { | |||||
| if ((1.f - beta1_power) <= 0.0f) { | if ((1.f - beta1_power) <= 0.0f) { | ||||
| MS_LOG(ERROR) << "divisor cannot be 0 or below"; | MS_LOG(ERROR) << "divisor cannot be 0 or below"; | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| @@ -63,8 +46,7 @@ int AdamCPUKernel::Execute(int task_id) { | |||||
| auto update_lr = learning_rate * std::sqrt(1.f - beta2_power) / (1.f - beta1_power); | auto update_lr = learning_rate * std::sqrt(1.f - beta2_power) / (1.f - beta1_power); | ||||
| const float one_minus_beta1 = 1.f - beta1; | const float one_minus_beta1 = 1.f - beta1; | ||||
| const float one_minus_beta2 = 1.f - beta2; | const float one_minus_beta2 = 1.f - beta2; | ||||
| if (adam_param_->use_nesterov_) { // Nadam | |||||
| if (nesterov) { // Nadam | |||||
| for (size_t i = start; i < end; ++i) { | for (size_t i = start; i < end; ++i) { | ||||
| m[i] += (gradient[i] - m[i]) * one_minus_beta1; | m[i] += (gradient[i] - m[i]) * one_minus_beta1; | ||||
| v[i] += (gradient[i] * gradient[i] - v[i]) * one_minus_beta2; | v[i] += (gradient[i] * gradient[i] - v[i]) * one_minus_beta2; | ||||
| @@ -80,10 +62,39 @@ int AdamCPUKernel::Execute(int task_id) { | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| int AdamCPUKernel::Execute(int task_id) { | |||||
| auto weight = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | |||||
| auto m = reinterpret_cast<float *>(in_tensors_.at(1)->MutableData()); | |||||
| auto v = reinterpret_cast<float *>(in_tensors_.at(2)->MutableData()); | |||||
| auto beta1_power = reinterpret_cast<float *>(in_tensors_.at(3)->MutableData())[0]; | |||||
| auto beta2_power = reinterpret_cast<float *>(in_tensors_.at(4)->MutableData())[0]; | |||||
| auto learning_rate = lr_; | |||||
| auto beta1 = reinterpret_cast<float *>(in_tensors_.at(6)->MutableData())[0]; | |||||
| auto beta2 = reinterpret_cast<float *>(in_tensors_.at(7)->MutableData())[0]; | |||||
| auto eps = reinterpret_cast<float *>(in_tensors_.at(8)->MutableData())[0]; | |||||
| auto gradient = reinterpret_cast<float *>(in_tensors_.at(9)->MutableData()); | |||||
| size_t length = in_tensors_.at(0)->ElementsNum(); | |||||
| size_t stride = UP_DIV(length, thread_count_); | |||||
| size_t count = MSMIN(stride, length - stride * task_id); | |||||
| size_t start = stride * task_id; | |||||
| size_t end = start + count; | |||||
| return DoAdam(m, v, gradient, weight, beta1, beta2, beta1_power, beta2_power, eps, learning_rate, | |||||
| adam_param_->use_nesterov_, start, end); | |||||
| } | |||||
| int AdamRun(void *cdata, int task_id) { | int AdamRun(void *cdata, int task_id) { | ||||
| MS_ASSERT(cdata != nullptr); | MS_ASSERT(cdata != nullptr); | ||||
| auto Adam_kernel = reinterpret_cast<AdamCPUKernel *>(cdata); | |||||
| auto error_code = Adam_kernel->Execute(task_id); | |||||
| auto adam_kernel = reinterpret_cast<AdamCPUKernel *>(cdata); | |||||
| auto error_code = RET_OK; | |||||
| if (adam_kernel->get_optimizer_mode() == OptimizerKernel::WeightUpdateMode::VIRTUAL_BATCH) { | |||||
| error_code = adam_kernel->ExecuteVirtualBatch(task_id); | |||||
| } else { | |||||
| error_code = adam_kernel->Execute(task_id); | |||||
| } | |||||
| if (error_code != RET_OK) { | if (error_code != RET_OK) { | ||||
| MS_LOG(ERROR) << "Adam run error task_id[" << task_id << "] error_code[" << error_code << "]"; | MS_LOG(ERROR) << "Adam run error task_id[" << task_id << "] error_code[" << error_code << "]"; | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| @@ -100,18 +111,38 @@ int AdamCPUKernel::Run() { | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| int AdamCPUKernel::SetLearningRate(float lr) { | |||||
| auto learning_rate_tensor = reinterpret_cast<float *>(in_tensors_.at(5)->MutableData()); | |||||
| learning_rate_tensor[0] = lr; | |||||
| int AdamCPUKernel::Init() { | |||||
| auto ret = OptimizerKernel::Init(); | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << "Failed to initialize Adam Kernel"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| float AdamCPUKernel::GetLearningRate() { | |||||
| auto learning_rate_tensor = reinterpret_cast<float *>(in_tensors_.at(5)->MutableData()); | |||||
| return learning_rate_tensor[0]; | |||||
| } | |||||
| int AdamCPUKernel::OptimizerStep() { | |||||
| auto weight = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | |||||
| auto m = reinterpret_cast<float *>(in_tensors_.at(1)->MutableData()); | |||||
| auto v = reinterpret_cast<float *>(in_tensors_.at(2)->MutableData()); | |||||
| auto beta1_power = reinterpret_cast<float *>(in_tensors_.at(3)->MutableData())[0]; | |||||
| auto beta2_power = reinterpret_cast<float *>(in_tensors_.at(4)->MutableData())[0]; | |||||
| auto learning_rate = lr_; | |||||
| auto beta1 = reinterpret_cast<float *>(in_tensors_.at(6)->MutableData())[0]; | |||||
| auto beta2 = reinterpret_cast<float *>(in_tensors_.at(7)->MutableData())[0]; | |||||
| auto eps = reinterpret_cast<float *>(in_tensors_.at(8)->MutableData())[0]; | |||||
| size_t length = in_tensors_.at(0)->ElementsNum(); | |||||
| int AdamCPUKernel::Init() { return RET_OK; } | |||||
| int ret = RET_OK; | |||||
| if (grad_sum_ != nullptr && valid_grad_sum_) { | |||||
| size_t start = 0; | |||||
| size_t end = length; | |||||
| ret = DoAdam(m, v, grad_sum_, weight, beta1, beta2, beta1_power, beta2_power, eps, learning_rate, | |||||
| adam_param_->use_nesterov_, start, end); | |||||
| std::fill(grad_sum_, grad_sum_ + length, 0); | |||||
| OptimizerKernel::OptimizerStep(); | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| kernel::LiteKernel *CpuAdamFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | kernel::LiteKernel *CpuAdamFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | ||||
| const std::vector<lite::Tensor *> &outputs, OpParameter *opParameter, | const std::vector<lite::Tensor *> &outputs, OpParameter *opParameter, | ||||
| @@ -27,16 +27,20 @@ class AdamCPUKernel : public OptimizerKernel { | |||||
| explicit AdamCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | explicit AdamCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | ||||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | ||||
| const mindspore::lite::PrimitiveC *primitive) | const mindspore::lite::PrimitiveC *primitive) | ||||
| : OptimizerKernel(parameter, inputs, outputs, ctx, primitive), thread_count_(ctx->thread_num_) { | |||||
| : OptimizerKernel(parameter, inputs, outputs, ctx, primitive, 5, 9), thread_count_(ctx->thread_num_) { | |||||
| adam_param_ = reinterpret_cast<AdamParameter *>(parameter); | adam_param_ = reinterpret_cast<AdamParameter *>(parameter); | ||||
| } | } | ||||
| ~AdamCPUKernel() override {} | |||||
| ~AdamCPUKernel() override { | |||||
| if (grad_sum_ != nullptr) { | |||||
| context_->allocator->Free(grad_sum_); | |||||
| grad_sum_ = nullptr; | |||||
| } | |||||
| } | |||||
| int Init() override; | int Init() override; | ||||
| int ReSize() override; | int ReSize() override; | ||||
| int Run() override; | int Run() override; | ||||
| int SetLearningRate(float lr) override; | |||||
| float GetLearningRate() override; | |||||
| int Execute(int task_id); | int Execute(int task_id); | ||||
| int OptimizerStep() override; | |||||
| private: | private: | ||||
| int thread_count_; | int thread_count_; | ||||
| @@ -30,10 +30,26 @@ using mindspore::schema::PrimitiveType_ApplyMomentum; | |||||
| namespace mindspore::kernel { | namespace mindspore::kernel { | ||||
| int ApplyMomentumCPUKernel::ReSize() { return RET_OK; } | int ApplyMomentumCPUKernel::ReSize() { return RET_OK; } | ||||
| int DoApplyMomentum(float *weight, float *accumulate, float learning_rate, float *gradient, float moment, bool nesterov, | |||||
| size_t start, size_t end) { | |||||
| if (nesterov) { | |||||
| for (size_t i = start; i < end; i++) { | |||||
| accumulate[i] = accumulate[i] * moment + gradient[i]; | |||||
| weight[i] -= (accumulate[i] * moment + gradient[i]) * learning_rate; | |||||
| } | |||||
| } else { | |||||
| for (size_t i = start; i < end; i++) { | |||||
| accumulate[i] = accumulate[i] * moment + gradient[i]; | |||||
| weight[i] -= accumulate[i] * learning_rate; | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| int ApplyMomentumCPUKernel::Execute(int task_id) { | int ApplyMomentumCPUKernel::Execute(int task_id) { | ||||
| auto weight = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | auto weight = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | ||||
| auto accumulate = reinterpret_cast<float *>(in_tensors_.at(1)->MutableData()); | auto accumulate = reinterpret_cast<float *>(in_tensors_.at(1)->MutableData()); | ||||
| float learning_rate = reinterpret_cast<float *>(in_tensors_.at(2)->MutableData())[0]; | |||||
| float learning_rate = lr_; | |||||
| auto gradient = reinterpret_cast<float *>(in_tensors_.at(3)->MutableData()); | auto gradient = reinterpret_cast<float *>(in_tensors_.at(3)->MutableData()); | ||||
| float moment = reinterpret_cast<float *>(in_tensors_.at(4)->MutableData())[0]; | float moment = reinterpret_cast<float *>(in_tensors_.at(4)->MutableData())[0]; | ||||
| size_t length = in_tensors_.at(0)->ElementsNum(); | size_t length = in_tensors_.at(0)->ElementsNum(); | ||||
| @@ -43,24 +59,20 @@ int ApplyMomentumCPUKernel::Execute(int task_id) { | |||||
| size_t start = stride * task_id; | size_t start = stride * task_id; | ||||
| size_t end = start + count; | size_t end = start + count; | ||||
| if (apply_momentum_param_->use_nesterov_) { | |||||
| for (size_t i = start; i < end; i++) { | |||||
| accumulate[i] = accumulate[i] * moment + gradient[i]; | |||||
| weight[i] -= (accumulate[i] * moment + gradient[i]) * learning_rate; | |||||
| } | |||||
| } else { | |||||
| for (size_t i = start; i < end; i++) { | |||||
| accumulate[i] = accumulate[i] * moment + gradient[i]; | |||||
| weight[i] -= accumulate[i] * learning_rate; | |||||
| } | |||||
| } | |||||
| DoApplyMomentum(weight, accumulate, learning_rate, gradient, moment, apply_momentum_param_->use_nesterov_, start, | |||||
| end); | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| int ApplyMomentumRun(void *cdata, int task_id) { | int ApplyMomentumRun(void *cdata, int task_id) { | ||||
| MS_ASSERT(cdata != nullptr); | MS_ASSERT(cdata != nullptr); | ||||
| auto applyMomentum_kernel = reinterpret_cast<ApplyMomentumCPUKernel *>(cdata); | auto applyMomentum_kernel = reinterpret_cast<ApplyMomentumCPUKernel *>(cdata); | ||||
| auto error_code = applyMomentum_kernel->Execute(task_id); | |||||
| auto error_code = RET_OK; | |||||
| if (applyMomentum_kernel->get_optimizer_mode() == OptimizerKernel::WeightUpdateMode::VIRTUAL_BATCH) { | |||||
| error_code = applyMomentum_kernel->ExecuteVirtualBatch(task_id); | |||||
| } else { | |||||
| error_code = applyMomentum_kernel->Execute(task_id); | |||||
| } | |||||
| if (error_code != RET_OK) { | if (error_code != RET_OK) { | ||||
| MS_LOG(ERROR) << "apply Momentum run error task_id[" << task_id << "] error_code[" << error_code << "]"; | MS_LOG(ERROR) << "apply Momentum run error task_id[" << task_id << "] error_code[" << error_code << "]"; | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| @@ -77,17 +89,31 @@ int ApplyMomentumCPUKernel::Run() { | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| int ApplyMomentumCPUKernel::Init() { return RET_OK; } | |||||
| int ApplyMomentumCPUKernel::SetLearningRate(float lr) { | |||||
| auto learning_rate_tensor = reinterpret_cast<float *>(in_tensors_.at(2)->MutableData()); | |||||
| learning_rate_tensor[0] = lr; | |||||
| int ApplyMomentumCPUKernel::Init() { | |||||
| auto ret = OptimizerKernel::Init(); | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << "Failed to initialize Apply Momentum Kernel"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| float ApplyMomentumCPUKernel::GetLearningRate() { | |||||
| auto learning_rate_tensor = reinterpret_cast<float *>(in_tensors_.at(2)->MutableData()); | |||||
| return learning_rate_tensor[0]; | |||||
| int ApplyMomentumCPUKernel::OptimizerStep() { | |||||
| auto weight = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | |||||
| auto accumulate = reinterpret_cast<float *>(in_tensors_.at(1)->MutableData()); | |||||
| float learning_rate = lr_; | |||||
| float moment = reinterpret_cast<float *>(in_tensors_.at(4)->MutableData())[0]; | |||||
| size_t length = in_tensors_.at(0)->ElementsNum(); | |||||
| if (grad_sum_ != nullptr && valid_grad_sum_) { | |||||
| size_t start = 0; | |||||
| size_t end = length; | |||||
| DoApplyMomentum(weight, accumulate, learning_rate, grad_sum_, moment, apply_momentum_param_->use_nesterov_, start, | |||||
| end); | |||||
| std::fill(grad_sum_, grad_sum_ + length, 0); | |||||
| OptimizerKernel::OptimizerStep(); | |||||
| } | |||||
| return RET_OK; | |||||
| } | } | ||||
| kernel::LiteKernel *CpuApplyMomentumFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | kernel::LiteKernel *CpuApplyMomentumFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | ||||
| @@ -27,23 +27,28 @@ class ApplyMomentumCPUKernel : public OptimizerKernel { | |||||
| explicit ApplyMomentumCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | explicit ApplyMomentumCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | ||||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | ||||
| const mindspore::lite::PrimitiveC *primitive) | const mindspore::lite::PrimitiveC *primitive) | ||||
| : OptimizerKernel(parameter, inputs, outputs, ctx, primitive), | |||||
| : OptimizerKernel(parameter, inputs, outputs, ctx, primitive, 2, 3), | |||||
| thread_count_(ctx->thread_num_), | thread_count_(ctx->thread_num_), | ||||
| apply_momentum_param_(nullptr) { | apply_momentum_param_(nullptr) { | ||||
| apply_momentum_param_ = reinterpret_cast<ApplyMomentumParameter *>(parameter); | apply_momentum_param_ = reinterpret_cast<ApplyMomentumParameter *>(parameter); | ||||
| } | } | ||||
| ~ApplyMomentumCPUKernel() override {} | |||||
| ~ApplyMomentumCPUKernel() override { | |||||
| if (grad_sum_ != nullptr) { | |||||
| context_->allocator->Free(grad_sum_); | |||||
| grad_sum_ = nullptr; | |||||
| } | |||||
| } | |||||
| int Init() override; | int Init() override; | ||||
| int ReSize() override; | int ReSize() override; | ||||
| int Run() override; | |||||
| int Execute(int task_id); | int Execute(int task_id); | ||||
| int SetLearningRate(float lr) override; | |||||
| float GetLearningRate() override; | |||||
| int Run() override; | |||||
| int OptimizerStep() override; | |||||
| private: | private: | ||||
| int thread_count_; | int thread_count_; | ||||
| ApplyMomentumParameter *apply_momentum_param_; | ApplyMomentumParameter *apply_momentum_param_; | ||||
| }; | }; | ||||
| } // namespace mindspore::kernel | } // namespace mindspore::kernel | ||||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_APPLY_MOMENTUM_H_ | #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_APPLY_MOMENTUM_H_ | ||||
| @@ -20,11 +20,13 @@ | |||||
| #include "include/errorcode.h" | #include "include/errorcode.h" | ||||
| #include "src/runtime/runtime_api.h" | #include "src/runtime/runtime_api.h" | ||||
| #include "nnacl/fp32/arithmetic_fp32.h" | #include "nnacl/fp32/arithmetic_fp32.h" | ||||
| #include "nnacl/fp32_grad/arithmetic_grad.h" | |||||
| using mindspore::kernel::KERNEL_ARCH::kCPU; | using mindspore::kernel::KERNEL_ARCH::kCPU; | ||||
| using mindspore::lite::KernelRegistrar; | using mindspore::lite::KernelRegistrar; | ||||
| using mindspore::lite::RET_ERROR; | using mindspore::lite::RET_ERROR; | ||||
| using mindspore::lite::RET_OK; | using mindspore::lite::RET_OK; | ||||
| using mindspore::schema::PrimitiveType_AbsGrad; | |||||
| using mindspore::schema::PrimitiveType_LogGrad; | using mindspore::schema::PrimitiveType_LogGrad; | ||||
| namespace mindspore::kernel { | namespace mindspore::kernel { | ||||
| @@ -42,6 +44,9 @@ int ArithmeticSelfGradCPUKernel::Init() { | |||||
| case PrimitiveType_LogGrad: | case PrimitiveType_LogGrad: | ||||
| self_grad_operation_ = ElementDiv; | self_grad_operation_ = ElementDiv; | ||||
| break; | break; | ||||
| case PrimitiveType_AbsGrad: | |||||
| self_grad_operation_ = ElementAbsGrad; | |||||
| break; | |||||
| default: | default: | ||||
| MS_LOG(ERROR) << "Unsupported type: " << type; | MS_LOG(ERROR) << "Unsupported type: " << type; | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| @@ -102,4 +107,5 @@ kernel::LiteKernel *CpuArithmeticSelfGradFp32KernelCreator(const std::vector<lit | |||||
| } | } | ||||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_LogGrad, CpuArithmeticSelfGradFp32KernelCreator) | REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_LogGrad, CpuArithmeticSelfGradFp32KernelCreator) | ||||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_AbsGrad, CpuArithmeticSelfGradFp32KernelCreator) | |||||
| } // namespace mindspore::kernel | } // namespace mindspore::kernel | ||||
| @@ -32,10 +32,68 @@ namespace mindspore::kernel { | |||||
| int SgdCPUKernel::ReSize() { return RET_OK; } | int SgdCPUKernel::ReSize() { return RET_OK; } | ||||
| int DoSgd(float *weight, float *accumulate, float *gradient, float learning_rate, float dampening, float moment, | |||||
| bool nesterov, size_t start, size_t end) { | |||||
| if (moment > 0.f) { | |||||
| if (nesterov) { | |||||
| for (size_t i = start; i < end; ++i) { | |||||
| accumulate[i] = accumulate[i] * moment + gradient[i] * (1.f - dampening); | |||||
| weight[i] -= (accumulate[i] * moment + gradient[i]) * learning_rate; | |||||
| } | |||||
| } else { | |||||
| for (size_t i = start; i < end; ++i) { | |||||
| accumulate[i] = accumulate[i] * moment + gradient[i] * (1.f - dampening); | |||||
| weight[i] -= accumulate[i] * learning_rate; | |||||
| } | |||||
| } | |||||
| } else { | |||||
| for (size_t i = start; i < end; ++i) { | |||||
| weight[i] -= gradient[i] * learning_rate; | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| int DoSgdInit(float *weight, float *accumulate, float *gradient, float *stat, float learning_rate, float dampening, | |||||
| float moment, bool nesterov, size_t start, size_t end) { | |||||
| std::copy(&(gradient[start]), &(gradient[end]), &(accumulate[start])); | |||||
| if (nesterov) { | |||||
| for (size_t i = start; i < end; ++i) { | |||||
| weight[i] -= (accumulate[i] * moment + gradient[i]) * learning_rate; | |||||
| } | |||||
| } else { | |||||
| for (size_t i = start; i < end; ++i) { | |||||
| weight[i] -= accumulate[i] * learning_rate; | |||||
| } | |||||
| } | |||||
| *stat = 1.0f; | |||||
| return RET_OK; | |||||
| } | |||||
| int SgdCPUKernel::Execute(int task_id) { | int SgdCPUKernel::Execute(int task_id) { | ||||
| auto weight = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | auto weight = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | ||||
| auto accumulate = reinterpret_cast<float *>(in_tensors_.at(3)->MutableData()); | auto accumulate = reinterpret_cast<float *>(in_tensors_.at(3)->MutableData()); | ||||
| float learning_rate = reinterpret_cast<float *>(in_tensors_.at(2)->MutableData())[0]; | |||||
| float learning_rate = lr_; | |||||
| auto gradient = reinterpret_cast<float *>(in_tensors_.at(1)->MutableData()); | |||||
| float moment = reinterpret_cast<float *>(in_tensors_.at(4)->MutableData())[0]; | |||||
| size_t length = in_tensors_.at(0)->ElementsNum(); | |||||
| size_t stride = UP_DIV(length, thread_count_); | |||||
| size_t count = MSMIN(stride, length - stride * task_id); | |||||
| size_t start = stride * task_id; | |||||
| size_t end = start + count; | |||||
| DoSgd(weight, accumulate, gradient, learning_rate, sgd_param_->dampening_, moment, sgd_param_->use_nesterov_, start, | |||||
| end); | |||||
| return RET_OK; | |||||
| } | |||||
| int SgdCPUKernel::ExecuteInit(int task_id) { | |||||
| auto weight = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | |||||
| auto accumulate = reinterpret_cast<float *>(in_tensors_.at(3)->MutableData()); | |||||
| float learning_rate = lr_; | |||||
| auto gradient = reinterpret_cast<float *>(in_tensors_.at(1)->MutableData()); | auto gradient = reinterpret_cast<float *>(in_tensors_.at(1)->MutableData()); | ||||
| float moment = reinterpret_cast<float *>(in_tensors_.at(4)->MutableData())[0]; | float moment = reinterpret_cast<float *>(in_tensors_.at(4)->MutableData())[0]; | ||||
| auto stat = reinterpret_cast<float *>(in_tensors_.at(5)->MutableData()); | auto stat = reinterpret_cast<float *>(in_tensors_.at(5)->MutableData()); | ||||
| @@ -47,43 +105,34 @@ int SgdCPUKernel::Execute(int task_id) { | |||||
| size_t start = stride * task_id; | size_t start = stride * task_id; | ||||
| size_t end = start + count; | size_t end = start + count; | ||||
| if (stat[task_id] > 0) { | |||||
| stat[task_id] = 0; // Haim Please approve this | |||||
| std::copy(&(gradient[start]), &(gradient[end]), &(accumulate[start])); | |||||
| if (sgd_param_->use_nesterov_) { | |||||
| for (size_t i = start; i < end; ++i) { | |||||
| weight[i] -= (accumulate[i] * moment + gradient[i]) * learning_rate; | |||||
| } | |||||
| } else { | |||||
| for (size_t i = start; i < end; ++i) { | |||||
| weight[i] -= accumulate[i] * learning_rate; | |||||
| } | |||||
| } | |||||
| DoSgdInit(weight, accumulate, gradient, stat, learning_rate, sgd_param_->dampening_, moment, | |||||
| sgd_param_->use_nesterov_, start, end); | |||||
| return RET_OK; | |||||
| } | |||||
| int SgdRun(void *cdata, int task_id) { | |||||
| auto sgd_kernel = reinterpret_cast<SgdCPUKernel *>(cdata); | |||||
| auto error_code = RET_OK; | |||||
| if (sgd_kernel->get_optimizer_mode() == OptimizerKernel::WeightUpdateMode::VIRTUAL_BATCH) { | |||||
| error_code = sgd_kernel->ExecuteVirtualBatch(task_id); | |||||
| } else { | } else { | ||||
| if (moment > 0.f) { | |||||
| if (sgd_param_->use_nesterov_) { | |||||
| for (size_t i = start; i < end; ++i) { | |||||
| accumulate[i] = accumulate[i] * moment + gradient[i] * (1.f - sgd_param_->dampening_); | |||||
| weight[i] -= (accumulate[i] * moment + gradient[i]) * learning_rate; | |||||
| } | |||||
| } else { | |||||
| for (size_t i = start; i < end; ++i) { | |||||
| accumulate[i] = accumulate[i] * moment + gradient[i] * (1.f - sgd_param_->dampening_); | |||||
| weight[i] -= accumulate[i] * learning_rate; | |||||
| } | |||||
| } | |||||
| } else { | |||||
| for (size_t i = start; i < end; ++i) { | |||||
| weight[i] -= gradient[i] * learning_rate; | |||||
| } | |||||
| } | |||||
| error_code = sgd_kernel->Execute(task_id); | |||||
| } | |||||
| if (error_code != RET_OK) { | |||||
| MS_LOG(ERROR) << "SGD run error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||||
| return RET_ERROR; | |||||
| } | } | ||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| int SgdRun(void *cdata, int task_id) { | |||||
| auto Sgd_kernel = reinterpret_cast<SgdCPUKernel *>(cdata); | |||||
| auto error_code = Sgd_kernel->Execute(task_id); | |||||
| int SgdRunInit(void *cdata, int task_id) { | |||||
| auto sgd_kernel = reinterpret_cast<SgdCPUKernel *>(cdata); | |||||
| auto error_code = RET_OK; | |||||
| if (sgd_kernel->get_optimizer_mode() == OptimizerKernel::WeightUpdateMode::VIRTUAL_BATCH) { | |||||
| error_code = sgd_kernel->ExecuteVirtualBatch(task_id); | |||||
| } else { | |||||
| error_code = sgd_kernel->ExecuteInit(task_id); | |||||
| } | |||||
| if (error_code != RET_OK) { | if (error_code != RET_OK) { | ||||
| MS_LOG(ERROR) << "SGD run error task_id[" << task_id << "] error_code[" << error_code << "]"; | MS_LOG(ERROR) << "SGD run error task_id[" << task_id << "] error_code[" << error_code << "]"; | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| @@ -92,7 +141,13 @@ int SgdRun(void *cdata, int task_id) { | |||||
| } | } | ||||
| int SgdCPUKernel::Run() { | int SgdCPUKernel::Run() { | ||||
| int error_code = ParallelLaunch(this->context_->thread_pool_, SgdRun, this, thread_count_); | |||||
| auto stat = reinterpret_cast<float *>(in_tensors_.at(5)->MutableData()); | |||||
| auto error_code = RET_OK; | |||||
| if (*stat > 0.0f) { | |||||
| error_code = ParallelLaunch(this->context_->thread_pool_, SgdRunInit, this, thread_count_); | |||||
| } else { | |||||
| error_code = ParallelLaunch(this->context_->thread_pool_, SgdRun, this, thread_count_); | |||||
| } | |||||
| if (error_code != RET_OK) { | if (error_code != RET_OK) { | ||||
| MS_LOG(ERROR) << "SGD function error error_code[" << error_code << "]"; | MS_LOG(ERROR) << "SGD function error error_code[" << error_code << "]"; | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| @@ -101,13 +156,6 @@ int SgdCPUKernel::Run() { | |||||
| } | } | ||||
| int SgdCPUKernel::Init() { | int SgdCPUKernel::Init() { | ||||
| // Only for test with uninitialized Data | |||||
| size_t elem_num = in_tensors_.at(0)->ElementsNum(); | |||||
| auto accumulate = reinterpret_cast<float *>(in_tensors_.at(3)->MutableData()); | |||||
| for (size_t i = 0; i < elem_num; i++) { | |||||
| accumulate[i] = 0.0; | |||||
| } | |||||
| if (sgd_param_->dampening_ < 0.0f) { | if (sgd_param_->dampening_ < 0.0f) { | ||||
| MS_LOG(ERROR) << "dampening should be at least 0.0"; | MS_LOG(ERROR) << "dampening should be at least 0.0"; | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| @@ -117,19 +165,37 @@ int SgdCPUKernel::Init() { | |||||
| MS_LOG(ERROR) << "If use nesterov, dampening must equal to 0.0"; | MS_LOG(ERROR) << "If use nesterov, dampening must equal to 0.0"; | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| } | } | ||||
| auto ret = OptimizerKernel::Init(); | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << "Failed to initialize Sgd Kernel"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| int SgdCPUKernel::SetLearningRate(float lr) { | |||||
| auto learning_rate_tensor = reinterpret_cast<float *>(in_tensors_.at(2)->MutableData()); | |||||
| learning_rate_tensor[0] = lr; | |||||
| return RET_OK; | |||||
| } | |||||
| int SgdCPUKernel::OptimizerStep() { | |||||
| auto weight = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | |||||
| auto accumulate = reinterpret_cast<float *>(in_tensors_.at(3)->MutableData()); | |||||
| float learning_rate = lr_; | |||||
| auto stat = reinterpret_cast<float *>(in_tensors_.at(5)->MutableData()); | |||||
| float moment = reinterpret_cast<float *>(in_tensors_.at(4)->MutableData())[0]; | |||||
| size_t length = in_tensors_.at(0)->ElementsNum(); | |||||
| float SgdCPUKernel::GetLearningRate() { | |||||
| auto learning_rate_tensor = reinterpret_cast<float *>(in_tensors_.at(2)->MutableData()); | |||||
| return learning_rate_tensor[0]; | |||||
| if (grad_sum_ != nullptr && valid_grad_sum_) { | |||||
| size_t start = 0; | |||||
| size_t end = length; | |||||
| if (*stat > 0) { | |||||
| DoSgd(weight, accumulate, grad_sum_, learning_rate, sgd_param_->dampening_, moment, sgd_param_->use_nesterov_, | |||||
| start, end); | |||||
| } else { | |||||
| DoSgdInit(weight, accumulate, grad_sum_, stat, learning_rate, sgd_param_->dampening_, moment, | |||||
| sgd_param_->use_nesterov_, start, end); | |||||
| } | |||||
| std::fill(grad_sum_, grad_sum_ + length, 0); | |||||
| OptimizerKernel::OptimizerStep(); | |||||
| } | |||||
| return RET_OK; | |||||
| } | } | ||||
| kernel::LiteKernel *CpuSgdFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | kernel::LiteKernel *CpuSgdFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | ||||
| @@ -27,18 +27,23 @@ class SgdCPUKernel : public OptimizerKernel { | |||||
| explicit SgdCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | explicit SgdCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | ||||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | ||||
| const mindspore::lite::PrimitiveC *primitive) | const mindspore::lite::PrimitiveC *primitive) | ||||
| : OptimizerKernel(parameter, inputs, outputs, ctx, primitive), | |||||
| : OptimizerKernel(parameter, inputs, outputs, ctx, primitive, 2, 1), | |||||
| thread_count_(ctx->thread_num_), | thread_count_(ctx->thread_num_), | ||||
| sgd_param_(nullptr) { | sgd_param_(nullptr) { | ||||
| sgd_param_ = reinterpret_cast<SgdParameter *>(parameter); | sgd_param_ = reinterpret_cast<SgdParameter *>(parameter); | ||||
| } | } | ||||
| ~SgdCPUKernel() override {} | |||||
| ~SgdCPUKernel() override { | |||||
| if (grad_sum_ != nullptr) { | |||||
| context_->allocator->Free(grad_sum_); | |||||
| grad_sum_ = nullptr; | |||||
| } | |||||
| } | |||||
| int Init() override; | int Init() override; | ||||
| int ReSize() override; | int ReSize() override; | ||||
| int Run() override; | int Run() override; | ||||
| int ExecuteInit(int task_id); | |||||
| int Execute(int task_id); | int Execute(int task_id); | ||||
| int SetLearningRate(float lr) override; | |||||
| float GetLearningRate() override; | |||||
| int OptimizerStep() override; | |||||
| private: | private: | ||||
| int thread_count_; | int thread_count_; | ||||
| @@ -136,9 +136,13 @@ int StridedSliceGradCPUKernel::Execute(int task_id) { | |||||
| auto input = in_tensors_.at(0); | auto input = in_tensors_.at(0); | ||||
| auto output = out_tensors_.at(0); | auto output = out_tensors_.at(0); | ||||
| MS_ASSERT(output); | MS_ASSERT(output); | ||||
| int *po = output_shape_.data(); | int *po = output_shape_.data(); | ||||
| auto ret = DoStridedSliceGrad(reinterpret_cast<float *>(input->MutableData()), | |||||
| reinterpret_cast<float *>(output->MutableData()), po, param_); | |||||
| auto dx = reinterpret_cast<float *>(output->MutableData()); | |||||
| auto dy = reinterpret_cast<float *>(input->MutableData()); | |||||
| std::fill(dx, dx + output->ElementsNum(), 0.f); | |||||
| auto ret = DoStridedSliceGrad(dy, dx, po, param_); | |||||
| if (ret != RET_OK) { | if (ret != RET_OK) { | ||||
| MS_LOG(ERROR) << "StridedSliceGrad error error_code[" << ret << "]"; | MS_LOG(ERROR) << "StridedSliceGrad error error_code[" << ret << "]"; | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| @@ -0,0 +1,71 @@ | |||||
| /** | |||||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * 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/train/accuracy_metrics.h" | |||||
| #include "include/errorcode.h" | |||||
| #include "src/common/utils.h" | |||||
| #include "src/tensor.h" | |||||
| #include "src/train/train_utils.h" | |||||
| namespace mindspore { | |||||
| namespace lite { | |||||
| AccuracyMetrics::AccuracyMetrics(int accuracy_metrics, const std::vector<int> &input_indexes, | |||||
| const std::vector<int> &output_indexes) | |||||
| : Metrics() { | |||||
| if (input_indexes.size() == output_indexes.size()) { | |||||
| input_indexes_ = input_indexes; | |||||
| output_indexes_ = output_indexes; | |||||
| } else { | |||||
| MS_LOG(WARNING) << "input to output mapping vectors sizes do not match"; | |||||
| } | |||||
| if (accuracy_metrics != METRICS_CLASSIFICATION) { | |||||
| MS_LOG(WARNING) << "Only classification metrics is supported"; | |||||
| } else { | |||||
| accuracy_metrics_ = accuracy_metrics; | |||||
| } | |||||
| } | |||||
| void AccuracyMetrics::Update(std::vector<tensor::MSTensor *> inputs, std::vector<tensor::MSTensor *> outputs) { | |||||
| for (unsigned int i = 0; i < input_indexes_.size(); i++) { | |||||
| if ((inputs.size() <= static_cast<unsigned int>(input_indexes_[i])) || | |||||
| (outputs.size() <= static_cast<unsigned int>(output_indexes_[i]))) { | |||||
| MS_LOG(WARNING) << "indices " << input_indexes_[i] << "/" << output_indexes_[i] | |||||
| << " is outside of input/output range"; | |||||
| return; | |||||
| } | |||||
| float accuracy = 0.0; | |||||
| if (inputs.at(input_indexes_[i])->data_type() == kNumberTypeInt32) { | |||||
| accuracy = CalculateSparseClassification(inputs.at(input_indexes_[i]), outputs.at(output_indexes_[i])); | |||||
| } else { | |||||
| accuracy = CalculateOneHotClassification(inputs.at(input_indexes_[i]), outputs.at(output_indexes_[i])); | |||||
| } | |||||
| total_accuracy_ += accuracy; | |||||
| total_steps_ += 1.0; | |||||
| } | |||||
| } | |||||
| float AccuracyMetrics::Eval() { | |||||
| if (total_steps_ == 0.0) { | |||||
| MS_LOG(WARNING) << "Accuary can not be calculated, because the number of samples is 0."; | |||||
| return 0.0; | |||||
| } | |||||
| return (total_accuracy_ / total_steps_); | |||||
| } | |||||
| } // namespace lite | |||||
| } // namespace mindspore | |||||
| @@ -0,0 +1,45 @@ | |||||
| /** | |||||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * 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/train/accuracy_monitor.h" | |||||
| #include <sys/stat.h> | |||||
| #include <algorithm> | |||||
| #include <utility> | |||||
| #include <vector> | |||||
| #include <iostream> | |||||
| #include <fstream> | |||||
| #include <memory> | |||||
| #include "include/errorcode.h" | |||||
| #include "include/train/train_loop.h" | |||||
| #include "src/common/utils.h" | |||||
| #include "src/tensor.h" | |||||
| namespace mindspore { | |||||
| namespace lite { | |||||
| void AccuracyMonitor::Begin(const session::TrainLoopCallBackData &cb_data) { | |||||
| if (cb_data.epoch_ == 0) accuracies_.clear(); | |||||
| } | |||||
| int AccuracyMonitor::EpochEnd(const session::TrainLoopCallBackData &cb_data) { | |||||
| if ((cb_data.epoch_ + 1) % check_every_n_ == 0) cb_data.loop_->Eval(ds_, {}, nullptr, max_steps_); | |||||
| accuracies_.push_back(std::make_pair(cb_data.epoch_, 0.0)); | |||||
| return mindspore::session::RET_CONTINUE; | |||||
| } | |||||
| } // namespace lite | |||||
| } // namespace mindspore | |||||
| @@ -16,28 +16,32 @@ | |||||
| #include "include/train/classification_train_accuracy_monitor.h" | #include "include/train/classification_train_accuracy_monitor.h" | ||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||
| #include <algorithm> | |||||
| #include <utility> | |||||
| #include <vector> | #include <vector> | ||||
| #include <iostream> | |||||
| #include <fstream> | |||||
| #include <memory> | |||||
| #include "include/errorcode.h" | #include "include/errorcode.h" | ||||
| #include "include/train_session.h" | #include "include/train_session.h" | ||||
| #include "src/common/utils.h" | #include "src/common/utils.h" | ||||
| #include "src/tensor.h" | |||||
| #include "src/train/loss_kernel.h" | |||||
| #include "src/train/optimizer_kernel.h" | |||||
| #include "src/sub_graph_kernel.h" | |||||
| #include "src/train/train_populate_parameter.h" | |||||
| #include "src/runtime/runtime_api.h" | |||||
| #include "src/executor.h" | |||||
| #include "src/kernel_registry.h" | |||||
| #include "src/runtime/kernel/arm/fp32_grad/convolution.h" | |||||
| #include "src/train/train_utils.h" | |||||
| namespace mindspore { | namespace mindspore { | ||||
| namespace lite { | namespace lite { | ||||
| ClassificationTrainAccuracyMonitor::ClassificationTrainAccuracyMonitor(int print_every_n, int accuracy_metrics, | |||||
| const std::vector<int> &input_indexes, | |||||
| const std::vector<int> &output_indexes) { | |||||
| if (input_indexes.size() == output_indexes.size()) { | |||||
| input_indexes_ = input_indexes; | |||||
| output_indexes_ = output_indexes; | |||||
| } else { | |||||
| MS_LOG(WARNING) << "input to output mapping vectors sizes do not match"; | |||||
| } | |||||
| if (accuracy_metrics != METRICS_CLASSIFICATION) { | |||||
| MS_LOG(WARNING) << "Only classification metrics is supported"; | |||||
| } else { | |||||
| accuracy_metrics_ = accuracy_metrics; | |||||
| } | |||||
| print_every_n_ = print_every_n; | |||||
| } | |||||
| void ClassificationTrainAccuracyMonitor::Begin(const session::TrainLoopCallBackData &cb_data) { | void ClassificationTrainAccuracyMonitor::Begin(const session::TrainLoopCallBackData &cb_data) { | ||||
| if (cb_data.epoch_ == 0) accuracies_.clear(); | if (cb_data.epoch_ == 0) accuracies_.clear(); | ||||
| } | } | ||||
| @@ -51,9 +55,10 @@ void ClassificationTrainAccuracyMonitor::EpochBegin(const session::TrainLoopCall | |||||
| } | } | ||||
| int ClassificationTrainAccuracyMonitor::EpochEnd(const session::TrainLoopCallBackData &cb_data) { | int ClassificationTrainAccuracyMonitor::EpochEnd(const session::TrainLoopCallBackData &cb_data) { | ||||
| if (cb_data.step_ > 0) accuracies_.at(cb_data.epoch_).second /= static_cast<float>(cb_data.step_); | |||||
| if (cb_data.step_ > 0) accuracies_.at(cb_data.epoch_).second /= static_cast<float>(cb_data.step_ + 1); | |||||
| if ((cb_data.epoch_ + 1) % print_every_n_ == 0) { | if ((cb_data.epoch_ + 1) % print_every_n_ == 0) { | ||||
| std::cout << cb_data.epoch_ + 1 << ":\tTraining Accuracy is " << accuracies_.at(cb_data.epoch_).second << std::endl; | |||||
| std::cout << "Epoch (" << cb_data.epoch_ + 1 << "):\tTraining Accuracy is " << accuracies_.at(cb_data.epoch_).second | |||||
| << std::endl; | |||||
| } | } | ||||
| return mindspore::session::RET_CONTINUE; | return mindspore::session::RET_CONTINUE; | ||||
| } | } | ||||
| @@ -61,37 +66,22 @@ int ClassificationTrainAccuracyMonitor::EpochEnd(const session::TrainLoopCallBac | |||||
| void ClassificationTrainAccuracyMonitor::StepEnd(const session::TrainLoopCallBackData &cb_data) { | void ClassificationTrainAccuracyMonitor::StepEnd(const session::TrainLoopCallBackData &cb_data) { | ||||
| auto inputs = cb_data.session_->GetInputs(); | auto inputs = cb_data.session_->GetInputs(); | ||||
| auto outputs = cb_data.session_->GetPredictions(); | auto outputs = cb_data.session_->GetPredictions(); | ||||
| auto labels = reinterpret_cast<float *>(inputs.at(1)->MutableData()); | |||||
| for (auto it = outputs.begin(); it != outputs.end(); ++it) { | |||||
| if (it->second->ElementsNum() == inputs.at(1)->ElementsNum()) { | |||||
| int batch_size = inputs.at(1)->shape().at(0); | |||||
| int num_of_classes = inputs.at(1)->shape().at(1); | |||||
| auto predictions = reinterpret_cast<float *>(it->second->MutableData()); | |||||
| float accuracy = 0.0; | |||||
| for (int b = 0; b < batch_size; b++) { | |||||
| int label = 0; | |||||
| int max_idx = 0; | |||||
| float max_label_score = labels[num_of_classes * b]; | |||||
| float max_score = predictions[num_of_classes * b]; | |||||
| for (int c = 1; c < num_of_classes; c++) { | |||||
| if (predictions[num_of_classes * b + c] > max_score) { | |||||
| max_score = predictions[num_of_classes * b + c]; | |||||
| max_idx = c; | |||||
| } | |||||
| if (labels[num_of_classes * b + c] > max_label_score) { | |||||
| max_label_score = labels[num_of_classes * b + c]; | |||||
| label = c; | |||||
| } | |||||
| } | |||||
| if (label == max_idx) accuracy += 1.0; | |||||
| } | |||||
| accuracy /= static_cast<float>(batch_size); | |||||
| accuracies_.at(cb_data.epoch_).second = accuracy; | |||||
| float accuracy = 0.0; | |||||
| for (unsigned int i = 0; i < input_indexes_.size(); i++) { | |||||
| if ((inputs.size() <= static_cast<unsigned int>(input_indexes_[i])) || | |||||
| (outputs.size() <= static_cast<unsigned int>(output_indexes_[i]))) { | |||||
| MS_LOG(WARNING) << "indices " << input_indexes_[i] << "/" << output_indexes_[i] | |||||
| << " is outside of input/output range"; | |||||
| return; | return; | ||||
| } | } | ||||
| if (inputs.at(input_indexes_[i])->data_type() == kNumberTypeInt32) { | |||||
| accuracy += CalculateSparseClassification(inputs.at(input_indexes_[i]), outputs.at(output_indexes_[i])); | |||||
| } else { | |||||
| accuracy += CalculateOneHotClassification(inputs.at(input_indexes_[i]), outputs.at(output_indexes_[i])); | |||||
| } | |||||
| } | } | ||||
| MS_LOG(WARNING) << "Model does not have a loss output tensor of size 1"; | |||||
| accuracies_.at(cb_data.epoch_).second += accuracy; | |||||
| } | } | ||||
| } // namespace lite | } // namespace lite | ||||
| @@ -20,9 +20,6 @@ | |||||
| #include <utility> | #include <utility> | ||||
| #include <vector> | #include <vector> | ||||
| #include <iostream> | #include <iostream> | ||||
| #include <fstream> | |||||
| #include <memory> | |||||
| #include "include/errorcode.h" | |||||
| #include "include/train_session.h" | #include "include/train_session.h" | ||||
| #include "src/common/utils.h" | #include "src/common/utils.h" | ||||
| #include "src/tensor.h" | #include "src/tensor.h" | ||||
| @@ -43,9 +40,9 @@ void LossMonitor::EpochBegin(const session::TrainLoopCallBackData &cb_data) { | |||||
| } | } | ||||
| int LossMonitor::EpochEnd(const session::TrainLoopCallBackData &cb_data) { | int LossMonitor::EpochEnd(const session::TrainLoopCallBackData &cb_data) { | ||||
| if (cb_data.step_ > 0) losses_.at(cb_data.epoch_).second /= static_cast<float>(cb_data.step_); | |||||
| if ((cb_data.epoch_ + 1) % print_every_n_ == 0) { | |||||
| std::cout << cb_data.epoch_ + 1 << ":\tLoss is " << losses_.at(cb_data.epoch_).second << std::endl; | |||||
| if (cb_data.step_ > 0) losses_.at(cb_data.epoch_).second /= static_cast<float>(cb_data.step_ + 1); | |||||
| if (print_every_n_ > 0) { | |||||
| std::cout << "Epoch (" << cb_data.epoch_ + 1 << "):\tLoss is " << losses_.at(cb_data.epoch_).second << std::endl; | |||||
| } | } | ||||
| return mindspore::session::RET_CONTINUE; | return mindspore::session::RET_CONTINUE; | ||||
| } | } | ||||
| @@ -56,6 +53,8 @@ void LossMonitor::StepEnd(const session::TrainLoopCallBackData &cb_data) { | |||||
| if (it->second->ElementsNum() == 1) { | if (it->second->ElementsNum() == 1) { | ||||
| auto loss = reinterpret_cast<float *>(it->second->MutableData()); | auto loss = reinterpret_cast<float *>(it->second->MutableData()); | ||||
| losses_.at(cb_data.epoch_).second += loss[0]; | losses_.at(cb_data.epoch_).second += loss[0]; | ||||
| if ((cb_data.step_ + 1) % print_every_n_ == 0) | |||||
| std::cout << cb_data.epoch_ + 1 << "." << cb_data.step_ + 1 << ":\tLoss is " << loss[0] << std::endl; | |||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| @@ -17,6 +17,10 @@ | |||||
| #define MINDSPORE_LITE_SRC_TRAIN_OPTIMIZER_KERNEL_H_ | #define MINDSPORE_LITE_SRC_TRAIN_OPTIMIZER_KERNEL_H_ | ||||
| #include <vector> | #include <vector> | ||||
| #include "src/lite_kernel.h" | #include "src/lite_kernel.h" | ||||
| #include "include/errorcode.h" | |||||
| using mindspore::lite::RET_ERROR; | |||||
| using mindspore::lite::RET_OK; | |||||
| namespace mindspore::kernel { | namespace mindspore::kernel { | ||||
| class OptimizerKernel : public LiteKernel { | class OptimizerKernel : public LiteKernel { | ||||
| @@ -24,11 +28,88 @@ class OptimizerKernel : public LiteKernel { | |||||
| OptimizerKernel() = default; | OptimizerKernel() = default; | ||||
| OptimizerKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | OptimizerKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | ||||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | ||||
| const lite::PrimitiveC *primitive) | |||||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) {} | |||||
| const lite::PrimitiveC *primitive, int lr_idx, int grad_idx) | |||||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive), lr_idx_(lr_idx), grad_idx_(grad_idx) {} | |||||
| ~OptimizerKernel() = default; | ~OptimizerKernel() = default; | ||||
| virtual int SetLearningRate(float lr) = 0; | |||||
| virtual float GetLearningRate() = 0; | |||||
| enum class WeightUpdateMode { NORMAL, VIRTUAL_BATCH }; | |||||
| WeightUpdateMode get_optimizer_mode() { return weightUpdateMod_; } | |||||
| int Init() override { | |||||
| default_lr_ = reinterpret_cast<float *>(in_tensors_.at(lr_idx_)->MutableData())[0]; | |||||
| lr_ = default_lr_; | |||||
| return RET_OK; | |||||
| } | |||||
| int SetLearningRate(float lr) { | |||||
| lr_ = lr; | |||||
| return RET_OK; | |||||
| } | |||||
| float GetLearningRate() { return lr_; } | |||||
| int RestoreDefaultLearningRate() { | |||||
| SetLearningRate(default_lr_); | |||||
| return RET_OK; | |||||
| } | |||||
| int SetOptimizerMode(WeightUpdateMode mod) { | |||||
| if (mod == WeightUpdateMode::VIRTUAL_BATCH) { | |||||
| if (grad_sum_ != nullptr) { | |||||
| context_->allocator->Free(grad_sum_); | |||||
| grad_sum_ = nullptr; | |||||
| } | |||||
| size_t size = in_tensors_.at(grad_idx_)->Size(); | |||||
| size_t elem_num = in_tensors_.at(grad_idx_)->ElementsNum(); | |||||
| grad_sum_ = reinterpret_cast<float *>(context_->allocator->Malloc(size)); | |||||
| if (grad_sum_ == nullptr) { | |||||
| MS_LOG(ERROR) << "failed to malloc grad sum tensor, size=" << size; | |||||
| return RET_ERROR; | |||||
| } | |||||
| valid_grad_sum_ = false; | |||||
| std::fill(grad_sum_, grad_sum_ + elem_num, 0); | |||||
| } else { | |||||
| if (grad_sum_ != nullptr) { | |||||
| context_->allocator->Free(grad_sum_); | |||||
| grad_sum_ = nullptr; | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| int ExecuteVirtualBatch(int task_id) { | |||||
| auto gradient = reinterpret_cast<float *>(in_tensors_.at(grad_idx_)->MutableData()); | |||||
| size_t length = in_tensors_.at(grad_idx_)->ElementsNum(); | |||||
| size_t stride = UP_DIV(length, context_->thread_num_); | |||||
| size_t count = MSMIN(stride, length - stride * task_id); | |||||
| size_t start = stride * task_id; | |||||
| size_t end = start + count; | |||||
| for (size_t i = start; i < end; ++i) { | |||||
| grad_sum_[i] += gradient[i]; | |||||
| } | |||||
| valid_grad_sum_ = true; | |||||
| return RET_OK; | |||||
| } | |||||
| virtual int OptimizerStep() { | |||||
| valid_grad_sum_ = false; | |||||
| return RET_OK; | |||||
| } | |||||
| int Eval() override { return OptimizerStep(); } | |||||
| protected: | |||||
| float default_lr_ = 0.0f; | |||||
| float lr_ = 0.0f; | |||||
| int lr_idx_ = 0; | |||||
| int grad_idx_ = 0; | |||||
| float *grad_sum_ = nullptr; | |||||
| bool valid_grad_sum_ = false; | |||||
| private: | |||||
| WeightUpdateMode weightUpdateMod_ = WeightUpdateMode::NORMAL; | |||||
| }; | }; | ||||
| } // namespace mindspore::kernel | } // namespace mindspore::kernel | ||||
| @@ -16,28 +16,19 @@ | |||||
| #include "src/train/train_loop.h" | #include "src/train/train_loop.h" | ||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||
| #include <algorithm> | |||||
| #include <utility> | |||||
| #include <vector> | #include <vector> | ||||
| #include <iostream> | |||||
| #include <fstream> | |||||
| #include <memory> | #include <memory> | ||||
| #include <algorithm> | |||||
| #include "include/errorcode.h" | #include "include/errorcode.h" | ||||
| #include "include/train_session.h" | #include "include/train_session.h" | ||||
| #include "src/common/utils.h" | |||||
| #include "src/tensor.h" | |||||
| #include "src/train/loss_kernel.h" | |||||
| #include "src/train/optimizer_kernel.h" | |||||
| #include "src/sub_graph_kernel.h" | |||||
| #include "src/train/train_populate_parameter.h" | |||||
| #include "src/runtime/runtime_api.h" | |||||
| #include "src/executor.h" | |||||
| #include "src/kernel_registry.h" | |||||
| #include "src/runtime/kernel/arm/fp32_grad/convolution.h" | |||||
| #include "include/iterator.h" | |||||
| namespace mindspore { | namespace mindspore { | ||||
| namespace lite { | namespace lite { | ||||
| using dataset::Dataset; | |||||
| using dataset::Iterator; | |||||
| using dataset::MSTensorVec; | |||||
| using session::RET_CONTINUE; | using session::RET_CONTINUE; | ||||
| using session::RET_EXIT; | using session::RET_EXIT; | ||||
| using session::RET_STOP_TRAINING; | using session::RET_STOP_TRAINING; | ||||
| @@ -46,24 +37,35 @@ TrainLoop::~TrainLoop() { | |||||
| if (train_session_ != nullptr) delete train_session_; | if (train_session_ != nullptr) delete train_session_; | ||||
| } | } | ||||
| int TrainLoop::Train(int epochs, std::vector<session::TrainLoopCallBack *> cbs) { | |||||
| int TrainLoop::Train(int epochs, Dataset *ds, std::vector<session::TrainLoopCallBack *> cbs, LoadDataFunc load_func) { | |||||
| train_session_->Train(); | train_session_->Train(); | ||||
| session::TrainLoopCallBackData cb_data(true, epoch_, train_session_, this); | session::TrainLoopCallBackData cb_data(true, epoch_, train_session_, this); | ||||
| if (load_func == nullptr) load_func = TrainLoop::LoadData; | |||||
| for (auto cb : cbs) cb->Begin(cb_data); | for (auto cb : cbs) cb->Begin(cb_data); | ||||
| int steps_in_epoch = 1; // should be data_size/batch_size | |||||
| for (int i = 0; i < epochs; i++) { | for (int i = 0; i < epochs; i++) { | ||||
| cb_data.epoch_ = epoch_++; | cb_data.epoch_ = epoch_++; | ||||
| for (auto cb : cbs) cb->EpochBegin(cb_data); | for (auto cb : cbs) cb->EpochBegin(cb_data); | ||||
| for (int s = 0; s < steps_in_epoch; s++) { | |||||
| cb_data.step_ = s; | |||||
| std::shared_ptr<Iterator> iter = ds->CreateIterator(); | |||||
| MSTensorVec row_vec; | |||||
| int s = 0; | |||||
| iter->GetNextRow(&row_vec); | |||||
| while (row_vec.size() != 0) { | |||||
| auto ret = load_func(cb_data.session_->GetInputs(), &row_vec); | |||||
| if (ret != RET_OK) break; | |||||
| cb_data.step_ = s++; | |||||
| for (auto cb : cbs) cb->StepBegin(cb_data); | for (auto cb : cbs) cb->StepBegin(cb_data); | ||||
| train_session_->RunGraph(before_cb_, after_cb_); | train_session_->RunGraph(before_cb_, after_cb_); | ||||
| for (auto cb : cbs) cb->StepEnd(cb_data); | for (auto cb : cbs) cb->StepEnd(cb_data); | ||||
| iter->GetNextRow(&row_vec); | |||||
| } | } | ||||
| iter->Stop(); | |||||
| int break_loop = false; | int break_loop = false; | ||||
| for (auto cb : cbs) { | for (auto cb : cbs) { | ||||
| int ret = cb->EpochEnd(cb_data); | int ret = cb->EpochEnd(cb_data); | ||||
| @@ -86,6 +88,83 @@ int TrainLoop::Train(int epochs, std::vector<session::TrainLoopCallBack *> cbs) | |||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| int TrainLoop::Eval(Dataset *ds, std::vector<session::TrainLoopCallBack *> cbs, LoadDataFunc load_func, int max_steps) { | |||||
| train_session_->Eval(); | |||||
| session::TrainLoopCallBackData cb_data(false, epoch_, train_session_, this); | |||||
| if (load_func == nullptr) load_func = TrainLoop::LoadData; | |||||
| for (auto metric : metrics_) metric->Clear(); | |||||
| for (auto cb : cbs) cb->Begin(cb_data); | |||||
| for (auto cb : cbs) cb->EpochBegin(cb_data); | |||||
| std::shared_ptr<Iterator> iter = ds->CreateIterator(); | |||||
| MSTensorVec row_vec; | |||||
| int s = 0; | |||||
| iter->GetNextRow(&row_vec); | |||||
| while (row_vec.size() != 0) { | |||||
| if (s >= max_steps) break; | |||||
| auto ret = load_func(cb_data.session_->GetInputs(), &row_vec); | |||||
| if (ret != RET_OK) break; | |||||
| cb_data.step_ = ++s; | |||||
| for (auto cb : cbs) cb->StepBegin(cb_data); | |||||
| train_session_->RunGraph(before_cb_, after_cb_); | |||||
| for (auto cb : cbs) cb->StepEnd(cb_data); | |||||
| auto outputs = cb_data.session_->GetPredictions(); | |||||
| for (auto metric : metrics_) metric->Update(cb_data.session_->GetInputs(), outputs); | |||||
| iter->GetNextRow(&row_vec); | |||||
| } | |||||
| iter->Stop(); | |||||
| for (auto cb : cbs) cb->EpochEnd(cb_data); | |||||
| for (auto cb : cbs) cb->End(cb_data); | |||||
| return RET_OK; | |||||
| } | |||||
| int TrainLoop::LoadData(std::vector<tensor::MSTensor *> inputs, dataset::MSTensorVec *row_vec) { | |||||
| auto num_of_inputs = inputs.size(); | |||||
| if ((num_of_inputs == 0) || (row_vec == nullptr) || (num_of_inputs != row_vec->size())) { | |||||
| return RET_STOP_TRAINING; | |||||
| } | |||||
| for (unsigned int i = 0; i < num_of_inputs; i++) { | |||||
| unsigned char *input_data = reinterpret_cast<unsigned char *>(inputs.at(i)->MutableData()); | |||||
| const unsigned char *row_data = reinterpret_cast<const unsigned char *>(row_vec->at(i).MutableData()); | |||||
| auto data_size = row_vec->at(i).DataSize(); | |||||
| if (data_size != inputs.at(i)->Size()) { | |||||
| MS_LOG(WARNING) << "Model Input tensor " << i << " size (" << inputs.at(i)->Size() | |||||
| << ") does not match dataset size (" << data_size << ")\n"; | |||||
| return RET_STOP_TRAINING; | |||||
| } | |||||
| std::copy(row_data, row_data + data_size, input_data); | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| int TrainLoop::LoadPartialData(std::vector<tensor::MSTensor *> inputs, dataset::MSTensorVec *row_vec) { | |||||
| auto num_of_inputs = inputs.size(); | |||||
| if ((num_of_inputs == 0) || (row_vec == nullptr) || (num_of_inputs < row_vec->size())) { | |||||
| return RET_STOP_TRAINING; | |||||
| } | |||||
| for (unsigned int i = 0; i < row_vec->size(); i++) { | |||||
| unsigned char *input_data = reinterpret_cast<unsigned char *>(inputs.at(i)->MutableData()); | |||||
| const unsigned char *row_data = reinterpret_cast<const unsigned char *>(row_vec->at(i).MutableData()); | |||||
| auto data_size = row_vec->at(i).DataSize(); | |||||
| if (data_size != inputs.at(i)->Size()) { | |||||
| MS_LOG(WARNING) << "Model Input tensor " << i << " size (" << inputs.at(i)->Size() | |||||
| << ") does not match dataset size (" << data_size << ")\n"; | |||||
| return RET_STOP_TRAINING; | |||||
| } | |||||
| std::copy(row_data, row_data + data_size, input_data); | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| } // namespace lite | } // namespace lite | ||||
| session::TrainLoop *session::TrainLoop::CreateTrainLoop(const std::string &model_filename, lite::Context *context, | session::TrainLoop *session::TrainLoop::CreateTrainLoop(const std::string &model_filename, lite::Context *context, | ||||
| @@ -18,11 +18,16 @@ | |||||
| #include <vector> | #include <vector> | ||||
| #include <string> | #include <string> | ||||
| #include <tuple> | #include <tuple> | ||||
| #include <memory> | |||||
| #include <unordered_map> | #include <unordered_map> | ||||
| #include "src/ops/primitive_c.h" | #include "src/ops/primitive_c.h" | ||||
| #include "include/train/train_loop.h" | #include "include/train/train_loop.h" | ||||
| #include "include/train/metrics.h" | |||||
| #include "include/train_session.h" | #include "include/train_session.h" | ||||
| #include "include/datasets.h" | |||||
| #include "include/iterator.h" | |||||
| namespace mindspore { | namespace mindspore { | ||||
| namespace lite { | namespace lite { | ||||
| @@ -39,20 +44,34 @@ class TrainLoop : virtual public session::TrainLoop { | |||||
| virtual ~TrainLoop(); | virtual ~TrainLoop(); | ||||
| int Init(std::vector<mindspore::session::Metrics *> metrics) override { | |||||
| metrics_ = metrics; | |||||
| return RET_OK; | |||||
| } | |||||
| int SetKernelCallBack(const KernelCallBack &before, const KernelCallBack &after) override { | int SetKernelCallBack(const KernelCallBack &before, const KernelCallBack &after) override { | ||||
| before_cb_ = before; | before_cb_ = before; | ||||
| after_cb_ = after; | after_cb_ = after; | ||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| int Train(int epochs, std::vector<session::TrainLoopCallBack *> cbs) override; | |||||
| int Train(int epochs, dataset::Dataset *dataset, std::vector<session::TrainLoopCallBack *> cbs, | |||||
| LoadDataFunc load_func = nullptr) override; | |||||
| int Eval(dataset::Dataset *dataset, std::vector<session::TrainLoopCallBack *> cbs, LoadDataFunc load_func = nullptr, | |||||
| int max_steps = 0) override; | |||||
| std::vector<mindspore::session::Metrics *> GetMetrics() override { return metrics_; } | |||||
| protected: | protected: | ||||
| static int LoadData(std::vector<tensor::MSTensor *> inputs, dataset::MSTensorVec *dataset_vec); | |||||
| static int LoadPartialData(std::vector<tensor::MSTensor *> inputs, dataset::MSTensorVec *dataset_vec); | |||||
| session::TrainSession *train_session_ = nullptr; | session::TrainSession *train_session_ = nullptr; | ||||
| unsigned int epoch_ = 0; | unsigned int epoch_ = 0; | ||||
| KernelCallBack before_cb_ = nullptr; | KernelCallBack before_cb_ = nullptr; | ||||
| KernelCallBack after_cb_ = nullptr; | KernelCallBack after_cb_ = nullptr; | ||||
| int batch_size; | int batch_size; | ||||
| std::vector<mindspore::session::Metrics *> metrics_; | |||||
| }; | }; | ||||
| } // namespace lite | } // namespace lite | ||||
| } // namespace mindspore | } // namespace mindspore | ||||
| @@ -75,4 +75,18 @@ char *TrainModel::ExportBuf(char *buffer, size_t *len) const { | |||||
| *len = buf_size_; | *len = buf_size_; | ||||
| return buffer; | return buffer; | ||||
| } | } | ||||
| char *TrainModel::GetBuffer(size_t *len) const { | |||||
| if (len == nullptr) { | |||||
| MS_LOG(ERROR) << "len is nullptr"; | |||||
| return nullptr; | |||||
| } | |||||
| if (buf_size_ == 0 || buf == nullptr) { | |||||
| MS_LOG(ERROR) << "Model::Export is only available for Train Session"; | |||||
| return nullptr; | |||||
| } | |||||
| *len = buf_size_; | |||||
| return buf; | |||||
| } | |||||
| } // namespace mindspore::lite | } // namespace mindspore::lite | ||||
| @@ -43,6 +43,13 @@ struct TrainModel : public lite::LiteModel { | |||||
| /// | /// | ||||
| /// \return Pointer to buffer with exported model | /// \return Pointer to buffer with exported model | ||||
| char *ExportBuf(char *buf, size_t *len) const; | char *ExportBuf(char *buf, size_t *len) const; | ||||
| /// \brief Get Model buffer | |||||
| /// | |||||
| /// \param[in,out] len Return size of the buffer | |||||
| /// | |||||
| /// \return Pointer to model buffer | |||||
| char *GetBuffer(size_t *len) const; | |||||
| }; | }; | ||||
| } // namespace lite | } // namespace lite | ||||
| } // namespace mindspore | } // namespace mindspore | ||||
| @@ -33,10 +33,50 @@ | |||||
| #include "src/executor.h" | #include "src/executor.h" | ||||
| #include "src/kernel_registry.h" | #include "src/kernel_registry.h" | ||||
| #include "src/runtime/kernel/arm/fp32_grad/convolution.h" | #include "src/runtime/kernel/arm/fp32_grad/convolution.h" | ||||
| #include "src/runtime/kernel/arm/fp32/batchnorm_fp32.h" | |||||
| namespace mindspore { | namespace mindspore { | ||||
| namespace lite { | namespace lite { | ||||
| std::unique_ptr<char[]> ReadFileToBuf(const std::string &filename, size_t *size) { | |||||
| std::ifstream ifs(filename); | |||||
| if (!ifs.good()) { | |||||
| MS_LOG(ERROR) << "File: " << filename << " does not exist"; | |||||
| return std::unique_ptr<char[]>(nullptr); | |||||
| } | |||||
| if (!ifs.is_open()) { | |||||
| MS_LOG(ERROR) << "File: " << filename << " open failed"; | |||||
| return std::unique_ptr<char[]>(nullptr); | |||||
| } | |||||
| ifs.seekg(0, std::ios::end); | |||||
| auto tellg_ret = ifs.tellg(); | |||||
| if (tellg_ret <= 0) { | |||||
| MS_LOG(ERROR) << "Could not read file " << filename; | |||||
| return std::unique_ptr<char[]>(nullptr); | |||||
| } | |||||
| size_t fsize = static_cast<size_t>(tellg_ret); | |||||
| std::unique_ptr<char[]> buf(new (std::nothrow) char[fsize]); | |||||
| if (buf == nullptr) { | |||||
| MS_LOG(ERROR) << "malloc buf failed, file: " << filename; | |||||
| ifs.close(); | |||||
| return std::unique_ptr<char[]>(nullptr); | |||||
| } | |||||
| ifs.seekg(0, std::ios::beg); | |||||
| ifs.read(buf.get(), fsize); | |||||
| if (!ifs) { | |||||
| MS_LOG(ERROR) << "only read " << ifs.gcount() << "bytes in " << filename; | |||||
| ifs.close(); | |||||
| return std::unique_ptr<char[]>(nullptr); | |||||
| } | |||||
| ifs.close(); | |||||
| if (size) *size = fsize; | |||||
| return buf; | |||||
| } | |||||
| static size_t TSFindTensor(const std::vector<lite::Tensor *> &where, const lite::Tensor *searchParameter) { | static size_t TSFindTensor(const std::vector<lite::Tensor *> &where, const lite::Tensor *searchParameter) { | ||||
| for (size_t i = 0; i < where.size(); i++) { | for (size_t i = 0; i < where.size(); i++) { | ||||
| if (where[i] == searchParameter) { | if (where[i] == searchParameter) { | ||||
| @@ -46,6 +86,12 @@ static size_t TSFindTensor(const std::vector<lite::Tensor *> &where, const lite: | |||||
| return where.size(); | return where.size(); | ||||
| } | } | ||||
| static kernel::LiteKernel *TSFindKernel(const std::vector<kernel::LiteKernel *> &where, | |||||
| const std::string &searchParameter) { | |||||
| auto it = std::find_if(where.begin(), where.end(), | |||||
| [&searchParameter](const kernel::LiteKernel *k) { return (k->name() == searchParameter); }); | |||||
| return *it; | |||||
| } | |||||
| TrainSession::TrainSession() { kernel::PopulateTrainParameters(); } | TrainSession::TrainSession() { kernel::PopulateTrainParameters(); } | ||||
| std::vector<CreatorOp> TrainSession::ReplaceOps() { | std::vector<CreatorOp> TrainSession::ReplaceOps() { | ||||
| @@ -96,10 +142,10 @@ int TrainSession::CompileTrainGraph(mindspore::lite::TrainModel *model) { | |||||
| for (auto inTensor : inputs_) inTensor->MutableData(); | for (auto inTensor : inputs_) inTensor->MutableData(); | ||||
| RestoreOps(restore); | RestoreOps(restore); | ||||
| CompileTrainKernels(); // Prepare a list of train kernels | CompileTrainKernels(); // Prepare a list of train kernels | ||||
| CompileInferenceKernels(); // Prepare a list of eval kernels | |||||
| CompileOptimizedKernels(); // Prepare a list of kernels which are optimized (weight update step) | CompileOptimizedKernels(); // Prepare a list of kernels which are optimized (weight update step) | ||||
| CompileTrainOutputs(); // prepare outputs in train mode | CompileTrainOutputs(); // prepare outputs in train mode | ||||
| CompileEvalOutputs(); // prepare outputs in eval mode | CompileEvalOutputs(); // prepare outputs in eval mode | ||||
| CompileInferenceKernels(); // Prepare a list of eval kernels | |||||
| AllocWorkSpace(); | AllocWorkSpace(); | ||||
| return RET_OK; | return RET_OK; | ||||
| @@ -107,7 +153,10 @@ int TrainSession::CompileTrainGraph(mindspore::lite::TrainModel *model) { | |||||
| TrainSession::~TrainSession() { | TrainSession::~TrainSession() { | ||||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | mindspore::kernel::LiteKernel::FreeWorkspace(); | ||||
| delete model_; | |||||
| if (model_ != nullptr) { | |||||
| delete model_; | |||||
| model_ = nullptr; | |||||
| } | |||||
| } | } | ||||
| void *TrainSession::ExportToBuf(char *buf, size_t *len) const { return model_->ExportBuf(buf, len); } | void *TrainSession::ExportToBuf(char *buf, size_t *len) const { return model_->ExportBuf(buf, len); } | ||||
| @@ -128,16 +177,34 @@ int TrainSession::RunGraph(const KernelCallBack &before, const KernelCallBack &a | |||||
| } | } | ||||
| auto run_kernel = (train_mode_) ? train_kernels_ : inference_kernels_; | auto run_kernel = (train_mode_) ? train_kernels_ : inference_kernels_; | ||||
| lite::CpuExecutor executor; | lite::CpuExecutor executor; | ||||
| auto ret = RET_OK; | |||||
| if (before == nullptr && after == nullptr) { | if (before == nullptr && after == nullptr) { | ||||
| return executor.Run(this->inputs_, this->outputs_, run_kernel, this->context_->allocator.get()); | |||||
| ret = executor.Run(this->inputs_, this->outputs_, run_kernel, this->context_->allocator.get()); | |||||
| } else { | } else { | ||||
| return executor.Run(this->inputs_, this->outputs_, run_kernel, this->context_->allocator.get(), before, after); | |||||
| ret = executor.Run(this->inputs_, this->outputs_, run_kernel, this->context_->allocator.get(), before, after); | |||||
| } | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << "failed to run model"; | |||||
| return ret; | |||||
| } | |||||
| if (train_mode_ && virtual_batch_multiplier_) { | |||||
| virtual_batch_idx_++; | |||||
| if (virtual_batch_idx_ >= virtual_batch_multiplier_) { | |||||
| virtual_batch_idx_ = 0; | |||||
| ret = OptimizerStep(); | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << "failed to optimize model weights"; | |||||
| return ret; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| return RET_OK; | |||||
| } | } | ||||
| int TrainSession::SaveToFile(const std::string &filename) const { | int TrainSession::SaveToFile(const std::string &filename) const { | ||||
| size_t fb_size = 0; | size_t fb_size = 0; | ||||
| auto *buf = reinterpret_cast<char *>(ExportToBuf(nullptr, &fb_size)); | |||||
| const auto *buf = reinterpret_cast<char *>(model_->GetBuffer(&fb_size)); | |||||
| if (buf == nullptr) { | if (buf == nullptr) { | ||||
| MS_LOG(ERROR) << "Could not Export Trained model"; | MS_LOG(ERROR) << "Could not Export Trained model"; | ||||
| return lite::RET_NULL_PTR; | return lite::RET_NULL_PTR; | ||||
| @@ -145,20 +212,19 @@ int TrainSession::SaveToFile(const std::string &filename) const { | |||||
| std::ofstream ofs(filename); | std::ofstream ofs(filename); | ||||
| if ((true != ofs.good()) || (true != ofs.is_open())) { | if ((true != ofs.good()) || (true != ofs.is_open())) { | ||||
| MS_LOG(ERROR) << "Could not open file \"" << filename << "\" for writing"; | MS_LOG(ERROR) << "Could not open file \"" << filename << "\" for writing"; | ||||
| free(buf); | |||||
| return RET_ERROR; | return RET_ERROR; | ||||
| } | } | ||||
| ofs.seekp(0, std::ios::beg); | ofs.seekp(0, std::ios::beg); | ||||
| ofs.write(buf, fb_size); | ofs.write(buf, fb_size); | ||||
| ofs.close(); | ofs.close(); | ||||
| free(buf); | |||||
| return chmod(filename.c_str(), S_IRUSR); | return chmod(filename.c_str(), S_IRUSR); | ||||
| } | } | ||||
| int TrainSession::Train() { | int TrainSession::Train() { | ||||
| // shift kernels to train mode | // shift kernels to train mode | ||||
| train_mode_ = true; | train_mode_ = true; | ||||
| virtual_batch_idx_ = 0; | |||||
| for (auto kernel : this->train_kernels_) { | for (auto kernel : this->train_kernels_) { | ||||
| MS_ASSERT(nullptr != kernel); | MS_ASSERT(nullptr != kernel); | ||||
| auto ret = kernel->Train(); | auto ret = kernel->Train(); | ||||
| @@ -177,6 +243,7 @@ int TrainSession::Train() { | |||||
| int TrainSession::Eval() { | int TrainSession::Eval() { | ||||
| // shift kernels to eval mode | // shift kernels to eval mode | ||||
| train_mode_ = false; | train_mode_ = false; | ||||
| virtual_batch_idx_ = 0; | |||||
| for (auto kernel : this->train_kernels_) { | for (auto kernel : this->train_kernels_) { | ||||
| MS_ASSERT(kernel != nullptr); | MS_ASSERT(kernel != nullptr); | ||||
| auto ret = kernel->Eval(); | auto ret = kernel->Eval(); | ||||
| @@ -197,6 +264,7 @@ void TrainSession::CompileEvalOutputs() { | |||||
| for (auto kernel : this->train_kernels_) { | for (auto kernel : this->train_kernels_) { | ||||
| if (IsLossKernel(kernel)) { | if (IsLossKernel(kernel)) { | ||||
| for (auto in_kernel : kernel->in_kernels()) { | for (auto in_kernel : kernel->in_kernels()) { | ||||
| if (IsLossKernel(in_kernel) || IsGradKernel(in_kernel)) continue; | |||||
| // insert if not already in | // insert if not already in | ||||
| if (eval_output_node_map_.find(in_kernel->name()) == eval_output_node_map_.end()) { | if (eval_output_node_map_.find(in_kernel->name()) == eval_output_node_map_.end()) { | ||||
| auto *ms_tensor = in_kernel->out_tensors().at(0); | auto *ms_tensor = in_kernel->out_tensors().at(0); | ||||
| @@ -240,10 +308,10 @@ void TrainSession::CompileTrainOutputs() { | |||||
| void TrainSession::BuildInferenceKernelsRecursive(kernel::LiteKernel *kernel, std::vector<kernel::LiteKernel *> *v) { | void TrainSession::BuildInferenceKernelsRecursive(kernel::LiteKernel *kernel, std::vector<kernel::LiteKernel *> *v) { | ||||
| if (std::find(v->begin(), v->end(), kernel) == v->end()) { // kernel is not already in vector | if (std::find(v->begin(), v->end(), kernel) == v->end()) { // kernel is not already in vector | ||||
| if (!IsLossKernel(kernel)) v->push_back(kernel); | |||||
| for (auto in_node : kernel->in_kernels()) { | for (auto in_node : kernel->in_kernels()) { | ||||
| BuildInferenceKernelsRecursive(in_node, v); | BuildInferenceKernelsRecursive(in_node, v); | ||||
| } | } | ||||
| if (!IsLossKernel(kernel)) v->push_back(kernel); | |||||
| } | } | ||||
| } | } | ||||
| @@ -262,19 +330,10 @@ void TrainSession::CompileTrainKernels() { | |||||
| } | } | ||||
| void TrainSession::CompileInferenceKernels() { | void TrainSession::CompileInferenceKernels() { | ||||
| std::vector<kernel::LiteKernel *> req_kernels; | |||||
| for (auto kernel : this->train_kernels_) { | |||||
| if (IsLossKernel(kernel)) { // For each loss in the system add backward tree | |||||
| for (auto in_node : kernel->in_kernels()) { | |||||
| BuildInferenceKernelsRecursive(in_node, &req_kernels); | |||||
| } | |||||
| } | |||||
| } | |||||
| inference_kernels_.clear(); | |||||
| for (auto ori_kernel : this->train_kernels_) { | |||||
| if (std::find(req_kernels.begin(), req_kernels.end(), ori_kernel) != req_kernels.end()) { | |||||
| inference_kernels_.push_back(ori_kernel); | |||||
| } | |||||
| for (auto item : eval_output_node_map_) { | |||||
| std::string kernel_name = item.first; | |||||
| auto kernel = TSFindKernel(train_kernels_, kernel_name); | |||||
| BuildInferenceKernelsRecursive(kernel, &inference_kernels_); | |||||
| } | } | ||||
| if (inference_kernels_.size() == 0) { | if (inference_kernels_.size() == 0) { | ||||
| inference_kernels_ = this->train_kernels_; | inference_kernels_ = this->train_kernels_; | ||||
| @@ -325,23 +384,92 @@ float TrainSession::GetLearningRate() { | |||||
| return 0.0; | return 0.0; | ||||
| } | } | ||||
| int TrainSession::SetupVirtualBatch(int virtual_batch_multiplier, float lr, float momentum) { | |||||
| auto mod = (virtual_batch_multiplier <= 1) ? kernel::OptimizerKernel::WeightUpdateMode::NORMAL | |||||
| : kernel::OptimizerKernel::WeightUpdateMode::VIRTUAL_BATCH; | |||||
| virtual_batch_multiplier_ = (virtual_batch_multiplier <= 1) ? 0 : virtual_batch_multiplier; | |||||
| virtual_batch_idx_ = 0; | |||||
| for (auto kernel : this->train_kernels_) { | |||||
| if (IsOptimizer(kernel)) { | |||||
| auto optimizer = reinterpret_cast<kernel::OptimizerKernel *>(kernel); | |||||
| auto ret = optimizer->SetOptimizerMode(mod); | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << kernel->name() << " failed to set optimizer mode"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| if (mod == kernel::OptimizerKernel::WeightUpdateMode::VIRTUAL_BATCH) { | |||||
| lr = (lr < 0.0f) ? (optimizer->GetLearningRate() / static_cast<float>(virtual_batch_multiplier_)) : lr; | |||||
| ret = optimizer->SetLearningRate(lr); | |||||
| } else { | |||||
| ret = optimizer->RestoreDefaultLearningRate(); | |||||
| } | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << kernel->name() << " failed to set learning rate"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| } | |||||
| if (IsBN(kernel) && kernel->is_trainable()) { | |||||
| auto batchnorm = reinterpret_cast<kernel::BatchnormCPUKernel *>(kernel); | |||||
| auto ret = RET_OK; | |||||
| if (mod == kernel::OptimizerKernel::WeightUpdateMode::VIRTUAL_BATCH) { | |||||
| momentum = (momentum < 0.0f) ? (batchnorm->get_momentum() / virtual_batch_multiplier_) : momentum; | |||||
| ret = batchnorm->set_momentum(momentum); | |||||
| } else { | |||||
| ret = batchnorm->RestoreDefaultMomentum(); | |||||
| } | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << kernel->name() << " failed to set momentum"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| int TrainSession::OptimizerStep() { | |||||
| for (auto kernel : this->train_kernels_) { | |||||
| if (IsOptimizer(kernel)) { | |||||
| auto optimizer = reinterpret_cast<kernel::OptimizerKernel *>(kernel); | |||||
| auto ret = optimizer->OptimizerStep(); | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << kernel->name() << " failed to do optimize step"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| bool TrainSession::IsLossKernel(const kernel::LiteKernel *kernel) const { | bool TrainSession::IsLossKernel(const kernel::LiteKernel *kernel) const { | ||||
| return (kernel->Type() == schema::PrimitiveType_SoftmaxCrossEntropy || | return (kernel->Type() == schema::PrimitiveType_SoftmaxCrossEntropy || | ||||
| kernel->Type() == schema::PrimitiveType_SparseSoftmaxCrossEntropy || | kernel->Type() == schema::PrimitiveType_SparseSoftmaxCrossEntropy || | ||||
| kernel->Type() == schema::PrimitiveType_SmoothL1Loss || | kernel->Type() == schema::PrimitiveType_SmoothL1Loss || | ||||
| kernel->Type() == schema::PrimitiveType_SmoothL1LossGrad || | kernel->Type() == schema::PrimitiveType_SmoothL1LossGrad || | ||||
| kernel->Type() == schema::PrimitiveType_SigmoidCrossEntropyWithLogits || | kernel->Type() == schema::PrimitiveType_SigmoidCrossEntropyWithLogits || | ||||
| kernel->Type() == schema::PrimitiveType_SigmoidCrossEntropyWithLogitsGrad); | |||||
| kernel->Type() == schema::PrimitiveType_SigmoidCrossEntropyWithLogitsGrad) || | |||||
| kernel->name().find(get_loss_name()) != std::string::npos; | |||||
| } | |||||
| bool TrainSession::IsGradKernel(const kernel::LiteKernel *kernel) const { | |||||
| return kernel->name().find("Gradients") != std::string::npos; | |||||
| } | } | ||||
| bool TrainSession::IsOptimizer(kernel::LiteKernel *kernel) const { | bool TrainSession::IsOptimizer(kernel::LiteKernel *kernel) const { | ||||
| return ((kernel->Type() == schema::PrimitiveType_Adam) || (kernel->Type() == schema::PrimitiveType_Sgd) || | return ((kernel->Type() == schema::PrimitiveType_Adam) || (kernel->Type() == schema::PrimitiveType_Sgd) || | ||||
| (kernel->Type() == schema::PrimitiveType_ApplyMomentum)); | (kernel->Type() == schema::PrimitiveType_ApplyMomentum)); | ||||
| } | } | ||||
| bool TrainSession::IsMaskOutput(kernel::LiteKernel *kernel) const { | bool TrainSession::IsMaskOutput(kernel::LiteKernel *kernel) const { | ||||
| return (IsOptimizer(kernel) || (kernel->Type() == schema::PrimitiveType_Assign)); | return (IsOptimizer(kernel) || (kernel->Type() == schema::PrimitiveType_Assign)); | ||||
| } | } | ||||
| bool TrainSession::IsBN(kernel::LiteKernel *kernel) const { | |||||
| return ((kernel->Type() == schema::PrimitiveType_BatchNorm) || | |||||
| (kernel->Type() == schema::PrimitiveType_FusedBatchNorm)); | |||||
| } | |||||
| } // namespace lite | } // namespace lite | ||||
| session::TrainSession *session::TrainSession::CreateSession(const char *model_buf, size_t size, lite::Context *context, | session::TrainSession *session::TrainSession::CreateSession(const char *model_buf, size_t size, lite::Context *context, | ||||
| @@ -362,6 +490,7 @@ session::TrainSession *session::TrainSession::CreateSession(const char *model_bu | |||||
| if (ret != mindspore::lite::RET_OK) { | if (ret != mindspore::lite::RET_OK) { | ||||
| MS_LOG(ERROR) << "init session failed"; | MS_LOG(ERROR) << "init session failed"; | ||||
| delete session; | delete session; | ||||
| delete model; | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -388,38 +517,11 @@ session::TrainSession *session::TrainSession::CreateSession(const char *model_bu | |||||
| session::TrainSession *session::TrainSession::CreateSession(const std::string &filename, lite::Context *context, | session::TrainSession *session::TrainSession::CreateSession(const std::string &filename, lite::Context *context, | ||||
| bool train_mode) { | bool train_mode) { | ||||
| std::ifstream ifs(filename); | |||||
| if (!ifs.good()) { | |||||
| MS_LOG(ERROR) << "File: " << filename << " does not exist"; | |||||
| return nullptr; | |||||
| } | |||||
| if (!ifs.is_open()) { | |||||
| MS_LOG(ERROR) << "File: " << filename << " open failed"; | |||||
| return nullptr; | |||||
| } | |||||
| ifs.seekg(0, std::ios::end); | |||||
| auto size = ifs.tellg(); | |||||
| if (size <= 0) { | |||||
| MS_LOG(ERROR) << "Could not read file " << filename; | |||||
| return nullptr; | |||||
| } | |||||
| std::unique_ptr<char[]> buf(new (std::nothrow) char[size]); | |||||
| size_t size = -1; | |||||
| auto buf = lite::ReadFileToBuf(filename, &size); | |||||
| if (buf == nullptr) { | if (buf == nullptr) { | ||||
| MS_LOG(ERROR) << "malloc buf failed, file: " << filename; | |||||
| ifs.close(); | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| ifs.seekg(0, std::ios::beg); | |||||
| ifs.read(buf.get(), size); | |||||
| if (!ifs) { | |||||
| MS_LOG(ERROR) << "only read " << ifs.gcount() << "bytes in " << filename; | |||||
| ifs.close(); | |||||
| return nullptr; | |||||
| } | |||||
| ifs.close(); | |||||
| return session::TrainSession::CreateSession(buf.get(), size, context, train_mode); | return session::TrainSession::CreateSession(buf.get(), size, context, train_mode); | ||||
| } | } | ||||
| @@ -19,6 +19,7 @@ | |||||
| #include <string> | #include <string> | ||||
| #include <tuple> | #include <tuple> | ||||
| #include <unordered_map> | #include <unordered_map> | ||||
| #include <memory> | |||||
| #include "src/ops/primitive_c.h" | #include "src/ops/primitive_c.h" | ||||
| #include "include/train_session.h" | #include "include/train_session.h" | ||||
| #include "src/train/train_model.h" | #include "src/train/train_model.h" | ||||
| @@ -42,6 +43,7 @@ | |||||
| namespace mindspore { | namespace mindspore { | ||||
| namespace lite { | namespace lite { | ||||
| std::unique_ptr<char[]> ReadFileToBuf(const std::string &filename, size_t *size); | |||||
| using CreatorOp = std::tuple<mindspore::kernel::KernelKey, mindspore::kernel::KernelCreator>; | using CreatorOp = std::tuple<mindspore::kernel::KernelKey, mindspore::kernel::KernelCreator>; | ||||
| class TrainSession : virtual public session::TrainSession, virtual public lite::LiteSession { | class TrainSession : virtual public session::TrainSession, virtual public lite::LiteSession { | ||||
| public: | public: | ||||
| @@ -60,6 +62,7 @@ class TrainSession : virtual public session::TrainSession, virtual public lite:: | |||||
| int Eval() override; | int Eval() override; | ||||
| int SetLearningRate(float learning_rate) override; | int SetLearningRate(float learning_rate) override; | ||||
| float GetLearningRate() override; | float GetLearningRate() override; | ||||
| int SetupVirtualBatch(int virtual_batch_multiplier, float lr = -1.0f, float momentum = -1.0f) override; | |||||
| void BindThread(bool if_bind) override { return lite::LiteSession::BindThread(if_bind); } | void BindThread(bool if_bind) override { return lite::LiteSession::BindThread(if_bind); } | ||||
| std::vector<tensor::MSTensor *> GetInputs() const override { return lite::LiteSession::GetInputs(); } | std::vector<tensor::MSTensor *> GetInputs() const override { return lite::LiteSession::GetInputs(); } | ||||
| @@ -81,15 +84,22 @@ class TrainSession : virtual public session::TrainSession, virtual public lite:: | |||||
| return lite::RET_ERROR; | return lite::RET_ERROR; | ||||
| } | } | ||||
| std::unordered_map<std::string, mindspore::tensor::MSTensor *> GetPredictions() const override { | |||||
| return eval_output_tensor_map_; | |||||
| std::vector<tensor::MSTensor *> GetPredictions() const override { | |||||
| std::vector<tensor::MSTensor *> outputs; | |||||
| for (auto it = eval_output_tensor_map_.begin(); it != eval_output_tensor_map_.end(); ++it) { | |||||
| outputs.push_back(it->second); | |||||
| } | |||||
| return outputs; | |||||
| } | } | ||||
| protected: | protected: | ||||
| void AllocWorkSpace(); | void AllocWorkSpace(); | ||||
| bool IsLossKernel(const kernel::LiteKernel *kernel) const; | bool IsLossKernel(const kernel::LiteKernel *kernel) const; | ||||
| bool IsGradKernel(const kernel::LiteKernel *kernel) const; | |||||
| bool IsOptimizer(kernel::LiteKernel *kernel) const; | bool IsOptimizer(kernel::LiteKernel *kernel) const; | ||||
| bool IsMaskOutput(kernel::LiteKernel *kernel) const; | bool IsMaskOutput(kernel::LiteKernel *kernel) const; | ||||
| bool IsBN(kernel::LiteKernel *kernel) const; | |||||
| virtual std::vector<CreatorOp> ReplaceOps(); | virtual std::vector<CreatorOp> ReplaceOps(); | ||||
| virtual void RestoreOps(const std::vector<CreatorOp> &restore); | virtual void RestoreOps(const std::vector<CreatorOp> &restore); | ||||
| virtual void CompileTrainKernels(); | virtual void CompileTrainKernels(); | ||||
| @@ -113,7 +123,11 @@ class TrainSession : virtual public session::TrainSession, virtual public lite:: | |||||
| private: | private: | ||||
| void BuildInferenceKernelsRecursive(kernel::LiteKernel *ker, std::vector<kernel::LiteKernel *> *req_kernels); | void BuildInferenceKernelsRecursive(kernel::LiteKernel *ker, std::vector<kernel::LiteKernel *> *req_kernels); | ||||
| int OptimizerStep(); | |||||
| int virtual_batch_idx_ = 0; | |||||
| int virtual_batch_multiplier_ = 0; | |||||
| }; | }; | ||||
| } // namespace lite | } // namespace lite | ||||
| } // namespace mindspore | } // namespace mindspore | ||||
| #endif // MINDSPORE_LITE_SRC_TRAIN_TRAIN_SESSION_H_ | #endif // MINDSPORE_LITE_SRC_TRAIN_TRAIN_SESSION_H_ | ||||
| @@ -0,0 +1,85 @@ | |||||
| /** | |||||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * 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 "src/train/train_utils.h" | |||||
| #include <vector> | |||||
| #include "include/errorcode.h" | |||||
| #include "include/ms_tensor.h" | |||||
| #include "src/common/utils.h" | |||||
| namespace mindspore { | |||||
| namespace lite { | |||||
| float CalculateSparseClassification(tensor::MSTensor *input, tensor::MSTensor *output) { | |||||
| if ((input->shape().size() != 1) || (input->data_type() != kNumberTypeInt32) || (output->shape().size() != 2)) { | |||||
| MS_LOG(WARNING) << "SparceClassification got a " << input->shape() << "-D input tensor, " << output->shape() | |||||
| << "-D output tensor"; | |||||
| return 0.0; | |||||
| } | |||||
| int batch_size = input->shape().at(0); | |||||
| int num_of_classes = output->shape().at(1); | |||||
| auto labels = reinterpret_cast<int *>(input->MutableData()); | |||||
| auto predictions = reinterpret_cast<float *>(output->MutableData()); | |||||
| float accuracy = 0.0; | |||||
| for (int b = 0; b < batch_size; b++) { | |||||
| int max_idx = 0; | |||||
| float max_score = predictions[num_of_classes * b]; | |||||
| for (int c = 1; c < num_of_classes; c++) { | |||||
| if (predictions[num_of_classes * b + c] > max_score) { | |||||
| max_score = predictions[num_of_classes * b + c]; | |||||
| max_idx = c; | |||||
| } | |||||
| } | |||||
| if (labels[b] == max_idx) accuracy += 1.0; | |||||
| } | |||||
| return accuracy / (static_cast<float>(batch_size)); | |||||
| } | |||||
| float CalculateOneHotClassification(tensor::MSTensor *input, tensor::MSTensor *output) { | |||||
| if ((input->shape().size() != 2) || (output->shape().size() != 2)) { | |||||
| MS_LOG(WARNING) << "OneHotClassification got a " << input->shape() << "-D input tensor, " << output->shape() | |||||
| << "-D output tensor"; | |||||
| return 0.0; | |||||
| } | |||||
| int batch_size = input->shape().at(0); | |||||
| int num_of_classes = input->shape().at(1); | |||||
| auto labels = reinterpret_cast<float *>(input->MutableData()); | |||||
| auto predictions = reinterpret_cast<float *>(output->MutableData()); | |||||
| float accuracy = 0.0; | |||||
| for (int b = 0; b < batch_size; b++) { | |||||
| int label = 0; | |||||
| int max_idx = 0; | |||||
| float max_label_score = labels[num_of_classes * b]; | |||||
| float max_score = predictions[num_of_classes * b]; | |||||
| for (int c = 1; c < num_of_classes; c++) { | |||||
| if (predictions[num_of_classes * b + c] > max_score) { | |||||
| max_score = predictions[num_of_classes * b + c]; | |||||
| max_idx = c; | |||||
| } | |||||
| if (labels[num_of_classes * b + c] > max_label_score) { | |||||
| max_label_score = labels[num_of_classes * b + c]; | |||||
| label = c; | |||||
| } | |||||
| } | |||||
| if (label == max_idx) accuracy += 1.0; | |||||
| } | |||||
| return accuracy / (static_cast<float>(batch_size)); | |||||
| } | |||||
| } // namespace lite | |||||
| } // namespace mindspore | |||||
| @@ -0,0 +1,29 @@ | |||||
| /** | |||||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * 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. | |||||
| */ | |||||
| #ifndef MINDSPORE_LITE_SRC_TRAIN_TRAIN_UTILS_H_ | |||||
| #define MINDSPORE_LITE_SRC_TRAIN_TRAIN_UTILS_H_ | |||||
| #include "include/ms_tensor.h" | |||||
| namespace mindspore { | |||||
| namespace lite { | |||||
| float CalculateSparseClassification(tensor::MSTensor *input, tensor::MSTensor *output); | |||||
| float CalculateOneHotClassification(tensor::MSTensor *input, tensor::MSTensor *output); | |||||
| } // namespace lite | |||||
| } // namespace mindspore | |||||
| #endif // MINDSPORE_LITE_SRC_TRAIN_TRAIN_UTILS_H_ | |||||
| @@ -0,0 +1,207 @@ | |||||
| /** | |||||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * 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 "src/train/transfer_session.h" | |||||
| #include <sys/stat.h> | |||||
| #include <algorithm> | |||||
| #include <utility> | |||||
| #include <vector> | |||||
| #include <iostream> | |||||
| #include <fstream> | |||||
| #include <memory> | |||||
| #include "include/errorcode.h" | |||||
| #include "src/common/utils.h" | |||||
| #include "src/tensor.h" | |||||
| #include "src/train/loss_kernel.h" | |||||
| #include "src/train/optimizer_kernel.h" | |||||
| #include "src/sub_graph_kernel.h" | |||||
| #include "src/train/train_populate_parameter.h" | |||||
| #include "src/runtime/runtime_api.h" | |||||
| #include "src/executor.h" | |||||
| #include "src/kernel_registry.h" | |||||
| #include "src/runtime/kernel/arm/fp32_grad/convolution.h" | |||||
| namespace mindspore { | |||||
| namespace lite { | |||||
| TransferSession::TransferSession(const char *model_buf_backbone, size_t size_backbone, lite::Context *context) | |||||
| : is_valid_(false) { | |||||
| lite_model_ = reinterpret_cast<char *>(malloc(size_backbone)); | |||||
| if (lite_model_ != nullptr) { | |||||
| std::copy(model_buf_backbone, model_buf_backbone + size_backbone, lite_model_); | |||||
| backbone_session_ = | |||||
| reinterpret_cast<lite::LiteSession *>(session::LiteSession::CreateSession(lite_model_, size_backbone, context)); | |||||
| if (backbone_session_ != nullptr) { | |||||
| is_valid_ = true; | |||||
| } else { | |||||
| MS_LOG(ERROR) << "transfer session: create backbone session failed"; | |||||
| } | |||||
| } | |||||
| } | |||||
| std::vector<tensor::MSTensor *> TransferSession::GetInputs() const { return combined_inputs_; } | |||||
| int TransferSession::CompileTransferGraph() { | |||||
| combined_inputs_ = backbone_session_->GetInputs(); | |||||
| auto outputs_backbone = backbone_session_->GetOutputs(); | |||||
| auto inputs_head = lite::TrainSession::GetInputs(); | |||||
| int ret = RET_OK; | |||||
| for (auto input : inputs_head) { | |||||
| bool match = false; | |||||
| mindspore::tensor::MSTensor *output = nullptr; | |||||
| for (auto it = outputs_backbone.begin(); it != outputs_backbone.end(); ++it) { | |||||
| output = it->second; | |||||
| if (output->ElementsNum() == input->ElementsNum() && output->shape().size() == input->shape().size()) { | |||||
| match = true; | |||||
| for (std::size_t dim = 0; dim != output->shape().size(); ++dim) { | |||||
| if (input->shape().at(dim) != output->shape().at(dim)) { | |||||
| match = false; | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (true == match) { | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| if (true == match) { | |||||
| backbone_head_map_.push_back(std::make_pair(input, output)); | |||||
| } else { | |||||
| combined_inputs_.push_back(input); | |||||
| } | |||||
| } | |||||
| if (0 == backbone_head_map_.size()) { | |||||
| ret = RET_ERROR; | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| mindspore::tensor::MSTensor *TransferSession::GetInputsByTensorName(const std::string &tensor_name) const { | |||||
| /* First look in backbone netwok */ | |||||
| auto ret = backbone_session_->GetInputsByTensorName(tensor_name); | |||||
| /* If not found look in head network */ | |||||
| if (nullptr == ret) { | |||||
| ret = TrainSession::GetInputsByTensorName(tensor_name); | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| TransferSession::~TransferSession() { | |||||
| if (backbone_session_ != nullptr) { | |||||
| delete backbone_session_; | |||||
| backbone_session_ = nullptr; | |||||
| } | |||||
| if (lite_model_ != nullptr) { | |||||
| free(lite_model_); | |||||
| lite_model_ = nullptr; | |||||
| } | |||||
| } | |||||
| void TransferSession::BindThread(bool if_bind) { | |||||
| backbone_session_->BindThread(if_bind); | |||||
| TrainSession::BindThread(if_bind); | |||||
| } | |||||
| int TransferSession::RunGraph(const KernelCallBack &before, const KernelCallBack &after) { | |||||
| auto ret = backbone_session_->RunGraph(before, after); | |||||
| if (ret != RET_OK) { | |||||
| return ret; | |||||
| } | |||||
| for (auto &backbone_head_pair : backbone_head_map_) { | |||||
| auto input = backbone_head_pair.first; | |||||
| auto output = backbone_head_pair.second; | |||||
| char *input_data = reinterpret_cast<char *>(input->MutableData()); | |||||
| char *output_data = reinterpret_cast<char *>(output->MutableData()); | |||||
| std::copy(output_data, output_data + output->Size(), input_data); | |||||
| } | |||||
| ret = lite::TrainSession::RunGraph(before, after); | |||||
| return ret; | |||||
| } | |||||
| } // namespace lite | |||||
| session::TrainSession *session::TrainSession::CreateTransferSession(const char *model_buf_backbone, | |||||
| size_t size_backbone, const char *model_buf_head, | |||||
| size_t size_head, lite::Context *context, | |||||
| bool train_mode) { | |||||
| auto session = new (std::nothrow) lite::TransferSession(model_buf_backbone, size_backbone, context); | |||||
| if (session == nullptr) { | |||||
| MS_LOG(ERROR) << "create transfer session failed"; | |||||
| return nullptr; | |||||
| } | |||||
| if (!session->is_valid()) { | |||||
| MS_LOG(ERROR) << "create transfer session failed"; | |||||
| delete session; | |||||
| return nullptr; | |||||
| } | |||||
| auto ret = session->Init(context); | |||||
| if (ret != lite::RET_OK) { | |||||
| MS_LOG(ERROR) << "init transfer session failed"; | |||||
| delete session; | |||||
| return nullptr; | |||||
| } | |||||
| auto model = lite::TrainModel::Import(model_buf_head, size_head); | |||||
| if (model == nullptr) { | |||||
| MS_LOG(ERROR) << "create model for head train session failed"; | |||||
| delete session; | |||||
| return nullptr; | |||||
| } | |||||
| ret = session->CompileTrainGraph(model); | |||||
| if (ret != lite::RET_OK) { | |||||
| MS_LOG(ERROR) << "Compiling Train Graph failed"; | |||||
| delete session; | |||||
| return nullptr; | |||||
| } | |||||
| ret = session->CompileTransferGraph(); | |||||
| if (ret != lite::RET_OK) { | |||||
| MS_LOG(ERROR) << "Compiling Transfer Graph failed"; | |||||
| delete session; | |||||
| return nullptr; | |||||
| } | |||||
| if (train_mode) { | |||||
| ret = session->Train(); | |||||
| } else { | |||||
| ret = session->Eval(); | |||||
| } | |||||
| if (ret != lite::RET_OK) { | |||||
| MS_LOG(ERROR) << "Could not switch to Train Mode " << train_mode; | |||||
| delete session; | |||||
| return nullptr; | |||||
| } | |||||
| return session; | |||||
| } | |||||
| session::TrainSession *session::TrainSession::CreateTransferSession(const std::string &filename_backbone, | |||||
| const std::string &filename_head, | |||||
| lite::Context *context, bool train_mode) { | |||||
| size_t size_head = -1; | |||||
| size_t size_backbone = -1; | |||||
| auto buf_head = lite::ReadFileToBuf(filename_head, &size_head); | |||||
| if (buf_head == nullptr) { | |||||
| return nullptr; | |||||
| } | |||||
| auto buf_backbone = lite::ReadFileToBuf(filename_backbone, &size_backbone); | |||||
| if (buf_backbone == nullptr) { | |||||
| return nullptr; | |||||
| } | |||||
| return session::TrainSession::CreateTransferSession(buf_backbone.get(), size_backbone, buf_head.get(), size_head, | |||||
| context, train_mode); | |||||
| } | |||||
| } // namespace mindspore | |||||
| @@ -19,6 +19,7 @@ | |||||
| #include <string> | #include <string> | ||||
| #include <tuple> | #include <tuple> | ||||
| #include <unordered_map> | #include <unordered_map> | ||||
| #include <utility> | |||||
| #include "src/ops/primitive_c.h" | #include "src/ops/primitive_c.h" | ||||
| #include "include/train_session.h" | #include "include/train_session.h" | ||||
| #include "src/train/train_model.h" | #include "src/train/train_model.h" | ||||
| @@ -50,20 +51,26 @@ namespace lite { | |||||
| class TransferSession : public lite::TrainSession { | class TransferSession : public lite::TrainSession { | ||||
| public: | public: | ||||
| TransferSession(); | |||||
| explicit TransferSession(lite::LiteSession *backend_session); | |||||
| explicit TransferSession(const char *model_buf_backbone, size_t size_backbone, lite::Context *context); | |||||
| ~TransferSession(); | ~TransferSession(); | ||||
| bool is_valid() const { return is_valid_; } | |||||
| int RunGraph(const KernelCallBack &before = nullptr, const KernelCallBack &after = nullptr) override; | int RunGraph(const KernelCallBack &before = nullptr, const KernelCallBack &after = nullptr) override; | ||||
| void BindThread(bool if_bind) override; | void BindThread(bool if_bind) override; | ||||
| std::vector<tensor::MSTensor *> GetInputs() const override { return lite::LiteSession::GetInputs(); } | |||||
| mindspore::tensor::MSTensor *GetInputsByTensorName(const std::string &tensor_name) const override { | |||||
| return lite::LiteSession::GetInputsByTensorName(tensor_name); | |||||
| } | |||||
| std::vector<tensor::MSTensor *> GetInputs() const override; | |||||
| mindspore::tensor::MSTensor *GetInputsByTensorName(const std::string &tensor_name) const override; | |||||
| int CompileTransferGraph(); | |||||
| protected: | protected: | ||||
| lite::LiteSession *backend_session_; | |||||
| lite::LiteSession *backbone_session_; | |||||
| char *lite_model_; | |||||
| std::vector<mindspore::tensor::MSTensor *> combined_inputs_; | |||||
| std::vector<std::pair<mindspore::tensor::MSTensor *, mindspore::tensor::MSTensor *>> backbone_head_map_; | |||||
| bool is_valid_; | |||||
| private: | private: | ||||
| }; | }; | ||||
| @@ -0,0 +1,4 @@ | |||||
| benchmark_train_test | |||||
| logs_train | |||||
| ms_models_train | |||||
| net_train_test | |||||
| @@ -244,6 +244,7 @@ if(SUPPORT_TRAIN) | |||||
| ${TEST_LITE_SRC} | ${TEST_LITE_SRC} | ||||
| ${LITE_DIR}/src/train/train_populate_parameter.cc | ${LITE_DIR}/src/train/train_populate_parameter.cc | ||||
| ${LITE_DIR}/src/train/train_session.cc | ${LITE_DIR}/src/train/train_session.cc | ||||
| ${LITE_DIR}/src/train/transfer_session.cc | |||||
| ${LITE_DIR}/src/train/train_model.cc | ${LITE_DIR}/src/train/train_model.cc | ||||
| ${LITE_DIR}/src/lite_session.cc | ${LITE_DIR}/src/lite_session.cc | ||||
| ) | ) | ||||
| @@ -332,6 +333,10 @@ endif() | |||||
| add_executable(lite-test ${TEST_SRC}) | add_executable(lite-test ${TEST_SRC}) | ||||
| add_dependencies(lite-test fbs_src) | add_dependencies(lite-test fbs_src) | ||||
| target_link_libraries(lite-test dl mindspore::gtest) | target_link_libraries(lite-test dl mindspore::gtest) | ||||
| if(SUPPORT_TRAIN) | |||||
| target_link_libraries(lite-test minddata-lite) | |||||
| endif() | |||||
| if(PLATFORM_ARM64 AND ENABLE_FP16) | if(PLATFORM_ARM64 AND ENABLE_FP16) | ||||
| target_link_libraries(lite-test nnacl_fp16_mid nnacl_optimize_mid) | target_link_libraries(lite-test nnacl_fp16_mid nnacl_optimize_mid) | ||||
| endif() | endif() | ||||
| @@ -1,7 +1,7 @@ | |||||
| mini_alexnet | mini_alexnet | ||||
| mobilenetv1 | mobilenetv1 | ||||
| mobilenetv2 | mobilenetv2 | ||||
| #mobilenetv3 | |||||
| mobilenetv3 | |||||
| lenet | lenet | ||||
| effnet | effnet | ||||
| effnet_tune | effnet_tune | ||||
| @@ -9,7 +9,7 @@ resnet | |||||
| googlenet | googlenet | ||||
| # densenet | # densenet | ||||
| # shufflenetv2 | # shufflenetv2 | ||||
| # nin | |||||
| #nin | |||||
| # one_net | # one_net | ||||
| # lenetv1 | # lenetv1 | ||||
| #LAST | |||||
| #LAST | |||||
| @@ -16,13 +16,19 @@ function Print_Result() { | |||||
| basepath=$(pwd) | basepath=$(pwd) | ||||
| echo ${basepath} | echo ${basepath} | ||||
| # Set models default config filepath | |||||
| models_mindspore_train_config=${basepath}/models_ms_train.cfg | |||||
| # Example:run_net_export.sh -m /home/emir/Work/TestingEnv/train_models | # Example:run_net_export.sh -m /home/emir/Work/TestingEnv/train_models | ||||
| epoch_num=1 | epoch_num=1 | ||||
| while getopts "m:t:" opt; do | |||||
| while getopts "c:m:t:" opt; do | |||||
| case ${opt} in | case ${opt} in | ||||
| c) | |||||
| models_mindspore_train_config=${OPTARG} | |||||
| echo "models_mindspore_train_config is ${models_mindspore_train_config}" | |||||
| ;; | |||||
| m) | m) | ||||
| models_path=${OPTARG}"/models_train" | models_path=${OPTARG}"/models_train" | ||||
| echo "models_path is ${OPTARG}" | echo "models_path is ${OPTARG}" | ||||
| ;; | ;; | ||||
| @@ -37,9 +43,6 @@ while getopts "m:t:" opt; do | |||||
| done | done | ||||
| # Set models config filepath | |||||
| models_mindspore_train_config=${basepath}/models_ms_train.cfg | |||||
| logs_path=${basepath}/logs_train | logs_path=${basepath}/logs_train | ||||
| rm -rf ${logs_path} | rm -rf ${logs_path} | ||||
| mkdir -p ${logs_path} | mkdir -p ${logs_path} | ||||
| @@ -81,9 +81,9 @@ function Run_x86() { | |||||
| echo ${model_name}'_train' >> "${run_x86_log_file}" | echo ${model_name}'_train' >> "${run_x86_log_file}" | ||||
| echo 'cd '${x86_path}'/mindspore-lite-'${version}'-train-linux-x64' >> "${run_x86_log_file}" | echo 'cd '${x86_path}'/mindspore-lite-'${version}'-train-linux-x64' >> "${run_x86_log_file}" | ||||
| cd ${x86_path}/mindspore-lite-${version}-train-linux-x64 || return 1 | cd ${x86_path}/mindspore-lite-${version}-train-linux-x64 || return 1 | ||||
| echo 'LD_LIBRARY_PATH='${LD_LIBRARY_PATH}':./lib:./third_party/libjpeg-turbo/lib:./third_party/opencv/lib;./benchmark_train/benchmark_train --epochs='${epoch_num}' --modelFile='${ms_models_path}'/'${model_name}'_train.ms --inDataFile='${train_io_path}/${model_name}_input1.bin,${train_io_path}/${model_name}_input2.bin' --expectedDataFile='${train_io_path}'/'${model_name}'_output --exportFile='${ms_models_path}'/'${model_name}'_train_exported.ms' >> "${run_x86_log_file}" | |||||
| echo 'LD_LIBRARY_PATH='${LD_LIBRARY_PATH}':./lib:./third_party/libjpeg-turbo/lib:./third_party/opencv/lib ./benchmark_train/benchmark_train --epochs='${epoch_num}' --modelFile='${ms_models_path}'/'${model_name}'_train.ms --inDataFile='${train_io_path}/${model_name}_input1.bin,${train_io_path}/${model_name}_input2.bin' --expectedDataFile='${train_io_path}'/'${model_name}'_output --exportFile='${ms_models_path}'/'${model_name}'_train_exported.ms' >> "${run_x86_log_file}" | |||||
| echo '-------------------------------------------------------------------------------' >> "${run_x86_log_file}" | echo '-------------------------------------------------------------------------------' >> "${run_x86_log_file}" | ||||
| LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:./lib:./third_party/libjpeg-turbo/lib:./third_party/opencv/lib \ | |||||
| LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:./lib:./third_party/libjpeg-turbo/lib:./third_party/opencv/lib:./minddata/lib:./minddata/third_party/libjpeg-turbo/lib \ | |||||
| ${run_valgrind}./benchmark_train/benchmark_train \ | ${run_valgrind}./benchmark_train/benchmark_train \ | ||||
| --modelFile=${ms_models_path}/${model_name}_train.ms \ | --modelFile=${ms_models_path}/${model_name}_train.ms \ | ||||
| --inDataFile=${train_io_path}/${model_name}_input1.bin,${train_io_path}/${model_name}_input2.bin \ | --inDataFile=${train_io_path}/${model_name}_input1.bin,${train_io_path}/${model_name}_input2.bin \ | ||||
| @@ -131,13 +131,10 @@ function Run_arm() { | |||||
| # If build with minddata, copy the minddata related libs | # If build with minddata, copy the minddata related libs | ||||
| cd ${benchmark_train_test_path} || exit 1 | cd ${benchmark_train_test_path} || exit 1 | ||||
| if [ -f ${arm_path}/mindspore-lite-${version_arm}-train-android-${process_unit}/lib/libminddata-lite.so ]; then | |||||
| cp -a ${arm_path}/mindspore-lite-${version_arm}-train-android-${process_unit}/third_party/libjpeg-turbo/lib/libjpeg.so ${benchmark_train_test_path}/libjpeg.so || exit 1 | |||||
| cp -a ${arm_path}/mindspore-lite-${version_arm}-train-android-${process_unit}/third_party/libjpeg-turbo/lib/libturbojpeg.so ${benchmark_train_test_path}/libturbojpeg.so || exit 1 | |||||
| cp -a ${arm_path}/mindspore-lite-${version_arm}-train-android-${process_unit}/third_party/opencv/lib/libopencv_core.so ${benchmark_train_test_path}/libopencv_core.so || exit 1 | |||||
| cp -a ${arm_path}/mindspore-lite-${version_arm}-train-android-${process_unit}/third_party/opencv/lib/libopencv_imgcodecs.so ${benchmark_train_test_path}/libopencv_imgcodecs.so || exit 1 | |||||
| cp -a ${arm_path}/mindspore-lite-${version_arm}-train-android-${process_unit}/third_party/opencv/lib/libopencv_imgproc.so ${benchmark_train_test_path}/libopencv_imgproc.so || exit 1 | |||||
| cp -a ${arm_path}/mindspore-lite-${version_arm}-train-android-${process_unit}/lib/libminddata-lite.so ${benchmark_train_test_path}/libminddata-lite.so || exit 1 | |||||
| if [ -f ${arm_path}/mindspore-lite-${version_arm}-train-android-${process_unit}/minddata/lib/libminddata-lite.so ]; then | |||||
| cp -a ${arm_path}/mindspore-lite-${version_arm}-train-android-${process_unit}/minddata/third_party/libjpeg-turbo/lib/libjpeg.so ${benchmark_train_test_path}/libjpeg.so || exit 1 | |||||
| cp -a ${arm_path}/mindspore-lite-${version_arm}-train-android-${process_unit}/minddata/third_party/libjpeg-turbo/lib/libturbojpeg.so ${benchmark_train_test_path}/libturbojpeg.so || exit 1 | |||||
| cp -a ${arm_path}/mindspore-lite-${version_arm}-train-android-${process_unit}/minddata/lib/libminddata-lite.so ${benchmark_train_test_path}/libminddata-lite.so || exit 1 | |||||
| fi | fi | ||||
| if [ "$1" == arm64 ]; then | if [ "$1" == arm64 ]; then | ||||
| cp -a ${arm_path}/mindspore-lite-${version_arm}-train-android-${process_unit}/third_party/hiai_ddk/lib/libhiai.so ${benchmark_train_test_path}/libhiai.so || exit 1 | cp -a ${arm_path}/mindspore-lite-${version_arm}-train-android-${process_unit}/third_party/hiai_ddk/lib/libhiai.so ${benchmark_train_test_path}/libhiai.so || exit 1 | ||||
| @@ -230,12 +227,15 @@ function Print_Result() { | |||||
| basepath=$(pwd) | basepath=$(pwd) | ||||
| echo ${basepath} | echo ${basepath} | ||||
| # Set default models config filepath | |||||
| models_mindspore_train_config=${basepath}/models_ms_train.cfg | |||||
| # Example:run_benchmark_train.sh -r /home/emir/Work/TestingEnv/release -m /home/emir/Work/TestingEnv/train_models -i /home/emir/Work/TestingEnv/train_io -d "8KE5T19620002408" | # Example:run_benchmark_train.sh -r /home/emir/Work/TestingEnv/release -m /home/emir/Work/TestingEnv/train_models -i /home/emir/Work/TestingEnv/train_io -d "8KE5T19620002408" | ||||
| # For running on arm64, use -t to set platform tools path (for using adb commands) | # For running on arm64, use -t to set platform tools path (for using adb commands) | ||||
| epoch_num=1 | epoch_num=1 | ||||
| threads=2 | threads=2 | ||||
| train_io_path="" | train_io_path="" | ||||
| while getopts "r:m:d:i:e:vt:q:D" opt; do | |||||
| while getopts "r:M:c:m:d:i:e:vt:q:D" opt; do | |||||
| case ${opt} in | case ${opt} in | ||||
| r) | r) | ||||
| release_path=${OPTARG} | release_path=${OPTARG} | ||||
| @@ -245,6 +245,14 @@ while getopts "r:m:d:i:e:vt:q:D" opt; do | |||||
| models_path=${OPTARG}"/models_train" | models_path=${OPTARG}"/models_train" | ||||
| echo "models_path is ${OPTARG}" | echo "models_path is ${OPTARG}" | ||||
| ;; | ;; | ||||
| M) | |||||
| models_path=${OPTARG} | |||||
| echo "models_path is ${models_path}" | |||||
| ;; | |||||
| c) | |||||
| models_mindspore_train_config=${OPTARG} | |||||
| echo "models_mindspore_train_config is ${models_mindspore_train_config}" | |||||
| ;; | |||||
| i) | i) | ||||
| train_io_path=${OPTARG} | train_io_path=${OPTARG} | ||||
| echo "train_io_path is ${OPTARG}" | echo "train_io_path is ${OPTARG}" | ||||
| @@ -278,8 +286,10 @@ done | |||||
| if [[ $train_io_path == "" ]] | if [[ $train_io_path == "" ]] | ||||
| then | then | ||||
| echo "train_io path is empty" | |||||
| train_io_path=${models_path}/input_output | train_io_path=${models_path}/input_output | ||||
| fi | fi | ||||
| echo $train_io_path | |||||
| arm64_path=${release_path}/android_aarch64 | arm64_path=${release_path}/android_aarch64 | ||||
| file=$(ls ${arm64_path}/*train-android-aarch64.tar.gz) | file=$(ls ${arm64_path}/*train-android-aarch64.tar.gz) | ||||
| @@ -299,9 +309,6 @@ file_name="${file##*/}" | |||||
| IFS="-" read -r -a file_name_array <<< "$file_name" | IFS="-" read -r -a file_name_array <<< "$file_name" | ||||
| version=${file_name_array[2]} | version=${file_name_array[2]} | ||||
| # Set models config filepath | |||||
| models_mindspore_train_config=${basepath}/models_ms_train.cfg | |||||
| ms_models_path=${basepath}/ms_models_train | ms_models_path=${basepath}/ms_models_train | ||||
| logs_path=${basepath}/logs_train | logs_path=${basepath}/logs_train | ||||
| @@ -387,16 +394,11 @@ Run_x86_PID=$! | |||||
| sleep 1 | sleep 1 | ||||
| # wait ${Run_x86_PID} | |||||
| cat ${run_benchmark_train_result_file} | |||||
| wait ${Run_x86_PID} | |||||
| Run_x86_status=$? | |||||
| # Run on arm64 | # Run on arm64 | ||||
| echo "start Run arm64 ..." | echo "start Run arm64 ..." | ||||
| Run_arm arm64 | Run_arm arm64 | ||||
| Run_arm64_status=$? | Run_arm64_status=$? | ||||
| sleep 3 | |||||
| sleep 1 | |||||
| # Run on arm32 | # Run on arm32 | ||||
| echo "start Run arm32 ..." | echo "start Run arm32 ..." | ||||
| @@ -404,6 +406,10 @@ Run_arm arm32 | |||||
| Run_arm32_status=$? | Run_arm32_status=$? | ||||
| sleep 1 | sleep 1 | ||||
| wait ${Run_x86_PID} | |||||
| Run_x86_status=$? | |||||
| cat ${run_benchmark_train_result_file} | |||||
| END=$(date +%s.%N) | END=$(date +%s.%N) | ||||
| DIFF=$(echo "$END - $START" | bc) | DIFF=$(echo "$END - $START" | bc) | ||||
| @@ -415,6 +421,8 @@ function Print_Benchmark_Result() { | |||||
| done < ${run_benchmark_train_result_file} | done < ${run_benchmark_train_result_file} | ||||
| MS_PRINT_TESTCASE_END_MSG | MS_PRINT_TESTCASE_END_MSG | ||||
| } | } | ||||
| result=0 | result=0 | ||||
| # Check benchmark_train result and return value | # Check benchmark_train result and return value | ||||
| if [[ ${Run_x86_status} != 0 ]];then | if [[ ${Run_x86_status} != 0 ]];then | ||||
| @@ -16,23 +16,15 @@ else() | |||||
| endif() | endif() | ||||
| if(PLATFORM_ARM32 OR PLATFORM_ARM64) | if(PLATFORM_ARM32 OR PLATFORM_ARM64) | ||||
| target_link_libraries(benchmark_train mindspore-lite) | |||||
| target_link_libraries(benchmark_train mindspore-lite minddata-lite) | |||||
| else() | else() | ||||
| if(WIN32) | if(WIN32) | ||||
| target_link_libraries(benchmark_train mindspore-lite_static pthread cpu_kernel_mid nnacl_mid) | |||||
| target_link_libraries(benchmark_train mindspore-lite_static pthread cpu_kernel_mid nnacl_mid minddata-lite) | |||||
| else() | else() | ||||
| target_link_libraries(benchmark_train mindspore-lite pthread) | |||||
| endif() | |||||
| endif() | |||||
| if(PLATFORM_ARM32 OR PLATFORM_ARM64) | |||||
| install(TARGETS benchmark_train | |||||
| RUNTIME DESTINATION ${MAIN_DIR}-${RUNTIME_COMPONENT_NAME}/benchmark_train COMPONENT ${RUNTIME_COMPONENT_NAME}) | |||||
| else() | |||||
| if(WIN32) | |||||
| install(TARGETS benchmark_train | |||||
| RUNTIME DESTINATION ${MAIN_DIR}-${RUNTIME_COMPONENT_NAME}/benchmark_train COMPONENT ${RUNTIME_COMPONENT_NAME}) | |||||
| else() | |||||
| install(TARGETS benchmark_train | |||||
| RUNTIME DESTINATION ${MAIN_DIR}-${RUNTIME_COMPONENT_NAME}/benchmark_train COMPONENT ${RUNTIME_COMPONENT_NAME}) | |||||
| target_link_libraries(benchmark_train mindspore-lite pthread minddata-lite) | |||||
| endif() | endif() | ||||
| endif() | endif() | ||||
| install(TARGETS benchmark_train | |||||
| RUNTIME DESTINATION ${MAIN_DIR}-${RUNTIME_COMPONENT_NAME}/benchmark_train | |||||
| COMPONENT ${RUNTIME_COMPONENT_NAME}) | |||||
| @@ -124,7 +124,11 @@ int NetTrain::ReadInputFile() { | |||||
| MS_LOG(ERROR) << "Not supported image input"; | MS_LOG(ERROR) << "Not supported image input"; | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| } else { | } else { | ||||
| for (size_t i = 0; i < flags_->input_data_list_.size(); i++) { | |||||
| if (ms_inputs_.size() > flags_->input_data_list_.size()) { | |||||
| MS_LOG(ERROR) << "missing input files"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| for (size_t i = 0; i < ms_inputs_.size(); i++) { | |||||
| auto cur_tensor = ms_inputs_.at(i); | auto cur_tensor = ms_inputs_.at(i); | ||||
| MS_ASSERT(cur_tensor != nullptr); | MS_ASSERT(cur_tensor != nullptr); | ||||
| size_t size; | size_t size; | ||||
| @@ -163,6 +167,7 @@ int NetTrain::CompareOutput() { | |||||
| int i = 1; | int i = 1; | ||||
| for (auto it = tensors_list.begin(); it != tensors_list.end(); ++it) { | for (auto it = tensors_list.begin(); it != tensors_list.end(); ++it) { | ||||
| tensor = session_->GetOutputByTensorName(it->first); | tensor = session_->GetOutputByTensorName(it->first); | ||||
| std::cout << "output is tensor " << it->first << "\n"; | |||||
| auto outputs = tensor->MutableData(); | auto outputs = tensor->MutableData(); | ||||
| size_t size; | size_t size; | ||||
| std::string output_file = flags_->data_file_ + std::to_string(i) + ".bin"; | std::string output_file = flags_->data_file_ + std::to_string(i) + ".bin"; | ||||
| @@ -185,7 +190,7 @@ int NetTrain::CompareOutput() { | |||||
| break; | break; | ||||
| } | } | ||||
| i++; | i++; | ||||
| delete bin_buf; | |||||
| delete[] bin_buf; | |||||
| } | } | ||||
| if (!has_error) { | if (!has_error) { | ||||
| @@ -326,7 +331,6 @@ int NetTrain::RunExportedNet() { | |||||
| std::cout << "CreateSession failed while running ", model_name.c_str(); | std::cout << "CreateSession failed while running ", model_name.c_str(); | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| } | } | ||||
| ms_inputs_ = session_->GetInputs(); | ms_inputs_ = session_->GetInputs(); | ||||
| auto end_prepare_time = GetTimeUs(); | auto end_prepare_time = GetTimeUs(); | ||||
| MS_LOG(INFO) << "Exported model PrepareTime = " << (end_prepare_time - start_prepare_time) / 1000 << " ms"; | MS_LOG(INFO) << "Exported model PrepareTime = " << (end_prepare_time - start_prepare_time) / 1000 << " ms"; | ||||
| @@ -438,7 +442,7 @@ int NetTrain::RunNetTrain() { | |||||
| std::cout << "Run SaveToFile error"; | std::cout << "Run SaveToFile error"; | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| } | } | ||||
| // delete session_; | |||||
| delete session_; | |||||
| status = RunExportedNet(); | status = RunExportedNet(); | ||||
| if (status != RET_OK) { | if (status != RET_OK) { | ||||
| MS_LOG(ERROR) << "Run Exported model error: " << status; | MS_LOG(ERROR) << "Run Exported model error: " << status; | ||||