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_batchnorm.py 13 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. # -*- coding: utf-8 -*-
  2. # MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  3. #
  4. # Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
  5. #
  6. # Unless required by applicable law or agreed to in writing,
  7. # software distributed under the License is distributed on an
  8. # "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. import functools
  10. import platform
  11. import numpy as np
  12. import pytest
  13. import megengine as mge
  14. import megengine.distributed as dist
  15. from megengine import Tensor
  16. from megengine.core._trace_option import use_symbolic_shape
  17. from megengine.module import BatchNorm1d, BatchNorm2d, SyncBatchNorm
  18. _assert_allclose = functools.partial(np.testing.assert_allclose, atol=5e-6, rtol=5e-6)
  19. @pytest.mark.require_ngpu(2)
  20. @pytest.mark.isolated_distributed
  21. def test_syncbn():
  22. nr_chan = 8
  23. data_shape = (3, nr_chan, 4, 16)
  24. momentum = 0.9
  25. eps = 1e-5
  26. running_mean = np.zeros((1, nr_chan, 1, 1), dtype=np.float32)
  27. running_var = np.ones((1, nr_chan, 1, 1), dtype=np.float32)
  28. steps = 4
  29. nr_ranks = 2
  30. server = dist.Server()
  31. port = server.py_server_port
  32. @dist.launcher(n_gpus=2)
  33. def worker(data, yv_expect, running_mean, running_var):
  34. rank = dist.get_rank()
  35. bn = SyncBatchNorm(nr_chan, momentum=momentum, eps=eps)
  36. for i in range(steps):
  37. yv = bn(Tensor(data[rank][i]))
  38. _assert_allclose(yv.numpy(), yv_expect[rank])
  39. _assert_allclose(bn.running_mean.numpy(), running_mean)
  40. _assert_allclose(bn.running_var.numpy(), running_var)
  41. xv = []
  42. for i in range(steps):
  43. xv.append(np.random.normal(loc=2.3, size=data_shape).astype(np.float32))
  44. xv_transposed = np.transpose(xv[i], [0, 2, 3, 1]).reshape(
  45. (data_shape[0] * data_shape[2] * data_shape[3], nr_chan)
  46. )
  47. mean = np.mean(xv_transposed, axis=0).reshape(1, nr_chan, 1, 1)
  48. var_biased = np.var(xv_transposed, axis=0).reshape((1, nr_chan, 1, 1))
  49. sd = np.sqrt(var_biased + eps)
  50. var_unbiased = np.var(xv_transposed, axis=0, ddof=1).reshape((1, nr_chan, 1, 1))
  51. running_mean = running_mean * momentum + mean * (1 - momentum)
  52. running_var = running_var * momentum + var_unbiased * (1 - momentum)
  53. yv_expect = (xv[i] - mean) / sd
  54. data = []
  55. for i in range(nr_ranks):
  56. data.append([])
  57. for j in range(steps):
  58. data[i].append(xv[j][:, :, :, i * 8 : i * 8 + 8])
  59. yv_expect = [yv_expect[:, :, :, i * 8 : i * 8 + 8] for i in range(nr_ranks)]
  60. worker(data, yv_expect, running_mean, running_var)
  61. def test_batchnorm():
  62. nr_chan = 8
  63. data_shape = (3, nr_chan, 4)
  64. momentum = 0.9
  65. bn = BatchNorm1d(nr_chan, momentum=momentum)
  66. running_mean = np.zeros((1, nr_chan, 1), dtype=np.float32)
  67. running_var = np.ones((1, nr_chan, 1), dtype=np.float32)
  68. for i in range(3):
  69. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  70. mean = np.mean(np.mean(xv, axis=0, keepdims=True), axis=2, keepdims=True)
  71. xv_transposed = np.transpose(xv, [0, 2, 1]).reshape(
  72. (data_shape[0] * data_shape[2], nr_chan)
  73. )
  74. var_biased = np.var(xv_transposed, axis=0).reshape((1, nr_chan, 1))
  75. sd = np.sqrt(var_biased + bn.eps)
  76. var_unbiased = np.var(xv_transposed, axis=0, ddof=1).reshape((1, nr_chan, 1))
  77. running_mean = running_mean * momentum + mean * (1 - momentum)
  78. running_var = running_var * momentum + var_unbiased * (1 - momentum)
  79. yv = bn(Tensor(xv))
  80. yv_expect = (xv - mean) / sd
  81. _assert_allclose(yv.numpy(), yv_expect)
  82. _assert_allclose(bn.running_mean.numpy().reshape(-1), running_mean.reshape(-1))
  83. _assert_allclose(bn.running_var.numpy().reshape(-1), running_var.reshape(-1))
  84. # test set 'training' flag to False
  85. mean_backup = bn.running_mean.numpy()
  86. var_backup = bn.running_var.numpy()
  87. bn.training = False
  88. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  89. data = Tensor(xv)
  90. yv1 = bn(data)
  91. yv2 = bn(data)
  92. np.testing.assert_equal(yv1.numpy(), yv2.numpy())
  93. np.testing.assert_equal(mean_backup, bn.running_mean.numpy())
  94. np.testing.assert_equal(var_backup, bn.running_var.numpy())
  95. yv_expect = (xv - running_mean) / np.sqrt(running_var + bn.eps)
  96. _assert_allclose(yv1.numpy(), yv_expect)
  97. def test_syncbn1d():
  98. nr_chan = 8
  99. data_shape = (3, nr_chan, 4)
  100. momentum = 0.9
  101. bn = SyncBatchNorm(nr_chan, momentum=momentum)
  102. running_mean = np.zeros((1, nr_chan, 1), dtype=np.float32)
  103. running_var = np.ones((1, nr_chan, 1), dtype=np.float32)
  104. for i in range(3):
  105. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  106. mean = np.mean(np.mean(xv, axis=0, keepdims=True), axis=2, keepdims=True)
  107. xv_transposed = np.transpose(xv, [0, 2, 1]).reshape(
  108. (data_shape[0] * data_shape[2], nr_chan)
  109. )
  110. var_biased = np.var(xv_transposed, axis=0).reshape((1, nr_chan, 1))
  111. sd = np.sqrt(var_biased + bn.eps)
  112. var_unbiased = np.var(xv_transposed, axis=0, ddof=1).reshape((1, nr_chan, 1))
  113. running_mean = running_mean * momentum + mean * (1 - momentum)
  114. running_var = running_var * momentum + var_unbiased * (1 - momentum)
  115. yv = bn(Tensor(xv))
  116. yv_expect = (xv - mean) / sd
  117. _assert_allclose(yv.numpy(), yv_expect)
  118. _assert_allclose(bn.running_mean.numpy().reshape(-1), running_mean.reshape(-1))
  119. _assert_allclose(bn.running_var.numpy().reshape(-1), running_var.reshape(-1))
  120. # test set 'training' flag to False
  121. mean_backup = bn.running_mean.numpy()
  122. var_backup = bn.running_var.numpy()
  123. bn.training = False
  124. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  125. data = Tensor(xv)
  126. yv1 = bn(data)
  127. yv2 = bn(data)
  128. np.testing.assert_equal(yv1.numpy(), yv2.numpy())
  129. np.testing.assert_equal(mean_backup, bn.running_mean.numpy())
  130. np.testing.assert_equal(var_backup, bn.running_var.numpy())
  131. yv_expect = (xv - running_mean) / np.sqrt(running_var + bn.eps)
  132. _assert_allclose(yv1.numpy(), yv_expect)
  133. def test_batchnorm2d():
  134. nr_chan = 8
  135. data_shape = (3, nr_chan, 16, 16)
  136. momentum = 0.9
  137. bn = BatchNorm2d(nr_chan, momentum=momentum)
  138. running_mean = np.zeros((1, nr_chan, 1, 1), dtype=np.float32)
  139. running_var = np.ones((1, nr_chan, 1, 1), dtype=np.float32)
  140. for i in range(3):
  141. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  142. xv_transposed = np.transpose(xv, [0, 2, 3, 1]).reshape(
  143. (data_shape[0] * data_shape[2] * data_shape[3], nr_chan)
  144. )
  145. mean = np.mean(xv_transposed, axis=0).reshape(1, nr_chan, 1, 1)
  146. var_biased = np.var(xv_transposed, axis=0).reshape((1, nr_chan, 1, 1))
  147. sd = np.sqrt(var_biased + bn.eps)
  148. var_unbiased = np.var(xv_transposed, axis=0, ddof=1).reshape((1, nr_chan, 1, 1))
  149. running_mean = running_mean * momentum + mean * (1 - momentum)
  150. running_var = running_var * momentum + var_unbiased * (1 - momentum)
  151. yv = bn(Tensor(xv))
  152. yv_expect = (xv - mean) / sd
  153. _assert_allclose(yv.numpy(), yv_expect)
  154. _assert_allclose(bn.running_mean.numpy(), running_mean)
  155. _assert_allclose(bn.running_var.numpy(), running_var)
  156. # test set 'training' flag to False
  157. mean_backup = bn.running_mean.numpy()
  158. var_backup = bn.running_var.numpy()
  159. bn.training = False
  160. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  161. data = Tensor(xv)
  162. yv1 = bn(data)
  163. yv2 = bn(data)
  164. np.testing.assert_equal(yv1.numpy(), yv2.numpy())
  165. np.testing.assert_equal(mean_backup, bn.running_mean.numpy())
  166. np.testing.assert_equal(var_backup, bn.running_var.numpy())
  167. yv_expect = (xv - running_mean) / np.sqrt(running_var + bn.eps)
  168. _assert_allclose(yv1.numpy(), yv_expect)
  169. def test_syncbn2d():
  170. nr_chan = 8
  171. data_shape = (3, nr_chan, 16, 16)
  172. momentum = 0.9
  173. bn = SyncBatchNorm(nr_chan, momentum=momentum)
  174. running_mean = np.zeros((1, nr_chan, 1, 1), dtype=np.float32)
  175. running_var = np.ones((1, nr_chan, 1, 1), dtype=np.float32)
  176. for i in range(3):
  177. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  178. xv_transposed = np.transpose(xv, [0, 2, 3, 1]).reshape(
  179. (data_shape[0] * data_shape[2] * data_shape[3], nr_chan)
  180. )
  181. mean = np.mean(xv_transposed, axis=0).reshape(1, nr_chan, 1, 1)
  182. var_biased = np.var(xv_transposed, axis=0).reshape((1, nr_chan, 1, 1))
  183. sd = np.sqrt(var_biased + bn.eps)
  184. var_unbiased = np.var(xv_transposed, axis=0, ddof=1).reshape((1, nr_chan, 1, 1))
  185. running_mean = running_mean * momentum + mean * (1 - momentum)
  186. running_var = running_var * momentum + var_unbiased * (1 - momentum)
  187. yv = bn(Tensor(xv))
  188. yv_expect = (xv - mean) / sd
  189. _assert_allclose(yv.numpy(), yv_expect)
  190. _assert_allclose(bn.running_mean.numpy(), running_mean)
  191. _assert_allclose(bn.running_var.numpy(), running_var)
  192. # test set 'training' flag to False
  193. mean_backup = bn.running_mean.numpy()
  194. var_backup = bn.running_var.numpy()
  195. bn.training = False
  196. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  197. data = Tensor(xv)
  198. yv1 = bn(data)
  199. yv2 = bn(data)
  200. np.testing.assert_equal(yv1.numpy(), yv2.numpy())
  201. np.testing.assert_equal(mean_backup, bn.running_mean.numpy())
  202. np.testing.assert_equal(var_backup, bn.running_var.numpy())
  203. yv_expect = (xv - running_mean) / np.sqrt(running_var + bn.eps)
  204. _assert_allclose(yv1.numpy(), yv_expect)
  205. def test_batchnorm_no_stats():
  206. nr_chan = 8
  207. data_shape = (3, nr_chan, 4)
  208. bn = BatchNorm1d(8, track_running_stats=False)
  209. for i in range(4):
  210. if i == 2:
  211. bn.training = False
  212. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  213. mean = np.mean(np.mean(xv, axis=0, keepdims=True), axis=2, keepdims=True)
  214. var = np.var(
  215. np.transpose(xv, [0, 2, 1]).reshape(
  216. (data_shape[0] * data_shape[2], nr_chan)
  217. ),
  218. axis=0,
  219. ).reshape((1, nr_chan, 1))
  220. sd = np.sqrt(var + bn.eps)
  221. yv = bn(Tensor(xv))
  222. yv_expect = (xv - mean) / sd
  223. _assert_allclose(yv.numpy(), yv_expect)
  224. def test_syncbn_no_stats():
  225. nr_chan = 8
  226. data_shape = (3, nr_chan, 4)
  227. bn = SyncBatchNorm(8, track_running_stats=False)
  228. for i in range(4):
  229. if i == 2:
  230. bn.training = False
  231. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  232. mean = np.mean(np.mean(xv, axis=0, keepdims=True), axis=2, keepdims=True)
  233. var = np.var(
  234. np.transpose(xv, [0, 2, 1]).reshape(
  235. (data_shape[0] * data_shape[2], nr_chan)
  236. ),
  237. axis=0,
  238. ).reshape((1, nr_chan, 1))
  239. sd = np.sqrt(var + bn.eps)
  240. yv = bn(Tensor(xv))
  241. yv_expect = (xv - mean) / sd
  242. _assert_allclose(yv.numpy(), yv_expect)
  243. def test_batchnorm2d_no_stats():
  244. nr_chan = 8
  245. data_shape = (3, nr_chan, 16, 16)
  246. bn = BatchNorm2d(8, track_running_stats=False)
  247. for i in range(4):
  248. if i == 2:
  249. bn.training = False
  250. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  251. xv_transposed = np.transpose(xv, [0, 2, 3, 1]).reshape(
  252. (data_shape[0] * data_shape[2] * data_shape[3], nr_chan)
  253. )
  254. mean = np.mean(xv_transposed, axis=0).reshape(1, nr_chan, 1, 1)
  255. var = np.var(xv_transposed, axis=0).reshape((1, nr_chan, 1, 1))
  256. sd = np.sqrt(var + bn.eps)
  257. yv = bn(Tensor(xv))
  258. yv_expect = (xv - mean) / sd
  259. _assert_allclose(yv.numpy(), yv_expect)
  260. def test_syncbn2d_no_stats():
  261. nr_chan = 8
  262. data_shape = (3, nr_chan, 16, 16)
  263. bn = SyncBatchNorm(8, track_running_stats=False)
  264. for i in range(4):
  265. if i == 2:
  266. bn.training = False
  267. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  268. xv_transposed = np.transpose(xv, [0, 2, 3, 1]).reshape(
  269. (data_shape[0] * data_shape[2] * data_shape[3], nr_chan)
  270. )
  271. mean = np.mean(xv_transposed, axis=0).reshape(1, nr_chan, 1, 1)
  272. var = np.var(xv_transposed, axis=0).reshape((1, nr_chan, 1, 1))
  273. sd = np.sqrt(var + bn.eps)
  274. yv = bn(Tensor(xv))
  275. yv_expect = (xv - mean) / sd
  276. _assert_allclose(yv.numpy(), yv_expect)

MegEngine 安装包中集成了使用 GPU 运行代码所需的 CUDA 环境,不用区分 CPU 和 GPU 版。 如果想要运行 GPU 程序,请确保机器本身配有 GPU 硬件设备并安装好驱动。 如果你想体验在云端 GPU 算力平台进行深度学习开发的感觉,欢迎访问 MegStudio 平台