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.

08-batch-normalization.ipynb 22 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. {
  2. "cells": [
  3. {
  4. "cell_type": "markdown",
  5. "metadata": {},
  6. "source": [
  7. "# 批标准化\n",
  8. "在正式进入模型的构建和训练之前,先讲一下数据预处理和批标准化。因为模型训练并不容易,特别是一些非常复杂的模型,并不能非常好的训练得到收敛的结果,所以对数据增加一些预处理,同时使用批标准化能够得到非常好的收敛结果,这也是卷积网络能够训练到非常深的层的一个重要原因。"
  9. ]
  10. },
  11. {
  12. "cell_type": "markdown",
  13. "metadata": {},
  14. "source": [
  15. "## 1. 数据预处理\n",
  16. "目前数据预处理最常见的方法就是 `中心化` 和 `标准化`\n",
  17. "* **中心化** 相当于修正数据的中心位置,实现方法非常简单,就是在每个特征维度上减去对应的均值,最后得到 0 均值的特征。\n",
  18. "* **标准化** 也非常简单,在数据变成 0 均值之后,为了使得不同的特征维度有着相同的规模,可以除以标准差近似为一个标准正态分布,也可以依据最大值和最小值将其转化为 -1 ~ 1 之间\n",
  19. "\n",
  20. "下图是处理的的示例:\n",
  21. "\n",
  22. "![](images/data_normalize.png)\n",
  23. "\n"
  24. ]
  25. },
  26. {
  27. "cell_type": "markdown",
  28. "metadata": {},
  29. "source": [
  30. "## 2. Batch Normalization\n",
  31. "前面在数据预处理的时候,我们尽量输入特征不相关且满足一个标准的正态分布,这样模型的表现一般也较好。但是对于很深的网络结构,网络的非线性层会使得输出的结果变得相关,且不再满足一个标准的 ${N}(0, 1)$ 的分布,甚至输出的中心已经发生了偏移,这对于模型的训练,特别是深层的模型训练非常的困难。\n",
  32. "\n",
  33. "所以在 2015 年一篇论文提出了这个方法,批标准化(batch normalization),简而言之,就是对于每一层网络的输出,对其做一个归一化,使其服从标准的正态分布,这样后一层网络的输入也是一个标准的正态分布,所以能够比较好的进行训练,加快收敛速度。"
  34. ]
  35. },
  36. {
  37. "cell_type": "markdown",
  38. "metadata": {},
  39. "source": [
  40. "批标准化的实现非常简单,对于给定的一个 batch 的数据 $B = \\{x_1, x_2, \\cdots, x_m\\}$算法的公式如下\n",
  41. "\n",
  42. "$$\n",
  43. "\\mu_B = \\frac{1}{m} \\sum_{i=1}^m x_i\n",
  44. "$$\n",
  45. "$$\n",
  46. "\\sigma^2_B = \\frac{1}{m} \\sum_{i=1}^m (x_i - \\mu_B)^2\n",
  47. "$$\n",
  48. "$$\n",
  49. "\\hat{x}_i = \\frac{x_i - \\mu_B}{\\sqrt{\\sigma^2_B + \\epsilon}}\n",
  50. "$$\n",
  51. "$$\n",
  52. "y_i = \\gamma \\hat{x}_i + \\beta\n",
  53. "$$"
  54. ]
  55. },
  56. {
  57. "cell_type": "markdown",
  58. "metadata": {},
  59. "source": [
  60. "* 第一和第二个公式计算出一个 batch 中数据的均值和方差\n",
  61. "* 第三个公式对 batch 中的每个数据点做标准化,$\\epsilon$ 是为了计算稳定引入的一个小的常数,通常取 $10^{-5}$\n",
  62. "* 最后利用权重修正得到最后的输出结果,其中 $\\gamma$ $\\beta$是权值变换参数,也是网络参数在训练过程一起学习\n",
  63. "\n",
  64. "下面演示一维的情况,也就是神经网络中的情况"
  65. ]
  66. },
  67. {
  68. "cell_type": "code",
  69. "execution_count": 1,
  70. "metadata": {
  71. "ExecuteTime": {
  72. "end_time": "2017-12-23T06:50:51.579067Z",
  73. "start_time": "2017-12-23T06:50:51.575693Z"
  74. },
  75. "collapsed": true
  76. },
  77. "outputs": [],
  78. "source": [
  79. "import sys\n",
  80. "sys.path.append('..')\n",
  81. "\n",
  82. "import torch"
  83. ]
  84. },
  85. {
  86. "cell_type": "code",
  87. "execution_count": 2,
  88. "metadata": {
  89. "ExecuteTime": {
  90. "end_time": "2017-12-23T07:14:11.077807Z",
  91. "start_time": "2017-12-23T07:14:11.060849Z"
  92. },
  93. "collapsed": true
  94. },
  95. "outputs": [],
  96. "source": [
  97. "def simple_batch_norm_1d(x, gamma, beta):\n",
  98. " eps = 1e-5\n",
  99. " x_mean = torch.mean(x, dim=0, keepdim=True) # 保留维度进行 broadcast\n",
  100. " x_var = torch.mean((x - x_mean) ** 2, dim=0, keepdim=True)\n",
  101. " x_hat = (x - x_mean) / torch.sqrt(x_var + eps)\n",
  102. " return gamma.view_as(x_mean) * x_hat + beta.view_as(x_mean)"
  103. ]
  104. },
  105. {
  106. "cell_type": "markdown",
  107. "metadata": {},
  108. "source": [
  109. "我们来验证一下是否对于任意的输入,输出会被标准化"
  110. ]
  111. },
  112. {
  113. "cell_type": "code",
  114. "execution_count": 3,
  115. "metadata": {
  116. "ExecuteTime": {
  117. "end_time": "2017-12-23T07:14:20.610603Z",
  118. "start_time": "2017-12-23T07:14:20.597682Z"
  119. }
  120. },
  121. "outputs": [
  122. {
  123. "name": "stdout",
  124. "output_type": "stream",
  125. "text": [
  126. "before bn: \n",
  127. "\n",
  128. " 0 1 2\n",
  129. " 3 4 5\n",
  130. " 6 7 8\n",
  131. " 9 10 11\n",
  132. " 12 13 14\n",
  133. "[torch.FloatTensor of size 5x3]\n",
  134. "\n",
  135. "after bn: \n",
  136. "\n",
  137. "-1.4142 -1.4142 -1.4142\n",
  138. "-0.7071 -0.7071 -0.7071\n",
  139. " 0.0000 0.0000 0.0000\n",
  140. " 0.7071 0.7071 0.7071\n",
  141. " 1.4142 1.4142 1.4142\n",
  142. "[torch.FloatTensor of size 5x3]\n",
  143. "\n"
  144. ]
  145. }
  146. ],
  147. "source": [
  148. "x = torch.arange(15).view(5, 3)\n",
  149. "gamma = torch.ones(x.shape[1])\n",
  150. "beta = torch.zeros(x.shape[1])\n",
  151. "print('before bn: ')\n",
  152. "print(x)\n",
  153. "y = simple_batch_norm_1d(x, gamma, beta)\n",
  154. "print('after bn: ')\n",
  155. "print(y)"
  156. ]
  157. },
  158. {
  159. "cell_type": "markdown",
  160. "metadata": {},
  161. "source": [
  162. "可以看到这里一共是 5 个数据点,三个特征,每一列表示一个特征的不同数据点,使用批标准化之后,每一列都变成了标准的正态分布\n",
  163. "\n",
  164. "这个时候会出现一个问题,就是测试的时候该使用批标准化吗?\n",
  165. "\n",
  166. "答案是肯定的,因为训练的时候使用了,而测试的时候不使用肯定会导致结果出现偏差,但是测试的时候如果只有一个数据集,那么均值不就是这个值,方差为 0 吗?这显然是随机的,所以**测试的时候不能用测试的数据集去算均值和方差,而是用训练的时候算出的移动平均均值和方差去代替**\n",
  167. "\n",
  168. "下面我们实现以下能够区分训练状态和测试状态的批标准化方法"
  169. ]
  170. },
  171. {
  172. "cell_type": "code",
  173. "execution_count": 4,
  174. "metadata": {
  175. "ExecuteTime": {
  176. "end_time": "2017-12-23T07:32:48.025709Z",
  177. "start_time": "2017-12-23T07:32:48.005892Z"
  178. },
  179. "collapsed": true
  180. },
  181. "outputs": [],
  182. "source": [
  183. "def batch_norm_1d(x, gamma, beta, \n",
  184. " is_training, \n",
  185. " moving_mean, moving_var, moving_momentum=0.1):\n",
  186. " eps = 1e-5\n",
  187. " x_mean = torch.mean(x, dim=0, keepdim=True) # 保留维度进行 broadcast\n",
  188. " x_var = torch.mean((x - x_mean) ** 2, dim=0, keepdim=True)\n",
  189. " if is_training:\n",
  190. " x_hat = (x - x_mean) / torch.sqrt(x_var + eps)\n",
  191. " moving_mean[:] = moving_momentum * moving_mean + (1. - moving_momentum) * x_mean\n",
  192. " moving_var[:] = moving_momentum * moving_var + (1. - moving_momentum) * x_var\n",
  193. " else:\n",
  194. " x_hat = (x - moving_mean) / torch.sqrt(moving_var + eps)\n",
  195. " return gamma.view_as(x_mean) * x_hat + beta.view_as(x_mean)"
  196. ]
  197. },
  198. {
  199. "cell_type": "markdown",
  200. "metadata": {},
  201. "source": [
  202. "下面我们使用上一节课将的深度神经网络分类 MNIST 数据集的例子来试验一下批标准化是否有用"
  203. ]
  204. },
  205. {
  206. "cell_type": "code",
  207. "execution_count": 6,
  208. "metadata": {
  209. "collapsed": true
  210. },
  211. "outputs": [],
  212. "source": [
  213. "import numpy as np\n",
  214. "from torchvision.datasets import mnist # 导入 pytorch 内置的 mnist 数据\n",
  215. "from torch.utils.data import DataLoader\n",
  216. "from torch import nn\n",
  217. "from torch.autograd import Variable\n",
  218. "\n",
  219. "def data_tf(x):\n",
  220. " x = np.array(x, dtype='float32') / 255\n",
  221. " x = (x - 0.5) / 0.5 # 数据预处理,标准化\n",
  222. " x = x.reshape((-1,)) # 拉平\n",
  223. " x = torch.from_numpy(x)\n",
  224. " return x\n",
  225. "\n",
  226. "# 下载 MNIST 数据集,载入数据集,申明定义的数据变换\n",
  227. "train_set = mnist.MNIST('../../data/mnist', train=True, \n",
  228. " transform=data_tf, download=True) \n",
  229. "test_set = mnist.MNIST('../../data/mnist', train=False, \n",
  230. " transform=data_tf, download=True)\n",
  231. "train_data = DataLoader(train_set, batch_size=64, shuffle=True)\n",
  232. "test_data = DataLoader(test_set, batch_size=128, shuffle=False)"
  233. ]
  234. },
  235. {
  236. "cell_type": "code",
  237. "execution_count": 7,
  238. "metadata": {
  239. "collapsed": true
  240. },
  241. "outputs": [],
  242. "source": [
  243. "class multi_network(nn.Module):\n",
  244. " def __init__(self):\n",
  245. " super(multi_network, self).__init__()\n",
  246. " self.layer1 = nn.Linear(784, 100)\n",
  247. " self.relu = nn.ReLU(True)\n",
  248. " self.layer2 = nn.Linear(100, 10)\n",
  249. " \n",
  250. " self.gamma = nn.Parameter(torch.randn(100))\n",
  251. " self.beta = nn.Parameter(torch.randn(100))\n",
  252. " \n",
  253. " self.moving_mean = Variable(torch.zeros(100))\n",
  254. " self.moving_var = Variable(torch.zeros(100))\n",
  255. " \n",
  256. " def forward(self, x, is_train=True):\n",
  257. " x = self.layer1(x)\n",
  258. " x = batch_norm_1d(x, self.gamma, self.beta, \n",
  259. " is_train, self.moving_mean, self.moving_var)\n",
  260. " x = self.relu(x)\n",
  261. " x = self.layer2(x)\n",
  262. " return x"
  263. ]
  264. },
  265. {
  266. "cell_type": "code",
  267. "execution_count": 8,
  268. "metadata": {
  269. "collapsed": true
  270. },
  271. "outputs": [],
  272. "source": [
  273. "net = multi_network()"
  274. ]
  275. },
  276. {
  277. "cell_type": "code",
  278. "execution_count": 9,
  279. "metadata": {
  280. "collapsed": true
  281. },
  282. "outputs": [],
  283. "source": [
  284. "# 定义 loss 函数\n",
  285. "criterion = nn.CrossEntropyLoss()\n",
  286. "optimizer = torch.optim.SGD(net.parameters(), 1e-1) # 使用随机梯度下降,学习率 0.1"
  287. ]
  288. },
  289. {
  290. "cell_type": "markdown",
  291. "metadata": {},
  292. "source": [
  293. "为了方便,训练函数已经定义在外面的 `utils.py` 中,跟前面训练网络的操作是一样的。"
  294. ]
  295. },
  296. {
  297. "cell_type": "code",
  298. "execution_count": 10,
  299. "metadata": {},
  300. "outputs": [
  301. {
  302. "name": "stdout",
  303. "output_type": "stream",
  304. "text": [
  305. "Epoch 0. Train Loss: 0.308139, Train Acc: 0.912797, Valid Loss: 0.181375, Valid Acc: 0.948279, Time 00:00:07\n",
  306. "Epoch 1. Train Loss: 0.174049, Train Acc: 0.949910, Valid Loss: 0.143940, Valid Acc: 0.958267, Time 00:00:09\n",
  307. "Epoch 2. Train Loss: 0.134983, Train Acc: 0.961587, Valid Loss: 0.122489, Valid Acc: 0.963904, Time 00:00:08\n",
  308. "Epoch 3. Train Loss: 0.111758, Train Acc: 0.968317, Valid Loss: 0.106595, Valid Acc: 0.966278, Time 00:00:09\n",
  309. "Epoch 4. Train Loss: 0.096425, Train Acc: 0.971915, Valid Loss: 0.108423, Valid Acc: 0.967563, Time 00:00:10\n",
  310. "Epoch 5. Train Loss: 0.084424, Train Acc: 0.974464, Valid Loss: 0.107135, Valid Acc: 0.969838, Time 00:00:09\n",
  311. "Epoch 6. Train Loss: 0.076206, Train Acc: 0.977645, Valid Loss: 0.092725, Valid Acc: 0.971420, Time 00:00:09\n",
  312. "Epoch 7. Train Loss: 0.069438, Train Acc: 0.979661, Valid Loss: 0.091497, Valid Acc: 0.971519, Time 00:00:09\n",
  313. "Epoch 8. Train Loss: 0.062908, Train Acc: 0.980810, Valid Loss: 0.088797, Valid Acc: 0.972903, Time 00:00:08\n",
  314. "Epoch 9. Train Loss: 0.058186, Train Acc: 0.982309, Valid Loss: 0.090830, Valid Acc: 0.972310, Time 00:00:08\n"
  315. ]
  316. }
  317. ],
  318. "source": [
  319. "from utils import train\n",
  320. "train(net, train_data, test_data, 10, optimizer, criterion)"
  321. ]
  322. },
  323. {
  324. "cell_type": "markdown",
  325. "metadata": {},
  326. "source": [
  327. "这里的 $\\gamma$ 和 $\\beta$ 都作为参数进行训练,初始化为随机的高斯分布,`moving_mean` 和 `moving_var` 都初始化为 0,并不是更新的参数,训练完 10 次之后,我们可以看看移动平均和移动方差被修改为了多少"
  328. ]
  329. },
  330. {
  331. "cell_type": "code",
  332. "execution_count": 11,
  333. "metadata": {
  334. "scrolled": true
  335. },
  336. "outputs": [
  337. {
  338. "name": "stdout",
  339. "output_type": "stream",
  340. "text": [
  341. "Variable containing:\n",
  342. " 0.5505\n",
  343. " 2.0835\n",
  344. " 0.0794\n",
  345. "-0.1991\n",
  346. "-0.9822\n",
  347. "-0.5820\n",
  348. " 0.6991\n",
  349. "-0.1292\n",
  350. " 2.9608\n",
  351. " 1.0826\n",
  352. "[torch.FloatTensor of size 10]\n",
  353. "\n"
  354. ]
  355. }
  356. ],
  357. "source": [
  358. "# 打出 moving_mean 的前 10 项\n",
  359. "print(net.moving_mean[:10])"
  360. ]
  361. },
  362. {
  363. "cell_type": "markdown",
  364. "metadata": {},
  365. "source": [
  366. "可以看到,这些值已经在训练的过程中进行了修改,在测试过程中,我们不需要再计算均值和方差,直接使用移动平均和移动方差即可"
  367. ]
  368. },
  369. {
  370. "cell_type": "markdown",
  371. "metadata": {},
  372. "source": [
  373. "作为对比,我们看看不使用批标准化的结果"
  374. ]
  375. },
  376. {
  377. "cell_type": "code",
  378. "execution_count": 12,
  379. "metadata": {},
  380. "outputs": [
  381. {
  382. "name": "stdout",
  383. "output_type": "stream",
  384. "text": [
  385. "Epoch 0. Train Loss: 0.402263, Train Acc: 0.873817, Valid Loss: 0.220468, Valid Acc: 0.932852, Time 00:00:07\n",
  386. "Epoch 1. Train Loss: 0.181916, Train Acc: 0.945379, Valid Loss: 0.162440, Valid Acc: 0.953817, Time 00:00:08\n",
  387. "Epoch 2. Train Loss: 0.136073, Train Acc: 0.958522, Valid Loss: 0.264888, Valid Acc: 0.918216, Time 00:00:08\n",
  388. "Epoch 3. Train Loss: 0.111658, Train Acc: 0.966551, Valid Loss: 0.149704, Valid Acc: 0.950752, Time 00:00:08\n",
  389. "Epoch 4. Train Loss: 0.096433, Train Acc: 0.970732, Valid Loss: 0.116364, Valid Acc: 0.963311, Time 00:00:07\n",
  390. "Epoch 5. Train Loss: 0.083800, Train Acc: 0.973914, Valid Loss: 0.105775, Valid Acc: 0.968058, Time 00:00:08\n",
  391. "Epoch 6. Train Loss: 0.074534, Train Acc: 0.977129, Valid Loss: 0.094511, Valid Acc: 0.970728, Time 00:00:08\n",
  392. "Epoch 7. Train Loss: 0.067365, Train Acc: 0.979311, Valid Loss: 0.130495, Valid Acc: 0.960146, Time 00:00:09\n",
  393. "Epoch 8. Train Loss: 0.061585, Train Acc: 0.980894, Valid Loss: 0.089632, Valid Acc: 0.974090, Time 00:00:08\n",
  394. "Epoch 9. Train Loss: 0.055352, Train Acc: 0.982892, Valid Loss: 0.091508, Valid Acc: 0.970431, Time 00:00:08\n"
  395. ]
  396. }
  397. ],
  398. "source": [
  399. "no_bn_net = nn.Sequential(\n",
  400. " nn.Linear(784, 100),\n",
  401. " nn.ReLU(True),\n",
  402. " nn.Linear(100, 10)\n",
  403. ")\n",
  404. "\n",
  405. "optimizer = torch.optim.SGD(no_bn_net.parameters(), 1e-1) # 使用随机梯度下降,学习率 0.1\n",
  406. "train(no_bn_net, train_data, test_data, 10, optimizer, criterion)"
  407. ]
  408. },
  409. {
  410. "cell_type": "markdown",
  411. "metadata": {},
  412. "source": [
  413. "可以看到虽然最后的结果两种情况一样,但是如果我们看前几次的情况,可以看到使用批标准化的情况能够更快的收敛,因为这只是一个小网络,所以用不用批标准化都能够收敛,但是对于更加深的网络,使用批标准化在训练的时候能够很快地收敛"
  414. ]
  415. },
  416. {
  417. "cell_type": "markdown",
  418. "metadata": {},
  419. "source": [
  420. "从上面可以看到,我们自己实现了 2 维情况的批标准化,对应于卷积的 4 维情况的标准化是类似的,只需要沿着通道的维度进行均值和方差的计算,但是我们自己实现批标准化是很累的,pytorch 当然也为我们内置了批标准化的函数,一维和二维分别是 `torch.nn.BatchNorm1d()` 和 `torch.nn.BatchNorm2d()`,不同于我们的实现,pytorch 不仅将 $\\gamma$ 和 $\\beta$ 作为训练的参数,也将 `moving_mean` 和 `moving_var` 也作为参数进行训练"
  421. ]
  422. },
  423. {
  424. "cell_type": "markdown",
  425. "metadata": {},
  426. "source": [
  427. "下面我们在卷积网络下试用一下批标准化看看效果"
  428. ]
  429. },
  430. {
  431. "cell_type": "code",
  432. "execution_count": null,
  433. "metadata": {
  434. "collapsed": true
  435. },
  436. "outputs": [],
  437. "source": [
  438. "def data_tf(x):\n",
  439. " x = np.array(x, dtype='float32') / 255\n",
  440. " x = (x - 0.5) / 0.5 # 数据预处理,标准化\n",
  441. " x = torch.from_numpy(x)\n",
  442. " x = x.unsqueeze(0)\n",
  443. " return x\n",
  444. "\n",
  445. "train_set = mnist.MNIST('../../data/mnist', train=True, transform=data_tf, download=True) # 重新载入数据集,申明定义的数据变换\n",
  446. "test_set = mnist.MNIST('../../data/mnist', train=False, transform=data_tf, download=True)\n",
  447. "train_data = DataLoader(train_set, batch_size=64, shuffle=True)\n",
  448. "test_data = DataLoader(test_set, batch_size=128, shuffle=False)"
  449. ]
  450. },
  451. {
  452. "cell_type": "code",
  453. "execution_count": 78,
  454. "metadata": {
  455. "collapsed": true
  456. },
  457. "outputs": [],
  458. "source": [
  459. "# 使用批标准化\n",
  460. "class conv_bn_net(nn.Module):\n",
  461. " def __init__(self):\n",
  462. " super(conv_bn_net, self).__init__()\n",
  463. " self.stage1 = nn.Sequential(\n",
  464. " nn.Conv2d(1, 6, 3, padding=1),\n",
  465. " nn.BatchNorm2d(6),\n",
  466. " nn.ReLU(True),\n",
  467. " nn.MaxPool2d(2, 2),\n",
  468. " nn.Conv2d(6, 16, 5),\n",
  469. " nn.BatchNorm2d(16),\n",
  470. " nn.ReLU(True),\n",
  471. " nn.MaxPool2d(2, 2)\n",
  472. " )\n",
  473. " \n",
  474. " self.classfy = nn.Linear(400, 10)\n",
  475. " def forward(self, x):\n",
  476. " x = self.stage1(x)\n",
  477. " x = x.view(x.shape[0], -1)\n",
  478. " x = self.classfy(x)\n",
  479. " return x\n",
  480. "\n",
  481. "net = conv_bn_net()\n",
  482. "optimizer = torch.optim.SGD(net.parameters(), 1e-1) # 使用随机梯度下降,学习率 0.1"
  483. ]
  484. },
  485. {
  486. "cell_type": "code",
  487. "execution_count": 79,
  488. "metadata": {},
  489. "outputs": [
  490. {
  491. "name": "stdout",
  492. "output_type": "stream",
  493. "text": [
  494. "Epoch 0. Train Loss: 0.160329, Train Acc: 0.952842, Valid Loss: 0.063328, Valid Acc: 0.978441, Time 00:00:33\n",
  495. "Epoch 1. Train Loss: 0.067862, Train Acc: 0.979361, Valid Loss: 0.068229, Valid Acc: 0.979430, Time 00:00:37\n",
  496. "Epoch 2. Train Loss: 0.051867, Train Acc: 0.984625, Valid Loss: 0.044616, Valid Acc: 0.985265, Time 00:00:37\n",
  497. "Epoch 3. Train Loss: 0.044797, Train Acc: 0.986141, Valid Loss: 0.042711, Valid Acc: 0.986056, Time 00:00:38\n",
  498. "Epoch 4. Train Loss: 0.039876, Train Acc: 0.987690, Valid Loss: 0.042499, Valid Acc: 0.985067, Time 00:00:41\n"
  499. ]
  500. }
  501. ],
  502. "source": [
  503. "train(net, train_data, test_data, 5, optimizer, criterion)"
  504. ]
  505. },
  506. {
  507. "cell_type": "code",
  508. "execution_count": 76,
  509. "metadata": {
  510. "collapsed": true
  511. },
  512. "outputs": [],
  513. "source": [
  514. "# 不使用批标准化\n",
  515. "class conv_no_bn_net(nn.Module):\n",
  516. " def __init__(self):\n",
  517. " super(conv_no_bn_net, self).__init__()\n",
  518. " self.stage1 = nn.Sequential(\n",
  519. " nn.Conv2d(1, 6, 3, padding=1),\n",
  520. " nn.ReLU(True),\n",
  521. " nn.MaxPool2d(2, 2),\n",
  522. " nn.Conv2d(6, 16, 5),\n",
  523. " nn.ReLU(True),\n",
  524. " nn.MaxPool2d(2, 2)\n",
  525. " )\n",
  526. " \n",
  527. " self.classfy = nn.Linear(400, 10)\n",
  528. " def forward(self, x):\n",
  529. " x = self.stage1(x)\n",
  530. " x = x.view(x.shape[0], -1)\n",
  531. " x = self.classfy(x)\n",
  532. " return x\n",
  533. "\n",
  534. "net = conv_no_bn_net()\n",
  535. "optimizer = torch.optim.SGD(net.parameters(), 1e-1) # 使用随机梯度下降,学习率 0.1 "
  536. ]
  537. },
  538. {
  539. "cell_type": "code",
  540. "execution_count": 77,
  541. "metadata": {},
  542. "outputs": [
  543. {
  544. "name": "stdout",
  545. "output_type": "stream",
  546. "text": [
  547. "Epoch 0. Train Loss: 0.211075, Train Acc: 0.935934, Valid Loss: 0.062950, Valid Acc: 0.980123, Time 00:00:27\n",
  548. "Epoch 1. Train Loss: 0.066763, Train Acc: 0.978778, Valid Loss: 0.050143, Valid Acc: 0.984375, Time 00:00:29\n",
  549. "Epoch 2. Train Loss: 0.050870, Train Acc: 0.984292, Valid Loss: 0.039761, Valid Acc: 0.988034, Time 00:00:29\n",
  550. "Epoch 3. Train Loss: 0.041476, Train Acc: 0.986924, Valid Loss: 0.041925, Valid Acc: 0.986155, Time 00:00:29\n",
  551. "Epoch 4. Train Loss: 0.036118, Train Acc: 0.988523, Valid Loss: 0.042703, Valid Acc: 0.986452, Time 00:00:29\n"
  552. ]
  553. }
  554. ],
  555. "source": [
  556. "train(net, train_data, test_data, 5, optimizer, criterion)"
  557. ]
  558. },
  559. {
  560. "cell_type": "markdown",
  561. "metadata": {},
  562. "source": [
  563. "之后介绍一些著名的网络结构的时候,我们会慢慢认识到批标准化的重要性,使用 pytorch 能够非常方便地添加批标准化层"
  564. ]
  565. },
  566. {
  567. "cell_type": "markdown",
  568. "metadata": {},
  569. "source": [
  570. "## References\n",
  571. "* [透彻分析批归一化Batch Normalization强大作用](https://m.toutiaocdn.com/i6641764088760238595)"
  572. ]
  573. }
  574. ],
  575. "metadata": {
  576. "kernelspec": {
  577. "display_name": "Python 3",
  578. "language": "python",
  579. "name": "python3"
  580. },
  581. "language_info": {
  582. "codemirror_mode": {
  583. "name": "ipython",
  584. "version": 3
  585. },
  586. "file_extension": ".py",
  587. "mimetype": "text/x-python",
  588. "name": "python",
  589. "nbconvert_exporter": "python",
  590. "pygments_lexer": "ipython3",
  591. "version": "3.7.9"
  592. }
  593. },
  594. "nbformat": 4,
  595. "nbformat_minor": 2
  596. }

机器学习越来越多应用到飞行器、机器人等领域,其目的是利用计算机实现类似人类的智能,从而实现装备的智能化与无人化。本课程旨在引导学生掌握机器学习的基本知识、典型方法与技术,通过具体的应用案例激发学生对该学科的兴趣,鼓励学生能够从人工智能的角度来分析、解决飞行器、机器人所面临的问题和挑战。本课程主要内容包括Python编程基础,机器学习模型,无监督学习、监督学习、深度学习基础知识与实现,并学习如何利用机器学习解决实际问题,从而全面提升自我的《综合能力》。