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 14 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. # -*- coding: utf-8 -*-
  2. # MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  3. #
  4. # Copyright (c) 2014-2020 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 multiprocessing as mp
  10. import numpy as np
  11. import pytest
  12. import megengine as mge
  13. import megengine.distributed as dist
  14. from megengine.core import tensor
  15. from megengine.module import BatchNorm1d, BatchNorm2d, SyncBatchNorm
  16. from megengine.test import assertTensorClose
  17. @pytest.mark.isolated_distributed
  18. def test_syncbn():
  19. nr_chan = 8
  20. data_shape = (3, nr_chan, 4, 16)
  21. momentum = 0.9
  22. eps = 1e-5
  23. running_mean = np.zeros((1, nr_chan, 1, 1), dtype=np.float32)
  24. running_var = np.ones((1, nr_chan, 1, 1), dtype=np.float32)
  25. steps = 4
  26. def worker(rank, data, yv_expect, running_mean, running_var):
  27. if not mge.is_cuda_available():
  28. return
  29. dist.init_process_group("localhost", 2333, 4, rank, rank)
  30. bn = SyncBatchNorm(nr_chan, momentum=momentum, eps=eps)
  31. data_tensor = tensor()
  32. for i in range(steps):
  33. data_tensor.set_value(data[i])
  34. yv = bn(data_tensor)
  35. assertTensorClose(yv_expect, yv.numpy(), max_err=5e-6)
  36. assertTensorClose(running_mean, bn.running_mean.numpy(), max_err=5e-6)
  37. assertTensorClose(running_var, bn.running_var.numpy(), max_err=5e-6)
  38. xv = []
  39. for i in range(steps):
  40. xv.append(np.random.normal(loc=2.3, size=data_shape).astype(np.float32))
  41. xv_transposed = np.transpose(xv[i], [0, 2, 3, 1]).reshape(
  42. (data_shape[0] * data_shape[2] * data_shape[3], nr_chan)
  43. )
  44. mean = np.mean(xv_transposed, axis=0).reshape(1, nr_chan, 1, 1)
  45. var_biased = np.var(xv_transposed, axis=0).reshape((1, nr_chan, 1, 1))
  46. sd = np.sqrt(var_biased + eps)
  47. var_unbiased = np.var(xv_transposed, axis=0, ddof=1).reshape((1, nr_chan, 1, 1))
  48. running_mean = running_mean * momentum + mean * (1 - momentum)
  49. running_var = running_var * momentum + var_unbiased * (1 - momentum)
  50. yv_expect = (xv[i] - mean) / sd
  51. data = []
  52. for i in range(4):
  53. data.append([])
  54. for j in range(steps):
  55. data[i].append(xv[j][:, :, :, i * 4 : i * 4 + 4])
  56. procs = []
  57. for rank in range(4):
  58. p = mp.Process(
  59. target=worker,
  60. args=(
  61. rank,
  62. data[rank],
  63. yv_expect[:, :, :, rank * 4 : rank * 4 + 4],
  64. running_mean,
  65. running_var,
  66. ),
  67. )
  68. p.start()
  69. procs.append(p)
  70. for p in procs:
  71. p.join()
  72. assert p.exitcode == 0
  73. def test_batchnorm():
  74. nr_chan = 8
  75. data_shape = (3, nr_chan, 4)
  76. momentum = 0.9
  77. bn = BatchNorm1d(nr_chan, momentum=momentum)
  78. running_mean = np.zeros((1, nr_chan, 1), dtype=np.float32)
  79. running_var = np.ones((1, nr_chan, 1), dtype=np.float32)
  80. data = tensor()
  81. for i in range(3):
  82. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  83. mean = np.mean(np.mean(xv, axis=0, keepdims=True), axis=2, keepdims=True)
  84. xv_transposed = np.transpose(xv, [0, 2, 1]).reshape(
  85. (data_shape[0] * data_shape[2], nr_chan)
  86. )
  87. var_biased = np.var(xv_transposed, axis=0).reshape((1, nr_chan, 1))
  88. sd = np.sqrt(var_biased + bn.eps)
  89. var_unbiased = np.var(xv_transposed, axis=0, ddof=1).reshape((1, nr_chan, 1))
  90. running_mean = running_mean * momentum + mean * (1 - momentum)
  91. running_var = running_var * momentum + var_unbiased * (1 - momentum)
  92. data.set_value(xv)
  93. yv = bn(data)
  94. yv_expect = (xv - mean) / sd
  95. assertTensorClose(yv_expect, yv.numpy(), max_err=5e-6)
  96. assertTensorClose(
  97. running_mean.reshape(-1), bn.running_mean.numpy().reshape(-1), max_err=5e-6
  98. )
  99. assertTensorClose(
  100. running_var.reshape(-1), bn.running_var.numpy().reshape(-1), max_err=5e-6
  101. )
  102. # test set 'training' flag to False
  103. mean_backup = bn.running_mean.numpy()
  104. var_backup = bn.running_var.numpy()
  105. bn.training = False
  106. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  107. data.set_value(xv)
  108. yv1 = bn(data)
  109. yv2 = bn(data)
  110. assertTensorClose(yv1.numpy(), yv2.numpy(), max_err=0)
  111. assertTensorClose(mean_backup, bn.running_mean.numpy(), max_err=0)
  112. assertTensorClose(var_backup, bn.running_var.numpy(), max_err=0)
  113. yv_expect = (xv - running_mean) / np.sqrt(running_var + bn.eps)
  114. assertTensorClose(yv_expect, yv1.numpy(), max_err=5e-6)
  115. def test_syncbn1d():
  116. nr_chan = 8
  117. data_shape = (3, nr_chan, 4)
  118. momentum = 0.9
  119. bn = SyncBatchNorm(nr_chan, momentum=momentum)
  120. running_mean = np.zeros((1, nr_chan, 1), dtype=np.float32)
  121. running_var = np.ones((1, nr_chan, 1), dtype=np.float32)
  122. data = tensor()
  123. for i in range(3):
  124. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  125. mean = np.mean(np.mean(xv, axis=0, keepdims=True), axis=2, keepdims=True)
  126. xv_transposed = np.transpose(xv, [0, 2, 1]).reshape(
  127. (data_shape[0] * data_shape[2], nr_chan)
  128. )
  129. var_biased = np.var(xv_transposed, axis=0).reshape((1, nr_chan, 1))
  130. sd = np.sqrt(var_biased + bn.eps)
  131. var_unbiased = np.var(xv_transposed, axis=0, ddof=1).reshape((1, nr_chan, 1))
  132. running_mean = running_mean * momentum + mean * (1 - momentum)
  133. running_var = running_var * momentum + var_unbiased * (1 - momentum)
  134. data.set_value(xv)
  135. yv = bn(data)
  136. yv_expect = (xv - mean) / sd
  137. assertTensorClose(yv_expect, yv.numpy(), max_err=5e-6)
  138. assertTensorClose(
  139. running_mean.reshape(-1), bn.running_mean.numpy().reshape(-1), max_err=5e-6
  140. )
  141. assertTensorClose(
  142. running_var.reshape(-1), bn.running_var.numpy().reshape(-1), max_err=5e-6
  143. )
  144. # test set 'training' flag to False
  145. mean_backup = bn.running_mean.numpy()
  146. var_backup = bn.running_var.numpy()
  147. bn.training = False
  148. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  149. data.set_value(xv)
  150. yv1 = bn(data)
  151. yv2 = bn(data)
  152. assertTensorClose(yv1.numpy(), yv2.numpy(), max_err=0)
  153. assertTensorClose(mean_backup, bn.running_mean.numpy(), max_err=0)
  154. assertTensorClose(var_backup, bn.running_var.numpy(), max_err=0)
  155. yv_expect = (xv - running_mean) / np.sqrt(running_var + bn.eps)
  156. assertTensorClose(yv_expect, yv1.numpy(), max_err=5e-6)
  157. def test_batchnorm2d():
  158. nr_chan = 8
  159. data_shape = (3, nr_chan, 16, 16)
  160. momentum = 0.9
  161. bn = BatchNorm2d(nr_chan, momentum=momentum)
  162. running_mean = np.zeros((1, nr_chan, 1, 1), dtype=np.float32)
  163. running_var = np.ones((1, nr_chan, 1, 1), dtype=np.float32)
  164. data = tensor()
  165. for i in range(3):
  166. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  167. xv_transposed = np.transpose(xv, [0, 2, 3, 1]).reshape(
  168. (data_shape[0] * data_shape[2] * data_shape[3], nr_chan)
  169. )
  170. mean = np.mean(xv_transposed, axis=0).reshape(1, nr_chan, 1, 1)
  171. var_biased = np.var(xv_transposed, axis=0).reshape((1, nr_chan, 1, 1))
  172. sd = np.sqrt(var_biased + bn.eps)
  173. var_unbiased = np.var(xv_transposed, axis=0, ddof=1).reshape((1, nr_chan, 1, 1))
  174. running_mean = running_mean * momentum + mean * (1 - momentum)
  175. running_var = running_var * momentum + var_unbiased * (1 - momentum)
  176. data.set_value(xv)
  177. yv = bn(data)
  178. yv_expect = (xv - mean) / sd
  179. assertTensorClose(yv_expect, yv.numpy(), max_err=5e-6)
  180. assertTensorClose(running_mean, bn.running_mean.numpy(), max_err=5e-6)
  181. assertTensorClose(running_var, bn.running_var.numpy(), max_err=5e-6)
  182. # test set 'training' flag to False
  183. mean_backup = bn.running_mean.numpy()
  184. var_backup = bn.running_var.numpy()
  185. bn.training = False
  186. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  187. data.set_value(xv)
  188. yv1 = bn(data)
  189. yv2 = bn(data)
  190. assertTensorClose(yv1.numpy(), yv2.numpy(), max_err=0)
  191. assertTensorClose(mean_backup, bn.running_mean.numpy(), max_err=0)
  192. assertTensorClose(var_backup, bn.running_var.numpy(), max_err=0)
  193. yv_expect = (xv - running_mean) / np.sqrt(running_var + bn.eps)
  194. assertTensorClose(yv_expect, yv1.numpy(), max_err=5e-6)
  195. def test_syncbn2d():
  196. nr_chan = 8
  197. data_shape = (3, nr_chan, 16, 16)
  198. momentum = 0.9
  199. bn = SyncBatchNorm(nr_chan, momentum=momentum)
  200. running_mean = np.zeros((1, nr_chan, 1, 1), dtype=np.float32)
  201. running_var = np.ones((1, nr_chan, 1, 1), dtype=np.float32)
  202. data = tensor()
  203. for i in range(3):
  204. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  205. xv_transposed = np.transpose(xv, [0, 2, 3, 1]).reshape(
  206. (data_shape[0] * data_shape[2] * data_shape[3], nr_chan)
  207. )
  208. mean = np.mean(xv_transposed, axis=0).reshape(1, nr_chan, 1, 1)
  209. var_biased = np.var(xv_transposed, axis=0).reshape((1, nr_chan, 1, 1))
  210. sd = np.sqrt(var_biased + bn.eps)
  211. var_unbiased = np.var(xv_transposed, axis=0, ddof=1).reshape((1, nr_chan, 1, 1))
  212. running_mean = running_mean * momentum + mean * (1 - momentum)
  213. running_var = running_var * momentum + var_unbiased * (1 - momentum)
  214. data.set_value(xv)
  215. yv = bn(data)
  216. yv_expect = (xv - mean) / sd
  217. assertTensorClose(yv_expect, yv.numpy(), max_err=5e-6)
  218. assertTensorClose(running_mean, bn.running_mean.numpy(), max_err=5e-6)
  219. assertTensorClose(running_var, bn.running_var.numpy(), max_err=5e-6)
  220. # test set 'training' flag to False
  221. mean_backup = bn.running_mean.numpy()
  222. var_backup = bn.running_var.numpy()
  223. bn.training = False
  224. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  225. data.set_value(xv)
  226. yv1 = bn(data)
  227. yv2 = bn(data)
  228. assertTensorClose(yv1.numpy(), yv2.numpy(), max_err=0)
  229. assertTensorClose(mean_backup, bn.running_mean.numpy(), max_err=0)
  230. assertTensorClose(var_backup, bn.running_var.numpy(), max_err=0)
  231. yv_expect = (xv - running_mean) / np.sqrt(running_var + bn.eps)
  232. assertTensorClose(yv_expect, yv1.numpy(), max_err=5e-6)
  233. def test_batchnorm_no_stats():
  234. nr_chan = 8
  235. data_shape = (3, nr_chan, 4)
  236. bn = BatchNorm1d(8, track_running_stats=False)
  237. data = tensor()
  238. for i in range(4):
  239. if i == 2:
  240. bn.training = False
  241. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  242. mean = np.mean(np.mean(xv, axis=0, keepdims=True), axis=2, keepdims=True)
  243. var = np.var(
  244. np.transpose(xv, [0, 2, 1]).reshape(
  245. (data_shape[0] * data_shape[2], nr_chan)
  246. ),
  247. axis=0,
  248. ).reshape((1, nr_chan, 1))
  249. sd = np.sqrt(var + bn.eps)
  250. data.set_value(xv)
  251. yv = bn(data)
  252. yv_expect = (xv - mean) / sd
  253. assertTensorClose(yv_expect, yv.numpy(), max_err=5e-6)
  254. def test_syncbn_no_stats():
  255. nr_chan = 8
  256. data_shape = (3, nr_chan, 4)
  257. bn = SyncBatchNorm(8, track_running_stats=False)
  258. data = tensor()
  259. for i in range(4):
  260. if i == 2:
  261. bn.training = False
  262. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  263. mean = np.mean(np.mean(xv, axis=0, keepdims=True), axis=2, keepdims=True)
  264. var = np.var(
  265. np.transpose(xv, [0, 2, 1]).reshape(
  266. (data_shape[0] * data_shape[2], nr_chan)
  267. ),
  268. axis=0,
  269. ).reshape((1, nr_chan, 1))
  270. sd = np.sqrt(var + bn.eps)
  271. data.set_value(xv)
  272. yv = bn(data)
  273. yv_expect = (xv - mean) / sd
  274. assertTensorClose(yv_expect, yv.numpy(), max_err=5e-6)
  275. def test_batchnorm2d_no_stats():
  276. nr_chan = 8
  277. data_shape = (3, nr_chan, 16, 16)
  278. bn = BatchNorm2d(8, track_running_stats=False)
  279. data = tensor()
  280. for i in range(4):
  281. if i == 2:
  282. bn.training = False
  283. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  284. xv_transposed = np.transpose(xv, [0, 2, 3, 1]).reshape(
  285. (data_shape[0] * data_shape[2] * data_shape[3], nr_chan)
  286. )
  287. mean = np.mean(xv_transposed, axis=0).reshape(1, nr_chan, 1, 1)
  288. var = np.var(xv_transposed, axis=0).reshape((1, nr_chan, 1, 1))
  289. sd = np.sqrt(var + bn.eps)
  290. data.set_value(xv)
  291. yv = bn(data)
  292. yv_expect = (xv - mean) / sd
  293. assertTensorClose(yv_expect, yv.numpy(), max_err=5e-6)
  294. def test_syncbn2d_no_stats():
  295. nr_chan = 8
  296. data_shape = (3, nr_chan, 16, 16)
  297. bn = SyncBatchNorm(8, track_running_stats=False)
  298. data = tensor()
  299. for i in range(4):
  300. if i == 2:
  301. bn.training = False
  302. xv = np.random.normal(loc=2.3, size=data_shape).astype(np.float32)
  303. xv_transposed = np.transpose(xv, [0, 2, 3, 1]).reshape(
  304. (data_shape[0] * data_shape[2] * data_shape[3], nr_chan)
  305. )
  306. mean = np.mean(xv_transposed, axis=0).reshape(1, nr_chan, 1, 1)
  307. var = np.var(xv_transposed, axis=0).reshape((1, nr_chan, 1, 1))
  308. sd = np.sqrt(var + bn.eps)
  309. data.set_value(xv)
  310. yv = bn(data)
  311. yv_expect = (xv - mean) / sd
  312. assertTensorClose(yv_expect, yv.numpy(), max_err=5e-6)

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