You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_pynative_resnet50_ascend.py 14 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. # Copyright 2020 Huawei Technologies Co., Ltd
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. # ============================================================================
  15. import time
  16. import random
  17. import numpy as np
  18. import pytest
  19. import mindspore.common.dtype as mstype
  20. import mindspore.dataset as ds
  21. import mindspore.dataset.transforms.c_transforms as C
  22. import mindspore.dataset.vision.c_transforms as vision
  23. import mindspore.nn as nn
  24. import mindspore.ops.functional as F
  25. from mindspore import Tensor
  26. from mindspore import context
  27. from mindspore import ParameterTuple
  28. from mindspore.nn import Cell
  29. from mindspore.ops import operations as P
  30. from mindspore.ops import composite as CP
  31. from mindspore.nn.optim.momentum import Momentum
  32. from mindspore.train.callback import LossMonitor, Callback
  33. from mindspore.nn.loss import SoftmaxCrossEntropyWithLogits
  34. from mindspore.train.loss_scale_manager import FixedLossScaleManager
  35. from mindspore.train.model import Model
  36. class MyTimeMonitor(Callback):
  37. def __init__(self, data_size):
  38. super(MyTimeMonitor, self).__init__()
  39. self.data_size = data_size
  40. self.total = 0
  41. def epoch_begin(self, run_context):
  42. self.epoch_time = time.time()
  43. def epoch_end(self, run_context):
  44. epoch_msseconds = (time.time()-self.epoch_time) * 1000
  45. per_step_mssconds = epoch_msseconds / self.data_size
  46. print("epoch time:{0}, per step time:{1}".format(epoch_msseconds, per_step_mssconds), flush=True)
  47. def step_begin(self, run_context):
  48. self.step_time = time.time()
  49. def step_end(self, run_context):
  50. step_msseconds = (time.time() - self.step_time) * 1000
  51. if step_msseconds < 265:
  52. self.total = self.total + 1
  53. print(f"step time:{step_msseconds}", flush=True)
  54. def good_step(self):
  55. return self.total
  56. random.seed(1)
  57. np.random.seed(1)
  58. ds.config.set_seed(1)
  59. grad_by_list = CP.GradOperation(get_by_list=True)
  60. def weight_variable_0(shape):
  61. zeros = np.zeros(shape).astype(np.float32)
  62. return Tensor(zeros)
  63. def weight_variable_1(shape):
  64. ones = np.ones(shape).astype(np.float32)
  65. return Tensor(ones)
  66. def conv3x3(in_channels, out_channels, stride=1, padding=0):
  67. """3x3 convolution """
  68. return nn.Conv2d(in_channels, out_channels,
  69. kernel_size=3, stride=stride, padding=padding, weight_init='XavierUniform',
  70. has_bias=False, pad_mode="same")
  71. def conv1x1(in_channels, out_channels, stride=1, padding=0):
  72. """1x1 convolution"""
  73. return nn.Conv2d(in_channels, out_channels,
  74. kernel_size=1, stride=stride, padding=padding, weight_init='XavierUniform',
  75. has_bias=False, pad_mode="same")
  76. def conv7x7(in_channels, out_channels, stride=1, padding=0):
  77. """1x1 convolution"""
  78. return nn.Conv2d(in_channels, out_channels,
  79. kernel_size=7, stride=stride, padding=padding, weight_init='XavierUniform',
  80. has_bias=False, pad_mode="same")
  81. def bn_with_initialize(out_channels):
  82. shape = (out_channels)
  83. mean = weight_variable_0(shape)
  84. var = weight_variable_1(shape)
  85. beta = weight_variable_0(shape)
  86. bn = nn.BatchNorm2d(out_channels, momentum=0.99, eps=0.00001, gamma_init='Uniform',
  87. beta_init=beta, moving_mean_init=mean, moving_var_init=var)
  88. return bn
  89. def bn_with_initialize_last(out_channels):
  90. shape = (out_channels)
  91. mean = weight_variable_0(shape)
  92. var = weight_variable_1(shape)
  93. beta = weight_variable_0(shape)
  94. bn = nn.BatchNorm2d(out_channels, momentum=0.99, eps=0.00001, gamma_init='Uniform',
  95. beta_init=beta, moving_mean_init=mean, moving_var_init=var)
  96. return bn
  97. def fc_with_initialize(input_channels, out_channels):
  98. return nn.Dense(input_channels, out_channels, weight_init='XavierUniform', bias_init='Uniform')
  99. class ResidualBlock(nn.Cell):
  100. expansion = 4
  101. def __init__(self,
  102. in_channels,
  103. out_channels,
  104. stride=1):
  105. super(ResidualBlock, self).__init__()
  106. out_chls = out_channels // self.expansion
  107. self.conv1 = conv1x1(in_channels, out_chls, stride=stride, padding=0)
  108. self.bn1 = bn_with_initialize(out_chls)
  109. self.conv2 = conv3x3(out_chls, out_chls, stride=1, padding=0)
  110. self.bn2 = bn_with_initialize(out_chls)
  111. self.conv3 = conv1x1(out_chls, out_channels, stride=1, padding=0)
  112. self.bn3 = bn_with_initialize_last(out_channels)
  113. self.relu = P.ReLU()
  114. self.add = P.Add()
  115. def construct(self, x):
  116. identity = x
  117. out = self.conv1(x)
  118. out = self.bn1(out)
  119. out = self.relu(out)
  120. out = self.conv2(out)
  121. out = self.bn2(out)
  122. out = self.relu(out)
  123. out = self.conv3(out)
  124. out = self.bn3(out)
  125. out = self.add(out, identity)
  126. out = self.relu(out)
  127. return out
  128. class ResidualBlockWithDown(nn.Cell):
  129. expansion = 4
  130. def __init__(self,
  131. in_channels,
  132. out_channels,
  133. stride=1,
  134. down_sample=False):
  135. super(ResidualBlockWithDown, self).__init__()
  136. out_chls = out_channels // self.expansion
  137. self.conv1 = conv1x1(in_channels, out_chls, stride=stride, padding=0)
  138. self.bn1 = bn_with_initialize(out_chls)
  139. self.conv2 = conv3x3(out_chls, out_chls, stride=1, padding=0)
  140. self.bn2 = bn_with_initialize(out_chls)
  141. self.conv3 = conv1x1(out_chls, out_channels, stride=1, padding=0)
  142. self.bn3 = bn_with_initialize_last(out_channels)
  143. self.relu = P.ReLU()
  144. self.downSample = down_sample
  145. self.conv_down_sample = conv1x1(in_channels, out_channels, stride=stride, padding=0)
  146. self.bn_down_sample = bn_with_initialize(out_channels)
  147. self.add = P.Add()
  148. def construct(self, x):
  149. identity = x
  150. out = self.conv1(x)
  151. out = self.bn1(out)
  152. out = self.relu(out)
  153. out = self.conv2(out)
  154. out = self.bn2(out)
  155. out = self.relu(out)
  156. out = self.conv3(out)
  157. out = self.bn3(out)
  158. identity = self.conv_down_sample(identity)
  159. identity = self.bn_down_sample(identity)
  160. out = self.add(out, identity)
  161. out = self.relu(out)
  162. return out
  163. class MakeLayer0(nn.Cell):
  164. def __init__(self, block, in_channels, out_channels, stride):
  165. super(MakeLayer0, self).__init__()
  166. self.a = ResidualBlockWithDown(in_channels, out_channels, stride=1, down_sample=True)
  167. self.b = block(out_channels, out_channels, stride=stride)
  168. self.c = block(out_channels, out_channels, stride=1)
  169. def construct(self, x):
  170. x = self.a(x)
  171. x = self.b(x)
  172. x = self.c(x)
  173. return x
  174. class MakeLayer1(nn.Cell):
  175. def __init__(self, block, in_channels, out_channels, stride):
  176. super(MakeLayer1, self).__init__()
  177. self.a = ResidualBlockWithDown(in_channels, out_channels, stride=stride, down_sample=True)
  178. self.b = block(out_channels, out_channels, stride=1)
  179. self.c = block(out_channels, out_channels, stride=1)
  180. self.d = block(out_channels, out_channels, stride=1)
  181. def construct(self, x):
  182. x = self.a(x)
  183. x = self.b(x)
  184. x = self.c(x)
  185. x = self.d(x)
  186. return x
  187. class MakeLayer2(nn.Cell):
  188. def __init__(self, block, in_channels, out_channels, stride):
  189. super(MakeLayer2, self).__init__()
  190. self.a = ResidualBlockWithDown(in_channels, out_channels, stride=stride, down_sample=True)
  191. self.b = block(out_channels, out_channels, stride=1)
  192. self.c = block(out_channels, out_channels, stride=1)
  193. self.d = block(out_channels, out_channels, stride=1)
  194. self.e = block(out_channels, out_channels, stride=1)
  195. self.f = block(out_channels, out_channels, stride=1)
  196. def construct(self, x):
  197. x = self.a(x)
  198. x = self.b(x)
  199. x = self.c(x)
  200. x = self.d(x)
  201. x = self.e(x)
  202. x = self.f(x)
  203. return x
  204. class MakeLayer3(nn.Cell):
  205. def __init__(self, block, in_channels, out_channels, stride):
  206. super(MakeLayer3, self).__init__()
  207. self.a = ResidualBlockWithDown(in_channels, out_channels, stride=stride, down_sample=True)
  208. self.b = block(out_channels, out_channels, stride=1)
  209. self.c = block(out_channels, out_channels, stride=1)
  210. def construct(self, x):
  211. x = self.a(x)
  212. x = self.b(x)
  213. x = self.c(x)
  214. return x
  215. class ResNet(nn.Cell):
  216. def __init__(self, block, num_classes=100, batch_size=32):
  217. super(ResNet, self).__init__()
  218. self.batch_size = batch_size
  219. self.num_classes = num_classes
  220. self.conv1 = conv7x7(3, 64, stride=2, padding=0)
  221. self.bn1 = bn_with_initialize(64)
  222. self.relu = P.ReLU()
  223. self.maxpool = P.MaxPoolWithArgmax(kernel_size=3, strides=2, pad_mode="SAME")
  224. self.layer1 = MakeLayer0(block, in_channels=64, out_channels=256, stride=1)
  225. self.layer2 = MakeLayer1(block, in_channels=256, out_channels=512, stride=2)
  226. self.layer3 = MakeLayer2(block, in_channels=512, out_channels=1024, stride=2)
  227. self.layer4 = MakeLayer3(block, in_channels=1024, out_channels=2048, stride=2)
  228. self.pool = P.ReduceMean(keep_dims=True)
  229. self.squeeze = P.Squeeze(axis=(2, 3))
  230. self.fc = fc_with_initialize(512 * block.expansion, num_classes)
  231. def construct(self, x):
  232. x = self.conv1(x)
  233. x = self.bn1(x)
  234. x = self.relu(x)
  235. x = self.maxpool(x)[0]
  236. x = self.layer1(x)
  237. x = self.layer2(x)
  238. x = self.layer3(x)
  239. x = self.layer4(x)
  240. x = self.pool(x, (2, 3))
  241. x = self.squeeze(x)
  242. x = self.fc(x)
  243. return x
  244. def resnet50(batch_size, num_classes):
  245. return ResNet(ResidualBlock, num_classes, batch_size)
  246. def create_dataset(repeat_num=1, training=True, batch_size=32, num_samples=1600):
  247. data_home = "/home/workspace/mindspore_dataset"
  248. data_dir = data_home + "/cifar-10-batches-bin"
  249. if not training:
  250. data_dir = data_home + "/cifar-10-verify-bin"
  251. data_set = ds.Cifar10Dataset(data_dir, num_samples=num_samples)
  252. resize_height = 224
  253. resize_width = 224
  254. rescale = 1.0 / 255.0
  255. shift = 0.0
  256. # define map operations
  257. random_crop_op = vision.RandomCrop((32, 32), (4, 4, 4, 4)) # padding_mode default CONSTANT
  258. random_horizontal_op = vision.RandomHorizontalFlip()
  259. # interpolation default BILINEAR
  260. resize_op = vision.Resize((resize_height, resize_width))
  261. rescale_op = vision.Rescale(rescale, shift)
  262. normalize_op = vision.Normalize((0.4465, 0.4822, 0.4914), (0.2010, 0.1994, 0.2023))
  263. changeswap_op = vision.HWC2CHW()
  264. type_cast_op = C.TypeCast(mstype.int32)
  265. c_trans = []
  266. if training:
  267. c_trans = [random_crop_op, random_horizontal_op]
  268. c_trans += [resize_op, rescale_op, normalize_op,
  269. changeswap_op]
  270. # apply map operations on images
  271. data_set = data_set.map(operations=type_cast_op, input_columns="label")
  272. data_set = data_set.map(operations=c_trans, input_columns="image")
  273. # apply shuffle operations
  274. data_set = data_set.shuffle(buffer_size=1000)
  275. # apply batch operations
  276. data_set = data_set.batch(batch_size=batch_size, drop_remainder=True)
  277. # apply repeat operations
  278. data_set = data_set.repeat(repeat_num)
  279. return data_set
  280. class CrossEntropyLoss(nn.Cell):
  281. def __init__(self):
  282. super(CrossEntropyLoss, self).__init__()
  283. self.cross_entropy = P.SoftmaxCrossEntropyWithLogits()
  284. self.mean = P.ReduceMean()
  285. self.one_hot = P.OneHot()
  286. self.one = Tensor(1.0, mstype.float32)
  287. self.zero = Tensor(0.0, mstype.float32)
  288. def construct(self, logits, label):
  289. label = self.one_hot(label, F.shape(logits)[1], self.one, self.zero)
  290. loss = self.cross_entropy(logits, label)[0]
  291. loss = self.mean(loss, (-1,))
  292. return loss
  293. class GradWrap(Cell):
  294. """ GradWrap definition """
  295. def __init__(self, network):
  296. super(GradWrap, self).__init__()
  297. self.network = network
  298. self.weights = ParameterTuple(network.trainable_params())
  299. def construct(self, x, label):
  300. weights = self.weights
  301. return grad_by_list(self.network, weights)(x, label)
  302. @pytest.mark.level1
  303. @pytest.mark.platform_arm_ascend_training
  304. @pytest.mark.platform_x86_ascend_training
  305. @pytest.mark.env_onecard
  306. def test_pynative_resnet50():
  307. context.set_context(mode=context.PYNATIVE_MODE, device_target="Ascend")
  308. batch_size = 32
  309. num_classes = 10
  310. loss_scale = 128
  311. total_step = 50
  312. net = resnet50(batch_size, num_classes)
  313. optimizer = Momentum(learning_rate=0.01, momentum=0.9,
  314. params=filter(lambda x: x.requires_grad, net.get_parameters()))
  315. data_set = create_dataset(repeat_num=1, training=True, batch_size=batch_size, num_samples=total_step * batch_size)
  316. # define callbacks
  317. time_cb = MyTimeMonitor(data_size=data_set.get_dataset_size())
  318. loss_cb = LossMonitor()
  319. cb = [time_cb, loss_cb]
  320. loss = SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
  321. loss_scale = FixedLossScaleManager(loss_scale=loss_scale, drop_overflow_update=False)
  322. model = Model(net, loss_fn=loss, optimizer=optimizer, loss_scale_manager=loss_scale, metrics={'acc'},
  323. amp_level="O2", keep_batchnorm_fp32=False)
  324. # train model
  325. model.train(1, data_set, callbacks=cb,
  326. sink_size=data_set.get_dataset_size(), dataset_sink_mode=True)
  327. assert time_cb.good_step() > 10