-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
347 lines (204 loc) · 291 KB
/
Copy pathatom.xml
File metadata and controls
347 lines (204 loc) · 291 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>逗比南波万</title>
<subtitle>welcome to my blog</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://yoursite.com/"/>
<updated>2021-05-16T13:08:12.000Z</updated>
<id>http://yoursite.com/</id>
<author>
<name>王振</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>图像处理_homework2</title>
<link href="http://yoursite.com/2021/05/16/%E5%9B%BE%E5%83%8F%E5%A4%84%E7%90%86-homework2/"/>
<id>http://yoursite.com/2021/05/16/图像处理-homework2/</id>
<published>2021-05-16T10:12:32.000Z</published>
<updated>2021-05-16T13:08:12.000Z</updated>
<content type="html"><![CDATA[<h2 id="内容"><a href="#内容" class="headerlink" title="内容"></a>内容</h2><p>图像处理课程第二次作业</p><a id="more"></a><h2 id="1-Questions"><a href="#1-Questions" class="headerlink" title="1. Questions"></a>1. Questions</h2><h3 id="1-1"><a href="#1-1" class="headerlink" title="1.1"></a>1.1</h3><p><img src="/2021/05/16/图像处理-homework2/image-20210504142846870.png" alt="image-20210504142846870"></p><p>上面是第一对图片经过 Harris corner detection 得到的结果,可以看到第一张图片有四个角点,而第二张图片一个都没有,从原图以及结果来看,出现这种情况的原因应该是第二张图片的清晰度比较低,比较模糊,因此在各个位置的 cornerness score 会比较低,没有超过 Threshold,所以没有检测出角点</p><p><img src="/2021/05/16/图像处理-homework2/image-20210504143007116.png" alt="image-20210504143007116"></p><p>上面是第二对图片经过 Harris corner detection 得到的结果,与第一张图片相比,第二张图片中建筑的拍摄角度不太相同,并且还有许多其他的人或景物,因此位于建筑上的角点比较少,而且还有很多位于其他地方的角点,出现这种情况就是因为拍摄的角度问题,以及其他人和景物的干扰</p><p><img src="/2021/05/16/图像处理-homework2/image-20210504143507684.png" alt="image-20210504143507684"></p><p>上面是第三对图片经过 Harris corner detection 得到的结果,第一张图片中的角点都集中在鞋子上,第二张图片中的角点都集中在边缘的一些椅子腿之类的东西上面,而两张图片在地板上都没有出现角点,出现这种情况的原因可能是地板的特征值变化不大,没有超过 Threshold,因此角点都在其他的物体上</p><p><img src="/2021/05/16/图像处理-homework2/image-20210504143040840.png" alt="image-20210504143040840"></p><p>于是我将 Threshold 从 0.5 改为了 0.01,在这种情况下第一张图片的角点不变,而第二张图片中出现了很多,这种情况下两张图片的不同就是由于光线的区别</p><blockquote><p>因此在现实世界中,无论是拍摄的清晰度,拍摄的角度,其他物体的干扰,以及拍摄时的光线,滤镜等,都会对于图片的特征匹配造成影响,而同时代码中对于 threshold 或是其他参数的设置,也会有一定的影响</p></blockquote><h3 id="1-2"><a href="#1-2" class="headerlink" title="1.2"></a>1.2</h3><p>local image brightness 在哪个方向变化的越快,那么那个方向的特征值就会越大</p><p>我们可以将M可视化为椭圆,其轴长由M的特征值决定,方向由M的特征向量确定</p><h3 id="1-3"><a href="#1-3" class="headerlink" title="1.3"></a>1.3</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># You can assume access to the image , x and y gradients , and their magnitudes /</span></span><br><span class="line"><span class="comment"># orientations .</span></span><br><span class="line"></span><br><span class="line">image = imread (’rara .jpg ’)</span><br><span class="line">grad_x = filter ( image , ’sobelX ’)</span><br><span class="line">grad_y = filter ( image , ’sobelY ’)</span><br><span class="line">grad_mag = sqrt ( grad_x .^ <span class="number">2</span> + grad_y .^ <span class="number">2</span> )</span><br><span class="line">grad_ori = atan2 ( grad_y , grad_x )</span><br><span class="line"></span><br><span class="line"><span class="comment"># Takes in a feature point x,y location and returns a descriptor</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">SIFTdescriptor</span> <span class="params">(x , y )</span></span></span><br><span class="line">descriptor = zeros ( 128 , 1 )</span><br><span class="line"><span class="comment"># write your psudocode here ...</span></span><br><span class="line"> num = <span class="number">0</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(x<span class="number">-8</span>, x+<span class="number">8</span>, <span class="number">4</span>): <span class="comment"># 将周围16*16区域的所有行划分为四个部分</span></span><br><span class="line"> <span class="keyword">for</span> k <span class="keyword">in</span> range(y<span class="number">-8</span>, y+<span class="number">8</span>, <span class="number">4</span>): <span class="comment"># 将周围16*16区域的所有列划分为四个部分,总共16个部分</span></span><br><span class="line"> cell = np.zeros(<span class="number">9</span>) <span class="comment"># cell 为一个区域的描述符 其中cell[0]和cell[8]是一个方向</span></span><br><span class="line"> <span class="keyword">for</span> a <span class="keyword">in</span> (i,i+<span class="number">4</span>):</span><br><span class="line"> <span class="keyword">for</span> b <span class="keyword">in</span> (k,k+<span class="number">4</span>): <span class="comment"># 遍历一个区域内的每个点</span></span><br><span class="line"> <span class="comment"># 将该点的梯度强度加到最近的方向上</span></span><br><span class="line"> cell[round(<span class="number">4</span> * grad_ori[a][b] / np.pi + <span class="number">4</span>)] += grad_mag[a][b]</span><br><span class="line"> cell[<span class="number">0</span>] += cell[<span class="number">8</span>] <span class="comment"># 因为cell[0]和cell[8]是一个方向,所以要合并</span></span><br><span class="line"> cell = list(cell)</span><br><span class="line"> <span class="keyword">del</span> cell[<span class="number">8</span>] <span class="comment"># 删除最后的,因为已经加到cell[0]了</span></span><br><span class="line"> descriptor[num:num+<span class="number">8</span>]=cell <span class="comment"># 将单个区域的描述符赋值到总描述符的对应位置</span></span><br><span class="line"> num += <span class="number">1</span></span><br><span class="line"><span class="keyword">return</span> descriptor</span><br></pre></td></tr></table></figure><h3 id="1-4"><a href="#1-4" class="headerlink" title="1.4"></a>1.4</h3><p>(a) <img src="/2021/05/16/图像处理-homework2/image-20210504214724458.png" alt="image-20210504214724458"></p><p>如图是两个向量 A(x1, y1) 和 B(x2, y2),那么欧氏距离就是两个向量之间的实际距离 d,而余弦相似度为两个向量之间的夹角 θ,因此当向量的大小无关紧要时,余弦相似度通常用作距离的度量,而当向量的大小重要的时候需要使用欧氏距离作为距离的度量</p><p>(b) 如果给定了一个距离度量的方法,我们可以使用 Nearest Neighbor Distance Ratio 的方法来进行特征匹配,对于第一幅图中的每个点,计算出第二幅图中与其最近的距离和第二近的距离的比例,将所有点的比例按照从小到大排序,即为匹配的准确性的排序,因为这个比例越大,就代表第二幅图中有其他点与要匹配的点的相似度越高,那么进行特征匹配的准确率就越低,而比例越小,就代表这个点越独特,也能更好的作为要匹配的特征点</p><h3 id="1-5"><a href="#1-5" class="headerlink" title="1.5"></a>1.5</h3><h4 id="a"><a href="#a" class="headerlink" title="(a)"></a>(a)</h4><p>line 是由满足坐标 (u+λa, v+λb), ∀λ ∈ R 的点组成的,对于其中的每一个点 (x, y),经过变换后的点满足</p><script type="math/tex; mode=display">x'= \frac {h_{11}x+h_{12}y+h_{13}} {h_{31}x+h_{32}y+h_{33}}</script><script type="math/tex; mode=display">y'= \frac {h_{21}x+h_{22}y+h_{23}} {h_{31}x+h_{32}y+h_{33}}</script><p>因此变换后的线是由满足坐标</p><script type="math/tex; mode=display">(\frac {h_{11}(u+\lambda a)+h_{12}(v+\lambda b)+h_{13}} {h_{31}(u+\lambda a)+h_{32}(v+\lambda b)+h_{33}},\frac {h_{21}(u+\lambda a)+h_{22}(v+\lambda b)+h_{23}} {h_{31}(u+\lambda a)+h_{32}(v+\lambda b)+h_{33}}),\forall\lambda\in R</script><p>的点组成的</p><h4 id="b"><a href="#b" class="headerlink" title="(b)"></a>(b)</h4><p>要使变换后的线汇聚到一个点,那么对于任意的 λ ,坐标都应该是一样的,那么有以下几种情况:</p><ol><li><p>a=0, b=0 此时汇聚点的坐标为 </p><script type="math/tex; mode=display">(\frac {h_{11}u+h_{12}v+h_{13}} {h_{31}u+h_{32}v+h_{33}},\frac {h_{21}u+h_{22}v+h_{23}} {h_{31}u+h_{32}v+h_{33}})</script></li><li><p>a=0, H 的第二列均为0 此时汇聚点的坐标为 </p><script type="math/tex; mode=display">(\frac {h_{11}u+h_{13}} {h_{31}u+h_{33}},\frac {h_{21}u+h_{23}} {h_{31}u+h_{33}})</script></li><li><p>b=0, H 的第一列均为0 此时汇聚点的坐标为</p><script type="math/tex; mode=display">(\frac {h_{12}v+h_{13}} {h_{32}v+h_{33}},\frac {h_{22}v+h_{23}} {h_{32}v+h_{33}})</script></li><li><p>H 的第一列和第二列均为0 此时汇聚点的坐标为</p><script type="math/tex; mode=display">(\frac {h_{13}} {h_{33}},\frac {h_{23}} {h_{33}})</script></li></ol><h4 id="c"><a href="#c" class="headerlink" title="(c)"></a>(c)</h4><p>如果 a, b, H的第一列的值, H的第二列的值不满足上一问的任何一种情况,则变换后的线不会汇聚到一个点</p><h2 id="2-Programming-Project"><a href="#2-Programming-Project" class="headerlink" title="2. Programming Project"></a>2. Programming Project</h2><h3 id="2-1-Implement-match-features"><a href="#2-1-Implement-match-features" class="headerlink" title="2.1 Implement match_features()"></a>2.1 Implement match_features()</h3><h4 id="计算欧氏距离"><a href="#计算欧氏距离" class="headerlink" title="计算欧氏距离"></a>计算欧氏距离</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">dist = []</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> im1_features:</span><br><span class="line"> temp = []</span><br><span class="line"> <span class="keyword">for</span> k <span class="keyword">in</span> im2_features:</span><br><span class="line"> vec_dist = np.sum((i-k)**<span class="number">2</span>)**<span class="number">0.5</span></span><br><span class="line"> temp.append(vec_dist)</span><br><span class="line"> dist.append(temp)</span><br><span class="line">dist = np.array(dist)</span><br></pre></td></tr></table></figure><p>开始写了一个循环版本的,后来看到要求使用 numpy 中的函数不能用循环,就写了一个计算欧氏距离的函数</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">euclidean_distances</span><span class="params">(a, b)</span>:</span></span><br><span class="line"> bt = b.transpose()</span><br><span class="line"> vec_prod = np.dot(a, bt)</span><br><span class="line"> </span><br><span class="line"> sqa = a ** <span class="number">2</span></span><br><span class="line"> sum_sqa = np.array(np.sum(sqa, axis=<span class="number">1</span>))</span><br><span class="line"> sum_sqa_ex = np.tile(sum_sqa, (vec_prod.shape[<span class="number">1</span>], <span class="number">1</span>)).transpose()</span><br><span class="line"></span><br><span class="line"> sqb = b ** <span class="number">2</span></span><br><span class="line"> sum_sqb = np.sum(sqb, axis=<span class="number">1</span>)</span><br><span class="line"> sum_sqb_ex = np.tile(sum_sqb, (vec_prod.shape[<span class="number">0</span>], <span class="number">1</span>))</span><br><span class="line"></span><br><span class="line"> sq_ed = sum_sqb_ex + sum_sqa_ex - <span class="number">2</span> * vec_prod</span><br><span class="line"> sq_ed[sq_ed < <span class="number">0</span>] = <span class="number">0.0</span></span><br><span class="line"> ed = np.sqrt(sq_ed)</span><br><span class="line"> <span class="keyword">return</span> ed</span><br></pre></td></tr></table></figure><p>要求 a,b 两个集合中的元素两两间欧氏距离,先求出 a 乘 b 的转置,然后对 a 和 bt 分别求其中每个向量的模平方,并使用 tile 函数扩展为原来的大小,然后相加减去 2倍 的 a 乘 b 转置开平方就得到了结果,开平方之前把小于零的变为0,防止开平方出错</p><h4 id="最近邻匹配"><a href="#最近邻匹配" class="headerlink" title="最近邻匹配"></a>最近邻匹配</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">matches = np.zeros((len(im1_features), <span class="number">2</span>))</span><br><span class="line">confidences = np.zeros(len(im1_features))</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> range(len(dist)):</span><br><span class="line"> d = sorted(list(dist[i]))</span><br><span class="line"> <span class="comment"># print(d)</span></span><br><span class="line"> nn1 = d[<span class="number">0</span>]</span><br><span class="line"> near_id = np.where(dist[i] == nn1)[<span class="number">0</span>][<span class="number">0</span>]</span><br><span class="line"> <span class="comment"># print("near_id:", near_id)</span></span><br><span class="line"> nn2 = d[<span class="number">1</span>]</span><br><span class="line"> ratio = nn1 / nn2</span><br><span class="line"> <span class="comment"># print(ratio)</span></span><br><span class="line"></span><br><span class="line"> matches[i][<span class="number">0</span>] = i</span><br><span class="line"> matches[i][<span class="number">1</span>] = near_id</span><br><span class="line"> confidences[i] = <span class="number">1</span> / ratio</span><br></pre></td></tr></table></figure><p>对于第一幅图片的每一个特征点,在第二幅图片中找到欧氏距离最小的点作为匹配点,计算最小的距离和第二小的距离的比,将这个比的倒数作为 confidence</p><p>此时在总共149个匹配中只有一个能匹配成功</p><h3 id="2-2-Change-get-features"><a href="#2-2-Change-get-features" class="headerlink" title="2.2 Change get_features()"></a>2.2 Change get_features()</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">features = np.zeros((len(x), <span class="number">256</span>))</span><br><span class="line">width_2 = int(feature_width/<span class="number">2</span>)</span><br><span class="line">width_4 = int(feature_width/<span class="number">4</span>)</span><br><span class="line"><span class="keyword">for</span> j <span class="keyword">in</span> range(len(x)):</span><br><span class="line"> <span class="keyword">if</span> int(x[j]) - width_2 < <span class="number">0</span> <span class="keyword">or</span> int(x[j]) + width_2 >= image.shape[<span class="number">1</span>] <span class="keyword">or</span> int(y[j]) - width_2 < <span class="number">0</span> <span class="keyword">or</span> int(y[j]) + width_2 >= image.shape[<span class="number">0</span>]:</span><br><span class="line"> <span class="keyword">continue</span></span><br><span class="line"> one_feature = image[int(y[j])-width_2:int(y[j])+width_2, int(x[j])-width_2:int(x[j])+width_2]</span><br><span class="line"> one_feature = one_feature.reshape(<span class="number">1</span>, <span class="number">256</span>)</span><br><span class="line"> features[j] = np.array(one_feature)</span><br><span class="line"><span class="keyword">return</span> features</span><br></pre></td></tr></table></figure><p>直接使用 image 里面的值作为特征值,此时的结果为:</p><p><img src="/2021/05/16/图像处理-homework2/image-20210508103912178.png" alt="image-20210508103912178"></p><p><img src="/2021/05/16/图像处理-homework2/image-20210508103927352.png" alt="image-20210508103927352"></p><p><img src="/2021/05/16/图像处理-homework2/image-20210508110240040.png" alt="image-20210508110240040"></p><p><img src="/2021/05/16/图像处理-homework2/image-20210508110251330.png" alt="image-20210508110251330"></p><h3 id="2-3-Finish-get-features-by-implementing-a-SIFT-like-feature"><a href="#2-3-Finish-get-features-by-implementing-a-SIFT-like-feature" class="headerlink" title="2.3 Finish get_features() by implementing a SIFT-like feature"></a>2.3 Finish get_features() by implementing a SIFT-like feature</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">features = np.zeros((len(x), <span class="number">128</span>))</span><br><span class="line">width_2 = int(feature_width/<span class="number">2</span>)</span><br><span class="line">width_4 = int(feature_width/<span class="number">4</span>)</span><br><span class="line"><span class="keyword">for</span> j <span class="keyword">in</span> range(len(x)):</span><br><span class="line"> <span class="keyword">if</span> int(x[j]) - width_2 < <span class="number">0</span> <span class="keyword">or</span> int(x[j]) + width_2 >= image.shape[<span class="number">1</span>] <span class="keyword">or</span> int(y[j]) - width_2 < <span class="number">0</span> <span class="keyword">or</span> int(y[j]) + width_2 >= image.shape[<span class="number">0</span>]:</span><br><span class="line"> <span class="keyword">continue</span></span><br><span class="line"> one_feature = []</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(int(y[j]) - width_2, int(y[j]) + width_2, width_4):</span><br><span class="line"> <span class="keyword">for</span> k <span class="keyword">in</span> range(int(x[j]) - width_2, int(x[j]) + width_2, width_4):</span><br><span class="line"> cell = np.zeros(<span class="number">9</span>)</span><br><span class="line"> <span class="keyword">for</span> a <span class="keyword">in</span> range(i, i + width_4):</span><br><span class="line"> <span class="keyword">for</span> b <span class="keyword">in</span> range(k, k + width_4):</span><br><span class="line"> x_grad = (image[a + <span class="number">1</span>][b] - image[a - <span class="number">1</span>][b]) / <span class="number">2</span></span><br><span class="line"> y_grad = (image[a][b + <span class="number">1</span>] - image[a][b - <span class="number">1</span>]) / <span class="number">2</span></span><br><span class="line"> grad = np.sqrt(x_grad ** <span class="number">2</span> + y_grad ** <span class="number">2</span>)</span><br><span class="line"> orientation = np.arctan2(y_grad, x_grad)</span><br><span class="line"> cell[round(<span class="number">4</span> * orientation / np.pi + <span class="number">4</span>)] += grad</span><br><span class="line"> cell[<span class="number">0</span>] += cell[<span class="number">8</span>]</span><br><span class="line"> cell = list(cell)</span><br><span class="line"> <span class="keyword">del</span> cell[<span class="number">8</span>]</span><br><span class="line"> one_feature.extend(cell)</span><br><span class="line"> one_feature = [(float(x) - min(one_feature)) / float(max(one_feature) - min(one_feature)) <span class="keyword">if</span> float(max(one_feature) - min(one_feature)) != <span class="number">0</span> <span class="keyword">else</span> <span class="number">1</span> <span class="keyword">for</span> x <span class="keyword">in</span> one_feature]</span><br><span class="line"> features[j] = np.array(one_feature)</span><br><span class="line"><span class="keyword">return</span> features</span><br></pre></td></tr></table></figure><p>对于每一个关键点,将以关键点为中心的 feature_width<em>feature_width 大小的区域划分为 `4</em>4=16<code>个小区域,计算出每一个区域在八个方向上的梯度大小,拼接成长度为</code>4<em>4</em>8=128` 的特征向量,最后进行归一化,此时结果如下:<br><img src="/2021/05/16/图像处理-homework2/image-20210508104250629.png" alt="image-20210508104250629"></p><p><img src="/2021/05/16/图像处理-homework2/image-20210508105814568.png" alt="image-20210508105814568"></p><p><img src="/2021/05/16/图像处理-homework2/image-20210508110114661.png" alt="image-20210508110114661"></p><p><img src="/2021/05/16/图像处理-homework2/image-20210508110130316.png" alt="image-20210508110130316"></p><p>可以看到准确率在 notre_dame 上提升了一点,但是在 mt_rushmore 上提升了许多</p><h3 id="2-4-Stop-cheating-and-implement-get-interest-points"><a href="#2-4-Stop-cheating-and-implement-get-interest-points" class="headerlink" title="2.4 Stop cheating and implement get_interest_points()"></a>2.4 Stop cheating and implement get_interest_points()</h3><blockquote><p>在开始的时候我没有在多尺度上提取关键点,只是使用了 Harris Corner detection,首先对输入的图片进行一次高斯滤波,高斯核大小为<code>3*3</code>,sigma为1,随后对处理之后的图片计算出 x 方向和 y 方向的梯度grad_x和 grad_y,随后计算出 <code>grad_x*grad_x</code>, <code>grad_x*grad_y</code>, <code>grad_y*grad_y</code>, 再对这三个梯度分别进行一次高斯滤波,高斯核大小为<code>9*9</code>,sigma为2,然后利用下面的公式计算出每个点的 cornerness,为了避免边缘效应,我将图片 feature_width 大小的边缘的值设置为0,随后先利用 threshold 得到 cornerness 较大的点,再使用 cv2 中的 dilate 将每个点的值变为局部极大值,然后得到这些局部极大值对应的点,即为我们要寻找的关键点,但是这样测试的结果不太稳定,即准确率随 threshold 值的变化而产生的变化很大<img src="/2021/05/16/图像处理-homework2/image-20210514231639541.png" alt="image-20210514231639541"></p><p>因为我看到实验结果不是很好,所以紧接着就决定在多个尺度上进行特征提取</p></blockquote><h3 id="textcolor-red-Extra-credit-:Detect-keypoints-at-multiple-scales"><a href="#textcolor-red-Extra-credit-:Detect-keypoints-at-multiple-scales" class="headerlink" title="$\textcolor{red}{Extra\ credit} $:Detect keypoints at multiple scales"></a>$\textcolor{red}{Extra\ credit} $:Detect keypoints at multiple scales</h3><blockquote><p>在多尺度上检测关键点就是建立高斯金字塔和差分金字塔,其中多尺度指的是对同一幅图片用不同的高斯核进行滤波,来得到图片的不同尺度的特征,然后寻找特征点的时候要判断特征点的 cornerness 值是否在差分金字塔的当前尺度和相邻尺度的邻域最大,然后据我调查,高斯金字塔设置为多个组的原因是工程上的需要,因此我在本次实验中只计算并使用了和输入图片相同大小的一个组。</p></blockquote><p>具体代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line">start = time.time()</span><br><span class="line"> sigma = <span class="number">1</span></span><br><span class="line"> octave = []</span><br><span class="line"> <span class="keyword">for</span> k <span class="keyword">in</span> range(<span class="number">0</span>, <span class="number">5</span>):</span><br><span class="line"> sigma_new = sigma*(<span class="number">2</span>**(k/<span class="number">2</span>))</span><br><span class="line"> kernel_size = ceil(sigma_new*<span class="number">6</span>)</span><br><span class="line"> <span class="keyword">if</span> kernel_size % <span class="number">2</span> == <span class="number">0</span>:</span><br><span class="line"> kernel_size += <span class="number">1</span></span><br><span class="line"> image = GaussianBlur(image, ksize=(kernel_size, <span class="number">1</span>), sigmaX=sigma_new)</span><br><span class="line"> image = GaussianBlur(image, ksize=(<span class="number">1</span>, kernel_size), sigmaX=sigma_new)</span><br><span class="line"> octave.append(image)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> k <span class="keyword">in</span> range(<span class="number">4</span>, <span class="number">0</span>, <span class="number">-1</span>):</span><br><span class="line"> octave[k] -= octave[k<span class="number">-1</span>]</span><br><span class="line"> <span class="keyword">del</span> octave[<span class="number">0</span>]</span><br><span class="line"> </span><br><span class="line"> alpha = <span class="number">0.06</span></span><br><span class="line"> hs = []</span><br><span class="line"> cs = []</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">4</span>):</span><br><span class="line"> grad_x, grad_y = np.gradient(octave[i])</span><br><span class="line"> grad_xy = grad_x * grad_y</span><br><span class="line"> grad_xy = GaussianBlur(grad_xy, ksize=(<span class="number">9</span>, <span class="number">1</span>), sigmaX=<span class="number">2</span>, sigmaY=<span class="number">2</span>)</span><br><span class="line"> grad_xy = GaussianBlur(grad_xy, ksize=(<span class="number">1</span>, <span class="number">9</span>), sigmaX=<span class="number">2</span>, sigmaY=<span class="number">2</span>)</span><br><span class="line"> grad_xx = grad_x * grad_x</span><br><span class="line"> grad_xx = GaussianBlur(grad_xx, ksize=(<span class="number">9</span>, <span class="number">1</span>), sigmaX=<span class="number">2</span>, sigmaY=<span class="number">2</span>)</span><br><span class="line"> grad_xx = GaussianBlur(grad_xx, ksize=(<span class="number">1</span>, <span class="number">9</span>), sigmaX=<span class="number">2</span>, sigmaY=<span class="number">2</span>)</span><br><span class="line"> grad_yy = grad_y * grad_y</span><br><span class="line"> grad_yy = GaussianBlur(grad_yy, ksize=(<span class="number">9</span>, <span class="number">1</span>), sigmaX=<span class="number">2</span>, sigmaY=<span class="number">2</span>)</span><br><span class="line"> grad_yy = GaussianBlur(grad_yy, ksize=(<span class="number">1</span>, <span class="number">9</span>), sigmaX=<span class="number">2</span>, sigmaY=<span class="number">2</span>)</span><br><span class="line"> h = grad_xx * grad_yy - grad_xy * grad_xy - alpha * (grad_xx + grad_yy) * (grad_xx + grad_yy)</span><br><span class="line"> </span><br><span class="line"> border = np.zeros(octave[i].shape)</span><br><span class="line"> border[feature_width:-feature_width, feature_width:-feature_width] = <span class="number">1</span></span><br><span class="line"> h = h * border</span><br><span class="line"> </span><br><span class="line"> t = np.max(h)/<span class="number">10</span></span><br><span class="line"> h = h * (h > t)</span><br><span class="line"> hs.append(h)</span><br><span class="line"> kernel = np.ones((<span class="number">2</span>, <span class="number">2</span>), np.uint8)</span><br><span class="line"> pz = dilate(h, kernel, iterations=<span class="number">1</span>)</span><br><span class="line"> cs.append(pz)</span><br><span class="line"> xs = np.zeros(<span class="number">0</span>)</span><br><span class="line"> ys = np.zeros(<span class="number">0</span>)</span><br><span class="line"> scale = np.zeros(<span class="number">0</span>)</span><br><span class="line"> hs = np.array(hs)</span><br><span class="line"> cs = np.array(cs)</span><br><span class="line"> kernel = np.ones((<span class="number">2</span>, <span class="number">2</span>), np.uint8)</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(cs.shape[<span class="number">1</span>]):</span><br><span class="line"> cs[:, i, :] = dilate(cs[:, i, :], kernel, iterations=<span class="number">1</span>)</span><br><span class="line"> c = (hs == cs)</span><br><span class="line"> hs = c*hs</span><br><span class="line"> points = zip(*np.nonzero(hs[<span class="number">1</span>:<span class="number">3</span>, feature_width:-feature_width, feature_width:-feature_width]))</span><br><span class="line"> <span class="keyword">for</span> point <span class="keyword">in</span> list(points):</span><br><span class="line"> xs = np.append(xs, point[<span class="number">2</span>]+feature_width)</span><br><span class="line"> ys = np.append(ys, point[<span class="number">1</span>]+feature_width)</span><br><span class="line"> scale = np.append(scale, point[<span class="number">0</span>]+<span class="number">1</span>)</span><br><span class="line"> print(<span class="string">f'function get_intereset_points cost <span class="subst">{time.time() - start}</span>s'</span>)</span><br><span class="line"> <span class="keyword">return</span> xs, ys, scale</span><br></pre></td></tr></table></figure><ol><li>根据输入图片用不同的高斯核向同组的上一张图片进行滤波,得到高斯金字塔的一个组 octave</li><li>计算出差分金字塔</li><li>对于差分金字塔的每一层,像原来一样计算出梯度,进行高斯滤波,计算每一个点的 cornerness 值,去除边缘效应,其中我将阈值 threshold 设置为 cornerness 的最大值除以十,因为不同的图片所需要的阈值不同,因此这样设置能得到相对还可以的关键点的数量,在除以十的情况下,image1中得到的关键点的数量和题目中提到的300~700相一致,然后用dilate在当前尺度下进行膨胀操作</li><li>因为我们要求的关键点不仅要在当前尺度局部最大,还要在相邻尺度局部最大,因此我们在另一个维度也进行膨胀操作,随后得到局部极大值的坐标和对应尺度并返回</li></ol><h3 id="textcolor-red-Extra-credit-:Multi-scale-descriptor"><a href="#textcolor-red-Extra-credit-:Multi-scale-descriptor" class="headerlink" title="$\textcolor{red}{Extra\ credit} $:Multi-scale descriptor"></a>$\textcolor{red}{Extra\ credit} $:Multi-scale descriptor</h3><blockquote><p>既然我们已经在多个尺度上提取了图像的关键点,那么在提取特征的时候也要从对应的尺度来提取,因此要对原有的代码进行更改,首先就是在函数开始用和上面同样的方法计算出相应的高斯金字塔和差分金字塔,在提取特征的时候,先根据特征的尺度确定要在哪张图片上提取特征,随后跟之前一样提取一个128维的特征即可</p></blockquote><h3 id="最终结果"><a href="#最终结果" class="headerlink" title="最终结果"></a>最终结果</h3><h4 id="notre-dame"><a href="#notre-dame" class="headerlink" title="notre_dame"></a>notre_dame</h4><p><img src="/2021/05/16/图像处理-homework2/image-20210515093808930.png" alt="image-20210515093808930"></p><p><img src="/2021/05/16/图像处理-homework2/image-20210515094016827.png" alt="image-20210515094016827"></p><blockquote><p>将 threshold 改为 最大值除以20:t = np.max(h)/20</p></blockquote><p><img src="/2021/05/16/图像处理-homework2/image-20210515094557177.png" alt="image-20210515094557177"></p><p><img src="/2021/05/16/图像处理-homework2/image-20210515094623765.png" alt="image-20210515094623765"></p><h4 id="mt-rushmore"><a href="#mt-rushmore" class="headerlink" title="mt_rushmore"></a>mt_rushmore</h4><p><img src="/2021/05/16/图像处理-homework2/image-20210515094244648.png" alt="image-20210515094244648"></p><p><img src="/2021/05/16/图像处理-homework2/image-20210515094304138.png" alt="image-20210515094304138"></p><blockquote><p>将 threshold 改为 最大值除以20:t = np.max(h)/20</p></blockquote><p><img src="/2021/05/16/图像处理-homework2/image-20210515095022595.png" alt="image-20210515095022595"></p><p><img src="/2021/05/16/图像处理-homework2/image-20210515095036254.png" alt="image-20210515095036254"></p><blockquote><p>可以看到最终再 notre_dame 和 mt_rushmore 两组图片中的准确率都非常高,当 <code>t = np.max(h)/10</code>的时候,notre_dame 在 50 most confident 的匹配准确率为 78%,而 mt_rushmore 在 50 most confident 的匹配准确率为 90%,而当 <code>t = np.max(h)/20</code>的时候,两组图片在 50 most confident 的匹配准确率都达到了 90% 以上,即使是在 100 most confident 中也分别达到了 70%+ 和 80%+ 的准确率,远远高于题目中的要求</p></blockquote>]]></content>
<summary type="html">
<h2 id="内容"><a href="#内容" class="headerlink" title="内容"></a>内容</h2><p>图像处理课程第二次作业</p>
</summary>
<category term="图像处理" scheme="http://yoursite.com/tags/%E5%9B%BE%E5%83%8F%E5%A4%84%E7%90%86/"/>
</entry>
<entry>
<title>智能计算机实验</title>
<link href="http://yoursite.com/2020/12/21/%E6%99%BA%E8%83%BD%E8%AE%A1%E7%AE%97%E6%9C%BA/"/>
<id>http://yoursite.com/2020/12/21/智能计算机/</id>
<published>2020-12-21T08:01:31.000Z</published>
<updated>2021-05-16T13:08:20.000Z</updated>
<content type="html"><![CDATA[<h1 id="智能计算机实验"><a href="#智能计算机实验" class="headerlink" title="智能计算机实验"></a>智能计算机实验</h1><h2 id="我对于此课程实验的看法"><a href="#我对于此课程实验的看法" class="headerlink" title="我对于此课程实验的看法"></a>我对于此课程实验的看法</h2><p>关于此实验的指导比较少,主要来源就是寒武纪论坛和一些大体的指导,没有详细的介绍,而这门实验的测试是在服务器上进行的,坑比较多,因此可能会耗费比较多的时间(除非你直接补充那七个文件而且不用在服务器上测试,平台提交直接AC)</p><p>这篇文章的主要目的是提供一个比较详细的实验完成方法,并且减少大家在完成实验过程中踩的坑,但是不会提供具体的代码</p><p><strong>注意</strong>:如果你想快速顺利的完成此实验,可以观看这篇文章</p><p> 如果你想锻炼自己根据报错找 bug 的能力或者根据报错自学 tensorflow 的能力,可以先选择自己完成实验,如果实在是感到 困难,可以再来观看这篇文章</p><a id="more"></a><h2 id="实验一"><a href="#实验一" class="headerlink" title="实验一"></a>实验一</h2><p>(听说不用快速幂和多核拆分就能过,哭了)</p><ol><li>进入 /opt 将压缩包解压</li><li>进入 /opt/AICSE-demo-student/env 执行 source env.sh</li><li>cd tensorflow-v1.10 执行 source env.sh 然后激活虚拟环境</li></ol><p><img src="/2020/12/21/智能计算机/image-20201221161604172.png" alt="image-20201221161604172"></p><ol><li>以上两步非常重要,在每一次进入服务器之后都要执行,否则会在执行脚本或编译的时候出现奇怪的错误</li><li><p>进入 /opt/AICSE-demo-student/demo/style_transfer_bcl/src/bangc/PluginPowerDifferenceOp ,开始进行代码的补充,我建议的顺序如下:</p><ul><li>plugin_power_difference_kernel.mlu </li><li>plugin_power_difference_kernel.h</li><li>powerDiff.cpp</li><li>plugin_power_difference_op.cc</li><li>cnplugin.h</li></ul></li><li><p>在 .mlu 中进行 PowerDifference 算子的实现,这个部分比较简单,需要注意的地方为 GDRAM 和 NRAM 之间的转换,我的理解就是参数中的变量都是 GDRAM,你在函数中创建的 <code>__nram__ half</code> 变量都是 NRAM,而你的实现大概能分为三个阶段:</p><ul><li>初级阶段,实现了基本的算子功能,能得到60分</li><li>中级阶段,用快速幂进行实现,能够小幅降低在 CNRT 上的延时,能得到70分(不过不用快速幂可能也行</li><li>高级阶段,实现多核拆分计算,能够同时在多个核上进行运算,能得到100分(bushi</li></ul><p>此部分需要用到一些 bangc 的内置函数,使用其中的三个函数就能实现此算子:</p><ul><li><p>__memcpy (目标地址,源地址,长度,RAM类型转换) 功能为将源地址之后一定长度的数据拷贝到目标地址</p><p>一个栗子:<code>__memcpy(input1_nram+i*Seg, input1+i*Seg, Seg*sizeof(half), GDRAM2NRAM);</code></p></li><li><p>__bang_sub (目标地址,被减数,减数,长度) 功能为进行一定长度的向量减法,结果储存在目标地址</p><p>一个栗子:<code>__bang_sub(input1_nram+i*Seg, input1_nram+i*Seg, input2_nram+i*Seg, Seg);</code></p></li><li><p>__bang_mul 与上面类似,只不过进行的是乘法</p></li></ul><p>关于函数的具体使用以及更多的函数介绍,可以参考 bangc 的开发指导书</p><p>噢,忘说了,函数的参数大致是这样:<code>__mlu_entry__ void PowerDifferenceKernel(half* input1, half* input2, int pow, half* output, int len)</code></p></li><li><p>补全 plugin_power_difference_kernel.h,非常简单,只要和 .mlu 中的函数参数一致即可</p></li><li><p>补全 powerDiff.cpp,这部分若要自己写可能比较困难,我的建议是参照本来就有的其他算子的实现来完成,需要注意的是将其中的 *Kernel 改成自己的 PowerDifferenceKernel,当然还可能有其他的都需要改成 PowerDifference 对应的格式,在参照其他算子完成补全后,需要注意的是,如果你想使用多核拆分的话,还要修改两个地方:</p><ul><li>将 dim.x = 1 改为 dim.x = 8</li><li>将 cnrtFunctionType_t c 改为 CNRT_FUNC_TYPE_UNION2</li></ul></li><li><p>补全 plugin_power_difference_op.cc,这个比较难搞,即使参照其他算子,也比较烦人,我对于此部分的建议是选择的参照算子的实现可以选择简单的,并且不要思考的太过于复杂(</p></li><li><p>补全 cnplugin.h,参照上面的实现,定义 PowerDifference 对应的结构,结构指针以及 plugin_power_difference_op.cc 中函数的声明</p></li><li><p>在补全了以上文件之后,就可以进行算子的测试啦,在 xxx/src/bangc/PluginPowerDifferenceOp 中执行以下两句:</p><ul><li>bash make.sh</li><li>./power_diff_test</li></ul><p>就可以看到测试结果,正确的测试结果大致如下:</p><p><img src="/2020/12/21/智能计算机/image-20201221170316556.png" alt="image-20201221170316556"></p></li><li><p>如果你的运行结果和上图差不多,说明你前面的实现已经差不多完成啦,接下来就要进行 cnplugin 的集成,步骤如下:</p><ul><li><p>将 cnplugin.h 复制到下面两个目录中:</p><p>/opt/AICSE-demo-student/env/neuware/include/</p><p>/opt/AICSE-demo-student/env/Cambricon-CNPlugin-MLU270/common/include/</p></li><li><p>在 /opt/AICSE-demo-student/env/Cambricon-CNPlugin-MLU270 处执行 bash build_cnplugin.sh —mlu200,如果编译的最后显示 build success,说明你编译成功,会在 ./build 文件夹中生成新的 libcnplugin.so</p></li><li><p>将新生成的 libcnplugin.so 复制到 /opt/AICSE-demo-student/env/neuware/lib64/ 文件夹下</p></li></ul></li><li><p>很快啊,cnplugin 的集成就完成了,接下来要进行的就是 TensorFlow 算子集成,此部分首先需要按照 /opt/AICSE-demo-student/demo/style_transfer_bcl/src/tf-implementation/tf-add-power-diff/readme.txt 即下图:</p><p><img src="/2020/12/21/智能计算机/image-20201221171419046.png" alt="image-20201221171419046"></p><p>将此文件夹下的其他文件复制到 readme.txt 里对应的文件夹中,在进行这一步时请务必仔细,否则在稍后编译时可能会产生各种各样奇怪的 bug,在复制完成后,如果你直接在 /opt/AICSE-demo-student/env/tensorflow-v1.10 中执行 bash build_tensorflow-v1.10_mlu.sh,有 99.9% 的可能会出现以下的错误:</p><p><img src="/2020/12/21/智能计算机/image-20201221171900968.png" alt="image-20201221171900968"></p><p>根据错误信息可以看出来,实验提供的 mlu_lib_ops.cc 和你补充的 plugin_power_difference_op.cc 中 ,cnmlCreatePluginPowerDifferenceOp 以及 cnmlComputePluginPowerDifferenceOpForward 的参数不同,你需要选择修改其中之一来保证两个文件中的参数一致,我的建议是修改实验提供的 mlu_lib_ops.cc,因为修改起来比较简单,并且在其中你可以使用 nullptr 来填充参数,,下面是我的实现以供参考:</p><p>mlu_lib_ops.cc 中对于 plugin_power_difference_op的调用:<br><img src="/2020/12/21/智能计算机/image-20201222121105346.png" alt="image-20201222121105346"><br>plugin_power_difference_op.cc 中 plugin_power_difference_op 的参数:<br><img src="/2020/12/21/智能计算机/image-20201222121110969.png" alt="image-20201222121110969"><br>mlu_lib_ops.cc 中对于 cnmlComputePluginPowerDifferenceOpForward的调用:<br><img src="/2020/12/21/智能计算机/image-20201222121125219.png" alt="image-20201222121125219"><br>plugin_power_difference_op.cc 中 cnmlComputePluginPowerDifferenceOpForward 的参数:<br><img src="/2020/12/21/智能计算机/image-20201222121129289.png" alt="image-20201222121129289"></p><p>若在完成这一步之后,你的编译出现socket错误,就要将 .sh 文件中的 job_num 改为 16 ,你应该就可以成功的进行 tensorflow的编译啦(可能需要较长的时间</p></li><li><p>最后就是补全 …/src/online_mlu/power_difference_test_bcl.py 和 …/src/online_cpu/power_difference_test_cpu.py 文件 , 执行 python power_difference_test_xxx.py 进行测试,这两个文件的补全比较简单,并且是基本一样的,只是在 test_bcl 中有一个特殊的地方要修改,因此我的建议是先进行 cpu 的测试,成功的测试结果如下图:</p><p><img src="/2020/12/21/智能计算机/image-20201221173107160.png" alt="image-20201221173107160"></p><p>而当你将补全的地方复制到 test_mlu.py 中,进行测试,你会得到以下结果:</p><p><img src="/2020/12/21/智能计算机/image-20201221173352870.png" alt="image-20201221173352870"></p><p>我在开始的时候将代码中的 os.environ[‘MLU_VISIBLE_DEVICES’] = “0” 改为 os.environ[‘MLU_VISIBLE_DEVICES’] = “1” ,然后再次测试:</p><p><img src="/2020/12/21/智能计算机/image-20201221173555856.png" alt="image-20201221173555856"></p><p>虽然错误率看上去比较高,但是交上去的话可以过。不过这种改的方法应该是不正确的, 而且在实验二中这个问题会同样出现但是无法解决, 出现这种情况的原因应该是在多核拆分的循环的最后一次中数据的长度不足 Seg,因此我们需要将最后的一次单独提取出来做计算,之后的结果是这样的:</p><p><img src="/2020/12/21/智能计算机/image-20200118.png" alt="image-20200118"></p><p>可以看到错误率比之前低了很多</p></li><li><p>最后,如果你使用了快速幂,多核拆分,但是在 MLU 上仍然有着 100+ ms 的延迟,那么你需要在 test_bcl.py 中进行如下修改:</p><p><img src="/2020/12/21/智能计算机/image-20201221173834863.png" alt="image-20201221173834863"></p><p>因为 MLU 的启动时间比较慢,所以可以多次运行来获得更低的延迟,如果这样你还不能拿到满分,请多提交几次</p></li><li><p>补充:如果你提交到平台上的结果为 JSON 格式错误,说明你代码写错了,请确保你在如上测试中都成功的运行出了正确的结果,如果你在实验的完成过程中出现了其他错误,请看一下自己是不是漏了某个步骤,或者某个步骤做的不够仔细,如果还是不行的话,请前往和助教对线或者在群里请求帮助,此外,请务必不要重启你的服务器,<del>否则就会像我一样丢掉所有数据然后重新配一遍</del></p></li></ol><h2 id="实验一选作(四选一)—-softmax-算子实现"><a href="#实验一选作(四选一)—-softmax-算子实现" class="headerlink" title="实验一选作(四选一)— softmax 算子实现"></a>实验一选作(四选一)— softmax 算子实现</h2><h3 id="softmax-算子介绍"><a href="#softmax-算子介绍" class="headerlink" title="softmax 算子介绍"></a>softmax 算子介绍</h3><p><img src="/2020/12/21/智能计算机/image-20201222014249959.png" alt="image-20201222014249959"></p><h3 id="算子实现"><a href="#算子实现" class="headerlink" title="算子实现"></a>算子实现</h3><p>因为输入数据的规模为 20 × 256,共 20 行,256 列,我们首先要找出每一列的最大值,方法为每次接受一行的数据,对于每一列来说,如果新输入的数据大于最大值,就更新,否则不变,然后将每一列的所有数减去这个最大值,求出 e 关于这个数的指数,再全部加起来,然后取一个倒数,然后对于每一列的每一个数,乘以之前计算出来的倒数,这样计算出来的结果即为正确结果</p><h3 id="具体代码"><a href="#具体代码" class="headerlink" title="具体代码"></a>具体代码</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"mlu.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> input_size 20 # 列数</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> input_num 256 # 行数</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> LEN 256*20</span></span><br><span class="line">__<span class="function">mlu_entry__ <span class="keyword">void</span> <span class="title">SoftmaxKernel</span><span class="params">(half* input, half* output)</span></span></span><br><span class="line"><span class="function"></span>{ </span><br><span class="line"> __nram__ half input_nram[input_num];</span><br><span class="line"> __nram__ half output_nram[LEN];</span><br><span class="line"> __nram__ half temp1_nram[input_num];</span><br><span class="line"> __nram__ half temp2_nram[input_num];</span><br><span class="line"> __nram__ half comL_nram[input_num];</span><br><span class="line"> __nram__ half sum_nram[input_num];</span><br><span class="line"> __nram__ half sum_recip_nram[input_num];</span><br><span class="line"> __nram__ half mulL_nram[input_num];</span><br><span class="line"> __nram__ half mulR_nram[input_num];</span><br><span class="line"> __nramset_half(comL_nram, input_num, <span class="number">-3000.0</span>);</span><br><span class="line"> __nramset_half(sum_nram, input_num,<span class="number">0.0</span>);</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int32_t</span> i=<span class="number">0</span>; i<input_size;i++)</span><br><span class="line"> {</span><br><span class="line"> __memcpy(input_nram, input+i*input_num, input_num*<span class="keyword">sizeof</span>(half),GDRAM2NRAM); # 分别获取每行的输入数据</span><br><span class="line"> __bang_gt(temp1_nram,comL_nram,input_nram,input_num); # 若输入值小于最大值,则对应位置为<span class="number">1</span></span><br><span class="line"> __bang_not(temp2_nram,temp1_nram,input_num); # 若输入值大于最大值,则对应位置为<span class="number">1</span></span><br><span class="line"> __bang_mul(mulL_nram,temp1_nram,comL_nram,input_num); # 最大值不变的位置,置最大值</span><br><span class="line"> __bang_mul(mulR_nram,temp2_nram,input_nram,input_num); # 最大值改变的位置,置输入值</span><br><span class="line"> __bang_add(comL_nram,mulL_nram,mulR_nram,input_num); # 相加得到每列新的最大值</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int32_t</span> i=<span class="number">0</span>; i<input_size;i++)</span><br><span class="line"> {</span><br><span class="line"> __memcpy(input_nram, input+i*input_num, input_num*<span class="keyword">sizeof</span>(half),GDRAM2NRAM); # 分别获取每行的输入数据</span><br><span class="line"> __bang_sub(temp1_nram,input_nram,comL_nram,input_num); # 每一列减去该列最大值</span><br><span class="line"> __bang_active_exp(temp2_nram,temp1_nram,input_num); # 求 e 关于 j-max 的指数</span><br><span class="line"> __bang_add(sum_nram,sum_nram,temp2_nram,input_num); # 将所有的指数相加得到分母</span><br><span class="line"> }</span><br><span class="line"> __bang_active_recip(sum_recip_nram,sum_nram,input_num); # 求出分母的倒数</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int32_t</span> i=<span class="number">0</span>; i<input_size;i++)</span><br><span class="line"> {</span><br><span class="line"> __memcpy(input_nram, input+i*input_num, input_num*<span class="keyword">sizeof</span>(half),GDRAM2NRAM); # 分别获取每行的输入数据</span><br><span class="line"> __bang_sub(temp1_nram,input_nram,comL_nram,input_num); # 每一列减去该列最大值</span><br><span class="line"> __bang_active_exp(temp2_nram,temp1_nram,input_num); # 求 e 关于 i-max 的指数,即分子</span><br><span class="line"> __bang_mul(temp2_nram,temp2_nram,sum_recip_nram,input_num); # 将分子和分母的倒数相乘,得到结果</span><br><span class="line"> __memcpy(output+i*input_num,temp2_nram,input_num*<span class="keyword">sizeof</span>(half),NRAM2GDRAM); # 将结果返回到输出中</span><br><span class="line"> }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="实验总结"><a href="#实验总结" class="headerlink" title="实验总结"></a>实验总结</h3><p>该实验对于 softmax 算子进行实现,难点在于如何灵活的运用 bangc 提供的各种函数对于数据进行操作和计算,只要按照 softmax 的定义对式子一步一步的计算,并合理的运用 bangc 提供的函数,就可以比较简单的实现 softmax 算子,在这个过程中,bangc 的教学文档起到了很大的作用,文档对于各种各样的函数做出了详细的解释与注意事项,可以对算子实现起到很大的帮助</p><h2 id="实验二"><a href="#实验二" class="headerlink" title="实验二"></a>实验二</h2><h3 id="模型量化"><a href="#模型量化" class="headerlink" title="模型量化"></a>模型量化</h3><p>该部分代码和量化手段已经提前给出,直接按照<a href="http://forum.cambricon.com/uploadfile/user/file/20200714/1594717975554836.pdf" target="_blank" rel="noopener">教程</a>即可完成。</p><h3 id="在线推理"><a href="#在线推理" class="headerlink" title="在线推理"></a>在线推理</h3><p>在线推理部分主要分为两块,分别需要补全</p><p>/opt/AICSE-demo-student/demo/style_transfer_bcl/src/online_mlu/transform_mlu.py 和</p><p>/opt/AICSE-demo-student/demo/style_transfer_bcl/src/online_cpu/transform_cpu.py</p><h4 id="online-cpu"><a href="#online-cpu" class="headerlink" title="online_cpu"></a>online_cpu</h4><p>在cpu部分里,使用到的模型是非量化后的模型文件。</p><p>该部分需要补全两个函数run_ori_power_diff_pb和run_numpy_pb</p><ul><li><p><strong>run_ori_power_diff_pb</strong> :直接按照同文件下的run_ori_pb逻辑进行书写,但是要注意该函数使用的计算图与run_ori_pb不同点在于将原生的差平方计算算子改成了实验一中集成的power_difference算子,所以只需要我们进行feed数据(<strong>不需要</strong>重新实现power_difference的计算),将pow值传递至计算图计算。而其在<strong>计算图中的各节点信息可使用<a href="https://lutzroeder.github.io/netron/" target="_blank" rel="noopener">神经网络模型可视化网站</a>进行查找</strong>。</p><p><img src="/2020/12/21/智能计算机/image-20201222004846500.png" alt="image-20201222004846500"></p><p>从图中可以看出除了 X 还额外需要 feed 一个数据,即 PowerDifference_z,给它赋值为2即可,相当于将pow = 2 传递给了计算图</p><p><img src="/2020/12/21/智能计算机/image-20201222004912384.png" alt="image-20201222004912384"></p></li><li><p><strong>run_numpy_pb</strong>:与上一个类似,只不过这里需要我们手动将原生的差平方计算算子的输入数据提出并使用实验一中的power_diff_numpy.py的内置函数进行计算后,再传回计算图进行计算。<strong>需要注意</strong>该函数的输入参数跟上一个run_ori_power_diff_pb的计算图一样的参数,因为这里要手动算,所以在可视化的计算图上可以发现这里断开了。</p><p><img src="/2020/12/21/智能计算机/image-20201222004933612.png" alt="image-20201222004933612"></p><p>上面这张图是使用原生的差平方计算算子的模型,可以看到SquaredDifference算子的输入分别为Conv2D_13和 moments_15/StopGradient</p><p><img src="/2020/12/21/智能计算机/image-20201222004952263.png" alt="image-20201222004952263"></p><p>可以看到这个模型的 Conv2D_13和 moments_15/StopGradient 并没有参与到算子的计算中,所以我们要把这两个节点的数据提取出来,再加上一个 pow 值为 2,作为 power_diff_numpy 的三个参数计算出 PowerDifference 算子的输出结果,此处需要注意的是从计算图中提取出来的 Tensor 不能直接进行 reshape,否则会报错,所以我们要通过 eval() 将其转换为数组,并且要向 eval() feed 一个数据 X</p><p><img src="/2020/12/21/智能计算机/image-20201222005007770.png" alt="image-20201222005007770"></p></li><li><p>全部代码</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> tensorflow <span class="keyword">as</span> tf</span><br><span class="line"><span class="keyword">from</span> tensorflow.python.platform <span class="keyword">import</span> gfile</span><br><span class="line"><span class="keyword">import</span> argparse</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> cv2 <span class="keyword">as</span> cv</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">from</span> power_diff_numpy <span class="keyword">import</span> *</span><br><span class="line"></span><br><span class="line">os.putenv(<span class="string">'MLU_VISIBLE_DEVICES'</span>,<span class="string">''</span>)</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">parse_arg</span><span class="params">()</span>:</span></span><br><span class="line"> parser = argparse.ArgumentParser()</span><br><span class="line"> parser.add_argument(<span class="string">'image'</span>)</span><br><span class="line"> parser.add_argument(<span class="string">'ori_pb'</span>)</span><br><span class="line"> parser.add_argument(<span class="string">'ori_power_diff_pb'</span>)</span><br><span class="line"> parser.add_argument(<span class="string">'numpy_pb'</span>)</span><br><span class="line"> args = parser.parse_args()</span><br><span class="line"> <span class="keyword">return</span> args</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">run_ori_pb</span><span class="params">()</span>:</span></span><br><span class="line"> args = parse_arg()</span><br><span class="line"> config = tf.ConfigProto(allow_soft_placement=<span class="literal">True</span>,</span><br><span class="line"> inter_op_parallelism_threads=<span class="number">1</span>,</span><br><span class="line"> intra_op_parallelism_threads=<span class="number">1</span>)</span><br><span class="line"> model_name = os.path.basename(args.ori_pb).split(<span class="string">"."</span>)[<span class="number">0</span>]</span><br><span class="line"> image_name = os.path.basename(args.image).split(<span class="string">"."</span>)[<span class="number">0</span>]</span><br><span class="line"></span><br><span class="line"> g = tf.Graph()</span><br><span class="line"> <span class="keyword">with</span> g.as_default():</span><br><span class="line"> <span class="keyword">with</span> tf.gfile.FastGFile(args.ori_pb,<span class="string">'rb'</span>) <span class="keyword">as</span> f:</span><br><span class="line"> graph_def = tf.GraphDef()</span><br><span class="line"> graph_def.ParseFromString(f.read())</span><br><span class="line"> tf.import_graph_def(graph_def, name=<span class="string">''</span>)</span><br><span class="line"> img = cv.imread(args.image)</span><br><span class="line"> X = cv.resize(img, (<span class="number">256</span>, <span class="number">256</span>))</span><br><span class="line"> <span class="keyword">with</span> tf.Session(config=config) <span class="keyword">as</span> sess:</span><br><span class="line"> sess.graph.as_default()</span><br><span class="line"> sess.run(tf.global_variables_initializer())</span><br><span class="line"></span><br><span class="line"> input_tensor = sess.graph.get_tensor_by_name(<span class="string">'X_content:0'</span>)</span><br><span class="line"> output_tensor = sess.graph.get_tensor_by_name(<span class="string">'add_37:0'</span>)</span><br><span class="line"></span><br><span class="line"> start_time = time.time()</span><br><span class="line"> ret =sess.run(output_tensor, feed_dict={input_tensor:[X]})</span><br><span class="line"> end_time = time.time()</span><br><span class="line"> print(<span class="string">"C++ inference(CPU) origin pb time is: "</span>,end_time-start_time)</span><br><span class="line"> img1 = tf.reshape(ret,[<span class="number">256</span>,<span class="number">256</span>,<span class="number">3</span>])</span><br><span class="line"> img_numpy = img1.eval(session=sess)</span><br><span class="line"> cv.imwrite(image_name + <span class="string">'_'</span> + model_name + <span class="string">'_cpu.jpg'</span>,img_numpy)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">run_ori_power_diff_pb</span><span class="params">()</span>:</span></span><br><span class="line"> args = parse_arg()</span><br><span class="line"> config = tf.ConfigProto(allow_soft_placement=<span class="literal">True</span>,</span><br><span class="line"> inter_op_parallelism_threads=<span class="number">1</span>,</span><br><span class="line"> intra_op_parallelism_threads=<span class="number">1</span>)</span><br><span class="line"> model_name = os.path.basename(args.ori_power_diff_pb).split(<span class="string">"."</span>)[<span class="number">0</span>]</span><br><span class="line"> image_name = os.path.basename(args.image).split(<span class="string">"."</span>)[<span class="number">0</span>]</span><br><span class="line"></span><br><span class="line"> g = tf.Graph()</span><br><span class="line"> <span class="keyword">with</span> g.as_default():</span><br><span class="line"> <span class="keyword">with</span> tf.gfile.FastGFile(args.ori_power_diff_pb,<span class="string">'rb'</span>) <span class="keyword">as</span> f:</span><br><span class="line"> graph_def = tf.GraphDef()</span><br><span class="line"> graph_def.ParseFromString(f.read())</span><br><span class="line"> tf.import_graph_def(graph_def, name=<span class="string">''</span>)</span><br><span class="line"> img = cv.imread(args.image)</span><br><span class="line"> X = cv.resize(img, (<span class="number">256</span>, <span class="number">256</span>))</span><br><span class="line"> <span class="keyword">with</span> tf.Session(config=config) <span class="keyword">as</span> sess:</span><br><span class="line"> sess.graph.as_default()</span><br><span class="line"> sess.run(tf.global_variables_initializer())</span><br><span class="line"></span><br><span class="line"> input_tensor1 = sess.graph.get_tensor_by_name(<span class="string">'X_content:0'</span>)</span><br><span class="line"> input_tensor2 = sess.graph.get_tensor_by_name(<span class="string">'moments_15/PowerDifference_z:0'</span>)</span><br><span class="line"> output_tensor = sess.graph.get_tensor_by_name(<span class="string">'add_37:0'</span>)</span><br><span class="line"></span><br><span class="line"> start_time = time.time()</span><br><span class="line"> ret =sess.run(output_tensor, feed_dict={input_tensor1:[X], input_tensor2:<span class="number">2</span>})</span><br><span class="line"> end_time = time.time()</span><br><span class="line"> print(<span class="string">"C++ inference(CPU) time is: "</span>,end_time-start_time)</span><br><span class="line"> img1 = tf.reshape(ret,[<span class="number">256</span>,<span class="number">256</span>,<span class="number">3</span>])</span><br><span class="line"> img_numpy = img1.eval(session=sess)</span><br><span class="line"> cv.imwrite(image_name + <span class="string">'_'</span> + model_name + <span class="string">'_cpu.jpg'</span>,img_numpy)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">run_numpy_pb</span><span class="params">()</span>:</span></span><br><span class="line"> args = parse_arg()</span><br><span class="line"> config = tf.ConfigProto(allow_soft_placement=<span class="literal">True</span>,</span><br><span class="line"> inter_op_parallelism_threads=<span class="number">1</span>,</span><br><span class="line"> intra_op_parallelism_threads=<span class="number">1</span>)</span><br><span class="line"> model_name = os.path.basename(args.numpy_pb).split(<span class="string">"."</span>)[<span class="number">0</span>]</span><br><span class="line"> image_name = os.path.basename(args.image).split(<span class="string">"."</span>)[<span class="number">0</span>]</span><br><span class="line"></span><br><span class="line"> g = tf.Graph()</span><br><span class="line"> <span class="keyword">with</span> g.as_default():</span><br><span class="line"> <span class="keyword">with</span> tf.gfile.FastGFile(args.numpy_pb,<span class="string">'rb'</span>) <span class="keyword">as</span> f:</span><br><span class="line"> graph_def = tf.GraphDef()</span><br><span class="line"> graph_def.ParseFromString(f.read())</span><br><span class="line"> tf.import_graph_def(graph_def, name=<span class="string">''</span>)</span><br><span class="line"> img = cv.imread(args.image)</span><br><span class="line"> X = cv.resize(img, (<span class="number">256</span>, <span class="number">256</span>))</span><br><span class="line"> <span class="keyword">with</span> tf.Session(config=config) <span class="keyword">as</span> sess:</span><br><span class="line"> sess.graph.as_default()</span><br><span class="line"> sess.run(tf.global_variables_initializer())</span><br><span class="line"></span><br><span class="line"> input_tensor1 = sess.graph.get_tensor_by_name(<span class="string">'X_content:0'</span>)</span><br><span class="line"> input_tensor2 = sess.graph.get_tensor_by_name(<span class="string">'moments_15/PowerDifference:0'</span>)</span><br><span class="line"> output_tensor = sess.graph.get_tensor_by_name(<span class="string">'add_37:0'</span>)</span><br><span class="line"></span><br><span class="line"> start_time = time.time()</span><br><span class="line"> input_2 = power_diff_numpy(sess.graph.get_tensor_by_name(<span class="string">'Conv2D_13:0'</span>).eval(feed_dict={input_tensor1:[X]}),sess.graph.get_tensor_by_name(<span class="string">'moments_15/StopGradient:0'</span>).eval(feed_dict={input_tensor1:[X]}),<span class="number">2</span>)</span><br><span class="line"> ret =sess.run(output_tensor, feed_dict={input_tensor1:[X], input_tensor2:input_2})</span><br><span class="line"> end_time = time.time()</span><br><span class="line"> print(<span class="string">"Numpy inference(CPU) time is: "</span>,end_time-start_time)</span><br><span class="line"> img1 = tf.reshape(ret,[<span class="number">256</span>,<span class="number">256</span>,<span class="number">3</span>])</span><br><span class="line"> img_numpy = img1.eval(session=sess)</span><br><span class="line"> cv.imwrite(image_name + <span class="string">'_'</span> + model_name + <span class="string">'_cpu.jpg'</span>,img_numpy)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> run_ori_pb()</span><br><span class="line"> run_ori_power_diff_pb()</span><br><span class="line"> run_numpy_pb()</span><br></pre></td></tr></table></figure></li></ul><h4 id="online-mlu"><a href="#online-mlu" class="headerlink" title="online_mlu"></a>online_mlu</h4><p>在mlu部分,使用到的模型是量化后的模型文件。</p><p>仅仅需要在每个函数前加上</p><p><code>config.mlu_options.save_offline_model = True</code></p><p>这句话用于保存量化后可用于mlu的离线模型,其余部分均与cpu相同</p><h3 id="离线推理"><a href="#离线推理" class="headerlink" title="离线推理"></a>离线推理</h3><p><del>令人惊讶的是,当我写完了在线推理之后,提交了一手发现居然拿了满分,于是我还没有写离线推理</del></p><p>代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"inference.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"cnrt.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdlib.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><string.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"stdlib.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/time.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><time.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> StyleTransfer{</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">unsigned</span> <span class="keyword">short</span> half;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">cnrtConvertFloatToHalfArray</span><span class="params">(<span class="keyword">uint16_t</span>* x, <span class="keyword">const</span> <span class="keyword">float</span>* y, <span class="keyword">int</span> len)</span> </span>{</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < len; i++){</span><br><span class="line"> cnrtConvertFloatToHalf(x+i,y[i]);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">cnrtConvertHalfToFloatArray</span><span class="params">(<span class="keyword">float</span>* x, <span class="keyword">const</span> <span class="keyword">uint16_t</span>* y, <span class="keyword">int</span> len)</span> </span>{</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < len; i++){</span><br><span class="line"> cnrtConvertHalfToFloat(x+i,y[i]);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">cnrtConvertFloatToHalfArray</span><span class="params">(<span class="keyword">uint16_t</span>* x, <span class="keyword">float</span>* y, <span class="keyword">int</span> len)</span> </span>{</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < len; i++){</span><br><span class="line"> cnrtConvertFloatToHalf(x+i,y[i]);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">cnrtConvertHalfToFloatArray</span><span class="params">(<span class="keyword">float</span>* x, <span class="keyword">uint16_t</span>* y, <span class="keyword">int</span> len)</span> </span>{</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < len; i++){</span><br><span class="line"> cnrtConvertHalfToFloat(x+i,y[i]);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Inference :: Inference(<span class="built_in">std</span>::<span class="built_in">string</span> offline_model){</span><br><span class="line"> offline_model_ = offline_model;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> Inference :: run(DataTransfer* DataT){</span><br><span class="line"> cnrtInit(<span class="number">0</span>);</span><br><span class="line"> cnrtModel_t model;</span><br><span class="line"> cnrtLoadModel(&model, offline_model_.c_str());</span><br><span class="line"></span><br><span class="line"> cnrtDev_t dev;</span><br><span class="line"> cnrtGetDeviceHandle(&dev, <span class="number">0</span>);</span><br><span class="line"> cnrtSetCurrentDevice(dev);</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">float</span>* input_data = <span class="keyword">reinterpret_cast</span><<span class="keyword">float</span>*>(<span class="built_in">malloc</span>(<span class="number">256</span>*<span class="number">256</span>*<span class="number">3</span>*<span class="keyword">sizeof</span>(<span class="keyword">float</span>)));</span><br><span class="line"> <span class="keyword">float</span>* output_data = <span class="keyword">reinterpret_cast</span><<span class="keyword">float</span>*>(<span class="built_in">malloc</span>(<span class="number">256</span>*<span class="number">256</span>*<span class="number">3</span>*<span class="keyword">sizeof</span>(<span class="keyword">float</span>)));</span><br><span class="line"> <span class="keyword">int</span> t = <span class="number">256</span>*<span class="number">256</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i<t;i++)</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> j=<span class="number">0</span>;j<<span class="number">3</span>;j++)</span><br><span class="line"> input_data[i*<span class="number">3</span>+j] = DataT->input_data[t*j+i]; </span><br><span class="line"> <span class="keyword">int</span> number = <span class="number">0</span>;</span><br><span class="line"> cnrtGetFunctionNumber(model, &number);</span><br><span class="line"></span><br><span class="line"> cnrtFunction_t function;</span><br><span class="line"> cnrtCreateFunction(&function);</span><br><span class="line"> cnrtExtractFunction(&function, model, <span class="string">"subnet0"</span>);</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"> <span class="keyword">int</span> inputNum, outputNum;</span><br><span class="line"> <span class="keyword">int64_t</span> *inputSizeS, *outputSizeS;</span><br><span class="line"> cnrtGetInputDataSize(&inputSizeS, &inputNum, function);</span><br><span class="line"> cnrtGetOutputDataSize(&outputSizeS, &outputNum, function);</span><br><span class="line"></span><br><span class="line"> DataT->output_data = <span class="keyword">reinterpret_cast</span><<span class="keyword">float</span>*>(<span class="built_in">malloc</span>(<span class="number">256</span> * <span class="number">256</span> * <span class="number">3</span> * <span class="keyword">sizeof</span>(<span class="keyword">float</span>)));</span><br><span class="line"> half* input_half = (half*)<span class="built_in">malloc</span>(<span class="number">256</span> * <span class="number">256</span> * <span class="number">3</span> * <span class="keyword">sizeof</span>(half));</span><br><span class="line"> half* output_half = (half*)<span class="built_in">malloc</span>(<span class="number">256</span> * <span class="number">256</span> * <span class="number">3</span> * <span class="keyword">sizeof</span>(half));</span><br><span class="line"> </span><br><span class="line"> cnrtConvertFloatToHalfArray(input_half, input_data, <span class="number">256</span> * <span class="number">256</span> * <span class="number">3</span>);</span><br><span class="line"> cnrtConvertFloatToHalfArray(output_half, DataT->output_data, <span class="number">256</span> * <span class="number">256</span> * <span class="number">3</span>);</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"> <span class="keyword">void</span> *mlu_input, *mlu_output;</span><br><span class="line"> cnrtMalloc(&(mlu_input), inputSizeS[<span class="number">0</span>]);</span><br><span class="line"> cnrtMalloc(&(mlu_output), outputSizeS[<span class="number">0</span>]);</span><br><span class="line"> cnrtMemcpy(mlu_input, input_half, <span class="number">256</span> * <span class="number">256</span> * <span class="number">3</span> * <span class="keyword">sizeof</span>(half), CNRT_MEM_TRANS_DIR_HOST2DEV);</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"> cnrtRuntimeContext_t ctx;</span><br><span class="line"> cnrtCreateRuntimeContext(&ctx, function, <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line"> cnrtSetRuntimeContextDeviceId(ctx, <span class="number">0</span>);</span><br><span class="line"> cnrtInitRuntimeContext(ctx, <span class="literal">NULL</span>);</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">void</span> *param[<span class="number">2</span>];</span><br><span class="line"> param[<span class="number">0</span>] = mlu_input;</span><br><span class="line"> param[<span class="number">1</span>] = mlu_output;</span><br><span class="line"> cnrtQueue_t <span class="built_in">queue</span>;</span><br><span class="line"> cnrtRuntimeContextCreateQueue(ctx, &<span class="built_in">queue</span>);</span><br><span class="line"> cnrtInvokeRuntimeContext(ctx, (<span class="keyword">void</span>**)param, <span class="built_in">queue</span>, <span class="literal">nullptr</span>);</span><br><span class="line"> cnrtSyncQueue(<span class="built_in">queue</span>);</span><br><span class="line"> </span><br><span class="line"> cnrtMemcpy(output_half, mlu_output, <span class="number">256</span> * <span class="number">256</span> * <span class="number">3</span> * <span class="keyword">sizeof</span>(half), CNRT_MEM_TRANS_DIR_DEV2HOST);</span><br><span class="line"> </span><br><span class="line"> cnrtConvertHalfToFloatArray(output_data, output_half, <span class="number">256</span> * <span class="number">256</span> * <span class="number">3</span>);</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i<t;i++)</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> j=<span class="number">0</span>;j<<span class="number">3</span>;j++)</span><br><span class="line"> DataT->output_data[t*j+i] = output_data[i*<span class="number">3</span>+j];</span><br><span class="line"> cnrtFree(mlu_input);</span><br><span class="line"> cnrtFree(mlu_output);</span><br><span class="line"> cnrtDestroyQueue(<span class="built_in">queue</span>);</span><br><span class="line"> </span><br><span class="line"> cnrtDestroy();</span><br><span class="line"> <span class="built_in">free</span>(input_half);</span><br><span class="line"> <span class="built_in">free</span>(output_half);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="结束语"><a href="#结束语" class="headerlink" title="结束语"></a>结束语</h2><p>在这门课程中,<del>我根据报错找 bug 的能力确实有了很大的提高</del>,虽然体验不是很好,但是自己完成了之后还是挺有成就感的,如果您对于此篇文章有好的提议,或者对于这个实验还有其他的问题,可以向 $wz1234@buaa.edu.cn$ 发送邮件,也欢迎以其他方式和我交流</p>]]></content>
<summary type="html">
<h1 id="智能计算机实验"><a href="#智能计算机实验" class="headerlink" title="智能计算机实验"></a>智能计算机实验</h1><h2 id="我对于此课程实验的看法"><a href="#我对于此课程实验的看法" class="headerlink" title="我对于此课程实验的看法"></a>我对于此课程实验的看法</h2><p>关于此实验的指导比较少,主要来源就是寒武纪论坛和一些大体的指导,没有详细的介绍,而这门实验的测试是在服务器上进行的,坑比较多,因此可能会耗费比较多的时间(除非你直接补充那七个文件而且不用在服务器上测试,平台提交直接AC)</p>
<p>这篇文章的主要目的是提供一个比较详细的实验完成方法,并且减少大家在完成实验过程中踩的坑,但是不会提供具体的代码</p>
<p><strong>注意</strong>:如果你想快速顺利的完成此实验,可以观看这篇文章</p>
<p> 如果你想锻炼自己根据报错找 bug 的能力或者根据报错自学 tensorflow 的能力,可以先选择自己完成实验,如果实在是感到 困难,可以再来观看这篇文章</p>
</summary>
</entry>
<entry>
<title>数字电路复习笔记</title>
<link href="http://yoursite.com/2020/09/07/%E6%95%B0%E5%AD%97%E7%94%B5%E8%B7%AF/"/>
<id>http://yoursite.com/2020/09/07/数字电路/</id>
<published>2020-09-07T08:15:48.000Z</published>
<updated>2021-05-16T13:08:14.000Z</updated>
<content type="html"><![CDATA[<h1 id="数字电路复习笔记"><a href="#数字电路复习笔记" class="headerlink" title="数字电路复习笔记"></a>数字电路复习笔记</h1><p>关于数字电路自己总结的复习笔记,仅供参考,不怎么全</p><a id="more"></a><h2 id="第一章-数制和码制"><a href="#第一章-数制和码制" class="headerlink" title="第一章 数制和码制"></a>第一章 数制和码制</h2><h3 id="进制转换(整数和小数)"><a href="#进制转换(整数和小数)" class="headerlink" title="进制转换(整数和小数)"></a>进制转换(整数和小数)</h3><h3 id="原码,反码,补码"><a href="#原码,反码,补码" class="headerlink" title="原码,反码,补码"></a>原码,反码,补码</h3><blockquote><p>正数的原码等于反码等于补码</p><p>负数的反码等于原码0变1,1变0,补码等于反码+1</p><p>二进制数运算:补码运算</p></blockquote><h3 id="常用编码"><a href="#常用编码" class="headerlink" title="常用编码"></a>常用编码</h3><h4 id="十进制"><a href="#十进制" class="headerlink" title="十进制"></a>十进制</h4><p><img src="/2020/09/07/数字电路/image-20201207095115200.png" alt="image-20201207095115200"></p><p>余3码的数值比对应十进制数多3</p><p>注意下面的权值,代表各个位置为1时的大小</p><h4 id="格雷码"><a href="#格雷码" class="headerlink" title="格雷码"></a>格雷码</h4><p><img src="/2020/09/07/数字电路/image-20201207095702879.png" alt="image-20201207095702879"></p><h2 id="第二章-逻辑代数基础"><a href="#第二章-逻辑代数基础" class="headerlink" title="第二章 逻辑代数基础"></a>第二章 逻辑代数基础</h2><p><img src="/2020/09/07/数字电路/image-20201207100058038.png" alt="image-20201207100058038"></p><p><img src="/2020/09/07/数字电路/image-20201207100101916.png" alt="image-20201207100101916"></p><p><img src="/2020/09/07/数字电路/image-20201207100105985.png" alt="image-20201207100105985"></p><p><img src="/2020/09/07/数字电路/image-20201207100108953.png" alt="image-20201207100108953"></p><p><img src="/2020/09/07/数字电路/image-20201207100257128.png" alt="image-20201207100257128"></p><h3 id="基本公式"><a href="#基本公式" class="headerlink" title="基本公式"></a>基本公式</h3><p><img src="/2020/09/07/数字电路/image-20201207100339923.png" alt="image-20201207100339923"></p><h3 id="常用公式"><a href="#常用公式" class="headerlink" title="常用公式"></a>常用公式</h3><p><img src="/2020/09/07/数字电路/image-20201207100458411.png" alt="image-20201207100458411"></p><h3 id="逻辑函数的表示方法"><a href="#逻辑函数的表示方法" class="headerlink" title="逻辑函数的表示方法"></a>逻辑函数的表示方法</h3><p>逻辑真值表,逻辑函数式,逻辑图(将逻辑关系用图形符号表示出来),波形图</p><p>最小项和最大项</p><p>转化为或非可以先转化为与或非的形式(利用最小项以及Y=(Y ‘) ’),再转换为或非的形式</p><p>逻辑函数化简</p><h3 id="卡诺图"><a href="#卡诺图" class="headerlink" title="卡诺图"></a>卡诺图</h3><p><img src="/2020/09/07/数字电路/image-20201207103734768.png" alt="image-20201207103734768"></p><p>卡诺图合并,可以重复使用一个最小项</p><h3 id="具有无关项的逻辑函数及其化简"><a href="#具有无关项的逻辑函数及其化简" class="headerlink" title="具有无关项的逻辑函数及其化简"></a>具有无关项的逻辑函数及其化简</h3><h2 id="第三章-门电路"><a href="#第三章-门电路" class="headerlink" title="第三章 门电路"></a>第三章 门电路</h2><p><img src="/2020/09/07/数字电路/image-20201207141227512.png" alt="image-20201207141227512"></p><p><img src="/2020/09/07/数字电路/image-20201207141230974.png" alt="image-20201207141230974"></p><h3 id="CMOS门电路"><a href="#CMOS门电路" class="headerlink" title="CMOS门电路"></a>CMOS门电路</h3><p><img src="/2020/09/07/数字电路/image-20201207141338902.png" alt="image-20201207141338902"></p><h4 id="CMOS反相器"><a href="#CMOS反相器" class="headerlink" title="CMOS反相器"></a>CMOS反相器</h4><p><img src="/2020/09/07/数字电路/image-20201207143351015.png" alt="image-20201207143351015"></p><h4 id="CMOS与非门-或非门"><a href="#CMOS与非门-或非门" class="headerlink" title="CMOS与非门 或非门"></a>CMOS与非门 或非门</h4><p><img src="/2020/09/07/数字电路/image-20201207143605620.png" alt="image-20201207143605620"></p><h4 id="CMOS传输门"><a href="#CMOS传输门" class="headerlink" title="CMOS传输门"></a>CMOS传输门</h4><p><img src="/2020/09/07/数字电路/image-20201207150409345.png" alt="image-20201207150409345"></p><p>当C=1,C’=0时导通,C=0,C’=1时截止</p><h4 id="三态输出的CMOS门电路"><a href="#三态输出的CMOS门电路" class="headerlink" title="三态输出的CMOS门电路"></a>三态输出的CMOS门电路</h4><p>b图若EN’连线尾部有圈则为低电平有效,当EN’=0时正常与非门,当EN’=1时高阻</p><p><img src="/2020/09/07/数字电路/image-20201207151538922.png" alt="image-20201207151538922"></p><p>理解3.3.40图 难</p><h3 id="TTL门电路"><a href="#TTL门电路" class="headerlink" title="TTL门电路"></a>TTL门电路</h3><p><img src="/2020/09/07/数字电路/image-20201207155711758.png" alt="image-20201207155711758"></p><p><img src="/2020/09/07/数字电路/image-20201207155851664.png" alt="image-20201207155851664"></p><h4 id="三极管反相器"><a href="#三极管反相器" class="headerlink" title="三极管反相器"></a>三极管反相器</h4><p><img src="/2020/09/07/数字电路/image-20201207155940917.png" alt="image-20201207155940917"></p><h4 id="TTL反相器"><a href="#TTL反相器" class="headerlink" title="TTL反相器"></a>TTL反相器</h4><p><img src="/2020/09/07/数字电路/image-20201207160054355.png" alt="image-20201207160054355"></p><h4 id="TTL门电路——与非门,或非门,与或非门,异或门"><a href="#TTL门电路——与非门,或非门,与或非门,异或门" class="headerlink" title="TTL门电路——与非门,或非门,与或非门,异或门"></a>TTL门电路——与非门,或非门,与或非门,异或门</h4><p>多发射极三极管可以看作两个发射级独立而基极和集电极分别并联在一起的三极管</p><p><img src="/2020/09/07/数字电路/image-20201207163239045.png" alt="image-20201207163239045"></p><p>只要有一个导通,则输出为低电平,只有两个都不导通的时候,则输出端c才是高电平</p><p><img src="/2020/09/07/数字电路/image-20201207163011726.png" alt="image-20201207163011726"></p><p><img src="/2020/09/07/数字电路/image-20201207163100622.png" alt="image-20201207163100622"></p><h4 id="集电极开路输出的门电路(OC门)"><a href="#集电极开路输出的门电路(OC门)" class="headerlink" title="集电极开路输出的门电路(OC门)"></a>集电极开路输出的门电路(OC门)</h4><h4 id="三态输出门电路(TS门)"><a href="#三态输出门电路(TS门)" class="headerlink" title="三态输出门电路(TS门)"></a>三态输出门电路(TS门)</h4><p>高电平有效:</p><p><img src="/2020/09/07/数字电路/image-20201207164852673.png" alt="image-20201207164852673"></p><p>低电平有效:</p><p><img src="/2020/09/07/数字电路/image-20201207164837016.png" alt="image-20201207164837016"></p><h2 id="第四章-组合逻辑电路"><a href="#第四章-组合逻辑电路" class="headerlink" title="第四章 组合逻辑电路"></a>第四章 组合逻辑电路</h2><h3 id="组合逻辑电路的分析方法和设计方法"><a href="#组合逻辑电路的分析方法和设计方法" class="headerlink" title="组合逻辑电路的分析方法和设计方法"></a>组合逻辑电路的分析方法和设计方法</h3><h4 id="分析方法"><a href="#分析方法" class="headerlink" title="分析方法"></a>分析方法</h4><p>将电路图转换为函数式或者真值表</p><h4 id="设计方法"><a href="#设计方法" class="headerlink" title="设计方法"></a>设计方法</h4><ol><li>进行逻辑抽象,根据事件的因果关系确定输入变量和输出变量,定义逻辑状态的含义,根据给定的因果关系列出逻辑真值表</li><li>写出逻辑函数式</li><li>选定器件的类型</li><li>将逻辑函数化简或变换成适当的形式</li><li>根据逻辑函数式画出逻辑电路图</li></ol><h3 id="常用的组合逻辑电路"><a href="#常用的组合逻辑电路" class="headerlink" title="常用的组合逻辑电路"></a>常用的组合逻辑电路</h3><h4 id="编码器"><a href="#编码器" class="headerlink" title="编码器"></a>编码器</h4><h5 id="普通编码器"><a href="#普通编码器" class="headerlink" title="普通编码器"></a>普通编码器</h5><p>任何时刻只允许输入一个编码信号</p><p><img src="/2020/09/07/数字电路/image-20201207180435959.png" alt="image-20201207180435959"></p><p><img src="/2020/09/07/数字电路/image-20201207180624804.png" alt="image-20201207180624804"></p><h5 id="优先编码器"><a href="#优先编码器" class="headerlink" title="优先编码器"></a>优先编码器</h5><p><img src="/2020/09/07/数字电路/image-20201207202208723.png" alt="image-20201207202208723"></p><p>S‘ 为选通输入端,只有S’ = 0 时,编码器才能正常工作,而在S’ = 1时,所有的输出端均被封锁在高电平</p><p><img src="/2020/09/07/数字电路/image-20201207202442317.png" alt="image-20201207202442317"></p><p><img src="/2020/09/07/数字电路/image-20201207202738889.png" alt="image-20201207202738889"></p><p><img src="/2020/09/07/数字电路/image-20201207202617679.png" alt="image-20201207202617679"></p><blockquote><p>当芯片接口带圈时,输入信号表示为 X’</p></blockquote><h5 id="二—十进制优先编码器"><a href="#二—十进制优先编码器" class="headerlink" title="二—十进制优先编码器"></a>二—十进制优先编码器</h5><h4 id="译码器"><a href="#译码器" class="headerlink" title="译码器"></a>译码器</h4><h5 id="普通译码器"><a href="#普通译码器" class="headerlink" title="普通译码器"></a>普通译码器</h5><p><img src="/2020/09/07/数字电路/image-20201207204428555.png" alt="image-20201207204428555"></p><p><img src="/2020/09/07/数字电路/image-20201207204622034.png" alt="image-20201207204622034"></p><p><img src="/2020/09/07/数字电路/image-20201207204956445.png" alt="image-20201207204956445"></p><h5 id="二—十进制译码器"><a href="#二—十进制译码器" class="headerlink" title="二—十进制译码器"></a>二—十进制译码器</h5><h5 id="显示译码器"><a href="#显示译码器" class="headerlink" title="显示译码器"></a>显示译码器</h5><h6 id="七段字符显示器"><a href="#七段字符显示器" class="headerlink" title="七段字符显示器"></a>七段字符显示器</h6><h6 id="BCD-七段显示译码器"><a href="#BCD-七段显示译码器" class="headerlink" title="BCD - 七段显示译码器"></a>BCD - 七段显示译码器</h6><h5 id="用译码器设计组合逻辑电路"><a href="#用译码器设计组合逻辑电路" class="headerlink" title="用译码器设计组合逻辑电路"></a>用译码器设计组合逻辑电路</h5><p><img src="/2020/09/07/数字电路/image-20201207205904689.png" alt="image-20201207205904689"></p><p><img src="/2020/09/07/数字电路/image-20201207210045223.png" alt="image-20201207210045223"></p><h4 id="数据选择器"><a href="#数据选择器" class="headerlink" title="数据选择器"></a>数据选择器</h4><h5 id="四选一数据选择器"><a href="#四选一数据选择器" class="headerlink" title="四选一数据选择器"></a>四选一数据选择器</h5><p><code>A0, A1</code> 决定选择的数据,S‘ 控制电路工作状态,S’ = 0 时数据选择器工作,反之不工作</p><h5 id="八选一数据选择器"><a href="#八选一数据选择器" class="headerlink" title="八选一数据选择器"></a>八选一数据选择器</h5><p><img src="/2020/09/07/数字电路/image-20201207211753609.png" alt="image-20201207211753609"></p><h5 id="用数据选择器设计组合逻辑电路"><a href="#用数据选择器设计组合逻辑电路" class="headerlink" title="用数据选择器设计组合逻辑电路"></a>用数据选择器设计组合逻辑电路</h5><p><img src="/2020/09/07/数字电路/image-20201207225752379.png" alt="image-20201207225752379"></p><h4 id="加法器"><a href="#加法器" class="headerlink" title="加法器"></a>加法器</h4><h5 id="一位加法器"><a href="#一位加法器" class="headerlink" title="一位加法器"></a>一位加法器</h5><p>半加器(不考虑进位)</p><p>全加器(考虑进位)</p><h5 id="多位加法器"><a href="#多位加法器" class="headerlink" title="多位加法器"></a>多位加法器</h5><p>串行进位加法器</p><p>超前进位加法器</p><h4 id="利用加法器设计电路"><a href="#利用加法器设计电路" class="headerlink" title="利用加法器设计电路"></a>利用加法器设计电路</h4><p><img src="/2020/09/07/数字电路/image-20201207230758027.png" alt="image-20201207230758027"></p><h4 id="数值比较器"><a href="#数值比较器" class="headerlink" title="数值比较器"></a>数值比较器</h4><h5 id="1位数值比较器"><a href="#1位数值比较器" class="headerlink" title="1位数值比较器"></a>1位数值比较器</h5><p><img src="/2020/09/07/数字电路/image-20201207231257765.png" alt="image-20201207231257765"></p><h5 id="多位数值比较器"><a href="#多位数值比较器" class="headerlink" title="多位数值比较器"></a>多位数值比较器</h5><p><img src="/2020/09/07/数字电路/image-20201207231703395.png" alt="image-20201207231703395"></p><p>I 是来自低位的比较信息</p><h2 id="第五章-触发器"><a href="#第五章-触发器" class="headerlink" title="第五章 触发器"></a>第五章 触发器</h2><p>能够储存 1 位二值信号的基本单元电路统称为触发器</p><h3 id="SR锁存器"><a href="#SR锁存器" class="headerlink" title="SR锁存器"></a>SR锁存器</h3><p><img src="/2020/09/07/数字电路/image-20201207234319334.png" alt="image-20201207234319334"></p><p><img src="/2020/09/07/数字电路/image-20201207234431264.png" alt="image-20201207234431264"></p><h3 id="电平触发的触发器"><a href="#电平触发的触发器" class="headerlink" title="电平触发的触发器"></a>电平触发的触发器</h3><p>触发信号输入端 触发信号 <code>CLK</code></p><p><img src="/2020/09/07/数字电路/image-20201208093951521.png" alt="image-20201208093951521"></p><p>当 <code>CLK=0</code>时,S, R的信号无法影响到输出,当 <code>CLK=1</code>时,S, R的信号才能起作用</p><p><img src="/2020/09/07/数字电路/image-20201208094730885.png" alt="image-20201208094730885"></p><h3 id="电平触发的D触发器"><a href="#电平触发的D触发器" class="headerlink" title="电平触发的D触发器"></a>电平触发的D触发器</h3><p><img src="/2020/09/07/数字电路/image-20201208095118685.png" alt="image-20201208095118685"></p><p>当<code>CLK=1</code>时,Q的值和D相同,当<code>CLK=0</code>时,Q的值保持不变</p><h3 id="脉冲触发的触发器(主从SR触发器)"><a href="#脉冲触发的触发器(主从SR触发器)" class="headerlink" title="脉冲触发的触发器(主从SR触发器)"></a>脉冲触发的触发器(主从SR触发器)</h3><p><img src="/2020/09/07/数字电路/image-20201208100213115.png" alt="image-20201208100213115"></p><p><img src="/2020/09/07/数字电路/image-20201208100252440.png" alt="image-20201208100252440"></p><p><img src="/2020/09/07/数字电路/image-20201208100311393.png" alt="image-20201208100311393"></p><h3 id="主从-JK-触发器"><a href="#主从-JK-触发器" class="headerlink" title="主从 JK 触发器"></a>主从 JK 触发器</h3><p><img src="/2020/09/07/数字电路/image-20201208100710777.png" alt="image-20201208100710777"></p><p>当下降沿到达时,</p><p>若 J=1, K=0,则Q置1,若 J=0, K=1,则Q置0,若 J=0, K=0,则Q不变,若 J=1, K=1,则Q状态翻转(0变1,1变0)</p><p>主从触发器的状态由全部在CLK=1时的动作决定</p><h3 id="边沿触发的触发器"><a href="#边沿触发的触发器" class="headerlink" title="边沿触发的触发器"></a>边沿触发的触发器</h3><p><img src="/2020/09/07/数字电路/image-20201208102916928.png" alt="image-20201208102916928"></p><p><img src="/2020/09/07/数字电路/image-20201208103050351.png" alt="image-20201208103050351"></p><h3 id="T触发器"><a href="#T触发器" class="headerlink" title="T触发器"></a>T触发器</h3><p><img src="/2020/09/07/数字电路/image-20201208103416148.png" alt="image-20201208103416148"></p><h3 id="触发器分类"><a href="#触发器分类" class="headerlink" title="触发器分类"></a>触发器分类</h3><p><img src="/2020/09/07/数字电路/image-20201208103304650.png" alt="image-20201208103304650"></p><h2 id="第六章-时序逻辑电路"><a href="#第六章-时序逻辑电路" class="headerlink" title="第六章 时序逻辑电路"></a>第六章 时序逻辑电路</h2><h3 id="特性方程"><a href="#特性方程" class="headerlink" title="特性方程"></a>特性方程</h3><p> <img src="/2020/09/07/数字电路/image-20201208120335673.png" alt="image-20201208120335673"></p><p>D 触发器的特性方程 Q* = D</p><p>T 触发器的特性方程 Q* = TQ’ + T’Q</p><h3 id="分析同步时序逻辑电路"><a href="#分析同步时序逻辑电路" class="headerlink" title="分析同步时序逻辑电路"></a>分析同步时序逻辑电路</h3><p><img src="/2020/09/07/数字电路/image-20201208120149198.png" alt="image-20201208120149198"></p><h3 id="异步时序逻辑电路"><a href="#异步时序逻辑电路" class="headerlink" title="异步时序逻辑电路"></a>异步时序逻辑电路</h3><h3 id="常用时序逻辑电路"><a href="#常用时序逻辑电路" class="headerlink" title="常用时序逻辑电路"></a>常用时序逻辑电路</h3><h4 id="寄存器"><a href="#寄存器" class="headerlink" title="寄存器"></a>寄存器</h4><h4 id="移位寄存器"><a href="#移位寄存器" class="headerlink" title="移位寄存器"></a>移位寄存器</h4><p><img src="/2020/09/07/数字电路/image-20201208133000921.png" alt="image-20201208133000921"></p><p><img src="/2020/09/07/数字电路/image-20201208133500161.png" alt="image-20201208133500161"></p><h4 id="计数器"><a href="#计数器" class="headerlink" title="计数器"></a>计数器</h4><h5 id="同步计数器"><a href="#同步计数器" class="headerlink" title="同步计数器"></a>同步计数器</h5><p><img src="/2020/09/07/数字电路/image-20201208162623051.png" alt="image-20201208162623051"></p><p><img src="/2020/09/07/数字电路/image-20201208162700995.png" alt="image-20201208162700995"></p><p><img src="/2020/09/07/数字电路/image-20201208163034352.png" alt="image-20201208163034352"></p><p><img src="/2020/09/07/数字电路/image-20201208163053439.png" alt="image-20201208163053439"></p><h5 id="同步置零和异步置零"><a href="#同步置零和异步置零" class="headerlink" title="同步置零和异步置零"></a>同步置零和异步置零</h5><p><img src="/2020/09/07/数字电路/image-20201208163510773.png" alt="image-20201208163510773"></p><h5 id="异步计数器"><a href="#异步计数器" class="headerlink" title="异步计数器"></a>异步计数器</h5><h5 id="任意进制计数器的构成方法"><a href="#任意进制计数器的构成方法" class="headerlink" title="任意进制计数器的构成方法"></a>任意进制计数器的构成方法</h5><p>假设已有的是N进制计数器,而需要得到的是M进制计数器,此时分为两种情况:</p><ol><li>M<N</li></ol><p>置零法(复位法),置数法(置位法)</p><p>同步置零法:从S0状态出发到达S(M-1)状态时译出同步置零信号,在下一次CLK到达后变为S0状态</p><p><img src="/2020/09/07/数字电路/image-20201208192312875.png" alt="image-20201208192312875"></p><p>异步置零法:从S0状态出发到达S(M)状态时译出异步置零信号,变为S0状态</p><p>同步置数法:到达 Si 状态时令 LD’=0 ,在下一个 CLK 到来时,将要置入的数据置入计数器中,状态变为 Sj</p><p><img src="/2020/09/07/数字电路/image-20201208192326383.png" alt="image-20201208192326383"></p><p>异步置数法:到达 S(i+1) 状态时令 LD’=0 ,状态直接变为 Sj</p><ol><li>M>N</li></ol><p><img src="/2020/09/07/数字电路/image-20201208211819333.png" alt="image-20201208211819333"></p><p><img src="/2020/09/07/数字电路/image-20201208211825145.png" alt="image-20201208211825145"></p><p><img src="/2020/09/07/数字电路/image-20201208212439760.png" alt="image-20201208212439760"></p><p><img src="/2020/09/07/数字电路/image-20201208212442919.png" alt="image-20201208212442919"></p><h5 id="移位寄存器型计数器"><a href="#移位寄存器型计数器" class="headerlink" title="移位寄存器型计数器"></a>移位寄存器型计数器</h5><p>环形计数器</p><p>扭环形计数器</p><h3 id="同步时序逻辑电路的设计方法"><a href="#同步时序逻辑电路的设计方法" class="headerlink" title="同步时序逻辑电路的设计方法"></a>同步时序逻辑电路的设计方法</h3><p><img src="/2020/09/07/数字电路/image-20201208214549378.png" alt="image-20201208214549378"></p><ol><li>逻辑抽象,得出电路的状态转换图或状态转换表</li><li>状态化简</li></ol><p><img src="/2020/09/07/数字电路/image-20201208214717350.png" alt="image-20201208214717350"></p><ol><li>状态分配</li></ol><p><img src="/2020/09/07/数字电路/image-20201208214956731.png" alt="image-20201208214956731"></p><ol><li>选定触发器的类型,求出电路的状态方程、驱动方程和输出方程</li></ol><p><img src="/2020/09/07/数字电路/image-20201208215446146.png" alt="image-20201208215446146"></p><p><img src="/2020/09/07/数字电路/image-20201208215327269.png" alt="image-20201208215327269"></p><p><img src="/2020/09/07/数字电路/image-20201208215405366.png" alt="image-20201208215405366"></p><p><img src="/2020/09/07/数字电路/image-20201208215602590.png" alt="image-20201208215602590"></p><ol><li>根据得到的方程式画出逻辑图</li></ol><p><img src="/2020/09/07/数字电路/image-20201208215639819.png" alt="image-20201208215639819"></p><ol><li>检查设计的电路能否自启动</li></ol><p><img src="/2020/09/07/数字电路/image-20201208215654220.png" alt="image-20201208215654220"></p><h3 id="异步时序逻辑电路的设计方法"><a href="#异步时序逻辑电路的设计方法" class="headerlink" title="异步时序逻辑电路的设计方法"></a>异步时序逻辑电路的设计方法</h3><p><img src="/2020/09/07/数字电路/image-20201208215859239.png" alt="image-20201208215859239"></p><h2 id="第七章-半导体存储器"><a href="#第七章-半导体存储器" class="headerlink" title="第七章 半导体存储器"></a>第七章 半导体存储器</h2><h3 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h3><h4 id="只读存储器"><a href="#只读存储器" class="headerlink" title="只读存储器"></a>只读存储器</h4><p>掩模 ROM</p><p>可编程 PROM</p><p>可擦除的可编程 EPROM</p><h4 id="随机读写存储器"><a href="#随机读写存储器" class="headerlink" title="随机读写存储器"></a>随机读写存储器</h4><p>动态 DRAM</p><p>静态 SRAM</p><p><img src="/2020/09/07/数字电路/image-20201209091933646.png" alt="image-20201209091933646"></p><p><img src="/2020/09/07/数字电路/image-20201209092949508.png" alt="image-20201209092949508"></p>]]></content>
<summary type="html">
<h1 id="数字电路复习笔记"><a href="#数字电路复习笔记" class="headerlink" title="数字电路复习笔记"></a>数字电路复习笔记</h1><p>关于数字电路自己总结的复习笔记,仅供参考,不怎么全</p>
</summary>
</entry>
<entry>
<title>git操作</title>
<link href="http://yoursite.com/2020/01/30/git%E6%93%8D%E4%BD%9C/"/>
<id>http://yoursite.com/2020/01/30/git操作/</id>
<published>2020-01-30T05:08:33.000Z</published>
<updated>2021-05-16T13:08:12.000Z</updated>
<content type="html"><![CDATA[<h2 id="the-first-step"><a href="#the-first-step" class="headerlink" title="the first step"></a>the first step</h2><p>进入用git管理的文件夹中 cd<br>添加用户名 user.name 和用户email user.email:<br>git config —global user.name ‘你的用户名’<br>git config —global user.email ‘你的邮箱’</p><h3 id="创建版本库"><a href="#创建版本库" class="headerlink" title="创建版本库"></a>创建版本库</h3><p>git init</p><h3 id="查看当前文件夹中的所有文件"><a href="#查看当前文件夹中的所有文件" class="headerlink" title="查看当前文件夹中的所有文件"></a>查看当前文件夹中的所有文件</h3><p>ls 要想查看被隐藏的文件,使用 ls -a</p><h3 id="建立一个新的名为-“1-py”-的文件"><a href="#建立一个新的名为-“1-py”-的文件" class="headerlink" title="建立一个新的名为 “1.py” 的文件"></a>建立一个新的名为 “1.py” 的文件</h3><p>touch 1.py</p><h3 id><a href="#" class="headerlink" title=" "></a> </h3>]]></content>
<summary type="html">
<h2 id="the-first-step"><a href="#the-first-step" class="headerlink" title="the first step"></a>the first step</h2><p>进入用git管理的文件夹中 cd<br>添加
</summary>
</entry>
<entry>
<title>Mobilenetv2_第三版</title>
<link href="http://yoursite.com/2020/01/29/Mobilenetv2_%E7%AC%AC%E4%B8%89%E7%89%88/"/>
<id>http://yoursite.com/2020/01/29/Mobilenetv2_第三版/</id>
<published>2020-01-29T11:06:51.000Z</published>
<updated>2021-05-16T13:08:12.000Z</updated>
<content type="html"><![CDATA[<h2 id="Mobilenet-v2-第三版"><a href="#Mobilenet-v2-第三版" class="headerlink" title="Mobilenet v2 第三版"></a>Mobilenet v2 第三版</h2><p>在这一版中,纠正了原来 Model 中的错误……<br><a id="more"></a></p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"><span class="keyword">import</span> torch.utils.data <span class="keyword">as</span> data</span><br><span class="line"><span class="keyword">import</span> torch.nn <span class="keyword">as</span> nn</span><br><span class="line"><span class="keyword">import</span> torch.nn.functional <span class="keyword">as</span> F</span><br><span class="line"><span class="keyword">import</span> torchvision <span class="keyword">as</span> tv</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="keyword">from</span> torchvision <span class="keyword">import</span> transforms, datasets</span><br><span class="line"><span class="keyword">from</span> torchvision.transforms <span class="keyword">import</span> ToPILImage</span><br><span class="line"><span class="keyword">from</span> torch.autograd <span class="keyword">import</span> Variable</span><br><span class="line"><span class="keyword">from</span> torch <span class="keyword">import</span> optim</span><br><span class="line"><span class="keyword">from</span> tensorboardX <span class="keyword">import</span> SummaryWriter</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> datetime</span><br><span class="line"></span><br><span class="line">mnist_mean = <span class="number">0.1307</span></span><br><span class="line">mnist_std = <span class="number">0.3081</span></span><br><span class="line">epoch_n = <span class="number">5</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">class Model(nn.Module):</span><br><span class="line"> def __init__(self):</span><br><span class="line"> <span class="keyword">super</span>(Model, self).__init__()</span><br><span class="line"></span><br><span class="line"> channels = [<span class="number">32</span>, <span class="number">64</span>, <span class="number">144</span>, <span class="number">192</span>, <span class="number">384</span>]</span><br><span class="line"> strides = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">1</span>, <span class="number">1</span>]</span><br><span class="line"> ex_ch = [ch * <span class="number">3</span> <span class="keyword">for</span> ch <span class="keyword">in</span> channels]</span><br><span class="line"></span><br><span class="line"> self.conv1 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(<span class="number">1</span>, channels[<span class="number">0</span>], kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">2</span>, bias=False),</span><br><span class="line"> nn.BatchNorm2d(channels[<span class="number">0</span>]),</span><br><span class="line"> nn.ReLU6()</span><br><span class="line"> )</span><br><span class="line"></span><br><span class="line"> # Bottleneck第一层和第三层都是pointwise卷积,也即kernel_size=1,groups=1的卷积,</span><br><span class="line"> # 第二层是depthwise卷积,也即kernel_size=3,groups=channels的卷积</span><br><span class="line"> self.bottleneck1 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(channels[<span class="number">0</span>], ex_ch[<span class="number">0</span>], kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>, bias=False),</span><br><span class="line"> nn.BatchNorm2d(ex_ch[<span class="number">0</span>]),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(ex_ch[<span class="number">0</span>], ex_ch[<span class="number">0</span>], kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=strides[<span class="number">0</span>], groups=ex_ch[<span class="number">0</span>], bias=False),</span><br><span class="line"> nn.BatchNorm2d(ex_ch[<span class="number">0</span>]),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(ex_ch[<span class="number">0</span>], channels[<span class="number">1</span>], kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>, bias=False),</span><br><span class="line"> nn.BatchNorm2d(channels[<span class="number">1</span>])</span><br><span class="line"> )</span><br><span class="line"> self.bottleneck2 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(channels[<span class="number">1</span>], ex_ch[<span class="number">1</span>], kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>, bias=False),</span><br><span class="line"> nn.BatchNorm2d(ex_ch[<span class="number">1</span>]),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(ex_ch[<span class="number">1</span>], ex_ch[<span class="number">1</span>], kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=strides[<span class="number">1</span>], groups=ex_ch[<span class="number">1</span>], bias=False),</span><br><span class="line"> nn.BatchNorm2d(ex_ch[<span class="number">1</span>]),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(ex_ch[<span class="number">1</span>], channels[<span class="number">2</span>], kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>, bias=False),</span><br><span class="line"> nn.BatchNorm2d(channels[<span class="number">2</span>])</span><br><span class="line"> )</span><br><span class="line"> self.bottleneck3 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(channels[<span class="number">2</span>], ex_ch[<span class="number">2</span>], kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>, bias=False),</span><br><span class="line"> nn.BatchNorm2d(ex_ch[<span class="number">2</span>]),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(ex_ch[<span class="number">2</span>], ex_ch[<span class="number">2</span>], kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=strides[<span class="number">2</span>], groups=ex_ch[<span class="number">2</span>], bias=False),</span><br><span class="line"> nn.BatchNorm2d(ex_ch[<span class="number">2</span>]),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(ex_ch[<span class="number">2</span>], channels[<span class="number">3</span>], kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>, bias=False),</span><br><span class="line"> nn.BatchNorm2d(channels[<span class="number">3</span>])</span><br><span class="line"> )</span><br><span class="line"> self.bottleneck4 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(channels[<span class="number">3</span>], ex_ch[<span class="number">3</span>], kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>, bias=False),</span><br><span class="line"> nn.BatchNorm2d(ex_ch[<span class="number">3</span>]),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(ex_ch[<span class="number">3</span>], ex_ch[<span class="number">3</span>], kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=strides[<span class="number">3</span>], groups=ex_ch[<span class="number">3</span>], bias=False),</span><br><span class="line"> nn.BatchNorm2d(ex_ch[<span class="number">3</span>]),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(ex_ch[<span class="number">3</span>], channels[<span class="number">4</span>], kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>, bias=False),</span><br><span class="line"> nn.BatchNorm2d(channels[<span class="number">4</span>])</span><br><span class="line"> )</span><br><span class="line"></span><br><span class="line"> self.last_ch = <span class="number">512</span></span><br><span class="line"> self.conv2 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(channels[<span class="number">4</span>], self.last_ch, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>, bias=False),</span><br><span class="line"> nn.BatchNorm2d(self.last_ch),</span><br><span class="line"> nn.ReLU6()</span><br><span class="line"> )</span><br><span class="line"> self.pool1 = nn.AvgPool2d(kernel_size=<span class="number">7</span>)</span><br><span class="line"> self.Dense = nn.Linear(self.last_ch, <span class="number">10</span>)</span><br><span class="line"></span><br><span class="line"> def forward(self, x):</span><br><span class="line"> out = self.conv1(x)</span><br><span class="line"> out = self.bottleneck1(out)</span><br><span class="line"> out = self.bottleneck2(out)</span><br><span class="line"> out = self.bottleneck3(out)</span><br><span class="line"> out = self.bottleneck4(out)</span><br><span class="line"> out = self.conv2(out)</span><br><span class="line"> out = self.pool1(out)</span><br><span class="line"> out = out.view(<span class="number">-1</span>, self.last_ch)</span><br><span class="line"> out = self.Dense(out)</span><br><span class="line"> <span class="keyword">return</span> out</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def get_trainloader(batch_size):</span><br><span class="line"> dataset = datasets.MNIST(root=<span class="string">"./mmnist/"</span>, train=True, download=True,</span><br><span class="line"> transform=transforms.Compose([</span><br><span class="line"> transforms.ToTensor(),</span><br><span class="line"> transforms.Normalize(</span><br><span class="line"> (mnist_mean,), (mnist_std,)</span><br><span class="line"> )</span><br><span class="line"> ]))</span><br><span class="line"> <span class="keyword">return</span> data.DataLoader(</span><br><span class="line"> dataset=dataset,</span><br><span class="line"> batch_size=batch_size,</span><br><span class="line"> shuffle=True,</span><br><span class="line"> num_workers=<span class="number">2</span>,</span><br><span class="line"> pin_memory=True,</span><br><span class="line"> drop_last=False,</span><br><span class="line"> )</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def get_testloader(batch_size):</span><br><span class="line"> dataset = datasets.MNIST(root=<span class="string">"./mmnist/"</span>, train=False, download=True,</span><br><span class="line"> transform=transforms.Compose([</span><br><span class="line"> transforms.ToTensor(),</span><br><span class="line"> transforms.Normalize(</span><br><span class="line"> (mnist_mean,), (mnist_std,)</span><br><span class="line"> )</span><br><span class="line"> ]))</span><br><span class="line"> <span class="keyword">return</span> data.DataLoader(</span><br><span class="line"> dataset=dataset,</span><br><span class="line"> batch_size=batch_size,</span><br><span class="line"> shuffle=False, # 每个epoch是否混淆</span><br><span class="line"> num_workers=2, # 多进程并发装载</span><br><span class="line"> pin_memory=True, # 是否使用锁页内存</span><br><span class="line"> drop_last=False, # 是否丢弃最后一个不完整的batch</span><br><span class="line"> )</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def train(train_data_loader, optimizer):</span><br><span class="line"> epoch_acc = <span class="number">0.0</span></span><br><span class="line"> epoch_loss = <span class="number">0.0</span></span><br><span class="line"> train_dataset_length = <span class="number">0.0</span></span><br><span class="line"> tot_it = len(train_data_loader)</span><br><span class="line"> <span class="keyword">for</span> it, (x_train, y_train) <span class="keyword">in</span> enumerate(train_data_loader):</span><br><span class="line"> train_dataset_length += len(y_train)</span><br><span class="line"> y_pred = model(x_train)</span><br><span class="line"> optimizer.zero_grad()</span><br><span class="line"> loss = nn.functional.cross_entropy(y_pred, y_train)</span><br><span class="line"> loss.backward()</span><br><span class="line"> optimizer.step()</span><br><span class="line"> epoch_loss += loss.item()</span><br><span class="line"> y_pred = torch.argmax(y_pred, dim=<span class="number">1</span>)</span><br><span class="line"> epoch_acc += y_pred.eq(y_train).sum().item()</span><br><span class="line"> print(it)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> it % <span class="number">32</span> == <span class="number">0</span>:</span><br><span class="line"> print(f<span class="string">'it:{it}/{tot_it}, '</span></span><br><span class="line"> f<span class="string">'Loss:{epoch_loss}/{it+1} = {epoch_loss/(it+1)}, '</span></span><br><span class="line"> f<span class="string">'Acc:{epoch_acc}/{train_dataset_length} = {epoch_acc/train_dataset_length}'</span>)</span><br><span class="line"></span><br><span class="line"> print(<span class="string">"train_Epoch:Loss is:{:4f},Acc is:{:4f}"</span>.format(epoch_loss/tot_it, epoch_acc/train_dataset_length))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def validation(test_data_loader):</span><br><span class="line"> <span class="keyword">with</span> torch.no_grad():</span><br><span class="line"> model.eval()</span><br><span class="line"> epoch_acc = <span class="number">0.0</span></span><br><span class="line"> epoch_loss = <span class="number">0.0</span></span><br><span class="line"> test_dataset_length = <span class="number">0.0</span></span><br><span class="line"> tot_it = len(test_data_loader)</span><br><span class="line"> <span class="keyword">for</span> it, (x_test, y_test) <span class="keyword">in</span> enumerate(test_data_loader):</span><br><span class="line"> test_dataset_length += len(y_test)</span><br><span class="line"> y_pred = model(x_test)</span><br><span class="line"> loss = nn.functional.cross_entropy(y_pred, y_test)</span><br><span class="line"> epoch_loss += loss.item()</span><br><span class="line"> y_pred = torch.argmax(y_pred, dim=<span class="number">1</span>)</span><br><span class="line"> epoch_acc += y_pred.eq(y_test).sum().item()</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> it % <span class="number">32</span> == <span class="number">0</span>:</span><br><span class="line"> print(f<span class="string">'it:{it}/{tot_it}, '</span></span><br><span class="line"> f<span class="string">'Loss:{epoch_loss}/{it+1} = {epoch_loss / (it+1)}, '</span></span><br><span class="line"> f<span class="string">'Acc:{epoch_acc}/{test_dataset_length} = {epoch_acc / test_dataset_length}'</span>)</span><br><span class="line"></span><br><span class="line"> model.train()</span><br><span class="line"> print(<span class="string">"test_Epoch:Loss is:{:4f},Acc is:{:4f}"</span>.format(epoch_loss/tot_it, epoch_acc/test_dataset_length))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">model = Model()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line"> PATH = <span class="string">'./Mobilenetv2.pth'</span></span><br><span class="line"> # pretrained_net = torch.load(PATH)</span><br><span class="line"> # model.load_state_dict(pretrained_net)</span><br><span class="line"> optimizer = torch.optim.Adam(model.parameters(), lr=<span class="number">0.001</span>)</span><br><span class="line"> train_data_loader = get_trainloader(<span class="number">64</span>)</span><br><span class="line"> test_data_loader = get_testloader(<span class="number">64</span>)</span><br><span class="line"> <span class="keyword">for</span> epoch <span class="keyword">in</span> range(epoch_n):</span><br><span class="line"> train(train_data_loader=train_data_loader, optimizer=optimizer)</span><br><span class="line"> validation(test_data_loader=test_data_loader)</span><br><span class="line"> torch.save(model.state_dict(), PATH)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> main()</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="Mobilenet-v2-第三版"><a href="#Mobilenet-v2-第三版" class="headerlink" title="Mobilenet v2 第三版"></a>Mobilenet v2 第三版</h2><p>在这一版中,纠正了原来 Model 中的错误……<br></p>
</summary>
<category term="机器学习" scheme="http://yoursite.com/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>Mobilenetv2_第二版</title>
<link href="http://yoursite.com/2020/01/29/Mobilenetv2_%E7%AC%AC%E4%BA%8C%E7%89%88/"/>
<id>http://yoursite.com/2020/01/29/Mobilenetv2_第二版/</id>
<published>2020-01-29T03:26:23.000Z</published>
<updated>2021-05-16T13:08:12.000Z</updated>
<content type="html"><![CDATA[<h2 id="Mobilenet-v2-第二版"><a href="#Mobilenet-v2-第二版" class="headerlink" title="Mobilenet v2 第二版"></a>Mobilenet v2 第二版</h2><p>在这一版中,优化了数据加载类,将创建训练数据加载类,测试数据加载类,训练和测试分别写成了一个函数,有利于管理和修改,最后写main函数可以使模型多进程并发装载,加快训练速度<br><a id="more"></a></p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"><span class="keyword">import</span> torch.utils.data <span class="keyword">as</span> data</span><br><span class="line"><span class="keyword">import</span> torch.nn <span class="keyword">as</span> nn</span><br><span class="line"><span class="keyword">import</span> torch.nn.functional <span class="keyword">as</span> F</span><br><span class="line"><span class="keyword">import</span> torchvision <span class="keyword">as</span> tv</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="keyword">from</span> torchvision <span class="keyword">import</span> transforms, datasets</span><br><span class="line"><span class="keyword">from</span> torchvision.transforms <span class="keyword">import</span> ToPILImage</span><br><span class="line"><span class="keyword">from</span> torch.autograd <span class="keyword">import</span> Variable</span><br><span class="line"><span class="keyword">from</span> torch <span class="keyword">import</span> optim</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> datetime</span><br><span class="line"></span><br><span class="line">mnist_mean = <span class="number">0.1307</span></span><br><span class="line">mnist_std = <span class="number">0.3081</span></span><br><span class="line">epoch_n = <span class="number">5</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">class Model(nn.Module):</span><br><span class="line"> def __init__(self):</span><br><span class="line"> <span class="keyword">super</span>(Model, self).__init__()</span><br><span class="line"> self.conv1 = nn.Conv2d(<span class="number">1</span>, <span class="number">32</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">2</span>)</span><br><span class="line"> self.bottleneck1 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(<span class="number">32</span>, <span class="number">32</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">32</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(<span class="number">32</span>, <span class="number">32</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>, groups=<span class="number">32</span>),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">32</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(<span class="number">32</span>, <span class="number">16</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> )</span><br><span class="line"> self.bottleneck2 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(<span class="number">16</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">2</span>),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>, groups=<span class="number">32</span>),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> )</span><br><span class="line"> self.bottleneck3 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>, groups=<span class="number">32</span>),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> )</span><br><span class="line"> self.bottleneck4 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>, groups=<span class="number">32</span>),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> )</span><br><span class="line"> self.bottleneck5 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>, groups=<span class="number">32</span>),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> )</span><br><span class="line"> self.bottleneck6 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">384</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">384</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(<span class="number">384</span>, <span class="number">384</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>, groups=<span class="number">32</span>),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">384</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.Conv2d(<span class="number">384</span>, <span class="number">128</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> )</span><br><span class="line"> self.conv2 = nn.Conv2d(<span class="number">128</span>, <span class="number">512</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> self.pool1 = nn.AvgPool2d(kernel_size=<span class="number">7</span>)</span><br><span class="line"> self.conv3 = nn.Conv2d(<span class="number">512</span>, <span class="number">512</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> self.Dense = nn.Linear(<span class="number">512</span>, <span class="number">10</span>)</span><br><span class="line"></span><br><span class="line"> def forward(self, x):</span><br><span class="line"> out = self.conv1(x)</span><br><span class="line"> out = self.bottleneck1(out)</span><br><span class="line"> out = self.bottleneck2(out)</span><br><span class="line"> out = self.bottleneck3(out)</span><br><span class="line"> out = self.bottleneck4(out)</span><br><span class="line"> out = self.bottleneck5(out)</span><br><span class="line"> out = self.bottleneck6(out)</span><br><span class="line"> out = self.conv2(out)</span><br><span class="line"> out = self.pool1(out)</span><br><span class="line"> out = self.conv3(out)</span><br><span class="line"> out = out.view(<span class="number">-1</span>, <span class="number">512</span>)</span><br><span class="line"> out = self.Dense(out)</span><br><span class="line"> <span class="keyword">return</span> out</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def get_trainloader(batch_size):</span><br><span class="line"> dataset = datasets.MNIST(root=<span class="string">"./mmnist/"</span>, train=True, download=True,</span><br><span class="line"> transform=transforms.Compose([</span><br><span class="line"> transforms.ToTensor(),</span><br><span class="line"> transforms.Normalize(</span><br><span class="line"> (mnist_mean,), (mnist_std,)</span><br><span class="line"> )</span><br><span class="line"> ]))</span><br><span class="line"> <span class="keyword">return</span> data.DataLoader(</span><br><span class="line"> dataset=dataset,</span><br><span class="line"> batch_size=batch_size,</span><br><span class="line"> shuffle=True,</span><br><span class="line"> num_workers=<span class="number">2</span>,</span><br><span class="line"> pin_memory=True,</span><br><span class="line"> drop_last=False,</span><br><span class="line"> )</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def get_testloader(batch_size):</span><br><span class="line"> dataset = datasets.MNIST(root=<span class="string">"./mmnist/"</span>, train=False, download=True,</span><br><span class="line"> transform=transforms.Compose([</span><br><span class="line"> transforms.ToTensor(),</span><br><span class="line"> transforms.Normalize(</span><br><span class="line"> (mnist_mean,), (mnist_std,)</span><br><span class="line"> )</span><br><span class="line"> ]))</span><br><span class="line"> <span class="keyword">return</span> data.DataLoader(</span><br><span class="line"> dataset=dataset,</span><br><span class="line"> batch_size=batch_size,</span><br><span class="line"> shuffle=False, # 每个epoch是否混淆</span><br><span class="line"> num_workers=2, # 多进程并发装载</span><br><span class="line"> pin_memory=True, # 是否使用锁页内存</span><br><span class="line"> drop_last=False, # 是否丢弃最后一个不完整的batch</span><br><span class="line"> ), len(dataset)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def train(train_data_loader, optimizer):</span><br><span class="line"> <span class="keyword">for</span> batch <span class="keyword">in</span> train_data_loader:</span><br><span class="line"> x_train, y_train = batch</span><br><span class="line"> y_pred = model(x_train)</span><br><span class="line"> optimizer.zero_grad()</span><br><span class="line"> loss = nn.functional.cross_entropy(y_pred, y_train)</span><br><span class="line"> loss.backward()</span><br><span class="line"> optimizer.step()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def validation(test_data_loader, test_dataset_length):</span><br><span class="line"> <span class="keyword">with</span> torch.no_grad():</span><br><span class="line"> model.eval()</span><br><span class="line"> epoch_acc = <span class="number">0.0</span></span><br><span class="line"> epoch_loss = <span class="number">0.0</span></span><br><span class="line"> <span class="keyword">for</span> batch <span class="keyword">in</span> test_data_loader:</span><br><span class="line"> x_test, y_test = batch</span><br><span class="line"> y_pred = model(x_test)</span><br><span class="line"> loss = nn.functional.cross_entropy(y_pred, y_test)</span><br><span class="line"> epoch_loss += loss.item()</span><br><span class="line"> y_pred = torch.argmax(y_pred, dim=<span class="number">1</span>)</span><br><span class="line"> epoch_acc += y_pred.eq(y_test).sum().item()</span><br><span class="line"> epoch_loss = epoch_loss * <span class="number">64</span> / test_dataset_length</span><br><span class="line"> epoch_acc = epoch_acc / test_dataset_length</span><br><span class="line"> print(<span class="string">"Epoch:Loss is:{:4f},Acc is:{:4f}"</span>.format(epoch_loss, epoch_acc))</span><br><span class="line"> model.train()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">model = Model()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line"> optimizer = torch.optim.Adam(model.parameters(), lr=<span class="number">0.001</span>)</span><br><span class="line"> train_data_loader = get_trainloader(<span class="number">64</span>)</span><br><span class="line"> test_data_loader, dataset_length = get_testloader(<span class="number">64</span>)</span><br><span class="line"> <span class="keyword">for</span> epoch <span class="keyword">in</span> range(epoch_n):</span><br><span class="line"> train(train_data_loader=train_data_loader, optimizer=optimizer)</span><br><span class="line"> validation(test_data_loader=test_data_loader, test_dataset_length=dataset_length)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> main()</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="Mobilenet-v2-第二版"><a href="#Mobilenet-v2-第二版" class="headerlink" title="Mobilenet v2 第二版"></a>Mobilenet v2 第二版</h2><p>在这一版中,优化了数据加载类,将创建训练数据加载类,测试数据加载类,训练和测试分别写成了一个函数,有利于管理和修改,最后写main函数可以使模型多进程并发装载,加快训练速度<br></p>
</summary>
<category term="机器学习" scheme="http://yoursite.com/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>torch操作总结</title>
<link href="http://yoursite.com/2020/01/23/torch%E6%93%8D%E4%BD%9C%E6%80%BB%E7%BB%93/"/>
<id>http://yoursite.com/2020/01/23/torch操作总结/</id>
<published>2020-01-23T06:18:50.000Z</published>
<updated>2021-05-16T13:08:12.000Z</updated>
<content type="html"><![CDATA[<h3 id="在学习过程中记录一些需要用到的关于-torch(可能还有其他库)-的操作"><a href="#在学习过程中记录一些需要用到的关于-torch(可能还有其他库)-的操作" class="headerlink" title="在学习过程中记录一些需要用到的关于 torch(可能还有其他库) 的操作"></a>在学习过程中记录一些需要用到的关于 torch(可能还有其他库) 的操作</h3><p>在这里慢慢积累一下各种操作,希望大家能在这篇里有所收获</p><a id="more"></a><h4 id="torch-argmax-求数组中某个维度的最大值的下标"><a href="#torch-argmax-求数组中某个维度的最大值的下标" class="headerlink" title="torch.argmax 求数组中某个维度的最大值的下标"></a>torch.argmax 求数组中某个维度的最大值的下标</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">x = torch.randn(<span class="number">5</span>, <span class="number">2</span>)</span><br><span class="line">print(x)</span><br><span class="line">y = torch.argmax(x, dim=1) # dim的值为几就代表求第几维的最大值(从0开始)</span><br><span class="line">print(y)</span><br><span class="line"></span><br><span class="line">output:</span><br><span class="line"></span><br><span class="line">tensor([[<span class="number">-0.5390</span>, <span class="number">-0.3401</span>],</span><br><span class="line"> [<span class="number">-1.9364</span>, <span class="number">0.1501</span>],</span><br><span class="line"> [ <span class="number">1.6209</span>, <span class="number">0.3534</span>],</span><br><span class="line"> [ <span class="number">1.2624</span>, <span class="number">2.0758</span>],</span><br><span class="line"> [ <span class="number">1.6152</span>, <span class="number">0.6949</span>]])</span><br><span class="line">tensor([<span class="number">1</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>])</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="存取模型"><a href="#存取模型" class="headerlink" title="存取模型"></a>存取模型</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">仅保存和加载模型参数(推荐使用)</span><br><span class="line"></span><br><span class="line">model = Model()</span><br><span class="line">PATH = <span class="string">'./Mobilenetv2.pth'</span></span><br><span class="line">torch.save(model.state_dict(), PATH)</span><br><span class="line"></span><br><span class="line">PATH = <span class="string">'./Mobilenetv2.pth'</span></span><br><span class="line">pretrained_net = torch.load(PATH)</span><br><span class="line">model.load_state_dict(pretrained_net)</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h3 id="在学习过程中记录一些需要用到的关于-torch(可能还有其他库)-的操作"><a href="#在学习过程中记录一些需要用到的关于-torch(可能还有其他库)-的操作" class="headerlink" title="在学习过程中记录一些需要用到的关于 torch(可能还有其他库) 的操作"></a>在学习过程中记录一些需要用到的关于 torch(可能还有其他库) 的操作</h3><p>在这里慢慢积累一下各种操作,希望大家能在这篇里有所收获</p>
</summary>
<category term="机器学习" scheme="http://yoursite.com/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>Mobilenetv2_第一版</title>
<link href="http://yoursite.com/2020/01/20/Mobilenetv2_%E7%AC%AC%E4%B8%80%E7%89%88/"/>
<id>http://yoursite.com/2020/01/20/Mobilenetv2_第一版/</id>
<published>2020-01-20T06:09:50.000Z</published>
<updated>2021-05-16T13:08:12.000Z</updated>
<content type="html"><![CDATA[<h2 id="Mobilenetv2-第一版"><a href="#Mobilenetv2-第一版" class="headerlink" title="Mobilenetv2_第一版"></a>Mobilenetv2_第一版</h2><p>第一版只是简单的实现了 Mobilenetv2 的结构,代码有些冗余,而且有许多需要改进的地方</p><a id="more"></a><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"><span class="keyword">import</span> torch.utils.data <span class="keyword">as</span> data</span><br><span class="line"><span class="keyword">import</span> torch.nn <span class="keyword">as</span> nn</span><br><span class="line"><span class="keyword">import</span> torch.nn.functional <span class="keyword">as</span> F</span><br><span class="line"><span class="keyword">import</span> torchvision <span class="keyword">as</span> tv</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="keyword">from</span> torchvision <span class="keyword">import</span> transforms, datasets</span><br><span class="line"><span class="keyword">from</span> torchvision.transforms <span class="keyword">import</span> ToPILImage</span><br><span class="line"><span class="keyword">from</span> torch.autograd <span class="keyword">import</span> Variable</span><br><span class="line"><span class="keyword">from</span> torch <span class="keyword">import</span> optim</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> datetime</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">class Model(nn.Module):</span><br><span class="line"> def __init__(self):</span><br><span class="line"> <span class="keyword">super</span>(Model, self).__init__()</span><br><span class="line"> self.conv1 = nn.Conv2d(<span class="number">1</span>, <span class="number">32</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">2</span>)</span><br><span class="line"> self.bottleneck1 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(<span class="number">32</span>, <span class="number">32</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">32</span>),</span><br><span class="line"> nn.Conv2d(<span class="number">32</span>, <span class="number">32</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>, groups=<span class="number">32</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">32</span>),</span><br><span class="line"> nn.Conv2d(<span class="number">32</span>, <span class="number">16</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> )</span><br><span class="line"> self.bottleneck2 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(<span class="number">16</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">2</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>, groups=<span class="number">32</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> )</span><br><span class="line"> self.bottleneck3 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>, groups=<span class="number">32</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> )</span><br><span class="line"> self.bottleneck4 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>, groups=<span class="number">32</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> )</span><br><span class="line"> self.bottleneck5 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>, groups=<span class="number">32</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">64</span>),</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">64</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> )</span><br><span class="line"> self.bottleneck6 = nn.Sequential(</span><br><span class="line"> nn.Conv2d(<span class="number">64</span>, <span class="number">384</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">384</span>),</span><br><span class="line"> nn.Conv2d(<span class="number">384</span>, <span class="number">384</span>, kernel_size=<span class="number">3</span>, padding=<span class="number">1</span>, stride=<span class="number">1</span>, groups=<span class="number">32</span>),</span><br><span class="line"> nn.ReLU6(),</span><br><span class="line"> nn.BatchNorm2d(<span class="number">384</span>),</span><br><span class="line"> nn.Conv2d(<span class="number">384</span>, <span class="number">128</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> )</span><br><span class="line"> self.conv2 = nn.Conv2d(<span class="number">128</span>, <span class="number">512</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> self.pool1 = nn.AvgPool2d(kernel_size=<span class="number">7</span>)</span><br><span class="line"> self.conv3 = nn.Conv2d(<span class="number">512</span>, <span class="number">512</span>, kernel_size=<span class="number">1</span>, padding=<span class="number">0</span>, stride=<span class="number">1</span>)</span><br><span class="line"> self.Dense = nn.Linear(<span class="number">512</span>, <span class="number">10</span>)</span><br><span class="line"></span><br><span class="line"> def forward(self, x):</span><br><span class="line"> out = self.conv1(x)</span><br><span class="line"> out = self.bottleneck1(out)</span><br><span class="line"> out = self.bottleneck2(out)</span><br><span class="line"> out = self.bottleneck3(out)</span><br><span class="line"> out = self.bottleneck4(out)</span><br><span class="line"> out = self.bottleneck5(out)</span><br><span class="line"> out = self.bottleneck6(out)</span><br><span class="line"> out = self.conv2(out)</span><br><span class="line"> out = self.pool1(out)</span><br><span class="line"> out = self.conv3(out)</span><br><span class="line"> out = out.view(<span class="number">-1</span>, <span class="number">512</span>)</span><br><span class="line"> print(out.size())</span><br><span class="line"> out = self.Dense(out)</span><br><span class="line"> <span class="keyword">return</span> out</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">transform = transforms.ToTensor()</span><br><span class="line">train_dataset = datasets.MNIST(root=<span class="string">"./mmnist/"</span>, train=True, transform=transform, download=True)</span><br><span class="line">test_dataset = datasets.MNIST(root=<span class="string">"./mmnist/"</span>, train=False, transform=transform, download=True)</span><br><span class="line">train_data_loader = data.DataLoader(dataset=train_dataset, batch_size=<span class="number">64</span>, shuffle=True)</span><br><span class="line">test_data_loader = data.DataLoader(dataset=test_dataset, batch_size=<span class="number">64</span>, shuffle=True)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">epoch_n = <span class="number">5</span></span><br><span class="line">model = Model()</span><br><span class="line">optimizer = torch.optim.Adam(model.parameters(), lr=<span class="number">0.001</span>)</span><br><span class="line"><span class="keyword">for</span> epoch <span class="keyword">in</span> range(epoch_n):</span><br><span class="line"> epoch_loss = <span class="number">0.0</span></span><br><span class="line"> epoch_acc = <span class="number">0.0</span></span><br><span class="line"> <span class="keyword">for</span> batch <span class="keyword">in</span> train_data_loader:</span><br><span class="line"> x_train, y_train = batch</span><br><span class="line"> y_pred = model(x_train)</span><br><span class="line"> optimizer.zero_grad()</span><br><span class="line"> loss = nn.functional.cross_entropy(y_pred, y_train)</span><br><span class="line"> loss.backward()</span><br><span class="line"> optimizer.step()</span><br><span class="line"></span><br><span class="line"> <span class="keyword">with</span> torch.no_grad():</span><br><span class="line"> model.eval()</span><br><span class="line"> <span class="keyword">for</span> batch <span class="keyword">in</span> test_data_loader:</span><br><span class="line"> x_test, y_test = batch</span><br><span class="line"> y_pred = model(x_test)</span><br><span class="line"> loss = nn.functional.cross_entropy(y_pred, y_test)</span><br><span class="line"> epoch_loss += loss.item()</span><br><span class="line"> i = <span class="number">-1</span></span><br><span class="line"> <span class="keyword">for</span> num <span class="keyword">in</span> y_pred:</span><br><span class="line"> i += <span class="number">1</span></span><br><span class="line"> index = <span class="number">-1</span></span><br><span class="line"> max_num = torch.max(num)</span><br><span class="line"> <span class="keyword">for</span> nnum <span class="keyword">in</span> num:</span><br><span class="line"> index += <span class="number">1</span></span><br><span class="line"> <span class="keyword">if</span> nnum == max_num:</span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"> max_num = index</span><br><span class="line"> <span class="keyword">if</span> max_num == y_test[i]:</span><br><span class="line"> epoch_acc += <span class="number">1</span></span><br><span class="line"> epoch_loss = epoch_loss * <span class="number">64</span> / len(test_dataset)</span><br><span class="line"> epoch_acc = epoch_acc / len(test_dataset)</span><br><span class="line"> print(<span class="string">"Epoch{}:Loss is:{:4f},Acc is:{:4f}"</span>.format(epoch, epoch_loss, epoch_acc))</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="tky看完后说:"><a href="#tky看完后说:" class="headerlink" title="tky看完后说:"></a>tky看完后说:</h2><p>1.写个validate函数吧,用test_dataloader测,记得开with torch.no_grad(): 和model.eval(),val集上的acc只比train集低一点就差不多成功了<br>2.用matplotlib把训练过程每个batch的acc和loss画出来<br>3.试一下把adam换成带momentum、带nestrov的sgd,并且调一个合适的学习率(lr)<br>4.可以用cosannealing这个scheduler套住optimizer<br>5.试一下把CEloss加上label smooth<br>6.再练一下torch保存和加载模型:torch.save和torch.load 一般格式是torch.save(model.state_dict(), ‘ckpt.pth.tar’)<br>好像是model.load .pth.tar是常用后缀名 model.state_dict()返回一个字典,表示模型里面的各种东西,包括网络结构和参数张量</p><p>PS:<br>scheduler是学习率的调整器,是套在optimizer外面的一层壳,可以随着训练过程调整lr<br>常用的sche有cos的、指数decay的、多段式decay的<br>比如batchsize64,假设trainset有50000张照片,并且定义dataloader的时候drop_last参数是False,那么每个epoch有 上取整(50000 // 64) 即782个batch,比如你训10个epoch,那么总的batch数是7820<br>所以在定义scheduler的时候传参最大迭代次数就是7820,然后每得到一个batch的时候就让scheduler.step(),这样刚好可以step()7820次,每次step函数都会让学习率变化一点点</p><p>tky orz</p><p>参考:<a href="https://zhuanlan.zhihu.com/p/33720450" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/33720450</a></p>]]></content>
<summary type="html">
<h2 id="Mobilenetv2-第一版"><a href="#Mobilenetv2-第一版" class="headerlink" title="Mobilenetv2_第一版"></a>Mobilenetv2_第一版</h2><p>第一版只是简单的实现了 Mobilenetv2 的结构,代码有些冗余,而且有许多需要改进的地方</p>
</summary>
<category term="机器学习" scheme="http://yoursite.com/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>第一次上机E题题解</title>
<link href="http://yoursite.com/2019/10/11/%E7%AC%AC%E4%B8%80%E6%AC%A1%E4%B8%8A%E6%9C%BAE%E9%A2%98%E9%A2%98%E8%A7%A3/"/>
<id>http://yoursite.com/2019/10/11/第一次上机E题题解/</id>
<published>2019-10-11T04:01:24.000Z</published>
<updated>2021-05-16T13:08:24.000Z</updated>
<content type="html"><![CDATA[<h2 id="题目:点灯"><a href="#题目:点灯" class="headerlink" title="题目:点灯"></a>题目:点灯</h2><h3 id="题目描述"><a href="#题目描述" class="headerlink" title="题目描述"></a>题目描述</h3><hr><p>有n个灯,编号0∼n−1,一开始都是关闭状态。</p><p>每次操作会拨动一个区间[L,R]灯的开关,也就是说,对于灯i,L≤i≤R,如果i是关闭状态,则操作会使灯亮,反之会使灯灭。</p><p>请问k次操作后有多少灯亮着。</p><a id="more"></a><h3 id="输入"><a href="#输入" class="headerlink" title="输入"></a>输入</h3><hr><p>多组输入数据</p><p>每组数据第一行两个数n,k(1≤n≤109,1≤k≤105)</p><p>接下来k行,每行两个数l,r(0≤l≤r≤n−1)</p><h3 id="输出"><a href="#输出" class="headerlink" title="输出"></a>输出</h3><hr><p>每组数据一行一个数,表示最后灯亮的个数</p><h3 id="输入样例"><a href="#输入样例" class="headerlink" title="输入样例"></a>输入样例</h3><hr><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">10</span> <span class="number">1</span></span><br><span class="line"><span class="number">2</span> <span class="number">6</span></span><br></pre></td></tr></table></figure><h3 id="输出样例"><a href="#输出样例" class="headerlink" title="输出样例"></a>输出样例</h3><hr><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">5</span></span><br></pre></td></tr></table></figure><h3 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h3><hr><p>对于每一个灯,如果它位于一个 [L,R] 区间内,说明开关被按动一次,设这个灯位于 k 个 [L,R] 的区间之内,那么 k 是奇数代表开关被按了奇数次,此时灯是亮的,若 k 是偶数,则灯是灭的。那么问题的关键就是如何求出每个灯的 k 。</p><p>因此,读入了 k 个 L 和 k 个 R 之后,我们将这 2*k 个数( k 个 L 和 k 个 R+1 )放在一起,并标记每个数是 L 还是 R+1(二维数组和结构数组均可,我使用的是二维数组),由小到大排序,然后定义一个变量 turn = 0(turn 就相当于之前的 k) ,之后对排序后的数组从前向后循环,如果遇到 L ,则 turn += 1 ,说明进入到了一个开关范围内,如果遇到 R+1 ,则 turn -= 1 ,说明离开了一个开关的范围,turn 每次改变后进行判断,若改变后 turn 为奇数,则改变前为偶数,说明从现在这个 L 或 R+1 的位置到上一个 L 或 R+1 的位置中的所有灯的 turn 都是偶数,即灯是灭的,若改变后 turn 为偶数 ,说明从现在的位置到上一个位置的灯都是亮的,那么 ans += 两个位置的差,循环结束即可得到正确结果。</p><h3 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> Author: 王振</span></span><br><span class="line"><span class="comment"> Result: ACSubmission_id: 1860544</span></span><br><span class="line"><span class="comment"> Created at: Thu Oct 10 2019 17:08:32 GMT+0800 (CST)</span></span><br><span class="line"><span class="comment"> Problem_id: 2489Time: 824Memory: 7180</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"> </span><br><span class="line">#include <algorithm></span><br><span class="line">#include <cmath></span><br><span class="line">#include <cstdlib></span><br><span class="line">#include <cstring></span><br><span class="line">#include <iostream></span><br><span class="line">#include <queue></span><br><span class="line">#include <vector></span><br><span class="line">using namespace std;</span><br><span class="line">int l[<span class="number">100005</span>];</span><br><span class="line">int r[<span class="number">100005</span>];</span><br><span class="line">int t[<span class="number">200005</span>][<span class="number">2</span>];</span><br><span class="line">int turn;</span><br><span class="line">int cmp(<span class="keyword">const</span> <span class="keyword">void</span> *a, <span class="keyword">const</span> <span class="keyword">void</span> *b) { <span class="keyword">return</span> *(int *)a - *(int *)b; }</span><br><span class="line">int main()</span><br><span class="line">{</span><br><span class="line"> int n, k;</span><br><span class="line"> <span class="keyword">while</span> (cin >> n >> k)</span><br><span class="line"> {</span><br><span class="line"> int i;</span><br><span class="line"> int p = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (i = <span class="number">1</span>; i <= k; i++)</span><br><span class="line"> {</span><br><span class="line"> scanf(<span class="string">"%d%d"</span>, &l[i], &r[i]);</span><br><span class="line"> t[++p][<span class="number">0</span>] = l[i];</span><br><span class="line"> t[p][<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line"> t[++p][<span class="number">0</span>] = r[i] + <span class="number">1</span>;</span><br><span class="line"> t[p][<span class="number">1</span>] = <span class="number">2</span>;</span><br><span class="line"> }</span><br><span class="line"> qsort(t + <span class="number">1</span>, k * <span class="number">2</span>, <span class="number">8</span>, cmp);</span><br><span class="line"> int ans = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (i = <span class="number">1</span>; i <= k * <span class="number">2</span>; i++)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (t[i][<span class="number">1</span>] == <span class="number">1</span>)</span><br><span class="line"> {</span><br><span class="line"> turn++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> turn--;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (turn % <span class="number">2</span> == <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> ans += t[i][<span class="number">0</span>] - t[i - <span class="number">1</span>][<span class="number">0</span>];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> cout << ans << endl;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="题目:点灯"><a href="#题目:点灯" class="headerlink" title="题目:点灯"></a>题目:点灯</h2><h3 id="题目描述"><a href="#题目描述" class="headerlink" title="题目描述"></a>题目描述</h3><hr>
<p>有n个灯,编号0∼n−1,一开始都是关闭状态。</p>
<p>每次操作会拨动一个区间[L,R]灯的开关,也就是说,对于灯i,L≤i≤R,如果i是关闭状态,则操作会使灯亮,反之会使灯灭。</p>
<p>请问k次操作后有多少灯亮着。</p>
</summary>
<category term="题解" scheme="http://yoursite.com/tags/%E9%A2%98%E8%A7%A3/"/>
</entry>
<entry>
<title>STL容器的总结</title>
<link href="http://yoursite.com/2019/09/29/STL%E5%AE%B9%E5%99%A8%E7%9A%84%E6%80%BB%E7%BB%93/"/>
<id>http://yoursite.com/2019/09/29/STL容器的总结/</id>
<published>2019-09-29T06:58:49.000Z</published>
<updated>2021-05-16T13:08:12.000Z</updated>
<content type="html"><![CDATA[<h1 id="什么是-STL"><a href="#什么是-STL" class="headerlink" title="什么是 STL"></a>什么是 STL</h1><p>STL 是 standard template library 的简写,是标准模板库<br>STL 里面有许多容器和函数,可以让我们快速的写出一些的数据结构或者实现一些功能<br>STL 真的太棒了~~~<br>在此篇文章里,我记录了部分容器的使用方法<br>对于函数的使用,将会在下一篇中记录</p><a id="more"></a><h2 id="STL-—-vector"><a href="#STL-—-vector" class="headerlink" title="STL — vector"></a>STL — vector</h2><h3 id="解释"><a href="#解释" class="headerlink" title="解释"></a>解释</h3><p>vector 是一个数组的模板</p><h3 id="用法"><a href="#用法" class="headerlink" title="用法"></a>用法</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">vector <int> v;</span><br><span class="line">vector <int> v1(v);</span><br><span class="line">v.push_back(value); <span class="comment">//在尾部加入一个数据</span></span><br><span class="line">v.pop_back(); <span class="comment">//删除最后一个数据</span></span><br><span class="line">v.clear(); <span class="comment">//清除容器中所有数据</span></span><br><span class="line">v.empty(); <span class="comment">//判断容器是否为空</span></span><br><span class="line">v.size(); <span class="comment">//返回容器中实际数据的个数</span></span><br><span class="line">v[a].swap(v[b])<span class="comment">//交换元素</span></span><br><span class="line">v.begin(); <span class="comment">//返回第一个元素的地址</span></span><br><span class="line">v.front(); <span class="comment">//返回第一个元素的值</span></span><br><span class="line">v.end(); <span class="comment">//返回最后一个元素的地址</span></span><br><span class="line">v.back(); <span class="comment">//返回最后一个元素的值</span></span><br><span class="line">v.erase(pos) v.erase(begin,end)</span><br><span class="line">v.insert(pos,value)</span><br><span class="line">v.insert(pos,n,value)</span><br></pre></td></tr></table></figure><h2 id="STL-—-queue-priority-queue-stack"><a href="#STL-—-queue-priority-queue-stack" class="headerlink" title="STL — queue/priority_queue/stack"></a>STL — queue/priority_queue/stack</h2><h3 id="解释-1"><a href="#解释-1" class="headerlink" title="解释"></a>解释</h3><p>queue 是一个队列的模板<br>priority_queue 是一个优先队列的模板<br>stack 是一个栈的模板</p><h3 id="用法-1"><a href="#用法-1" class="headerlink" title="用法"></a>用法</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">queue <int> q; stack <int> q;</span><br><span class="line">q.push(x);</span><br><span class="line">q.pop();</span><br><span class="line">q.top();</span><br><span class="line">q.front();</span><br><span class="line">q.back();</span><br><span class="line">q.empty();</span><br><span class="line">q.size();</span><br></pre></td></tr></table></figure><h3 id="优先队列-—-priority-queue"><a href="#优先队列-—-priority-queue" class="headerlink" title="优先队列 — priority_queue"></a>优先队列 — priority_queue</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">priority_queue <int> q;</span><br><span class="line">priority_queue <int,vector <int>,greater <int>> q;</span><br><span class="line">用法同queue</span><br></pre></td></tr></table></figure><h2 id="STL-—-list"><a href="#STL-—-list" class="headerlink" title="STL — list"></a>STL — list</h2><h3 id="解释-2"><a href="#解释-2" class="headerlink" title="解释"></a>解释</h3><p>list 是一个双向链表的模板</p><h3 id="用法-2"><a href="#用法-2" class="headerlink" title="用法"></a>用法</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">begin()和end()</span><br><span class="line">front()和back()</span><br><span class="line">push_back() 和push_front()</span><br><span class="line">empty()</span><br><span class="line">clear()</span><br><span class="line">insert(pos,num)</span><br><span class="line">erase(pos)</span><br><span class="line">sort() <span class="comment">//将链表排序,默认升序</span></span><br><span class="line">remove(num) <span class="comment">//删除链表中匹配num的元素。</span></span><br><span class="line">reverse() <span class="comment">// 逆置list</span></span><br><span class="line">merge() l1.merge(l2) <span class="comment">//合并两个链表,合并后l1拥有l1和l2的元素,默认升序排列</span></span><br></pre></td></tr></table></figure><h2 id="STL-—-set"><a href="#STL-—-set" class="headerlink" title="STL — set"></a>STL — set</h2><h3 id="解释-3"><a href="#解释-3" class="headerlink" title="解释"></a>解释</h3><p>set 是一个红黑树(一种平衡树)的模板,自带去重效果</p><h3 id="用法-3"><a href="#用法-3" class="headerlink" title="用法"></a>用法</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">begin() <span class="comment">//返回set容器的第一个元素</span></span><br><span class="line">end() <span class="comment">//返回set容器的最后一个元素</span></span><br><span class="line">clear() <span class="comment">//删除set容器中的所有的元素</span></span><br><span class="line">empty() <span class="comment">//判断set容器是否为空</span></span><br><span class="line">max_size() <span class="comment">//返回set容器可能包含的元素最大个数</span></span><br><span class="line">size() <span class="comment">//返回当前set容器中的元素个数</span></span><br><span class="line">find(x) <span class="comment">//返回x的地址,若没有则返回end()</span></span><br></pre></td></tr></table></figure><h2 id="STL-—-map"><a href="#STL-—-map" class="headerlink" title="STL — map"></a>STL — map</h2><h3 id="解释-4"><a href="#解释-4" class="headerlink" title="解释"></a>解释</h3><p>map 提供的是一种键值对容器,里面的数据都是成对出现的, 每一对中的第一个值称之为关键字(key),每个关键字只能在map中出现一次;第二个称之为该关键字的对应值。</p><h3 id="方法"><a href="#方法" class="headerlink" title="方法"></a>方法</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line">map <int, string> ID_Name; <span class="comment">// 即一个 ID 对应一个名字,其中 ID 为 int 类型,名字为 string 类型</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用{}赋值是从c++11开始的,因此编译器版本过低时会报错,如visual studio 2012</span></span><br><span class="line">map <int, string> ID_Name = {</span><br><span class="line"> { <span class="number">2015</span>, <span class="string">"Jim"</span> },</span><br><span class="line"> { <span class="number">2016</span>, <span class="string">"Tom"</span> },</span><br><span class="line"> { <span class="number">2017</span>, <span class="string">"Bob"</span> } };</span><br><span class="line">插入:</span><br><span class="line"> 使用[ ]进行单个插入,ID_Name[<span class="number">2015</span>] = <span class="string">"Tom"</span>; <span class="comment">// 如果已经存在键值2015,则会作赋值修改操作,如果没有则插入(2015不是数组下标</span></span><br><span class="line"> <span class="comment">// 插入单个值</span></span><br><span class="line"> mymap.insert(std::pair<char, int>(<span class="string">'a'</span>, <span class="number">100</span>));</span><br><span class="line"> <span class="comment">// 列表形式插入</span></span><br><span class="line"> anothermap.insert({ { <span class="string">'d'</span>, <span class="number">100</span> }, {<span class="string">'e'</span>, <span class="number">200</span>} });</span><br><span class="line">取值:</span><br><span class="line"> <span class="built_in">Map</span>中元素取值主要有at和[ ]两种操作,at会作下标检查,而[]不会。</span><br><span class="line">容量查询:</span><br><span class="line"> <span class="comment">// 查询map是否为空</span></span><br><span class="line"> bool empty();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 查询map中键值对的数量</span></span><br><span class="line"> size_t size();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 查询map所能包含的最大键值对数量,和系统和应用库有关。</span></span><br><span class="line"> <span class="comment">// 此外,这并不意味着用户一定可以存这么多,很可能还没达到就已经开辟内存失败了</span></span><br><span class="line"> size_t max_size();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 查询关键字为key的元素的个数,在map里结果非0即1</span></span><br><span class="line"> size_t count( <span class="keyword">const</span> Key& key ) <span class="keyword">const</span>; <span class="comment">// 例:map.count("a")</span></span><br><span class="line">删除:</span><br><span class="line"> <span class="comment">// 删除迭代器指向位置的键值对,并返回一个指向下一元素的迭代器</span></span><br><span class="line"> iterator erase( iterator pos )</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 删除一定范围内的元素,并返回一个指向下一元素的迭代器</span></span><br><span class="line"> iterator erase( const_iterator first, const_iterator last );</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 根据Key来进行删除, 返回删除的元素数量,在map里结果非0即1</span></span><br><span class="line"> size_t erase( <span class="keyword">const</span> key_type& key );</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 清空map,清空后的size为0</span></span><br><span class="line"> <span class="keyword">void</span> clear();</span><br><span class="line">查找:</span><br><span class="line"> <span class="comment">// 关键字查询,找到则返回指向该关键字的迭代器,否则返回指向end的迭代器</span></span><br><span class="line"> <span class="comment">// 根据map的类型,返回的迭代器为 iterator 或者 const_iterator</span></span><br><span class="line"> iterator find (<span class="keyword">const</span> key_type& k);</span><br><span class="line"> const_iterator find (<span class="keyword">const</span> key_type& k) <span class="keyword">const</span>;</span><br></pre></td></tr></table></figure><h2 id="STL-—-pair"><a href="#STL-—-pair" class="headerlink" title="STL — pair"></a>STL — pair</h2><h3 id="解释-5"><a href="#解释-5" class="headerlink" title="解释"></a>解释</h3><p>pair 是一个储存键值对的容器</p><h3 id="用法-4"><a href="#用法-4" class="headerlink" title="用法"></a>用法</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">pair <string,double> product1 (<span class="string">"tomatoes"</span>,<span class="number">3.25</span>);</span><br><span class="line">pair <string,double> product2;</span><br><span class="line">pair <string,double> product3;</span><br><span class="line"> </span><br><span class="line">product2.first =<span class="string">"lightbulbs"</span>; <span class="comment">// type of first is string</span></span><br><span class="line">product2.second =<span class="number">0.99</span>; <span class="comment">// type of second is double</span></span><br><span class="line"> </span><br><span class="line">product3 = make_pair (<span class="string">"shoes"</span>,<span class="number">20.0</span>);</span><br></pre></td></tr></table></figure><h2 id="STL-—-iterator"><a href="#STL-—-iterator" class="headerlink" title="STL — iterator"></a>STL — iterator</h2><h3 id="解释-6"><a href="#解释-6" class="headerlink" title="解释"></a>解释</h3><p>iterator 是迭代器 可以用来接收容器的地址,如 begin(),end() 等的返回值</p><h3 id="用法-5"><a href="#用法-5" class="headerlink" title="用法"></a>用法</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">vector <int> v;</span><br><span class="line">vector <int>::iterator it;</span><br><span class="line"><span class="keyword">while</span>(it = v.begin(); it != v.end(); it++)</span><br><span class="line">{</span><br><span class="line"> <span class="comment">//进行操作</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="特殊说明"><a href="#特殊说明" class="headerlink" title="特殊说明"></a>特殊说明</h2><p>若在容器中存放结构,例如:<br>struct edge{<br> int v,w;<br>}e;<br>应该如此:vector <edge> v; 注意尖括号内应为结构原来的名称</edge></p><p>此外,若容器为 set 容器,则结构中必须重载小于号,若 set <edge,greater <int> >,则要重载大于号<br>set 中只能有两个参数,vector <int>和 greater <int> 不能同时写进去,而 priority_queue 可以</int></int></edge,greater></p>]]></content>
<summary type="html">
<h1 id="什么是-STL"><a href="#什么是-STL" class="headerlink" title="什么是 STL"></a>什么是 STL</h1><p>STL 是 standard template library 的简写,是标准模板库<br>STL 里面有许多容器和函数,可以让我们快速的写出一些的数据结构或者实现一些功能<br>STL 真的太棒了~~~<br>在此篇文章里,我记录了部分容器的使用方法<br>对于函数的使用,将会在下一篇中记录</p>
</summary>
<category term="STL" scheme="http://yoursite.com/tags/STL/"/>
</entry>
<entry>
<title>单/多源最短路</title>
<link href="http://yoursite.com/2019/09/24/%E6%9C%80%E7%9F%AD%E8%B7%AF%E7%AE%97%E6%B3%95/"/>
<id>http://yoursite.com/2019/09/24/最短路算法/</id>
<published>2019-09-24T06:25:09.000Z</published>
<updated>2021-05-16T13:08:24.000Z</updated>
<content type="html"><![CDATA[<h2 id="单-多源最短路的三种算法-—-dijkstra-amp-spfa-amp-floyd"><a href="#单-多源最短路的三种算法-—-dijkstra-amp-spfa-amp-floyd" class="headerlink" title="单/多源最短路的三种算法 — dijkstra & spfa & floyd"></a>单/多源最短路的三种算法 — dijkstra & spfa & floyd</h2><h3 id="什么是最短路"><a href="#什么是最短路" class="headerlink" title="什么是最短路"></a>什么是最短路</h3><p>单源最短路:计算图中一个点到其他各点的最短距离<br>多源最短路:计算图中多个点到其他各点的最短距离</p><h3 id="单源最短路-—-dijkstra-算法"><a href="#单源最短路-—-dijkstra-算法" class="headerlink" title="单源最短路 — dijkstra 算法"></a>单源最短路 — dijkstra 算法</h3><h4 id="算法描述"><a href="#算法描述" class="headerlink" title="算法描述"></a>算法描述</h4><p>main 函数:用vector数组存边,初始化一维数组 dist 来表示起点到其他各点的距离(到自己为 0,其他点为 INF),将初始边(目标点为起点,权值为 0)加入到优先队列 queue 中<br>dijkstra 函数:抛出优先队列的 top 边,若这个边的权值比现在到这个目标点的权值大(说明起点到该点的长度又更新了,而且那个边肯定在这个边前面),就跳过,否则就疏松以这个点为起点的所有边,若通过这个点,起始点到其他的点的距离有减小的,则把路径减小的目标点和减小后的距离加入到优先队列中,重复操作<br><a id="more"></a></p><h4 id="算法应用"><a href="#算法应用" class="headerlink" title="算法应用"></a>算法应用</h4><p>说明:这个题有点意思(</p><h5 id="题目描述"><a href="#题目描述" class="headerlink" title="题目描述"></a>题目描述</h5><p>知识点:最短路,最短路的优化</p><p>贝克兰德有n个城镇,这些城镇之间有m条道路连接,每条道路有一个长度l。</p><p>zf在其中k个城镇设置了治安点。当一个城镇发生事件时,任意一个治安点都可以派人前往。但是为了节省资源,往往会选择距离最近的治安点。</p><p>那么请问,对于每一个城镇,最近的治安点距离为多少。</p><h5 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h5><p>这个题要求算部分点到其他点的最短距离,因此看起来是一个多源最短路,但是你如果执行多次 dijkstra 你就超时了,所以我们要多设立一个虚拟点 s,把所有的治安点往这个虚拟点上拉一条距离为 0的边(无向),以这个点为起点计算到其他点的最短路即满足要求</p><h5 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"> Author: 王振</span></span><br><span class="line"><span class="comment"> Result: ACSubmission_id: 1833390</span></span><br><span class="line"><span class="comment"> Created at: Fri Sep 13 2019 21:01:55 GMT+0800 (CST)</span></span><br><span class="line"><span class="comment"> Problem_id: 2378Time: 540Memory: 5508</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line">#include <iostream></span><br><span class="line">#include <queue></span><br><span class="line">#include <vector></span><br><span class="line">#include <algorithm></span><br><span class="line">using namespace std;</span><br><span class="line">int n,m,s;</span><br><span class="line">int dist[<span class="number">1005</span>];</span><br><span class="line">struct line{</span><br><span class="line"> int w;</span><br><span class="line"> int v;</span><br><span class="line"> bool operator <(<span class="keyword">const</span> line&b) <span class="keyword">const</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> w>b.w;</span><br><span class="line">}</span><br><span class="line">}list;</span><br><span class="line"></span><br><span class="line">vector <line> vec[<span class="number">1005</span>];</span><br><span class="line">priority_queue <line> q;</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> dijkstra(int p)</span><br><span class="line">{</span><br><span class="line">list.v=p;</span><br><span class="line">list.w=<span class="number">0</span>;</span><br><span class="line">q.push(list);</span><br><span class="line"><span class="keyword">while</span>(!q.empty())</span><br><span class="line">{</span><br><span class="line">struct line k=q.top();</span><br><span class="line">q.pop();</span><br><span class="line"><span class="keyword">if</span>(k.w>dist[k.v])</span><br><span class="line">{</span><br><span class="line"><span class="keyword">continue</span>;</span><br><span class="line">}<span class="keyword">else</span></span><br><span class="line">{</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">0</span>;i<vec[k.v].size();i++)</span><br><span class="line">{</span><br><span class="line">struct line j=vec[k.v][i];</span><br><span class="line"><span class="keyword">if</span>(dist[j.v]>dist[k.v]+j.w)</span><br><span class="line">{</span><br><span class="line">dist[j.v]=dist[k.v]+j.w;</span><br><span class="line">list.v=j.v;</span><br><span class="line">list.w=dist[j.v];</span><br><span class="line">q.push(list);</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">int main()</span><br><span class="line">{</span><br><span class="line">int t;</span><br><span class="line">cin>>t;</span><br><span class="line"><span class="keyword">while</span>(t--)</span><br><span class="line">{</span><br><span class="line">int u,v,w;</span><br><span class="line">scanf(<span class="string">"%d%d%d"</span>,&n,&m,&s);</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">1</span>;i<=n+<span class="number">1</span>;i++)</span><br><span class="line">{</span><br><span class="line"><span class="keyword">while</span>(!vec[i].empty())</span><br><span class="line">{</span><br><span class="line">vec[i].pop_back();</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">1</span>;i<=n+<span class="number">1</span>;i++)</span><br><span class="line">{</span><br><span class="line">dist[i]=<span class="number">10000000</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">1</span>;i<=s;i++)</span><br><span class="line">{</span><br><span class="line">scanf(<span class="string">"%d"</span>,&u);</span><br><span class="line">list.w=<span class="number">0</span>;</span><br><span class="line">list.v=u;</span><br><span class="line">vec[n+<span class="number">1</span>].push_back(list);</span><br><span class="line">list.v=n+<span class="number">1</span>;</span><br><span class="line">vec[u].push_back(list);</span><br><span class="line">}</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">1</span>;i<=m;i++)</span><br><span class="line">{</span><br><span class="line">scanf(<span class="string">"%d%d%d"</span>,&u,&v,&w);</span><br><span class="line">list.v=v;</span><br><span class="line">list.w=w;</span><br><span class="line">vec[u].push_back(list);</span><br><span class="line">list.v=u;</span><br><span class="line">vec[v].push_back(list);</span><br><span class="line">}</span><br><span class="line">dist[n+<span class="number">1</span>]=<span class="number">0</span>;</span><br><span class="line">dijkstra(n+<span class="number">1</span>);</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">1</span>;i<=n;i++)</span><br><span class="line">{</span><br><span class="line">printf(<span class="string">"%d "</span>,dist[i]);</span><br><span class="line">}</span><br><span class="line">printf(<span class="string">"\n"</span>);</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="单源最短路-—-spfa-算法-可以判断负环!"><a href="#单源最短路-—-spfa-算法-可以判断负环!" class="headerlink" title="单源最短路 — spfa 算法 可以判断负环!"></a>单源最短路 — spfa 算法 可以判断负环!</h3><h4 id="算法描述-1"><a href="#算法描述-1" class="headerlink" title="算法描述"></a>算法描述</h4><p>将某个点的序号 x 作为 spfa 函数的输入,则从这个点开始进行单源最短路,如果点 v 通过当前点 u 到输入点 x 的距离变小,那么更新距离值,并且如果 v 不在队列中,就将 v 加入到队列里,对于每个点记录它们加入队列的次数,如果大于总点数 n ,就判定为当前图中存在负环。</p><h4 id="题目描述-1"><a href="#题目描述-1" class="headerlink" title="题目描述"></a>题目描述</h4><p>知识点:最短路</p><p>克莱恩在一场冒险中得到了得到了一个破损的魔法阵,这个魔法阵是一个有n个点m条边的有向有环图,任意两点之间最多只有一条边,每条边有一个能量值a(可能是负数,别问问就是magical),不存在负环。</p><p>克莱恩试图去修补这个魔法阵。已知,这个魔法阵缺少了3条边,且已经知道这3条边的起点和终点(有向)。对于每条边,克莱恩要赋予其一个能量值c,为了避免邪神出现,修补过程以及结束后也不能出现负环。</p><p>请问每次的最小花费是多少(保证有解,可以是负数)。</p><h4 id="题目思路"><a href="#题目思路" class="headerlink" title="题目思路"></a>题目思路</h4><p>修补过程及结束后不能出现负环,则枚举边权来找到最大的可以使图中出现负环的权值,那么给这个权值加一图中就没有负环(其实可以二分权值直接找到答案)</p><h4 id="代码示例"><a href="#代码示例" class="headerlink" title="代码示例"></a>代码示例</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"> Author: 王振</span></span><br><span class="line"><span class="comment"> Result: ACSubmission_id: 1833275</span></span><br><span class="line"><span class="comment"> Created at: Fri Sep 13 2019 16:22:27 GMT+0800 (CST)</span></span><br><span class="line"><span class="comment"> Problem_id: 2376Time: 790Memory: 3228</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line">#include <iostream></span><br><span class="line">#include <queue></span><br><span class="line">#include <algorithm></span><br><span class="line">#include <vector></span><br><span class="line">#include <cmath></span><br><span class="line">using namespace std;</span><br><span class="line"></span><br><span class="line">struct edge{</span><br><span class="line">int v,w;</span><br><span class="line">}e;</span><br><span class="line"></span><br><span class="line">vector <edge> v[<span class="number">305</span>];</span><br><span class="line">queue <int> q;</span><br><span class="line">int n,m;</span><br><span class="line">int flag=<span class="number">0</span>; <span class="comment">// 有无负环的标志,有负环 flag=1 </span></span><br><span class="line">int num[<span class="number">305</span>]; <span class="comment">// 存储每个点加入队列的次数 </span></span><br><span class="line">int visit[<span class="number">305</span>]; <span class="comment">// 如果某个点在队列中,那么visit[i]=1,反之为0 </span></span><br><span class="line">int dist[<span class="number">305</span>]; <span class="comment">// 存储距离 </span></span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> spfa(int x)</span><br><span class="line">{</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">0</span>;i<n;i++) <span class="comment">// 初始化 </span></span><br><span class="line">{</span><br><span class="line">num[i]=<span class="number">0</span>;</span><br><span class="line">visit[i]=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">if</span>(i!=x) dist[i]=<span class="number">10000000</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">while</span>(!q.empty())</span><br><span class="line">{</span><br><span class="line">int a=q.front();</span><br><span class="line">visit[a]=<span class="number">0</span>;</span><br><span class="line">q.pop();</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">0</span>;i<v[a].size();i++)</span><br><span class="line">{</span><br><span class="line">int c=v[a][i].v;</span><br><span class="line"><span class="keyword">if</span>(dist[c]>dist[a]+v[a][i].w) <span class="comment">// 距离小于当前距离,更新,如果这个点不在队列中则加入队列,且这个点的访问次数+1 </span></span><br><span class="line">{</span><br><span class="line">dist[c]=dist[a]+v[a][i].w;</span><br><span class="line"><span class="keyword">if</span>(visit[c]==<span class="number">0</span>)</span><br><span class="line">{</span><br><span class="line">num[c]++; </span><br><span class="line">q.push(c);</span><br><span class="line">visit[c]=<span class="number">1</span>;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">0</span>;i<n;i++)</span><br><span class="line">{</span><br><span class="line"><span class="keyword">if</span>(num[i]>n) <span class="comment">// 如果对一个点访问次数 >n 则判定为存在负环 </span></span><br><span class="line">{</span><br><span class="line">flag=<span class="number">1</span>;</span><br><span class="line"><span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">int main()</span><br><span class="line">{</span><br><span class="line">cin>>n>>m;</span><br><span class="line">int x,y,z;</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">0</span>;i<m;i++) <span class="comment">// 输入边 </span></span><br><span class="line">{</span><br><span class="line">cin>>x>>y>>z;</span><br><span class="line">e.v=y;</span><br><span class="line">e.w=z;</span><br><span class="line">v[x].push_back(e);</span><br><span class="line">}</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">0</span>;i<<span class="number">3</span>;i++)</span><br><span class="line">{</span><br><span class="line">flag=<span class="number">0</span>;</span><br><span class="line">cin>>x>>y;</span><br><span class="line">e.v=y;</span><br><span class="line">e.w=<span class="number">1000</span>;</span><br><span class="line">v[x].push_back(e);</span><br><span class="line"><span class="keyword">while</span>(flag==<span class="number">0</span>) <span class="comment">// 若没有负环则边权减小直到有负环为止</span></span><br><span class="line">{</span><br><span class="line">q.push(x);</span><br><span class="line">e.w--;</span><br><span class="line">v[x].pop_back();</span><br><span class="line">v[x].push_back(e);</span><br><span class="line">spfa(x);</span><br><span class="line">}</span><br><span class="line">v[x].pop_back(); <span class="comment">//此时的边权为最大的有负环的权值,加一则没有负环</span></span><br><span class="line">e.w++;</span><br><span class="line">v[x].push_back(e);</span><br><span class="line">cout<<e.w<<endl;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="多源最短路-—-floyd-算法"><a href="#多源最短路-—-floyd-算法" class="headerlink" title="多源最短路 — floyd 算法"></a>多源最短路 — floyd 算法</h3><h4 id="算法描述-2"><a href="#算法描述-2" class="headerlink" title="算法描述"></a>算法描述</h4><p>floyd 算法很简单,先在邻接矩阵中将直接相连的边的权值更新,然后对于任意两个点,以任意一个点为中介,更新两个点之间的权值,注意将当成中介的点放在最外面的循环,如若不然,可以将这三个循环执行三遍,则不用管i,j,k的顺序</p><h4 id="代码示例-1"><a href="#代码示例-1" class="headerlink" title="代码示例"></a>代码示例</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">for</span>(int k=<span class="number">1</span>;k<=n;k++)</span><br><span class="line">{</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">1</span>;i<=n;i++)</span><br><span class="line">{</span><br><span class="line"><span class="keyword">for</span>(int j=<span class="number">1</span>;j<=n;j++)</span><br><span class="line">{</span><br><span class="line"><span class="keyword">if</span>(dist[i][j]>dist[i][k]+dist[k][j])</span><br><span class="line">{</span><br><span class="line">dist[i][j]=dist[i][k]+dist[k][j];</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="单-多源最短路的三种算法-—-dijkstra-amp-spfa-amp-floyd"><a href="#单-多源最短路的三种算法-—-dijkstra-amp-spfa-amp-floyd" class="headerlink" title="单/多源最短路的三种算法 — dijkstra &amp; spfa &amp; floyd"></a>单/多源最短路的三种算法 — dijkstra &amp; spfa &amp; floyd</h2><h3 id="什么是最短路"><a href="#什么是最短路" class="headerlink" title="什么是最短路"></a>什么是最短路</h3><p>单源最短路:计算图中一个点到其他各点的最短距离<br>多源最短路:计算图中多个点到其他各点的最短距离</p>
<h3 id="单源最短路-—-dijkstra-算法"><a href="#单源最短路-—-dijkstra-算法" class="headerlink" title="单源最短路 — dijkstra 算法"></a>单源最短路 — dijkstra 算法</h3><h4 id="算法描述"><a href="#算法描述" class="headerlink" title="算法描述"></a>算法描述</h4><p>main 函数:用vector数组存边,初始化一维数组 dist 来表示起点到其他各点的距离(到自己为 0,其他点为 INF),将初始边(目标点为起点,权值为 0)加入到优先队列 queue 中<br>dijkstra 函数:抛出优先队列的 top 边,若这个边的权值比现在到这个目标点的权值大(说明起点到该点的长度又更新了,而且那个边肯定在这个边前面),就跳过,否则就疏松以这个点为起点的所有边,若通过这个点,起始点到其他的点的距离有减小的,则把路径减小的目标点和减小后的距离加入到优先队列中,重复操作<br></p>
</summary>
<category term="数据结构" scheme="http://yoursite.com/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
</entry>
<entry>
<title>最小生成树</title>
<link href="http://yoursite.com/2019/09/24/%E6%9C%80%E5%B0%8F%E7%94%9F%E6%88%90%E6%A0%91/"/>
<id>http://yoursite.com/2019/09/24/最小生成树/</id>
<published>2019-09-24T05:54:47.000Z</published>
<updated>2021-05-16T13:08:24.000Z</updated>
<content type="html"><![CDATA[<h2 id="最小生成树的两种算法-—-Prim-amp-Kruscal"><a href="#最小生成树的两种算法-—-Prim-amp-Kruscal" class="headerlink" title="最小生成树的两种算法 — Prim & Kruscal"></a>最小生成树的两种算法 — Prim & Kruscal</h2><h3 id="什么是最小生成树"><a href="#什么是最小生成树" class="headerlink" title="什么是最小生成树"></a>什么是最小生成树</h3><p>最小生成树是一副连通加权无向图中一棵权值最小的生成树。</p><p>在一给定的无向图 G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即 {\displaystyle (u,v)\in E}(u,v)\in E),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集且 (V, T) 为树,使得 w(T) 最小,则此 T 为 G 的最小生成树。<br><a id="more"></a></p><h3 id="最小生成树-—-Prim-算法"><a href="#最小生成树-—-Prim-算法" class="headerlink" title="最小生成树 — Prim 算法"></a>最小生成树 — Prim 算法</h3><h4 id="算法描述"><a href="#算法描述" class="headerlink" title="算法描述"></a>算法描述</h4><ol><li>准备:定义一个二维数组 dist 来存储每两个点之间的距离,定义一个一维数组 minc 来存储每个点到已经在最小生成树中的点的最小距离</li><li>初始化邻接矩阵,然后通过输入的数据来改变邻接矩阵</li><li>选择一个顶点 s 作为最小生成树中的点,初始化 minc 数组,其中 minc[s] 为 0 ,若其他点到 s 有边,则初始化为边的权重,否则初始化为 MAX 值</li><li>选择 minc 数组中不为 0 且最小的一个值对应的点,加入最小生成树,将该值变为 0,更新其他点到最小生成树中的点的最小距离</li><li>重复第三步操作直到所有的点都加入到最小生成树中</li></ol><h4 id="代码示例"><a href="#代码示例" class="headerlink" title="代码示例"></a>代码示例</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line">#include <stdio.h></span><br><span class="line">#define M 5001</span><br><span class="line">#define INF 99999999</span><br><span class="line">int n,e1,e;</span><br><span class="line">int dist[M][M];</span><br><span class="line">int minc[M];</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> solve(int s)</span><br><span class="line">{</span><br><span class="line"> int i,j,count=<span class="number">0</span>,min,k;</span><br><span class="line"> <span class="keyword">for</span>(i=<span class="number">1</span>;i<=n;i++)</span><br><span class="line"> {</span><br><span class="line"> minc[i]=dist[s][i];</span><br><span class="line">}</span><br><span class="line"> minc[s]=<span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(i=<span class="number">1</span>;i<n;i++)</span><br><span class="line">{</span><br><span class="line"> min=INF;</span><br><span class="line"> <span class="keyword">for</span>(j=<span class="number">1</span>;j<=n;j++)</span><br><span class="line">{</span><br><span class="line"> <span class="keyword">if</span>(minc[j] && minc[j]<min)</span><br><span class="line">{</span><br><span class="line"> min=minc[j];</span><br><span class="line"> k=j;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> minc[k]=<span class="number">0</span>;</span><br><span class="line"> count+=min;</span><br><span class="line"> <span class="keyword">for</span>(j=<span class="number">1</span>;j<=n;j++)</span><br><span class="line">{</span><br><span class="line"> <span class="keyword">if</span>(dist[k][j]<minc[j])</span><br><span class="line"> {</span><br><span class="line"> minc[j]=dist[k][j];</span><br><span class="line">}</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> printf(<span class="string">"%d"</span>,count);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">int main()</span><br><span class="line">{</span><br><span class="line"> int t1,t2,t3,i,j;</span><br><span class="line"> <span class="keyword">for</span>(i=<span class="number">0</span>;i<M;i++)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">for</span>(j=<span class="number">0</span>;j<M;j++)</span><br><span class="line"> {</span><br><span class="line"> dist[i][j]=INF;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"> scanf(<span class="string">"%d%d"</span>,&n,&e);</span><br><span class="line"> <span class="keyword">for</span>(i=<span class="number">1</span>;i<=e;i++)</span><br><span class="line">{</span><br><span class="line"> scanf(<span class="string">"%d%d%d"</span>,&t1,&t2,&t3);</span><br><span class="line"> <span class="keyword">if</span>(t3<dist[t1][t2])</span><br><span class="line"> {</span><br><span class="line"> dist[t2][t1]=dist[t1][t2]=t3;</span><br><span class="line">}</span><br><span class="line"> }</span><br><span class="line"> solve(<span class="number">1</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="最小生成树-—-kruscal-算法"><a href="#最小生成树-—-kruscal-算法" class="headerlink" title="最小生成树 — kruscal 算法"></a>最小生成树 — kruscal 算法</h3><h4 id="算法描述-1"><a href="#算法描述-1" class="headerlink" title="算法描述"></a>算法描述</h4><ol><li>准备:并查集的知识</li><li>用邻接链表存储每一条边,再用一个结构数组存储所有的边,将结构数组按照边的权值大小从小到大排序</li><li>遍历结构数组,如果一条边的两个端点的祖宗不同,则将起点的祖宗的祖宗设为终点的祖宗(有点绕嘴),否则直接跳到下一条边</li><li>重复 2 操作,直到所有的点都加入到了最小生成树中</li></ol><h4 id="代码示例-1"><a href="#代码示例-1" class="headerlink" title="代码示例"></a>代码示例</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line">#include <stdio.h></span><br><span class="line">#include <stdlib.h></span><br><span class="line">int n,m,i,j,u,v,total;</span><br><span class="line">struct edge{</span><br><span class="line">int start,to;</span><br><span class="line">long long val;</span><br><span class="line">}bian[<span class="number">200005</span>];</span><br><span class="line">int f[<span class="number">100000</span>];</span><br><span class="line">long long ans;</span><br><span class="line"></span><br><span class="line">int find(int x)</span><br><span class="line"> <span class="keyword">if</span>(f[x]==x)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> x;</span><br><span class="line">}<span class="keyword">else</span> </span><br><span class="line"> {</span><br><span class="line"> f[x]=find(f[x]);</span><br><span class="line"> <span class="keyword">return</span> f[x];</span><br><span class="line"> } </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> kruskal()</span><br><span class="line">{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span>(i=<span class="number">1</span>;i<=m;i++)</span><br><span class="line"> {</span><br><span class="line"> u=find(bian[i].start);</span><br><span class="line"> v=find(bian[i].to);</span><br><span class="line"> <span class="keyword">if</span>(u==v) <span class="keyword">continue</span>;</span><br><span class="line"> ans+=bian[i].val;</span><br><span class="line"> f[u]=v;</span><br><span class="line"> total++;</span><br><span class="line"> <span class="keyword">if</span>(total==n<span class="number">-1</span>) <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line">} </span><br><span class="line"></span><br><span class="line">int cmp(<span class="keyword">const</span> <span class="keyword">void</span> *ap,<span class="keyword">const</span> <span class="keyword">void</span> *bp)</span><br><span class="line">{</span><br><span class="line"><span class="keyword">const</span> struct edge *a=(struct edge *)ap;</span><br><span class="line"><span class="keyword">const</span> struct edge *b=(struct edge *)bp;</span><br><span class="line"><span class="keyword">return</span> a->val-b->val;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">int main()</span><br><span class="line">{</span><br><span class="line"> scanf(<span class="string">"%d%d"</span>,&n,&m);</span><br><span class="line"> <span class="keyword">for</span>(i=<span class="number">1</span>;i<=n;i++) </span><br><span class="line"> {</span><br><span class="line"> f[i]=i;</span><br><span class="line">}</span><br><span class="line"> <span class="keyword">for</span>(i=<span class="number">1</span>;i<=m;i++)</span><br><span class="line"> {</span><br><span class="line"> scanf(<span class="string">"%d%d%d"</span>,&bian[i].start,&bian[i].to,&bian[i].val);</span><br><span class="line"> }</span><br><span class="line"> qsort(bian+<span class="number">1</span>,m,sizeof(struct edge),cmp);</span><br><span class="line"> kruskal();</span><br><span class="line"> printf(<span class="string">"%d"</span>,ans);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h3><p>Prim 算法多用于稠密图,Kruscal 算法多用于稀疏图</p>]]></content>
<summary type="html">
<h2 id="最小生成树的两种算法-—-Prim-amp-Kruscal"><a href="#最小生成树的两种算法-—-Prim-amp-Kruscal" class="headerlink" title="最小生成树的两种算法 — Prim &amp; Kruscal"></a>最小生成树的两种算法 — Prim &amp; Kruscal</h2><h3 id="什么是最小生成树"><a href="#什么是最小生成树" class="headerlink" title="什么是最小生成树"></a>什么是最小生成树</h3><p>最小生成树是一副连通加权无向图中一棵权值最小的生成树。</p>
<p>在一给定的无向图 G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即 {\displaystyle (u,v)\in E}(u,v)\in E),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集且 (V, T) 为树,使得 w(T) 最小,则此 T 为 G 的最小生成树。<br></p>
</summary>
<category term="数据结构" scheme="http://yoursite.com/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
</entry>
<entry>
<title>状压dp</title>
<link href="http://yoursite.com/2019/09/22/%E7%8A%B6%E5%8E%8Bdp/"/>
<id>http://yoursite.com/2019/09/22/状压dp/</id>
<published>2019-09-22T14:33:50.000Z</published>
<updated>2021-05-16T13:08:24.000Z</updated>
<content type="html"><![CDATA[<h2 id="题目:互不侵犯"><a href="#题目:互不侵犯" class="headerlink" title="题目:互不侵犯"></a>题目:互不侵犯</h2><h3 id="题目描述"><a href="#题目描述" class="headerlink" title="题目描述"></a>题目描述</h3><p>在 N*N 的棋盘里面放 K 个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共 8 个格子。<br><a id="more"></a></p><h3 id="输入"><a href="#输入" class="headerlink" title="输入"></a>输入</h3><p>只有一行,包含两个数 N, K。</p><h3 id="输出"><a href="#输出" class="headerlink" title="输出"></a>输出</h3><p>所得的方案数。</p><h3 id="输入样例"><a href="#输入样例" class="headerlink" title="输入样例"></a>输入样例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">3 2</span><br></pre></td></tr></table></figure><h3 id="输出样例"><a href="#输出样例" class="headerlink" title="输出样例"></a>输出样例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">16</span><br></pre></td></tr></table></figure><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><h3 id="关于-状压dp"><a href="#关于-状压dp" class="headerlink" title="关于 状压dp"></a>关于 状压dp</h3><p>状压dp是动态规划的一种,通过将状态压缩为整数来达到优化转移的目的。<br>具体来说,我们可以用一个二进制数的每一个二进制位来表示一个位置的状态,在这个题中,我们就可以用 0 来表示该位置不放置国王,用 1 来表示该位置放置国王<br>因为棋盘是一个 N*N 大小的矩阵,我们就可以每一行用一个二进制数来表示该行国王的放置情况</p><h3 id="具体操作"><a href="#具体操作" class="headerlink" title="具体操作"></a>具体操作</h3><p>见代码注释</p><h3 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h3><p>这里是本蒟蒻的代码~</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line">#include <iostream></span><br><span class="line">#include <algorithm></span><br><span class="line">using namespace std;</span><br><span class="line"></span><br><span class="line">int n,k,cnt; <span class="comment">// n为棋盘的大小,k为国王的个数,cnt为只考虑一行的情况下(即一个国王的左右不能放置国王)放置国王的所有可能情况(国王为任意数量)</span></span><br><span class="line">long long sta[<span class="number">2005</span>],sit[<span class="number">2005</span>]; <span class="comment">// sta数组存储各个情况放置的国王的数目 sit数组存储各个情况下国王的放置位置(用一个二进制数来表示)</span></span><br><span class="line">int f[<span class="number">15</span>][<span class="number">2005</span>][<span class="number">105</span>]; <span class="comment">// f数组的第一维是当前的行数,第二维是放置国王的所有情况中的第几个,第三维是到该行总共放置国王的个数</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> dfs(int x,int num,int cur) <span class="comment">// 预处理出单行情况放置国王的所有情况 x:国王的放置位置(一个二进制数) num:放置国王的个数 cur:当前搜到的位置</span></span><br><span class="line">{</span><br><span class="line"><span class="keyword">if</span>(cur>=n) <span class="comment">// cur>=n 表示一行搜完</span></span><br><span class="line">{</span><br><span class="line">sit[++cnt]=x; </span><br><span class="line">sta[cnt]=num;</span><br><span class="line"><span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line">dfs(x,num,cur+<span class="number">1</span>); <span class="comment">//该位置不放国王</span></span><br><span class="line">dfs(x+(<span class="number">1</span><<cur),num+<span class="number">1</span>,cur+<span class="number">2</span>); <span class="comment">//该位置放国王</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">int main()</span><br><span class="line">{</span><br><span class="line"><span class="keyword">while</span>(cin>>n>>k)</span><br><span class="line">{</span><br><span class="line">dfs(<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>); <span class="comment">//预处理出所有情况</span></span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">1</span>;i<=cnt;i++) <span class="comment">//将结果赋给第一行</span></span><br><span class="line">{</span><br><span class="line">f[<span class="number">1</span>][i][sta[i]]=<span class="number">1</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">2</span>;i<=n;i++) <span class="comment">//从第 2 行到第 n 行,对于前一行的所有可能状态,当前行用所有的可能状态进行比较</span></span><br><span class="line">{</span><br><span class="line"><span class="keyword">for</span>(int j=<span class="number">1</span>;j<=cnt;j++)</span><br><span class="line">{</span><br><span class="line"><span class="keyword">for</span>(int l=<span class="number">1</span>;l<=cnt;l++)</span><br><span class="line">{</span><br><span class="line"><span class="keyword">if</span>(sit[j]&sit[l]) <span class="keyword">continue</span>;</span><br><span class="line"><span class="keyword">if</span>((sit[j]<<<span class="number">1</span>)&sit[l]) <span class="keyword">continue</span>;</span><br><span class="line"><span class="keyword">if</span>(sit[j]&(sit[l]<<<span class="number">1</span>)) <span class="keyword">continue</span>;</span><br><span class="line"> <span class="comment">//上面这三行用来排除不合法的转移 即当前行有国王的上方或左上或右上存在国王</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(int p=sta[j];p<=k;p++) <span class="comment">// 如果两行没有冲突 则当前行放置 sta[j] 个国王</span></span><br><span class="line">{</span><br><span class="line">f[i][j][p]+=f[i<span class="number">-1</span>][l][p-sta[j]];</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">long long ans=<span class="number">0</span>; <span class="comment">// ans为答案</span></span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">1</span>;i<=cnt;i++) <span class="comment">// ans加上第n行的每一种情况下放置k个国王的总数</span></span><br><span class="line">{</span><br><span class="line">ans+=f[n][i][k];</span><br><span class="line">}</span><br><span class="line">cout<<ans<<endl;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>感谢观看~</p>]]></content>
<summary type="html">
<h2 id="题目:互不侵犯"><a href="#题目:互不侵犯" class="headerlink" title="题目:互不侵犯"></a>题目:互不侵犯</h2><h3 id="题目描述"><a href="#题目描述" class="headerlink" title="题目描述"></a>题目描述</h3><p>在 N*N 的棋盘里面放 K 个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共 8 个格子。<br></p>
</summary>
<category term="算法" scheme="http://yoursite.com/tags/%E7%AE%97%E6%B3%95/"/>
<category term="动态规划" scheme="http://yoursite.com/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
</entry>
<entry>
<title>背包问题(一) -- 01背包</title>
<link href="http://yoursite.com/2019/09/20/01%E8%83%8C%E5%8C%85/"/>
<id>http://yoursite.com/2019/09/20/01背包/</id>
<published>2019-09-20T14:28:51.000Z</published>
<updated>2021-05-16T13:08:12.000Z</updated>
<content type="html"><![CDATA[<h2 id="题目:Magry的朋友很多-零食篇"><a href="#题目:Magry的朋友很多-零食篇" class="headerlink" title="题目:Magry的朋友很多 - 零食篇"></a>题目:Magry的朋友很多 - 零食篇</h2><h3 id="题目描述"><a href="#题目描述" class="headerlink" title="题目描述"></a>题目描述</h3><p>Magry有个好朋友Ricardo快要过生日了。Ricardo突然想到可以借生日坑蒙拐骗点东西出来,于是就找了Magry要他买零食当生日礼物。</p><p>Magry手上没那么多钱,不过想了想还是上了天猫超市搜了一波,被那么多吃的看的眼花缭乱头晕目眩不知所措,因为Ricardo只有一个要求,那就是东西尽量好吃,而且还不要有Ricardo不喜欢的东西。。。</p><p>Magry已经知道的是:卖的零食总共有n种,不过比较坑爹的是一种零食一个用户限购一件;每种商品的价格为x元,好吃程度为w。另外,Magry已经知道在那些零食中有一部分是Ricardo不喜欢的(也许是忌口,总之这个和零食的好吃程度毫无关联,甚至对于一部分好吃程度为0甚至是负数的黑暗料理Ricardo也很有可能喜欢吃)。然后,Magry身上总共只有k元。</p><p>现在,Magry想要的是:如何确定购买方案使得在Magry手上的k元不会被透支(即商品总额不大于k元)的情况下买到总的好吃程度最高并且没有Ricardo不喜欢的零食呢?<br><a id="more"></a></p><h3 id="输入"><a href="#输入" class="headerlink" title="输入"></a>输入</h3><p>多组测试数据。</p><p>每组数据第一行为一个数,为商品种类数n,0≤n≤10000<br>接下来n行,每行3个整数x,w,t,每行分别表示一种商品,x代表商品价格,w代表东西的好吃程度,t表示Ricardo喜不喜欢这个东西,1表示喜欢,0表示不喜欢。其中1≤x≤1000,w在int范围内。</p><p>还有最后一行,一个数,k,表示Magry手头的钱。0≤k≤100000</p><h3 id="输出"><a href="#输出" class="headerlink" title="输出"></a>输出</h3><p>对于每组数据,输出一行,一个数,表示Magry在手头的k元不被透支的情况下所购商品的最大好吃程度。</p><h3 id="输入样例"><a href="#输入样例" class="headerlink" title="输入样例"></a>输入样例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">2</span><br><span class="line">3 61 1</span><br><span class="line">7 101 0</span><br><span class="line">100</span><br><span class="line">1</span><br><span class="line">10 1 0</span><br><span class="line">2</span><br></pre></td></tr></table></figure><h3 id="输出样例"><a href="#输出样例" class="headerlink" title="输出样例"></a>输出样例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">61</span><br><span class="line">0</span><br></pre></td></tr></table></figure><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><h3 id="关于-01-背包"><a href="#关于-01-背包" class="headerlink" title="关于 01 背包"></a>关于 01 背包</h3><p>顾名思义,01背包指放入背包的物品每一种只有一个,因此对于每一种物品都只有两个选择,放或者不放,所以我们可以遍历所有的物品,得出状态转移方程:f[m] = max(f[m], f[m-a[i].x]+a[i].w), 其中 f[m] 指花 m 元钱的时候能得到的最大好吃程度 ,a结构数组用来存放每一个物品的价格,好吃程度和喜不喜欢</p><p>关键:我们在里面的循环要通过状态转移方程得出所有的f[m]值,而这个循环必须是从最大钱数 k 递减到 a[i].x, 这是为什么呢?<br> 因为对于每一个 m ,f[m]都是由钱数少于m的状态所得到的,所以如果有少到多,每一个物品都会出现放多个的情况(这就是完全背包的思路)<br> 相信聪明的你一定懂了!!!</p><h3 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h3><p>这里是本蒟蒻的代码~<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"> Author: 王振</span></span><br><span class="line"><span class="comment"> Result: ACSubmission_id: 1838386</span></span><br><span class="line"><span class="comment"> Created at: Fri Sep 20 2019 22:24:18 GMT+0800 (CST)</span></span><br><span class="line"><span class="comment"> Problem_id: 474Time: 2670Memory: 4056</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line">#include <iostream></span><br><span class="line">#include <algorithm></span><br><span class="line">using namespace std;</span><br><span class="line">struct thing{</span><br><span class="line">long long x,w,t;</span><br><span class="line">}a[<span class="number">10005</span>];</span><br><span class="line">long long f[<span class="number">100005</span>];</span><br><span class="line">int main()</span><br><span class="line">{</span><br><span class="line">int n;</span><br><span class="line"><span class="keyword">while</span>(cin>>n)</span><br><span class="line">{</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">1</span>;i<=n;i++)</span><br><span class="line">{</span><br><span class="line">cin>>a[i].x>>a[i].w>>a[i].t;</span><br><span class="line"><span class="keyword">if</span>(a[i].t==<span class="number">0</span>||a[i].w<=<span class="number">0</span>)</span><br><span class="line">{</span><br><span class="line">i--;</span><br><span class="line">n--;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">int k;</span><br><span class="line">cin>>k;</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">0</span>;i<=k;i++)</span><br><span class="line">{</span><br><span class="line">f[i]=<span class="number">0</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">for</span>(int i=<span class="number">1</span>;i<=n;i++)</span><br><span class="line">{</span><br><span class="line"><span class="keyword">for</span>(int m=k;m>=a[i].x;m--)</span><br><span class="line">{</span><br><span class="line">f[m]=max(f[m],f[m-a[i].x]+a[i].w);</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">cout<<f[k]<<endl;</span><br><span class="line">}</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>感谢观看~</p>]]></content>
<summary type="html">
<h2 id="题目:Magry的朋友很多-零食篇"><a href="#题目:Magry的朋友很多-零食篇" class="headerlink" title="题目:Magry的朋友很多 - 零食篇"></a>题目:Magry的朋友很多 - 零食篇</h2><h3 id="题目描述"><a href="#题目描述" class="headerlink" title="题目描述"></a>题目描述</h3><p>Magry有个好朋友Ricardo快要过生日了。Ricardo突然想到可以借生日坑蒙拐骗点东西出来,于是就找了Magry要他买零食当生日礼物。</p>
<p>Magry手上没那么多钱,不过想了想还是上了天猫超市搜了一波,被那么多吃的看的眼花缭乱头晕目眩不知所措,因为Ricardo只有一个要求,那就是东西尽量好吃,而且还不要有Ricardo不喜欢的东西。。。</p>
<p>Magry已经知道的是:卖的零食总共有n种,不过比较坑爹的是一种零食一个用户限购一件;每种商品的价格为x元,好吃程度为w。另外,Magry已经知道在那些零食中有一部分是Ricardo不喜欢的(也许是忌口,总之这个和零食的好吃程度毫无关联,甚至对于一部分好吃程度为0甚至是负数的黑暗料理Ricardo也很有可能喜欢吃)。然后,Magry身上总共只有k元。</p>
<p>现在,Magry想要的是:如何确定购买方案使得在Magry手上的k元不会被透支(即商品总额不大于k元)的情况下买到总的好吃程度最高并且没有Ricardo不喜欢的零食呢?<br></p>
</summary>
<category term="算法" scheme="http://yoursite.com/tags/%E7%AE%97%E6%B3%95/"/>
<category term="动态规划" scheme="http://yoursite.com/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
<category term="背包问题" scheme="http://yoursite.com/tags/%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98/"/>
</entry>
<entry>
<title>关于此博客</title>
<link href="http://yoursite.com/2019/09/20/%E5%85%B3%E4%BA%8E%E6%AD%A4%E5%8D%9A%E5%AE%A2/"/>
<id>http://yoursite.com/2019/09/20/关于此博客/</id>
<published>2019-09-20T08:50:01.000Z</published>
<updated>2021-05-16T13:08:12.000Z</updated>
<content type="html"><![CDATA[<p>欢迎大家来到我的博客,在下在写博客这方面是一个新人小白,如果有人来看的话,希望不要笑话我O(∩_∩)O</p><h2 id="我在博客中会写的东西"><a href="#我在博客中会写的东西" class="headerlink" title="我在博客中会写的东西"></a>我在博客中会写的东西</h2><h3 id="编程学习过程的笔记"><a href="#编程学习过程的笔记" class="headerlink" title="编程学习过程的笔记"></a>编程学习过程的笔记</h3><p>因为我的编程技术很菜,而且脑子又不好,学了啥都记不住,所以想在我的博客中记录下我学习的东西,以便我在以后的时候通过看我的博客能够快速回顾,如果有人能看到我的博客,也希望能从我的笔记中有一些收获,如果我的笔记能对更多人有帮助的话,我会感到十分荣幸</p><a id="more"></a><h3 id="其他一些很nice的东西"><a href="#其他一些很nice的东西" class="headerlink" title="其他一些很nice的东西"></a>其他一些很nice的东西</h3><p>我们在网络上浏览的时候经常能遇到一些好的网站或是一些其他东西,所以我希望能把它们记录下来</p><p>目前我的博客中可能只会添加这些东西,如果我有其他想要添加的东西的话,就会更新这篇文章,希望通过此方式我和其他人都能有更大的进步</p>]]></content>
<summary type="html">
<p>欢迎大家来到我的博客,在下在写博客这方面是一个新人小白,如果有人来看的话,希望不要笑话我O(∩_∩)O</p>
<h2 id="我在博客中会写的东西"><a href="#我在博客中会写的东西" class="headerlink" title="我在博客中会写的东西"></a>我在博客中会写的东西</h2><h3 id="编程学习过程的笔记"><a href="#编程学习过程的笔记" class="headerlink" title="编程学习过程的笔记"></a>编程学习过程的笔记</h3><p>因为我的编程技术很菜,而且脑子又不好,学了啥都记不住,所以想在我的博客中记录下我学习的东西,以便我在以后的时候通过看我的博客能够快速回顾,如果有人能看到我的博客,也希望能从我的笔记中有一些收获,如果我的笔记能对更多人有帮助的话,我会感到十分荣幸</p>
</summary>
</entry>
</feed>