-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch.xml
More file actions
635 lines (305 loc) · 195 KB
/
Copy pathsearch.xml
File metadata and controls
635 lines (305 loc) · 195 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
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>论文写作</title>
<link href="/2025/09/%E8%AE%BA%E6%96%87%E5%86%99%E4%BD%9C/"/>
<url>/2025/09/%E8%AE%BA%E6%96%87%E5%86%99%E4%BD%9C/</url>
<content type="html"><![CDATA[<h3 id="导师推荐的论文写作资料"><a href="#导师推荐的论文写作资料" class="headerlink" title="导师推荐的论文写作资料"></a>导师推荐的论文写作资料</h3><p>主要是计算机方向的</p><ul><li><a href="https://github.com/MLNLP-World/Paper-Writing-Tips">https://github.com/MLNLP-World/Paper-Writing-Tips</a></li><li><a href="https://github.com/guanyingc/latex_paper_writing_tips">https://github.com/guanyingc/latex_paper_writing_tips</a></li><li><a href="https://github.com/hzwer/WritingAIPaper">https://github.com/hzwer/WritingAIPaper</a></li></ul><p>CVPR2018 workshop</p><ul><li><a href="https://deviparikh.com/citizenofcvpr/">https://deviparikh.com/citizenofcvpr/</a></li></ul><p>经典 Talk</p><ul><li><a href="https://www.youtube.com/watch?v=1AYxMbYZQ1Y">https://www.youtube.com/watch?v=1AYxMbYZQ1Y</a></li></ul><h3 id="如何撰写-Conclusion"><a href="#如何撰写-Conclusion" class="headerlink" title="如何撰写 Conclusion"></a>如何撰写 Conclusion</h3><ul><li><a href="https://www.essay-home.com/essay_home/event/140.html">https://www.essay-home.com/essay_home/event/140.html</a></li></ul><ol><li>重申研究问题-1 句</li></ol><ul><li>This study aimed to investigate [研究问题],</li></ul><ol><li>总结主要发现和采用的方法方式-3~4 句</li><li>研究贡献-1~2 句</li><li>局限性以及未来方向(可写)</li></ol><ul><li>While the case study provides in-depth insights, the findings may lack generalisability. Future studies could adopt mixed methods across multiple regions.</li></ul>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> 论文写作 </tag>
</tags>
</entry>
<entry>
<title>HOG-梯度直方图</title>
<link href="/2025/09/HOG-%E6%A2%AF%E5%BA%A6%E7%9B%B4%E6%96%B9%E5%9B%BE/"/>
<url>/2025/09/HOG-%E6%A2%AF%E5%BA%A6%E7%9B%B4%E6%96%B9%E5%9B%BE/</url>
<content type="html"><![CDATA[<h2 id="什么是-HOG"><a href="#什么是-HOG" class="headerlink" title="什么是 HOG"></a>什么是 HOG</h2><p>HOG (Histogram of Oriented Gradients,方向梯度直方图) 是一种在计算机视觉和图像处理中用来进行目标检测的特征描述子。统计局部梯度方向分布,强调边缘和轮廓信息。</p><h3 id="HOG-的核心思想"><a href="#HOG-的核心思想" class="headerlink" title="HOG 的核心思想"></a>HOG 的核心思想</h3><p>HOG 特征的基本思想是:<strong>在一副图像中,局部目标的表象和形状(appearance and shape)能够被梯度或边缘的方向密度分布很好地描述</strong>。</p><p>具体来说:</p><ul><li>图像中的边缘信息对于目标识别非常重要</li><li>边缘的方向信息比边缘的位置信息更稳定</li><li>通过统计局部区域内不同方向梯度的出现频率,可以有效地描述目标的形状特征</li></ul><h3 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h3><ul><li><a href="https://learnopencv.com/histogram-of-oriented-gradients/">https://learnopencv.com/histogram-of-oriented-gradients/</a></li><li><a href="https://zhuanlan.zhihu.com/p/85829145">https://zhuanlan.zhihu.com/p/85829145</a></li></ul>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> HOG </tag>
</tags>
</entry>
<entry>
<title>DCT/DWT-离散余弦变换/离散小波变换</title>
<link href="/2025/09/DCT-DWT-%E7%A6%BB%E6%95%A3%E4%BD%99%E5%BC%A6-%E5%B0%8F%E6%B3%A2%E5%8F%98%E6%8D%A2/"/>
<url>/2025/09/DCT-DWT-%E7%A6%BB%E6%95%A3%E4%BD%99%E5%BC%A6-%E5%B0%8F%E6%B3%A2%E5%8F%98%E6%8D%A2/</url>
<content type="html"><![CDATA[<p>DCT(离散余弦变换)和 DWT(离散小波变换)是两种在频域上分解面部图像、提取多分辨率纹理特征的有效方法。</p><h3 id="DCT-的应用"><a href="#DCT-的应用" class="headerlink" title="DCT 的应用"></a>DCT 的应用</h3><p>DCT 通过将图像转换到频域,利用低频分量保留主要图像信息,高频分量表征细节和纹理,从而实现压缩和特征提取。<br><img src="/images/DCT.png" alt="DCT"><br><img src="/images/DCT_验证.png" alt="DCT_验证"></p><ul><li><p>压缩<br>图像压缩是利用人眼对低频信息比较敏感和对高频信息比较不敏感的原理,对 DCT 变换后的图像,去除部分高频信息,让人眼察觉不到改变,从而实现压缩。</p><p>如下图所示为保留 DCT 变换后系数的比例,可以看到仅保留左上角 32%的系数基本就可以让人眼看不出来变化。</p><p><img src="/images/dct_compression_comparison.png" alt="DCT_压缩"></p><details> <summary>代码</summary><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><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><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</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.nn.functional <span class="keyword">as</span> F</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">from</span> PIL <span class="keyword">import</span> Image</span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">dct_2d</span>(<span class="params">x</span>):</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">2D 离散余弦变换 (DCT)</span></span><br><span class="line"><span class="string">输入: x - shape (B, C, H, W) 或 (H, W)</span></span><br><span class="line"><span class="string">输出: DCT 系数</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="keyword">if</span> <span class="built_in">len</span>(x.shape) == <span class="number">2</span>:</span><br><span class="line">x = x.unsqueeze(<span class="number">0</span>).unsqueeze(<span class="number">0</span>) <span class="comment"># (H, W) -> (1, 1, H, W)</span></span><br><span class="line"></span><br><span class="line"> B, C, H, W = x.shape</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 创建DCT基矩阵</span></span><br><span class="line"> n = H</span><br><span class="line"> m = W</span><br><span class="line"></span><br><span class="line"> <span class="comment"># DCT-II 基矩阵</span></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">dct_matrix</span>(<span class="params">size</span>):</span><br><span class="line"> mat = torch.zeros(size, size)</span><br><span class="line"> <span class="keyword">for</span> k <span class="keyword">in</span> <span class="built_in">range</span>(size):</span><br><span class="line"> <span class="keyword">for</span> n <span class="keyword">in</span> <span class="built_in">range</span>(size):</span><br><span class="line"> <span class="keyword">if</span> k == <span class="number">0</span>:</span><br><span class="line"> mat[k, n] = np.sqrt(<span class="number">1</span>/size)</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> mat[k, n] = np.sqrt(</span><br><span class="line"> <span class="number">2</span>/size) * np.cos(np.pi * k * (<span class="number">2</span>*n + <span class="number">1</span>) / (<span class="number">2</span>*size))</span><br><span class="line"> <span class="keyword">return</span> mat</span><br><span class="line"></span><br><span class="line"> dct_h = dct_matrix(H).to(x.device)</span><br><span class="line"> dct_w = dct_matrix(W).to(x.device)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 应用2D DCT: Y = DxD^T</span></span><br><span class="line"> x_dct = torch.zeros_like(x)</span><br><span class="line"> <span class="keyword">for</span> b <span class="keyword">in</span> <span class="built_in">range</span>(B):</span><br><span class="line"> <span class="keyword">for</span> c <span class="keyword">in</span> <span class="built_in">range</span>(C):</span><br><span class="line"> x_dct[b, c] = torch.mm(torch.mm(dct_h, x[b, c]), dct_w.t())</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> x_dct</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">idct_2d</span>(<span class="params">x_dct</span>):</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">2D 逆离散余弦变换 (IDCT)</span></span><br><span class="line"><span class="string">输入: x_dct - DCT 系数</span></span><br><span class="line"><span class="string">输出: 重构的图像</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line">B, C, H, W = x_dct.shape</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 创建DCT基矩阵</span></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">dct_matrix</span>(<span class="params">size</span>):</span><br><span class="line"> mat = torch.zeros(size, size)</span><br><span class="line"> <span class="keyword">for</span> k <span class="keyword">in</span> <span class="built_in">range</span>(size):</span><br><span class="line"> <span class="keyword">for</span> n <span class="keyword">in</span> <span class="built_in">range</span>(size):</span><br><span class="line"> <span class="keyword">if</span> k == <span class="number">0</span>:</span><br><span class="line"> mat[k, n] = np.sqrt(<span class="number">1</span>/size)</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> mat[k, n] = np.sqrt(</span><br><span class="line"> <span class="number">2</span>/size) * np.cos(np.pi * k * (<span class="number">2</span>*n + <span class="number">1</span>) / (<span class="number">2</span>*size))</span><br><span class="line"> <span class="keyword">return</span> mat</span><br><span class="line"></span><br><span class="line"> dct_h = dct_matrix(H).to(x_dct.device)</span><br><span class="line"> dct_w = dct_matrix(W).to(x_dct.device)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 应用2D IDCT: X = D^T Y D</span></span><br><span class="line"> x_recon = torch.zeros_like(x_dct)</span><br><span class="line"> <span class="keyword">for</span> b <span class="keyword">in</span> <span class="built_in">range</span>(B):</span><br><span class="line"> <span class="keyword">for</span> c <span class="keyword">in</span> <span class="built_in">range</span>(C):</span><br><span class="line"> x_recon[b, c] = torch.mm(torch.mm(dct_h.t(), x_dct[b, c]), dct_w)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> x_recon</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">dct_compress_image</span>(<span class="params">image, compression_ratio=<span class="number">0.1</span></span>):</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">使用 DCT 压缩图像</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"> 参数:</span></span><br><span class="line"><span class="string"> - image: 输入图像 tensor (C, H, W) 或 (B, C, H, W)</span></span><br><span class="line"><span class="string"> - compression_ratio: 保留的DCT系数比例 (0-1)</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"> 返回:</span></span><br><span class="line"><span class="string"> - compressed_image: 压缩后的图像</span></span><br><span class="line"><span class="string"> - compression_stats: 压缩统计信息</span></span><br><span class="line"><span class="string"> """</span></span><br><span class="line"> <span class="keyword">if</span> <span class="built_in">len</span>(image.shape) == <span class="number">3</span>:</span><br><span class="line"> image = image.unsqueeze(<span class="number">0</span>) <span class="comment"># (C, H, W) -> (1, C, H, W)</span></span><br><span class="line"></span><br><span class="line"> B, C, H, W = image.shape</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 分块DCT (8x8块)</span></span><br><span class="line"> block_size = <span class="number">8</span></span><br><span class="line"> compressed_blocks = []</span><br><span class="line"> original_blocks = []</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 确保图像尺寸是8的倍数</span></span><br><span class="line"> pad_h = (block_size - H % block_size) % block_size</span><br><span class="line"> pad_w = (block_size - W % block_size) % block_size</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> pad_h > <span class="number">0</span> <span class="keyword">or</span> pad_w > <span class="number">0</span>:</span><br><span class="line"> image = F.pad(image, (<span class="number">0</span>, pad_w, <span class="number">0</span>, pad_h), mode=<span class="string">'reflect'</span>)</span><br><span class="line"> _, _, H, W = image.shape</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 分块处理</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>, H, block_size):</span><br><span class="line"> <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>, W, block_size):</span><br><span class="line"> <span class="comment"># 提取8x8块</span></span><br><span class="line"> block = image[:, :, i:i+block_size, j:j+block_size]</span><br><span class="line"> original_blocks.append(block.clone())</span><br><span class="line"></span><br><span class="line"> <span class="comment"># DCT变换</span></span><br><span class="line"> dct_block = dct_2d(block)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 压缩: 保留左上角的低频系数</span></span><br><span class="line"> keep_size = <span class="built_in">int</span>(block_size * block_size * compression_ratio)</span><br><span class="line"> mask = torch.zeros_like(dct_block)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 创建zigzag扫描模式保留最重要的系数</span></span><br><span class="line"> <span class="keyword">for</span> b <span class="keyword">in</span> <span class="built_in">range</span>(B):</span><br><span class="line"> <span class="keyword">for</span> c <span class="keyword">in</span> <span class="built_in">range</span>(C):</span><br><span class="line"> coeffs = dct_block[b, c].flatten()</span><br><span class="line"> <span class="comment"># 按幅值排序,保留最大的系数</span></span><br><span class="line"> _, indices = torch.topk(torch.<span class="built_in">abs</span>(coeffs), keep_size)</span><br><span class="line"> mask_flat = torch.zeros_like(coeffs)</span><br><span class="line"> mask_flat[indices] = <span class="number">1</span></span><br><span class="line"> mask[b, c] = mask_flat.reshape(block_size, block_size)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 应用压缩掩码</span></span><br><span class="line"> compressed_dct = dct_block * mask</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 逆DCT重构</span></span><br><span class="line"> reconstructed_block = idct_2d(compressed_dct)</span><br><span class="line"> compressed_blocks.append(reconstructed_block)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 重组图像</span></span><br><span class="line"> compressed_image = torch.zeros_like(image)</span><br><span class="line"> block_idx = <span class="number">0</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>, H, block_size):</span><br><span class="line"> <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>, W, block_size):</span><br><span class="line"> compressed_image[:, :, i:i+block_size, j:j +</span><br><span class="line"> block_size] = compressed_blocks[block_idx]</span><br><span class="line"> block_idx += <span class="number">1</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 移除填充</span></span><br><span class="line"> <span class="keyword">if</span> pad_h > <span class="number">0</span> <span class="keyword">or</span> pad_w > <span class="number">0</span>:</span><br><span class="line"> compressed_image = compressed_image[:, :, :H-pad_h, :W-pad_w]</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 计算压缩统计</span></span><br><span class="line"> original_size = image.numel() * <span class="number">32</span> <span class="comment"># 假设32位浮点</span></span><br><span class="line"> compressed_size = original_size * compression_ratio</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 计算PSNR</span></span><br><span class="line"> mse = F.mse_loss(compressed_image.squeeze(<span class="number">0</span>), image.squeeze(<span class="number">0</span>))</span><br><span class="line"> psnr = <span class="number">20</span> * torch.log10(<span class="number">1.0</span> / torch.sqrt(mse)) <span class="keyword">if</span> mse > <span class="number">0</span> <span class="keyword">else</span> <span class="built_in">float</span>(<span class="string">'inf'</span>)</span><br><span class="line"></span><br><span class="line"> compression_stats = {</span><br><span class="line"> <span class="string">'original_size'</span>: original_size,</span><br><span class="line"> <span class="string">'compressed_size'</span>: compressed_size,</span><br><span class="line"> <span class="string">'compression_ratio'</span>: compression_ratio,</span><br><span class="line"> <span class="string">'size_reduction'</span>: (<span class="number">1</span> - compression_ratio) * <span class="number">100</span>,</span><br><span class="line"> <span class="string">'psnr'</span>: psnr.item(),</span><br><span class="line"> <span class="string">'mse'</span>: mse.item()</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> compressed_image.squeeze(<span class="number">0</span>), compression_stats</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">visualize_compression_comparison</span>(<span class="params">original, compression_ratios, save_path=<span class="literal">None</span></span>):</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">可视化不同压缩比例的对比效果,同排显示</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line">num_ratios = <span class="built_in">len</span>(compression_ratios)</span><br><span class="line">fig, axes = plt.subplots(<span class="number">1</span>, num_ratios + <span class="number">1</span>, figsize=(<span class="number">4</span>*(num_ratios+<span class="number">1</span>), <span class="number">4</span>))</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 转换原始图像为numpy数组</span></span><br><span class="line"> <span class="keyword">if</span> <span class="built_in">isinstance</span>(original, torch.Tensor):</span><br><span class="line"> original_np = original.permute(<span class="number">1</span>, <span class="number">2</span>, <span class="number">0</span>).cpu().numpy()</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> original_np = original</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 归一化到[0,1]</span></span><br><span class="line"> original_np = np.clip(original_np, <span class="number">0</span>, <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 显示原始图像</span></span><br><span class="line"> axes[<span class="number">0</span>].imshow(original_np)</span><br><span class="line"> axes[<span class="number">0</span>].set_title(<span class="string">'original image'</span>, fontsize=<span class="number">12</span>)</span><br><span class="line"> axes[<span class="number">0</span>].axis(<span class="string">'off'</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 对每个压缩比例进行压缩并显示</span></span><br><span class="line"> <span class="keyword">for</span> i, ratio <span class="keyword">in</span> <span class="built_in">enumerate</span>(compression_ratios):</span><br><span class="line"> compressed_img, stats = dct_compress_image(original, compression_ratio=ratio)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 转换为numpy数组</span></span><br><span class="line"> <span class="keyword">if</span> <span class="built_in">isinstance</span>(compressed_img, torch.Tensor):</span><br><span class="line"> compressed_np = compressed_img.permute(<span class="number">1</span>, <span class="number">2</span>, <span class="number">0</span>).cpu().numpy()</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> compressed_np = compressed_img</span><br><span class="line"></span><br><span class="line"> compressed_np = np.clip(compressed_np, <span class="number">0</span>, <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 显示压缩图像</span></span><br><span class="line"> axes[i+<span class="number">1</span>].imshow(compressed_np)</span><br><span class="line"> axes[i+<span class="number">1</span>].set_title(<span class="string">f'compression ratio: <span class="subst">{ratio}</span>\nPSNR: <span class="subst">{stats[<span class="string">"psnr"</span>]:<span class="number">.1</span>f}</span>dB'</span>, fontsize=<span class="number">10</span>)</span><br><span class="line"> axes[i+<span class="number">1</span>].axis(<span class="string">'off'</span>)</span><br><span class="line"></span><br><span class="line"> plt.tight_layout()</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> save_path:</span><br><span class="line"> plt.savefig(save_path, dpi=<span class="number">300</span>, bbox_inches=<span class="string">'tight'</span>)</span><br><span class="line"> plt.show()</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">visualize_compression</span>(<span class="params">original, compressed, stats, save_path=<span class="literal">None</span></span>):</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">可视化压缩结果</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line">fig, axes = plt.subplots(<span class="number">1</span>, <span class="number">3</span>, figsize=(<span class="number">15</span>, <span class="number">5</span>))</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 转换为numpy数组用于显示</span></span><br><span class="line"> <span class="keyword">if</span> <span class="built_in">isinstance</span>(original, torch.Tensor):</span><br><span class="line"> original = original.permute(<span class="number">1</span>, <span class="number">2</span>, <span class="number">0</span>).cpu().numpy()</span><br><span class="line"> compressed = compressed.permute(<span class="number">1</span>, <span class="number">2</span>, <span class="number">0</span>).cpu().numpy()</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 归一化到[0,1]</span></span><br><span class="line"> original = np.clip(original, <span class="number">0</span>, <span class="number">1</span>)</span><br><span class="line"> compressed = np.clip(compressed, <span class="number">0</span>, <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 原始图像</span></span><br><span class="line"> axes[<span class="number">0</span>].imshow(original)</span><br><span class="line"> axes[<span class="number">0</span>].set_title(<span class="string">'Original Image'</span>)</span><br><span class="line"> axes[<span class="number">0</span>].axis(<span class="string">'off'</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 压缩图像</span></span><br><span class="line"> axes[<span class="number">1</span>].imshow(compressed)</span><br><span class="line"> axes[<span class="number">1</span>].set_title(</span><br><span class="line"> <span class="string">f'Compressed Image (Ratio: <span class="subst">{stats[<span class="string">"compression_ratio"</span>]}</span>)'</span>)</span><br><span class="line"> axes[<span class="number">1</span>].axis(<span class="string">'off'</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 差异图像</span></span><br><span class="line"> diff = np.<span class="built_in">abs</span>(original - compressed)</span><br><span class="line"> im = axes[<span class="number">2</span>].imshow(diff)</span><br><span class="line"> axes[<span class="number">2</span>].set_title(<span class="string">f'Difference Image (PSNR: <span class="subst">{stats[<span class="string">"psnr"</span>]:<span class="number">.2</span>f}</span>dB)'</span>)</span><br><span class="line"> axes[<span class="number">2</span>].axis(<span class="string">'off'</span>)</span><br><span class="line"> plt.colorbar(im, ax=axes[<span class="number">2</span>])</span><br><span class="line"></span><br><span class="line"> plt.tight_layout()</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> save_path:</span><br><span class="line"> plt.savefig(save_path, dpi=<span class="number">300</span>, bbox_inches=<span class="string">'tight'</span>)</span><br><span class="line"> plt.show()</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 打印统计信息</span></span><br><span class="line"> <span class="built_in">print</span>(<span class="string">f"压缩统计:"</span>)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">f"- 压缩比例: <span class="subst">{stats[<span class="string">'compression_ratio'</span>]}</span>"</span>)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">f"- 尺寸减少: <span class="subst">{stats[<span class="string">'size_reduction'</span>]:<span class="number">.1</span>f}</span>%"</span>)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">f"- PSNR: <span class="subst">{stats[<span class="string">'psnr'</span>]:<span class="number">.2</span>f}</span> dB"</span>)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">f"- MSE: <span class="subst">{stats[<span class="string">'mse'</span>]:<span class="number">.6</span>f}</span>"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 示例使用</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">demo_dct_compression</span>():</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">DCT 压缩演示</span></span><br><span class="line"><span class="string">"""</span> <span class="comment"># 创建示例图像或加载图像 # 这里创建一个简单的测试图像</span></span><br><span class="line">device = torch.device(<span class="string">'cuda'</span> <span class="keyword">if</span> torch.cuda.is_available() <span class="keyword">else</span> <span class="string">'cpu'</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 生成测试图像</span></span><br><span class="line"> test_image = torch.rand(<span class="number">3</span>, <span class="number">256</span>, <span class="number">256</span>).to(device)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 或者从文件加载图像</span></span><br><span class="line"> <span class="keyword">from</span> torchvision <span class="keyword">import</span> transforms</span><br><span class="line"> img = Image.<span class="built_in">open</span>(</span><br><span class="line"> <span class="string">'/home/wangj928/data/CelebA_HQ/Img/celeba-hq/celeba-512/000004.jpg'</span>)</span><br><span class="line"> transform = transforms.Compose([</span><br><span class="line"> transforms.Resize((<span class="number">256</span>, <span class="number">256</span>)),</span><br><span class="line"> transforms.ToTensor()</span><br><span class="line"> ])</span><br><span class="line"> test_image = transform(img).to(device)</span><br><span class="line"></span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"开始DCT压缩..."</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 测试不同的压缩比例</span></span><br><span class="line"> compression_ratios = [<span class="number">0.05</span>, <span class="number">0.1</span>, <span class="number">0.2</span>, <span class="number">0.3</span>, <span class="number">0.5</span>]</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 使用新的可视化函数显示同排对比</span></span><br><span class="line"> visualize_compression_comparison(</span><br><span class="line"> test_image,</span><br><span class="line"> compression_ratios,</span><br><span class="line"> save_path=<span class="string">'dct_compression_comparison.png'</span></span><br><span class="line"> )</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 也可以单独显示每个压缩结果的详细信息</span></span><br><span class="line"> <span class="keyword">for</span> ratio <span class="keyword">in</span> compression_ratios:</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">f"\n压缩比例: <span class="subst">{ratio}</span>"</span>)</span><br><span class="line"> compressed_img, stats = dct_compress_image(</span><br><span class="line"> test_image, compression_ratio=ratio)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 可视化结果</span></span><br><span class="line"> visualize_compression(</span><br><span class="line"> test_image,</span><br><span class="line"> compressed_img,</span><br><span class="line"> stats,</span><br><span class="line"> save_path=<span class="string">f'dct_compression_<span class="subst">{ratio}</span>.png'</span></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">demo_dct_compression()</span><br><span class="line"></span><br></pre></td></tr></table></figure></details></li><li><p>去噪<br>图像去噪是利用噪声在 DCT 图像中的分布特性(噪声一般为高频信息,DCT 变换后频谱的右下角),基本的方法就是去除 DCT 变换后图像的右下角信息,类似图像压缩。</p></li><li><p>增强<br>基本原理就是增强高频信息(与去噪相反),最简单的方法就是对高频信息乘以一个大于 1 的数。当然这样也会增强噪声。DCT 图像增强仅对细节进行了增强,图像整体亮度对比度还需结合其他方法。</p></li></ul><h3 id="DCT-在面部图像中的应用"><a href="#DCT-在面部图像中的应用" class="headerlink" title="DCT 在面部图像中的应用"></a>DCT 在面部图像中的应用</h3><p>面部图像中,DCT 能够有效压缩图像数据,同时突出低频区域的结构特征,用作人脸识别和纹理分析的特征向量。这些低频系数中包含了人脸的主要信息,而高频系数则对应于面部的纹理细节.</p><h3 id="DWT-在多分辨率纹理提取中的优势"><a href="#DWT-在多分辨率纹理提取中的优势" class="headerlink" title="DWT 在多分辨率纹理提取中的优势"></a>DWT 在多分辨率纹理提取中的优势</h3><p><a href="https://zh.wikipedia.org/wiki/%E9%9B%A2%E6%95%A3%E5%B0%8F%E6%B3%A2%E8%AE%8A%E6%8F%9B">DWT 的公式和推导</a></p><p>DWT 分解面部图像为多尺度的子频带,包括低频(LL)和三个高频细节(LH、HL、HH)分量。通过多层小波分解,DWT 能同时获取图像的粗略结构和细节纹理,实现多分辨率分析。这种方法特别适合于人脸图像的纹理提取和重建,能有效保留面部轮廓和边缘特征,同时在不同分辨率层级捕捉局部纹理变化,被广泛应用于面部超级分辨率重建和特征提取.</p><p>清晰的图像<br><img src="/images/dwt1.png" alt="dwt1"><br>Wider 数据集中的带有噪声的人脸图像<br><img src="/images/dwt2.png" alt="dwt2"></p><details><summary>代码</summary><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></pre></td><td class="code"><pre><span class="line"></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">from</span> matplotlib <span class="keyword">import</span> pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="keyword">import</span> pywt</span><br><span class="line"><span class="keyword">import</span> PIL</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> cv2</span><br><span class="line"></span><br><span class="line">img = cv2.imread(<span class="string">"/home/wangj928/data/Wider-Test/0000.png"</span>, cv2.IMREAD_GRAYSCALE)</span><br><span class="line"></span><br><span class="line">LLY,(LHY,HLY,HHY) = pywt.dwt2(img, <span class="string">'haar'</span>)</span><br><span class="line">plt.subplot(<span class="number">2</span>, <span class="number">2</span>, <span class="number">1</span>)</span><br><span class="line">plt.imshow(LLY, cmap=<span class="string">"Greys"</span>)</span><br><span class="line">plt.subplot(<span class="number">2</span>, <span class="number">2</span>, <span class="number">2</span>)</span><br><span class="line">plt.imshow(LHY, cmap=<span class="string">"Greys"</span>)</span><br><span class="line">plt.subplot(<span class="number">2</span>, <span class="number">2</span>, <span class="number">3</span>)</span><br><span class="line">plt.imshow(HLY, cmap=<span class="string">"Greys"</span>)</span><br><span class="line">plt.subplot(<span class="number">2</span>, <span class="number">2</span>, <span class="number">4</span>)</span><br><span class="line">plt.imshow(HHY, cmap=<span class="string">"Greys"</span>)</span><br><span class="line"></span><br><span class="line">plt.savefig(<span class="string">"dwt.png"</span>)</span><br></pre></td></tr></table></figure></details><h3 id="References"><a href="#References" class="headerlink" title="References"></a>References</h3><ul><li><p><a href="https://zhuanlan.zhihu.com/p/676174673">https://zhuanlan.zhihu.com/p/676174673</a></p></li><li><p><a href="https://zhuanlan.zhihu.com/p/16532542052">https://zhuanlan.zhihu.com/p/16532542052</a></p></li><li><p><a href="https://blog.csdn.net/qq_45981086/article/details/131388457">https://blog.csdn.net/qq_45981086/article/details/131388457</a></p></li></ul>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> DCT </tag>
<tag> DWT </tag>
</tags>
</entry>
<entry>
<title>null_kv cls_token</title>
<link href="/2025/09/null-kv/"/>
<url>/2025/09/null-kv/</url>
<content type="html"><![CDATA[<p>简单来说,nk 和 nv 共同组成了一个可学习的 “空”令牌(null token) 或 “哨兵”令牌(sentinel token)。这个特殊的令牌不来自任何输入,而是作为模型的一个内置参数,在每次注意力计算时被动态添加到序列的开头。</p><h3 id="初始化"><a href="#初始化" class="headerlink" title="初始化"></a>初始化</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">self.null_kv = nn.Parameter(torch.randn(<span class="number">2</span>, heads, <span class="number">1</span>, dim_head))</span><br></pre></td></tr></table></figure><ul><li>第一个维度是 2, 分别代表 key(k) 和 value(v)</li><li>1 代表这是长度为 1 的序列,即单个令牌</li></ul><h3 id="forward"><a href="#forward" class="headerlink" title="forward"></a>forward</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"></span><br><span class="line"><span class="comment"># 1. 解包成 nk (null key) 和 nv (null value)</span></span><br><span class="line">nk, nv = self.null_kv</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 复制以匹配批次大小 (batch size)</span></span><br><span class="line">nk, nv = <span class="built_in">map</span>(<span class="keyword">lambda</span> t: repeat(t, <span class="string">'h 1 d -> b h 1 d'</span>, b=x.shape[<span class="number">0</span>]), (nk, nv))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 将 nk 和 nv 拼接到真实 key 和 value 序列的开头</span></span><br><span class="line">k = torch.cat((nk, k), dim=-<span class="number">2</span>)</span><br><span class="line">v = torch.cat((nv, v), dim=-<span class="number">2</span>)</span><br></pre></td></tr></table></figure><h3 id="核心目的"><a href="#核心目的" class="headerlink" title="核心目的"></a>核心目的</h3><p>引入这样一个“空”令牌主要有两个核心目的,这让模型变得更加灵活和强大:</p><ol><li><strong>作为“信息池”或“空操作” (Information Sink / No-Op)</strong><br>想象一下,序列中的某个查询令牌(query)可能在当前上下文中找不到任何与之强相关的其他令牌。如果没有 null_kv,它仍然必须将注意力权重分配给序列中的其他项。</li></ol><ul><li><p>提供一个“无处可去”时的选择:null_kv 提供了一个“无所谓”或“以上都不是”的选项。当一个 query 不需要从序列中任何特定部分提取信息时,它可以将大部分注意力权重分配给这个“空”令牌。</p></li><li><p>充当信息“垃圾桶”:这允许模型有效地执行“空操作”(No-Operation),即选择性地忽略当前上下文,而不是被迫整合不相关的信息。这在处理包含噪声或不重要元素的序列时特别有用。</p></li></ul><ol><li><strong>作为“全局信息库” (Global Information Repository)</strong><br>由于 null_kv 是一个可学习的参数,它不依赖于任何具体输入。在整个训练过程中,模型可以学会将一些全局的、与上下文无关的“知识”或“偏置”存储在 nv (null value) 中。</li></ol><ul><li><p>可学习的全局内存:任何位置的 query 都可以通过关注 nk (null key) 来从 nv 中读取这些存储好的全局信息。</p></li><li><p>类比:你可以把它想象成一个小的、可读写的“剪贴板”或“草稿纸”。模型在上面记录了一些普遍有用的信息(比如任务类型、通用特征等),序列中的任何令牌都可以随时查阅。</p></li></ul>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> Null_kv </tag>
<tag> cls_token </tag>
</tags>
</entry>
<entry>
<title>Token-Critic</title>
<link href="/2025/09/Token-Critic/"/>
<url>/2025/09/Token-Critic/</url>
<content type="html"><![CDATA[<h3 id="作用"><a href="#作用" class="headerlink" title="作用"></a>作用</h3><p>Token-Critic 用来判断 which visual tokens belong to the original image and which were sampled by the generative transformer. 在非自回归的生成中知道哪些 tokens 需要保留哪些 tokens 需要被替换是一件比较困难的事情,所以 token-critic (一个 transformer 模型) 被提出用来解决这个问题。<br><img src="/images/token-critic.png" alt="token-critic"></p><p>Token-Critic 解决了三个关键的限制问题:</p><ol><li><p><strong>token 掩码委托给 Token-Critic 模型</strong></p><ul><li>Token-Critic 模型经过训练,能够区分哪些 token 属于真实分布,哪些不属于</li><li>它学习判断每个 visual token 的质量和真实性</li></ul></li><li><p><strong>迭代采样过程中的精确掩码</strong></p><ul><li>在每次迭代中,Token-Critic 不是简单地丢弃采样的 token,而是能够精确地识别出质量较差的 token</li><li>这使得模型能够保留高质量的生成 token,同时替换掉不符合真实分布的 token</li></ul></li><li><p><strong>改进的采样程序</strong></p><ul><li>传统方法可能会在迭代解码过程中错误地丢弃已经正确采样的 token</li><li>Token-Critic 通过精确的质量评估,避免了这种误删除,从而提升了整体生成质量</li></ul></li></ol><h3 id="Token-Critic-的结构"><a href="#Token-Critic-的结构" class="headerlink" title="Token-Critic 的结构"></a>Token-Critic 的结构</h3><p>Transformer 结构,输出的结果为每个 token 的得分,表示在根据 condition 的情况下生成的 token 的质量。</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></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.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">from</span> einops <span class="keyword">import</span> rearrange</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">exists</span>(<span class="params">val</span>):</span><br><span class="line"> <span class="keyword">return</span> val <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">None</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">SelfCritic</span>(nn.Module):</span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, net</span>):</span><br><span class="line"> <span class="built_in">super</span>().__init__()</span><br><span class="line"> self.net = net</span><br><span class="line"> self.to_pred = nn.Linear(net.dim, <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">forward_with_cond_scale</span>(<span class="params">self, x, *args, **kwargs</span>):</span><br><span class="line"> _, embeds = self.net.forward_with_cond_scale(</span><br><span class="line"> x, *args, return_embed=<span class="literal">True</span>, **kwargs)</span><br><span class="line"> <span class="keyword">return</span> self.to_pred(embeds)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">forward_with_neg_prompt</span>(<span class="params">self, x, *args, **kwargs</span>):</span><br><span class="line"> _, embeds = self.net.forward_with_neg_prompt(</span><br><span class="line"> x, *args, return_embed=<span class="literal">True</span>, **kwargs)</span><br><span class="line"> <span class="keyword">return</span> self.to_pred(embeds)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">forward</span>(<span class="params">self, x, *args, labels=<span class="literal">None</span>, **kwargs</span>):</span><br><span class="line"> _, embeds = self.net(x, *args, return_embed=<span class="literal">True</span>, **kwargs)</span><br><span class="line"> logits = self.to_pred(embeds)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> exists(labels):</span><br><span class="line"> <span class="keyword">return</span> logits</span><br><span class="line"></span><br><span class="line"> logits = rearrange(logits, <span class="string">'... 1 -> ...'</span>)</span><br><span class="line"> <span class="keyword">return</span> F.binary_cross_entropy_with_logits(logits, labels)</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> Token-Critic </tag>
</tags>
</entry>
<entry>
<title>python-@beartype</title>
<link href="/2025/09/python-beartype/"/>
<url>/2025/09/python-beartype/</url>
<content type="html"><![CDATA[<p>@beartype 是 Python 里的一个 函数/方法/类的装饰器,来自 <a href="https://github.com/beartype/beartype?utm_source=chatgpt.com">beartype 库</a>,用于 运行时类型检查。</p><h3 id="🔹-简单解释"><a href="#🔹-简单解释" class="headerlink" title="🔹 简单解释"></a>🔹 简单解释</h3><p>在 Python 里我们通常用 类型注解(type hints),例如:</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">add</span>(<span class="params">x: <span class="built_in">int</span>, y: <span class="built_in">int</span></span>) -> <span class="built_in">int</span>:</span><br><span class="line"> <span class="keyword">return</span> x + y</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>Python 本身不会强制检查类型(add(“a”, “b”) 也能跑)。<br>beartype 就是一个运行时检查工具,可以让这些类型注解 真正生效,在调用时验证输入输出是否符合注解。</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> beartype <span class="keyword">import</span> beartype</span><br><span class="line"></span><br><span class="line"><span class="meta">@beartype</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">concat</span>(<span class="params">a: <span class="built_in">str</span>, b: <span class="built_in">str</span></span>) -> <span class="built_in">str</span>:</span><br><span class="line"> <span class="keyword">return</span> a + b</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(concat(<span class="string">"hello"</span>, <span class="string">"world"</span>)) <span class="comment"># ✅ 正常</span></span><br><span class="line"><span class="built_in">print</span>(concat(<span class="string">"hello"</span>, <span class="number">123</span>)) <span class="comment"># ❌ TypeError</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="支持的功能"><a href="#支持的功能" class="headerlink" title="支持的功能"></a>支持的功能</h3><p>✅ 检查函数参数和返回值的类型</p><p>✅ 支持 List[int], Tuple[str, int], Optional[float] 等复杂注解</p><p>✅ 支持类和方法</p><p>✅ 出错时会给出清晰的报错信息</p>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> python </tag>
</tags>
</entry>
<entry>
<title>python-einops</title>
<link href="/2025/09/python-einops/"/>
<url>/2025/09/python-einops/</url>
<content type="html"><![CDATA[<h3 id="what-is-einops"><a href="#what-is-einops" class="headerlink" title="what is einops"></a>what is einops</h3><p>einops 是一个用于张量操作的 Python 库,它的核心思想是使用一种更直观、更声明性的方式来重塑、转置和执行其他多维数组操作。它的名字是 “Einstein operations” 的缩写,因为它受到爱因斯坦求和约定(Einstein summation notation)的启发。</p><h3 id="einops-的用法"><a href="#einops-的用法" class="headerlink" title="einops 的用法"></a>einops 的用法</h3><p>传统上,在 NumPy、PyTorch、TensorFlow 等库中进行张量操作,你需要使用一系列函数,比如 <code>reshape</code>, <code>transpose</code>, <code>permute</code>, <code>view</code> 等。这很容易出错,特别是当张量的维度很多时,你可能会混淆轴的顺序和大小。</p><p>einops 通过一个统一的、高可读性的表达式来解决这个问题。它的核心函数是 <code>rearrange</code>, <code>reduce</code> 和 <code>repeat</code>。</p><ol><li><p><code>rearrange</code><br>这是 einops 最常用的函数,它结合了 重塑 (reshape) 和 转置 (transpose) 的功能。它的语法非常直观:einops.rearrange(tensor, ‘… -> …’)。</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> einops</span><br><span class="line"><span class="keyword">import</span> torch</span><br><span class="line">tensor = torch.randn(<span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>)</span><br><span class="line"><span class="built_in">print</span>(einops.rearrange(tensor, <span class="string">'b c h w -> b h w c'</span>))</span><br></pre></td></tr></table></figure><p>另一个例子是,将形状为 (batch, channels, height, width) 的图像分割成不重叠的小块(patch),并展平。</p><figure class="highlight python"><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="comment"># 假设 patch 大小是 16x16</span></span><br><span class="line"><span class="built_in">print</span>(einops.rearrange(img, <span class="string">'b c (h p1) (w p2) -> b (h w) (p1 p2 c)'</span>, p1=<span class="number">16</span>, p2=<span class="number">16</span>))</span><br></pre></td></tr></table></figure></li><li><p><code>reduce</code><br>这个函数用于执行各种常见的聚合操作,比如求和、求平均、最大值、最小值等。它的语法是:einops.reduce(tensor, ‘… -> …’, ‘op’)。</p><figure class="highlight python"><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="keyword">from</span> einops <span class="keyword">import</span> reduce</span><br><span class="line">output_tensor = reduce(input_tensor, <span class="string">'b c h w -> c'</span>, <span class="string">'mean'</span>)</span><br></pre></td></tr></table></figure><p>这个表达式表示将 b, h, w 维度求平均,只保留 c 维度。</p></li><li><p><code>repeat</code><br>这个函数用于重复张量的某些维度,它的语法是:einops.repeat(tensor, ‘… -> …’, **kwargs)。</p><figure class="highlight python"><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="keyword">from</span> einops <span class="keyword">import</span> repeat</span><br><span class="line">output_tensor = repeat(img, <span class="string">'h w -> h w 3'</span>)</span><br></pre></td></tr></table></figure><p>将一个形状为 (height, width) 的灰度图像复制成 3 个通道。</p></li></ol>]]></content>
</entry>
<entry>
<title>机试考前复习</title>
<link href="/2025/08/%E6%9C%BA%E8%AF%95%E8%80%83%E5%89%8D%E5%A4%8D%E4%B9%A0/"/>
<url>/2025/08/%E6%9C%BA%E8%AF%95%E8%80%83%E5%89%8D%E5%A4%8D%E4%B9%A0/</url>
<content type="html"><<figure class="highlight c++"><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="comment">/**</span></span><br><span class="line"><span class="comment"> * struct ListNode {</span></span><br><span class="line"><span class="comment"> *int val;</span></span><br><span class="line"><span class="comment"> *struct ListNode *next;</span></span><br><span class="line"><span class="comment"> *ListNode(int x) : val(x), next(nullptr) {}</span></span><br><span class="line"><span class="comment"> * };</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><vector></span></span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * @param head ListNode类</span></span><br><span class="line"><span class="comment"> * @param k int整型</span></span><br><span class="line"><span class="comment"> * @return ListNode类</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function">ListNode* <span class="title">reverseKGroup</span><span class="params">(ListNode* head, <span class="type">int</span> k)</span> </span>{</span><br><span class="line"> <span class="comment">// write code here</span></span><br><span class="line"> vector<<span class="type">int</span>> list;</span><br><span class="line"> ListNode* node = head;</span><br><span class="line"> <span class="keyword">while</span>(node){</span><br><span class="line"> list.<span class="built_in">push_back</span>(node->val);</span><br><span class="line"> node = node->next;</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> l = <span class="number">0</span>, r = k<span class="number">-1</span>;</span><br><span class="line"> <span class="keyword">while</span>(r < list.<span class="built_in">size</span>()){</span><br><span class="line"> <span class="type">int</span> i = l, j = r;</span><br><span class="line"> <span class="keyword">while</span>(i < j){</span><br><span class="line"> <span class="type">int</span> tmp = list[i];</span><br><span class="line"> list[i] = list[j];</span><br><span class="line"> list[j] = tmp;</span><br><span class="line"> i++; j--;</span><br><span class="line"> }</span><br><span class="line"> l = l + k;</span><br><span class="line"> r = r + k;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> ListNode* dummyhead = <span class="keyword">new</span> <span class="built_in">ListNode</span>(<span class="number">0</span>);</span><br><span class="line"> ListNode* newHead = dummyhead;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">auto</span> num : list){</span><br><span class="line"> newHead->next = <span class="keyword">new</span> <span class="built_in">ListNode</span>(num);</span><br><span class="line"> newHead = newHead->next;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> dummyhead->next;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></details><h3 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h3><details><summary>快速排序</summary><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><iostream></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">100010</span>;</span><br><span class="line"><span class="type">int</span> arr[N];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">quicksort</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> r)</span></span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 递归终止情况</span></span><br><span class="line"> <span class="keyword">if</span>(l >= r) <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 分成子问题</span></span><br><span class="line"> <span class="type">int</span> i = l<span class="number">-1</span>, j = r+<span class="number">1</span>, x = arr[(l + r) >> <span class="number">1</span>];</span><br><span class="line"> <span class="keyword">while</span>(i < j){</span><br><span class="line"> <span class="keyword">do</span> i++; <span class="keyword">while</span>(arr[i] < x);</span><br><span class="line"> <span class="keyword">do</span> j--; <span class="keyword">while</span>(arr[j] > x);</span><br><span class="line"> <span class="keyword">if</span>(i < j) <span class="built_in">swap</span>(arr[i], arr[j]);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">quicksort</span>(l, j); <span class="built_in">quicksort</span>(j+<span class="number">1</span>, r);</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="type">int</span> <span class="title">main</span><span class="params">()</span></span>{</span><br><span class="line">cin >> n;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i < n; i++){</span><br><span class="line">cin >> arr[i];</span><br><span class="line">}</span><br><span class="line"> <span class="built_in">quicksort</span>(<span class="number">0</span>, n<span class="number">-1</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i < n; i++){</span><br><span class="line"> cout << arr[i] << <span class="string">" "</span>;</span><br><span class="line"> }</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><span class="line"></span><br></pre></td></tr></table></figure></details><h3 id="高精度"><a href="#高精度" class="headerlink" title="高精度"></a>高精度</h3><details><summary>高精度加法</summary><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><string></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line"></span><br><span class="line"><span class="function">vector<<span class="type">int</span>> <span class="title">add</span><span class="params">(vector<<span class="type">int</span>>& A, vector<<span class="type">int</span>>& B)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(B.<span class="built_in">size</span>() > A.<span class="built_in">size</span>()) <span class="keyword">return</span> <span class="built_in">add</span>(B, A);</span><br><span class="line"> <span class="comment">// 默认A的大小比B大</span></span><br><span class="line"> vector<<span class="type">int</span>> C;</span><br><span class="line"> <span class="type">int</span> t = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i < A.<span class="built_in">size</span>(); i++){</span><br><span class="line"> <span class="keyword">if</span>(i < B.<span class="built_in">size</span>()) t += B[i];</span><br><span class="line"> t += A[i];</span><br><span class="line"> C.<span class="built_in">push_back</span>(t % <span class="number">10</span>);</span><br><span class="line"> t /= <span class="number">10</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(t) C.<span class="built_in">push_back</span>(t);</span><br><span class="line"> <span class="keyword">return</span> C;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span>{</span><br><span class="line"> string a, b;</span><br><span class="line"> cin >> a >> b;</span><br><span class="line"> vector<<span class="type">int</span>> A;</span><br><span class="line"> vector<<span class="type">int</span>> B;</span><br><span class="line"> <span class="comment">// 倒序存入</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = a.<span class="built_in">size</span>()<span class="number">-1</span>; i >= <span class="number">0</span>; i--){</span><br><span class="line"> A.<span class="built_in">push_back</span>(a[i]-<span class="string">'0'</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = b.<span class="built_in">size</span>()<span class="number">-1</span>; i >= <span class="number">0</span>; i--){</span><br><span class="line"> B.<span class="built_in">push_back</span>(b[i]-<span class="string">'0'</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> vector<<span class="type">int</span>> C = <span class="built_in">add</span>(A, B);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = C.<span class="built_in">size</span>()<span class="number">-1</span>; i >= <span class="number">0</span>; i--){</span><br><span class="line"> cout << C[i];</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure></details><h3 id="数学问题"><a href="#数学问题" class="headerlink" title="数学问题"></a>数学问题</h3><details><summary>试除法判断质数</summary><figure class="highlight c++"><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"><span class="function"><span class="type">bool</span> <span class="title">prime</span><span class="params">(<span class="type">int</span> t)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(t < <span class="number">2</span>) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">2</span>;i <= t / i;i++)<span class="comment">//循环为了加快速度,可以只到t / i</span></span><br><span class="line"> <span class="keyword">if</span>(t % i == <span class="number">0</span>) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></details><details><summary>分解质因数</summary><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><iostream></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">is_prime</span><span class="params">(<span class="type">int</span> num)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(num < <span class="number">2</span>) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">2</span>; i <= num / i; i++){</span><br><span class="line"> <span class="keyword">if</span>(num % i == <span class="number">0</span>) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span>{</span><br><span class="line"> cin >> n;</span><br><span class="line"> <span class="type">int</span> num;</span><br><span class="line"> <span class="type">int</span> i;</span><br><span class="line"> <span class="keyword">while</span>(n--){</span><br><span class="line"> cin >> num;</span><br><span class="line"> <span class="keyword">for</span>(i = <span class="number">2</span>; i <= num / i; i++){</span><br><span class="line"> <span class="keyword">if</span>(<span class="built_in">is_prime</span>(i)){</span><br><span class="line"> <span class="type">int</span> count = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(num && num % i == <span class="number">0</span>){</span><br><span class="line"> count += <span class="number">1</span>;</span><br><span class="line"> num /= i;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(count != <span class="number">0</span>) cout << i << <span class="string">" "</span> << count << endl;</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 class="keyword">if</span>(num > <span class="number">1</span>) cout << num << <span class="string">" "</span> << <span class="number">1</span> << endl;</span><br><span class="line"> cout << 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></details><details><summary>最大公约数</summary><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><algorithm></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">gcd</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(b == <span class="number">0</span>) <span class="keyword">return</span> a;</span><br><span class="line"> <span class="keyword">else</span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">gcd</span>(b, a % b);</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="type">int</span> <span class="title">main</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="keyword">while</span>(n--){</span><br><span class="line"> <span class="type">int</span> a, b;</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &a, &b);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, <span class="built_in">gcd</span>(a, b));</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure></details><h3 id="搜索与图论"><a href="#搜索与图论" class="headerlink" title="搜索与图论"></a>搜索与图论</h3><details><summary>建图</summary><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> n;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">100010</span>;</span><br><span class="line"><span class="type">int</span> h[N], ne[N * <span class="number">2</span>], e[N * <span class="number">2</span>], idx;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">add</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span></span>{</span><br><span class="line"> e[idx] = b;</span><br><span class="line"> ne[idx] = h[a];</span><br><span class="line"> h[a] = idx++;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></details><details><summary>计算子树大小</summary><figure class="highlight c++"><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"><span class="function"><span class="type">void</span> <span class="title">dfs_sz</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> parent)</span></span>{</span><br><span class="line"> sz[u] = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = h[u]; i != <span class="number">-1</span>; i = ne[i]){</span><br><span class="line"> <span class="type">int</span> j = e[i];</span><br><span class="line"> <span class="keyword">if</span>(j != parent){</span><br><span class="line"> <span class="built_in">dfs_sz</span>(j, u);</span><br><span class="line"> sz[u] += sz[j];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></details><details><summary>图中点的层次</summary><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><algorithm></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><queue></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">100010</span>;</span><br><span class="line"><span class="type">int</span> dist[N]; <span class="comment">// dis[N]用来计算从1到n点的距离</span></span><br><span class="line"><span class="type">bool</span> st[N]; <span class="comment">//表示当前的点是否访问过</span></span><br><span class="line"><span class="type">int</span> h[N], ne[<span class="number">2</span> * N], e[<span class="number">2</span> * N], idx;</span><br><span class="line"><span class="type">int</span> n, m;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">add</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span></span>{</span><br><span class="line"> e[idx] = b; ne[idx] = h[a]; h[a] = idx++;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">bfs</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="built_in">memset</span>(dist, <span class="number">0x3f3f3f3f</span>, <span class="built_in">sizeof</span>(dist));</span><br><span class="line"> queue<<span class="type">int</span>> q;</span><br><span class="line"> q.<span class="built_in">push</span>(<span class="number">1</span>);</span><br><span class="line"> st[<span class="number">1</span>] = <span class="literal">true</span>;</span><br><span class="line"> dist[<span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span>(!q.<span class="built_in">empty</span>()){</span><br><span class="line"> <span class="type">int</span> t = q.<span class="built_in">front</span>(); q.<span class="built_in">pop</span>();</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = h[t]; i != <span class="number">-1</span>; i = ne[i]){</span><br><span class="line"> <span class="type">int</span> j = e[i];</span><br><span class="line"> <span class="keyword">if</span>(!st[j]){</span><br><span class="line"> dist[j] = dist[t] + <span class="number">1</span>;</span><br><span class="line"> q.<span class="built_in">push</span>(j);</span><br><span class="line"> st[j] = <span class="literal">true</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 class="keyword">if</span>(dist[n] > <span class="number">0x3f3f3f3f</span> / <span class="number">2</span>) cout << <span class="number">-1</span> << endl;</span><br><span class="line"> <span class="keyword">else</span> cout << dist[n] << endl;</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="type">int</span> <span class="title">main</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &n, &m);</span><br><span class="line"> <span class="built_in">memset</span>(h, <span class="number">-1</span>, <span class="keyword">sizeof</span> h);</span><br><span class="line"> <span class="comment">// 构建图</span></span><br><span class="line"> <span class="keyword">while</span>(m--){</span><br><span class="line"> <span class="type">int</span> x, y;</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &x, &y);</span><br><span class="line"> <span class="built_in">add</span>(x, y);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">bfs</span>();</span><br><span class="line">}</span><br></pre></td></tr></table></figure></details><details><summary>拓扑排序</summary><figure class="highlight c++"><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"><span class="meta">#<span class="keyword">include</span><span class="string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><algorithm></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><queue></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><vector></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">100010</span>;</span><br><span class="line"><span class="type">int</span> h[N], ne[N], e[N], idx;</span><br><span class="line"><span class="type">int</span> d[N]; <span class="comment">// 用来存储入度</span></span><br><span class="line">queue<<span class="type">int</span>> q;</span><br><span class="line">vector<<span class="type">int</span>> path;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">add</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span></span>{</span><br><span class="line"> e[idx] = b, ne[idx] = h[a], h[a] = idx++;</span><br><span class="line"> d[b] += <span class="number">1</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">topsort</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">while</span>(!q.<span class="built_in">empty</span>()){</span><br><span class="line"> <span class="type">int</span> t = q.<span class="built_in">front</span>(); q.<span class="built_in">pop</span>();</span><br><span class="line"> path.<span class="built_in">push_back</span>(t);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = h[t]; i != <span class="number">-1</span>; i = ne[i]){</span><br><span class="line"> <span class="type">int</span> j = e[i];</span><br><span class="line"> d[j] --;</span><br><span class="line"> <span class="keyword">if</span>(d[j] == <span class="number">0</span>){</span><br><span class="line"> q.<span class="built_in">push</span>(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><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span>{</span><br><span class="line"> cin >> n >> m;</span><br><span class="line"> <span class="type">int</span> a, b;</span><br><span class="line"> <span class="built_in">memset</span>(h, <span class="number">-1</span>, <span class="keyword">sizeof</span> h);</span><br><span class="line"> <span class="keyword">while</span>(m--){</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &a, &b);</span><br><span class="line"> <span class="built_in">add</span>(a, b);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 将所有入度为0的节点加入到队列中</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= n; i++){</span><br><span class="line"> <span class="keyword">if</span>(d[i] == <span class="number">0</span>){</span><br><span class="line"> q.<span class="built_in">push</span>(i);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">topsort</span>();</span><br><span class="line"> <span class="keyword">if</span>(path.<span class="built_in">size</span>() == n){</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">auto</span> num : path){</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d "</span>, num);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">""</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="built_in">printf</span>(<span class="string">"-1"</span>);</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure></details><details><summary>迪杰斯特拉求最短路</summary><figure class="highlight c++"><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"><span class="meta">#<span class="keyword">include</span><span class="string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><algorithm></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><queue></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><vector></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">1e6</span> + <span class="number">10</span>;</span><br><span class="line"><span class="keyword">typedef</span> pair<<span class="type">int</span>, <span class="type">int</span>> PII; <span class="comment">// 存储从节点 1 到当前点的最小距离</span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> h[N], e[N], ne[N], w[N], idx;</span><br><span class="line"><span class="type">int</span> dist[N];</span><br><span class="line"><span class="type">bool</span> st[N];</span><br><span class="line"><span class="type">int</span> n, m;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">add</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b, <span class="type">int</span> c)</span></span>{</span><br><span class="line"> e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dijkstra</span><span class="params">()</span></span>{</span><br><span class="line"> priority_queue<PII, vector<PII>, greater<PII>> q;</span><br><span class="line"> <span class="built_in">memset</span>(dist, <span class="number">0x3f</span>, <span class="keyword">sizeof</span> dist);</span><br><span class="line"> dist[<span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line"> q.<span class="built_in">push</span>({<span class="number">0</span>, <span class="number">1</span>}); <span class="comment">// 注意:这里 `dist[1]` 的值已经是 `0`</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span>(!q.<span class="built_in">empty</span>()){</span><br><span class="line"> <span class="keyword">auto</span> t = q.<span class="built_in">top</span>();</span><br><span class="line"> <span class="type">int</span> distance = t.first, ver = t.second;</span><br><span class="line"> q.<span class="built_in">pop</span>();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span>(st[ver]) <span class="keyword">continue</span>;</span><br><span class="line"> st[ver] = <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = h[ver]; i != <span class="number">-1</span>; i = ne[i]){</span><br><span class="line"> <span class="type">int</span> j = e[i];</span><br><span class="line"> <span class="keyword">if</span>(dist[j] > dist[ver] + w[i]){</span><br><span class="line"> dist[j] = dist[ver] + w[i];</span><br><span class="line"> q.<span class="built_in">push</span>({dist[j], 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><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="built_in">memset</span>(h, <span class="number">-1</span>, <span class="keyword">sizeof</span> h);</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &n, &m);</span><br><span class="line"> <span class="keyword">while</span>(m--){</span><br><span class="line"> <span class="type">int</span> a, b, c;</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d%d"</span>, &a, &b, &c);</span><br><span class="line"> <span class="built_in">add</span>(a, b, c);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">dijkstra</span>(); <span class="comment">// 修复:缺少 Dijkstra 调用</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span>(dist[n] == <span class="number">0x3f3f3f3f</span>) <span class="built_in">puts</span>(<span class="string">"-1"</span>); <span class="comment">// 修复:正确的无穷大判断</span></span><br><span class="line"> <span class="keyword">else</span> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, dist[n]);</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></details><details><summary>prim求最小生成树</summary>https://www.acwing.com/solution/content/38312/<figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><algorithm></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">510</span>;</span><br><span class="line"><span class="type">int</span> g[N][N];<span class="comment">//存储图</span></span><br><span class="line"><span class="type">int</span> dt[N];<span class="comment">//存储各个节点到生成树的距离</span></span><br><span class="line"><span class="type">int</span> st[N];<span class="comment">//节点是否被加入到生成树中</span></span><br><span class="line"><span class="type">int</span> pre[N];<span class="comment">//节点的前去节点</span></span><br><span class="line"><span class="type">int</span> n, m;<span class="comment">//n 个节点,m 条边</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">prim</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="built_in">memset</span>(dt,<span class="number">0x3f</span>, <span class="built_in">sizeof</span>(dt));<span class="comment">//初始化距离数组为一个很大的数(10亿左右)</span></span><br><span class="line"> <span class="type">int</span> res= <span class="number">0</span>;</span><br><span class="line"> dt[<span class="number">1</span>] = <span class="number">0</span>;<span class="comment">//从 1 号节点开始生成</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i < n; i++)<span class="comment">//每次循环选出一个点加入到生成树</span></span><br><span class="line"> {</span><br><span class="line"> <span class="type">int</span> t = <span class="number">-1</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">1</span>; j <= n; j++)<span class="comment">//每个节点一次判断</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span>(!st[j] && (t == <span class="number">-1</span> || dt[j] < dt[t]))<span class="comment">//如果没有在树中,且到树的距离最短,则选择该点</span></span><br><span class="line"> t = j;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//2022.6.1 发现测试用例加强后,需要判断孤立点了</span></span><br><span class="line"> <span class="comment">//如果孤立点,直返输出不能,然后退出</span></span><br><span class="line"> <span class="keyword">if</span>(dt[t] == <span class="number">0x3f3f3f3f</span>) {</span><br><span class="line"> cout << <span class="string">"impossible"</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"> st[t] = <span class="number">1</span>;<span class="comment">// 选择该点</span></span><br><span class="line"> res += dt[t];</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= n; i++)<span class="comment">//更新生成树外的点到生成树的距离</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span>(dt[i] > g[t][i] && !st[i])<span class="comment">//从 t 到节点 i 的距离小于原来距离,则更新。</span></span><br><span class="line"> {</span><br><span class="line"> dt[i] = g[t][i];<span class="comment">//更新距离</span></span><br><span class="line"> pre[i] = t;<span class="comment">//从 t 到 i 的距离更短,i 的前驱变为 t.</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"> cout << res;</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="type">void</span> <span class="title">getPath</span><span class="params">()</span><span class="comment">//输出各个边</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = n; i > <span class="number">1</span>; i--)<span class="comment">//n 个节点,所以有 n-1 条边。</span></span><br><span class="line"></span><br><span class="line"> {</span><br><span class="line"> cout << i <<<span class="string">" "</span> << pre[i] << <span class="string">" "</span><< endl;<span class="comment">// i 是节点编号,pre[i] 是 i 节点的前驱节点。他们构成一条边。</span></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="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="built_in">memset</span>(g, <span class="number">0x3f</span>, <span class="built_in">sizeof</span>(g));<span class="comment">//各个点之间的距离初始化成很大的数</span></span><br><span class="line"> cin >> n >> m;<span class="comment">//输入节点数和边数</span></span><br><span class="line"> <span class="keyword">while</span>(m --)</span><br><span class="line"> {</span><br><span class="line"> <span class="type">int</span> a, b, w;</span><br><span class="line"> cin >> a >> b >> w;<span class="comment">//输出边的两个顶点和权重</span></span><br><span class="line"> g[a][b] = g[b][a] = <span class="built_in">min</span>(g[a][b],w);<span class="comment">//存储权重</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">prim</span>();<span class="comment">//求最下生成树</span></span><br><span class="line"> <span class="comment">//getPath();//输出路径</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></details><h3 id="动态规划"><a href="#动态规划" class="headerlink" title="动态规划"></a>动态规划</h3><details><summary>最小路径和</summary>[leetcode 64 题](https://leetcode.cn/problems/minimum-path-sum/description/?envType=problem-list-v2&envId=dynamic-programming)<figure class="highlight c++"><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"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">minPathSum</span><span class="params">(vector<vector<<span class="type">int</span>>>& grid)</span> </span>{</span><br><span class="line"> <span class="type">int</span> n = grid.<span class="built_in">size</span>();</span><br><span class="line"> <span class="type">int</span> m = grid[<span class="number">0</span>].<span class="built_in">size</span>();</span><br><span class="line"> <span class="keyword">if</span>(n <= <span class="number">1</span> && m <= <span class="number">1</span>) <span class="keyword">return</span> grid[<span class="number">0</span>][<span class="number">0</span>];</span><br><span class="line"> <span class="comment">// f[i][j] 表示走到 (i, j) 的最小路径</span></span><br><span class="line"> vector<vector<<span class="type">int</span>>> <span class="built_in">f</span>(n, <span class="built_in">vector</span><<span class="type">int</span>>(m, <span class="number">0x3f3f3f3f</span>));</span><br><span class="line"> f[<span class="number">0</span>][<span class="number">0</span>] = grid[<span class="number">0</span>][<span class="number">0</span>];</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i < m; i++) f[<span class="number">0</span>][i] = f[<span class="number">0</span>][i<span class="number">-1</span>] + grid[<span class="number">0</span>][i];</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i < n; i++) f[i][<span class="number">0</span>] = f[i<span class="number">-1</span>][<span class="number">0</span>] + grid[i][<span class="number">0</span>];</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i < n; i++){</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">1</span>; j < m; j++){</span><br><span class="line"> f[i][j] = <span class="built_in">min</span>(f[i<span class="number">-1</span>][j] + grid[i][j], f[i][j]);</span><br><span class="line"> f[i][j] = <span class="built_in">min</span>(f[i][j<span class="number">-1</span>] + grid[i][j], f[i][j]);</span><br><span class="line"> <span class="comment">// cout << i << " " << j << " " << f[i][j] << endl;</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> f[n<span class="number">-1</span>][m<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><br></pre></td></tr></table></figure></details>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> 应试 </tag>
</tags>
</entry>
<entry>
<title>特征融合的问题</title>
<link href="/2025/08/%E7%89%B9%E5%BE%81%E8%9E%8D%E5%90%88%E7%9A%84%E9%97%AE%E9%A2%98/"/>
<url>/2025/08/%E7%89%B9%E5%BE%81%E8%9E%8D%E5%90%88%E7%9A%84%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<h3 id="可能原因"><a href="#可能原因" class="headerlink" title="可能原因"></a>可能原因</h3><ol><li><strong>特征融合方式不平滑</strong><ul><li>如果用的是简单的 <strong>add 或 cat → conv</strong>,不同来源的特征分布差别很大,容易在局部出现爆点。</li><li>特别是人脸区域,分布差异会被放大,导致 decoder 输出异常颜色。 (如图鼻子处的橙色 spot)[lq, gt, decoder1, fuse, decoder2]<br><img src="/images/特征融合.png" alt="特征融合不平滑"></li></ul></li><li><strong>特征未完全对齐</strong><ul><li>特征不严格对齐,就会在融合时留下边界/点状伪影。</li><li>简单的 bilinear 插值可能不足以保证平滑过渡。</li></ul></li><li><strong>数值范围不匹配</strong><ul><li>不同的 feature 可能处于不同的数值范围。</li><li>如果没有做 <strong>归一化 (LayerNorm/InstanceNorm)</strong>,直接相加/拼接就会出现色彩点。</li></ul></li><li><strong>过度依赖外部特征 (shortcut)</strong><ul><li>Decoder 可能在某些 spatial 位置几乎完全依赖外部特征,导致颜色直接来自教师分布 → 出现随机偏色点。</li></ul></li></ol><hr><h3 id="✅-改进建议(减少颜色点伪影)"><a href="#✅-改进建议(减少颜色点伪影)" class="headerlink" title="✅ 改进建议(减少颜色点伪影)"></a>✅ 改进建议(减少颜色点伪影)</h3><ol><li><strong>融合前加归一化</strong><ul><li>做 <code>LayerNorm</code> 或 <code>InstanceNorm</code>。</li><li>保证不同来源特征在数值范围和统计量上一致。</li></ul></li><li><strong>改进融合模块</strong><ul><li>用 <strong>CrossAttention</strong> 替代简单的 cat/add:<ul><li>Query = 学生 decoder 当前特征</li><li>Key/Value = 对齐后的外部特征</li><li>好处:decoder 自己“选择”要不要用外部特征,而不是被硬注入。</li></ul></li><li>或者轻量化尝试 <strong>LoRA CrossAttn</strong>(只训练小参数),避免大模型过拟合。</li></ul></li><li><strong>特征 Dropout</strong><ul><li>训练时随机丢掉一部分外部特征通道或 spatial patch。</li><li>防止 decoder 过度依赖外部特征,减少 shortcut 伪影。</li></ul></li><li><strong>损失函数中加 smooth/TV loss</strong><ul><li>在图像层面约束颜色平滑性,抑制单点爆炸的颜色。</li></ul></li></ol><hr>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> 特征融合 </tag>
</tags>
</entry>
<entry>
<title>MoE (Mixture of Experts) 混合专家</title>
<link href="/2025/08/MoE/"/>
<url>/2025/08/MoE/</url>
<content type="html"><![CDATA[<h3 id="🔹-一、MoE-的核心概念"><a href="#🔹-一、MoE-的核心概念" class="headerlink" title="🔹 一、MoE 的核心概念"></a>🔹 一、MoE 的核心概念</h3><p><strong>Mixture of Experts(专家混合模型)</strong> 是一类模块化神经网络结构,其核心思想是:</p><ol><li><strong>模型拆解</strong>:把一个大模型拆解为多个专家(expert)子网络</li><li><strong>稀疏激活</strong>:每个输入样本只会激活其中一部分专家(而不是所有专家)</li><li><strong>智能路由</strong>:由一个门控网络(gating network)决定该输入要用哪些专家</li><li><strong>结果融合</strong>:最终的输出由这些专家的结果加权组合而成</li></ol><blockquote><p>💡 <strong>直观类比</strong>:就像一个公司里有很多专家,遇到不同的问题,先由秘书(gating network)判断该找谁,最后综合专家意见得到结果。</p></blockquote><hr><h3 id="🔹-二、MoE-的基本结构"><a href="#🔹-二、MoE-的基本结构" class="headerlink" title="🔹 二、MoE 的基本结构"></a>🔹 二、MoE 的基本结构</h3><h4 id="1-专家网络-Experts"><a href="#1-专家网络-Experts" class="headerlink" title="1. 专家网络 (Experts)"></a>1. 专家网络 (Experts)</h4><ul><li><strong>结构</strong>:通常是一些小型的前馈网络(Feed-Forward Network, FFN)</li><li><strong>职责</strong>:每个专家负责处理不同类型的输入特征</li><li><strong>规模</strong>:可以有几十到上百个专家,但每次输入通常只激活其中少数(如 Top-1 或 Top-2)</li></ul><h4 id="2-门控网络-Gating-Network"><a href="#2-门控网络-Gating-Network" class="headerlink" title="2. 门控网络 (Gating Network)"></a>2. 门控网络 (Gating Network)</h4><ul><li><strong>功能</strong>:接收输入后,输出一个分布(类似 softmax 权重),表示每个专家的重要性</li><li><strong>常见策略</strong>:<ul><li><strong>Soft gating</strong>:对所有专家分配权重(计算量大)</li><li><strong>Sparse gating</strong>:只选择前 k 个专家(Top-k),大大降低计算量(这也是现代 MoE 的常用方法)</li></ul></li></ul><h4 id="3-组合机制-Aggregation"><a href="#3-组合机制-Aggregation" class="headerlink" title="3. 组合机制 (Aggregation)"></a>3. 组合机制 (Aggregation)</h4><ul><li><strong>目标</strong>:将选中的专家输出结果加权求和,得到最终的输出</li></ul><h3 id="🔹-三、MoE-的优势"><a href="#🔹-三、MoE-的优势" class="headerlink" title="🔹 三、MoE 的优势"></a>🔹 三、MoE 的优势</h3><p><strong>参数规模大,但计算开销小</strong></p><ul><li>可以有上百亿参数(分布在各个专家里),但每次只用到少量专家,所以计算成本接近小模型。</li></ul><p><strong>提高模型表达能力</strong></p><ul><li>不同专家可以学习不同的数据模式,增强模型的多样性和泛化能力。</li></ul><p><strong>可扩展性好</strong></p><ul><li>可以通过增加专家数量来提升模型容量,而不显著增加推理时的计算量。</li></ul><h3 id="🔹-四、MoE-的挑战"><a href="#🔹-四、MoE-的挑战" class="headerlink" title="🔹 四、MoE 的挑战"></a>🔹 四、MoE 的挑战</h3><ol><li><p><strong>负载均衡 (Load Balancing)</strong>: 门控网络可能会偏好某几个专家,导致部分专家很少被训练到。解决方法:引入 负载均衡损失函数(如 Google 的 Switch Transformer 提出的正则化项)。</p></li><li><p><strong>通信开销大 (在分布式训练中)</strong>: 因为不同专家可能在不同 GPU 上,输入需要路由到对应的 GPU,容易造成通信瓶颈。</p></li><li><p><strong>训练稳定性</strong>: 门控网络训练不当时,可能出现梯度消失或专家不收敛的问题。</p></li></ol><h3 id="🔹-五、MoE-的代表性工作"><a href="#🔹-五、MoE-的代表性工作" class="headerlink" title="🔹 五、MoE 的代表性工作"></a>🔹 五、MoE 的代表性工作</h3><ol><li><p>Shazeer et al. (2017), “Outrageously Large Neural Networks”<br>提出最早的大规模稀疏 MoE 模型。</p></li><li><p>Switch Transformer (Google, 2021)<br>使用 Top-1 门控(每个输入只选一个专家),极大提升了训练效率。 证明了稀疏专家机制可以扩展到万亿参数级别。</p></li><li><p>GLaM (Google, 2021) Generalist Language Model,基于 MoE 的大规模语言模型,计算量比 GPT-3 少,但效果更好。</p></li><li><p>DeepSpeed MoE (Microsoft) 工程优化的 MoE 框架,广泛用于分布式训练。</p></li></ol><h3 id="🔹-六、学习资源推荐"><a href="#🔹-六、学习资源推荐" class="headerlink" title="🔹 六、学习资源推荐"></a>🔹 六、学习资源推荐</h3><p>🌐 工程框架</p><p><a href="https://github.com/deepspeedai/DeepSpeed?utm_source=chatgpt.com">DeepSpeed MoE (Microsoft)</a></p><p><a href="https://github.com/facebookresearch/fairseq?utm_source=chatgpt.com">Fairseq MoE (Meta AI)</a></p><p><a href="https://github.com/tensorflow/mesh?utm_source=chatgpt.com">TensorFlow MoE</a></p><h3 id="✅-总结一下:"><a href="#✅-总结一下:" class="headerlink" title="✅ 总结一下:"></a>✅ 总结一下:</h3><p>MoE 是一种 稀疏激活的大模型架构,通过专家分工+门控选择,大幅提升模型容量和泛化能力,同时保持计算开销可控。它在 大语言模型(LLM)和扩展到万亿参数级别的训练中应用非常广泛。</p>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> MoE </tag>
</tags>
</entry>
<entry>
<title>《Chole》(克洛伊)</title>
<link href="/2025/08/Chloe_%E5%85%8B%E6%B4%9B%E4%BC%8A/"/>
<url>/2025/08/Chloe_%E5%85%8B%E6%B4%9B%E4%BC%8A/</url>
<content type="html"><![CDATA[<h2 id="基本信息"><a href="#基本信息" class="headerlink" title="基本信息"></a>基本信息</h2><div class="movie-info-container"><div class="movie-details"> <ul> <li><strong>导演</strong>:阿托姆·伊戈扬</li> <li><strong>主演</strong>:朱丽安·摩尔 / 阿曼达·塞弗里德</li> <li><strong>上映时间</strong>:2009 年</li> <li><strong>观看时间</strong>:2025 年 8 月 </li> <li><strong>评分</strong> ⭐⭐⭐⭐☆ (4/5)</li> </ul></div><div class="movie-poster"><img src="/images/克洛伊.png" alt="克洛伊海报" width="250" height="370"></div></div><p>是一个剧情上很 drama,但是情绪感受上不 drama 的片子,因为两个女演员都演的很自然,剧情上跌宕起伏,但是情绪上顺利成章。有很多镜头上的语言表达,暗示两人的情愫和暧昧,很克制也很冷淡,在最后也有一个小高潮,所以看完心情舒畅,不是从头克制到尾连观众一起难受的影片。</p><p>我觉得应该是拍少女的情爱和女性的中年危机角度比较新颖和不错的片子。</p><p>ps: 朱丽安·摩尔不愧是大满贯,演的相当之好,看完激情澎湃的又去看了她的其他作品。推荐!</p><style>.movie-info-container { display: flex; gap: 2rem; align-items: flex-start; margin: 1.5rem 0;}.movie-details { flex: 2;}.movie-poster { flex: 1; text-align: center;}.movie-poster img { border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); object-fit: cover; /* 保持比例,裁剪溢出部分 */}@media (max-width: 768px) { .movie-info-container { flex-direction: column; gap: 1rem; } .movie-poster img { width: 200px !important; height: 300px !important; }}</style><hr><p><em>本文为个人观影感受,仅供参考。</em></p>]]></content>
<categories>
<category> 影音书评 </category>
<category> 电影 </category>
</categories>
<tags>
<tag> 电影 </tag>
<tag> 悬疑 </tag>
<tag> 同性 </tag>
<tag> 家庭 </tag>
</tags>
</entry>
<entry>
<title>How to train a LQ Encoder</title>
<link href="/2025/08/How-to-train-a-LQ-Encoder-%E5%A6%82%E4%BD%95%E8%AE%AD%E7%BB%83%E4%B8%80%E4%B8%AALQ-Encoder/"/>
<url>/2025/08/How-to-train-a-LQ-Encoder-%E5%A6%82%E4%BD%95%E8%AE%AD%E7%BB%83%E4%B8%80%E4%B8%AALQ-Encoder/</url>
<content type="html"><![CDATA[<ul><li><p>情况一:LQ = Low-Quality (低质量)</p><ul><li><p>目标:训练一个编码器(Encoder),使其能够从低质量、有损、模糊或带噪点的输入(如低分辨率图片、压缩过的音频)中提取出稳定、鲁棒的核心特征。</p></li><li><p>应用场景:图像超分辨率 (Super-Resolution)、图像修复 (Image Restoration)、人脸增强 (Face Enhancement)、去噪 (Denoising) 等。</p></li></ul></li><li><p>案例 1: 《SUPIR》<br><img src="/images/supir.png" alt="SUPIR"><br>在 SUPIR 中,为了确保低质量图像能够被正确映射到与预训练 SDXL 相同的潜在空间,作者提出了训练一个抗退化编码器(Degradation-Robust Encoder)。</p><p>SDXL 的扩散生成过程在潜在空间中进行。图像首先通过预训练的编码器映射到潜在空间。为了有效利用预训练的 SDXL,低质量图像 <script type="math/tex">x_{LQ}</script> 也应该被映射到相同的潜在空间。由于原始编码器没有在低质量图像上训练,直接使用它进行编码会影响模型对低质量图像内容的判断,进而产生误导性的人工制品作为图像内容。训练一个抗退化编码器 <script type="math/tex">\mathcal{E}_{dr}</script>,通过最小化损失函数使其对退化具有鲁棒性:</p><script type="math/tex; mode=display">\mathcal{L}_c = ||\mathcal{D}(\mathcal{E}_{dr}(x_{LQ})) - \mathcal{D}(\mathcal{E}_{dr}(x_{GT}))||_2^2</script><p>其中:</p><ul><li>$\mathcal{E}_{dr}$ 是待微调的抗退化编码器</li><li>$\mathcal{D}$ 是固定的解码器</li><li>$x_{GT}$ 是真实图像(ground truth)</li></ul><p>这样训练出的编码器能够将低质量图像编码到与高质量图像相同的潜在空间中,确保后续扩散过程的有效性。</p></li><li><p>案例 2: 《PASD》<br><img src="/images/PASD.png" alt="PASD"></p><p>真实世界的低质量图像通常受到复杂且未知的降解影响。因此,作者采用一个降解去除模块来减少降解的影响,并从低质量图像中提取“干净”的特征以控制扩散过程。如图 2 所示,作者采用金字塔网络来提取输入低质量图像的 1/2、1/4 和 1/8 缩放分辨率的多尺度特征图。直观地,这些特征可以用于尽可能接近地逼近相应尺度的高质量图像,以便后续的扩散模块可以专注于恢复真实的图像细节,减轻区分图像降解的负担。因此,作者通过采用卷积层“toRGB”将每个单尺度特征图转换为高质量 RGB 图像空间,引入中间监督。作者在每个分辨率尺度上应用 L1 损失,以强制该尺度的重建接近于高质量图像的相应尺度:</p><script type="math/tex; mode=display">L_{DR} = \sum_{s} ||I_{s}^{HQ} - I_{s}^{ISR}||_1</script><p>其中:</p><ul><li>$I_{s}^{HQ}$ 是尺度 s 上的高质量真实值</li><li>$I_{s}^{ISR}$ 是尺度 s 上的 ISR 输出</li></ul></li><li><p>案例 3: 《SeeSR》<br><img src="/images/Seesr.png" alt="Seesr"></p><p>DAPE 是从预训练的标签模型(如 RAM)微调而来的。如图 2(a) 所示,高分辨率图像 $x$ 通过一个冻结的标签模型输出表示嵌入 $f^{HR}$ 和 logits 嵌入 $g^{HR}$,作为监督 DAPE 训练的锚点。低分辨率图像 $y$ 是通过对 $x$ 应用随机降级获得的,它们被输入到可训练的图像编码器和标签头中。为了使 DAPE 对图像降级具有鲁棒性,作者强制低分辨率分支的表示嵌入和 logits 嵌入接近高分辨率分支的嵌入。训练目标如下:</p><script type="math/tex; mode=display">\mathcal{L}_{DAPE} = \mathcal{L}_{f}^{HR} + \lambda \mathcal{L}_{g}^{HR}</script><p>其中 $\lambda$ 是平衡参数,$f^{HR}$ 和 $g^{HR}$ 是低分辨率分支的表示嵌入和 logits 嵌入。<script type="math/tex">\mathcal{L}_{f}</script> 是均方误差(MSE)损失,而 <script type="math/tex">\mathcal{L}_{g}</script> 是交叉熵损失。通过对齐低分辨率和高分辨率分支的输出,DAPE 学会从损坏的图像输入中预测高质量的语义提示。</p></li><li><p>案例 4: 《HeroSR》<br><img src="/images/HeroSR.png" alt="HeroSR"><br>前三种都是有监督,HeroSR 是无监督的方式,采用端到端的优化,让 VAE encoder 和 Unet 注入的 LoRA 层去调制。</p></li><li><p>情况二:LQ = Learned Quantization (学习型量化)</p><ul><li><p>目标:训练一个编码器,其输出的连续特征向量会被一个量化层(Quantization Layer)映射到一组离散的、有限的“码本” (Codebook) 向量上。</p></li><li><p>应用场景:高效的数据压缩、高质量的生成模型(如 VQ-VAE, VQ-GAN)、学习离散化的数据表征。</p></li></ul></li><li><p>案例 1: 《CodeFormer》<br><img src="/images/CodeFormer.png" alt="CodeFormer"><br>借助训练好的包含 HQ 图像信息的码本,端到端的优化 LQ Encoder。</p></li><li><p>案例 2: 《DAEFR》<br><img src="/images/DAEFR_method.png" alt="DAEFR"></p><ol><li><p><strong>第一阶段</strong> 使用 VQ-VAE 预训练训练:</p><ul><li>LQ Encoder → LQ Codebook → LQ Decoder</li><li>目标:重建 LQ 图像 $x_{LQ}$,得到良好的潜在特征表示。</li></ul></li><li><p><strong>第二阶段</strong> 专注与 HQ 表示的关联:</p><ul><li>让 LQ Encoder 学习到能预测到 HQ Encoder 的特征边际。</li></ul></li><li><p><strong>第三阶段</strong>:</p><ul><li>LQ Encoder 提供输入特征,经过注意力加 Transformer,预测 HQ 的 code index,最终用 HQ Decoder 重建 HQ 图像。</li></ul></li></ol></li></ul><h2 id="References"><a href="#References" class="headerlink" title="References"></a>References</h2><ul><li><a href="https://arxiv.org/pdf/2401.13627">SUPIR</a></li><li><a href="https://arxiv.org/abs/2308.14469">PASD</a></li><li><a href="https://arxiv.org/pdf/2311.16518">SeeSR</a></li><li><a href="https://arxiv.org/pdf/2412.07152">HeroSR</a></li><li><a href="https://arxiv.org/abs/2206.11253">CodeFormer</a></li><li><a href="https://github.com/LIAGM/DAEFR">DAEFR</a></li></ul>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> LQ Encoder </tag>
<tag> Computer Vision </tag>
</tags>
</entry>
<entry>
<title>Feature-wise Linear Modulation (FiLM)</title>
<link href="/2025/08/FiLM-Feature-wise-Linear-Modulation/"/>
<url>/2025/08/FiLM-Feature-wise-Linear-Modulation/</url>
<content type="html"><![CDATA[<h1 id="FiLM-特征层面线性调制-Feature-wise-Linear-Modulation"><a href="#FiLM-特征层面线性调制-Feature-wise-Linear-Modulation" class="headerlink" title="FiLM: 特征层面线性调制 (Feature-wise Linear Modulation)"></a>FiLM: 特征层面线性调制 (Feature-wise Linear Modulation)</h1><p>在深度学习领域,我们经常需要模型根据某些外部条件来调整自身的行为。例如,在图像生成任务中,我们可能希望根据一段文字描述(“一只正在草地上奔跑的金色小狗”)来生成相应的图片;在视觉问答(VQA)中,模型需要根据提出的问题来分析图像并给出答案。</p><p>如何将这些“条件信息”高效地注入到神经网络中,一直是一个核心问题。一种朴素的方法是在输入层将条件向量与主输入数据拼接(Concatenate)在一起,但这常常导致条件信息在网络深层传递时被稀释或遗忘。</p><p>为了解决这个问题,FiLM (Feature-wise Linear Modulation) 应运而生。它是一种思想巧妙且高效的技术,其核心在于:不直接将条件作为数据输入,而是用它来“调制”或“操纵”网络中间层的特征,这种调整通过一个非常简单的仿射变换(affine transformation)来实现,也就是对特征进行缩放 (scale) 和偏移 (shift)。</p><h2 id="工作原理"><a href="#工作原理" class="headerlink" title="工作原理"></a>工作原理</h2><p>FiLM 层的基本数学公式是:</p><script type="math/tex; mode=display">FiLM(x) = \gamma \cdot x + \beta</script><p>其中,$x$ 是输入特征,$\gamma$ 和 $\beta$ 是可学习的参数, 由外部的条件信息(比如 文本嵌入、类别标签、时间步等)通过一个小网络预测得到。FiLM 的操作不包含归一化步骤。它直接在原始特征上进行缩放和偏移,目的是让条件信息来“操纵”或“调整”这些特征。</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></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.nn <span class="keyword">as</span> nn</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">FiLMLayer</span>(nn.Module):</span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, channels, condition_dim</span>):</span><br><span class="line"> <span class="built_in">super</span>().__init__()</span><br><span class="line"> <span class="comment"># 条件网络,将条件向量映射到 gamma 和 beta</span></span><br><span class="line"> self.cond_net = nn.Linear(condition_dim, channels * <span class="number">2</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">forward</span>(<span class="params">self, x, condition</span>):</span><br><span class="line"> <span class="comment"># x 的形状: [B, C, H, W] (以CNN为例)</span></span><br><span class="line"> <span class="comment"># condition 的形状: [B, D]</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 1. 通过条件网络生成 gamma 和 beta</span></span><br><span class="line"> gamma_beta = self.cond_net(condition) <span class="comment"># [B, C*2]</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 2. 将输出切分为 gamma 和 beta</span></span><br><span class="line"> gamma, beta = torch.chunk(gamma_beta, <span class="number">2</span>, dim=<span class="number">1</span>) <span class="comment"># 均为 [B, C]</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 3. 调整形状以匹配特征 x</span></span><br><span class="line"> <span class="comment"># unsqueeze 用于增加维度以进行广播 (broadcast)</span></span><br><span class="line"> gamma = gamma.unsqueeze(<span class="number">2</span>).unsqueeze(<span class="number">3</span>) <span class="comment"># [B, C, 1, 1]</span></span><br><span class="line"> beta = beta.unsqueeze(<span class="number">2</span>).unsqueeze(<span class="number">3</span>) <span class="comment"># [B, C, 1, 1]</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 4. 应用 FiLM 调制</span></span><br><span class="line"> <span class="keyword">return</span> x * gamma + beta</span><br></pre></td></tr></table></figure><h2 id="FiLM-vs-AdaLN"><a href="#FiLM-vs-AdaLN" class="headerlink" title="FiLM vs AdaLN"></a>FiLM vs AdaLN</h2><p>FiLM 经常与 AdaLN (Adaptive Layer Normalization) 相提并论。它们的核心思想相似(都是动态生成仿射变换参数),但有一个关键区别:</p><ul><li><p>FiLM: 直接对特征进行仿射变换 γx + β。</p></li><li><p>AdaLN: 先对特征进行归一化,然后再进行仿射变换 γ * Norm(x) + β。</p></li></ul><p>可以认为,AdaLN 是 FiLM 思想在层归一化(Layer Normalization)上的一种特例化应用。AdaLN 在稳定训练的同时注入条件,在许多生成模型(如 DiT)中非常流行。</p>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> FiLM </tag>
<tag> style transfer </tag>
</tags>
</entry>
<entry>
<title>React-useCallback</title>
<link href="/2025/08/React-UseCallback/"/>
<url>/2025/08/React-UseCallback/</url>
<content type="html"><![CDATA[<h2 id="核心思想"><a href="#核心思想" class="headerlink" title="核心思想"></a>核心思想</h2><p>useCallback 是一个 React Hook,它用于缓存(或称‘记忆化’)一个函数。这能确保在多次重新渲染之间,只要依赖项没有改变,这个函数就不会被重新创建,从而保持其引用的稳定性。</p><hr><figure class="highlight jsx"><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"><span class="keyword">const</span> memoizedCallback = <span class="title function_">useCallback</span>(<span class="function">() =></span> {</span><br><span class="line"> <span class="comment">// 执行逻辑</span></span><br><span class="line">}, [dependencies]);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 第一个参数:要记忆的函数</span></span><br><span class="line"><span class="comment">// 第二个参数:依赖数组(dependencies)</span></span><br><span class="line"><span class="comment">// 依赖不变时,返回**同**一个函数引用</span></span><br><span class="line"><span class="comment">// 依赖变化时,才会返回一个**新的**函数引用</span></span><br></pre></td></tr></table></figure><h3 id="为什么需要-useCallback"><a href="#为什么需要-useCallback" class="headerlink" title="为什么需要 useCallback"></a>为什么需要 useCallback</h3><p>在 React 中,函数组件每次渲染时都会重新创建函数对象。例如:</p><figure class="highlight jsx"><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"><span class="keyword">function</span> <span class="title function_">MyComponent</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">const</span> <span class="title function_">handleClick</span> = (<span class="params"></span>) => {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"clicked"</span>);</span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="language-xml"><span class="tag"><<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">{handleClick}</span>></span>Click<span class="tag"></<span class="name">button</span>></span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这里的 <code>handleClick</code> 每次渲染都会是一个 新的函数对象。如果这个函数作为 <code>props</code> 传给子组件,那么即使逻辑不变,子组件也会认为 <code>props</code> 变了,从而 导致子组件重新渲染。</p><figure class="highlight jsx"><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"><span class="keyword">function</span> <span class="title function_">MyComponent</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">const</span> handleClick = <span class="title function_">useCallback</span>(<span class="function">() =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"clicked"</span>);</span><br><span class="line"> }, []); <span class="comment">// 没有依赖,始终返回同一个函数引用</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="language-xml"><span class="tag"><<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">{handleClick}</span>></span>Click<span class="tag"></<span class="name">button</span>></span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这样 <code>handleClick</code> 的引用在组件多次渲染时保持不变。</p><hr><h3 id="举例对比"><a href="#举例对比" class="headerlink" title="举例对比"></a>举例对比</h3><p>❌ 不用 useCallback</p><figure class="highlight jsx"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title function_">Parent</span> = (<span class="params"></span>) => {</span><br><span class="line"> <span class="keyword">const</span> [count, setCount] = <span class="title function_">useState</span>(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> <span class="title function_">increment</span> = (<span class="params"></span>) => <span class="title function_">setCount</span>(<span class="function">(<span class="params">c</span>) =></span> c + <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">Child</span> <span class="attr">onClick</span>=<span class="string">{increment}</span> /></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span>></span>{count}<span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"> );</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Child</span> = <span class="title class_">React</span>.<span class="title function_">memo</span>(<span class="function">(<span class="params">{ onClick }</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"Child render"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="language-xml"><span class="tag"><<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">{onClick}</span>></span>Increment<span class="tag"></<span class="name">button</span>></span></span>;</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>即使 count 变化,increment 每次都是新函数 → Child 每次都会重新渲染。</p><p>✅ 用 useCallback</p><figure class="highlight jsx"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title function_">Parent</span> = (<span class="params"></span>) => {</span><br><span class="line"> <span class="keyword">const</span> [count, setCount] = <span class="title function_">useState</span>(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> increment = <span class="title function_">useCallback</span>(<span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">setCount</span>(<span class="function">(<span class="params">c</span>) =></span> c + <span class="number">1</span>);</span><br><span class="line"> }, []); <span class="comment">// increment 的引用固定</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">Child</span> <span class="attr">onClick</span>=<span class="string">{increment}</span> /></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span>></span>{count}<span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"> );</span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>这样 Child 不会因为函数引用变化而重复渲染,只在必要时更新。</p>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> React </tag>
</tags>
</entry>
<entry>
<title>《Ocean's Eight》</title>
<link href="/2025/08/Ocean8/"/>
<url>/2025/08/Ocean8/</url>
<content type="html"><![CDATA[<h2 id="基本信息"><a href="#基本信息" class="headerlink" title="基本信息"></a>基本信息</h2><div class="movie-info-container"><div class="movie-details"> <ul> <li><strong>导演</strong>:Gary Ross</li> <li><strong>主演</strong>:Sandra Bullock、Cate Blanchett、Anne Hathaway、Rihanna、Mindy Kaling、Sarah Paulson、Awkwafina</li> <li><strong>上映时间</strong>:2018 年</li> <li><strong>观看时间</strong>:2025 年 6 月 </li> <li><strong>评分</strong> ⭐⭐⭐⭐⭐ (5/5)</li> </ul></div><div class="movie-poster"><img src="/images/ocean8.png" alt="Ocean's Eight" width="250" height="370"></div></div><p>个人非常偏爱的电影,虽然剧情上总是被大家吐槽,但是请忽略剧情(bushi),就认认真真的看这些个女的还是相当快乐的。在电影中每个人的角色塑造都还是挺不错了,除了安妮海瑟薇的角色塑造有点别扭~ 强烈强烈安利喜欢 桑婆,大魔王和香蕉姐组合的人都速速看。 以及这部电影随之带来了非常多的线下采访和宣发,都非常的有意思,个人觉得 maybe 这才是精华。</p><p>总之这部电影带给人的感觉就是有权有势有演技的女明星们聚在一起的线上 play,线下每个人也都很有活力和魅力,大概就是独立成功女性的现实爽文,所以看起来很快乐了。</p><p>一些有意思的线下采访:</p><ul><li> <a href="【【中字】The.Graham.Norton.Show.S23E11 【凯特布兰切特】】 https://www.bilibili.com/video/BV1hW411c7Uu/?share_source=copy_web&vd_source=65ec8981c0c50f7df1a335cd85471278"> The.Graham.Norton.Show.S23E11 </a></li><li> <a href="【【中文字幕】Ocean's 8 BBC采访 蕉蕉凯特桑爪三人组(20 Jun 2018)】 https://www.bilibili.com/video/BV12b411M7kD/?share_source=copy_web&vd_source=65ec8981c0c50f7df1a335cd85471278"> 蕉蕉凯特桑爪三人组 </a> </li></ul><style>.movie-info-container { display: flex; gap: 2rem; align-items: flex-start; margin: 1.5rem 0;}.movie-details { flex: 2;}.movie-poster { flex: 1; text-align: center;}.movie-poster img { border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); object-fit: cover; /* 保持比例,裁剪溢出部分 */}@media (max-width: 768px) { .movie-info-container { flex-direction: column; gap: 1rem; } .movie-poster img { width: 200px !important; height: 300px !important; }}</style><hr><p><em>本文为个人观影感受,仅供参考。</em></p>]]></content>
<categories>
<category> 影音书评 </category>
<category> 电影 </category>
</categories>
<tags>
<tag> 电影 </tag>
<tag> 剧情片 </tag>
<tag> 喜剧片 </tag>
<tag> 全女主 </tag>
</tags>
</entry>
<entry>
<title>Gumbel-Softmax</title>
<link href="/2025/08/Gumbel-Softmax/"/>
<url>/2025/08/Gumbel-Softmax/</url>
<content type="html"><![CDATA[<p>背景:离散决策(one-hot 选择)是不可导的,不能直接在神经网络里反向传播梯度。</p><p>解决方法: 用 Gumbel-Softmax trick</p><h3 id="Gumbel-Softmax"><a href="#Gumbel-Softmax" class="headerlink" title="Gumbel-Softmax"></a>Gumbel-Softmax</h3><h4 id="普通-softmax"><a href="#普通-softmax" class="headerlink" title="普通 softmax:"></a>普通 softmax:</h4><script type="math/tex; mode=display">p_i = \frac{\exp(\text{logits}_i / \tau)}{\sum_j \exp(\text{logits}_j / \tau)}</script><ul><li><p><strong>各个符号的含义</strong></p><ul><li><p><strong>logits<sub>i</sub></strong>:<br>模型输出的第 i 类的”原始分数”,还没有经过归一化。</p></li><li><p><strong>τ (temperature, 温度参数)</strong>:<br>控制分布的”平滑程度”。当 τ=1 时,就是普通的 softmax。τ 越大,分布越平滑,概率越接近均匀分布。</p></li><li><p><strong>exp(·)</strong>:<br>指数函数,把分数变成正数。</p></li><li><p><strong>分母</strong>:<br>对所有类别的指数和求和,用来做归一化,保证结果是概率分布。</p></li><li><p><strong>结果 p<sub>i</sub></strong>:<br>这是第 i 类的概率,满足 $\sum_i p_i = 1$。</p></li></ul></li></ul><hr><h4 id="Gumbel-Softmax-的公式:"><a href="#Gumbel-Softmax-的公式:" class="headerlink" title="Gumbel-Softmax 的公式:"></a>Gumbel-Softmax 的公式:</h4><script type="math/tex; mode=display">p_i = \frac{\exp(\text{logits}_i + g_i / \tau)}{\sum_j \exp(\text{logits}_j + g_j / \tau)}</script><p>在 logits 上加上 Gumbel 噪声,再 softmax,有两种模式:</p><h4 id="1-hard-False-连续模式"><a href="#1-hard-False-连续模式" class="headerlink" title="1. hard = False (连续模式)"></a>1. <code>hard = False</code> (连续模式)</h4><ul><li>输出一个概率向量(类似 soft one-hot)</li><li>比如:<code>[0.7, 0.2, 0.1]</code></li><li>这个输出是连续的,可以直接反向传播梯度</li><li>好处:完全可导,可以用作常规训练</li><li>缺点:不是真正的离散化,模型真正使用时可能表现不同</li></ul><h4 id="2-hard-True-离散模式"><a href="#2-hard-True-离散模式" class="headerlink" title="2. hard = True (离散模式)"></a>2. <code>hard = True</code> (离散模式)</h4><ul><li>在前向传播时,会输出”硬化”为 one-hot,比如上面的数据会变成:<code>[1, 0, 0]</code></li><li>这样看起来像真正的离散选择</li><li>但在反向传播时,仍然是按照 soft 版本的梯度(就是那个 <code>[0.7, 0.2, 0.1]</code>)- 这叫 <strong>straight-through estimator</strong></li></ul><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> torch</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><br><span class="line"><span class="comment"># 假设 logits 来自一个 3 类分类器</span></span><br><span class="line">logits = torch.tensor([[<span class="number">2.0</span>, <span class="number">1.0</span>, <span class="number">0.1</span>]], requires_grad=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line">tau = <span class="number">1.0</span> <span class="comment"># 温度参数</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ---------------------------</span></span><br><span class="line"><span class="comment"># 1. hard=False (软 one-hot,连续概率分布)</span></span><br><span class="line"><span class="comment"># ---------------------------</span></span><br><span class="line">y_soft = F.gumbel_softmax(logits, tau=tau, hard=<span class="literal">False</span>)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">"hard=False 输出:"</span>, y_soft)</span><br><span class="line"></span><br><span class="line">loss_soft = y_soft.<span class="built_in">sum</span>() <span class="comment"># 简单构造一个损失</span></span><br><span class="line">loss_soft.backward()</span><br><span class="line"><span class="built_in">print</span>(<span class="string">"hard=False 梯度:"</span>, logits.grad)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 梯度清零</span></span><br><span class="line">logits.grad.zero_()</span><br><span class="line"></span><br><span class="line"><span class="comment"># ---------------------------</span></span><br><span class="line"><span class="comment"># 2. hard=True (前向 one-hot,但梯度来自 soft 版本)</span></span><br><span class="line"><span class="comment"># ---------------------------</span></span><br><span class="line">y_hard = F.gumbel_softmax(logits, tau=tau, hard=<span class="literal">True</span>)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">"\nhard=True 输出:"</span>, y_hard)</span><br><span class="line"></span><br><span class="line">loss_hard = y_hard.<span class="built_in">sum</span>()</span><br><span class="line">loss_hard.backward()</span><br><span class="line"><span class="built_in">print</span>(<span class="string">"hard=True 梯度:"</span>, logits.grad)</span><br><span class="line"></span><br><span class="line"><span class="comment"># hard=False 输出: tensor([[0.6591, 0.2479, 0.0930]], grad_fn=<GumbelSoftmaxBackward>)</span></span><br><span class="line"><span class="comment"># hard=False 梯度: tensor([[0., 0., 0.]])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># hard=True 输出: tensor([[1., 0., 0.]], grad_fn=<GumbelSoftmaxBackward>)</span></span><br><span class="line"><span class="comment"># hard=True 梯度: tensor([[0., 0., 0.]])</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> 机器学习 </tag>
</tags>
</entry>
<entry>
<title>门控残差-GRN</title>
<link href="/2025/08/%E9%97%A8%E6%8E%A7%E6%AE%8B%E5%B7%AE-GRN/"/>
<url>/2025/08/%E9%97%A8%E6%8E%A7%E6%AE%8B%E5%B7%AE-GRN/</url>
<content type="html"><![CDATA[<h2 id="核心思想"><a href="#核心思想" class="headerlink" title="核心思想"></a>核心思想</h2><p>GRN 的核心思想是将残差连接的“跳跃”路径与门控单元的“开关”功能结合起来。</p><h2 id="残差连接(Residual-Connection)"><a href="#残差连接(Residual-Connection)" class="headerlink" title="残差连接(Residual Connection)"></a>残差连接(Residual Connection)</h2><p>这是残差网络(ResNet)的核心思想。它通过在网络层之间添加一个“跳跃连接”(skip connection),将前一层的输入直接加到后面几层的输出上。这样做的好处是,即使某些层学到的特征不重要,梯度也可以通过这个“捷径”直接传导,有效缓解了梯度消失问题,并让网络更容易学习到恒等映射(identity mapping),从而使网络可以训练得更深。</p><h2 id="门控机制(Gating-Mechanism)"><a href="#门控机制(Gating-Mechanism)" class="headerlink" title="门控机制(Gating Mechanism)"></a>门控机制(Gating Mechanism)</h2><p>门控机制通常使用 Sigmoid 或 Softmax 等激活函数,生成一个 0 到 1 之间的门控值。这个值就像一个“门”,可以动态地控制信息流动的比例。当门控值为 1 时,信息完全通过;当门控值为 0 时,信息被阻断。这种机制让网络可以自适应地学习哪些信息是重要的,并只让重要的信息流向下一层。典型的例子就是长短期记忆网络(LSTM)和门控循环单元(GRU)。</p><p>用公式表示的话,一个典型的 GRN 模块可以写作:</p><script type="math/tex; mode=display">y = Gate(x) \odot F(x, W) + (1 - Gate(x)) \odot x</script>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> 深度学习 </tag>
</tags>
</entry>
<entry>
<title>《Fleabag》(伦敦生活)</title>
<link href="/2025/08/fleabag/"/>
<url>/2025/08/fleabag/</url>
<content type="html"><![CDATA[<h2 id="基本信息"><a href="#基本信息" class="headerlink" title="基本信息"></a>基本信息</h2><div class="movie-info-container"><div class="movie-details"> <ul> <li><strong>导演</strong>:菲比·沃勒-布里奇(Phoebe Waller-Bridge)</li> <li><strong>主演</strong> 菲比·沃勒-布里奇、安德鲁·斯科特等</li> <li><strong>上映时间</strong>:2016 年</li> <li><strong>观看时间</strong>:2025 年 5 月</li> <li><strong>评分</strong> ⭐⭐⭐⭐⭐ (5/5)</li> </ul></div><div class="movie-poster"><img src="/images/fleabag.png" alt="fleabag poster" width="250" height="370"></div></div><p>优质的互联网嘴替:</p><ul> <li><a href="https://ahsmmy.typlog.io/episodes/s2-e09-e68891e4bbace983bde698afe3808ce5a4b1e8b4a5e3808de79a84e5a5b3e69d83e4b8bbe4b989e88085-e3808ae4" target="_blank"> 播客《是猫咪呀》 </a> S2.E09 我们都是「失败」的女权主义者 | 《伦敦生活》</li> <li><a href="https://podcasts.apple.com/cn/podcast/%E7%87%95%E5%A4%96%E4%B9%8B%E6%84%8F-%E4%BC%A6%E6%95%A6%E7%94%9F%E6%B4%BB-%E6%88%91%E7%9A%84%E5%AE%8C%E8%9B%8B%E4%BA%BA%E7%94%9F/id1620123449?i=1000681056441" target="_blank"> 播客《燕外之意》 </a> 伦敦生活,我的完蛋人生 </li></ul><p>《Fleabag》是百看不厌的剧集,不同的心境和年龄看会有不一样的感受,和《Friends》很像,但是整体的色调更荒诞和孤独,所以就意外的很适合城市独居女性。有自我厌恶,家庭冲突,畸形的姐妹和伴侣关系… 但 Fleabag 总给我生生不息的生活希望可能是让我意识到了很多事情 dosen’t matter,生活可以很荒诞的过下去(不过也有人说看完更 emo 了,hh)。</p><style>.movie-info-container { display: flex; gap: 2rem; align-items: flex-start; margin: 1.5rem 0;}.movie-details { flex: 2;}.movie-poster { flex: 1; text-align: center;}.movie-poster img { border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); object-fit: cover; /* 保持比例,裁剪溢出部分 */}@media (max-width: 768px) { .movie-info-container { flex-direction: column; gap: 1rem; } .movie-poster img { width: 200px !important; height: 300px !important; }}</style><hr><p><em>本文为个人观影感受,仅供参考。</em></p>]]></content>
<categories>
<category> 影音书评 </category>
<category> 电视剧 </category>
</categories>
<tags>
<tag> 剧情片 </tag>
<tag> 英剧 </tag>
</tags>
</entry>
<entry>
<title>HTTP 状态码</title>
<link href="/2025/08/HTTP_status_code/"/>
<url>/2025/08/HTTP_status_code/</url>
<content type="html"><![CDATA[<h2 id="个人对于自己常见但不熟悉的-HTTP-状态码的总结"><a href="#个人对于自己常见但不熟悉的-HTTP-状态码的总结" class="headerlink" title="个人对于自己常见但不熟悉的 HTTP 状态码的总结"></a>个人对于自己常见但不熟悉的 HTTP 状态码的总结</h2><h3 id="304"><a href="#304" class="headerlink" title="304"></a>304</h3><p>HTTP 状态码 304 表示”未修改”。它表示请求的资源自上次访问以来没有变化,允许浏览器使用其缓存的版本,而不是重新下载。这有助于节省带宽并加快加载时间。</p><hr><h3 id="504"><a href="#504" class="headerlink" title="504"></a>504</h3><p>504 网关超时错误发生在网关或代理服务器未能及时从上游服务器收到响应时。此问题通常由服务器端连接问题引起,但偶尔也会受客户端配置影响。</p><h4 id="常见原因"><a href="#常见原因" class="headerlink" title="常见原因"></a>常见原因</h4><ul><li><p>上游服务器宕机或过载。</p></li><li><p>服务器之间的网络连接问题。</p></li><li><p>DNS 配置不正确或 DNS 记录已过期。</p></li><li><p>防火墙或代理配置错误导致请求被阻止。</p></li></ul><hr><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>4xx(<strong>客户端</strong>错误状态码):表示请求包含语法错误或无法完成。</p><p>5xx(<strong>服务器</strong>错误状态码):服务器在处理请求的过程中发生了错误。</p>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> Network </tag>
<tag> HTTP </tag>
</tags>
</entry>
<entry>
<title>《Killing Eve》(杀死伊芙)</title>
<link href="/2025/08/killing_eve/"/>
<url>/2025/08/killing_eve/</url>
<content type="html"><![CDATA[<h2 id="基本信息"><a href="#基本信息" class="headerlink" title="基本信息"></a>基本信息</h2><div class="movie-info-container"><div class="movie-details"> <ul> <li><strong>导演</strong>:每一季都在换(去豆瓣 or wiki查吧)</li> <li><strong>主演</strong>:朱迪·科默、吴珊卓等</li> <li><strong>上映时间</strong>:2018 年</li> <li><strong>观看时间</strong>:2025 年 5 月 17 日</li> <li><strong>评分</strong> ⭐⭐⭐⭐⭐ (5/5)</li> </ul></div><div class="movie-poster"><img src="/images/killing-eve-poster.png" alt="杀死伊芙海报" width="250" height="370">Killing eve 值得更好的结局。</div></div><p>太太太太喜欢了…,想法太多了,千言万绪说不完,找了一些优质的互联网嘴替。</p><ul> <li><a href="https://ahsmmy.typlog.io/episodes/s2-e02e3808akilling-evee3808be8afb7e694bee8bf87e8bf99e59cbae796afe78b82e38081e6b5aae6bcabe38081e6b7b" target="_blank"> 播客节目: 是猫咪呀 </a></li> <li><a href="https://b23.tv/YIfsoIu" target="_blank"> 剪辑 killing eve x fortnight </a>没有想到fortnight 歌词和 killing eve 意外的很搭。</li> </ul><p>看完喜欢朱迪·科默的也请去支持一下她的舞台剧作品:<a href="https://movie.douban.com/subject/35861791/" target="_blank">《初步举证》</a></p><style>.movie-info-container { display: flex; gap: 2rem; align-items: flex-start; margin: 1.5rem 0;}.movie-details { flex: 2;}.movie-poster { flex: 1; text-align: center;}.movie-poster img { border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); object-fit: cover; /* 保持比例,裁剪溢出部分 */}@media (max-width: 768px) { .movie-info-container { flex-direction: column; gap: 1rem; } .movie-poster img { width: 200px !important; height: 300px !important; }}</style><hr><p><em>本文为个人观影感受,仅供参考。</em></p>]]></content>
<categories>
<category> 影音书评 </category>
<category> 电视剧 </category>
</categories>
<tags>
<tag> 剧情片 </tag>
<tag> 英剧 </tag>
<tag> 双女主 </tag>
</tags>
</entry>
<entry>
<title>《Ocean's Eleven》(十一罗汉)</title>
<link href="/2025/08/%E5%8D%81%E4%B8%80%E7%BD%97%E6%B1%89/"/>
<url>/2025/08/%E5%8D%81%E4%B8%80%E7%BD%97%E6%B1%89/</url>
<content type="html"><![CDATA[<h2 id="基本信息"><a href="#基本信息" class="headerlink" title="基本信息"></a>基本信息</h2><div class="movie-info-container"><div class="movie-details"> <ul> <li><strong>导演</strong>:史蒂文·索德伯格</li> <li><strong>主演</strong>:乔治·克鲁尼、布拉德·皮特、马特·达蒙、朱莉娅·罗伯茨、凯瑟琳·泽塔-琼斯</li> <li><strong>上映时间</strong>:2001 年</li> <li><strong>观看时间</strong>:2025 年 8 月 16 日</li> <li><strong>评分</strong> ⭐⭐⭐☆☆ (3/5)</li> </ul></div><div class="movie-poster"><img src="/images/oceans-eleven-poster.png" alt="十一罗汉海报" width="250" height="370"></div></div><p>冲着茱莉亚·罗伯茨去看的,结果是花瓶美女的角色,可能是由于先看了 <a href="https://en.wikipedia.org/wiki/Ocean%27s_8">Ocean 8</a>,二者风格比较相似,所以并没有太多的惊喜。 不过众星云集,剧情和部分人物塑造都还不错。总体上算是不错的爆米花电影。</p><style>.movie-info-container { display: flex; gap: 2rem; align-items: flex-start; margin: 1.5rem 0;}.movie-details { flex: 2;}.movie-poster { flex: 1; text-align: center;}.movie-poster img { border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); object-fit: cover; /* 保持比例,裁剪溢出部分 */}@media (max-width: 768px) { .movie-info-container { flex-direction: column; gap: 1rem; } .movie-poster img { width: 200px !important; height: 300px !important; }}</style><hr><p><em>本文为个人观影感受,仅供参考。</em></p>]]></content>
<categories>
<category> 影音书评 </category>
<category> 电影 </category>
</categories>
<tags>
<tag> 电影 </tag>
<tag> 剧情片 </tag>
</tags>
</entry>
<entry>
<title>SD-Turbo</title>
<link href="/2025/08/SD-turbo/"/>
<url>/2025/08/SD-turbo/</url>
<content type="html"><![CDATA[<ol><li><p><strong>生成速度 (Generation Speed)</strong></p><p>SD-Turbo: 实现了单步图像生成。这意味着它只需要一次网络前向传播就能输出最终图像,大大缩短了生成时间,使其适用于实时交互应用。<br>其他扩散模型 (如 Stable Diffusion 1.5/2.1, SDXL): 通常需要一个迭代的“去噪”过程,步数(Steps)一般设置在 20 到 50 步之间。步数越多,细节通常越好,但耗时也越长。</p></li><li><p><strong>实现技术 (Underlying Technology)</strong></p><p>SD-Turbo: 采用了一种名为对抗性扩散蒸馏 (Adversarial Diffusion Distillation, ADD) 的新技术。<br>可以将其理解为一种“模型蒸馏”技术。它有一个强大的“教师模型”(基于 SD 2.1),SD-Turbo 作为“学生模型”来学习教师的生成能力。<br>与传统蒸馏不同,它引入了对抗性训练(类似 GANs),有一个判别器来判断生成图像的真伪,这迫使 SD-Turbo 学会在单步内就生成非常逼真的图像。<br>其他扩散模型: 使用的是扩散与去噪(Denoising Diffusion Probabilistic Models, DDPM)原理。通过一个逐步添加噪声的前向过程和一个逐步去除噪声的反向过程来生成图像,这个反向过程就是我们通常所说的采样(sampling)。</p></li><li><p><strong>图像质量与细节 (Image Quality & Detail)</strong></p><p>SD-Turbo: 在单步生成的前提下,图像质量非常惊人,但在精细的细节、复杂构图和对提示词(Prompt)的精确理解上,可能略逊于经过多步迭代的顶级模型(如 SDXL)。它在速度和质量之间做了一个极致的平衡。<br>其他扩散模型: 可以通过增加迭代步数来提升图像的细节和一致性,通常能够更好地遵循复杂的提示词。SDXL 在这方面尤其出色。</p></li><li><p><strong>使用方式 (Usage)</strong></p><p>SD-Turbo: 在使用时,通常不需要或不推荐使用 guidance_scale (CFG) 和 negative_prompt。因为它的模型设计就是为了在单步内直接生成,没有多步迭代的过程给这些参数来引导。通常会将 guidance_scale 设置为 0。<br>其他扩散模型: guidance_scale 和 negative_prompt 是非常重要的控制手段,用来增强提示词的相关性并避免不希望出现的元素。</p></li></ol><h3 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h3><p><a href="https://huggingface.co/stabilityai/sd-turbo">SD-Turbo huggingface</a></p>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> AI </tag>
</tags>
</entry>
<entry>
<title>Alignment Module</title>
<link href="/2025/08/AlignmentModule/"/>
<url>/2025/08/AlignmentModule/</url>
<content type="html"><![CDATA[<h2 id="计算机视觉领域的-Alignment-Module-设计"><a href="#计算机视觉领域的-Alignment-Module-设计" class="headerlink" title="计算机视觉领域的 Alignment Module 设计"></a>计算机视觉领域的 Alignment Module 设计</h2><p>目标:将视觉特征与文本或其他模态的特征空间对齐,以实现多模态理解或提升视觉推理能力。</p><h3 id="FaithDiff"><a href="#FaithDiff" class="headerlink" title="FaithDiff"></a>FaithDiff</h3><p><img src="/images/FaithDiff.png" alt="FaithDiff alignment Module"><br>为了能够更好的在生成过程中补充 LQ 图像信息,需要将 LQ 信息注入到模型的生成过程中,但是由于 LQ 图像和 noisy latnet $x_t^{HQ}$ 之间存在 gap,直接相加是不大合理的,所以设计 <code>Alignment Module</code> 将 LQ 图像和 $x_t^{HQ}$ 进行对齐,然后输入到模型中。<br>具体来说,FaithDiff 中的 Alignment Module 设计如下:</p><script type="math/tex; mode=display">\begin{align}f_t^x &= \text{Conv}(x_t^{HQ}), \\f^m &= \text{Conv}(f^{LQ}), \\f_t^c &= \text{Concat}(f_t^x, f^m), \\\text{Trans}(f_t^c) &= \mathcal{T}_2(\mathcal{T}_1(f_t^c)), \\f_t^a &= \text{Linear}(\text{Trans}(f_t^c) + f_t^x),\end{align}</script><p>其中 $\mathcal{T}$ 是 Transformer Block, 对应的 <a href="https://github.com/JyChen9811/FaithDiff/issues/16">Alignment Module</a> 的代码位置</p><h3 id="IP-Adapter"><a href="#IP-Adapter" class="headerlink" title="IP-Adapter"></a>IP-Adapter</h3><p><img src="/images/IPadapter.png" alt="IP-Adapter"></p><p>IP-Adapter 通过解耦的两个 Cross-Attention 分别融合图像信息和文本信息,其中图像信息通过 <code>Image-Conditioned Attention</code> 进行融合,文本信息通过 <code>Text-Conditioned Attention</code> 进行融合。这种方式不会让图像和文本信息相互干扰,在信息传递的过程中可以依次提取所需要的图像和文本信息。</p><h3 id="DAEFR"><a href="#DAEFR" class="headerlink" title="DAEFR"></a>DAEFR</h3><p><img src="/images/DAEFR.png" alt="DAEFR"></p><p>DAEFR 采用 CLIP 的方式,在 (b) Association Stage 对齐 LQ 和 HQ,后续采用 Attention 机制将 LQ 和 HQ 信息进行融合。</p><h2 id="参考论文"><a href="#参考论文" class="headerlink" title="参考论文"></a>参考论文</h2><ul><li><a href="https://arxiv.org/abs/2411.18824">FaithDiff: Unleashing Diffusion Models for Faithful Text-to-Image Generation</a></li><li><a href="https://arxiv.org/abs/2308.06721">IP-Adapter: Text Compatible Image Prompt Adapter for Text-to-Image Diffusion Models</a></li><li><a href="https://arxiv.org/pdf/2308.07314">DAEFR: DUAL ASSOCIATED ENCODER FOR FACE RESTORATION</a></li></ul>]]></content>
<categories>
<category> Learning </category>
</categories>
<tags>
<tag> Module </tag>
</tags>
</entry>
<entry>
<title>Hello World</title>
<link href="/2025/08/hello-world/"/>
<url>/2025/08/hello-world/</url>
<content type="html"><![CDATA[<p>欢迎来到我的博客!这是第一篇文章。</p><span id="more"></span><p>这里是文章的详细内容…</p>]]></content>
<categories>
<category> diary </category>
</categories>
<tags>
<tag> test </tag>
</tags>
</entry>
</search>