├── .gitignore
├── code
├── chapter2
│ ├── 2.1.ipynb
│ ├── 2.2.ipynb
│ ├── 2.3.ipynb
│ ├── 2.7.ipynb
│ └── 2.9.ipynb
├── chapter3
│ ├── 3.1.ipynb
│ ├── 3.2.ipynb
│ ├── 3.3.ipynb
│ ├── 3.4.ipynb
│ └── 3.5.ipynb
├── chapter4
│ ├── 4.1.ipynb
│ └── 4.2.ipynb
└── chapter5
│ ├── 5.2.ipynb
│ └── 5.3.ipynb
├── data
├── chapter2
│ ├── ourpoints.hdf5
│ └── ourpoints.t
└── chapter3
│ ├── 1342-0.txt
│ ├── bobby.jpg
│ ├── hour-fixed.csv
│ ├── image-cats
│ ├── cat1.png
│ ├── cat2.png
│ └── cat3.png
│ ├── volumetric-dicom
│ └── 2-LUNG 3.0 B70f-04083
│ │ ├── 000000.dcm
│ │ ├── 000001.dcm
│ │ ├── 000002.dcm
│ │ ├── 000003.dcm
│ │ ├── 000004.dcm
│ │ ├── 000005.dcm
│ │ ├── 000006.dcm
│ │ ├── 000007.dcm
│ │ ├── 000008.dcm
│ │ ├── 000009.dcm
│ │ ├── 000010.dcm
│ │ ├── 000011.dcm
│ │ ├── 000012.dcm
│ │ ├── 000013.dcm
│ │ ├── 000014.dcm
│ │ ├── 000015.dcm
│ │ ├── 000016.dcm
│ │ ├── 000017.dcm
│ │ ├── 000018.dcm
│ │ ├── 000019.dcm
│ │ ├── 000020.dcm
│ │ ├── 000021.dcm
│ │ ├── 000022.dcm
│ │ ├── 000023.dcm
│ │ ├── 000024.dcm
│ │ ├── 000025.dcm
│ │ ├── 000026.dcm
│ │ ├── 000027.dcm
│ │ ├── 000028.dcm
│ │ ├── 000029.dcm
│ │ ├── 000030.dcm
│ │ ├── 000031.dcm
│ │ ├── 000032.dcm
│ │ ├── 000033.dcm
│ │ ├── 000034.dcm
│ │ ├── 000035.dcm
│ │ ├── 000036.dcm
│ │ ├── 000037.dcm
│ │ ├── 000038.dcm
│ │ ├── 000039.dcm
│ │ ├── 000040.dcm
│ │ ├── 000041.dcm
│ │ ├── 000042.dcm
│ │ ├── 000043.dcm
│ │ ├── 000044.dcm
│ │ ├── 000045.dcm
│ │ ├── 000046.dcm
│ │ ├── 000047.dcm
│ │ ├── 000048.dcm
│ │ ├── 000049.dcm
│ │ ├── 000050.dcm
│ │ ├── 000051.dcm
│ │ ├── 000052.dcm
│ │ ├── 000053.dcm
│ │ ├── 000054.dcm
│ │ ├── 000055.dcm
│ │ ├── 000056.dcm
│ │ ├── 000057.dcm
│ │ ├── 000058.dcm
│ │ ├── 000059.dcm
│ │ ├── 000060.dcm
│ │ ├── 000061.dcm
│ │ ├── 000062.dcm
│ │ ├── 000063.dcm
│ │ ├── 000064.dcm
│ │ ├── 000065.dcm
│ │ ├── 000066.dcm
│ │ ├── 000067.dcm
│ │ ├── 000068.dcm
│ │ ├── 000069.dcm
│ │ ├── 000070.dcm
│ │ ├── 000071.dcm
│ │ ├── 000072.dcm
│ │ ├── 000073.dcm
│ │ ├── 000074.dcm
│ │ ├── 000075.dcm
│ │ ├── 000076.dcm
│ │ ├── 000077.dcm
│ │ ├── 000078.dcm
│ │ ├── 000079.dcm
│ │ ├── 000080.dcm
│ │ ├── 000081.dcm
│ │ ├── 000082.dcm
│ │ ├── 000083.dcm
│ │ ├── 000084.dcm
│ │ ├── 000085.dcm
│ │ ├── 000086.dcm
│ │ ├── 000087.dcm
│ │ ├── 000088.dcm
│ │ ├── 000089.dcm
│ │ ├── 000090.dcm
│ │ ├── 000091.dcm
│ │ ├── 000092.dcm
│ │ ├── 000093.dcm
│ │ ├── 000094.dcm
│ │ ├── 000095.dcm
│ │ ├── 000096.dcm
│ │ ├── 000097.dcm
│ │ └── 000098.dcm
│ └── winequality-white.csv
└── docs
├── .nojekyll
├── README.md
├── _sidebar.md
├── chapter1
├── 1.0.md
├── 1.1.md
├── 1.2.md
├── 1.3.md
└── 1.4.md
├── chapter2
├── 2.0.md
├── 2.1.md
├── 2.2.md
├── 2.3.md
├── 2.4.md
├── 2.5.md
├── 2.6.md
├── 2.7.md
├── 2.8.md
└── 2.9.md
├── chapter3
├── 3.0.md
├── 3.1.md
├── 3.2.md
├── 3.3.md
├── 3.4.md
└── 3.5.md
├── chapter4
├── 4.0.md
├── 4.1.md
└── 4.2.md
├── chapter5
├── 5.0.md
├── 5.1.md
├── 5.2.md
└── 5.3.md
├── docsify.js
├── img
├── chapter1
│ ├── 1.1.png
│ ├── 1.2.png
│ ├── 1.3.png
│ └── 1.4.png
├── chapter2
│ ├── 2.1.png
│ ├── 2.2.png
│ ├── 2.3.png
│ ├── 2.4.png
│ ├── 2.5.png
│ └── 2.6.png
├── chapter3
│ ├── 3.1.png
│ ├── 3.2.png
│ ├── 3.3.png
│ └── 3.4.png
├── chapter4
│ ├── 4.1.png
│ ├── 4.10.png
│ ├── 4.11.png
│ ├── 4.12.png
│ ├── 4.13.png
│ ├── 4.14.png
│ ├── 4.2.png
│ ├── 4.3.png
│ ├── 4.4.png
│ ├── 4.5.png
│ ├── 4.6.png
│ ├── 4.7.png
│ ├── 4.8.png
│ └── 4.9.png
├── chapter5
│ ├── 5.1.png
│ ├── 5.2.png
│ ├── 5.3.png
│ ├── 5.4.png
│ ├── 5.5.png
│ ├── 5.6.png
│ ├── 5.7.png
│ └── 5.8.png
├── cover.png
└── twitter.png
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 | *.pyc
3 | *checkpoint.ipynb
4 | .mypy_cache*
5 | .vscode*
6 |
--------------------------------------------------------------------------------
/code/chapter2/2.1.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# 2.1 张量基础"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 1,
13 | "metadata": {
14 | "collapsed": true
15 | },
16 | "outputs": [],
17 | "source": [
18 | "a = [1.0, 2.0, 1.0]"
19 | ]
20 | },
21 | {
22 | "cell_type": "code",
23 | "execution_count": 2,
24 | "metadata": {},
25 | "outputs": [
26 | {
27 | "data": {
28 | "text/plain": [
29 | "1.0"
30 | ]
31 | },
32 | "execution_count": 2,
33 | "metadata": {},
34 | "output_type": "execute_result"
35 | }
36 | ],
37 | "source": [
38 | "a[0]"
39 | ]
40 | },
41 | {
42 | "cell_type": "code",
43 | "execution_count": 3,
44 | "metadata": {},
45 | "outputs": [
46 | {
47 | "data": {
48 | "text/plain": [
49 | "[1.0, 2.0, 3.0]"
50 | ]
51 | },
52 | "execution_count": 3,
53 | "metadata": {},
54 | "output_type": "execute_result"
55 | }
56 | ],
57 | "source": [
58 | "a[2] = 3.0\n",
59 | "a"
60 | ]
61 | },
62 | {
63 | "cell_type": "code",
64 | "execution_count": 4,
65 | "metadata": {},
66 | "outputs": [
67 | {
68 | "data": {
69 | "text/plain": [
70 | "tensor([1., 1., 1.])"
71 | ]
72 | },
73 | "execution_count": 4,
74 | "metadata": {},
75 | "output_type": "execute_result"
76 | }
77 | ],
78 | "source": [
79 | "import torch\n",
80 | "a = torch.ones(3)\n",
81 | "a"
82 | ]
83 | },
84 | {
85 | "cell_type": "code",
86 | "execution_count": 5,
87 | "metadata": {},
88 | "outputs": [
89 | {
90 | "data": {
91 | "text/plain": [
92 | "tensor(1.)"
93 | ]
94 | },
95 | "execution_count": 5,
96 | "metadata": {},
97 | "output_type": "execute_result"
98 | }
99 | ],
100 | "source": [
101 | "a[1]"
102 | ]
103 | },
104 | {
105 | "cell_type": "code",
106 | "execution_count": 6,
107 | "metadata": {},
108 | "outputs": [
109 | {
110 | "data": {
111 | "text/plain": [
112 | "1.0"
113 | ]
114 | },
115 | "execution_count": 6,
116 | "metadata": {},
117 | "output_type": "execute_result"
118 | }
119 | ],
120 | "source": [
121 | "float(a[1])"
122 | ]
123 | },
124 | {
125 | "cell_type": "code",
126 | "execution_count": 7,
127 | "metadata": {},
128 | "outputs": [
129 | {
130 | "data": {
131 | "text/plain": [
132 | "tensor([1., 1., 2.])"
133 | ]
134 | },
135 | "execution_count": 7,
136 | "metadata": {},
137 | "output_type": "execute_result"
138 | }
139 | ],
140 | "source": [
141 | "a[2] = 2.0\n",
142 | "a"
143 | ]
144 | },
145 | {
146 | "cell_type": "code",
147 | "execution_count": 8,
148 | "metadata": {
149 | "collapsed": true
150 | },
151 | "outputs": [],
152 | "source": [
153 | "# 使用.zeros是获取适当大小的数组的一种方法\n",
154 | "points = torch.zeros(6)\n",
155 | "# 用所需的值覆盖这些0\n",
156 | "points[0] = 1.0\n",
157 | "points[1] = 4.0\n",
158 | "points[2] = 2.0\n",
159 | "points[3] = 1.0\n",
160 | "points[4] = 3.0\n",
161 | "points[5] = 5.0"
162 | ]
163 | },
164 | {
165 | "cell_type": "code",
166 | "execution_count": 9,
167 | "metadata": {},
168 | "outputs": [
169 | {
170 | "data": {
171 | "text/plain": [
172 | "tensor([1., 4., 2., 1., 3., 5.])"
173 | ]
174 | },
175 | "execution_count": 9,
176 | "metadata": {},
177 | "output_type": "execute_result"
178 | }
179 | ],
180 | "source": [
181 | "points = torch.tensor([1.0, 4.0, 2.0, 1.0, 3.0, 5.0])\n",
182 | "points"
183 | ]
184 | },
185 | {
186 | "cell_type": "code",
187 | "execution_count": 10,
188 | "metadata": {},
189 | "outputs": [
190 | {
191 | "data": {
192 | "text/plain": [
193 | "(1.0, 4.0)"
194 | ]
195 | },
196 | "execution_count": 10,
197 | "metadata": {},
198 | "output_type": "execute_result"
199 | }
200 | ],
201 | "source": [
202 | "float(points[0]), float(points[1])"
203 | ]
204 | },
205 | {
206 | "cell_type": "code",
207 | "execution_count": 11,
208 | "metadata": {},
209 | "outputs": [
210 | {
211 | "data": {
212 | "text/plain": [
213 | "tensor([[1., 4.],\n",
214 | " [2., 1.],\n",
215 | " [3., 5.]])"
216 | ]
217 | },
218 | "execution_count": 11,
219 | "metadata": {},
220 | "output_type": "execute_result"
221 | }
222 | ],
223 | "source": [
224 | "points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])\n",
225 | "points"
226 | ]
227 | },
228 | {
229 | "cell_type": "code",
230 | "execution_count": 12,
231 | "metadata": {},
232 | "outputs": [
233 | {
234 | "data": {
235 | "text/plain": [
236 | "torch.Size([3, 2])"
237 | ]
238 | },
239 | "execution_count": 12,
240 | "metadata": {},
241 | "output_type": "execute_result"
242 | }
243 | ],
244 | "source": [
245 | "points.shape"
246 | ]
247 | },
248 | {
249 | "cell_type": "code",
250 | "execution_count": 13,
251 | "metadata": {},
252 | "outputs": [
253 | {
254 | "data": {
255 | "text/plain": [
256 | "tensor([[0., 0.],\n",
257 | " [0., 0.],\n",
258 | " [0., 0.]])"
259 | ]
260 | },
261 | "execution_count": 13,
262 | "metadata": {},
263 | "output_type": "execute_result"
264 | }
265 | ],
266 | "source": [
267 | "points = torch.zeros(3, 2)\n",
268 | "points"
269 | ]
270 | },
271 | {
272 | "cell_type": "code",
273 | "execution_count": 14,
274 | "metadata": {},
275 | "outputs": [
276 | {
277 | "data": {
278 | "text/plain": [
279 | "tensor([[1., 4.],\n",
280 | " [2., 1.],\n",
281 | " [3., 5.]])"
282 | ]
283 | },
284 | "execution_count": 14,
285 | "metadata": {},
286 | "output_type": "execute_result"
287 | }
288 | ],
289 | "source": [
290 | "points = torch.FloatTensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])\n",
291 | "points"
292 | ]
293 | },
294 | {
295 | "cell_type": "code",
296 | "execution_count": 15,
297 | "metadata": {},
298 | "outputs": [
299 | {
300 | "data": {
301 | "text/plain": [
302 | "tensor(4.)"
303 | ]
304 | },
305 | "execution_count": 15,
306 | "metadata": {},
307 | "output_type": "execute_result"
308 | }
309 | ],
310 | "source": [
311 | "points[0, 1]"
312 | ]
313 | },
314 | {
315 | "cell_type": "code",
316 | "execution_count": 16,
317 | "metadata": {},
318 | "outputs": [
319 | {
320 | "data": {
321 | "text/plain": [
322 | "tensor([1., 4.])"
323 | ]
324 | },
325 | "execution_count": 16,
326 | "metadata": {},
327 | "output_type": "execute_result"
328 | }
329 | ],
330 | "source": [
331 | "points[0]"
332 | ]
333 | },
334 | {
335 | "cell_type": "code",
336 | "execution_count": null,
337 | "metadata": {
338 | "collapsed": true
339 | },
340 | "outputs": [],
341 | "source": []
342 | }
343 | ],
344 | "metadata": {
345 | "kernelspec": {
346 | "display_name": "Python 3",
347 | "language": "python",
348 | "name": "python3"
349 | },
350 | "language_info": {
351 | "codemirror_mode": {
352 | "name": "ipython",
353 | "version": 3
354 | },
355 | "file_extension": ".py",
356 | "mimetype": "text/x-python",
357 | "name": "python",
358 | "nbconvert_exporter": "python",
359 | "pygments_lexer": "ipython3",
360 | "version": "3.6.2"
361 | }
362 | },
363 | "nbformat": 4,
364 | "nbformat_minor": 2
365 | }
366 |
--------------------------------------------------------------------------------
/code/chapter2/2.2.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# 2.2 张量与存储"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 1,
13 | "metadata": {
14 | "collapsed": true
15 | },
16 | "outputs": [],
17 | "source": [
18 | "import torch"
19 | ]
20 | },
21 | {
22 | "cell_type": "code",
23 | "execution_count": 2,
24 | "metadata": {},
25 | "outputs": [
26 | {
27 | "data": {
28 | "text/plain": [
29 | " 1.0\n",
30 | " 4.0\n",
31 | " 2.0\n",
32 | " 1.0\n",
33 | " 3.0\n",
34 | " 5.0\n",
35 | "[torch.FloatStorage of size 6]"
36 | ]
37 | },
38 | "execution_count": 2,
39 | "metadata": {},
40 | "output_type": "execute_result"
41 | }
42 | ],
43 | "source": [
44 | "points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])\n",
45 | "points.storage()"
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "execution_count": 3,
51 | "metadata": {},
52 | "outputs": [
53 | {
54 | "data": {
55 | "text/plain": [
56 | "1.0"
57 | ]
58 | },
59 | "execution_count": 3,
60 | "metadata": {},
61 | "output_type": "execute_result"
62 | }
63 | ],
64 | "source": [
65 | "points_storage = points.storage()\n",
66 | "points_storage[0]"
67 | ]
68 | },
69 | {
70 | "cell_type": "code",
71 | "execution_count": 4,
72 | "metadata": {},
73 | "outputs": [
74 | {
75 | "data": {
76 | "text/plain": [
77 | "4.0"
78 | ]
79 | },
80 | "execution_count": 4,
81 | "metadata": {},
82 | "output_type": "execute_result"
83 | }
84 | ],
85 | "source": [
86 | "points.storage()[1]"
87 | ]
88 | },
89 | {
90 | "cell_type": "code",
91 | "execution_count": 5,
92 | "metadata": {},
93 | "outputs": [
94 | {
95 | "data": {
96 | "text/plain": [
97 | "tensor([[2., 4.],\n",
98 | " [2., 1.],\n",
99 | " [3., 5.]])"
100 | ]
101 | },
102 | "execution_count": 5,
103 | "metadata": {},
104 | "output_type": "execute_result"
105 | }
106 | ],
107 | "source": [
108 | "points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])\n",
109 | "points_storage = points.storage()\n",
110 | "points_storage[0] = 2.0\n",
111 | "points"
112 | ]
113 | },
114 | {
115 | "cell_type": "code",
116 | "execution_count": null,
117 | "metadata": {
118 | "collapsed": true
119 | },
120 | "outputs": [],
121 | "source": []
122 | }
123 | ],
124 | "metadata": {
125 | "kernelspec": {
126 | "display_name": "Python 3",
127 | "language": "python",
128 | "name": "python3"
129 | },
130 | "language_info": {
131 | "codemirror_mode": {
132 | "name": "ipython",
133 | "version": 3
134 | },
135 | "file_extension": ".py",
136 | "mimetype": "text/x-python",
137 | "name": "python",
138 | "nbconvert_exporter": "python",
139 | "pygments_lexer": "ipython3",
140 | "version": "3.6.2"
141 | }
142 | },
143 | "nbformat": 4,
144 | "nbformat_minor": 2
145 | }
146 |
--------------------------------------------------------------------------------
/code/chapter2/2.3.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# 2.3 尺寸、存储偏移与步长"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 1,
13 | "metadata": {},
14 | "outputs": [
15 | {
16 | "data": {
17 | "text/plain": [
18 | "2"
19 | ]
20 | },
21 | "execution_count": 1,
22 | "metadata": {},
23 | "output_type": "execute_result"
24 | }
25 | ],
26 | "source": [
27 | "import torch\n",
28 | "\n",
29 | "points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])\n",
30 | "second_point = points[1]\n",
31 | "second_point.storage_offset()"
32 | ]
33 | },
34 | {
35 | "cell_type": "code",
36 | "execution_count": 2,
37 | "metadata": {},
38 | "outputs": [
39 | {
40 | "data": {
41 | "text/plain": [
42 | "torch.Size([2])"
43 | ]
44 | },
45 | "execution_count": 2,
46 | "metadata": {},
47 | "output_type": "execute_result"
48 | }
49 | ],
50 | "source": [
51 | "second_point.size()"
52 | ]
53 | },
54 | {
55 | "cell_type": "code",
56 | "execution_count": 3,
57 | "metadata": {},
58 | "outputs": [
59 | {
60 | "data": {
61 | "text/plain": [
62 | "torch.Size([2])"
63 | ]
64 | },
65 | "execution_count": 3,
66 | "metadata": {},
67 | "output_type": "execute_result"
68 | }
69 | ],
70 | "source": [
71 | "second_point.shape"
72 | ]
73 | },
74 | {
75 | "cell_type": "code",
76 | "execution_count": 4,
77 | "metadata": {},
78 | "outputs": [
79 | {
80 | "data": {
81 | "text/plain": [
82 | "(2, 1)"
83 | ]
84 | },
85 | "execution_count": 4,
86 | "metadata": {},
87 | "output_type": "execute_result"
88 | }
89 | ],
90 | "source": [
91 | "points.stride()"
92 | ]
93 | },
94 | {
95 | "cell_type": "code",
96 | "execution_count": 5,
97 | "metadata": {},
98 | "outputs": [
99 | {
100 | "data": {
101 | "text/plain": [
102 | "torch.Size([2])"
103 | ]
104 | },
105 | "execution_count": 5,
106 | "metadata": {},
107 | "output_type": "execute_result"
108 | }
109 | ],
110 | "source": [
111 | "points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])\n",
112 | "second_point = points[1]\n",
113 | "second_point.size()"
114 | ]
115 | },
116 | {
117 | "cell_type": "code",
118 | "execution_count": 6,
119 | "metadata": {},
120 | "outputs": [
121 | {
122 | "data": {
123 | "text/plain": [
124 | "2"
125 | ]
126 | },
127 | "execution_count": 6,
128 | "metadata": {},
129 | "output_type": "execute_result"
130 | }
131 | ],
132 | "source": [
133 | "second_point.storage_offset()"
134 | ]
135 | },
136 | {
137 | "cell_type": "code",
138 | "execution_count": 7,
139 | "metadata": {},
140 | "outputs": [
141 | {
142 | "data": {
143 | "text/plain": [
144 | "(1,)"
145 | ]
146 | },
147 | "execution_count": 7,
148 | "metadata": {},
149 | "output_type": "execute_result"
150 | }
151 | ],
152 | "source": [
153 | "second_point.stride()"
154 | ]
155 | },
156 | {
157 | "cell_type": "code",
158 | "execution_count": 8,
159 | "metadata": {},
160 | "outputs": [
161 | {
162 | "data": {
163 | "text/plain": [
164 | "tensor([[ 1., 4.],\n",
165 | " [10., 1.],\n",
166 | " [ 3., 5.]])"
167 | ]
168 | },
169 | "execution_count": 8,
170 | "metadata": {},
171 | "output_type": "execute_result"
172 | }
173 | ],
174 | "source": [
175 | "points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])\n",
176 | "second_point = points[1]\n",
177 | "second_point[0] = 10.0\n",
178 | "points"
179 | ]
180 | },
181 | {
182 | "cell_type": "code",
183 | "execution_count": 9,
184 | "metadata": {},
185 | "outputs": [
186 | {
187 | "data": {
188 | "text/plain": [
189 | "tensor([[1., 4.],\n",
190 | " [2., 1.],\n",
191 | " [3., 5.]])"
192 | ]
193 | },
194 | "execution_count": 9,
195 | "metadata": {},
196 | "output_type": "execute_result"
197 | }
198 | ],
199 | "source": [
200 | "points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])\n",
201 | "second_point = points[1].clone()\n",
202 | "second_point[0] = 10.0\n",
203 | "points"
204 | ]
205 | },
206 | {
207 | "cell_type": "markdown",
208 | "metadata": {},
209 | "source": [
210 | "## 矩阵转置"
211 | ]
212 | },
213 | {
214 | "cell_type": "code",
215 | "execution_count": 10,
216 | "metadata": {},
217 | "outputs": [
218 | {
219 | "data": {
220 | "text/plain": [
221 | "tensor([[1., 4.],\n",
222 | " [2., 1.],\n",
223 | " [3., 5.]])"
224 | ]
225 | },
226 | "execution_count": 10,
227 | "metadata": {},
228 | "output_type": "execute_result"
229 | }
230 | ],
231 | "source": [
232 | "points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])\n",
233 | "points"
234 | ]
235 | },
236 | {
237 | "cell_type": "code",
238 | "execution_count": 11,
239 | "metadata": {},
240 | "outputs": [
241 | {
242 | "data": {
243 | "text/plain": [
244 | "tensor([[1., 2., 3.],\n",
245 | " [4., 1., 5.]])"
246 | ]
247 | },
248 | "execution_count": 11,
249 | "metadata": {},
250 | "output_type": "execute_result"
251 | }
252 | ],
253 | "source": [
254 | "points_t = points.t()\n",
255 | "points_t"
256 | ]
257 | },
258 | {
259 | "cell_type": "code",
260 | "execution_count": 12,
261 | "metadata": {},
262 | "outputs": [
263 | {
264 | "data": {
265 | "text/plain": [
266 | "True"
267 | ]
268 | },
269 | "execution_count": 12,
270 | "metadata": {},
271 | "output_type": "execute_result"
272 | }
273 | ],
274 | "source": [
275 | "id(points.storage()) == id(points_t.storage())"
276 | ]
277 | },
278 | {
279 | "cell_type": "code",
280 | "execution_count": 13,
281 | "metadata": {},
282 | "outputs": [
283 | {
284 | "data": {
285 | "text/plain": [
286 | "(2, 1)"
287 | ]
288 | },
289 | "execution_count": 13,
290 | "metadata": {},
291 | "output_type": "execute_result"
292 | }
293 | ],
294 | "source": [
295 | "points.stride()"
296 | ]
297 | },
298 | {
299 | "cell_type": "code",
300 | "execution_count": 14,
301 | "metadata": {},
302 | "outputs": [
303 | {
304 | "data": {
305 | "text/plain": [
306 | "(1, 2)"
307 | ]
308 | },
309 | "execution_count": 14,
310 | "metadata": {},
311 | "output_type": "execute_result"
312 | }
313 | ],
314 | "source": [
315 | "points_t.stride()"
316 | ]
317 | },
318 | {
319 | "cell_type": "markdown",
320 | "metadata": {},
321 | "source": [
322 | "## 多维数组转置"
323 | ]
324 | },
325 | {
326 | "cell_type": "code",
327 | "execution_count": 15,
328 | "metadata": {},
329 | "outputs": [
330 | {
331 | "data": {
332 | "text/plain": [
333 | "(torch.Size([3, 4, 5]), (20, 5, 1))"
334 | ]
335 | },
336 | "execution_count": 15,
337 | "metadata": {},
338 | "output_type": "execute_result"
339 | }
340 | ],
341 | "source": [
342 | "some_tensor = torch.ones(3, 4, 5)\n",
343 | "some_tensor.shape, some_tensor.stride()"
344 | ]
345 | },
346 | {
347 | "cell_type": "code",
348 | "execution_count": 16,
349 | "metadata": {},
350 | "outputs": [
351 | {
352 | "data": {
353 | "text/plain": [
354 | "(torch.Size([5, 4, 3]), (1, 5, 20))"
355 | ]
356 | },
357 | "execution_count": 16,
358 | "metadata": {},
359 | "output_type": "execute_result"
360 | }
361 | ],
362 | "source": [
363 | "some_tensor_t = some_tensor.transpose(0, 2)\n",
364 | "some_tensor_t.shape, some_tensor_t.stride()"
365 | ]
366 | },
367 | {
368 | "cell_type": "markdown",
369 | "metadata": {},
370 | "source": [
371 | "## 张量的连续性"
372 | ]
373 | },
374 | {
375 | "cell_type": "code",
376 | "execution_count": 17,
377 | "metadata": {},
378 | "outputs": [
379 | {
380 | "data": {
381 | "text/plain": [
382 | "(True, False)"
383 | ]
384 | },
385 | "execution_count": 17,
386 | "metadata": {},
387 | "output_type": "execute_result"
388 | }
389 | ],
390 | "source": [
391 | "points.is_contiguous(), points_t.is_contiguous()"
392 | ]
393 | },
394 | {
395 | "cell_type": "code",
396 | "execution_count": 18,
397 | "metadata": {},
398 | "outputs": [
399 | {
400 | "data": {
401 | "text/plain": [
402 | "tensor([[1., 2., 3.],\n",
403 | " [4., 1., 5.]])"
404 | ]
405 | },
406 | "execution_count": 18,
407 | "metadata": {},
408 | "output_type": "execute_result"
409 | }
410 | ],
411 | "source": [
412 | "points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])\n",
413 | "points_t = points.t()\n",
414 | "points_t"
415 | ]
416 | },
417 | {
418 | "cell_type": "code",
419 | "execution_count": 19,
420 | "metadata": {},
421 | "outputs": [
422 | {
423 | "data": {
424 | "text/plain": [
425 | " 1.0\n",
426 | " 4.0\n",
427 | " 2.0\n",
428 | " 1.0\n",
429 | " 3.0\n",
430 | " 5.0\n",
431 | "[torch.FloatStorage of size 6]"
432 | ]
433 | },
434 | "execution_count": 19,
435 | "metadata": {},
436 | "output_type": "execute_result"
437 | }
438 | ],
439 | "source": [
440 | "points_t.storage()"
441 | ]
442 | },
443 | {
444 | "cell_type": "code",
445 | "execution_count": 20,
446 | "metadata": {},
447 | "outputs": [
448 | {
449 | "data": {
450 | "text/plain": [
451 | "(1, 2)"
452 | ]
453 | },
454 | "execution_count": 20,
455 | "metadata": {},
456 | "output_type": "execute_result"
457 | }
458 | ],
459 | "source": [
460 | "points_t.stride()"
461 | ]
462 | },
463 | {
464 | "cell_type": "code",
465 | "execution_count": 21,
466 | "metadata": {},
467 | "outputs": [
468 | {
469 | "data": {
470 | "text/plain": [
471 | "tensor([[1., 2., 3.],\n",
472 | " [4., 1., 5.]])"
473 | ]
474 | },
475 | "execution_count": 21,
476 | "metadata": {},
477 | "output_type": "execute_result"
478 | }
479 | ],
480 | "source": [
481 | "points_t_cont = points_t.contiguous()\n",
482 | "points_t_cont"
483 | ]
484 | },
485 | {
486 | "cell_type": "code",
487 | "execution_count": 22,
488 | "metadata": {},
489 | "outputs": [
490 | {
491 | "data": {
492 | "text/plain": [
493 | "(3, 1)"
494 | ]
495 | },
496 | "execution_count": 22,
497 | "metadata": {},
498 | "output_type": "execute_result"
499 | }
500 | ],
501 | "source": [
502 | "points_t_cont.stride()"
503 | ]
504 | },
505 | {
506 | "cell_type": "code",
507 | "execution_count": 23,
508 | "metadata": {},
509 | "outputs": [
510 | {
511 | "data": {
512 | "text/plain": [
513 | " 1.0\n",
514 | " 2.0\n",
515 | " 3.0\n",
516 | " 4.0\n",
517 | " 1.0\n",
518 | " 5.0\n",
519 | "[torch.FloatStorage of size 6]"
520 | ]
521 | },
522 | "execution_count": 23,
523 | "metadata": {},
524 | "output_type": "execute_result"
525 | }
526 | ],
527 | "source": [
528 | "points_t_cont.storage()"
529 | ]
530 | },
531 | {
532 | "cell_type": "code",
533 | "execution_count": null,
534 | "metadata": {
535 | "collapsed": true
536 | },
537 | "outputs": [],
538 | "source": []
539 | }
540 | ],
541 | "metadata": {
542 | "kernelspec": {
543 | "display_name": "Python 3",
544 | "language": "python",
545 | "name": "python3"
546 | },
547 | "language_info": {
548 | "codemirror_mode": {
549 | "name": "ipython",
550 | "version": 3
551 | },
552 | "file_extension": ".py",
553 | "mimetype": "text/x-python",
554 | "name": "python",
555 | "nbconvert_exporter": "python",
556 | "pygments_lexer": "ipython3",
557 | "version": "3.6.2"
558 | }
559 | },
560 | "nbformat": 4,
561 | "nbformat_minor": 2
562 | }
563 |
--------------------------------------------------------------------------------
/code/chapter2/2.7.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# 2.7 序列化张量"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 1,
13 | "metadata": {},
14 | "outputs": [
15 | {
16 | "data": {
17 | "text/plain": [
18 | "tensor([[1., 4.],\n",
19 | " [2., 1.],\n",
20 | " [3., 5.]])"
21 | ]
22 | },
23 | "execution_count": 1,
24 | "metadata": {},
25 | "output_type": "execute_result"
26 | }
27 | ],
28 | "source": [
29 | "import torch\n",
30 | "\n",
31 | "points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])\n",
32 | "points"
33 | ]
34 | },
35 | {
36 | "cell_type": "code",
37 | "execution_count": 2,
38 | "metadata": {
39 | "collapsed": true
40 | },
41 | "outputs": [],
42 | "source": [
43 | "torch.save(points, '../../data/chapter2/ourpoints.t')"
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "execution_count": 3,
49 | "metadata": {},
50 | "outputs": [
51 | {
52 | "name": "stdout",
53 | "output_type": "stream",
54 | "text": [
55 | "ourpoints.hdf5 ourpoints.t\r\n"
56 | ]
57 | }
58 | ],
59 | "source": [
60 | "!ls ../../data/chapter2/"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": 4,
66 | "metadata": {
67 | "collapsed": true
68 | },
69 | "outputs": [],
70 | "source": [
71 | "with open('../../data/chapter2/ourpoints.t','wb') as f:\n",
72 | " torch.save(points, f)"
73 | ]
74 | },
75 | {
76 | "cell_type": "code",
77 | "execution_count": 5,
78 | "metadata": {
79 | "collapsed": true
80 | },
81 | "outputs": [],
82 | "source": [
83 | "points = torch.load('../../data/chapter2/ourpoints.t')"
84 | ]
85 | },
86 | {
87 | "cell_type": "code",
88 | "execution_count": 6,
89 | "metadata": {
90 | "collapsed": true
91 | },
92 | "outputs": [],
93 | "source": [
94 | "with open('../../data/chapter2/ourpoints.t','rb') as f:\n",
95 | " points = torch.load(f)"
96 | ]
97 | },
98 | {
99 | "cell_type": "markdown",
100 | "metadata": {},
101 | "source": [
102 | "## HDF5"
103 | ]
104 | },
105 | {
106 | "cell_type": "code",
107 | "execution_count": 7,
108 | "metadata": {
109 | "collapsed": true
110 | },
111 | "outputs": [],
112 | "source": [
113 | "import h5py\n",
114 | "\n",
115 | "f = h5py.File('../../data/chapter2/ourpoints.hdf5', 'w')\n",
116 | "dset = f.create_dataset('coords', data=points.numpy())\n",
117 | "f.close()"
118 | ]
119 | },
120 | {
121 | "cell_type": "code",
122 | "execution_count": 8,
123 | "metadata": {},
124 | "outputs": [
125 | {
126 | "name": "stdout",
127 | "output_type": "stream",
128 | "text": [
129 | "ourpoints.hdf5 ourpoints.t\r\n"
130 | ]
131 | }
132 | ],
133 | "source": [
134 | "!ls ../../data/chapter2/"
135 | ]
136 | },
137 | {
138 | "cell_type": "code",
139 | "execution_count": 9,
140 | "metadata": {},
141 | "outputs": [
142 | {
143 | "data": {
144 | "text/plain": [
145 | "array([[ 2., 1.],\n",
146 | " [ 3., 5.]], dtype=float32)"
147 | ]
148 | },
149 | "execution_count": 9,
150 | "metadata": {},
151 | "output_type": "execute_result"
152 | }
153 | ],
154 | "source": [
155 | "f = h5py.File('../../data/chapter2/ourpoints.hdf5', 'r')\n",
156 | "dset = f['coords']\n",
157 | "last_points = dset[1:]\n",
158 | "last_points"
159 | ]
160 | },
161 | {
162 | "cell_type": "code",
163 | "execution_count": 10,
164 | "metadata": {},
165 | "outputs": [
166 | {
167 | "data": {
168 | "text/plain": [
169 | "tensor([[2., 1.],\n",
170 | " [3., 5.]])"
171 | ]
172 | },
173 | "execution_count": 10,
174 | "metadata": {},
175 | "output_type": "execute_result"
176 | }
177 | ],
178 | "source": [
179 | "last_points = torch.from_numpy(dset[1:])\n",
180 | "f.close()\n",
181 | "last_points"
182 | ]
183 | },
184 | {
185 | "cell_type": "code",
186 | "execution_count": 11,
187 | "metadata": {},
188 | "outputs": [],
189 | "source": [
190 | "# last_points = torch.from_numpy(dset[1:]) # 会报错, 因为f已经关了"
191 | ]
192 | },
193 | {
194 | "cell_type": "code",
195 | "execution_count": null,
196 | "metadata": {
197 | "collapsed": true
198 | },
199 | "outputs": [],
200 | "source": []
201 | }
202 | ],
203 | "metadata": {
204 | "kernelspec": {
205 | "display_name": "Python 3",
206 | "language": "python",
207 | "name": "python3"
208 | },
209 | "language_info": {
210 | "codemirror_mode": {
211 | "name": "ipython",
212 | "version": 3
213 | },
214 | "file_extension": ".py",
215 | "mimetype": "text/x-python",
216 | "name": "python",
217 | "nbconvert_exporter": "python",
218 | "pygments_lexer": "ipython3",
219 | "version": "3.6.2"
220 | }
221 | },
222 | "nbformat": 4,
223 | "nbformat_minor": 2
224 | }
225 |
--------------------------------------------------------------------------------
/code/chapter2/2.9.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# 2.9 张量API"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 1,
13 | "metadata": {
14 | "collapsed": true
15 | },
16 | "outputs": [],
17 | "source": [
18 | "import torch"
19 | ]
20 | },
21 | {
22 | "cell_type": "code",
23 | "execution_count": 2,
24 | "metadata": {},
25 | "outputs": [],
26 | "source": [
27 | "a = torch.ones(3, 2)\n",
28 | "a_t = torch.transpose(a, 0, 1)"
29 | ]
30 | },
31 | {
32 | "cell_type": "code",
33 | "execution_count": 3,
34 | "metadata": {
35 | "collapsed": true
36 | },
37 | "outputs": [],
38 | "source": [
39 | "a = torch.ones(3, 2)\n",
40 | "a_t = a.transpose(0, 1)"
41 | ]
42 | },
43 | {
44 | "cell_type": "code",
45 | "execution_count": 4,
46 | "metadata": {
47 | "collapsed": true
48 | },
49 | "outputs": [],
50 | "source": [
51 | "a = torch.ones(3, 2)"
52 | ]
53 | },
54 | {
55 | "cell_type": "code",
56 | "execution_count": 5,
57 | "metadata": {},
58 | "outputs": [
59 | {
60 | "data": {
61 | "text/plain": [
62 | "tensor([[0., 0.],\n",
63 | " [0., 0.],\n",
64 | " [0., 0.]])"
65 | ]
66 | },
67 | "execution_count": 5,
68 | "metadata": {},
69 | "output_type": "execute_result"
70 | }
71 | ],
72 | "source": [
73 | "a.zero_()\n",
74 | "a"
75 | ]
76 | },
77 | {
78 | "cell_type": "code",
79 | "execution_count": null,
80 | "metadata": {
81 | "collapsed": true
82 | },
83 | "outputs": [],
84 | "source": []
85 | }
86 | ],
87 | "metadata": {
88 | "kernelspec": {
89 | "display_name": "Python 3",
90 | "language": "python",
91 | "name": "python3"
92 | },
93 | "language_info": {
94 | "codemirror_mode": {
95 | "name": "ipython",
96 | "version": 3
97 | },
98 | "file_extension": ".py",
99 | "mimetype": "text/x-python",
100 | "name": "python",
101 | "nbconvert_exporter": "python",
102 | "pygments_lexer": "ipython3",
103 | "version": "3.6.2"
104 | }
105 | },
106 | "nbformat": 4,
107 | "nbformat_minor": 2
108 | }
109 |
--------------------------------------------------------------------------------
/code/chapter3/3.2.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# 3.2 时间序列"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 2,
13 | "metadata": {},
14 | "outputs": [
15 | {
16 | "data": {
17 | "text/plain": [
18 | "tensor([[1.0000e+00, 1.0000e+00, 1.0000e+00, ..., 3.0000e+00, 1.3000e+01,\n",
19 | " 1.6000e+01],\n",
20 | " [2.0000e+00, 1.0000e+00, 1.0000e+00, ..., 8.0000e+00, 3.2000e+01,\n",
21 | " 4.0000e+01],\n",
22 | " [3.0000e+00, 1.0000e+00, 1.0000e+00, ..., 5.0000e+00, 2.7000e+01,\n",
23 | " 3.2000e+01],\n",
24 | " ...,\n",
25 | " [1.7377e+04, 3.1000e+01, 1.0000e+00, ..., 7.0000e+00, 8.3000e+01,\n",
26 | " 9.0000e+01],\n",
27 | " [1.7378e+04, 3.1000e+01, 1.0000e+00, ..., 1.3000e+01, 4.8000e+01,\n",
28 | " 6.1000e+01],\n",
29 | " [1.7379e+04, 3.1000e+01, 1.0000e+00, ..., 1.2000e+01, 3.7000e+01,\n",
30 | " 4.9000e+01]])"
31 | ]
32 | },
33 | "execution_count": 2,
34 | "metadata": {},
35 | "output_type": "execute_result"
36 | }
37 | ],
38 | "source": [
39 | "import csv\n",
40 | "import numpy as np\n",
41 | "import torch\n",
42 | "bikes_numpy = np.loadtxt(\"../../data/chapter3/hour-fixed.csv\",\n",
43 | " dtype=np.float32,\n",
44 | " delimiter=\",\",\n",
45 | " skiprows=1,\n",
46 | " converters={1: lambda x: float(x[8:10])})#将日期字符串转换为与列1中的月份对应的数字\n",
47 | "bikes = torch.from_numpy(bikes_numpy)\n",
48 | "bikes"
49 | ]
50 | },
51 | {
52 | "cell_type": "markdown",
53 | "metadata": {},
54 | "source": [
55 | "## 数据重塑"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": 3,
61 | "metadata": {},
62 | "outputs": [
63 | {
64 | "data": {
65 | "text/plain": [
66 | "(torch.Size([17520, 17]), (17, 1))"
67 | ]
68 | },
69 | "execution_count": 3,
70 | "metadata": {},
71 | "output_type": "execute_result"
72 | }
73 | ],
74 | "source": [
75 | "bikes.shape, bikes.stride()"
76 | ]
77 | },
78 | {
79 | "cell_type": "code",
80 | "execution_count": 28,
81 | "metadata": {},
82 | "outputs": [
83 | {
84 | "data": {
85 | "text/plain": [
86 | "(torch.Size([730, 24, 17]), (408, 17, 1))"
87 | ]
88 | },
89 | "execution_count": 28,
90 | "metadata": {},
91 | "output_type": "execute_result"
92 | }
93 | ],
94 | "source": [
95 | "daily_bikes = bikes.view(-1, 24, bikes.shape[1])\n",
96 | "daily_bikes.shape, daily_bikes.stride()"
97 | ]
98 | },
99 | {
100 | "cell_type": "markdown",
101 | "metadata": {},
102 | "source": [
103 | "## 数据转置"
104 | ]
105 | },
106 | {
107 | "cell_type": "code",
108 | "execution_count": 29,
109 | "metadata": {},
110 | "outputs": [
111 | {
112 | "data": {
113 | "text/plain": [
114 | "(torch.Size([730, 17, 24]), (408, 1, 17))"
115 | ]
116 | },
117 | "execution_count": 29,
118 | "metadata": {},
119 | "output_type": "execute_result"
120 | }
121 | ],
122 | "source": [
123 | "daily_bikes = daily_bikes.transpose(1, 2)\n",
124 | "daily_bikes.shape, daily_bikes.stride()"
125 | ]
126 | },
127 | {
128 | "cell_type": "markdown",
129 | "metadata": {},
130 | "source": [
131 | "## 独热编码"
132 | ]
133 | },
134 | {
135 | "cell_type": "code",
136 | "execution_count": 30,
137 | "metadata": {},
138 | "outputs": [
139 | {
140 | "data": {
141 | "text/plain": [
142 | "tensor([1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2])"
143 | ]
144 | },
145 | "execution_count": 30,
146 | "metadata": {},
147 | "output_type": "execute_result"
148 | }
149 | ],
150 | "source": [
151 | "first_day = bikes[:24].long()\n",
152 | "weather_onehot = torch.zeros(first_day.shape[0], 4)\n",
153 | "first_day[:,9]"
154 | ]
155 | },
156 | {
157 | "cell_type": "code",
158 | "execution_count": 31,
159 | "metadata": {},
160 | "outputs": [
161 | {
162 | "data": {
163 | "text/plain": [
164 | "tensor([[1., 0., 0., 0.],\n",
165 | " [1., 0., 0., 0.],\n",
166 | " [1., 0., 0., 0.],\n",
167 | " [1., 0., 0., 0.],\n",
168 | " [1., 0., 0., 0.],\n",
169 | " [0., 1., 0., 0.],\n",
170 | " [1., 0., 0., 0.],\n",
171 | " [1., 0., 0., 0.],\n",
172 | " [1., 0., 0., 0.],\n",
173 | " [1., 0., 0., 0.],\n",
174 | " [1., 0., 0., 0.],\n",
175 | " [1., 0., 0., 0.],\n",
176 | " [1., 0., 0., 0.],\n",
177 | " [0., 1., 0., 0.],\n",
178 | " [0., 1., 0., 0.],\n",
179 | " [0., 1., 0., 0.],\n",
180 | " [0., 1., 0., 0.],\n",
181 | " [0., 1., 0., 0.],\n",
182 | " [0., 0., 1., 0.],\n",
183 | " [0., 0., 1., 0.],\n",
184 | " [0., 1., 0., 0.],\n",
185 | " [0., 1., 0., 0.],\n",
186 | " [0., 1., 0., 0.],\n",
187 | " [0., 1., 0., 0.]])"
188 | ]
189 | },
190 | "execution_count": 31,
191 | "metadata": {},
192 | "output_type": "execute_result"
193 | }
194 | ],
195 | "source": [
196 | "weather_onehot.scatter_(\n",
197 | " dim=1,\n",
198 | " index=first_day[:,9].unsqueeze(1) - 1,\n",
199 | " value=1.0)"
200 | ]
201 | },
202 | {
203 | "cell_type": "markdown",
204 | "metadata": {},
205 | "source": [
206 | "## 数据连接"
207 | ]
208 | },
209 | {
210 | "cell_type": "code",
211 | "execution_count": 32,
212 | "metadata": {},
213 | "outputs": [
214 | {
215 | "data": {
216 | "text/plain": [
217 | "tensor([[ 1.0000, 1.0000, 1.0000, 0.0000, 1.0000, 0.0000, 0.0000, 6.0000,\n",
218 | " 0.0000, 1.0000, 0.2400, 0.2879, 0.8100, 0.0000, 3.0000, 13.0000,\n",
219 | " 16.0000, 1.0000, 0.0000, 0.0000, 0.0000]])"
220 | ]
221 | },
222 | "execution_count": 32,
223 | "metadata": {},
224 | "output_type": "execute_result"
225 | }
226 | ],
227 | "source": [
228 | "torch.cat((bikes[:24], weather_onehot), 1)[:1]"
229 | ]
230 | },
231 | {
232 | "cell_type": "code",
233 | "execution_count": 33,
234 | "metadata": {},
235 | "outputs": [
236 | {
237 | "data": {
238 | "text/plain": [
239 | "torch.Size([730, 4, 24])"
240 | ]
241 | },
242 | "execution_count": 33,
243 | "metadata": {},
244 | "output_type": "execute_result"
245 | }
246 | ],
247 | "source": [
248 | "daily_weather_onehot = torch.zeros(daily_bikes.shape[0], 4, daily_bikes.shape[2])\n",
249 | "daily_weather_onehot.shape"
250 | ]
251 | },
252 | {
253 | "cell_type": "code",
254 | "execution_count": 34,
255 | "metadata": {},
256 | "outputs": [
257 | {
258 | "data": {
259 | "text/plain": [
260 | "torch.Size([730, 4, 24])"
261 | ]
262 | },
263 | "execution_count": 34,
264 | "metadata": {},
265 | "output_type": "execute_result"
266 | }
267 | ],
268 | "source": [
269 | "daily_weather_onehot.scatter_(1, daily_bikes[:,9,:].long().unsqueeze(1) - 1, 1.0)#你将值减少1,因为天气情况的范围是1到4,而索引是从0开始\n",
270 | "daily_weather_onehot.shape"
271 | ]
272 | },
273 | {
274 | "cell_type": "code",
275 | "execution_count": 35,
276 | "metadata": {
277 | "collapsed": true
278 | },
279 | "outputs": [],
280 | "source": [
281 | "daily_bikes = torch.cat((daily_bikes, daily_weather_onehot), dim=1)"
282 | ]
283 | },
284 | {
285 | "cell_type": "code",
286 | "execution_count": 36,
287 | "metadata": {
288 | "collapsed": true
289 | },
290 | "outputs": [],
291 | "source": [
292 | "daily_bikes[:, 9, :] = (daily_bikes[:, 9, :] - 1.0) / 3.0"
293 | ]
294 | },
295 | {
296 | "cell_type": "markdown",
297 | "metadata": {},
298 | "source": [
299 | "## 数据缩放"
300 | ]
301 | },
302 | {
303 | "cell_type": "code",
304 | "execution_count": 37,
305 | "metadata": {
306 | "collapsed": true
307 | },
308 | "outputs": [],
309 | "source": [
310 | "temp = daily_bikes[:, 10, :]\n",
311 | "temp_min = torch.min(temp)\n",
312 | "temp_max = torch.max(temp)\n",
313 | "daily_bikes[:, 10, :] = (daily_bikes[:, 10, :] - temp_min) / (temp_max -\n",
314 | " temp_min)"
315 | ]
316 | },
317 | {
318 | "cell_type": "code",
319 | "execution_count": 38,
320 | "metadata": {
321 | "collapsed": true
322 | },
323 | "outputs": [],
324 | "source": [
325 | "temp = daily_bikes[:, 10, :]\n",
326 | "daily_bikes[:, 10, :] = (daily_bikes[:, 10, :] - torch.mean(temp)) / torch.std(temp)"
327 | ]
328 | },
329 | {
330 | "cell_type": "code",
331 | "execution_count": null,
332 | "metadata": {
333 | "collapsed": true
334 | },
335 | "outputs": [],
336 | "source": []
337 | }
338 | ],
339 | "metadata": {
340 | "kernelspec": {
341 | "display_name": "Python 3",
342 | "language": "python",
343 | "name": "python3"
344 | },
345 | "language_info": {
346 | "codemirror_mode": {
347 | "name": "ipython",
348 | "version": 3
349 | },
350 | "file_extension": ".py",
351 | "mimetype": "text/x-python",
352 | "name": "python",
353 | "nbconvert_exporter": "python",
354 | "pygments_lexer": "ipython3",
355 | "version": "3.6.2"
356 | }
357 | },
358 | "nbformat": 4,
359 | "nbformat_minor": 2
360 | }
361 |
--------------------------------------------------------------------------------
/code/chapter3/3.3.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# 3.3 文本数据"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 1,
13 | "metadata": {
14 | "collapsed": true
15 | },
16 | "outputs": [],
17 | "source": [
18 | "import torch"
19 | ]
20 | },
21 | {
22 | "cell_type": "code",
23 | "execution_count": 2,
24 | "metadata": {
25 | "collapsed": true
26 | },
27 | "outputs": [],
28 | "source": [
29 | "with open('../../data/chapter3/1342-0.txt', encoding='utf8') as f:\n",
30 | " text = f.read()"
31 | ]
32 | },
33 | {
34 | "cell_type": "code",
35 | "execution_count": 3,
36 | "metadata": {},
37 | "outputs": [
38 | {
39 | "data": {
40 | "text/plain": [
41 | "'“Impossible, Mr. Bennet, impossible, when I am not acquainted with him'"
42 | ]
43 | },
44 | "execution_count": 3,
45 | "metadata": {},
46 | "output_type": "execute_result"
47 | }
48 | ],
49 | "source": [
50 | "lines = text.split('\\n')\n",
51 | "line = lines[200]\n",
52 | "line"
53 | ]
54 | },
55 | {
56 | "cell_type": "code",
57 | "execution_count": 4,
58 | "metadata": {},
59 | "outputs": [
60 | {
61 | "data": {
62 | "text/plain": [
63 | "torch.Size([70, 128])"
64 | ]
65 | },
66 | "execution_count": 4,
67 | "metadata": {},
68 | "output_type": "execute_result"
69 | }
70 | ],
71 | "source": [
72 | "letter_tensor = torch.zeros(len(line), 128) # 128是由于ASCII的限制\n",
73 | "letter_tensor.shape"
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": 5,
79 | "metadata": {
80 | "collapsed": true
81 | },
82 | "outputs": [],
83 | "source": [
84 | "for i, letter in enumerate(line.lower().strip()):\n",
85 | " # 文本里含有双引号,不是有效的ASCII,因此在此处将其屏蔽\n",
86 | " letter_index = ord(letter) if ord(letter) < 128 else 0\n",
87 | " letter_tensor[i][letter_index] = 1"
88 | ]
89 | },
90 | {
91 | "cell_type": "code",
92 | "execution_count": 6,
93 | "metadata": {},
94 | "outputs": [
95 | {
96 | "data": {
97 | "text/plain": [
98 | "('“Impossible, Mr. Bennet, impossible, when I am not acquainted with him',\n",
99 | " ['impossible',\n",
100 | " 'mr',\n",
101 | " 'bennet',\n",
102 | " 'impossible',\n",
103 | " 'when',\n",
104 | " 'i',\n",
105 | " 'am',\n",
106 | " 'not',\n",
107 | " 'acquainted',\n",
108 | " 'with',\n",
109 | " 'him'])"
110 | ]
111 | },
112 | "execution_count": 6,
113 | "metadata": {},
114 | "output_type": "execute_result"
115 | }
116 | ],
117 | "source": [
118 | "def clean_words(input_str):\n",
119 | " punctuation = '.,;:\"!?”“_-'\n",
120 | " word_list = input_str.lower().replace('\\n',' ').split()\n",
121 | " word_list = [word.strip(punctuation) for word in word_list]\n",
122 | " return word_list\n",
123 | "words_in_line = clean_words(line)\n",
124 | "line, words_in_line"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "execution_count": 7,
130 | "metadata": {},
131 | "outputs": [
132 | {
133 | "data": {
134 | "text/plain": [
135 | "(7261, 3394)"
136 | ]
137 | },
138 | "execution_count": 7,
139 | "metadata": {},
140 | "output_type": "execute_result"
141 | }
142 | ],
143 | "source": [
144 | "word_list = sorted(set(clean_words(text)))\n",
145 | "word2index_dict = {word: i for (i, word) in enumerate(word_list)}\n",
146 | "len(word2index_dict), word2index_dict['impossible']"
147 | ]
148 | },
149 | {
150 | "cell_type": "code",
151 | "execution_count": 8,
152 | "metadata": {},
153 | "outputs": [
154 | {
155 | "name": "stdout",
156 | "output_type": "stream",
157 | "text": [
158 | " 0 3394 impossible\n",
159 | " 1 4305 mr\n",
160 | " 2 813 bennet\n",
161 | " 3 3394 impossible\n",
162 | " 4 7078 when\n",
163 | " 5 3315 i\n",
164 | " 6 415 am\n",
165 | " 7 4436 not\n",
166 | " 8 239 acquainted\n",
167 | " 9 7148 with\n",
168 | "10 3215 him\n",
169 | "torch.Size([11, 7261])\n"
170 | ]
171 | }
172 | ],
173 | "source": [
174 | "word_tensor = torch.zeros(len(words_in_line), len(word2index_dict))\n",
175 | "for i, word in enumerate(words_in_line):\n",
176 | " word_index = word2index_dict[word]\n",
177 | " word_tensor[i][word_index] = 1\n",
178 | " print('{:2} {:4} {}'.format(i, word_index, word))\n",
179 | "\n",
180 | "print(word_tensor.shape)"
181 | ]
182 | },
183 | {
184 | "cell_type": "code",
185 | "execution_count": null,
186 | "metadata": {
187 | "collapsed": true
188 | },
189 | "outputs": [],
190 | "source": []
191 | }
192 | ],
193 | "metadata": {
194 | "kernelspec": {
195 | "display_name": "Python 3",
196 | "language": "python",
197 | "name": "python3"
198 | },
199 | "language_info": {
200 | "codemirror_mode": {
201 | "name": "ipython",
202 | "version": 3
203 | },
204 | "file_extension": ".py",
205 | "mimetype": "text/x-python",
206 | "name": "python",
207 | "nbconvert_exporter": "python",
208 | "pygments_lexer": "ipython3",
209 | "version": "3.6.2"
210 | }
211 | },
212 | "nbformat": 4,
213 | "nbformat_minor": 2
214 | }
215 |
--------------------------------------------------------------------------------
/code/chapter3/3.4.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# 3.4 图像"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 14,
13 | "metadata": {},
14 | "outputs": [],
15 | "source": [
16 | "import numpy as np\n",
17 | "import torch\n",
18 | "torch.set_printoptions(edgeitems=2, threshold=50)"
19 | ]
20 | },
21 | {
22 | "cell_type": "code",
23 | "execution_count": 15,
24 | "metadata": {},
25 | "outputs": [
26 | {
27 | "data": {
28 | "text/plain": [
29 | "(720, 1280, 3)"
30 | ]
31 | },
32 | "execution_count": 15,
33 | "metadata": {},
34 | "output_type": "execute_result"
35 | }
36 | ],
37 | "source": [
38 | "import imageio\n",
39 | "img_arr = imageio.imread('../../data/chapter3/image-dog/bobby.jpg')\n",
40 | "img_arr.shape"
41 | ]
42 | },
43 | {
44 | "cell_type": "code",
45 | "execution_count": 16,
46 | "metadata": {},
47 | "outputs": [],
48 | "source": [
49 | "img = torch.from_numpy(img_arr)\n",
50 | "out = torch.transpose(img, 0, 2)"
51 | ]
52 | },
53 | {
54 | "cell_type": "markdown",
55 | "metadata": {},
56 | "source": [
57 | "# 归一化"
58 | ]
59 | },
60 | {
61 | "cell_type": "code",
62 | "execution_count": 17,
63 | "metadata": {},
64 | "outputs": [],
65 | "source": [
66 | "batch_size = 100\n",
67 | "batch = torch.zeros(100, 3, 256, 256, dtype=torch.uint8)"
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "execution_count": 20,
73 | "metadata": {},
74 | "outputs": [],
75 | "source": [
76 | "import os\n",
77 | "\n",
78 | "data_dir = '../../data/chapter3/image-cats/'\n",
79 | "filenames = [name for name in os.listdir(data_dir) if os.path.splitext(name)[-1] == '.png']\n",
80 | "for i, filename in enumerate(filenames):\n",
81 | " img_arr = imageio.imread('../../data/chapter3/image-cats/' + filename)\n",
82 | " img_arr = img_arr[:,:,0:3]\n",
83 | " batch[i] = torch.transpose(torch.from_numpy(img_arr), 0, 2)"
84 | ]
85 | },
86 | {
87 | "cell_type": "code",
88 | "execution_count": 21,
89 | "metadata": {},
90 | "outputs": [],
91 | "source": [
92 | "batch = batch.float()\n",
93 | "batch /= 255.0"
94 | ]
95 | },
96 | {
97 | "cell_type": "code",
98 | "execution_count": 22,
99 | "metadata": {},
100 | "outputs": [],
101 | "source": [
102 | "n_channels = batch.shape[1]\n",
103 | "for c in range(n_channels):\n",
104 | " mean = torch.mean(batch[:, c])\n",
105 | " std = torch.std(batch[:, c])\n",
106 | " batch[:, c] = (batch[:, c] - mean) / std"
107 | ]
108 | },
109 | {
110 | "cell_type": "code",
111 | "execution_count": null,
112 | "metadata": {},
113 | "outputs": [],
114 | "source": []
115 | }
116 | ],
117 | "metadata": {
118 | "kernelspec": {
119 | "display_name": "Python 3",
120 | "language": "python",
121 | "name": "python3"
122 | },
123 | "language_info": {
124 | "codemirror_mode": {
125 | "name": "ipython",
126 | "version": 3
127 | },
128 | "file_extension": ".py",
129 | "mimetype": "text/x-python",
130 | "name": "python",
131 | "nbconvert_exporter": "python",
132 | "pygments_lexer": "ipython3",
133 | "version": "3.6.8"
134 | }
135 | },
136 | "nbformat": 4,
137 | "nbformat_minor": 2
138 | }
139 |
--------------------------------------------------------------------------------
/code/chapter3/3.5.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# 3.5 体积数据"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 3,
13 | "metadata": {},
14 | "outputs": [
15 | {
16 | "name": "stdout",
17 | "output_type": "stream",
18 | "text": [
19 | "Reading DICOM (examining files): 1/99 files (1.0%99/99 files (100.0%)\n",
20 | " Found 1 correct series.\n",
21 | "Reading DICOM (loading data): 55/99 (55.699/99 (100.0%)\n"
22 | ]
23 | },
24 | {
25 | "data": {
26 | "text/plain": [
27 | "(99, 512, 512)"
28 | ]
29 | },
30 | "execution_count": 3,
31 | "metadata": {},
32 | "output_type": "execute_result"
33 | }
34 | ],
35 | "source": [
36 | "import imageio\n",
37 | "import torch\n",
38 | "dir_path = \"../../data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083\" \n",
39 | "vol_arr = imageio.volread(dir_path, 'DICOM') \n",
40 | "vol_arr.shape"
41 | ]
42 | },
43 | {
44 | "cell_type": "code",
45 | "execution_count": 4,
46 | "metadata": {},
47 | "outputs": [
48 | {
49 | "data": {
50 | "text/plain": [
51 | "torch.Size([1, 512, 512, 99])"
52 | ]
53 | },
54 | "execution_count": 4,
55 | "metadata": {},
56 | "output_type": "execute_result"
57 | }
58 | ],
59 | "source": [
60 | "vol = torch.from_numpy(vol_arr).float() \n",
61 | "vol = torch.transpose(vol, 0, 2) \n",
62 | "vol = torch.unsqueeze(vol, 0)\n",
63 | "vol.shape"
64 | ]
65 | },
66 | {
67 | "cell_type": "code",
68 | "execution_count": null,
69 | "metadata": {},
70 | "outputs": [],
71 | "source": []
72 | }
73 | ],
74 | "metadata": {
75 | "kernelspec": {
76 | "display_name": "Python 3",
77 | "language": "python",
78 | "name": "python3"
79 | },
80 | "language_info": {
81 | "codemirror_mode": {
82 | "name": "ipython",
83 | "version": 3
84 | },
85 | "file_extension": ".py",
86 | "mimetype": "text/x-python",
87 | "name": "python",
88 | "nbconvert_exporter": "python",
89 | "pygments_lexer": "ipython3",
90 | "version": "3.6.8"
91 | }
92 | },
93 | "nbformat": 4,
94 | "nbformat_minor": 2
95 | }
96 |
--------------------------------------------------------------------------------
/code/chapter5/5.3.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# 5.3 nn的子类"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 1,
13 | "metadata": {},
14 | "outputs": [],
15 | "source": [
16 | "%matplotlib inline\n",
17 | "import numpy as np\n",
18 | "import torch\n",
19 | "import torch.optim as optim\n",
20 | "import torch.nn as nn\n",
21 | "\n",
22 | "torch.set_printoptions(edgeitems=2)"
23 | ]
24 | },
25 | {
26 | "cell_type": "markdown",
27 | "metadata": {},
28 | "source": [
29 | "## `nn.Sequential`"
30 | ]
31 | },
32 | {
33 | "cell_type": "code",
34 | "execution_count": 2,
35 | "metadata": {},
36 | "outputs": [
37 | {
38 | "data": {
39 | "text/plain": [
40 | "Sequential(\n",
41 | " (0): Linear(in_features=1, out_features=11, bias=True)\n",
42 | " (1): Tanh()\n",
43 | " (2): Linear(in_features=11, out_features=1, bias=True)\n",
44 | ")"
45 | ]
46 | },
47 | "execution_count": 2,
48 | "metadata": {},
49 | "output_type": "execute_result"
50 | }
51 | ],
52 | "source": [
53 | "seq_model = nn.Sequential(\n",
54 | " nn.Linear(1, 11), # 11的选取是任意的\n",
55 | " nn.Tanh(),\n",
56 | " nn.Linear(11, 1)) # 这里的11需匹配上一层的输出\n",
57 | "seq_model"
58 | ]
59 | },
60 | {
61 | "cell_type": "code",
62 | "execution_count": 3,
63 | "metadata": {},
64 | "outputs": [
65 | {
66 | "data": {
67 | "text/plain": [
68 | "Sequential(\n",
69 | " (hidden_linear): Linear(in_features=1, out_features=12, bias=True)\n",
70 | " (hidden_activation): Tanh()\n",
71 | " (output_linear): Linear(in_features=12, out_features=1, bias=True)\n",
72 | ")"
73 | ]
74 | },
75 | "execution_count": 3,
76 | "metadata": {},
77 | "output_type": "execute_result"
78 | }
79 | ],
80 | "source": [
81 | "from collections import OrderedDict\n",
82 | "namedseq_model = nn.Sequential(OrderedDict([\n",
83 | " ('hidden_linear', nn.Linear(1, 12)),\n",
84 | " ('hidden_activation', nn.Tanh()),\n",
85 | " ('output_linear', nn.Linear(12 , 1))\n",
86 | "]))\n",
87 | "namedseq_model"
88 | ]
89 | },
90 | {
91 | "cell_type": "markdown",
92 | "metadata": {},
93 | "source": [
94 | "## 自定义"
95 | ]
96 | },
97 | {
98 | "cell_type": "code",
99 | "execution_count": 4,
100 | "metadata": {},
101 | "outputs": [
102 | {
103 | "data": {
104 | "text/plain": [
105 | "SubclassModel(\n",
106 | " (hidden_linear): Linear(in_features=1, out_features=13, bias=True)\n",
107 | " (hidden_activation): Tanh()\n",
108 | " (output_linear): Linear(in_features=13, out_features=1, bias=True)\n",
109 | ")"
110 | ]
111 | },
112 | "execution_count": 4,
113 | "metadata": {},
114 | "output_type": "execute_result"
115 | }
116 | ],
117 | "source": [
118 | "class SubclassModel(nn.Module):\n",
119 | " def __init__(self):\n",
120 | " super().__init__()\n",
121 | " self.hidden_linear = nn.Linear(1, 13)\n",
122 | " self.hidden_activation = nn.Tanh()\n",
123 | " self.output_linear = nn.Linear(13, 1)\n",
124 | " def forward(self, input):\n",
125 | " hidden_t = self.hidden_linear(input)\n",
126 | " activated_t = self.hidden_activation(hidden_t)\n",
127 | " output_t = self.output_linear(activated_t)\n",
128 | " return output_t\n",
129 | " \n",
130 | "subclass_model = SubclassModel()\n",
131 | "subclass_model"
132 | ]
133 | },
134 | {
135 | "cell_type": "code",
136 | "execution_count": 5,
137 | "metadata": {},
138 | "outputs": [
139 | {
140 | "name": "stdout",
141 | "output_type": "stream",
142 | "text": [
143 | "seq\n",
144 | "0.weight torch.Size([11, 1]) 11\n",
145 | "0.bias torch.Size([11]) 11\n",
146 | "2.weight torch.Size([1, 11]) 11\n",
147 | "2.bias torch.Size([1]) 1\n",
148 | "\n",
149 | "namedseq\n",
150 | "hidden_linear.weight torch.Size([12, 1]) 12\n",
151 | "hidden_linear.bias torch.Size([12]) 12\n",
152 | "output_linear.weight torch.Size([1, 12]) 12\n",
153 | "output_linear.bias torch.Size([1]) 1\n",
154 | "\n",
155 | "subclass\n",
156 | "hidden_linear.weight torch.Size([13, 1]) 13\n",
157 | "hidden_linear.bias torch.Size([13]) 13\n",
158 | "output_linear.weight torch.Size([1, 13]) 13\n",
159 | "output_linear.bias torch.Size([1]) 1\n",
160 | "\n"
161 | ]
162 | }
163 | ],
164 | "source": [
165 | "for type_str, model in [('seq', seq_model), ('namedseq', namedseq_model),\n",
166 | " ('subclass', subclass_model)]:\n",
167 | " print(type_str)\n",
168 | " for name_str, param in model.named_parameters():\n",
169 | " print(\"{:21} {:19} {}\".format(name_str, str(param.shape), param.numel())) \n",
170 | " print()"
171 | ]
172 | },
173 | {
174 | "cell_type": "code",
175 | "execution_count": 6,
176 | "metadata": {},
177 | "outputs": [
178 | {
179 | "data": {
180 | "text/plain": [
181 | "SubclassFunctionalModel(\n",
182 | " (hidden_linear): Linear(in_features=1, out_features=14, bias=True)\n",
183 | " (output_linear): Linear(in_features=14, out_features=1, bias=True)\n",
184 | ")"
185 | ]
186 | },
187 | "execution_count": 6,
188 | "metadata": {},
189 | "output_type": "execute_result"
190 | }
191 | ],
192 | "source": [
193 | "class SubclassFunctionalModel(nn.Module):\n",
194 | " def __init__(self):\n",
195 | " super().__init__()\n",
196 | " self.hidden_linear = nn.Linear(1, 14)\n",
197 | " # 去掉了nn.Tanh()\n",
198 | " self.output_linear = nn.Linear(14, 1)\n",
199 | " \n",
200 | " def forward(self, input):\n",
201 | " hidden_t = self.hidden_linear(input)\n",
202 | " activated_t = torch.tanh(hidden_t) # nn.Tanh对应的函数\n",
203 | " output_t = self.output_linear(activated_t)\n",
204 | " return output_t\n",
205 | " \n",
206 | "func_model = SubclassFunctionalModel()\n",
207 | "func_model"
208 | ]
209 | },
210 | {
211 | "cell_type": "code",
212 | "execution_count": null,
213 | "metadata": {},
214 | "outputs": [],
215 | "source": []
216 | }
217 | ],
218 | "metadata": {
219 | "kernelspec": {
220 | "display_name": "Python [conda env:py36]",
221 | "language": "python",
222 | "name": "conda-env-py36-py"
223 | },
224 | "language_info": {
225 | "codemirror_mode": {
226 | "name": "ipython",
227 | "version": 3
228 | },
229 | "file_extension": ".py",
230 | "mimetype": "text/x-python",
231 | "name": "python",
232 | "nbconvert_exporter": "python",
233 | "pygments_lexer": "ipython3",
234 | "version": "3.6.2"
235 | }
236 | },
237 | "nbformat": 4,
238 | "nbformat_minor": 2
239 | }
240 |
--------------------------------------------------------------------------------
/data/chapter2/ourpoints.hdf5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter2/ourpoints.hdf5
--------------------------------------------------------------------------------
/data/chapter2/ourpoints.t:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter2/ourpoints.t
--------------------------------------------------------------------------------
/data/chapter3/bobby.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/bobby.jpg
--------------------------------------------------------------------------------
/data/chapter3/image-cats/cat1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/image-cats/cat1.png
--------------------------------------------------------------------------------
/data/chapter3/image-cats/cat2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/image-cats/cat2.png
--------------------------------------------------------------------------------
/data/chapter3/image-cats/cat3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/image-cats/cat3.png
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000000.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000000.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000001.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000001.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000002.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000002.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000003.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000003.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000004.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000004.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000005.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000005.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000006.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000006.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000007.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000007.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000008.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000008.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000009.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000009.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000010.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000010.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000011.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000011.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000012.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000012.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000013.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000013.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000014.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000014.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000015.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000015.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000016.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000016.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000017.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000017.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000018.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000018.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000019.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000019.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000020.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000020.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000021.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000021.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000022.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000022.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000023.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000023.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000024.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000024.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000025.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000025.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000026.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000026.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000027.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000027.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000028.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000028.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000029.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000029.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000030.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000030.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000031.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000031.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000032.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000032.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000033.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000033.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000034.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000034.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000035.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000035.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000036.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000036.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000037.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000037.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000038.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000038.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000039.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000039.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000040.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000040.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000041.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000041.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000042.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000042.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000043.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000043.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000044.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000044.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000045.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000045.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000046.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000046.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000047.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000047.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000048.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000048.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000049.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000049.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000050.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000050.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000051.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000051.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000052.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000052.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000053.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000053.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000054.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000054.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000055.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000055.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000056.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000056.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000057.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000057.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000058.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000058.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000059.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000059.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000060.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000060.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000061.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000061.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000062.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000062.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000063.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000063.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000064.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000064.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000065.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000065.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000066.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000066.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000067.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000067.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000068.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000068.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000069.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000069.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000070.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000070.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000071.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000071.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000072.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000072.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000073.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000073.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000074.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000074.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000075.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000075.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000076.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000076.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000077.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000077.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000078.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000078.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000079.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000079.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000080.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000080.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000081.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000081.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000082.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000082.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000083.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000083.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000084.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000084.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000085.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000085.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000086.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000086.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000087.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000087.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000088.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000088.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000089.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000089.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000090.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000090.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000091.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000091.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000092.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000092.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000093.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000093.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000094.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000094.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000095.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000095.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000096.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000096.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000097.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000097.dcm
--------------------------------------------------------------------------------
/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000098.dcm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083/000098.dcm
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/.nojekyll
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Deep-Learning-with-PyTorch-Chinese
2 |
3 | 本项目([网页版传送门](https://tangshusen.me/Deep-Learning-with-PyTorch-Chinese))将PyTorch官方书籍[《Deep learning with PyTorch》(基本摘录版)](https://pytorch.org/deep-learning-with-pytorch)翻译成中文并给出全书可运行的相关代码。
4 |
5 | [This project](https://tangshusen.me/Deep-Learning-with-PyTorch-Chinese) translates the PyTorch official book "Deep learning with PyTorch" (essential excerpt version) into Chinese.
6 |
7 |
8 |
9 |

10 |
11 |
12 | ## 1. 书籍简介
13 | 自 2016 年诞生以来,PyTorch 已经成为当今最火热的深度学习框架之一。最近,官方权威的 PyTorch 教程书《Deep learning with PyTorch》终于问世了,消息一出就获得巨佬 Yann LeCun 力荐,是入门PyTorch及深度学习的绝佳教材。
14 |
15 |

16 |
17 |
18 | 需要注意的是,[PyTorch官网提供的PDF](https://pytorch.org/deep-learning-with-pytorch)是基本摘录版(Essential Excerpts),共141页,内容包括以下五个部分:
19 | 1. 深度学习与PyTorch简介
20 | 2. 从一个张量开始
21 | 3. 使用张量表示真实数据
22 | 4. 学习机制
23 | 5. 使用神经网络拟合数据
24 |
25 | 因此可作为快速入门PyTorch的教程。此书完整版目前也可免费预览,[传送门](https://www.manning.com/books/deep-learning-with-pytorch)。
26 |
27 | ## 2. 项目简介
28 | 本项目将原书翻译成中文并且给出可运行的相关代码。
29 |
30 | 本[仓库](https://github.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese)主要包含code和docs两个文件夹(外加一些数据存放在data中)。其中code文件夹就是每章相关jupyter notebook代码;docs文件夹就是markdown格式的《Deep learning with PyTorch》(基本摘录版)书中的相关内容的中文翻译,然后利用[docsify](https://docsify.js.org/#/zh-cn/)将网页文档部署到[GitHub Pages](https://tangshusen.me/Deep-Learning-with-PyTorch-Chinese)上。欢迎对本项目做出贡献或提出issue。
31 |
32 |
33 | ## 3. 使用方法
34 |
35 | 本项目面向对PyTorch感兴趣,尤其是想快速入门PyTorch的童鞋。本项目并不要求你有任何深度学习或者机器学习的背景知识,你只需了解基础的数学和编程,如基础的线性代数、微分和概率,以及基础的Python编程。
36 |
37 | 本仓库的文档包含一些latex公式,但github的markdown原生是不支持公式显示的,而docs文件夹已经利用[docsify](https://docsify.js.org/#/zh-cn/)被部署到了GitHub Pages上,所以你可以方便地访问[本项目网页版](https://tangshusen.me/Deep-Learning-with-PyTorch-Chinese)。如果你想跑一下相关代码的话需要把本项目clone下来,然后运行code文件夹下相关代码。
38 |
39 | 由于本项目所翻译的是基本摘录版,仅141页,所以适合快速入门PyTorch。如果你想对PyTorch以及深度学习(例如计算机视觉、自然语言处理等)有更深入的学习,可能还需要更多的资料,感兴趣的可以参考我的另一个项目[Dive-into-DL-PyTorch](http://tangshusen.me/Dive-into-DL-PyTorch/)。
40 |
41 |
42 | ## 4. 目录
43 | * [简介]()
44 | * [1. 深度学习与PyTorch简介](chapter1/1.0.md)
45 | * [1.1 什么是PyTorch](chapter1/1.1.md)
46 | * [1.2 这本书讲了什么](chapter1/1.2.md)
47 | * [1.3 为什么使用PyTorch](chapter1/1.3.md)
48 | * [1.4 PyTorch包含的组件](chapter1/1.4.md)
49 | * [2. 从张量开始](chapter2/2.0.md)
50 | * [2.1 张量基础](chapter2/2.1.md)
51 | * [2.2 张量与存储](chapter2/2.2.md)
52 | * [2.3 尺寸、存储偏移与步长](chapter2/2.3.md)
53 | * [2.4 数据类型](chapter2/2.4.md)
54 | * [2.5 索引张量](chapter2/2.5.md)
55 | * [2.6 与NumPy的互通性](chapter2/2.6.md)
56 | * [2.7 序列化张量](chapter2/2.8.md)
57 | * [2.8 将张量转移到GPU上运行](chapter2/2.8.md)
58 | * [2.9 张量API](chapter2/2.9.md)
59 | * [3. 使用张量表示真实数据](chapter3/3.0.md)
60 | * [3.1 表格数据](chapter3/3.1.md)
61 | * [3.2 时间序列](chapter3/3.2.md)
62 | * [3.3 文本数据](chapter3/3.3.md)
63 | * [3.4 图像数据](chapter3/3.4.md)
64 | * [3.5 体积数据](chapter3/3.5.md)
65 | * [4. 学习机制](chapter4/4.0.md)
66 | * [4.1 学习就是参数估计](chapter4/4.1.md)
67 | * [4.2 PyTorch自动求导](chapter4/4.2.md)
68 | * [5. 使用神经网络拟合数据](chapter5/5.0.md)
69 | * [5.1 神经元](chapter5/5.1.md)
70 | * [5.2 PyTorch的nn模块](chapter5/5.2.md)
71 | * [5.3 nn的子类](chapter5/5.3.md)
72 |
73 |
74 | ## 5. 声明
75 |
76 | * 译者纯粹出于学习目的与个人兴趣而进行翻译,不追求任何经济利益;
77 | * 本项目仅限于学习研究目的的使用,译者保留对此项目的署名权,任何转载必须注明出处,但不得用于任何商业用途;
78 | * 使用本项目对原著的侵权行为或者违反知识产权保护法的任何行为,与译者无关;
79 | * 有能力阅读英文书籍者请阅读原版或购买完整版书籍。
80 |
81 | ## LICENSE
82 | CC BY-NC(署名-非商业性使用)4.0
83 |
84 |
85 |
--------------------------------------------------------------------------------
/docs/_sidebar.md:
--------------------------------------------------------------------------------
1 | * [简介]()
2 | * [1. 深度学习与PyTorch简介](chapter1/1.0.md)
3 | * [1.1 什么是PyTorch](chapter1/1.1.md)
4 | * [1.2 这本书讲了什么](chapter1/1.2.md)
5 | * [1.3 为什么使用PyTorch](chapter1/1.3.md)
6 | * [1.4 PyTorch包含的组件](chapter1/1.4.md)
7 | * [2. 从张量开始](chapter2/2.0.md)
8 | * [2.1 张量基础](chapter2/2.1.md)
9 | * [2.2 张量与存储](chapter2/2.2.md)
10 | * [2.3 尺寸、存储偏移与步长](chapter2/2.3.md)
11 | * [2.4 数据类型](chapter2/2.4.md)
12 | * [2.5 索引张量](chapter2/2.5.md)
13 | * [2.6 与NumPy的互通性](chapter2/2.6.md)
14 | * [2.7 序列化张量](chapter2/2.7.md)
15 | * [2.8 将张量转移到GPU上运行](chapter2/2.8.md)
16 | * [2.9 张量API](chapter2/2.9.md)
17 | * [3. 使用张量表示真实数据](chapter3/3.0.md)
18 | * [3.1 表格数据](chapter3/3.1.md)
19 | * [3.2 时间序列](chapter3/3.2.md)
20 | * [3.3 文本数据](chapter3/3.3.md)
21 | * [3.4 图像数据](chapter3/3.4.md)
22 | * [3.5 体积数据](chapter3/3.5.md)
23 | * [4. 学习机制](chapter4/4.0.md)
24 | * [4.1 学习就是参数估计](chapter4/4.1.md)
25 | * [4.2 PyTorch自动求导](chapter4/4.2.md)
26 | * [5. 使用神经网络拟合数据](chapter5/5.0.md)
27 | * [5.1 神经元](chapter5/5.1.md)
28 | * [5.2 PyTorch的nn模块](chapter5/5.2.md)
29 | * [5.3 nn的子类](chapter5/5.3.md)
30 |
--------------------------------------------------------------------------------
/docs/chapter1/1.0.md:
--------------------------------------------------------------------------------
1 | # 1 深度学习与PyTorch简介
2 |
3 | 本章将介绍
4 |
5 | * 这本书将会教给你什么?
6 |
7 | * PyTorch作为构建深度学习项目库所扮演的角色
8 |
9 | * PyTorch的长处和短处
10 |
11 | * 实现样例所需的硬件
12 |
13 | --------------------------------------------
14 |
15 | 我们正处在一个激动人心的时代。计算机可以做的事每周都在改变。仅仅就数年,那些被我们所认为的高层次认知的任务正在逐渐被接近超人水平的机器所解决。类似于用通俗易懂的语言来描述图像、玩复杂的策略类游戏和通过放射学检查诊断肿瘤的这一系列任务正在统统被计算机所解决。更令人印象深刻的是计算机获得了通过样本而不是人工编码规则解决问题的能力。
16 |
17 | 说机器正在学习人类意义上"思考"是不准确的。相反,一般的算法能够非常有效地逼近复杂的非线性拟合过程。从某种程度上来说,我们正在学习的人工智能,从主观上讲,是一个经常与自我意识(self-awareness)混为一谈的概念,但是解决这类问题并不需要自我意识。到头来,这种计算机智能的问题甚至没那么重要,正如计算机科学先驱Edsger W. Dijkstra在"计算机科学的威胁"所说:
18 |
19 | Alan M. Turing认为,要问机器是否可以思考,就相当于问潜艇是否可以游泳。
20 | > Alan M. Turing thought about . . . the question of whether Machines Can Think, a question . . . about as relevant as the question of whether Submarines Can Swim.
21 |
22 | 我们正在讨论的算法属于深度学习的类别,它在基本的样本上对被称为深度神经网络的数学实体(mathematical entities)进行训练。深度学习利用大量数据拟合复杂的函数,这些函数的输入和输出差别很大,例如输入图像然后输出对输入图像的一行描述文本;又例如输入手写的剧本然后输出朗诵语音;或者更简单点,这些函数将金毛猎犬的图像和代表金毛猎犬存在的标志相互联系起来。这些能力使得开发人员能够创建一些程序,这些程序的功能在之前是人类所独有的。
--------------------------------------------------------------------------------
/docs/chapter1/1.1.md:
--------------------------------------------------------------------------------
1 | # 1.1 什么是PyTorch
2 |
3 | PyTorch是帮助和促进我们构建深度学习项目的一个库。它强调灵活性并允许我们使用熟悉的Python格式来表达深度学习模型。PyTorch的易用性使得其很早便被研究社区所接纳,并且在官方发布后的这几年里,它已发展成为适用于广泛应用的最杰出的深度学习工具之一。
4 |
5 | PyTorch提供了一个核心数据结构——Tensor,一个与NumPy数组非常相似的多维数组。在此基础上,为了轻松实现并运行一个项目,或者设计和训练一个新的神经网络结构,Tensor内部实现了一系列功能。Tensor可用于加速数学运算(需要软硬件搭配得当),并且PyTorch内置了可用于分布式训练、高效数据加载的函数包,以及大量常用的深度学习函数。
6 |
7 | 正如Python用于编程一样,PyTorch不仅是一个极好的入门深度学习的工具,也是一个在专业环境下用于现实世界中高水平作业的工具。
8 |
9 | 我们相信PyTorch将会是你学习的第一款深度学习库。是否是最后一款,这将由你自己决定。
--------------------------------------------------------------------------------
/docs/chapter1/1.2.md:
--------------------------------------------------------------------------------
1 | # 1.2 这本书讲了什么
2 |
3 | 本书旨在为熟悉Python并愿意使用PyTorch来构建深度学习项目的软件工程师、数据科学家和有兴趣的学生提供一个入门的切入点。为此,我们采取动手实战的方式。我们十分鼓励在学习本书的同时随时准备好使用计算机,以便亲自动手体验相关案例,并继续做更进一步的探索。
4 |
5 | 尽管我们强调动手实践,但是我们还认为本书还提供了对基础深度学习工具(如PyTorch)的一种简单直接的介绍,而不只是获得新技术技能的方式。这也是为新一代的科学家、工程师和从业人员配备工具方面的工作迈出的一步,这些工具将成为未来几十年许多软件项目的基础。
6 |
7 | 为了通俗易懂的理解书中的大多数内容,你需要具备两项条件:
8 |
9 | * 一些Python的编程经验,但不需要有任何的压力,仅仅需要掌握常见的Python数据类型、类、和浮点数等相关知识;
10 |
11 | * 一颗愿意潜心和动手的心。跟着书中的知识动手实践会使得学习变得更加容易。
12 |
13 | 深度学习是一个庞大的学科领域。在这本书里我们只会涉及该领域中的一小部分,使用PyTorch构建一些小规模的项目。大多的项目示例只会用到2D和3D图像数据集的处理。我们强调对PyTorch的实战,希望帮助读者打好足够的基础,从而能够利用深度学习来解决现实问题或在文献研究中探索新模型。一个很棒的关于深度学习最新研究的论文预印版发表网站是ArXiV,地址https://arxiv.org。
--------------------------------------------------------------------------------
/docs/chapter1/1.3.md:
--------------------------------------------------------------------------------
1 | # 1.3 为什么使用PyTorch
2 |
3 | 正如我们之前所说,通过给模型输送数据的方式,深度学习可以执行各种复杂的任务,例如机器翻译、玩策略游戏以及识别混乱场景中的目标物。但是想要将这些实践应用落地就需要一个灵活地工具以便于可以应对各种不同的场景和尽可能提高效率,以及在较短时间内完成对大量数据的训练。你也需要用训练好的网络在未知输入的情况下顺利得到正确输出。在本节中,我们来看看决定使用PyTorch的一些原因。
4 |
5 | PyTorch由于其简单性因此很容易被推荐。许多研究员和从业者都认为PyTorch易于学习、使用、扩展功能和调试。尽管PyTorch有一些注意事项(和任何复杂的领域一样),但是对于任何有过Python编程经验的开发的者来说,使用PyTorch会有种非常熟悉的感觉。
6 |
7 | 对于那些熟悉NumPy数组的使用者,PyTorch中的Tensor类会变得非常相似。PyTorch感觉就像是能够在GPU上运行并且带有自动求导功能的NumPy,这使得PyTorch非常适合于深度学习中的反向传播。
8 |
9 | Tensor API使得与深度学习相关类的其他功能不那么引人注目;用户大多可以假装这些功能不存在,直到需要它们为止。
10 |
11 | PyTorch的设计理念是强大的表达能力,它允许开发人员在实现复杂模型的同时避免增加不必要的复杂性,PyTorch库(library)并不是框架(framework)!在深度学习领域,PyTorch可以说是最容易将想法无缝翻译为Python代码的深度学习库。因此,PyTorch已经广泛应用于各种研究,国际会议的高引用率证明了这一点。
12 |
13 | > 在会议ICLR 2019上,PyTorch在252篇论文中被引用,比去年的87篇有所增加,与TensorFlow在266篇论文中的引用水平相同。
14 |
15 | PyTorch也能很好的完成从研发到生产这一过程。尽管PyTorch最初专注于学术研究领域,但它也配备了高性能的C++运行引擎以至于用户可以不必依赖Python来部署模型,并且可以在摆脱Python运行机制的限制下保留PyTorch的大部分灵活性。
16 |
17 | 当然,声称易用性和高性能是微不足道的。我们相信当你精读完这本书,你一定会认同我们的观点。
18 |
19 | ## 1.3.1 深度学习的革命
20 |
21 | 在这一节中,我们将回顾一下为PyTorch适合深度学习工具的当前和历史环境提供一些背景信息。
22 |
23 | 直到2000年代末,广泛使用“机器学习”系统还是非常依赖于特征工程(feature engineering)。特征是由输入的数据转换而来,其产生的数值特征有助于后续算法(例如分类器)在面对新数据时获得正确的结果。特征工程的目的是获取原始数据,并提取出原始数据的表示(representation),这种表示可以提供给算法以解决问题。例如,要在手写数字图像中把0和1区分开,你可能需要使用一组过滤器(filter)来预估图像上边缘的方向并训练一个分类器,之后给定一个边缘方向的分布,分类器就可以预测出准确的数字。其他有用的特征也可能是零、八或两个环中的两个封闭圆的数量。
24 |
25 | 不同的是,深度学习从原始数据中自动学习特征并成功地完成任务。在区分1和0的例子中,通过迭代不断查看样本和目标标签对,可以在训练过程中不断完善过滤器。这并不是说特性工程在深度学习中不重要,开发人员通常需要将某种形式的知识(特征)注入到学习系统中。神经网络能够根据样本提取数据并取出有价值的特征,这正是深度学习如此强大的原因。深度学习实践者的重点不是如何手工提取这些特征,而是思考构建一个数学模型架构使其能够从训练数据中自动地提取特征。通常,这些自动提取的特征比手工提取的特征要更好!正如其他许多颠覆性技术一样,这项技术也导致了观念的改变。
26 |
27 | 在下图1.1左侧,研发者忙于定义特征工程并提供学习的算法,模型最终的效果取决于研发者所提取特征的表征能力。右侧采用深度学习,直接将原始数据输入给算法,基于优化算法自动提取特征,模型最终的效果取决于研发者根据目标所用的算法性能。
28 |
29 |
30 |

31 |
32 | 图1.1 深度学习带来的视角变化
33 |
34 | ## 1.3.2 即时执行和延迟执行
35 |
36 | 不同深度学习库的一个关键区别在于是即时执行还是延迟执行。PyTorch的易用性很大程度上是因为它如何实现即时执行,因此我们在这里简要介绍一下。
37 |
38 | 首先看一个表示勾股定理的式子$\sqrt{a^2 + b^2}$,如果需要执行此表达式,你需要定义两个变量a和b,Python实现过程如下:
39 |
40 | ``` python
41 | a = 3
42 | b = 4
43 | c = (a ** 2 + b ** 2) ** 0.5
44 | c
45 | ```
46 | 输出:
47 | ```
48 | 5.0
49 | ```
50 |
51 | 像这样获取输入值后得到输出值(c)的过程就是即时执行。PyTorch就像普通的Python程序一样,默认执行方式为即时执行(在PyTorch文档中称为Eager Mode)。即时执行非常有用,因为如果在执行某个表达式时出现错误,Python的解释器、调试器或者其他类似的工具都能够直接访问到相关的Python对象,并且在执行出错的地方会直接抛出异常。
52 |
53 | 另外,你甚至可以在知道输入是什么之前定义勾股表达式,并在输入可用时使用该定义生成输出。您定义的可调用函数可以在以后与各种输入重复使用。比如像这样:
54 |
55 | ```python
56 | p = lambda a,b: (a**2 + b**2) ** 0.5
57 | p(1,2)
58 | ```
59 | 输出:
60 | ```
61 | 2.23606797749979
62 | ```
63 | ```python
64 | p(3,4)
65 | ```
66 | 输出:
67 | ```
68 | 5.0
69 | ```
70 | 在第二个例子中,你定义了一系列需要执行的操作,产生了一个输出函数(p)。然而直到你给定了具体的输入,这些操作才会执行,这就是延迟执行的例子。延迟执行意味着在调用函数时会引发大多数异常,而不是在函数定义时。对于普通的Python程序(正如你看到的这样)来说,这种实现方式很不错。这是因为在程序发生错误时,解释器和调试器能够完全访问到Python的状态。
71 |
72 | 然而,如果我们使用具有大量运算符重载的专用类,并且允许那些即时执行的操作推迟到后台运行,情况就会变得复杂棘手。
73 |
74 | 这些专用类看上去可能长这个样子:
75 |
76 | ```python
77 | a = InputParameterPlaceholder()
78 | b = InputParameterPlaceholder()
79 | c = (a**2 + b**2) ** 0.5
80 | callable(c)
81 | ```
82 | 输出:
83 | ```
84 | True
85 | ```
86 | ```python
87 | c(3, 4)
88 | ```
89 | 输出:
90 | ```
91 | 5.0
92 | ```
93 |
94 | 通常,在采用上述这种函数定义形式的库中,对a和b求平方、相加再取平方根的操作不会被记录为高级的Python字节码。相反,这些库更倾向于将表达式编译成静态计算图(包含基本操作的图),这种方式相比于纯Python代码的形式可能会有一些优势(例如为了性能将数学公式直接编译为机器代码)。
95 |
96 | 事实就是计算图在某处定义却在别处执行,这会使得调试变得更加困难。因为异常通常会缺失关于错误的具体信息,并且Python的调试工具也看不到数据的中间状态。另外,静态图通常不能与标准Python控制流很好的融合:它们是事实上的特定于域的语言,是在宿主语言之上实现的(本例是Python)。
97 |
98 | 接下来,我们将更具体地研究即时执行和延迟执行之间的区别,特别是在与神经网络相关的情况下。在这里我们不会深入地探索这些概念,而是在宏观角度上给读者介绍一下这些概念中的术语及其关系。理解这些概念及其关系可以帮助我们理解像PyTorch这种使用即时执行的框架与使用延迟执行的框架之间的区别,尽管这两种类型框架的底层数学原理是相同的。
99 |
100 | 神经网络的基本组成单元是神经元。大量的神经元串在一起构成神经网络。你可以在图1.2看到单个神经元典型的数学表达式:
101 |
102 | $$
103 | o = \tanh(wx + b)
104 | $$
105 |
106 | 在我们解释下图中的运行模式前,请注意以下几点:
107 |
108 | * x 是单个神经元计算的输入。
109 |
110 | * w 和 b 是神经元的参数或者说是权重,它们的值可以根据需要被更新。
111 |
112 | * 为了更新参数(生成更接近我们所期望的输出),我们通过反向传播将误差分配给每个权重,然后相应地对每个权重进行调整。
113 |
114 | * 反向传播需要计算输出相对于权重的梯度。
115 |
116 | * 我们使用自动微分来自动计算梯度,节省了手工编写微分计算的麻烦。
117 |
118 | 在图1.2中,神经元被编译进一个符号图,其中每个节点表示一个独立的操作(第二行),并对输入和输出使用占位符(placeholder)。然后,在将具体数字放入占位符中后(在本例中,放入占位符中的数字是存储在变量w、x和b中的值),该计算图便进行数值运算(第三行)。输出结果相对于权重的梯度是通过自动微分构造的,该自动微分反向遍历计算图并在各个节点处乘以梯度(第四行)。第五行展示了相应的数学表达式。
119 |
120 |
121 |

122 |
123 | 图1.2 用于单个神经元简单计算的静态图
124 |
125 | TensorFlow是深度学习框架中的主要竞争对手之一,其采用类似延迟执行的静态图模式。静态图模式是TensorFlow 1.0中的默认执行模式。相比之下,PyTorch使用了一个按运行定义(define-by-run)的动态图引擎,随着代码的不断执行,计算图将逐点构建。
126 |
127 | 图1.3中的上半部分展示了在动态图引擎下的相同的计算操作。计算操作被分解成独立的表达式,当执行到这些表达式时,它们会立刻运算。该程序对这些计算之间的内在联系没有预先的概念。图1.3下半部分展示了相同表达式的动态计算图的后台运行场景。该表达式仍然被分解为几个独立的操作,但是这些操作会立即运算求值,进而动态图渐渐地建立。类似于静态计算图,自动微分是通过反向遍历运算结果图来实现的。注意这并不意味着采用动态图的库自身就比采用静态图的库更好,只是动态图通常更容易完成循环或条件判断这些操作。
128 |
129 |
130 |

131 |
132 | 图1.3 用于单个神经单元简单计算的动态图
133 |
134 | 动态图在连续的前向传递过程中可能会发生变化。例如,可以根据先前节点输出的条件调用不同的节点,而无需在图本身中表示出这些情况,这与静态图模式相比有明显的优势。
135 |
136 | 目前主要的一些框架都趋向于支持以上两种操作模式。PyTorch 1.0能够在静态计算图中记录模型的执行情况,或通过预编译的脚本语言对其进行定义,从而提高了性能并易于将模型部署到工业生产。TensorFlow也增加了"eager mode",这是一种新的按运行定义的API,它增加了我们已经讨论的库的灵活性。
137 |
138 | ## 1.3.3 深度学习的竞争领域
139 |
140 | 尽管所有类比都会有瑕疵,但2017年1月发布的PyTorch 0.1似乎标志着从寒武纪生物大爆发时代(如深度学习库、封装器和数据交换格式的激增)到整合统一时代的过渡。
141 |
142 | 请注意:
143 |
144 | 近几年深度学习领域发展得非常迅猛,以至于你在阅读本书时,某些方面的介绍可能已经过时了。即使你对下面提到的某些库不太熟悉,也不必在意。
145 |
146 | 在PyTorch第一个beta版本发布的时候:
147 |
148 | * Theano和TensorFlow是主要的更偏向于底层的采用延迟执行方式的库。
149 |
150 | * Lasagne和Keras是Theano的高级封装库,而Keras同时也对TensorFlow和CNTK进行了高级封装。
151 |
152 | * Caffe、Chainer、Dynet、Torch(基于Lua的PyTorch的前身)、mxnet、CNTK和DL4J等库填补了深度学习生态系统中的各个领域。
153 |
154 | 随后大约两年中,该领域便发生了巨大的变化。PyTorch和TensorFlow背后的社区已经基本巩固完善,与之伴随的是其他库的使用量逐渐减少,或者只能退居某一特定领域:
155 |
156 | * Theano是最早的深度学习框架之一,现已停止发展。
157 |
158 | * TensorFlow
159 | * 使用Keras作为核心API
160 | * 提供即时执行模式(eager mode)
161 | * 宣布eager mode为TF2.0的默认执行模式
162 |
163 | * PyTorch
164 | * 使用Caffe2作为后端
165 | * 替换了基于Lua的Torch项目中重复使用的大多数低级代码
166 | * 增加了对ONNX的支持,定义了一种与深度学习库无关的模型描述和转换格式
167 | * 增加了称为TorchScript的延迟执行图模式运行引擎
168 | * 发布了1.0版本
169 |
170 | TensorFlow拥有强大的生产渠道、广泛的行业社区和广泛的思维共享。另一方面,由于PyTorch的易用性,它已在研究和教学社区中取得了巨大进展,并且随着研究人员和毕业生培训学生不断进入行业而不断发展壮大。有趣的是,随着TorchScript和eager mode的出现,这两个框架的功能集开始融合。
--------------------------------------------------------------------------------
/docs/chapter1/1.4.md:
--------------------------------------------------------------------------------
1 | # 1.4 PyTorch包含的组件
2 |
3 | 在前文中我们已经透露出PyTorch的一些组件。现在,我们将花费一些时间来正式介绍构成PyTorch的主要组件。
4 |
5 | 首先,虽然“PyTorch”包含“Python”中的"Py",但PyTorch中有很多非Python代码。由于性能原因,大多数PyTorch都是用C++和[CUDA](https://www.geforce.com/hardware/technology/cuda)编写的,CUDA是NVIDIA提供的类似C++的语言,可以将其编译然后在NVIDIA GPU上大规模并行运行。有多种方法可以直接从C运行PyTorch,此功能的主要动机之一是为生产中的模型部署提供可靠的策略。然而大多数情况下,你将基于Python来运行PyTorch,构建和训练模型,并使用训练后的模型来解决问题。根据给定的性能实际要求和规模要求,纯Python代码的方案足以将模型投入生产。例如,使用Flask web服务器来封装一个基于Python实现的PyTorch模型是完全切实可行的。
6 |
7 | 实际上,就可用性和与广泛的Python生态系统的集成性而言,Python API就是PyTorch的亮点。接下来,我们来探究下PyTorch的内置模块。
8 |
9 | PyTorch的核心是提供多维数组的库,在PyTorch术语中这些多维数组称为张量(tensor),而`torch`模块则提供了可对其进行扩展操作的库。张量和相关操作都可以在CPU或GPU上运行。相比于CPU,在GPU上运行可以显著的提高速度(如果你愿意为高端GPU付费的话),而且使用PyTorch最多需要一到两个额外的函数来调用GPU。PyTorch提供的第二个核心功能是允许张量跟踪对其所执行的操作,并通过反向传播来计算输出相对于其任何输入的导数。此功能由张量自身提供,并通过`torch.autograd`进一步扩展完善。
10 |
11 | 我们可以说,通过拥有张量和启用能自动求导的张量标准库,PyTorch不仅可以用于神经网络,还可以用于物理学、渲染、优化、仿真和建模等。我们很可能会看到PyTorch将以创造性的方式在各种科学应用中得到使用。
12 |
13 | 但是PyTorch首先是深度学习库,因此它提供了构建和训练神经网络所需的所有模块。图1.4展示了一个标准流程:加载数据,训练模型,然后将该模型部署到生产环境中。
14 |
15 | PyTorch中用于构建神经网络的核心模块位于`torch.nn`中,该模块提供了常见的神经网络层和其他架构组件。全连接层、卷积层、激活函数和损失函数都能在该模块找到。这些组件可用于构建和初始化图1.4中心部分所展示的未训练模型。
16 |
17 |
18 |

19 |
20 | 图1.4 PyTorch项目的基本高层结构,包括数据加载,训练和部署到生产
21 |
22 | 为了训练该模型,你需要以下几点(除了循环本身以外,循环可直接采用标准的Python for循环):训练数据的资源、使模型能够适应训练数据的优化器以及将模型和数据导入硬件中的方法,该硬件将执行训练模型所需的计算。
23 |
24 | `torch.util.data`模块能够找到适用于数据加载和处理的工具。需要用到的两个主要的类是`Dataset`和`DataLoader`。`Dataset`承担了你的自定义的数据(可以是任何一种格式)与标准PyTorch张量之间的转换任务。`DataLoader`可以在后台生成子进程来从`Dataset`中加载数据,使数据准备就绪并在循环可以使用后立即等待训练循环。
25 |
26 | 在最简单的情况下,模型将在本地CPU或单个GPU上运行所需的计算。因此,当训练循环获取到数据时就能够立即开始运算。然而更常见的情形是使用专用的硬件(例如多个GPU)或利用多台计算机的资源来训练模型。在这些情况下,可以通过`torch.nn.DataParallel`和`torch.distributed`来使用其他的可用硬件。
27 |
28 | 当模型根据训练数据得到输出结果后,`torch.optim`提供了更新模型的标准方法,从而使输出更接近于训练数据中的标签。
29 |
30 | 如前所述,PyTorch的默认运行方式为即时执行(eager mode)。每当Python解释器执行到包含PyTorch的指令时,相应的操作就会立即通过底层的C++或CUDA来执行。
31 |
32 | 为了避开Python解释器所带来的成本,以及使模型能够独立于Python而运行,PyTorch还提供了一个名为TorchScript的延迟执行模块。借助TorchScript,PyTorch可以序列化一组独立于Python而被调用的指令集。你可以将这个模型看作是具有针对张量操作的有限指令集的虚拟机。除了不产生调用Python的开销外,这种执行模式还使得PyTorch能够实时(Just in Time, JIT)将已知操作序列转换为更有效的混合操作。这些功能是PyTorch产品部署能力的基础。
33 |
34 | ## 1.4.1 深度学习所需要的硬件
35 |
36 | 任何最近的笔记本电脑或私人计算机都具有在新数据上运行预训练网络的能力。即使是对一个预训练网络的一小部分进行再训练,以使其拟合到一个新的数据集上,也不一定需要专门的硬件。你可以在标准个人电脑或笔记本上练习本书中的示例。不过可以预见的是,对于一些更复杂的示例,进行一次完整的训练可能会需要一个具有CUDA功能的图形处理单元(GPU),例如一个具有8GB RAM的GPU(我们建议使用NVIDIA GTX 1070及以上级别的GPU)。当然,如果你的硬件中可用的RAM较少,也可以适当调整这些参数。
37 |
38 | 需要注意的是:如果你愿意等待程序运行的话那么硬件就不是强制性的。但是在GPU上运行会将训练时间降低至少一个数量级(通常会快40到50倍)。以一次执行来看,计算参数更新所需的操作在现代硬件如常见笔记本电脑的CPU上的执行速度是很快的(几毫秒到几秒不等),问题在于训练过程会一次又一次地运行这些操作很多次,逐步更新网络参数从而使训练误差降到最低。
39 |
40 | 配备有良好GPU的工作站在大型真实世界中的数据集上从头开始训练一般的中大规模网络可能需要花费数小时乃至数天的时间。在同一个机器上使用多个GPU,或者更进一步使用配备了多个GPU的机器集群,能够有效地降低训练时间。由于云计算提供商的提供,这些设置对访问的限制比听起来要少。[DAWNBench](https://dawn.cs.stanford.edu/benchmark/index.html)是斯坦福大学的一项有趣的计划,旨在为完成常见的深度学习任务提供一个在对应公开数据集上关于模型训练时间和云计算成本的参考基准。
41 |
42 | 如果你拥有GPU那就再好不过了。否则的话,我们建议查看各种云平台的服务,其中许多服务都内置了支持GPU且预安装PyTorch的Jupyter notebooks,并且这些服务通常都会有一定的免费额度。
43 |
44 | 最后需要考虑的是:操作系统(OS)。PyTorch从第一个版本开始就支持Linux和macOS,并于2018年期间增加了对Windows的支持。由于目前的苹果笔记本电脑不支持具有CUDA功能的GPU,所以macOS系统上的PyTorch预编译包仅支持CPU。我们尽量避免假设你是在某个特定的操作系统上运行的情况;脚本命令行应该能很容易地转换成Windows兼容的格式。为了方便起见,只要有可能,我们就会列出代码,就像它在Jupyter Notebook上运行一样。
45 |
46 | 有关安装的信息,请参阅[PyTorch官方网站](https://pytorch.org/get-started/locally)上的入门指南。我们建议Windows用户使用Anaconda或Miniconda进行安装。其他操作系统的用户,如Linux用户,通常会有更多的可用选项,其中Pip是最常见的安装程序的工具之一。当然,有经验的用户可以自由地以与其首选的开发环境最兼容的方式安装软件包。
47 |
48 | ## 1.4.2 使用Jupyter Notebook
49 |
50 | 我们假设你已经安装了PyTorch和其他依赖项,并且已经确认了它们可以工作。我们将经常使用Jupyter Notebook,例如展示代码。Jupyter Notebook在浏览器中以页面的形式来展示,提供代码交互式运行的体验。其代码由内核计算,该内核是指一个运行在服务器上的进程,它随时准备接收并执行代码,之后返回结果并将它显示在页面上。Notebook将持续维护内存中的内核状态,如代码求值期间定义的变量,直到Notebook被终止或重新启动。你与Notebook进行交互的基本单元是一个单元格(cell),即页面上的一个编辑框,你可以在其中键入代码并让内核对其进行求值(通过在菜单项中选择或按Shift+Enter键)。你可以将多个单元格添加到Notebook中,新单元格会包含在较早单元格中创建的变量。执行后,单元格最后一行返回的值将打印在该单元格下方,绘图也一样。通过混合源代码、执行结果和Markdown格式的文本单元,你可以创作漂亮的交互式文档。你可以在[其项目网站](https://jupyter.org)上阅读有关Jupyter Notebooks的所有信息。
51 |
52 | 现在,读者需要从GitHub上获得代码,并在其根目录启动notebook服务器。服务器的启动方式取决于操作系统以及Jupyter的安装方式和位置。如果你有任何问题,随时在我们的[论坛](https://forums.manning.com/forums/deep-learning-with-pytorch)上提问。当notebook服务器启动时,会弹出默认浏览器,显示本地的notebook文件列表。
53 |
54 | Jupyter Notebooks是借助代码来表达和调研思路的强大工具。尽管我们认为它们很适合我们的使用情况,但它们并不适合所有情况。我们认为,本书中重要的是集中精力克服障碍并最大程度地降低认知成本(cognitive overhead),但这对每个人都是不同的。你在体验PyTorch的时候完全可以选择自己喜欢的方式。
55 |
56 | 你可以在[GitHub仓库](https://github.com/deep-learning-with-pytorch/dlwpt-code)中找到本书清单中的完整代码。
57 |
58 | ## 练习
59 |
60 | - 启动Python来获取交互式体验:
61 |
62 | - - 读者使用Python哪个版本?2.x还是3.x?
63 | - 读者会导入`torch`包吗?配好的PyTorch的版本号是什么?
64 | - 执行`torch.cuda.is_available()`的返回结果是什么?可依据你所使用的硬件判断它是否符合你的期望?
65 |
66 | - 启动Jupyter Notebook服务器:
67 |
68 | - - Jupyter使用的Python版本号是什么?
69 | - Jupyter使用的torch库的位置与你从交互式Python中导入的`torch`库的位置相同吗?
70 |
71 | ## 总结
72 |
73 | - 深度学习模型会自动地学习将样本中的输入和期望输出建立联系。
74 | - PyTorch等深度学习库可以使你有效地构建和训练神经网络模型。
75 | - PyTorch在专注于灵活性和速度的同时最大程度地降低了认知成本。它默认使用即时执行模式。
76 | - TorchScript是一种可以在C++中调用的预编译的延迟执行模型。
77 | - 自2017年初PyTorch问世以来,深度学习工具的生态系统已显着巩固完善。
78 | - PyTorch提供了多个实用的功能库来帮助深度学习项目开发。
--------------------------------------------------------------------------------
/docs/chapter2/2.0.md:
--------------------------------------------------------------------------------
1 | # 2 从张量开始
2 |
3 | 本章将介绍
4 | * PyTorch最基本的数据结构张量(tensor)
5 | * 索引和操作张量以探索和处理数据
6 | * 与NumPy多维数组相互操作
7 | * 将运算移至GPU以提高速度
8 |
9 | -----------
10 |
11 | 深度学习有许多应用,这些应用往往包括以某种形式获取数据(例如图像或文本),并以另一种形式生成数据(例如标签,数字或更多文本)。从这个角度来看,深度学习包括构建一个将数据从一种表示转换为另一种表示的系统。这种转换是通过从一系列样本中提取的共性来驱动的,这些共性能够反映期望的映射关系。例如,该系统可能会记录狗的一般形状和金毛的典型颜色,通过组合这两个图像属性,该系统可以正确地将具有给定形状和颜色的图像映射到金毛猎犬标签,而不是黑色实验室(或黄褐色的雄猫)。最终的系统可以消耗大量类似输入,并为这些输入产生有意义的输出。
12 |
13 | 这个过程的第一步是将输入转换为浮点数,如图2.1所示的第一步(也可以是其他类型的数据)。因为网络使用浮点数来处理信息,所以我们需要对真实世界的数据进行编码,使其成为网络可理解的形式,然后再将输出解码回我们可以理解并用于某种用途的形式。
14 |
15 |
16 |

17 |
18 | 图2.1 深度神经网络学习如何将输入转换为输出(注:神经元和输出的数量不成比例)
19 |
20 |
21 | 从一种数据形式到另一种数据形式的转换通常是由深度神经网络分层次学习的,这意味着我们可以将层次之间转换得到的数据视为一系列中间表示(intermediate representation)。以图像识别为例,浅层的表示可以是特征(例如边缘检测)或纹理(例如毛发),较深层次的表征可以捕获更复杂的结构(例如耳朵、鼻子或眼睛)。
22 |
23 | 通常,这种中间表示形式是浮点数的集合,这些浮点数表征输入并捕获数据中的结构,从而有助于描述输入如何映射到神经网络的输出。这种表征是特定于当前任务的,可以从相关示例中学习。这些浮点数的集合及其操作是现代AI的核心。请务必牢记,这些中间表示(例如图2.1第二步所示)是将输入与前一层神经元权重相结合的结果,每个中间表示对于之前的输入都是唯一的。
24 |
25 | 在开始将数据转换为浮点输入之前,我们必须对PyTorch如何处理和存储数据(输入、中间表示以及输出)有深刻的了解。本章就帮助读者准确地理解这些原理。
26 |
27 | 为此,PyTorch引入了一个基本的数据结构:张量(tensor)。对于来自数学、物理学或工程学的人来说,张量一词是与空间、参考系以及它们之间的转换的概念是捆绑在一起的。对于其他人来说,张量是指将向量(vector)和矩阵(matrix)推广到任意维度,如图2.2所示。与张量相同概念的另一个名称是多维数组(multidimensional array)。张量的维数与用来索引张量中某个标量值的索引数一致。
28 |
29 |
30 |

31 |
32 | 图2.2 张量被用来表示数据
33 |
34 | PyTorch并不是唯一能处理多维数组的库。NumPy是迄今为止最受欢迎的多维数组处理库,以至于它可以被当做数据科学的通用语言。事实上,PyTorch可以与NumPy无缝衔接,从而使得PyTorch能够与Python中的其他科学库(如[SciPy](https://www.scipy.org)、[Scikit-learn](https://scikit-learn.org/stable)和[Pandas](https://pandas.pydata.org))进行高度的整合。
35 |
36 | 与NumPy数组相比,PyTorch的张量具有一些更强大功能,例如能够在GPU进行快速运算、在多个设备或机器上进行分布式操作以及跟踪所创建的计算图。所有这些功能对于实现现代深度学习库都很重要。
37 |
38 | 我们通过介绍PyTorch张量来开启本章,涵盖了基础入门的知识。然后将展示如何使用PyTorch张量库来操作张量,例如数据如何存储在内存中以及如何在常数时间内对任意大张量执行某些操作之类的内容。然后我们将深入探讨前面提到的与NumPy的相互操作性和GPU加速。
39 |
40 | 要想张量成为编程工具,了解张量的功能和API是很重要的。
--------------------------------------------------------------------------------
/docs/chapter2/2.1.md:
--------------------------------------------------------------------------------
1 | # 2.1 张量基础
2 |
3 | 我们已经了解到张量是PyTorch中基本的数据结构。张量是一个数组,即一种存储数字集合的数据结构,这些数字可通过索引单独访问,也可通过多个索引进行索引。
4 |
5 | 我们来实际观察一下python的列表(list)索引,以便将其与张量索引进行比较。以下代码展示了Python中三个数字的列表。
6 | ``` python
7 | a = [1.0, 2.0, 1.0]
8 | ```
9 | 你可以使用相应的索引(从0开始的)来访问列表的第一个元素:
10 | ``` python
11 | a[0]
12 | ```
13 | 输出:
14 | ```
15 | 1.0
16 | ```
17 |
18 | ``` python
19 | a[2] = 3.0
20 | a
21 | ```
22 | 输出:
23 | ```
24 | [1.0, 2.0, 3.0]
25 | ```
26 |
27 | 使用列表来存储并处理向量(例如2D线的坐标)在简单的Python程序中是很常见的。但是,由于以下几个原因,这种做法可能不是最佳的:
28 | * *Python中的数是完整( full-fledged)的对象。* 浮点数只需要32位就可以在计算机上表示,而Python将它们封装(boxes)在具有引用计数等功能的完整Python对象中。如果只需要存储少量数字,这种做法就没问题,但是要想分配数百万个这样的数字效率就太低了。
29 | * *Python中的列表用于对象的有序集合。* 没有定义高效计算两个向量点积或向量求和的操作。此外,Python列表无法优化其在内存中的布局,因为它们是指向Python对象(任何类型,而不仅仅是数字)的可索引指针集合。最后,Python列表是一维的,尽管我们可以创建列表的列表,但这种做法仍然效率很低。
30 | * *与经过优化和编译的代码相比,Python解释器速度较慢。* 使用可编译的低层语言(例如C)编写的优化代码可以更快地对大量数据进行数学运算。
31 |
32 | 由于这些原因,数据科学库依赖于NumPy或引入专用数据结构(例如PyTorch张量),这些结构提供了高效的数值数据结构的底层实现以及相关运算,并被封装成高级API。
33 |
34 | 从图像到时间序列、音频甚至文本,张量可以表示许多类型的数据。通过定义在张量上的操作(本章将探讨其中的一些操作),即使使用不是特别快高级语言(例如Python),也可以高效地进行切片(slice)和操作数据。
35 |
36 | 现在,你可以构建第一个PyTorch张量来观察其特性。这个张量包含三个1,没有特别的意义:
37 | ``` python
38 | import torch
39 | a = torch.ones(3)
40 | a
41 | ```
42 | 输出:
43 | ```
44 | tensor([1., 1., 1.])
45 | ```
46 |
47 | ``` python
48 | a[1]
49 | ```
50 | 输出:
51 | ```
52 | tensor(1.)
53 | ```
54 |
55 | ``` python
56 | float(a[1])
57 | ```
58 | 输出:
59 | ```
60 | 1.0
61 | ```
62 |
63 | ``` python
64 | a[2] = 2.0
65 | a
66 | ```
67 | 输出:
68 | ```
69 | tensor([1., 1., 2.])
70 | ```
71 |
72 |
73 |
74 |
75 | 现在我们来看看刚刚做了什么。导入`torch`模块后,我们调用了一个函数,该函数创建了大小为3的(一维)张量,并填充值为1.0。你可以使用从0开始的索引来访问元素,也可以为其分配新的值。
76 |
77 | 尽管从表面上看,此示例与Python列表并没有太大区别,但实际上情况完全不同。Python列表或数字元组(tuple)是在内存中单独分配的Python对象的集合,如图2.3左侧所示。然而,PyTorch张量或NumPy数组(通常)是连续内存块上的视图(view),这些内存块存有未封装(unboxed)的C数值类型,在本例中,如图2.3右侧所示,就是32位的浮点数(4字节),而不是Python对象。因此,包含100万个浮点数的一维张量需要400万个连续字节存储空间,再加上存放元数据(尺寸、数据类型等)的少量开销。
78 |
79 |
80 |

81 |
82 | 图2.3 Python中封装(boxed)的数值对象与张量(未封装数组)数据
83 |
84 | 假设你要管理一个2D坐标列表来表示一个几何对象,例如三角形。虽然这个例子与深度学习不是很相关,但是很容易理解。你可以用一个一维张量将横坐标`x`存储在偶数索引中然后将纵坐标`y`存储在奇数索引中,而不是用Python列表存放坐标数字,如下所示:
85 |
86 | ``` python
87 | # 使用.zeros是获取适当大小的数组的一种方法
88 | points = torch.zeros(6)
89 | # 用所需的值覆盖这些0
90 | points[0] = 1.0
91 | points[1] = 4.0
92 | points[2] = 2.0
93 | points[3] = 1.0
94 | points[4] = 3.0
95 | points[5] = 5.0
96 | ```
97 |
98 | 还可以传入Python列表以达到相同的效果:
99 | ``` python
100 | points = torch.tensor([1.0, 4.0, 2.0, 1.0, 3.0, 5.0])
101 | points
102 | ```
103 | 输出:
104 | ```
105 | tensor([1., 4., 2., 1., 3., 5.])
106 | ```
107 |
108 | 获取第一个点的坐标:
109 | ``` python
110 | float(points[0]), float(points[1])
111 | ```
112 | 输出:
113 | ```
114 | (1.0, 4.0)
115 | ```
116 |
117 | 以上做法是可以的,虽然实际上往往让第一个索引直接索引一个二维点而不是点坐标。为此,可以使用二维张量:
118 |
119 | ``` python
120 | points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])
121 | points
122 | ```
123 | 输出:
124 | ```
125 | tensor([[1., 4.],
126 | [2., 1.],
127 | [3., 5.]])
128 | ```
129 |
130 | 上例将列表的列表传递给了张量构造函数。你可以获取一个张量的形状,
131 |
132 | ``` python
133 | points.shape
134 | ```
135 | 输出:
136 | ```
137 | torch.Size([3, 2])
138 | ```
139 | 它会告诉你沿每个维度的张量的大小。你还可以使用`zeros`或`ones`来初始化张量,同时用元组指定大小:
140 |
141 | ``` python
142 | points = torch.zeros(3, 2)
143 | points
144 | ```
145 | 输出:
146 | ```
147 | tensor([[0., 0.],
148 | [0., 0.],
149 | [0., 0.]])
150 | ```
151 |
152 | 现在,你可以使用两个索引访问张量中的单个元素:
153 |
154 | ``` python
155 | points = torch.FloatTensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])
156 | points
157 | ```
158 | 输出:
159 | ```
160 | tensor([[1., 4.],
161 | [2., 1.],
162 | [3., 5.]])
163 | ```
164 |
165 | ``` python
166 | points[0, 1]
167 | ```
168 | 输出:
169 | ```
170 | tensor(4.)
171 | ```
172 |
173 | 此代码返回数据集中第0个点的y坐标。你还可以像以前一样访问张量中的第一个元素,以获取第一个点的二维坐标:
174 |
175 | ``` python
176 | points[0]
177 | ```
178 | 输出:
179 | ```
180 | tensor([1., 4.])
181 | ```
182 |
183 | 请注意,输出结果是另一个张量,它是大小为2的一维张量,包含了`points`的第一行中的值。上述输出是否将值复制到了新分配的内存块并将新的内存封装在新的张量对象中?答案是不,因为这样效率不高,尤其是如果有数百万个点数据。与之相反,上述输出是相同数据块的仅限于第一行的视图(view)。
184 |
185 |
186 |
--------------------------------------------------------------------------------
/docs/chapter2/2.2.md:
--------------------------------------------------------------------------------
1 | # 2.2 张量与存储
2 |
3 | 在本节中,我们将开始了解关于内部实现的信息。数值分配在连续的内存块中,由`torch.Storage`实例管理。存储(`Storage`)是一个一维的数值数据数组,例如一块包含了指定类型(可能是float或int32)数字的连续内存块。PyTorch的张量(`Tensor`)就是这种存储(`Storage`)的视图(view),我们可以使用偏移量和每一维的跨度索引到该存储中。
4 |
5 | 多个张量可以索引同一存储,即使它们的索引方式可能不同,如图2.4所示。 实际上,当你在上节最后一个代码片段中获取`points[0]`时,你得到的是另一个张量,该张量与`points`索引相同的存储,只是不是索引该存储的全部并且具有不同的维数(一维与二维)。由于基础内存仅分配一次,所以无论`Storage`实例管理的数据大小如何,都可以快速地在该数据上创建不同的张量视图。
6 |
7 |
8 |

9 |
10 | 图2.4 张量是一个存储实例的视图(view)
11 |
12 | 接下来,你将看到在二维坐标点的例子中索引到存储是如何工作的。我们可以使用`storage`属性访问给定张量的存储:
13 |
14 | ``` python
15 | import torch
16 | points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])
17 | points.storage()
18 | ```
19 | 输出:
20 | ```
21 | 1.0
22 | 4.0
23 | 2.0
24 | 1.0
25 | 3.0
26 | 5.0
27 | [torch.FloatStorage of size 6]
28 | ```
29 |
30 | 即使张量具有三行两列,但内部的存储却是大小为6的连续数组。从这个意义上讲,张量知道如何将一对索引转换为存储中的某个位置。
31 |
32 | 还可以手动索引到存储中:
33 | ``` python
34 | points_storage = points.storage()
35 | points_storage[0]
36 | ```
37 | 输出:
38 | ```
39 | 1.0
40 | ```
41 |
42 | ``` python
43 | points.storage()[1]
44 | ```
45 | 输出:
46 | ```
47 | 4.0
48 | ```
49 |
50 | 无法使用两个索引来索引二维张量的存储,因为存储始终是一维的,与引用它的任何张量的维数无关。
51 |
52 | 因此,更改存储的值当然也会更改引用它的张量的内容:
53 |
54 | ``` python
55 | points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])
56 | points_storage = points.storage()
57 | points_storage[0] = 2.0
58 | points
59 | ```
60 | 输出:
61 | ```
62 | tensor([[2., 4.],
63 | [2., 1.],
64 | [3., 5.]])
65 | ```
66 |
67 | 我们几乎很少会直接使用存储实例,但是了解张量与存储之间的关系对于以后了解某些操作的代价很有帮助。当你要编写高效的PyTorch代码时,请牢记这一思维模型。
--------------------------------------------------------------------------------
/docs/chapter2/2.3.md:
--------------------------------------------------------------------------------
1 | # 2.3 尺寸、存储偏移与步长
2 | 除了存放存储外,为了索引存储,张量依赖于几条明确定义它们的信息:尺寸(size)、存储偏移(storage offset)和步长(stride),如图2.5所示。尺寸(或按照NumPy中的说法:形状shape)是一个元组,表示张量每个维度上有多少个元素。存储偏移是存储中与张量中的第一个元素相对应的索引。步长是在存储中为了沿每个维度获取下一个元素而需要跳过的元素数量。
3 |
4 |
5 |

6 |
7 | 图2.5 张量的尺寸、偏移与步长之间的关系
8 |
9 | 您可以通过提供相应的索引来获得张量中的第二个点:
10 | ``` python
11 | points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])
12 | second_point = points[1]
13 | second_point.storage_offset()
14 | ```
15 | 输出:
16 | ```
17 | 2
18 | ```
19 |
20 | ``` python
21 | second_point.size()
22 | ```
23 | 输出:
24 | ```
25 | torch.Size([2])
26 | ```
27 |
28 | 结果张量在存储中的偏移为2(因为我们需要跳过第一个点,该点有两个元素),并且尺寸是包含一个元素的`Size`类的实例,因为结果张量是一维的。需要注意的是,张量尺寸信息与张量对象的`shape`属性中包含的信息相同:
29 |
30 | ``` python
31 | second_point.shape
32 | ```
33 | 输出:
34 | ```
35 | torch.Size([2])
36 | ```
37 |
38 | 最后,步长是一个元组,表示当索引在每个维度上增加1时必须跳过的存储中元素的数量。例如,上例`points`张量的步长:
39 |
40 | ``` python
41 | points.stride()
42 | ```
43 | 输出:
44 | ```
45 | (2, 1)
46 | ```
47 |
48 | 用下标`i`和`j`访问二维张量等价于访问存储中的`storage_offset + stride[0] * i + stride[1] * j`元素。偏移通常为零,但如果此张量是一个可容纳更大张量的存储的视图,则偏移可能为正值。
49 |
50 | 张量`Tensor`和和存储`Storage`之间的这种间接操作会使某些操作(例如转置或提取子张量)的代价很小,因为它们不会导致内存重新分配;相反,它们(仅仅)分配一个新的张量对象,该对象具有不同的尺寸、存储偏移或步长。
51 |
52 | 刚刚我们已经看到了通过索引特定点来提取子张量,并且也看到了存储偏移增加了。现在来看看尺寸和步长发生了什么:
53 |
54 | ``` python
55 | points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])
56 | second_point = points[1]
57 | second_point.size()
58 | ```
59 | 输出:
60 | ```
61 | torch.Size([2])
62 | ```
63 |
64 | ``` python
65 | second_point.storage_offset()
66 | ```
67 | 输出:
68 | ```
69 | 2
70 | ```
71 |
72 | ``` python
73 | second_point.stride()
74 | ```
75 | 输出:
76 | ```
77 | (1,)
78 | ```
79 |
80 | 结果是,子张量减少了一个维度(正如我们期望的那样),同时索引的是与原始点张量相同的存储。更改子张量同时也会对原始张量产生影响:
81 |
82 | ``` python
83 | points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])
84 | second_point = points[1]
85 | second_point[0] = 10.0
86 | points
87 | ```
88 | 输出:
89 | ```
90 | tensor([[ 1., 4.],
91 | [10., 1.],
92 | [ 3., 5.]])
93 | ```
94 |
95 | 这种影响可能不总是我们想要的,所以我们可以克隆子张量得到新的张量(以避免这种影响):
96 |
97 | ``` python
98 | points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])
99 | second_point = points[1].clone()
100 | second_point[0] = 10.0
101 | points
102 | ```
103 | 输出:
104 | ```
105 | tensor([[1., 4.],
106 | [2., 1.],
107 | [3., 5.]])
108 | ```
109 |
110 | 我们现在试试转置操作。`points`张量沿每一行就是单个点坐标,沿每一列分别是(所有点的)x和y坐标,现在我们将其旋转以使沿每一列是单个点坐标:
111 |
112 | ``` python
113 | points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])
114 | points
115 | ```
116 | 输出:
117 | ```
118 | tensor([[1., 4.],
119 | [2., 1.],
120 | [3., 5.]])
121 | ```
122 |
123 | ``` python
124 | points_t = points.t()
125 | points_t
126 | ```
127 | 输出:
128 | ```
129 | tensor([[1., 2., 3.],
130 | [4., 1., 5.]])
131 | ```
132 |
133 | 你可以轻松地验证两个张量共享同一存储:
134 |
135 | ``` python
136 | id(points.storage()) == id(points_t.storage())
137 | ```
138 | 输出:
139 | ```
140 | True
141 | ```
142 |
143 | 并且它们的仅仅是尺寸和步长不同:
144 |
145 | ``` python
146 | points.stride()
147 | ```
148 | 输出:
149 | ```
150 | (2, 1)
151 | ```
152 |
153 | ``` python
154 | points_t.stride()
155 | ```
156 | 输出:
157 | ```
158 | (1, 2)
159 | ```
160 |
161 | 上述结果告诉我们,在`points`中将第一个索引增加1(即,从`points[0,0]`到`points[1,0]`)会沿着存储跳过两个元素,将第二个索引从`points[0,0]`到点`points[0,1]`会沿存储跳过一个元素。换句话说,存储将`points`张量中的元素逐行保存着。
162 |
163 | 你可以按照图2.6那样将`points`转置为`points_t`。你更改了步长中元素的顺序。这样一来,增加行(张量的第一个索引)就会沿着存储跳过1个元素,就像`points`沿着列移动一样,这就是转置的定义。(这个过程)没有分配新的内存:仅通过创建一个步长顺序与原始张量不同的新的张量实例来实现转置。
164 |
165 |
166 |

167 |
168 | 图2.6 张量的转置
169 |
170 | 在PyTorch中进行转置不仅限于矩阵(即二维数组)。以翻转三维数组的步长和尺寸为例,你可以通过指定应需要转置的两个维度来转置多维数组:
171 |
172 | ``` python
173 | some_tensor = torch.ones(3, 4, 5)
174 | some_tensor.shape, some_tensor.stride()
175 | ```
176 | 输出:
177 | ```
178 | (torch.Size([3, 4, 5]), (20, 5, 1))
179 | ```
180 |
181 | ``` python
182 | some_tensor_t = some_tensor.transpose(0, 2)
183 | some_tensor_t.shape, some_tensor_t.stride()
184 | ```
185 | 输出:
186 | ```
187 | (torch.Size([5, 4, 3]), (1, 5, 20))
188 | ```
189 |
190 | 从最右边的维开始将其值存放在存储中的张量(例如沿着行存放在存储中的二维张量)定义为连续(Contiguous)张量。连续张量很方便,因为你可以高效且有序地访问它们的元素而不是在存储中四处跳跃访问。(由于现代CPU中内存访问的工作原理,改善数据局部性可提高性能。译者注:即连续张量满足局部性原理)
191 |
192 | 在前例中,`points`是连续的,但其转置不是:
193 |
194 | ``` python
195 | points.is_contiguous(), points_t.is_contiguous()
196 | ```
197 | 输出:
198 | ```
199 | (True, False)
200 | ```
201 |
202 | 你可以使用`contiguous`方法从非连续张量获得新的连续张量。 张量的内容保持不变,但步长发生变化,存储也是如此:
203 |
204 | ``` python
205 | points = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 5.0]])
206 | points_t = points.t()
207 | points_t
208 | ```
209 | 输出:
210 | ```
211 | tensor([[1., 2., 3.],
212 | [4., 1., 5.]])
213 | ```
214 |
215 | ``` python
216 | points_t.storage()
217 | ```
218 | 输出:
219 | ```
220 | 1.0
221 | 4.0
222 | 2.0
223 | 1.0
224 | 3.0
225 | 5.0
226 | [torch.FloatStorage of size 6]
227 | ```
228 |
229 | ``` python
230 | points_t.stride()
231 | ```
232 | 输出:
233 | ```
234 | (1, 2)
235 | ```
236 |
237 | ``` python
238 | points_t_cont = points_t.contiguous()
239 | points_t_cont
240 | ```
241 | 输出:
242 | ```
243 | tensor([[1., 2., 3.],
244 | [4., 1., 5.]])
245 | ```
246 |
247 | ``` python
248 | points_t_cont.stride()
249 | ```
250 | 输出:
251 | ```
252 | (3, 1)
253 | ```
254 |
255 | ``` python
256 | points_t_cont.storage()
257 | ```
258 | 输出:
259 | ```
260 | 1.0
261 | 2.0
262 | 3.0
263 | 4.0
264 | 1.0
265 | 5.0
266 | [torch.FloatStorage of size 6]
267 | ```
268 |
269 | 请注意,新的存储对元素进行了重组以便逐行存放张量元素。步长也已改变以反映新的布局。
270 |
271 |
272 |
--------------------------------------------------------------------------------
/docs/chapter2/2.4.md:
--------------------------------------------------------------------------------
1 | # 2.4 数据类型
2 |
3 | 好吧,你现在知道张量如何工作的基础知识了。但是我们还没有涉及可以存放在张量中的数据类型。张量构造函数(即`tensor`、`ones`、`zeros`之类的函数)的`dtype`参数指定了张量中的数据类型。数据类型指定张量可以容纳的可能值(整数还是浮点数)以及每个值的字节数。`dtype`参数被故意设计成类似于同名的标准NumPy参数。以下是`dtype`参数的可能取值的列表:
4 |
5 | * `torch.float32`或`torch.float` —— 32位浮点数
6 | * `torch.float64`或`torch.double` —— 64位双精度浮点数
7 | * `torch.float16`或`torch.half` —— 16位半精度浮点数
8 | * `torch.int8` —— 带符号8位整数
9 | * `torch.uint8` —— 无符号8位整数
10 | * `torch.int16`或`torch.short` —— 带符号16位整数
11 | * `torch.int32`或`torch.int` —— 带符号32位整数
12 | * `torch.int64`或`torch.long` —— 带符号64位整数
13 |
14 | 每个`torch.float`、`torch.double`等等都有一个与之对应的具体类:`torch.FloatTensor`、`torch.DoubleTensor`等等。`torch.int8`对应的类是`torch.CharTensor`,而`torch.uint8`对应的类是`torch.ByteTensor`。`torch.Tensor`是`torch.FloatTensor`的别名,即默认数据类型为32位浮点型。
15 |
16 | 想要分配正确数字类型的张量,你可以指定合适的`dtype`作为张量构造函数的参数,如下所示:
17 |
18 | ``` python
19 | double_points = torch.ones(10, 2, dtype=torch.double)
20 | short_points = torch.tensor([[1, 2], [3, 4]], dtype=torch.short)
21 | ```
22 |
23 | 你可以通过访问`dtype`属性来获得张量的数据类型:
24 |
25 | ``` python
26 | short_points.dtype
27 | ```
28 | 输出:
29 | ```
30 | torch.int16
31 | ```
32 |
33 | 您还可以使用相应的转换方法将张量创建函数的输出转换为正确的类型,例如
34 | ``` python
35 | double_points = torch.zeros(10, 2).double()
36 | short_points = torch.ones(10, 2).short()
37 | ```
38 |
39 | 或者用更方便的`to`方法:
40 | ``` python
41 | double_points = torch.zeros(10, 2).to(torch.double)
42 | short_points = torch.ones(10, 2).to(dtype=torch.short)
43 | ```
44 |
45 | 在实现内部,`type`和`to`执行相同的操作,即“检查类型如果需要就转换(check-and-convert-if-needed)”,但是`to`方法可以使用其他参数。
46 |
47 | 你始终可以使用`type`方法将一种类型的张量转换为另一种类型的张量:
48 |
49 | ``` python
50 | points = torch.randn(10, 2)
51 | short_points = points.type(torch.short)
52 | ```
53 | 上例的`randn`返回一个元素是0到1之间随机数的张量。
--------------------------------------------------------------------------------
/docs/chapter2/2.5.md:
--------------------------------------------------------------------------------
1 | # 2.5 索引张量
2 |
3 | 我们已经知道`points[0]`返回一个张量,该张量包含`points`第一行所表示二维点。如果你需要获取一个包含除第一个点之外的所有点的张量怎么办?如果是应用在标准Python列表上,那么上述任务就可以很简单地用区间索引来实现:
4 |
5 | ``` python
6 | some_list = list(range(6))
7 | some_list[:] # 所有元素
8 | some_list[1:4] # 第1(含)到第4(不含)个元素
9 | some_list[1:] # 第1(含)个之后所有元素
10 | some_list[:4] # 第4(不含)个之前所有元素
11 | some_list[:-1] # 最末尾(不含)元素之前所有元素
12 | some_list[1:4:2] # 范围1(含)到4(不含),步长为2的元素
13 | ```
14 |
15 | 为了实现这个目标,你可以对PyTorch张量使用相同的表示,并且具有与NumPy和其他Python科学库一样的额外好处,即我们可以对张量的每个维使用区间索引:
16 |
17 | ``` python
18 | points[1:] # 第1行及之后所有行,(默认)所有列
19 | points[1:, :] # 第1行及之后所有行,所有列
20 | points[1:, 0] # 第1行及之后所有行,仅第0列
21 | ```
22 |
23 | 除了使用区间索引外,PyTorch还具有更强大的索引方式,被称为高级索引(advanced indexing)。
--------------------------------------------------------------------------------
/docs/chapter2/2.6.md:
--------------------------------------------------------------------------------
1 | # 2.6 与NumPy的互通性
2 |
3 | 尽管我们认为有使用NumPy的经验不是阅读本书的先决条件,但由于NumPy在Python数据科学生态系统中无处不在,我们强烈建议你熟悉NumPy。PyTorch张量可以方便地转换为NumPy数组,反之亦然。这样,你就可以使用围绕NumPy数组类型构建的更广泛的Python生态系统中的大量功能。
4 |
5 | 与NumPy数组的这种零拷贝互通性是由于(PyTorch的)存储是遵守[Python缓冲协议](https://docs.python.org/3/c-api/buffer.html)的。
6 |
7 | 要从`points`张量创建NumPy数组,请调用
8 |
9 | ``` python
10 | points = torch.ones(3, 4)
11 | points_np = points.numpy()
12 | points_np
13 | ```
14 | 输出:
15 | ```
16 | array([[1., 1., 1., 1.],
17 | [1., 1., 1., 1.],
18 | [1., 1., 1., 1.]], dtype=float32)
19 | ```
20 |
21 | 它返回尺寸、形状和数值类型正确的NumPy多维数组。有趣的是,返回的数组与张量存储共享一个基础缓冲区。因此,只要数据位于CPU RAM中,`numpy`方法就可以几乎零花费地高效执行,并且修改得到的NumPy数组会导致原始张量发生变化。
22 |
23 | 如果在GPU上分配了张量,(调用`numpy`方法时)PyTorch会将张量的内容复制到在CPU上分配的NumPy数组中。
24 |
25 | 相反,你可以通过以下方式从NumPy数组创建PyTorch张量:
26 | ``` python
27 | points = torch.from_numpy(points_np)
28 | ```
29 |
30 | `from_numpy`使用相同的缓冲共享策略。
--------------------------------------------------------------------------------
/docs/chapter2/2.7.md:
--------------------------------------------------------------------------------
1 | # 2.7 序列化张量
2 |
3 | 动态创建张量是很不错的,但是如果其中的数据对你来说具有价值,那么你可能希望将其保存到文件中并在某个时候加载回去。毕竟你可不想每次开始运行程序时都从头开始重新训练模型!PyTorch内部使用`pickle`来序列化张量对象和实现用于存储的专用序列化代码。下面展示怎样将`points`张量保存到ourpoints.t文件中:
4 |
5 | ``` python
6 | torch.save(points, '../../data/chapter2/ourpoints.t')
7 | ```
8 |
9 | 或者,你也可以传递文件描述符代替文件名:
10 |
11 | ``` python
12 | with open('../../data/chapter2/ourpoints.t','wb') as f:
13 | torch.save(points, f)
14 | ```
15 |
16 | 将`points`加载回来也是一行类似代码:
17 |
18 | ``` python
19 | points = torch.load('../../data/chapter2/ourpoints.t')
20 | ```
21 | 等价于
22 | ``` python
23 | with open('../../data/chapter2/ourpoints.t','rb') as f:
24 | points = torch.load(f)
25 | ```
26 |
27 | 如果只想通过PyTorch加载张量,则上述例子可让你快速保存张量,但这个文件格式本身是不互通(interoperable)的,你无法使用除PyTorch外其他软件读取它。根据实际使用情况,上述情况可能问题不大,但应该学习一下如何在有的时候(即想用其他软件读取的时候)互通地保存张量。尽管实际情况都是独一无二的,但当你想将PyTorch引入已经依赖于不同库的现有系统中时,上述情况会很常见;而全新的项目可能不需要经常互通地保存张量。
28 |
29 | 对于需要(互通)的情况,你可以使用[HDF5](https://www.hdfgroup.org/solutions/hdf5)格式和库。HDF5是一种可移植的、广泛支持的格式,用于表示以嵌套键值字典形式组织的序列化多维数组。Python通过[h5py库](http://www.h5py.org)支持HDF5,该库以NumPy数组的形式接收和返回数据。
30 |
31 | 你可以使用以下命令安装`h5py`:
32 | ``` shell
33 | conda install h5py
34 | ```
35 |
36 | 此时,你可以通过将`points`张量转换为NumPy数组(如前所述,此操作几乎零花费)并将其传递给`create_dataset`函数来保存`points`张量:
37 |
38 | ``` python
39 | import h5py
40 |
41 | f = h5py.File('../../data/chapter2/ourpoints.hdf5', 'w')
42 | dset = f.create_dataset('coords', data=points.numpy())
43 | f.close()
44 | ```
45 | 这里,`coords`是传入HDF5文件的键值。你还可以有其他键值,甚至是嵌套键值。HDF5中的一件有趣的事情是,你可以索引在磁盘的数据并且仅访问你感兴趣的元素。例如你只想加载数据集中的最后两个点数据:
46 | ``` python
47 | f = h5py.File('../../data/chapter2/ourpoints.hdf5', 'r')
48 | dset = f['coords']
49 | last_points = dset[1:]
50 | ```
51 | 上例中,当你打开文件或需要数据集时并未加载数据。相反,数据一直保留在磁盘上,直到你请求数据集中的第二行和最后一行。此时,`h5py`才访问这两行并返回了一个包含你想要数据的类似NumPy数组的对象,该对象的行为类似于NumPy数组,并且具有相同的API。
52 |
53 | 基于这个事实,你可以将返回的对象传递给`torch.from_numpy`函数以直接获取张量。需要注意的是,在这种情况下,数据将复制到张量存储中:
54 | ``` python
55 | last_points = torch.from_numpy(dset[1:])
56 | f.close()
57 | # last_points = torch.from_numpy(dset[1:]) # 会报错, 因为f已经关了
58 | ```
59 |
60 | 完成数据加载后,必须关闭文件。
61 |
--------------------------------------------------------------------------------
/docs/chapter2/2.8.md:
--------------------------------------------------------------------------------
1 | # 2.8 将张量转移到GPU上运行
2 |
3 | PyTorch张量的最后一点是关于在GPU上计算。每一个Torch张量都可以转移到GPU上去执行快速、大规模并且可以并行的计算。在张量上执行的所有操作均由PyTorch自带的GPU特定例程执行。
4 |
5 | > 请注意:
6 | > 截止至2019年初,主要的PyTorch版本仅仅在支持CUDA的GPU上具有加速功能。PyTorch的概念验证版本(Proof-of-concept version)已经可以运行在AMD的[ROCm](https://rocm.github.io)平台上,但是从1.0版开始,尚未将全部支持合并到PyTorch中。对[Google TPU的支持](https://github.com/pytorch/xla)正在进行开发中,目前的概念验证版已在[Google Colab](https://colab.research.google.com)中向公众公开。在我们写这章的时候,并未计划在其他GPU技术(例如OpenCL)上实现相应的数据结构和内核。
7 |
8 | 除了`dtype`之外,PyTorch张量还具有设备(`device`)的概念,这是在设置计算机上放张量(tensor)数据的位置。 通过为构造函数指定相应的参数,可以在GPU上创建张量:
9 |
10 | ```python
11 | points_gpu = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 4.0]], device='cuda')
12 | ```
13 |
14 | 你可以使用`to`方法将在CPU上创建的张量(tensor)复制到GPU:
15 |
16 | ```python
17 | points_gpu = points.to(device='cuda')
18 | ```
19 |
20 | 这段代码返回一个具有相同数值数据的新张量,但存储在GPU的RAM中,而不是常规的系统RAM中。
21 |
22 | 现在数据已经存放在本地的GPU中,当在张量上运行数字运算时,你可以看见很好的加速效果。并且,这个新GPU支持的张量的类也更改为`torch.cuda.FloatTensor`(一开始输入的类型为`torch.FloatTensor`;`torch.cuda.DoubleTensor`等等也存在对应关系)。在大部分样例中,基于CPU和GPU的张量都公开面向用户相同的API,这使得与繁琐数字运算过程中无关的代码的编写更加容易。
23 |
24 | 如果你的机器拥有多个GPU,你可以通过传递从零开始的整数来确定张量分配给哪个GPU,该整数标志着机器上的GPU下标:
25 |
26 | ```python
27 | points_gpu = points.to(device='cuda:0')
28 | ```
29 |
30 | 此时,在GPU上执行对张量的任何操作,例如将所有元素乘以一个常数。
31 |
32 | ```python
33 | points = 2 * points # 在CPU上做乘法
34 | points_gpu = 2 * points.to(device='cuda') # 在GPU上做乘法
35 | ```
36 |
37 | 请注意,当计算结果产生后,`points_gpu`的张量并不会返回到CPU。这里发生的是以下三个过程:
38 |
39 | 1. 将`points`张量复制到GPU
40 | 2. 在GPU上分配了一个新的张量,并用于存储乘法的结果
41 | 3. 返回该GPU张量的句柄
42 |
43 | 因此,如果你还想向结果加上一个常量:
44 |
45 | ```python
46 | points_gpu = points_gpu + 4
47 | ```
48 |
49 | 加法仍然在GPU上执行,并且没有信息流到CPU(除非您打印或访问得到的张量)。 如果要将张量移回CPU,你需要为`to`方法提供一个cpu参数:
50 |
51 | ```python
52 | points_cpu = points_gpu.to(device='cpu')
53 | ```
54 |
55 | 你可以使用速记方法`cpu`和`cuda`代替`to`方法来实现相同的目标
56 |
57 | ```python
58 | points_gpu = points.cuda() # 默认为GPU0
59 | points_gpu = points.cuda(0)
60 | points_cpu = points_gpu.cpu()
61 | ```
62 |
63 | 值得一提的是,使用`to`方法时,可以通过提供`device`和`dtype`参数来同时更改位置和数据类型。
--------------------------------------------------------------------------------
/docs/chapter2/2.9.md:
--------------------------------------------------------------------------------
1 | # 2.9 张量API
2 |
3 | 本节,你将知道PyTorch张量是什么以及在内部它们如何运行。在结束本章之前,我们还会看一下PyTorch提供的张量的操作。在这里列出所有操作没什么用,取而代之的是,我们将为你提供相关API的一般感觉并展示如何在[官方文档](http://pytorch.org/docs)中查找相关内容。
4 |
5 | 首先,在`torch`模块下可进行张量上和张量之间的绝大多数操作,这些操作也可以作为张量对象的方法进行调用。例如,你可以通过`torch`模块使用先前遇到的`transpose`函数:
6 |
7 | ``` python
8 | a = torch.ones(3, 2)
9 | a_t = torch.transpose(a, 0, 1)
10 | ```
11 |
12 | 或者调用`a`张量的方法:
13 |
14 | ```
15 | a = torch.ones(3, 2)
16 | a_t = a.transpose(0, 1)
17 | ```
18 |
19 | 以上两种形式之间没有区别,可以互换使用。需要注意的是:有少量的操作仅作为张量对象的方法存在。你可以通过名称中的下划线来识别它们,例如`zero_`,下划线标识表明该方法是就地(inplace)运行的,即直接修改输入而不是创建新的输出并返回。例如,`zero_`方法会将输入的所有元素清零。任何不带下划线的方法都将保持源张量不变并返回新的张量:
20 |
21 | ``` python
22 | a = torch.ones(3, 2)
23 | a.zero_()
24 | a
25 | ```
26 | 输出:
27 | ```
28 | tensor([[0., 0.],
29 | [0., 0.],
30 | [0., 0.]])
31 | ```
32 |
33 | 刚刚我们提到了[官方文档](http://pytorch.org/docs),它是详尽无遗并且组织合理的,它将张量操作分为几组:
34 |
35 | * 创建操作 —— 构造张量的函数,例如`ones`和`from_numpy`;
36 | * 索引、切片、联接和变异操作 —— 更改形状、步长或张量内容,例如`transpose`;
37 | * 数学操作 —— 通过计算来操纵张量内容的函数:
38 | * 按点(pointwise)操作 —— 将函数分别应用于每个元素(例如`abs`和`cos`)的函数
39 | * 简化(reduction)操作 —— 通过张量迭代计算合计值的函数,例如`mean`、`std`和`norm`;
40 | * 比较操作 —— 用于比较张量的函数,例如`equal`和`max`;
41 | * 频谱操作 —— 在频域中转换和运行的函数,例如`stft`和`hamming_window`;
42 | * 其他操作 —— 一些特殊函数,例如对于向量的`cross`,对于矩阵的`trace`;
43 | * BLAS和LAPACK操作 —— 遵循BLAS(Basic Linear Algebra Subprograms)规范的函数,用于标量、向量与向量、矩阵与向量和矩阵与矩阵的运算。
44 |
45 | * 随机采样操作 —— 从概率分布中随机采样值的函数,例如`randn`和`normal`;
46 | * 序列化操作 —— 用于保存和加载张量的函数,例如`save`和`load`;
47 | * 并行操作 —— 控制并行CPU执行的线程数的函数,例如`set_num_threads`;
48 |
49 | 动手探索常见张量API是很有帮助的。本章提供了此类交互式探索的所有先决知识。
50 |
51 | ## 练习
52 | * 从`list(range(9))`创建一个张量`a`,然后预测并验证一下尺寸、偏移和步长。
53 | * 创建一个张量`b = a.view(3, 3)`,`b[1,1]`的值是多少?
54 | * 创建一个张量`c = b [1:, 1:]`,然后预测并验证一下尺寸、偏移和步长。
55 | * 选择一个余弦或平方根之类的数学运算。你能找到在`torch`找到正确的对应方法吗?
56 | * 你刚刚选择的函数有就地(inplace)版本吗?
57 |
58 | ## 总结
59 |
60 | * 神经网络将浮点表示形式转换为其他浮点表示形式,起始和结束的表示形式通常是人类可以理解的,但中间表示则不是这样。
61 | * 这些浮点表示存储在张量中。
62 | * 张量是多维数组,它是PyTorch中的基本数据结构。
63 | * PyTorch有一个全面的标准库,用于张量创建、操作和数学运算。
64 | * 张量可以序列化存储到磁盘上也可以加载回来。
65 | * PyTorch中的所有张量操作都可以在CPU和GPU上执行,无需更改代码。
66 | * PyTorch使用结尾下划线标识来表示就地操作(例如`Tensor.sqrt_`)。
67 |
--------------------------------------------------------------------------------
/docs/chapter3/3.0.md:
--------------------------------------------------------------------------------
1 | # 3 使用张量表示真实数据
2 |
3 | 本章将介绍
4 |
5 | * 将不同类型的现实世界数据表示为PyTorch张量
6 | * 处理各种数据类型,包括电子表格、时间序列、文本、图像和医学成像
7 | * 从文件加载数据
8 | * 将数据转换为张量
9 | * 调整张量以便于它们可以用作神经网络模型的输入
10 |
11 | -------------------------------
12 |
13 | 张量是PyTorch中数据的基础。神经网络将张量输入并产生张量作为输出。实际上,神经网络内部和优化期间的所有操作都是张量之间的操作,而神经网络中的所有参数(例如权重和偏差)也都是张量。掌握如何在张量上执行操作并对其进行有效索引是成功使用PyTorch等工具的关键。现在你已经了解了张量的基本知识,你对它们灵活性的理解将会大大增强。
14 |
15 | 我们现在可以解决一个问题:你怎样获取一条数据、一段视频或一段文本,并且用张量表示它们,然后用适合于训练深度学习模型的方式进行处理。
16 |
17 | 答案就是你将在本章中所学到的内容。本章涵盖了不同类型的数据,并向你展示了如何使它们表示为张量。然后,我们向你展示如何从最常见的磁盘格式中加载数据,并了解这些数据类型的结构,以便于你可以理解怎样为训练神经网络做准备。通常,对于需要解决的问题,原始数据的格式可能并不完美,因此你将有机会在更多有趣的张量操作中练习你的张量处理技巧。你将使用大量的图像和立体数据,因为这些数据类型很常见并且可以以书本格式(book format)很好地复制。我们还将介绍表格数据、时间序列和文本,这也是许多读者感兴趣的。
18 |
19 | 本章的每个部分都会描述一种数据类型,并且每种数据类型都有其自己的数据集。尽管我们已经对本章进行了结构设计,以便于每种数据类型都建立在前一章的基础上,但如果你愿意,可以随时跳过去。
20 |
21 | 正如你在电子表格中所发现的一样,我们首先从关于葡萄酒数据的表格数据开始。接下来,我们转到有序的表格数据——来自共享单车程序的时间序列数据集。之后,我们向你展示如何使用Jane Austen的文本数据。文本数据保留了有序的方面,但是引入了将单词表示为数字数组的问题。因为一图胜千言,所以我们还演示了如何处理图像数据。最后,我们使用包含患者解剖结构的3D数组来深入研究医学数据。
22 |
23 | 在接下来的每个部分中,我们都会在深度学习研究者开始的地方停下来:在将数据输入模型之前。我们鼓励你保留这些数据集。当你开始学习如何训练神经网络模型时,它们将成为极好的数据集。
--------------------------------------------------------------------------------
/docs/chapter3/3.1.md:
--------------------------------------------------------------------------------
1 | # 3.1 表格数据
2 |
3 | 你在机器学习工作中遇到的最简单的数据形式是位于电子表格、CSV(以逗号分隔值)文件或数据库中的。无论使用哪种介质,此数据都是一个表格,每个样本(或记录)包含一行,其中的列包含这个样本的一条信息。
4 |
5 | 首先,我们假设样本在表格中的显示顺序是没有意义的。这与时间序列不同,这里的表是独立样本的集合,而在时间序列中,样本是在时间维度上相关的。
6 |
7 | 列可以包含数值型数据(例如特定位置的温度)或标签(例如表示样品属性的字符串,比如“蓝色”)。因此,表格数据通常不是同质的(homogeneous),不同的列有不同的类型。你可能有一列显示苹果的重量,另一列则用标签编码其颜色。
8 |
9 | 然而,PyTorch张量是同质的。其他数据科学软件包,例如Pandas,具有`dataframe`的概念,`dataframe`即用异构(heterogenous)的列来表示数据的对象。相比之下,PyTorch中的信息被编码为数字,通常为浮点数(尽管也支持整数类型)。(PyTorch中的)数值编码是有意为之的,因为神经网络是将实数作为输入并通过连续应用矩阵乘法和非线性函数产生实数作为输出的数学实体。
10 |
11 | 因此,作为深度学习从业人员,你的第一项工作是将异构的现实世界数据编码成浮点数张量以供神经网络使用。
12 |
13 | 互联网上提供大量免费的表格数据集,例如[awesome-public-data仓库](https://github.com/awesomedata/awesome-public-datasets)。
14 |
15 | 我们从有趣的东西开始:葡萄酒。葡萄酒质量数据集是可免费获得的表格数据,其中包含vinho verde(葡萄牙北部的葡萄酒)样品的化学表征以及感官质量评分。您可以从[此处](https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-white.csv)下载白葡萄酒的数据集。
16 |
17 | 该文件包含用逗号分隔的值的集合,总共12列,第一行是包含列名称的标题行。前11列包含化学变量的值。最后一列包含从0(最差)到10(优秀)的感官质量得分。以下是列名在数据集中显示的顺序:
18 | ```
19 | fixed acidity
20 | volatile acidity
21 | citric acid
22 | residual sugar
23 | chlorides
24 | free sulfur dioxide
25 | total sulfur dioxide
26 | density
27 | pH
28 | sulphates
29 | alcohol
30 | quality
31 | ```
32 |
33 | 针对此数据集可能的机器学习任务是通过化学表征来预测质量得分。不过,请放心,机器学习不会在短期内杀死葡萄酒品尝者,因为我们必须从某个地方获取训练数据!
34 |
35 | 如图3.1所示,你希望找到数据中的某一化学列与质量之间的关系。例如在此图中,你将看到质量随着硫含量减少而提高。
36 |
37 |
38 |

39 |
40 | 图3.1 葡萄酒中硫(sulfur)与品质的关系
41 |
42 | 但是,在进行该观察之前,你需要一种比在文本编辑器中打开文件更有用的方式检查数据。我们将向您展示如何使用Python加载数据,然后将其转换为PyTorch张量。
43 |
44 | Python提供了多个选项来快速加载CSV文件。三种常用的选择是
45 | * Python自带的`csv`模块
46 | * NumPy
47 | * Pandas
48 |
49 | 第三个选项是最省时和最省内存的方法,但是我们将避免仅仅是加载文件就将的额外的库引入学习曲线。因为我们已经介绍了NumPy,并且PyTorch具有出色的NumPy互操作性,所以您将继续使用NumPy来加载文件并将生成的NumPy数组转换为PyTorch张量,如下面的代码所示。
50 |
51 | ``` python
52 | import csv
53 | import numpy as np
54 | wine_path = "../../data/chapter3/winequality-white.csv"
55 | wineq_numpy = np.loadtxt(wine_path, dtype=np.float32, delimiter=";",
56 | skiprows=1)
57 | wineq_numpy
58 | ```
59 | 输出:
60 | ```
61 | array([[ 7. , 0.27000001, 0.36000001, ..., 0.44999999,
62 | 8.80000019, 6. ],
63 | [ 6.30000019, 0.30000001, 0.34 , ..., 0.49000001,
64 | 9.5 , 6. ],
65 | [ 8.10000038, 0.28 , 0.40000001, ..., 0.44 ,
66 | 10.10000038, 6. ],
67 | ...,
68 | [ 6.5 , 0.23999999, 0.19 , ..., 0.46000001,
69 | 9.39999962, 6. ],
70 | [ 5.5 , 0.28999999, 0.30000001, ..., 0.38 ,
71 | 12.80000019, 7. ],
72 | [ 6. , 0.20999999, 0.38 , ..., 0.31999999,
73 | 11.80000019, 6. ]], dtype=float32)
74 | ```
75 |
76 | 在这里,你指定了二维数组的类型(32位浮点数)和用于分隔每一行各值的分隔符,并指出不应读取第一行,因为它包含列名。接下来,检查是否已读取所有数据,
77 |
78 | ``` python
79 | col_list = next(csv.reader(open(wine_path), delimiter=';'))
80 | wineq_numpy.shape, col_list
81 | ```
82 | 输出:
83 | ```
84 | ((4898, 12),
85 | ['fixed acidity',
86 | 'volatile acidity',
87 | 'citric acid',
88 | 'residual sugar',
89 | 'chlorides',
90 | 'free sulfur dioxide',
91 | 'total sulfur dioxide',
92 | 'density',
93 | 'pH',
94 | 'sulphates',
95 | 'alcohol',
96 | 'quality'])
97 | ```
98 | 然后进一步将NumPy数组转成PyTorch张量:
99 |
100 | ``` python
101 | import torch
102 | wineq = torch.from_numpy(wineq_numpy)
103 | wineq.shape, wineq.type()
104 | ```
105 | 输出:
106 | ```
107 | (torch.Size([4898, 12]), 'torch.FloatTensor')
108 | ```
109 |
110 | 此时,你将拥有一个包含所有列的`torch.FloatTensor`,包括表示质量得分的最后一列。
111 |
112 | > 在尝试理解数据时,应注意三种数值。
113 | >
114 | > 第一种是连续(continuous)值。当以数字表示时,这些值是最直观的。它们是严格可排序的,各个值之间的差异具有严格的含义。例如,包裹A比包裹B重2公斤,或者包裹B的来源地比包裹A远100英里,这是有固定含义的,无论包裹A重3公斤还是10公斤,或者包裹B是来源于200英里还是2000英里之外。如果你要以单位进行计数或测量,那么得到的值可能就是连续值。
115 | >
116 | > 接下来是序数(ordinal)值。连续值的严格可排序性仍然保留,但是值之间的固定关系不再适用。一个很好的例子是订购小、中或大型饮料,将小号映射为值1,将中号映射为2,将大号映射为3。大号饮料大于中号,相同方式是3大于2,但它并没有告诉你大多少。如果要将1、2和3转换为实际体积(例如8、12和24盎司),则这些值就变成了连续值。一定要要记住,你不能对它们进行除了排序之外任何数学运算,尝试平均大和小杯不会得到中杯!
117 | >
118 | > 最后,类别(categorical)值既没有顺序也没有数值含义。这些值通常是可能性的枚举,并分配有任意数字。例如,将水分配给1,将咖啡分配给2,将苏打分配给3,将牛奶分配给4。水在前牛奶在后没有逻辑。你仅仅是需要不同的值来区分它们而已。你可以将咖啡分配给10,将牛奶分配给 –3,这不会带来明显变化(尽管当我们讨论独热(one-hot)编码时将分配值的范围设置成0..N-1会很有优势)。
119 |
120 | 你可以将(葡萄酒质量分数)分数视为连续变量,视为实数,然后进行回归任务;或者将其视为标签,作为分类任务尝试从化学分析猜出该标签。在这两种方法中,往往都将分数从输入数据的张量中删除,并将其保存在单独的张量中,以便将分数用作ground truth而不将其输入到模型中。
121 |
122 | ``` python
123 | data = wineq[:, :-1] # 除最后一列外所有列
124 | data, data.shape
125 | ```
126 | 输出:
127 | ```
128 | (tensor([[ 7.0000, 0.2700, 0.3600, ..., 3.0000, 0.4500, 8.8000],
129 | [ 6.3000, 0.3000, 0.3400, ..., 3.3000, 0.4900, 9.5000],
130 | [ 8.1000, 0.2800, 0.4000, ..., 3.2600, 0.4400, 10.1000],
131 | ...,
132 | [ 6.5000, 0.2400, 0.1900, ..., 2.9900, 0.4600, 9.4000],
133 | [ 5.5000, 0.2900, 0.3000, ..., 3.3400, 0.3800, 12.8000],
134 | [ 6.0000, 0.2100, 0.3800, ..., 3.2600, 0.3200, 11.8000]]),
135 | torch.Size([4898, 11]))
136 | ```
137 |
138 | ``` python
139 | target = wineq[:, -1] # 最后一列
140 | target, target.shape
141 | ```
142 | 输出:
143 | ```
144 | (tensor([6., 6., 6., ..., 6., 7., 6.]), torch.Size([4898]))
145 | ```
146 |
147 | 如果你想将`target`张量转换成标签张量,那么你有两个选择,具体取决于策略或使用分类数据的方式。第一种选择是将标签视为整数向量:
148 |
149 | ``` python
150 | target = wineq[:, -1].long()
151 | target
152 | ```
153 | 输出:
154 | ```
155 | tensor([6, 6, 6, ..., 6, 7, 6])
156 | ```
157 |
158 | 如果目标是字符串标签(例如颜色),则可以采用相同的方法为每个字符串分配一个整数。
159 |
160 | 另一种选择是构建独热(one-hot)编码,即将10个分数编码成10个向量,每个向量除了一个元素为1外其他所有元素都设置为0。此时,分数1可以映射到向量(1,0,0,0,0,0,0,0,0,0),分数5映射到(0,0,0,0,1,0,0,0,0,0),等等。分数值与非零元素的索引相对应的事实纯属偶然;你可以打乱上述分配,从分类的角度来看,什么都不会改变。
161 |
162 | 上述两种方法有明显的区别。将葡萄酒质量分数编码成分数的整数向量中会引入了分数的可排序性,在这个例子下可能是适当的,因为分数1低于分数4。这还会在分数之间产生一定的距离(例如1和3之间的距离与2和4之间的距离相同。)如果这符合你的定量关系,那就太好了。否则,如果分数纯粹是定性的(例如颜色),则独热编码更适合,因为它不涉及隐含的顺序或距离关系。当整数之间的分数值(例如2.4)对应用没有意义时(即要么是这个值要么是那个值),单热编码才适用。
163 |
164 | 您可以使用`scatter_`方法来实现独热编码,该方法将源张量中的值沿作为参数提供的索引进行填充。
165 |
166 | ``` python
167 | target_onehot = torch.zeros(target.shape[0], 10)
168 | target_onehot.scatter_(1, target.unsqueeze(1), 1.0)
169 | ```
170 | 输出:
171 | ```
172 | tensor([[0., 0., 0., ..., 0., 0., 0.],
173 | [0., 0., 0., ..., 0., 0., 0.],
174 | [0., 0., 0., ..., 0., 0., 0.],
175 | ...,
176 | [0., 0., 0., ..., 0., 0., 0.],
177 | [0., 0., 0., ..., 1., 0., 0.],
178 | [0., 0., 0., ..., 0., 0., 0.]])
179 | ```
180 |
181 | 现在看一下`scatter_`的作用。 首先请注意,其名称下划线结尾。PyTorch中,此约定表示该方法不会返回新的张量,而是就地修改源张量。 `scatter_`的参数是
182 | * 指定后面两个参数所处理的维度
183 | * 列张量,指示要填充的索引
184 | * 包含填充元素的张量或者单个标量(上例中即1.0)
185 |
186 | 换句话说,前面的调用可以这样理解:“对于每一行,获取目标标签的索引(在本例中即葡萄酒质量分数),并将其用作列索引以设置值为1.0。结果就是得到了一个编码分类信息的张量。”
187 |
188 | `scatter_`的第二个参数,即索引张量,必须具有与待填充张量相同的维数。由于`target_onehot`是二维(4898x10)的,因此你需要使用`unsqueeze`为`target`添加一个额外的维:
189 |
190 | ``` python
191 | target_unsqueezed = target.unsqueeze(1)
192 | target_unsqueezed
193 | ```
194 | 输出:
195 | ```
196 | tensor([[6],
197 | [6],
198 | [6],
199 | ...,
200 | [6],
201 | [7],
202 | [6]])
203 | ```
204 |
205 | 调用`unsqueeze`增加了一个单例的维度,从包含4898个元素的一维张量到尺寸为(4898x1)的二维张量,其内容并未改变。没有添加新元素;你决定使用额外的索引来访问元素。也就是说,你用`target[0]`访问`target`的第一个元素,并用`target_unsqueezed[0,0]`访问其未压缩(unsqueezed)对象的第一个元素。
206 |
207 | PyTorch允许你在训练神经网络时直接将类别索引用作目标。但是,如果要用作网络的分类输入,则必须将其转换为独热编码张量。
208 |
209 | 现在回到`data`张量,其中包含与化学分析关联的11个变量。你可以使用PyTorch张量API中的函数以张量形式处理数据。首先,获取每列的均值和标准差:
210 |
211 | ``` python
212 | data_mean = torch.mean(data, dim=0)
213 | data_mean
214 | ```
215 | 输出:
216 | ```
217 | tensor([6.8548e+00, 2.7824e-01, 3.3419e-01, 6.3914e+00, 4.5772e-02, 3.5308e+01,
218 | 1.3836e+02, 9.9403e-01, 3.1883e+00, 4.8985e-01, 1.0514e+01])
219 | ```
220 |
221 | ``` python
222 | data_var = torch.var(data, dim=0)
223 | data_var
224 | ```
225 | 输出:
226 | ```
227 | tensor([7.1211e-01, 1.0160e-02, 1.4646e-02, 2.5726e+01, 4.7733e-04, 2.8924e+02,
228 | 1.8061e+03, 8.9455e-06, 2.2801e-02, 1.3025e-02, 1.5144e+00])
229 | ```
230 |
231 | 在此例中,`dim = 0`表示沿维数0进行计算。此时,你可以通过减去平均值并除以标准偏差来对数据进行归一化,这有助于学习过程。
232 |
233 | ``` python
234 | data_normalized = (data - data_mean) / torch.sqrt(data_var)
235 | data_normalized
236 | ```
237 | 输出:
238 | ```
239 | tensor([[ 1.7209e-01, -8.1764e-02, 2.1325e-01, ..., -1.2468e+00,
240 | -3.4914e-01, -1.3930e+00],
241 | [-6.5743e-01, 2.1587e-01, 4.7991e-02, ..., 7.3992e-01,
242 | 1.3467e-03, -8.2418e-01],
243 | [ 1.4756e+00, 1.7448e-02, 5.4378e-01, ..., 4.7502e-01,
244 | -4.3677e-01, -3.3662e-01],
245 | ...,
246 | [-4.2042e-01, -3.7940e-01, -1.1915e+00, ..., -1.3131e+00,
247 | -2.6152e-01, -9.0544e-01],
248 | [-1.6054e+00, 1.1666e-01, -2.8253e-01, ..., 1.0048e+00,
249 | -9.6250e-01, 1.8574e+00],
250 | [-1.0129e+00, -6.7703e-01, 3.7852e-01, ..., 4.7502e-01,
251 | -1.4882e+00, 1.0448e+00]])
252 | ```
253 |
254 | 接下来,我们来审查数据以寻找一种简单的方法来一眼分辨好酒和坏酒。首先,使用`torch.le`函数确定`target`中哪些行对应的分数小于或等于3:
255 |
256 | ``` python
257 | bad_indexes = torch.le(target, 3)
258 | bad_indexes.shape, bad_indexes.dtype, bad_indexes.sum()
259 | ```
260 | 输出:
261 | ```
262 | (torch.Size([4898]), torch.bool, tensor(20))
263 | ```
264 |
265 | 注意,`bad_indexes`中只有20个元素为1!通过利用PyTorch中称为高级索引(advanced indexing)的功能,可以使用0/1张量来索引数据张量。此张量本质上将数据筛选为仅与索引张量中的1对应的元素(或行)。`bad_indexes`张量具有与`target`相同的形状,其值是0或1,具体取决于阈值与原始`target`张量中每个元素之间比较结果:
266 |
267 | ``` python
268 | bad_data = data[bad_indexes]
269 | bad_data.shape
270 | ```
271 | 输出:
272 | ```
273 | torch.Size([20, 11])
274 | ```
275 |
276 | 请注意,新的`bad_data`张量只有20行,这与`bad_indexes`张量1的个数相同。另外,`bad_data`保留所有11列。
277 |
278 | 现在,你可以开始获取被分为好、中、坏三类的葡萄酒的信息。对每列取`.mean`:
279 |
280 | ``` python
281 | bad_data = data[torch.le(target, 3)]
282 | # 对于numpy数组和PyTorch张量,&运算符执行逻辑和运算
283 | mid_data = data[torch.gt(target, 3) & torch.lt(target, 7)]
284 | good_data = data[torch.ge(target, 7)]
285 |
286 | bad_mean = torch.mean(bad_data, dim=0)
287 | mid_mean = torch.mean(mid_data, dim=0)
288 | good_mean = torch.mean(good_data, dim=0)
289 |
290 | for i, args in enumerate(zip(col_list, bad_mean, mid_mean, good_mean)):
291 | print('{:2} {:20} {:6.2f} {:6.2f} {:6.2f}'.format(i, *args))
292 | ```
293 | 输出:
294 | ```
295 | 0 fixed acidity 7.60 6.89 6.73
296 | 1 volatile acidity 0.33 0.28 0.27
297 | 2 citric acid 0.34 0.34 0.33
298 | 3 residual sugar 6.39 6.71 5.26
299 | 4 chlorides 0.05 0.05 0.04
300 | 5 free sulfur dioxide 53.33 35.42 34.55
301 | 6 total sulfur dioxide 170.60 141.83 125.25
302 | 7 density 0.99 0.99 0.99
303 | 8 pH 3.19 3.18 3.22
304 | 9 sulphates 0.47 0.49 0.50
305 | 10 alcohol 10.34 10.26 11.42
306 | ```
307 |
308 | 乍一看,劣质葡萄酒似乎具有更高的二氧化硫总含量(total sulfur dioxide),另外还有其他差异。你可以使用二氧化硫总含量的阈值作为区分好酒和差酒的粗略标准。现在获取二氧化硫总含量列中低于你刚刚计算的中值的索引,如下所示:
309 |
310 | ``` python
311 | total_sulfur_threshold = 141.83
312 | total_sulfur_data = data[:,6]
313 | predicted_indexes = torch.lt(total_sulfur_data, total_sulfur_threshold)
314 | predicted_indexes.shape, predicted_indexes.dtype, predicted_indexes.sum()
315 | ```
316 | 输出:
317 | ```
318 | (torch.Size([4898]), torch.bool, tensor(2727))
319 | ```
320 |
321 | 上面的阈值预测略高于一半的葡萄酒是高品质的。
322 |
323 | 接下来,你需要获取(实际)优质葡萄酒的索引
324 |
325 | ``` python
326 | actual_indexes = torch.gt(target, 5)
327 | actual_indexes.shape, actual_indexes.dtype, actual_indexes.sum()
328 | ```
329 | 输出:
330 | ```
331 | (torch.Size([4898]), torch.bool, tensor(3258))
332 | ```
333 |
334 | 由于实际的优质葡萄酒比阈值预测的多约500例,这证明该阈值并不完美。
335 |
336 | 现在,你需要查看预测与实际的吻合程度。在预测索引和实际索引之间执行逻辑与运算(请记住,每个索引都是0/1数组)得到交集,用这个交集来确定预测表现如何:
337 |
338 | ``` python
339 | n_matches = torch.sum(actual_indexes & predicted_indexes).item()
340 | n_predicted = torch.sum(predicted_indexes).item()
341 | n_actual = torch.sum(actual_indexes).item()
342 | n_matches, n_matches / n_predicted, n_matches / n_actual
343 | ```
344 | 输出:
345 | ```
346 | (2018, 0.74000733406674, 0.6193984039287906)
347 | ```
348 |
349 | 有大约2,000例葡萄酒预测对了!因为预测有大约2700例(高品质)葡萄酒,所以有74%的可能性确实是高品质的。不幸的是,实际有约3200例优质葡萄酒,仅预测出了61%。好吧,我们猜你已经知道了,这个结果仅比随机猜要好一点点。
350 |
351 | 当然,这个例子太天真了。你可以肯定地知道,葡萄酒的质量受多个变量影响,并且,这些变量的值与质量(可能是实际得分,而不是好/坏这种二值)之间的关系很可能比简单的单个值的阈值更复杂。
352 |
353 | 实际上,一个简单的神经网络就将克服所有这些缺点,就像许多其他基本的机器学习方法一样。在完成第5章和第6章后,你将拥有解决此问题的工具,在第5章中,你将从头开始构建第一个神经网络。
--------------------------------------------------------------------------------
/docs/chapter3/3.2.md:
--------------------------------------------------------------------------------
1 | # 3.2 时间序列
2 |
3 | 在上一节中,我们介绍了如何表示已经在平面表格中组织好的数据。正如我们之前所说,表格中的每一行都独立于其他行,他们的顺序页没有任何关系。并且,没有提供有关行之前和行之后的列编码信息。
4 |
5 | 回到葡萄酒数据集,你可能有一个`Year`栏可以查看葡萄酒质量如何逐年变化。(很遗憾,我们手头没有此类数据,但我们正在努力逐瓶地手动收集数据样本。)
6 |
7 | 同时,我们切换到另一个有趣的数据集:华盛顿特区自行车共享系统中的数据,报告了2011年至2012年之间首都自行车共享系统中租用自行车的每小时计数以及相应的天气和季节性信息。
8 |
9 | 我们的目的是获取平面2D数据集并将其转换为3D数据集,如图3.2所示。
10 |
11 |
12 |

13 |
14 | 图3.2 分割样本的日期和小时为独立的轴,将一维多通道数据集转换为二维多通道数据集
15 |
16 | 在源数据中,每一行是单独一个小时的数据(图3.2显示该数据的转置版本以更好地适合打印页面。)我们想改变行-小时的组织方式,这样你就可以使一个轴以天的速度增加,而另一个轴代表一天中的小时(与日期无关)。第三个轴每一列数据不同(天气,温度等)。
17 |
18 | 加载数据,如以下代码:
19 |
20 | ```python
21 | bikes_numpy = np.loadtxt("../../data/chapter3/hour-fixed.csv",
22 | dtype=np.float32,
23 | delimiter=",",
24 | skiprows=1,
25 | converters={1: lambda x: float(x[8:10])})
26 | bikes = torch.from_numpy(bikes_numpy)
27 | bikes
28 | ```
29 |
30 | 输出:
31 |
32 | ```python
33 | tensor([[1.0000e+00, 1.0000e+00, ..., 1.3000e+01, 1.6000e+01],
34 | [2.0000e+00, 1.0000e+00, ..., 3.2000e+01, 4.0000e+01],
35 | ...,
36 | [1.7378e+04, 3.1000e+01, ..., 4.8000e+01, 6.1000e+01],
37 | [1.7379e+04, 3.1000e+01, ..., 3.7000e+01, 4.9000e+01]])
38 | ```
39 |
40 | 每个小时,数据集都会报告以下变量:
41 |
42 | ```
43 | instant # index of record #索引记录
44 | day # day of month #一个月中的某天
45 | season # season (1: spring, 2: summer, 3: fall, 4: winter) #季节(1:春天,2:夏天,3:秋天,4:冬天)
46 | yr # year (0: 2011, 1: 2012) #年份
47 | mnth # month (1 to 12) #月
48 | hr # hour (0 to 23) #小时
49 | holiday # holiday status #假期状态
50 | weekday # day of the week #一周的某天
51 | workingday # working day status #工作状态
52 | weathersit # weather situation #天气情况
53 | # (1: clear, 2:mist, 3: light rain/snow, 4: heavy rain/snow) #1:晴,2:薄雾,3:小雨/雪,4:大雨/雪
54 | temp # temperature in C #摄氏温度
55 | atemp # perceived temperature in C #感知温度(摄氏度)
56 | hum # humidity #湿度
57 | windspeed # windspeed #风速
58 | casual # number of causal users #因果用户数
59 | registered # number of registered users #注册用户数
60 | cnt # count of rental bikes #出租自行车数
61 | ```
62 |
63 | 在此类的时间序列数据集中,行表示连续的时间点:按其排序来制定维度。当然,你可以将每一行视为独立行,并尝试根据例如一天中的特定时间来预测循环的自行车数量,而不管之前发生的事情如何。
64 |
65 | 但是,这种排序使你有机会利用因果关系去跨越时间。例如,你可以根据先前下雨的情况来预测一次自行车的骑行次数。暂且将你的注意力放在学习如何将自行车共享数据集转化为你的神经网络可以以固定大小提取的数据块。
66 |
67 | 这个神经网络模型需要查看每种数据的值序列,例如乘车次数,一天中的时间,温度和天气状况,因此`N`个并行的大小为`C`的并行序列。`C`代表通道(`channel`),在神经网络中,它与此处所用的一维数据列(`column`)相同。 `N`维代表时间轴,这里是每小时输入一次。
68 |
69 | 你可能希望在更长的收集期内(例如天)拆分2年数据集。以这种方式,你将获得`N`个样本数(`number of samples`),样本由长度为`L`的`C`个序列的集合。换句话说,你的时间序列数据集是维度为3的张量,形状为`N x C xL`。`C`仍然是 17个通道,而`L`则是一天中的24个小时通道。没有必要特别说明为什么我们必须使用24小时这一时间段,尽管一般的日常的生活节奏可能会给我们提供可用于预测的模式。如果需要,我们可以改为使用7 * 24 = 168个小时块来按周划分数据集。
70 |
71 | 现在回到你的自行车共享数据集。第一列是索引(数据的全局顺序);第二个是日期;第六个是一天中的时间点。你拥有可以创建行驶计数和其他变量等日常序列数据集所需的一切。一般情况下你的数据集已经排好序,但是如果一旦没有排序,你可以在其上使用`torch.sort`进行适当排序。
72 |
73 | > 请注意:
74 | >
75 | > 你在此处使用的文件的版本`hour-fixed.csv`已经过一些处理,以包含原始数据集中缺少的行。 我们假设丢失的时间数据有零个自行车处于活动状态(通常是清晨的时间)。
76 |
77 | 要获取每日工作时间数据集,你要做的就是每隔24小时查看同一个张量。看看你的自行车(`bikes`)张量的形状和步幅:
78 |
79 | ```python
80 | bikes.shape, bikes.stride()
81 | ```
82 |
83 | 输出:
84 |
85 | ```python
86 | (torch.Size([17520, 17]), (17, 1))
87 | ```
88 |
89 | 这是17,520小时,共17列。现在将数据重新排列为具有三个轴(日期,小时,然后是17列)。
90 |
91 | ```python
92 | daily_bikes = bikes.view(-1, 24, bikes.shape[1])
93 | daily_bikes.shape, daily_bikes.stride()
94 | ```
95 |
96 | 输出:
97 |
98 | ```python
99 | (torch.Size([730, 24, 17]), (408, 17, 1))
100 | ```
101 |
102 | 这里发生了什么?首先,`bikes.shape [1]`为`17`,它是自行车(`bikes`)张量中的列数。 但是代码的真正难点在于调用视图(`view`),这一点很重要:它改变了查看相同数据张量的方式。
103 |
104 | 在张量上调用视图方法(`view`)返回一个新的张量,该张量可以更改维数和步幅信息,而无需更改存储。结果,你可以以零成本重新布置张量因为根本没有数据被复制。你的视图(`view`)调用要求你为返回的张量提供新的形状。将`-1`用作占位符是为了“但是考虑到其他维度和元素的原始数量,还剩下很多索引”。
105 |
106 | 记住在这种情况下,存储(`Storage`)是连续的数字的线性容器——浮点数。你的自行车(`bikes`)张量在相应的存储中逐行存储,这一点已通过早期对`bikes.stride()`的调用输出确认。
107 |
108 | 对于`daily_bikes`,步幅告诉你沿小时维度(第二个)前进1个位置需要你将存储(或一组列)中的位置前进17个位置,而沿日期维度(第一个)前进则需要你在时间24小时中前进等于行长度的元素数(此处为408,即17 * 24)。
109 |
110 | 最右边的维度是原始数据集中的列数。在中间维度中,你将时间分为24个连续小时的块。换句话说,你现在每天有`C`个通道的`N`个`L`小时的序列。为了获得你所需的`NxCxL`顺序,你需要转置张量:
111 |
112 | ```python
113 | daily_bikes = daily_bikes.transpose(1, 2)
114 | daily_bikes.shape, daily_bikes.stride()
115 | ```
116 |
117 | 输出:
118 |
119 | ```python
120 | (torch.Size([730, 17, 24]), (408, 1, 17))
121 | ```
122 |
123 | 前面我们提到天气状况变量是有序数。实际上,它有4个等级:`1`表示最佳天气,而`4`表示最坏的天气。你可以将此变量视为分类变量,其级别解释为标签或者连续标签。如果你选择分类,则将变量转换为独热编码的向量,并将列与数据集连接起来。为了使你的数据渲染更容易,现在暂时限制为第一天。首先,初始化一个零填充矩阵,其行数等于一天中的小时数,列数等于天气等级的数:
124 |
125 | ```python
126 | first_day = bikes[:24].long()
127 | weather_onehot = torch.zeros(first_day.shape[0], 4)
128 | first_day[:,9]
129 | ```
130 |
131 | 输出:
132 |
133 | ```python
134 | tensor([1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2])
135 | ```
136 |
137 | 然后根据每一行的相应的等级将它们分散到我们的矩阵中。请记住,在之前需要使用取消压缩(`unsqueeze`)来添加单例尺寸:
138 |
139 | ```python
140 | weather_onehot.scatter_(
141 | dim=1,
142 | index=first_day[:,9].unsqueeze(1) - 1,
143 | value=1.0)
144 | ```
145 |
146 | 输出:
147 |
148 | ```python
149 | tensor([[1., 0., 0., 0.],
150 | [1., 0., 0., 0.],
151 | ...,
152 | [0., 1., 0., 0.],
153 | [0., 1., 0., 0.]])
154 | ```
155 |
156 | 这一天从`1`级天气开始到`2`级天气结束,所以这似乎是正确的。
157 |
158 | 最后,使用`cat`函数将矩阵连接到原始数据集。看你的第一个结果:
159 |
160 | ```python
161 | torch.cat((bikes[:24], weather_onehot), 1)[:1]
162 | ```
163 |
164 | 输出:
165 |
166 | ```python
167 | tensor([[ 1.0000, 1.0000, 1.0000, 0.0000, 1.0000, 0.0000, 0.0000, 6.0000,
168 | 0.0000, 1.0000, 0.2400, 0.2879, 0.8100, 0.0000, 3.0000, 13.0000,
169 | 16.0000, 1.0000, 0.0000, 0.0000, 0.0000]])
170 | ```
171 |
172 | 在这里,你指定了原始自行车(`bikes`)数据集和独热编码的天气情况矩阵,这些矩阵将沿列维(例如`1`)连接在一起。换句话说,将两个数据集的列堆叠在一起,或者将新的独热编码列追加到原始数据集。为了使`cat`成功,张量必须与其他维度(行维度在这种情况也想通)有相同的大小。
173 |
174 | 请注意,你最后的新四列分别是`1,0,0,0`——这正是你所期望的天气等级`1`。
175 |
176 | 你也可以使用重新排列的`daily_bikes`张量完成相同的操作。请记住,它的形状为`(B,C,L)`,其中`L=24`。首先创建零张量,有相同的`B`和`L`,但增加的列数与`C`:
177 |
178 | ```python
179 | daily_weather_onehot = torch.zeros(daily_bikes.shape[0], 4,
180 | daily_bikes.shape[2])
181 | daily_weather_onehot.shape
182 | ```
183 |
184 | 输出:
185 |
186 | ```python
187 | torch.Size([730, 4, 24])
188 | ```
189 |
190 | 然后将独热编码散布到`C`维中的张量中。由于操作是在原地执行的,因此仅张量的内容会更改:
191 |
192 | ```python
193 | daily_weather_onehot.scatter_(1, daily_bikes[:,9,:].long().unsqueeze(1) - 1,
194 | 1.0)
195 | daily_weather_onehot.shape
196 | ```
197 |
198 | 输出:
199 |
200 | ```python
201 | torch.Size([730, 4, 24])
202 | ```
203 |
204 | 沿`C`维度连接:
205 |
206 | ```python
207 | daily_bikes = torch.cat((daily_bikes, daily_weather_onehot), dim=1)
208 | ```
209 |
210 | 我们之前提到过,这种方法并不是处理天气情况变量的唯一方法。实际上,其标签具有序数关系因此你可以暂时认为它们是连续变量的特殊值。你可以转换变量,使其从`0.0`到`1.0`运行:
211 |
212 | ```python
213 | daily_bikes[:, 9, :] = (daily_bikes[:, 9, :] - 1.0) / 3.0
214 | ```
215 |
216 | 正如我们将会在第4.1节中提到,重新缩放变量为`[0.0,1.0]`区间或`[-1.0,1.0]`区间是你需要对所有的变量进行的操作,例如温度(`temperature`)(数据集中的第10列)。稍后你将会看到其原因;对于现在,我们说这对训练过程会很有帮助。
217 |
218 | 你有多种重新调整变量的方式。你可以将其范围映射到`[0.0,1.0]`。
219 |
220 | ```python
221 | temp = daily_bikes[:, 10, :]
222 | temp_min = torch.min(temp)
223 | temp_max = torch.max(temp)
224 | daily_bikes[:, 10, :] = (daily_bikes[:, 10, :] - temp_min) / (temp_max -
225 | temp_min)
226 | ```
227 |
228 | 或减去平均值并除以标准差:
229 |
230 | ```python
231 | temp = daily_bikes[:, 10, :]
232 | daily_bikes[:, 10, :] = (daily_bikes[:, 10, :] - torch.mean(temp)) /
233 | torch.std(temp)
234 | ```
235 |
236 | 在后一种情况下,变量的平均值为零并且标准差为零。如果取自高斯分布,则68%的样本将位于`[-1.0,1.0]`区间。
237 |
238 | 太棒了——你建立了另一个不错的数据集并且你以后将使用它。就目前而言,最重要的是你必须了解时间序列的布局方式以及如何将数据整理成网络可以读取的形式。
239 |
240 | 必须存在严格的排序其他类型的数据才可以看做时间序列。该类别中的前两名是文本和音频。
--------------------------------------------------------------------------------
/docs/chapter3/3.3.md:
--------------------------------------------------------------------------------
1 | # 3.3 文本数据
2 |
3 | 深度学习席卷了自然语言处理(natural language processing, NLP)领域,尤其是通过使用不断消耗输入和模型先前输出相结合的模型。这种模型称为递归神经网络(recurrent neural networks, RNN),它已被成功应用于文本分类、文本生成和自动翻译系统。在这之前的NLP工作的特点是复杂的多阶段处理流程,包括编码语言语法的规则。
4 | > * Nadkarni et al., “Natural language processing: an introduction”. JAMIA https://www.ncbi.nlm.nih.gov/pmc/arti-cles/PMC3168328
5 | > * Wikipedia entry for natural language processing: https://en.wikipedia.org/wiki/Natural-language_processing
6 |
7 | 目前,最先进的(state-of-the-art)工作在大型语料库上端到端地从头开始训练网络,让这些规则从数据中浮现出来。在过去的几年中,互联网上最常用的自动翻译系统服务就是基于深度学习的。
8 |
9 | 在本章中,你的目标是将文本转换成神经网络可以处理的东西,就像前面的例子一样,即数值张量。在处理成数值张量之后,再为你的文本处理工作选择正确的网络结构,然后就可以使用PyTorch进行NLP了。你马上就会看到此功能的强大之处:如果你以正确的形式提出了问题,就可以使用相同的PyTorch工具在不同领域中的任务上达到目前最先进的性能。这项工作的第一部分是重塑数据。
10 |
11 | 网络在两个级别上对文本进行操作:在字符级别上,一次处理一个字符;而在单词级别上,单词是网络中最细粒度的实体。无论是在字符级别还是在单词级别操作,将文本信息编码为张量形式的技术都是相同的。这种技术没什么神奇的,你之前已经用过了,即独热编码。
12 |
13 | 我们从字符级示例开始。首先,获取一些文本进行处理。[Gutenberg项目](http://www.gutenberg.org/)是一个很棒的资源,它是一项志愿性的工作,它对文化作品进行数字化并存档,并使其以开放格式(包括纯文本文件)免费提供。如果你的目标是大型语料库,那么维基百科语料库就非常出色:它是维基百科文章的完整集合,其中包含19亿个单词和超过440万条文章。你可以在[英语语料库网站](https://www.english-corpora.org/)上找到其他几种语料库。
14 |
15 | 从Gutenberg项目网站上加载Jane Austen的《傲慢与偏见》[(点击下载)](http://www.gutenberg.org/files/1342/1342-0.txt)。保存文件并读入文件,如下所示。
16 |
17 | ``` python
18 | with open('../../data/chapter3/1342-0.txt', encoding='utf8') as f:
19 | text = f.read()
20 | ```
21 |
22 | 在继续之前,你需要先注意一个细节:编码(encoding)。编码是一个宽泛的词,因此我们现在要做的就是实际“触摸”它。每个字符都由一个代码表示,该代码是一系列适当长度的比特(bit)位,它可以唯一地标识每个字符。最简单的这种编码是ASCII(American Standard Code for Information Interchange),其历史可以追溯到1960年代。ASCII使用128个整数对128个字符进行编码。例如,字母“a”对应于二进制`1100001`或十进制97;字母“b”对应于二进制`1100010`或十进制98,依此类推。该编码刚好8位,这在1965年是一个很大的收获。
23 |
24 | > 注意:显然,128个字符不足以正确表示除英语之外的其他书面文字所需的所有字形、字音、连字等等。为此,其他编码被开发了出来,用更多的比特位代码表示更大范围的字符。更大范围的字符被标准化为Unicode编码,它将所有已知字符映射为数字,这些数字的位表示由特定编码提供。流行的编码包括UTF-8、UTF-16和UTF-32,对应数字分别是8位、16位或32位整数的序列。 Python 3.x中的字符串是Unicode字符串。
25 |
26 | 你将对字符进行独热编码,以将独热编码限制为对要分析的文本有用的字符集。在本例中,因为你以英文加载了文本,所以使用ASCII这种小型编码是非常安全的。你也可以将所有字符都转换为小写,以减少编码中的字符数。同样,你还可以筛选出与预期的文本类型无关的标点符号、数字和其他字符,这可能会也可能不会对你的神经网络产生实际的影响,具体取决于手头的任务。
27 |
28 | 此时,你需要解析文本中的字符,并为每个字符进行独热编码。 每个字符将由一个长度等于编码中字符数的向量表示。该向量除了有一个元素是1外其他全为0,这个1的索引对应该字符在字符集中的位置。
29 |
30 | 首先,将文本分成若干行,然后选择任意一行:
31 |
32 | ``` python
33 | lines = text.split('\n')
34 | line = lines[200]
35 | line
36 | ```
37 | 输出:
38 | ```
39 | '“Impossible, Mr. Bennet, impossible, when I am not acquainted with him'
40 | ```
41 |
42 | 创建一个张量,该张量可以容纳整行的独热编码的字符总数:
43 |
44 | ``` python
45 | letter_tensor = torch.zeros(len(line), 128) # 128是由于ASCII的限制
46 | letter_tensor.shape
47 | ```
48 | 输出:
49 | ```
50 | torch.Size([70, 128])
51 | ```
52 |
53 | 请注意,`letter_tensor`每行将要表示一个独热编码字符。现在在每一行正确位置上设置成1,以使每一行代表正确的字符。设置1的索引对应于编码中字符的索引:
54 |
55 | ``` python
56 | for i, letter in enumerate(line.lower().strip()):
57 | # 文本里含有双引号,不是有效的ASCII,因此在此处将其屏蔽
58 | letter_index = ord(letter) if ord(letter) < 128 else 0
59 | letter_tensor[i][letter_index] = 1
60 | ```
61 |
62 | 你已经将句子独热编码成神经网络可以使用的表示形式。你也可以沿张量的行,通过建立词汇表来在词级别(word-level)对句子(即词序列)进行独热编码。由于词汇表包含许多单词,因此该方法会产生可能不是很实际的很宽的编码向量。在本章的后面,你将看到一种更有效的方式,通过使用嵌入(embedding)来在单词级别表示文本。现在,坚持独热编码,看看会发生什么。
63 |
64 | 定义`clean_words`函数,它接受文本并将其返回小写并删除标点符号。在“Impossible, Mr. Bennet”行上调用它时,会得到以下信息:
65 |
66 | ``` python
67 | def clean_words(input_str):
68 | punctuation = '.,;:"!?”“_-'
69 | word_list = input_str.lower().replace('\n',' ').split()
70 | word_list = [word.strip(punctuation) for word in word_list]
71 | return word_list
72 | words_in_line = clean_words(line)
73 | line, words_in_line
74 | ```
75 | 输出:
76 | ```
77 | ('“Impossible, Mr. Bennet, impossible, when I am not acquainted with him',
78 | ['impossible',
79 | 'mr',
80 | 'bennet',
81 | 'impossible',
82 | 'when',
83 | 'i',
84 | 'am',
85 | 'not',
86 | 'acquainted',
87 | 'with',
88 | 'him'])
89 | ```
90 |
91 | 接下来,在编码中建立单词到索引的映射:
92 |
93 | ``` python
94 | word_list = sorted(set(clean_words(text)))
95 | word2index_dict = {word: i for (i, word) in enumerate(word_list)}
96 | len(word2index_dict), word2index_dict['impossible']
97 | ```
98 | 输出:
99 | ```
100 | (7261, 3394)
101 | ```
102 |
103 | 请注意,`word2index_dict`现在是一个字典,其中单词作为键,而整数作为值。独热编码时,你将使用此词典来有效地找到单词的索引。
104 |
105 | 现在专注于句子,将其分解为单词并对其进行独热编码(即对每个单词使用一个独热编码向量来填充张量)。先创建一个空向量,然后赋值成句子中的单词的独热编码:
106 |
107 | ``` python
108 | word_tensor = torch.zeros(len(words_in_line), len(word2index_dict))
109 | for i, word in enumerate(words_in_line):
110 | word_index = word2index_dict[word]
111 | word_tensor[i][word_index] = 1
112 | print('{:2} {:4} {}'.format(i, word_index, word))
113 |
114 | print(word_tensor.shape)
115 | ```
116 | 输出:
117 | ```
118 | 0 3394 impossible
119 | 1 4305 mr
120 | 2 813 bennet
121 | 3 3394 impossible
122 | 4 7078 when
123 | 5 3315 i
124 | 6 415 am
125 | 7 4436 not
126 | 8 239 acquainted
127 | 9 7148 with
128 | 10 3215 him
129 | torch.Size([11, 7261])
130 | ```
131 |
132 | 此时,`word_tensor`表示长度为11编码长度为7261(这是字典中单词的数量)的一个句子。
133 |
134 |
135 | ## 3.1.1 文本嵌入
136 |
137 | 独热编码是一种将类别数据表示成张量的很有用技术。就像你可能预料到的那样,当需要编码的项目数很大(例如语料库中的单词)时,独热编码就开始崩溃了。一本书中有超过7000个单词!
138 |
139 | 当然,你可以做一些工作来对单词进行去重、压缩替代拼写、将过去和将来时统一为相同表示,等等。尽管如此,通用的英文编码仍将是巨大的。更糟糕的是,每次遇到一个新单词时,都必须在向量中添加一个新列,这意味着要在模型中添加一组新的权重以解决该新词汇输入问题,从训练角度看这将给你带来很大的痛苦。
140 |
141 | 如何将编码压缩为更易于管理的大小,并限制大小增长?好吧,可以使用浮点数向量,而不是使用多个0和一个1的向量。举例来说,一个含100个浮点数的向量就可以表示很大量的词汇。关键是找到一种有效的方法,以一种有助于下游学习的方式将单个单词映射到这个100维空间。这种技术称为嵌入(embedding)。
142 |
143 | 原则上,你可以遍历词汇表并为每个单词生成100个随机浮点数。 这种方法可能是有效的,因为你可以将大量词汇塞入100个数字中,但是它会丢弃掉基于语义或上下文的单词之间的任何距离信息。使用这种词嵌入的模型不得不处理其输入向量中的少量结构。理想的解决方案是以这样的方式生成嵌入:用于同一上下文的单词映射到嵌入空间的邻近区域。
144 |
145 | 如果要手工设计解决此问题的方法,你有可能决定通过沿轴映射基本名词和形容词来构建嵌入空间。你可以生成一个二维空间,在该空间中,两个坐标轴分别映射到名词“水果”(0.0-0.33)、“花”(0.33-0.66)和“狗”(0.66-1.0),以及形容词“红色”(0.0-0.2)、“橙色”(0.2-0.4)、“黄色”(0.4-0.6)、“白色”(0.6-0.8)和“棕色”(0.8-1.0)。你现在的目标是将水果、花和狗放置在嵌入中。
146 |
147 | 开始嵌入单词时,可以将“苹果”映射到“水果”和“红色”象限中的某个数。同样,你可以轻松地映射“橘子”、“柠檬”、“荔枝”和“猕猴桃”(五颜六色的水果)。然后,你可以从花开始,分配“玫瑰”、“罂粟”、“水仙花”、“百合”和...好吧,不存在很多棕色的花。好,“太阳花”可以推出“花”、“黄色”和“棕色”,而“雏菊”可以推出“花”、“白色”和“黄色”。也许你应该更新“猕猴桃”以将其映射到“水果”、“棕色”和“绿色”附近。对于狗和颜色,“redbone(译者注:狗的品种)”、“fox”可能是“橙色”、“金毛”和“贵宾犬”可是“白色”的,以及...大多数种类的狗都是“棕色”的。
148 |
149 | 尽管对于大型语料库而言,手动进行此映射并不可行,但你应注意,尽管嵌入大小仅为2,但你描述了除基数8个之外的15个不同的单词,如果你花一些创造性的时间,可能还会嵌入更多的单词。
150 |
151 | 你可能已经猜到了,这种工作是可以自动进行的。通过处理大量文本语料库,你可以生成与此类似的嵌入。主要区别在于嵌入向量具有100到1000个元素,并且坐标轴不直接映射到某个词义,但是意思相近的词映射到嵌入空间也是相近的,其轴可能是任意的浮点维(floating-point dimensions)。
152 |
153 | 尽管实际使用的算法(比如[word2vec](https://en.wikipedia.org/wiki/Word2vec))对于我们在此要关注的内容来说有点超出范围,但值得一提的是,嵌入通常是使用神经网络并试图根据句中邻近词(上下文)预测某个词而生成的。在这种情况下,你可以从独热编码的单词开始,使用(通常是相当浅的)神经网络来生成嵌入。当嵌入可用时,你就可以将其用于下游任务。
154 |
155 | 生成的嵌入的一个有趣的方面是,相似的词不仅会聚在一起,还会与其他词保持一致的空间关系。如果你要使用“苹果”的嵌入向量,并加上和减去其他词的嵌入向量,就可以进行类比,例如`苹果 - 红色 - 甜 + 酸`,最后可能得到一个类似“柠檬”的向量。
156 |
157 | 我们不会在这里使用文本嵌入,但是当必须用数字向量表示集合中的大量元素时,它们是必不可少的工具。
--------------------------------------------------------------------------------
/docs/chapter3/3.4.md:
--------------------------------------------------------------------------------
1 | # 3.4 图像数据
2 |
3 | [卷积神经网络的出现彻底改变了计算机视觉](https://en.wikipedia.org/wiki/Convolutional_neural_network#History),基于图像的系统从此获得了一系列新的能力。通过使用成对的输入和期望的输出样本来训练端到端网络,可以前所未有地解决需要高度优化算法块构建的复杂模型。为了参与到这场革命中,你需要能够从常见的图像格式中载入图像,然后将数据转换为张量表示,该张量以PyTorch所期望的方式排列图像的各个部分。
4 |
5 | 图像表示为按规则网格排列的标量集合,并且具有高度和宽度(以像素为单位)。每个网格点(像素)可能只有一个标量,这种图像表示为灰度图像;或者每个网格点可能有多个标量,它们通常代表不同的颜色或不同的特征(`features`),例如从深度相机获得的深度。
6 |
7 | 代表单个像素值的标量通常使用8位整数编码,例如在消费类相机中。在医学、科学和工业应用中,你经常会发现具有较高数字精度的像素,例如12位和16位。如果像素对有关物理特性的信息例如骨密度、温度或深度进行编码,则此高精度可提供更大的(表示)范围或更高的灵敏度。
8 |
9 | 你有几种[用数字编码颜色的方法](https://en.wikipedia.org/wiki/Color_model)。最常见的是RGB,它定义用三个数字表示颜色,这三个数字分别代表红色、绿色和蓝色的强度。你可以将一个颜色通道视为仅讨论该颜色时的灰度强度图,例如你通过一副纯红色太阳镜观察场景时所看到的情况。图3.3显示了一条彩虹,其中的每个RGB通道都捕获了光谱的特定部分。(该图被简化了,省略了一些东西。例如,橙色和黄色带表示为红色和绿色的组合。)
10 |
11 | 图像有好几种文件格式,但是幸运的是,你有很多方法可以在Python中加载图像。首先使用`imageio`模块加载PNG图像。在本章中,你将使用`imageio`方法,因为它通过统一的API处理不同的数据类型。现在加载图像,如以下所示。
12 |
13 | ```python
14 | import imageio
15 | img_arr = imageio.imread('../../data/chapter3/bobby.jpg')
16 | img_arr.shape
17 | ```
18 |
19 | 输出:
20 |
21 | ```python
22 | (720, 1280, 3)
23 | ```
24 |
25 |
26 |
27 |
28 |

29 |
30 | 图3.3 将彩虹分成红色,绿色和蓝色的通道
31 |
32 | 此例中,`img_arr`是一个NumPy数组对象,它有三个维度:两个空间维度(宽度和高度),以及对应于红色、绿色和蓝色的第三个维度。任何输出NumPy数组的库都这样做以获得PyTorch张量。唯一需要注意的是维度的设置,PyTorch模块处理图像数据需要将张量设置为`C x H x W`(分别为通道、高度和宽度)。
33 |
34 | 你可以使用转置(`transpose`)函数获得正确的维度设置。给定`W x H x C`的输入张量,你可以通过交换第一个和最后一个通道来获得正确的维度设置:
35 |
36 | ```python
37 | img = torch.from_numpy(img_arr)
38 | out = torch.transpose(img, 0, 2)
39 | ```
40 |
41 | 你之前已经看过此示例,但是请注意此操作不会复制张量数据。相反,`out`使用与`img`相同的内部存储,只是修改了张量的尺寸和步幅信息。这种安排很方便,因为操作的代价很少,但是(当心)更改`img`中的像素值会导致`out`变化。
42 |
43 | 还要注意其他深度学习框架使用不同的维度设置。最初,TensorFlow将通道尺寸保持在最后,从而形成`H x W x C`布局。(现在,它已经支持多种布局。)从底层性能角度来看此策略具有优缺点,但只要适当地重塑(reshape)你的张量它就不会对你有所影响。
44 |
45 | 到目前为止,你已经描述了一张图片。遵循与以前的数据类型相同的策略,创建包含多个图像的数据集以用作神经网络的输入,然后沿着第一维将这些图像按照批量存储,以获得`N x C x H x W` 张量。
46 |
47 | 一个高效的选择就是使用堆叠(`stack`)来构建这个张量,你可以预先分配适当尺寸的张量,并用从文件夹中加载图像填充它,
48 |
49 | ```python
50 | batch_size = 100
51 | batch = torch.zeros(100, 3, 256, 256, dtype=torch.uint8)
52 | ```
53 |
54 | 这表示你的批次将包含100个RGB图像,分别为256像素高度和256像素宽度。注意张量的类型:你期望每种颜色都以8位整数表示,就像大多数标准消费相机照出的相片格式一样。现在你可以从输入的文件夹中加载所有的`png`图像并将其存储在张量中:
55 |
56 | ```python
57 | import os
58 | data_dir = '../../data/chapter3/image-cats/'
59 | filenames = [name for name in os.listdir(data_dir) if os.path.splitext(name) == '.png']
60 | for i, filename in enumerate(filenames):
61 | img_arr = imageio.imread(filename)
62 | batch[i] = torch.transpose(torch.from_numpy(img_arr), 0, 2)
63 | ```
64 |
65 | 如前所述,神经网络通常使用浮点张量作为输入。正如你将在接下来的章节中看到的那样,当输入数据的范围大约为`0`到`1`或`–1`到`1`时,神经网络表现出最佳的训练性能(影响来自于其如何构造模块的定义。)
66 |
67 | 你一贯要做的事情是将张量转换为浮点数并归一化像素值。强制转换为浮点数很容易,但是归一化比较麻烦,因为它取决于你决定的输入的哪个范围应该落在`0`到`1`(或`–1`到`1`)之间。一种可能的选择是将像素的值除以255(8位无符号最大可表示的数字):
68 |
69 | ```python
70 | batch = batch.float()
71 | batch /= 255.0
72 | ```
73 |
74 | 另一种可能的选择是计算输入数据的均值和标准偏差并对其进行缩放,以便于在每个通道上的均值和单位标准偏差输出为零:
75 |
76 | ```python
77 | n_channels = batch.shape[1]
78 | for c in range(n_channels):
79 | mean = torch.mean(batch[:, c])
80 | std = torch.std(batch[:, c])
81 | batch[:, c] = (batch[:, c] - mean) / std
82 | ```
83 |
84 | 你可以对输入执行其他几种操作,包括旋转、缩放和裁切之类的几何变换。这些操作可能有助于训练,或者可能需要进行这些操作以使任意输入符合网络的输入要求,例如图像的尺寸大小。你可能会偶而发现其中一些策略。现在,请记住你已经有可用的图像处理选项了。
--------------------------------------------------------------------------------
/docs/chapter3/3.5.md:
--------------------------------------------------------------------------------
1 | # 3.5 体积数据
2 |
3 | 你已经学习了如何加载和表示2D图像,比如使用相机拍摄的图像。在诸如涉及CT(Computed Tomography)扫描等医学成像应用程序的情况下,通常需要处理从头到脚方向堆叠的图像序列,每个序列对应于整个身体的横截面。在CT扫描中,强度代表身体不同部位的密度:肺、脂肪、水、肌肉、骨骼,以密度递增的顺序排列,当在临床工作站上显示CT扫描时,会从暗到亮映射。根据穿过人体后到达检测器的X射线量计算每个点的密度,并使用一些复杂的数学运算将原始传感器数据反卷积(deconvolve)为完整体积数据。
4 |
5 | CT具有单个的强度通道,这类似于灰度图像。通常在本地数据格式中,通道维度被忽略了,因此原始数据通常会具有三个维度。通过将单个2D切片堆叠到3D张量中,你可以构建表示对象的3D解剖结构的体积数据。与图3.3不同,图3.4中的额外的维表示物理空间中的偏移量,而不是可见光谱的特定频带。
6 |
7 |
8 |

9 |
10 | 图3.4 从头顶到颌骨的CT扫描切片
11 |
12 | 我们并不会在此处详细介绍医学成像数据格式。现在,足以说存储体积数据的张量和存储图像数据的张量之间不存在根本差异。在通道(`channel`)维之后,你有一个额外的维——深度(`depth`),形成5D张量为`N x C x D x H x W`。
13 |
14 | 使用`imageio`模块中的`volread`函数加载一个CT扫描样本,该函数以文件夹作为参数,将所有[DICOM](https://wiki.cancerimagingarchive.net/display/Public/CPTAC-LSCC#dd4a08a246524596add33b9f8f00f288)(Digital Imaging Communication and Storage,数字图像通信和存储)系列文件组合成一个NumPy 3D数组中,如下所示。
15 |
16 | ```python
17 | import imageio
18 | dir_path = "../../data/chapter3/volumetric-dicom/2-LUNG 3.0 B70f-04083"
19 | vol_arr = imageio.volread(dir_path, 'DICOM')
20 | vol_arr.shape
21 | ```
22 |
23 | 输出:
24 |
25 | ```python
26 | Reading DICOM (examining files): 1/99 files (1.0%99/99 files (100.0%) Found 1 correct series.
27 | Reading DICOM (loading data): 87/99 (87.999/99 (100.0%)
28 | (99, 512, 512)
29 | ```
30 |
31 | 同样,由于缺少通道信息,此时的维度设置与PyTorch所期望的不同。你必须通过`unsqueeze`为新增通道(`channel`)维:
32 |
33 | ```python
34 | vol = torch.from_numpy(vol_arr).float()
35 | vol = torch.transpose(vol, 0, 2)
36 | vol = torch.unsqueeze(vol, 0)
37 | vol.shape
38 | ```
39 |
40 | 输出:
41 |
42 | ```python
43 | torch.Size([1, 512, 512, 99])
44 | ```
45 |
46 | 此时,你可以像本章前面所述通过沿批处理(`batch`)方向堆叠多个体积数据来组装5D数据集。
47 |
48 | ## 小结
49 |
50 | 在本章中,你学到了很多基础知识。你学习了如何加载最常见的数据类型并对其进行重塑,以供神经网络使用。当然,实际要处理的数据格式可能比单个体积数据中描述的更多。有些内容,例如医学史,过于复杂而无法涵盖。但是,对于感兴趣的读者,我们在[代码仓库](https://github.com/deep-learning-with-pytorch/dlwpt-code/tree/master/p1ch4)中提供了在Jupyter notebooks中创建的处理音视频张量的简单样例。
51 |
52 | ## 练习
53 |
54 | * 用手机或其他数码相机拍摄几张红色、蓝色和绿色的照片(或者从网上下载,如果你没有相机的话)。
55 | - 加载每张图像,并将其转换为张量。
56 | - 对于每个图像张量,请使用`.mean()`方法来获得图像的亮度。
57 | - 现在,取图像每个通道的均值。你能否仅从通道平均值中识别出红色、绿色或蓝色的图片吗?
58 |
59 | * 选择一个包含Python源代码的相对较大的文件。
60 | - 建立源文件中所有单词的索引。(标记化可随意简单或复杂;我们建议你先将`r"[^a-zA-Z0-9_]+”`替换为空格。
61 | - 将你的索引与为《傲慢与偏见》制定的索引进行比较。哪个更大?
62 | - 为源代码文件创建独热编码。
63 | - 这种编码会丢失什么信息?该信息与《傲慢与偏见》编码中丢失的信息相比如何?
64 |
65 | ## 总结
66 |
67 | * 神经网络要求将数据表示为多维数值张量,通常为32位浮点数。
68 | * 多亏了PyTorch库可以与Python标准库和周围的生态系统进行交互,因此可以方便地加载最常见的数据类型并将其转换为PyTorch张量。
69 | * 通常,PyTorch期望沿特定维度布局数据,这取决于模型架构(例如卷积与递归)。使用PyTorch张量API可以有效地实现数据重塑。
70 | * 电子表格可以很容易地直接转换为张量。类别和序数值列的处理方式应与区间值列的处理方式有所不同。
71 | * 通过使用字典,文本或分类数据可以使用独热编码表示。
72 | * 图像可以具有一个或多个通道。最常见的是典型数码照片的红色、绿色和蓝色通道。
73 | * 单通道数据格式有时会忽略显式的通道维。
74 | * 体积数据类似于2D图像数据,但增加了第三维:深度。
75 | * 尽管12位和16位图像并不罕见,但是大多数图像每像素依然还是8位。这些图像可以存储为32位浮点数,并不会降低精度。
--------------------------------------------------------------------------------
/docs/chapter4/4.0.md:
--------------------------------------------------------------------------------
1 | # 4 学习机制
2 |
3 | 本章将
4 | * 理解算法如何从数据中学习
5 | * 使用微分和梯度下降将学习重新构造为参数估计
6 | * 从头开始学习一个简单的学习算法
7 | * 了解PyTorch如何通过autograd支持学习
8 |
9 | -------------------------
10 |
11 | 随着近十年来机器学习的蓬勃发展,从经验中学习的机器这一概念已成为技术和媒体界的主流。那么,机器到底是如何学习的?学习的机制或背后的算法是什么?从外部观察者的角度来看,学习算法就是将输入数据与所需输出配对。当学习完成后,该算法在输入与训练后的输入数据足够相似的新数据时,便能够产生正确的输出。借助深度学习,即使输入数据和所需的输出来自彼此不同的域(例如图像和描述它的句子)时,该过程也可以正常工作。
12 |
13 | 实际上,解释输入/输出关系的模型可以追溯到几个世纪之前。翰尼斯·开普勒(Johannes Kepler,1571-1630,德国数学天文学家)基于他的导师Tycho Brahe用肉眼(是的,一双眼和一张纸)观察的数据,在1600年代初弄清楚了他的三个行星运动定律。当时开普勒没有牛顿的万有引力定律可供使用(实际上,牛顿反倒利用开普勒的著作来解决问题),他只是推断出最简单的几何模型来拟合数据。值得一提的是,[根据Michael Fowler的描述]( http://galileoandeinstein.physics.virginia.edu/1995/lectures/morekepl.html),他花了6年的时间盯着那些对他没有意义的数据来逐渐实现并制定这些定律。你可以在图4.1中看到这个过程。
14 |
15 | 第一条定律是:“每个行星的轨道都是椭圆形,太阳位于两个焦点之一。” 他不知道是什么原因使轨道成为椭圆形,但给定行星(或大行星的卫星,例如木星)的一组观测值,他可以估算出椭圆的形状(eccentricity,偏心率)和大小(semi-latus rectum,正半焦距)。利用从数据中计算出的这两个参数,他可以判断出行星在天空中可能位于何处。当他计算出第二定律(“一条连接行星和太阳的线在相等的时间间隔内扫出相等的区域”)时,他还可以根据给出的观测结果判断出行星何时到达空间中的特定点。
16 |
17 | > 理解本章不需要了解开普勒定律的细节,你可以在[这里](https://en.wikipedia.org/wiki/Kepler%27s_laws_of_planetary_motion)找到关于开普勒定律的更多信息。
18 |
19 |
20 |

21 |
22 | 图4.1 开普勒考虑了可能适合手头数据的多个候选模型并最终选择了椭圆模型
23 |
24 | 开普勒如何在没有计算机、微型计算器甚至微积分(那时这些都还没被发明出来的)的情况下估算椭圆的偏心率和尺寸? 你可以从开普勒自己在《新天文学》(New Astronomy)一书中的回忆,或者从J.V. Field的[《证明的起源》(The Origins of Proof)系列](https://plus.maths.org/content/origins-proof-ii-keplers-proofs)中找到答案:
25 | > 本质上,开普勒必须使用一定数量的观测值来计算出曲线以尝试不同形状,然后使用计算出的曲线估计出更多位置,这是他拥有观测值的时间。然后检查这些计算出的位置是否与观测到的位置一致。
26 |
27 | 总结一下,开普勒在过去的六年里
28 | 1. 从他的朋友Brahe那里得到了很多好的数据(费了一些周折)。
29 | 2. 试图将这些数据可视化,因为他觉得有的(数据)有些可疑。
30 | 3. 选择有可能拟合数据的最简单的模型(椭圆)。
31 | 4. 划分数据,以便处理部分数据并保留独立的数据集用来验证。
32 | 5. 从试探性的偏心率和大小开始,然后进行迭代直到模型拟合观察结果为止。
33 | 6. 根据独立的数据集验证他的模型。
34 | 7. 难以置信地回顾。
35 |
36 | 这就是一本从1609走来的数据科学手册。
37 |
38 | 正如科学家们在几个世纪以来所学到的那样,科学的历史是建立在这七个步骤之上的,背离它们就是灾难的根源。(除非你是一个理论物理学家:D)
39 |
40 | 这些步骤正是你想从数据中学到东西所需的。在这里,说拟合(fit)数据和说让算法从数据中学习几乎没有区别。该过程始终涉及具有未知参数的函数,其参数是根据数据估算的,简称模型(model)。
41 |
42 | 你可以说“从数据中学习”假设了模型不是旨在解决特定问题(如开普勒工作中的椭圆问题)而是能够估计更广泛的函数簇。神经网络可以预测Tycho Brahe的轨迹而无需开普勒的独到见解来尝试将数据拟合到椭圆上。然而,牛顿从通用模型中得出万有引力定律将要困难得多。
43 |
44 | 你可能对后一种模型感兴趣:这些模型不是为解决特定任务而设计的,而是可以用输入输出对自动适应于解决许多类似任务,换句话说,就是经过在与手头任务相关的数据上训练的通用模型。具体来讲,PyTorch就是旨在简化创建模型的过程,对于该模型,拟合误差相对于参数的导数可以被解析地表达出来。如果你不理解最后一句话,请不要担心,4.1.1节会为你清除疑惑。
45 |
46 | 本章介绍如何自动进行通用函数拟合过程,这是使用深度学习所做的全部工作,而深度神经网络就是通用函数,PyTorch使此过程尽可能简单和透明。为了确保正确理解关键概念并让你从原理中了解学习算法的机制,我们将从比深度神经网络简单得多的模型开始。
--------------------------------------------------------------------------------
/docs/chapter5/5.0.md:
--------------------------------------------------------------------------------
1 | # 5 使用神经网络拟合数据
2 |
3 | 本章将
4 | * 使用非线性激活函数作为与线性模型的关键区别
5 | * 介绍常用的激活函数
6 | * 介绍包含神经网络构件的PyTorch的nn模块
7 | * 用神经网络解决简单的线性拟合问题
8 |
9 | 你已经仔细研究了线性模型的学习方法以及如何在PyTorch中实现线性模型:重点关注一个简单的回归问题,该问题需要一个具有输入和输出的线性模型。这个简单的示例使你可以剖析学习模型的机制,而且不会因模型本身的实现而过度分散注意力。不管具体模型是什么,参数的更新方式都是一样的:反向传播误差然后通过计算损失关于参数的梯度来更新这些参数(图5.1)。
10 |
11 |
12 |

13 |
14 | 图5.1 学习过程的抽象模型
15 |
16 | 在本章中,你将更改模型架构,实现一个完整的人工神经网络来解决问题。
17 |
18 | 之前的温度转换例子中的训练循环代码和样本划分(训练集和验证集)都将保持不变。现在开始使用二次模型,将模型重写为其输入的二次函数(例如 $y = a x^2 + b x + c$)。因为这个模型是可微的,所以PyTorch能够自动计算梯度,训练循环代码将照常工作。不过,这对你来说并不太有趣,因为我们仍在固定函数的形状。
19 |
20 | 在本章中,你将开始了解如何使用PyTorch中处理项目经常使用的一些功能。你将了解PyTorch API内部的原理,而避免认为它是多么神奇。
21 |
22 | 不过,在开始实现新模型之前,我们将解释人工神经网络的含义。
23 |
--------------------------------------------------------------------------------
/docs/chapter5/5.1.md:
--------------------------------------------------------------------------------
1 | # 5.1 神经元
2 |
3 | 深度学习的核心是神经网络,即能够通过简单函数的组合来表示复杂函数的数学实体。神经网络这个词显然暗示了与人脑工作方式的联系。事实上,尽管[最初的神经网络模型是受神经科学启发的](http://psycnet.apa.org/doiLanding?doi=10.1037%2Fh0042519),但现代人工神经网络与大脑中神经元的机制仅有略微的相似之处。人工和生理(physiological)神经网络似乎使用的是略微相似的数学策略来近似复杂的函数,因为这种策略很有效。
4 |
5 | > 注:从现在开始,我们将省略“人工”并简称为神经网络。
6 |
7 | 这些复杂函数的基本组成单元是神经元,如图5.2所示。从本质上讲,神经元不过是输入的线性变换(例如,输入乘以一个数[weight,权重],再加上一个常数[偏置,bias]),然后再经过一个固定的非线性函数(称为激活函数)。
8 |
9 |
10 |

11 |
12 | 图5.2 神经元:线性变换后再经过一个非线性函数
13 |
14 | 数学上,你可以将其写为 $o = f(wx + b)$,其中 $x$ 为输入,$w$ 为权重或缩放因子,$b$ 为偏置或偏移。$f$ 是激活函数,在此处设置为双曲正切( tanh)函数。通常,$x$ 以及 $o$ 可以是简单的标量,也可以是向量(包含许多标量值)。类似地,$w$ 可以是单个标量或矩阵,而 $b$ 是标量或向量(输入和权重的维度必须匹配)。在后一种情况下,该表达式被称为神经元层,因为它通过多维度的权重和偏差表示许多神经元。
15 |
16 | 如图5.3所示的多层神经网络例子由下面的函数组成:
17 |
18 | $$
19 | x_1 = f(w_0 x + b_0) \\
20 | x_2 = f(w_1 x_1 + b_1) \\
21 | ... \\
22 | y = f(w_n x_n + b_n) \\
23 | $$
24 |
25 | 其中神经元层的输出将用作下一层的输入。请记住,这里的 $w_0$ 是一个矩阵,而 $x$ 是一个向量!在此使用向量可使 $w_0$ 容纳整个神经元层,而不仅仅是单个权重。
26 |
27 |
28 |

29 |
30 | 图5.3 一个三层的神经网络
31 |
32 | 之前的线性模型与你将要使用的深度学习模型之间的重要区别是误差函数的形状。线性模型和误差平方损失函数具有凸的具有明确定义的最小值的误差曲线。如果你要使用其他方法(译者注:即非梯度下降的方法),则可以自动地求出这个明确的最小值。而(译者注:使用梯度下降)参数更新则试图尽可能地估计出这个最小值。
33 |
34 | 即使使用相同的误差平方损失函数,神经网络也不具有凸误差曲面这个属性。你尝试优化的每个参数都没有一个明确正确的答案。相反,你尝试优化所有协同工作的参数以产生有用的输出。由于有用的输出只会逼近真实值,因此会有一定程度的不完美。这种不完美在何处以及如何表现是任意的,引起这种不完美的控制输出的参数在某种程度上也是任意的。从机械角度来看,神经网络训练的输出结果看起来很像参数估计,但是请记住,理论基础是完全不同的。
35 |
36 | 神经网络具有非凸误差曲面主要是因为激活函数。组合神经元来逼近各种复杂函数的能力取决于每个神经元固有的线性和非线性行为的组合。
37 |
38 | ## 5.1.1 你所需的只是激活函数
39 |
40 | (深度)神经网络中最简单的单元是线性运算(缩放+偏移)然后紧跟一个激活函数。在你的上一个模型中有一个线性运算,而这个线性运算就是整个模型。激活函数的作用是将先前线性运算的输出聚集到给定范围内。
41 |
42 | 假设你正在为图片是否是“狗”打分。猎犬和西班牙猎狗的照片应该评分很高;飞机和垃圾车的图像应得分较低。熊的图片也应具有较低的分数,尽管比垃圾车的分数高。
43 |
44 | 问题是你必须定义何为高分。因为可以使用float32的全部范围,所以高分可以达到很高。即使你说“这是10分制”,有时模型也会在 $11/10$ 分。请记住,在模型内部,这都是 $w x + b$ 矩阵乘法的求和结果,所以自然不会将自己限制在特定的输出范围内。
45 |
46 | 你需要做的就是将线性操作的输出严格限制在特定范围内,以便该模型输出的使用者不必处理(得分为) $12/10$ 的幼犬,$-10$ 的熊以及 $-1000$ 的垃圾车。
47 |
48 | 一种可能的解决办法是截断输出值。小于0的任何值都将设置为0,而10以上的任何值都将设置为10。你可以使用一个简单的激活函数[`torch.nn.Hardtanh`](https://pytorch.org/docs/stable/nn.html#hardtanh),它默认将输出值截断在 $[-1,1]$ 内。
49 |
50 | 另一个运作良好的函数族是`torch.nn.Sigmoid`(即 $1 / (1 + e ^ {-x})$),`torch.tanh`和稍后会看到的其他函数。这些函数的曲线随着 $x$ 趋于负无穷大而渐近地接近 $0$ 或 $-1$,随着 $x$ 的增加而接近 $1$,并且在 $x = 0$ 时具有大致恒定的斜率。从概念上讲,以这种方式形成的函数可以很好地工作,因为这意味着神经元(即线性函数紧跟着激活函数)将对线性函数输出中间的区域敏感,而其区域都集中在边界值旁边。如图5.4所示,垃圾车的得分为-0.97,而熊、狐狸和狼的得分可能在-0.3到0.3之间。
51 |
52 |
53 |

54 |
55 | 图5.4 通过tanh激活函数将狗、熊和垃圾车映射为“像狗”(的分数)
56 |
57 | 垃圾车被标记为“不是狗”,好狗映射为“显然是狗”,而熊最终停在中间。在代码中,你将看到确切的值:
58 |
59 | ``` python
60 | >>> import math
61 | >>> math.tanh(-2.2) # 垃圾车
62 | -0.9757431300314515
63 | >>> math.tanh(0.1) # 熊
64 | 0.09966799462495582
65 | >>> math.tanh(2.5) # 狗
66 | 0.9866142981514303
67 | ```
68 |
69 | 熊处于敏感范围内,因此熊的微小变化会导致结果发生明显变化。你可以从灰熊换成北极熊(北极熊的脸庞似地更像传统犬),此时当你向“very much a dog”滑动时当看到Y轴上的跳跃。相反,考拉熊会减少与狗的相似度,然后激活输出就会下降。不过,你很难对垃圾车做些改变使其更像狗,即使你对其做出了了巨大的改变,你也可能只会看到从-0.97提升到-0.8左右。
70 |
71 | 存在许多激活函数,其中一些如图5.5所示。在第一列中,你将看到连续函数`Tanh`和`Softplus`。第二列是它左侧激活函数的“硬”版本,即`Hardtanh`和`ReLU`。`ReLU`(Rectified Linear Unit,线性整流单元)值得特别注意,因为它被认为是性能最好的常用激活函数之一,因为许多最新的结果都使用了它。`Sigmoid`激活函数(也称为逻辑函数)在早期的深度学习工作中得到了广泛的使用,但已不常用。最后,`LeakyReLU`函数将标准`ReLU`修改为在负输入时具有小的正斜率(该斜率通常为0.01,但为清楚起见,此处显示的斜率为0.1)而不是严格为零。
72 |
73 |
74 |

75 |
76 | 图5.5 常用以及不是很常用的激活函数
77 |
78 | 激活函数很好奇,因为我们使用了如此众多成功的激活函数(比图5.5中展示的多得多),很明显我们对激活函数几乎没有严格的要求。因此,我们将讨论有关激活函数的一些一般性,这些一般性不是总是正确的。也就是说,根据定义,激活函数
79 |
80 | * 是非线性的。在没有激活函数的情况下重复应用 $w x + b$ 会产生多项式。非线性的激活函数允许整个网络能近似更复杂的函数。
81 | * 是可微的。激活函数是可微的这样就可以计算穿过它们的梯度。不可微的离散点是无伤大雅的,例如`Hardtanh`和`ReLU`。
82 |
83 | > [当然上述陈述不总是正确的。](https://openai.com/blog/nonlinear-computation-in-linear-networks/)
84 |
85 | 如果没有上述两个要求,网络要么退回到复杂的多项式,要么变得难以训练。
86 |
87 | 激活函数还通常(尽管并非总是如此)
88 |
89 | * 具有至少一个敏感范围,其中输入的轻微变化会导致输出中相应的变化。
90 | * 具有至少一个不敏感(或饱和)范围,其中输入的变化导致输出的变化很小甚至没有变化。
91 |
92 | 举例来说,由于结合了具有不同权重和输入偏差的敏感范围,因此`Hardtanh`函数可以轻松地用于函数的分段线性近似。
93 |
94 | 通常(但并非普遍如此),激活函数至少具有以下特点之一:
95 | * 当输入变为负无穷大时接近(或达到)下限
96 | * 当输入变为正无穷大时接近(或达到)上限
97 |
98 | 思考一下反向传播的工作原理,你可以发现,当输入处于响应范围内时,误差将通过激活更有效地向后传播,而误差不会严重影响输入饱和的神经元(因为由于输出周围区域很平坦,梯度将接近零)。
99 |
100 | 综上所述,此机制非常强大。我们要说的是,在由线性+激活单元构成的网络中,当向网络提供不同的输入时,(a)不同的单元对于相同的输入会在不同的范围内做出响应,并且(b)与这些输入相关的误差将主要影响在敏感范围内运行的神经元,而其他单元或多或少不受学习过程的影响。此外,由于激活函数相对于其输入的导数通常在敏感范围内接近1,因此通过梯度下降在该范围内估计线性变换的参数看起来很像线性拟合。
101 |
102 | 你开始对如何将多个线性+激活函数并行连接并一个接一个地堆叠到一个能够近似复杂函数的数学对象上有了更深入的了解。不同的组合会响应不同范围内的输入,并且对于这些参数,通过梯度下降相对容易优化,因为学习过程将非常类似于线性拟合,直到输出饱和为止。
103 |
104 | ## 5.1.2 对神经网络来说学习的意义
105 |
106 | 从一系列线性变换紧跟可微激活函数中可以构建出能近似高度非线性过程的模型,且可以通过梯度下降很好地估计出其参数。即使处理的是具有数百万个参数的模型,这一事实仍然成立。使用深度神经网络之所以如此吸引人,是因为它使你不必担心表示数据的确切函数(无论是二次多项式,分段多项式还是其他函数)。使用深度神经网络模型,你将获得通用的估计器和估算其参数的方法。根据模型容量及其对复杂的输入/输出关系进行建模的能力,通过组装简单的构建模块,你可以定制这个估计器。图5.6显示了一些示例。
107 |
108 |
109 |

110 |
111 | 图5.6 组合多个线性单元和tanh激活函数以产生非线性输出
112 |
113 | 左上方的四个图显示了四个神经元A、B、C和D,每个都有自己的(任意选择的)权重和偏差。每个神经元都使用Tanh激活函数,其输出最小为-1,最大为1。不同的权重和偏差会移动中心点,并改变从最小值到最大值过渡的剧烈程度,但是显然它们的形状都是大致相同的。右边的一列显示了合在一起的两对神经元(A+B和C+D)。这里,你开始看到一些模仿单层神经元的有趣属性。A+B显示出一条轻微的S曲线,其极值趋近于零,但正负都在中间。相反,C+D仅具有较大的正凸点,其峰值比单神经元最大值1高。
114 |
115 | 在第三行中,你开始组合神经元,就像它们在两层网络中一样。C(A+B)和D(A+B)都具有与A+B相同的正负凸点,但是正峰值更加微弱。C(A+B)+D(A+B)的成分显示出一个新特性:两个清晰的负凸点,以及在主要关注区域左侧可能还有一个细微的第二个正峰。所有这一切发生在两层中只有四个神经元的情况下!
116 |
117 | 再此提一下,选择这些神经元的参数只是为了产生视觉上有趣的结果。训练包括找到这些权重和偏差的可接受值,以使所得网络正确执行一项任务,例如根据给定的地理坐标和一年中的时间预测可能的温度。成功地执行任务的意思是在未见过的数据上获得正确的输出,这些未见过的数据的产生过程与训练数据是相同的。一个成功训练后的网络,通过其权重和偏差的值,能够捕获表示成有意义数字的数据的内在结构,这些数字表示形式对刚刚说的未见过的数据也适用。
118 |
119 | 这是你实现学习机制的又一步:深度神经网络可让你近似高度非线性的过程,而无需为它们建立明确的模型。 相反,从未经训练的通用模型开始,你可以通过为它提供一组输入和输出以及一个从中进行反向传播的损失函数,将其专门用于某个任务。通过训练样本将通用模型专门用于某个任务就是我们所谓的学习,因为模型并不是在考虑特定任务的情况下构建的;模型中没有编码描述该任务如何工作的规则。
120 |
121 | 根据之前温度计的经验,你假设两个温度计都是线性测量温度的。这个假设就是我们为任务隐式编码的地方:我们对输入/输出函数的形状进行了硬编码;我们无法近似除了围绕一条线的数据点外的数据。随着问题的维数增长(许多输入到许多输出)以及输入/输出关系变得复杂,假设输入/输出函数的形状变得不太可能。物理学家或应用数学家的工作通常是根据理论原理对现象进行函数描述,以便可以通过测量来估算未知参数并获得准确的模型。而另一方面,深度神经网络是一系列函数,可以近似各种输入/输出关系,而不必要求提供一种现象的解释模型。在某种程度上,你需要放弃可解释性来解决日益复杂的问题。换句话说,有时您缺乏能力、信息或者计算资源来为你遇到的问题建立显式模型,因此数据驱动方法是你前进的唯一方法。
122 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/docs/chapter5/5.2.md:
--------------------------------------------------------------------------------
1 | # 5.2 PyTorch的nn模块
2 |
3 | 之前这些关于神经网络的讨论可能会让你对使用PyTorch从头开始构建一个神经网络感到好奇。第一步是用神经网络模型替换之前的线性模型。从正确性的角度来看,此步骤是一个毫无用处的步骤,因为你已经验证了本任务只需要线性函数,但是对于从一个很简单的问题开始然后进行扩展来说仍然是有用的。
4 |
5 | PyTorch有一个专门用于神经网络的完整子模块:`torch.nn`。该子模块包含创建各种神经网络体系结构所需的构建块。这些构建块在PyTorch术语中称为module(模块),在其他框架中称为layer(层)。
6 |
7 | PyTorch模块都是从基类`nn.Module`继承而来的Python类。模块可以具有一个或多个参数(`Parameter`)实例作为属性,这些参数就是在训练过程中需要优化的张量(在之前的线性模型中即w和b)。模块还可以具有一个或多个子模块(`nn.Module`的子类)属性,并且也可以追踪其参数。
8 |
9 | > 注:子模块必须是顶级属性(top-level attributes),而不能包含在list或dict实例中!否则,优化器将无法找到子模块(及其参数)。对于需要子模块列表或字典的情况,PyTorch提供有`nn.ModuleList`和`nn.ModuleDict`。
10 |
11 | 你可以毫不奇怪地可以找到一个名为`nn.Linear`的`nn.Module`子类,它对其输入进行仿射变换(通过参数属性weight和bias);它就相当于之前在温度计实验中实现的方法。现在,从上次中断的地方开始,将之前的代码转换为使用`nn`的形式。
12 |
13 | 所有PyTorch提供的`nn.Module`子类都定义了其调用方法,使你可以实例化`nn.Linear`并将其像一个函数一样进行调用,如下面的代码所示:
14 |
15 | ``` python
16 | import torch.nn as nn
17 |
18 | linear_model = nn.Linear(1, 1) # 参数: input size, output size, bias(默认True)
19 | linear_model(t_un_val)
20 | ```
21 | 输出:
22 | ```
23 | tensor([[1.2665],
24 | [1.0006]], grad_fn=)
25 | ```
26 |
27 | 使用一组参数调用`nn.Module`实例最终会调用带有相同参数的名为`forward`的方法,`forward`方法会执行前向传播计算;不过在调用之前和之后还会执行其他相当重要的操作。因此,虽然从技术上讲直接调用`forward`是可行的,并且它产生的结果与调用`nn.Module`实例相同,但用户不应该这样做:
28 | ``` python
29 | >>> y = model(x)
30 | >>> y = model.forward(x) # 不要这样做!!!
31 | ```
32 |
33 | 以下代码显示了`Module.call`的实现(为清楚起见进行了一些简化):
34 | ``` python
35 | def __call__(self, *input, **kwargs):
36 | for hook in self._forward_pre_hooks.values():
37 | hook(self, input)
38 | result = self.forward(*input, **kwargs)
39 | for hook in self._forward_hooks.values():
40 | hook_result = hook(self, input, result)
41 | # ...
42 | for hook in self._backward_hooks.values():
43 | # ...
44 | return result
45 | ```
46 |
47 | 如上所示,如果直接使用`.forward(...)`,很多`hook`将无法正确调用。
48 |
49 | 现在回到线性模型。`nn.Linear`的构造函数接受三个参数:输入特征的数量,输出特征的数量以及线性模型是否包含偏差(此处默认为True)。
50 |
51 | 这里特征的数量是指输入和输出张量的尺寸,因此本例是1和1。例如,如果在输入中同时使用了温度和气压,则在其中输入具有两个特征输入和而输出只有一个特征。如你所见,对于具有多个中间模块的更复杂的模型,模型的容量与特征的数量有关。
52 |
53 | 现在你有一个具有一个输入和一个输出特征的`nn.Linear`实例,它需要一个权重
54 |
55 | ``` python
56 | linear_model.weight
57 | ```
58 | 输出:
59 | ```
60 | Parameter containing:
61 | tensor([[0.0806]], requires_grad=True)
62 | ```
63 | 和一个偏差
64 | ``` python
65 | linear_model.bias
66 | ```
67 | 输出:
68 | ```
69 | Parameter containing:
70 | tensor([0.6065], requires_grad=True)
71 | ```
72 |
73 | 你可以用一些输入来调用这个模块:
74 |
75 | ``` python
76 | x = torch.ones(1)
77 | linear_model(x)
78 | ```
79 | 输出:
80 | ```
81 | tensor([0.6871], grad_fn=)
82 | ```
83 |
84 | 在上面的代码中,你没有提供正确尺寸的输入(尽管还是产生了输出)。你有一个可以接受一个输入并产生一个输出的模型,但是PyTorch的`nn.Module`及其子类被设计为可以同时处理多个样本。为了容纳多个样本,模型希望输入的第0维为这个批次中的样本数目。
85 |
86 | `nn`中的任何模块都被编写成同时产生一个批次(即多个输入)的输出。 因此,假设你需要对10个样本运行`nn.Linear`,则可以创建大小为 B x Nin 的输入张量,其中 B 是批次的大小,而 Nin 是输入特征的数量,然后在模型中同时运行:
87 |
88 | ``` python
89 | x = torch.ones(10, 1)
90 | linear_model(x)
91 | ```
92 | 输出:
93 | ```
94 | tensor([[0.6871],
95 | [0.6871],
96 | [0.6871],
97 | [0.6871],
98 | [0.6871],
99 | [0.6871],
100 | [0.6871],
101 | [0.6871],
102 | [0.6871],
103 | [0.6871]], grad_fn=)
104 | ```
105 |
106 | 图5.7显示了批处理图像数据的类似的情况。输入尺寸为 BxCxHxW,其中批处理大小(batch size)B为3(狗、鸟和汽车的图像),每张图像通道数C为3(红色,绿色和蓝色),高度 H 和宽度 W 的像素数未指定。
107 |
108 | 正如你所看到的,输出是大小为 B x Nout 的张量,其中 Nout 是输出特征的数量——在此例中为四个。
109 |
110 |
111 |

112 |
113 | 图5.7 将三个RGB图像组成一批然后输入到神经网络中。输出是三个大小为4的向量。
114 |
115 | 我们要进行此批处理的原因是多方面的。一个主要动机是确保我们所需的计算量足够大,以使我们充分利用执行计算的计算资源。特别地,GPU是高度并行化的,因此在小型模型上的单个输入将使大多数计算单元处于空闲状态。通过提供成批的输入,可以将计算分散到其他闲置的计算单元上,这意味着成批的结果就像单个结果一样能够很快地返回。另一个好处是,某些高级模型将使用整个批次的统计信息,而当批次大小较大时那些统计数据将变得更准确。
116 |
117 | 现在回到温度计数据。`t_u`和`t_c`是两个大小为B的一维张量。由于广播机制,你可以将线性模型写为 $w x + b$,其中 $w$ 和 $b$ 是两个标量参数。该模型之所以有效,是因为你具有一个输入特征;如果你有两个,则需要添加额外的尺寸以将该1D张量转变为矩阵,该矩阵每一行代表每个样本,每列代表所有样本的某个特征。
118 |
119 | 这就是你要切换到使用`nn.Linear`所要做的。你需要将尺寸为 B 的输入reshape为 B x Nin,其中Nin为1。你可以使用`unsqueeze`轻松地做到这一点:
120 |
121 | ``` python
122 | t_c = [0.5, 14.0, 15.0, 28.0, 11.0, 8.0, 3.0, -4.0, 6.0, 13.0, 21.0]
123 | t_u = [35.7, 55.9, 58.2, 81.9, 56.3, 48.9, 33.9, 21.8, 48.4, 60.4, 68.4]
124 | t_c = torch.tensor(t_c).unsqueeze(1) # <1>
125 | t_u = torch.tensor(t_u).unsqueeze(1) # <1>
126 |
127 | t_u.shape
128 | ```
129 | 输出:
130 | ```
131 | torch.Size([11, 1])
132 | ```
133 |
134 | 你完成了。现在更新原来的训练代码。首先,将之前的手工模型替换为`nn.Linear(1,1)`,然后将线性模型参数传递给优化器:
135 | ``` python
136 | linear_model = nn.Linear(1, 1)
137 | optimizer = optim.SGD(
138 | linear_model.parameters(),
139 | lr=1e-2)
140 | ```
141 |
142 | 之前,你需要自己创建参数并将其作为第一个参数传递给`optim.SGD`。现在,你可以使用`parameters`方法获取任何`nn.Module`或其子模块的参数列表:
143 |
144 | ```python
145 | linear_model.parameters()
146 | ```
147 | ```
148 |
149 | ```
150 | ``` python
151 | list(linear_model.parameters())
152 | ```
153 | ```
154 | [Parameter containing:
155 | tensor([[0.5563]], requires_grad=True), Parameter containing:
156 | tensor([-0.0067], requires_grad=True)]
157 | ```
158 |
159 | 此调用递归调用到模块的`init`构造函数中定义的子模块中,并返回遇到的所有参数的列表,因此你可以像之前一样方便地将其传递给优化器构造函数。
160 |
161 | 你现在已经可以指出训练循环中会发生什么了。我们为优化器提供了一个`require_grad = True`张量列表。所有参数都是用这种方式定义的,因为它们需要通过梯度下降进行优化。调用`raining_loss.backward()`时,`grad`将累积在图的叶节点上,这些节点正是传递给优化器的参数。
162 |
163 | 此时,SGD优化器已具有所需的一切。调用`optimizer.step()`时,它将循环访问每个参数,并按与存储在其grad属性中的值成比例的量对其进行更改。
164 |
165 | 现在我们来看看训练循环:
166 | ``` python
167 | def training_loop(n_epochs, optimizer, model, loss_fn,
168 | t_u_train, t_u_val, t_c_train, t_c_val):
169 | for epoch in range(1, n_epochs + 1):
170 | t_p_train = model(t_un_train)
171 | loss_train = loss_fn(t_p_train, t_c_train)
172 |
173 | t_p_val = model(t_un_val)
174 | loss_val = loss_fn(t_p_val, t_c_val)
175 |
176 | optimizer.zero_grad()
177 | loss_train.backward()
178 | optimizer.step()
179 |
180 | if epoch == 1 or epoch % 1000 == 0:
181 | print('Epoch %d, Training loss %.4f, Validation loss %.4f' % (
182 | epoch, float(loss_train), float(loss_val)))
183 | ```
184 |
185 | 训练循环几乎没有改变,除了现在你不再明确地将`params`传递给`model`,因为`model`本身在内部保存有`Parameters`。
186 |
187 | 你还可以使用`torch.nn`的最后一部分:损失函数。实际上,`nn`具有几个常见的损失函数,其中`nn.MSELoss`(MSE代表均方误差)正是先前`loss_fn`的定义。`nn`中的损失函数仍然是`nn.Module`的子类,因此我们可以创建一个实例并将其作为函数调用。在本例中,你将摆脱手动定义的`loss_fn`并替换它:
188 |
189 | ``` python
190 | linear_model = nn.Linear(1, 1)
191 | optimizer = optim.SGD(linear_model.parameters(), lr=1e-2)
192 |
193 | training_loop(
194 | n_epochs = 3000,
195 | optimizer = optimizer,
196 | model = linear_model,
197 | loss_fn = nn.MSELoss(), # 不再使用自己定义的loss
198 | t_u_train = t_un_train,
199 | t_u_val = t_un_val,
200 | t_c_train = t_c_train,
201 | t_c_val = t_c_val)
202 |
203 | print()
204 | print(linear_model.weight)
205 | print(linear_model.bias)
206 | ```
207 | 输出:
208 | ```
209 | Epoch 1, Training loss 66.0145, Validation loss 239.8421
210 | Epoch 1000, Training loss 4.1785, Validation loss 9.3629
211 | Epoch 2000, Training loss 3.2060, Validation loss 3.8825
212 | Epoch 3000, Training loss 3.1601, Validation loss 3.0151
213 |
214 | Parameter containing:
215 | tensor([[5.0940]], requires_grad=True)
216 | Parameter containing:
217 | tensor([-16.0012], requires_grad=True)
218 | ```
219 |
220 | 输入到我们训练循环中的其他所有内容都保持不变。甚至我们的结果也和之前一样。当然,获得相同的结果只是我们所期望的,差异暗示了bug存在于这两种实现之一。
221 |
222 | 这是一段漫长的旅程,需要要对这二十多行代码进行很多探索。我们希望到现在为止魔术消失了而该工程师登场了。在本章中学习的内容将使你可以拥有自己编写的代码,而不是在事情变得更加复杂只能戳一戳黑匣子。
223 |
224 | 还差最后一个步骤:用神经网络代替线性模型作为近似函数。正如我们之前所说,使用神经网络不会产生更高质量的模型,因为我们这个温度校准问题背后的过程本质上是线性的。但是,从线性网络到神经网络的跨越是值得的,这样你以后就不会感到迷失了。
225 |
226 | 接下来我们将重新定义模型,并将所有其他内容(包括损失函数)保持不变。还是构建最简单的神经网络:一个线性模块然后是一个激活函数,最后将输入喂入另一个线性模块。由于历史原因,第一个 线性+激活层 通常称为隐藏层,因为它的输出不会直接观察到,而是会送到输出层。尽管模型的输入和输出均为大小1(一个输入和一个输出特征),但第一个线性模块的输出大小通常大于1。回顾前面关于激活作用的解释,这会使不同的单位对输入的不同范围做出响应,从而增加模型的容量。最后一个线性层获取激活函数的输出,并将它们线性组合以产生输出值。
227 |
228 | `nn`提供了一种通过`nn.Sequential`容器串联模块的简单方法:
229 |
230 | ``` python
231 | seq_model = nn.Sequential(
232 | nn.Linear(1, 13),
233 | nn.Tanh(),
234 | nn.Linear(13, 1))
235 | seq_model
236 | ```
237 | 输出:
238 | ```
239 | Sequential(
240 | (0): Linear(in_features=1, out_features=13, bias=True)
241 | (1): Tanh()
242 | (2): Linear(in_features=13, out_features=1, bias=True)
243 | )
244 | ```
245 |
246 | 得到的模型的输入是作为`nn.Sequential`的参数的第一个模块所指定的输入,然后将中间输出传递给后续模块,并输出最后一个模块返回的输出。该模型将1个输入特征散开为13个隐藏特征,然后将通过`tanh`激活函数,最后将得到的13个数字线性组合为1个输出特征。
247 |
248 | 调用`model.parameters()`可以得到第一线性模块和第二线性模块中的权重和偏差。在本例中,我们可以通过打印形状来检查参数:
249 | ``` python
250 | [param.shape for param in seq_model.parameters()]
251 | ```
252 | 输出:
253 | ```
254 | [torch.Size([13, 1]), torch.Size([13]), torch.Size([1, 13]), torch.Size([1])]
255 | ```
256 |
257 | 这些都是优化器所需的参数张量。同样,在调用`model.backward()`之后,所有参数都将被计算其`grad`,然后优化器会在调用`optimizer.step()`期间更新参数的值,这与之前的线性模型没有太大不同。毕竟这两个模型都是可微分的模型,可以通过梯度下降进行训练。
258 |
259 | 有关`nn.Modules`参数的一些注意事项:当你检查由几个子模块组成的模型的参数时,可以方便地通过其名称识别参数。这个方法叫做`named_parameters`:
260 |
261 | ``` python
262 | for name, param in seq_model.named_parameters():
263 | print(name, param.shape)
264 | ```
265 | 输出:
266 | ```
267 | 0.weight torch.Size([13, 1])
268 | 0.bias torch.Size([13])
269 | 2.weight torch.Size([1, 13])
270 | 2.bias torch.Size([1])
271 | ```
272 |
273 | 实际上,`Sequential`中每个模块的名称都是该模块在参数中出现的顺序。有趣的是,`Sequential`还可以接受`OrderedDict`作为参数,这样就可以给`Sequential`的每个模块命名:
274 |
275 | > 并非所有版本的Python都明确指定`dict`的迭代顺序,因此我们在这里使用`OrderedDict`来明确层的顺序并强调这个顺序的重要性。
276 |
277 | ``` python
278 | from collections import OrderedDict
279 |
280 | seq_model = nn.Sequential(OrderedDict([
281 | ('hidden_linear', nn.Linear(1, 8)),
282 | ('hidden_activation', nn.Tanh()),
283 | ('output_linear', nn.Linear(8, 1))
284 | ]))
285 |
286 | seq_model
287 | ```
288 | 输出:
289 | ```
290 | Sequential(
291 | (hidden_linear): Linear(in_features=1, out_features=8, bias=True)
292 | (hidden_activation): Tanh()
293 | (output_linear): Linear(in_features=8, out_features=1, bias=True)
294 | )
295 | ```
296 | 此代码使你可以允许子模块有更加具有解释性的名称:
297 |
298 | ``` python
299 | for name, param in seq_model.named_parameters():
300 | print(name, param.shape)
301 | ```
302 | 输出:
303 | ```
304 | hidden_linear.weight torch.Size([8, 1])
305 | hidden_linear.bias torch.Size([8])
306 | output_linear.weight torch.Size([1, 8])
307 | output_linear.bias torch.Size([1])
308 | ```
309 |
310 | 你还可以通过访问子模块来访问特定的参数,就像它们是属性一样:
311 |
312 | ``` python
313 | seq_model.output_linear.bias
314 | ```
315 | 输出:
316 | ```
317 | Parameter containing:
318 | tensor([-0.1786], requires_grad=True)
319 | ```
320 |
321 | 与本章开始时一样,该代码对于检查参数或其梯度(例如在训练期间监视梯度)很有用。假设你要打印出隐藏层线性部分的权重的梯度,你可以为新的神经网络模型运行训练循环,然后在最后一个epoch之后查看结果梯度:
322 |
323 | ``` python
324 | optimizer = optim.SGD(seq_model.parameters(), lr=1e-3) # 为了稳定性调小了梯度
325 |
326 | training_loop(
327 | n_epochs = 5000,
328 | optimizer = optimizer,
329 | model = seq_model,
330 | loss_fn = nn.MSELoss(),
331 | t_u_train = t_un_train,
332 | t_u_val = t_un_val,
333 | t_c_train = t_c_train,
334 | t_c_val = t_c_val)
335 |
336 | print('output', seq_model(t_un_val))
337 | print('answer', t_c_val)
338 | print('hidden', seq_model.hidden_linear.weight.grad)
339 | ```
340 | 输出:
341 | ```
342 | Epoch 1, Training loss 142.5878, Validation loss 439.7242
343 | Epoch 1000, Training loss 4.9129, Validation loss 46.7108
344 | Epoch 2000, Training loss 3.4471, Validation loss 25.7202
345 | Epoch 3000, Training loss 2.8642, Validation loss 16.3709
346 | Epoch 4000, Training loss 2.5688, Validation loss 11.2405
347 | Epoch 5000, Training loss 2.3860, Validation loss 8.0017
348 | output tensor([[24.0087],
349 | [ 7.7348]], grad_fn=)
350 | answer tensor([[28.],
351 | [ 8.]])
352 | hidden tensor([[ 0.0207],
353 | [ 0.0272],
354 | [-0.0065],
355 | [ 0.1072],
356 | [ 0.0060],
357 | [ 0.0142],
358 | [ 0.0004],
359 | [-0.0004]])
360 | ```
361 |
362 | 你还可以在整个数据上评估模型以查看与线性关系之间的差异:
363 |
364 | ``` python
365 | from matplotlib import pyplot as plt
366 |
367 | t_range = torch.arange(20., 90.).unsqueeze(1)
368 |
369 | fig = plt.figure(dpi=100)
370 | plt.xlabel("Fahrenheit")
371 | plt.ylabel("Celsius")
372 | plt.plot(t_u.numpy(), t_c.numpy(), 'o')
373 | plt.plot(t_range.numpy(), seq_model(0.1 * t_range).detach().numpy(), 'c-')
374 | plt.plot(t_u.numpy(), seq_model(0.1 * t_u).detach().numpy(), 'kx')
375 | plt.show()
376 | ```
377 | 上述代码将会输出图5.8。
378 |
379 |
380 |

381 |
382 | 图5.8 神经网络模型图示:输入数据(圆形),期望输出(叉号)和显示样本之间行为的连续曲线
383 |
384 | 你可能会意识到神经网络有过拟合的趋势,因为它试图拟合包括噪声在内的测量值。不过总体上神经网络表现还不错。
385 |
386 |
--------------------------------------------------------------------------------
/docs/chapter5/5.3.md:
--------------------------------------------------------------------------------
1 | # 5.3 nn的子类
2 |
3 | 对于更大,更复杂的项目,你需要将`nn.Sequential`放在一边转而使用可以带来更大灵活性的东西:将`nn.Module`子类化。要实现`nn.Module`的子类,至少需要定义一个`forward()`函数,该函数将接收模型输入并返回输出。如果你使用的是`torch`中的操作,那么`autograd`会自动处理反向传递。
4 |
5 | > 注:通常,整个模型都是作为`nn.Module`的子类实现的,而其内部又可以包含同样是`nn.Module`的子类的模块。
6 |
7 | 我们将使用越来越复杂的PyTorch函数展示用三种方法来实现相同的网络结构,并改变隐藏层中神经元的数量使它们更易于区分。
8 |
9 | 第一种方法是`nn.Sequential`,如下面的代码所示。
10 |
11 | ``` python
12 | seq_model = nn.Sequential(
13 | nn.Linear(1, 11),
14 | nn.Tanh(),
15 | nn.Linear(11, 1))
16 | seq_model
17 | ```
18 | 输出:
19 | ```
20 | Sequential(
21 | (0): Linear(in_features=1, out_features=11, bias=True)
22 | (1): Tanh()
23 | (2): Linear(in_features=11, out_features=1, bias=True)
24 | )
25 | ```
26 |
27 | 尽管此代码能够工作,但是你没有关于各层打算使用的语义信息。你可以通过以下方式改进这种情况:使用有序字典而不是列表作为输入为每一层添加标签:
28 |
29 | ``` python
30 | from collections import OrderedDict
31 | namedseq_model = nn.Sequential(OrderedDict([
32 | ('hidden_linear', nn.Linear(1, 12)),
33 | ('hidden_activation', nn.Tanh()),
34 | ('output_linear', nn.Linear(12 , 1))
35 | ]))
36 | namedseq_model
37 | ```
38 | 输出:
39 | ```
40 | Sequential(
41 | (hidden_linear): Linear(in_features=1, out_features=12, bias=True)
42 | (hidden_activation): Tanh()
43 | (output_linear): Linear(in_features=12, out_features=1, bias=True)
44 | )
45 | ```
46 |
47 | 这样就好多了。除了`nn.Sequential`类提供的顺序性之外,你不能控制通过网络的数据流向。你可以自己定义`nn.Module`的子类来完全控制输入数据的处理方式:
48 |
49 | ``` python
50 | class SubclassModel(nn.Module):
51 | def __init__(self):
52 | super().__init__()
53 | self.hidden_linear = nn.Linear(1, 13)
54 | self.hidden_activation = nn.Tanh()
55 | self.output_linear = nn.Linear(13, 1)
56 | def forward(self, input):
57 | hidden_t = self.hidden_linear(input)
58 | activated_t = self.hidden_activation(hidden_t)
59 | output_t = self.output_linear(activated_t)
60 | return output_t
61 |
62 | subclass_model = SubclassModel()
63 | subclass_model
64 | ```
65 | 输出:
66 | ```
67 | SubclassModel(
68 | (hidden_linear): Linear(in_features=1, out_features=13, bias=True)
69 | (hidden_activation): Tanh()
70 | (output_linear): Linear(in_features=13, out_features=1, bias=True)
71 | )
72 | ```
73 |
74 | 该代码最终变得更加冗长,因为你必须定义所需的网络层,然后定义在`forward`函数中应如何以及以什么顺序使用这些网络层。这为你在模型中提供了难以置信的灵活性,虽然在本例中你不必要在`forward`函数中执行各种有趣的事情。例如你可以用`activated_t = self.hidden_activation(hidden_t) if random.random() > 0.5 else hidden_t`以一般的概率应用激活函数,尽管这在本例中不太有意义。因为PyTorch使用基于动态图的自动梯度机制,所以无论`random.random()`返回什么,梯度都可以通过有时存在的激活正确地流动!
75 |
76 | 你通常在模型的构造函数中来定义我们在`forward`函数中需要调用的子模块,以便它们可以在模型的整个生命周期中保存其参数。例如,你可以在构造函数中实例化两个`nn.Linear`实例然后在`forward`中使用它。有趣的是,只要你将`nn.Module`实例分配为模型的属性,就像你在构造函数所做的那样,PyTorch就会自动将该模块登记(register)为子模块,这使模型可以访问其子模块的参数,而无需用户进一步操作。
77 |
78 | 回到前面的`SubclassModel`,你会看到该类的打印输出类似于具有命名参数的顺序模型`namedseq_model`的打印输出。这是有道理的,因为你使用了相同的名称并打算实现相同的网络结构。如果你查看所有三个模型的参数,也会看到相似之处(除了隐藏神经元数量的差异以外):
79 | ``` python
80 | for type_str, model in [('seq', seq_model), ('namedseq', namedseq_model),
81 | ('subclass', subclass_model)]:
82 | print(type_str)
83 | for name_str, param in model.named_parameters():
84 | print("{:21} {:19} {}".format(name_str, str(param.shape), param.numel()))
85 | print()
86 | ```
87 | 输出:
88 | ```
89 | seq
90 | 0.weight torch.Size([11, 1]) 11
91 | 0.bias torch.Size([11]) 11
92 | 2.weight torch.Size([1, 11]) 11
93 | 2.bias torch.Size([1]) 1
94 |
95 | namedseq
96 | hidden_linear.weight torch.Size([12, 1]) 12
97 | hidden_linear.bias torch.Size([12]) 12
98 | output_linear.weight torch.Size([1, 12]) 12
99 | output_linear.bias torch.Size([1]) 1
100 |
101 | subclass
102 | hidden_linear.weight torch.Size([13, 1]) 13
103 | hidden_linear.bias torch.Size([13]) 13
104 | output_linear.weight torch.Size([1, 13]) 13
105 | output_linear.bias torch.Size([1]) 1
106 | ```
107 |
108 | 此处发生的是:调用`named_parameters()`会深入搜寻构造函数中分配为属性的所有子模块,然后在这些子模块上递归调用`named_parameters()`。无论子模块如何嵌套,任何`nn.Module`实例都可以访问其所有子参数的列表。通过访问将由`autograd`计算出的`grad`属性,优化器就知道如何更新参数以最大程度地减少损失。
109 |
110 | > 注:Python列表或dict实例中包含的子模块不会被自动登记!你可以使用[`add_module(name, module)`](https://pytorch.org/docs/stable/nn.html#torch.nn.Module.add_module)方法手动登记这些子模块,或者可以使用`nn.ModuleList`和`nn.ModuleDict`类(它们为包含的实例提供自动登记)。
111 |
112 | 回顾`SubclassModel`类的实现,并考虑在构造函数中登记子模块以便访问其参数的实用功能,似乎同时登记没有参数的子模块(如`nn.Tanh`)有点浪费,直接在`forward`函数中调用它们难道不是更容易吗?当然可以。
113 |
114 | PyTorch的每个`nn`模块都有相应的函数。“函数”一词是指“没有内部状态”或“其输出值完全由输入的参数决定”。实际上,`torch.nn.functional`提供了许多与`nn`模块对应的函数,只是所有模型参数(parameter)都作为了参数(argument)移到了函数调用中。例如,与`nn.Linear`对应的是`nn.functional.linear`,它是一个具有参数`(input, weight, bias=None)`的函数,即模型的权重和偏差是该函数的参数。
115 |
116 | 回到模型中,继续使用`nn.Linear`模块是有意义的,因为方便`SubclassModel`可以在训练期间管理其所有`Parameter`实例。但你可以安全地切换到`Tanh`的函数版本,因为它没有参数:
117 |
118 | ``` python
119 | class SubclassFunctionalModel(nn.Module):
120 | def __init__(self):
121 | super().__init__()
122 | self.hidden_linear = nn.Linear(1, 14)
123 | # 去掉了nn.Tanh()
124 | self.output_linear = nn.Linear(14, 1)
125 |
126 | def forward(self, input):
127 | hidden_t = self.hidden_linear(input)
128 | activated_t = torch.tanh(hidden_t) # nn.Tanh对应的函数
129 | output_t = self.output_linear(activated_t)
130 | return output_t
131 |
132 | func_model = SubclassFunctionalModel()
133 | func_model
134 | ```
135 | 输出:
136 | ```
137 | SubclassFunctionalModel(
138 | (hidden_linear): Linear(in_features=1, out_features=14, bias=True)
139 | (output_linear): Linear(in_features=14, out_features=1, bias=True)
140 | )
141 | ```
142 |
143 | 这个版本更加简洁(随着模型变得越来越复杂,所需代码行将逐渐累加!),而且完全等同于非函数版本。注意,在构造函数中实例化需要参数进行初始化的模块仍然是有意义的。例如,`HardTanh`使用可选的`min_val`和`max_val`参数,所以你应该创建`HardTanh`实例并重用它而不是在`forward`中重复声明这些参数。
144 |
145 | > 小贴士:尽管1.0版的`torch.nn.function`中仍存在诸如`tanh`之类的通用科学函数,但不建议使用这些API,而应使用顶级`torch`命名空间中的API,例如`torch.tanh`。更多其他函数保留在`torch.nn.functional`中。
146 |
147 |
148 | ## 小结
149 |
150 | 我们在本章讨论了很多内容,虽然我们只是处理了一个简单的问题。我们剖析了可微模型构建,并通过使用梯度下降,先使用原始`autograd`然后依赖`nn`对模型进行训练。至此,你应该对(神经网络)幕后发生的事情充满信心。
151 |
152 | 我们希望PyTorch这种口味能够符合你的胃口!
153 |
154 | ## 更多资源
155 |
156 | 大量书籍和其他资源可用来帮助学习深度学习。 我们推荐以下内容:
157 |
158 | * PyTorch官方网站:https://pytorch.org ;
159 | * Andrew W. Traska撰写的[《Grokking Deep Learning》]( https://www.manning.com/books/grokking-deep-learning)是开发强大模型和理解深度神经网络基础机制的重要资源;
160 | * 有关该领域的详尽介绍和参考,我们推荐你进入Ian Goodfellow, Yoshua Bengio和Aaron Courville的[《Deep Learning》](https://www.deeplearningbook.org);
161 | * 最后但并非最不重要的是,这本书的完整版本现已在Early Access中提供,预计印刷日期为2019年末:https://www.manning.com/books/deep-learning-with-pytorch 。
162 |
163 | ## 练习
164 |
165 | * 在你的简单神经网络模型上做不同隐藏神经元的数量以及学习率的实验。
166 | * 哪些变化导致模型的输出更加线性?
167 | * 你能否使模型明显过拟合数据?
168 |
169 | * 物理学中第三难的问题是找到合适的葡萄酒来庆祝研究发现。从第3章中加载葡萄酒数据,并使用适当数量的输入参数创建一个新模型。
170 | * 与温度计数据相比,训练需要多长时间?
171 | * 你能否解释哪些因素会影响训练时间?
172 | * 在训练该数据集时损失会下降吗?
173 | * 如何绘制该数据集的图示?
174 |
175 | ## 总结
176 |
177 | * 神经网络可以自动调整以专门解决手头的问题。
178 | * 神经网络允许我们轻松访问模型中任何参数关于损失的导数,这使参数的改进变得高效。凭借自动求导引擎,PyTorch可以轻松计算出这些导数。
179 | * 围绕线性变换的激活函数使神经网络能够逼近高度非线性函数,同时使它们足够简单以容便易优化。
180 | * `nn`模块与张量标准库一起提供了用于创建神经网络的所有构建块。
181 | * 要想识别过拟合,必须将训练集与验证集分开。没有解决过拟合的诀窍,但是获取更多数据(或数据具有更多可变性)并采用更简单的模型是不错的尝试。
182 | * 任何从事数据科学的人都应该一直在绘制数据。
--------------------------------------------------------------------------------
/docs/img/chapter1/1.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter1/1.1.png
--------------------------------------------------------------------------------
/docs/img/chapter1/1.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter1/1.2.png
--------------------------------------------------------------------------------
/docs/img/chapter1/1.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter1/1.3.png
--------------------------------------------------------------------------------
/docs/img/chapter1/1.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter1/1.4.png
--------------------------------------------------------------------------------
/docs/img/chapter2/2.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter2/2.1.png
--------------------------------------------------------------------------------
/docs/img/chapter2/2.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter2/2.2.png
--------------------------------------------------------------------------------
/docs/img/chapter2/2.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter2/2.3.png
--------------------------------------------------------------------------------
/docs/img/chapter2/2.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter2/2.4.png
--------------------------------------------------------------------------------
/docs/img/chapter2/2.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter2/2.5.png
--------------------------------------------------------------------------------
/docs/img/chapter2/2.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter2/2.6.png
--------------------------------------------------------------------------------
/docs/img/chapter3/3.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter3/3.1.png
--------------------------------------------------------------------------------
/docs/img/chapter3/3.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter3/3.2.png
--------------------------------------------------------------------------------
/docs/img/chapter3/3.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter3/3.3.png
--------------------------------------------------------------------------------
/docs/img/chapter3/3.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter3/3.4.png
--------------------------------------------------------------------------------
/docs/img/chapter4/4.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter4/4.1.png
--------------------------------------------------------------------------------
/docs/img/chapter4/4.10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter4/4.10.png
--------------------------------------------------------------------------------
/docs/img/chapter4/4.11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter4/4.11.png
--------------------------------------------------------------------------------
/docs/img/chapter4/4.12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter4/4.12.png
--------------------------------------------------------------------------------
/docs/img/chapter4/4.13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter4/4.13.png
--------------------------------------------------------------------------------
/docs/img/chapter4/4.14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter4/4.14.png
--------------------------------------------------------------------------------
/docs/img/chapter4/4.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter4/4.2.png
--------------------------------------------------------------------------------
/docs/img/chapter4/4.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter4/4.3.png
--------------------------------------------------------------------------------
/docs/img/chapter4/4.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter4/4.4.png
--------------------------------------------------------------------------------
/docs/img/chapter4/4.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter4/4.5.png
--------------------------------------------------------------------------------
/docs/img/chapter4/4.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter4/4.6.png
--------------------------------------------------------------------------------
/docs/img/chapter4/4.7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter4/4.7.png
--------------------------------------------------------------------------------
/docs/img/chapter4/4.8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter4/4.8.png
--------------------------------------------------------------------------------
/docs/img/chapter4/4.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter4/4.9.png
--------------------------------------------------------------------------------
/docs/img/chapter5/5.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter5/5.1.png
--------------------------------------------------------------------------------
/docs/img/chapter5/5.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter5/5.2.png
--------------------------------------------------------------------------------
/docs/img/chapter5/5.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter5/5.3.png
--------------------------------------------------------------------------------
/docs/img/chapter5/5.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter5/5.4.png
--------------------------------------------------------------------------------
/docs/img/chapter5/5.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter5/5.5.png
--------------------------------------------------------------------------------
/docs/img/chapter5/5.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter5/5.6.png
--------------------------------------------------------------------------------
/docs/img/chapter5/5.7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter5/5.7.png
--------------------------------------------------------------------------------
/docs/img/chapter5/5.8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/chapter5/5.8.png
--------------------------------------------------------------------------------
/docs/img/cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/cover.png
--------------------------------------------------------------------------------
/docs/img/twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShusenTang/Deep-Learning-with-PyTorch-Chinese/c650465e89c2c0b78261b614f1d77a9371530077/docs/img/twitter.png
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DL-with-PyTorch-CHN
6 |
7 |
8 |
9 |
10 |
11 |
12 |
24 |
25 |
26 |
27 |
65 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------