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.

6-batch-normalization.ipynb 22 kB

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

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