-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
1646 lines (1646 loc) · 164 KB
/
search.xml
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
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>NLP</title>
<url>/2024/10/03/NLP/</url>
<content><![CDATA[<h3 id="三类不同的transformer模型">三类不同的Transformer模型:</h3>
<ul>
<li>GPT-like(自回归)</li>
<li>BERT-like(自动编码)</li>
<li>BART/T5-like(seq2seq)</li>
</ul>
<p>要执行微调需要获取一个经过预训练的预言模型,然后使用特定于任务的数据集执行额外的训练,之所以不在最后的任务训练是因为:</p>
<ul>
<li><p>利用模型在预训练期间获得的知识</p></li>
<li><p>避免过拟合 <span id="more"></span> ### 模型块:</p></li>
<li><p>Encoder:编码器接收输入并构建其表示(其特征)</p></li>
<li><p>Decoder:解码器使用编码器的表示(特征)以及其他输入来生成目标序列。</p></li>
</ul>
<p>这些部件可以根据任务独立使用:</p>
<ul>
<li><strong>Encoder-only models</strong>:
适用于需要理解输入的任务,如句子分类和命名实体识别。</li>
<li><strong>Decoder-only models</strong>:
适用于生成任务,如文本生成。</li>
<li><strong>Encoder-decoder models</strong> 或者
<strong>sequence-to-sequence models</strong>:
适用于需要根据输入进行生成的任务,如翻译或摘要。</li>
</ul>
<h3 id="原始结构">原始结构</h3>
<p>Encoder中的注意力层可以看到一个句子中的所有单词,但Decoder只能看到之前的单词,为了加快训练速度,会把整个目标输入,但是不允许获取到之后的单词</p>
<p>解码器块中的第一个注意力层关联到解码器的所有(过去的)输入,但是第二注意力层使用编码器的输出。因此,它可以访问整个输入句子,以最好地预测当前单词。</p>
<figure>
<img
src="/Users/sunyuanxu/Library/Application%20Support/typora-user-images/image-20240906171929209.png"
alt="image-20240906171929209" />
<figcaption aria-hidden="true">image-20240906171929209</figcaption>
</figure>
<h3 id="编码器模型">编码器模型</h3>
<p>仅使用编码器的Transformer模型,在每个阶段,注意力层都可以获取初始句子中的所有单词。这些模型通常具有“双向”注意力,被称为自编码模型。“双向注意力”通常指的是在模型中使用的注意力机制,能够在处理输入序列时同时考虑前后文的信息。</p>
<h3 id="解码器模型">解码器模型</h3>
<p>“解码器”模型通常指仅使用解码器的Transformer模型。在每个阶段,对于给定的单词,注意力层只能获取到句子中位于将要预测单词前面的单词。这些模型通常被称为自回归模型。“解码器”模型的预训练通常围绕预测句子中的下一个单词进行。这些模型最适合于涉及文本生成的任务。</p>
<h3 id="seq2seq模型">seq2seq模型</h3>
<p>编码器-解码器模型(也称为序列到序列模型)同时使用Transformer架构的编码器和解码器两个部分。在每个阶段,编码器的注意力层可以访问初始句子中的所有单词,而解码器的注意力层只能访问位于输入中将要预测单词前面的单词。这些模型的预训练可以使用训练编码器或解码器模型的方式来完成,但通常涉及更复杂的内容。例如,<a
href="https://huggingface.co/t5-base">T5</a>通过将文本的随机跨度(可以包含多个单词)替换为单个特殊单词来进行预训练,然后目标是预测该掩码单词替换的文本。序列到序列模型最适合于围绕根据给定输入生成新句子的任务,如摘要、翻译或生成性问答。</p>
<figure>
<img
src="/Users/sunyuanxu/Library/Application%20Support/typora-user-images/image-20240906172528917.png"
alt="image-20240906172528917" />
<figcaption aria-hidden="true">image-20240906172528917</figcaption>
</figure>
<h3 id="模型头">模型头</h3>
<figure>
<img
src="/Users/sunyuanxu/Library/Application%20Support/typora-user-images/image-20240907152633126.png"
alt="image-20240907152633126" />
<figcaption aria-hidden="true">image-20240907152633126</figcaption>
</figure>
<p>模型头将hidden
states的输出作为输入,并将其投影到不同的维度。它们通常有一个或几个线性层组成。</p>
<h3 id="对输出进行后处理">对输出进行后处理</h3>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">print(outputs.logits)</span><br><span class="line">tensor([[-1.5607, 1.6123],</span><br><span class="line"> [ 4.1692, -3.3464]], grad_fn=<AddmmBackward>)</span><br></pre></td></tr></table></figure>
<p>输出不是概率,而是logits,即模型最后一层输出的原始非标准化分数,概率是经过一个SoftMax层</p>
]]></content>
</entry>
<entry>
<title>RL学习笔记</title>
<url>/2024/10/03/RL/</url>
<content><![CDATA[<h2 id="markov-decision-process-mdp">Markov Decision Process (MDP)</h2>
<h3 id="马尔可夫过程">1. 马尔可夫过程</h3>
<p>通常用元组 <span class="math inline">\(⟨S,P⟩\)</span>
描述一个马尔可夫过程,其中 <span class="math inline">\(S\)</span>
为有限数量的状态集合,<span class="math inline">\(P\)</span>
是状态转移矩阵:</p>
<p><span class="math display">\[
P = \begin{bmatrix}
P(s_1|s_1) & \cdots & P(s_n|s_1) \\
\vdots & \ddots & \vdots \\
P(s_1|s_n) & \cdots & P(s_n|s_n)
\end{bmatrix}
\]</span></p>
<p>对于状态转移矩阵,每一行的和都是
1。直观地理解,每个状态一定会到下一个状态,那么把所有可能到达的状态的概率求和,就为
1。 <span id="more"></span> ### 2. 马尔可夫奖励过程</p>
<p>在马尔可夫过程中加入奖励函数 <span class="math inline">\(r\)</span>
和折扣因子 <span
class="math inline">\(\gamma\)</span>,就可以得到马尔可夫奖励过程(Markov
Reward Process)。一个马尔可夫奖励过程由 <span class="math inline">\((S,
P, r, \gamma)\)</span> 构成,各个组成元素的含义如下:</p>
<ul>
<li><span class="math inline">\(S\)</span> 是有限状态的集合。</li>
<li><span class="math inline">\(P\)</span> 是状态转移矩阵。</li>
<li><span class="math inline">\(r\)</span> 是奖励函数,某个状态 <span
class="math inline">\(s\)</span> 的奖励 <span
class="math inline">\(r(s)\)</span>
指转移到该状态时可以获得奖励的期望。</li>
<li><span class="math inline">\(\gamma\)</span> 是折扣因子(discount
factor),<span class="math inline">\(\gamma\)</span> 的取值范围为 [0,
1)。引入折扣因子的理由为远期利益具有一定不确定性,有时我们更希望能够尽快获得一些奖励,所以我们需要对远期利益打一些折扣。接近
1 的 <span class="math inline">\(\gamma\)</span>
更关注长期的累计奖励,接近 0 的 <span
class="math inline">\(\gamma\)</span> 更考虑短期奖励。</li>
</ul>
<h4 id="回报">2.1 回报</h4>
<p><span class="math display">\[
G_t = R_t + \gamma R_{t+1} + \gamma^2 R_{t+2} + \cdots =
\sum_{k=0}^\infty \gamma^k R_{t+k}
\]</span></p>
<p>其中,<span class="math inline">\(R_t\)</span> 表示在时刻 <span
class="math inline">\(t\)</span> 获得的奖励。</p>
<h4 id="价值函数">2.2 价值函数</h4>
<p>一个状态的期望回报(即从这个状态出发的未来累积奖励的期望)被称为这个状态的价值(value),价值函数的定义
<span class="math inline">\(V(s) = \mathbb{E}[G_t \mid S_t =
s]\)</span>,展开为:</p>
<p><span class="math display">\[
V(s) = \mathbb{E}[G_t \mid S_t = s]
= \mathbb{E}[R_t + \gamma R_{t+1} + \gamma^2 R_{t+2} + \cdots \mid S_t =
s]
= \mathbb{E}[R_t + \gamma G_{t+1} \mid S_t = s]
= \mathbb{E}[R_t \mid S_t = s] + \gamma \mathbb{E}[G_{t+1} \mid S_t = s]
= r(s) + \gamma \mathbb{E}[V(S_{t+1}) \mid S_t = s]
\]</span></p>
<p><span class="math inline">\(\mathbb{E}[R_t \mid S_t = s] =
r(s)\)</span>;另一方面,等式中剩余部分 <span
class="math inline">\(\mathbb{E}[\gamma V(S_{t+1}) \mid S_t =
s]\)</span> 可以根据从状态 <span class="math inline">\(s\)</span>
出发的转移概率得到,即可以得到:</p>
<p><span class="math display">\[
V(s) = r(s) + \gamma \sum_{s' \in S} p(s' \mid s)V(s')
\]</span></p>
<p>上面就是贝尔曼方程(Bellman
Equation)。将贝尔曼方程写成矩阵的形式:</p>
<p><span class="math display">\[
\mathbf{V} = \mathbf{R} + \gamma \mathbf{P} \mathbf{V}
\]</span></p>
<p><span class="math display">\[
\begin{bmatrix}
V(s_1) \\
V(s_2) \\
\vdots \\
V(s_n)
\end{bmatrix}
=
\begin{bmatrix}
r(s_1) \\
r(s_2) \\
\vdots \\
r(s_n)
\end{bmatrix}
+
\gamma
\begin{bmatrix}
p(s_1 \mid s_1) & \cdots & p(s_n \mid s_1) \\
p(s_1 \mid s_2) & \cdots & p(s_n \mid s_2) \\
\vdots & \ddots & \vdots \\
p(s_1 \mid s_n) & \cdots & p(s_n \mid s_n)
\end{bmatrix}
\begin{bmatrix}
V(s_1) \\
V(s_2) \\
\vdots \\
V(s_n)
\end{bmatrix}
\]</span></p>
<p>我们可以直接根据矩阵运算求解,得到以下解析解:</p>
<p><span class="math display">\[
\mathbf{V} = (\mathbf{I} - \gamma \mathbf{P})^{-1} \mathbf{R}
\]</span></p>
<h3 id="马尔可夫决策过程">3. 马尔可夫决策过程</h3>
<p>上面的过程都是自发的,对于 MP 过程是基于概率自发的,对于 MRP
过程基于概率和累积奖励自发,对于马尔可夫决策过程(Markov Decision
Process,
MDP),他接受来自外界的刺激,称作<strong>智能体的动作</strong>。与 MRP
的过程十分相似,只是多了一个动作的变量,具体而言,由 <span
class="math inline">\(⟨S,A,P,r,\lambda⟩\)</span> 构成:</p>
<ul>
<li><span class="math inline">\(S\)</span> 是状态的集合</li>
<li><span class="math inline">\(A\)</span> 是动作的集合</li>
<li><span class="math inline">\(\lambda\)</span> 是折扣因子</li>
<li><span class="math inline">\(r(s,a)\)</span> 是奖励函数</li>
<li><span class="math inline">\(P(s' \mid s,a)\)</span>
是状态转移函数,表示在 <span class="math inline">\(s\)</span>
状态执行动作 <span class="math inline">\(a\)</span> 之后到达状态 <span
class="math inline">\(s'\)</span> 的概率</li>
</ul>
<h4 id="策略">3.1 策略</h4>
<p>智能体的策略 (Policy) 通常使用 <span
class="math inline">\(\pi\)</span> 来表示。<span
class="math inline">\(\pi(a \mid s)=P(A_t=a \mid S_t=s)\)</span>
是一个函数,表示在输入状态 <span class="math inline">\(s\)</span>
情况下采取动作 <span class="math inline">\(a\)</span>
的概率。分为确定性策略(对于一个状态之后只会执行一个特定的动作)和随机性策略(对于一个状态会得到的是一个概率分布)。</p>
<h4 id="状态价值函数">3.2 状态价值函数</h4>
<p><span class="math inline">\(V^{\pi}(s)=E_{\pi}[G_t \mid
S_t=s]\)</span> 定义为从状态 <span class="math inline">\(s\)</span>
出发,按照策略 <span class="math inline">\(\pi\)</span>
能获得的期望回报。</p>
<h4 id="动作价值函数">3.3 动作价值函数</h4>
<p><span class="math inline">\(Q^{\pi}(s,a)=E_{\pi}[G_t \mid S_t=s,
A_t=a]\)</span> 表示在 MDP 遵循策略 <span
class="math inline">\(\pi\)</span> 的时候,对于当前动作 <span
class="math inline">\(s\)</span> 执行动作 <span
class="math inline">\(a\)</span> 得到的期望回报。</p>
<p>由全概率公式可以得到:</p>
<p><span class="math display">\[
V^{\pi}(s)=\sum_{a\in A}\pi(a \mid s)Q^{\pi}(s,a)
\]</span></p>
<p>类似于 MRP,可以得到下面的公式:</p>
<p><span class="math display">\[
Q^{\pi}(s,a)=E_{\pi}[R_t+\lambda Q^{\pi}(S_{t+1},A_{t+1}) \mid
S_t=s,A_t=a]
\]</span></p>
<p><span class="math display">\[
=r(s,a)+\lambda \sum_{s'\in S}(p(s' \mid s,a)\sum_{a'\in
A}\pi(a' \mid s')Q^{\pi}(s',a'))
\]</span></p>
<h4 id="贝尔曼期望方程">3.4 贝尔曼期望方程</h4>
<p><span class="math display">\[
V^{\pi}(s)=E_{\pi}[G_t \mid S_t=s]=\sum_{a\in A}\left(\pi(a \mid
s)\left(r(s,a)+\lambda\sum_{s'}p(s' \mid
s,a)V^{\pi}(s')\right)\right)
\]</span></p>
<p><span class="math display">\[
Q^{\pi}(s,a)=r(s,a)+\lambda \sum_{s'\in S}\left(p(s' \mid
s,a)\sum_{a'\in A}\pi(a' \mid
s')Q^{\pi}(s',a')\right)
\]</span></p>
<h4 id="占用度量">3.5 占用度量</h4>
<p>首先,我们定义 MDP 的初始状态分布 <span
class="math inline">\(V_0(s)\)</span>,用 <span
class="math inline">\(P_t^{\pi}\)</span> 表示采取策略 <span
class="math inline">\(\pi\)</span> 使得智能体在 <span
class="math inline">\(t\)</span> 时刻状态为 <span
class="math inline">\(s\)</span>
的概率,我们可以定义一个状态访问分布(它描述了在整个时间过程中,智能体有多大概率访问到某个特定状态):</p>
<p><span class="math display">\[
v^{\pi}(s)=(1-\lambda)\sum_{t=0}^{\infty}\lambda^{t}P_t^{\pi}(s)
\]</span></p>
<p>此外,我们还可以定义策略的占用度量(occupancy measure):</p>
<p><span class="math display">\[
\rho^\pi(s, a) = (1 - \gamma) \sum_{t=0}^{\infty} \gamma^t P_t^\pi(s)
\pi(a \mid s)
\]</span></p>
<p>它表示动作状态对 <span class="math inline">\((s, a)\)</span>
被访问到的概率。二者之间存在如下关系:</p>
<p><span class="math display">\[
\rho^\pi(s, a) = v^\pi(s) \pi(a \mid s)
\]</span></p>
<p>进一步得出如下两个定理。<strong>定理 1</strong>:智能体分别以策略
<span class="math inline">\(\pi_1\)</span> 和 <span
class="math inline">\(\pi_2\)</span> 和同一个 MDP 交互得到的占用度量
<span class="math inline">\(\rho^{\pi_1}\)</span> 和 <span
class="math inline">\(\rho^{\pi_2}\)</span> 满足:</p>
<p><span class="math display">\[
\rho^{\pi_1} = \rho^{\pi_2} \iff \pi_1 = \pi_2
\]</span></p>
<p><strong>定理 2</strong>:给定一个合法占用度量 <span
class="math inline">\(\rho\)</span>,可生成该占用度量的唯一策略是:</p>
<p><span class="math display">\[
\pi_\rho = \frac{\rho(s, a)}{\sum_{a'} \rho(s, a')}
\]</span></p>
<h4 id="最优策略">3.6 最优策略</h4>
<p>强化学习的目标通常是找到一个策略,使得智能体从初始状态出发能获得最多的期望回报。我们首先定义策略之间的偏序关系:当且仅当对于任意的状态
<span class="math inline">\(s\)</span> 都有 <span
class="math inline">\(V^{\pi'}(s) \ge V^\pi(s)\)</span> 时,记 <span
class="math inline">\(\pi' \succeq
\pi\)</span>。于是存在有限状态和动作集合的 MDP
中,至少存在一个策略比其他所有策略都好或者至少不差于其他所有策略,这个策略就是最优策略(optimal
policy)。最优策略可能有很多个,我们都将其表示为 <span
class="math inline">\(\pi^*\)</span>。</p>
<p>最优策略都有相同的状态价值函数,我们称之为<strong>最优状态价值函数</strong>,表示为:</p>
<p><span class="math display">\[
V^*(s) = \max_\pi V^\pi(s), \quad \forall s \in S
\]</span></p>
<p>同理,我们定义<strong>最优动作价值函数</strong>为:</p>
<p><span class="math display">\[
Q^*(s, a) = \max_\pi Q^\pi(s, a), \quad \forall s \in S, a \in A
\]</span></p>
<p>为了使 <span class="math inline">\(Q^\pi(s, a)\)</span>
最大,我们需要在当前的状态动作对 <span class="math inline">\((s,
a)\)</span>
之后都执行最优策略。于是我们得到了最优状态价值函数和最优动作价值函数之间的关系:</p>
<p><span class="math display">\[
Q^*(s, a) = r(s, a) + \gamma \sum_{s' \in S} P(s' \mid s, a)
V^*(s')
\]</span></p>
<p>这与在普通策略下的状态价值函数和动作价值函数之间的关系是一样的。另一方面,最优状态价值是选择使得最优动作价值最大的那个动作时的状态价值:</p>
<p><span class="math display">\[
V^*(s) = \max_{a \in A} Q^*(s, a)
\]</span></p>
<h4 id="贝尔曼最优方程">3.7 贝尔曼最优方程</h4>
<p>根据 <span class="math inline">\(V^*(s)\)</span> 和 <span
class="math inline">\(Q^*(s, a)\)</span>
的关系,我们可以得到<strong>贝尔曼最优方程</strong>(Bellman Optimality
Equation):</p>
<p><span class="math display">\[
V^*(s) = \max_{a \in A} \{ r(s, a) + \gamma \sum_{s' \in S} p(s'
\mid s, a) V^*(s') \}
\]</span></p>
<p><span class="math display">\[
Q^*(s, a) = r(s, a) + \gamma \sum_{s' \in S} P(s' \mid s, a)
\max_{a' \in A} Q^*(s', a')
\]</span></p>
<h2 id="动态规划算法">动态规划算法</h2>
<h3 id="策略迭代算法">1. 策略迭代算法</h3>
<h4 id="策略评估">1.1 策略评估</h4>
<p>随机选定<span
class="math inline">\(V^0\)</span>,在贝尔曼期望期望方程上迭代: <span
class="math display">\[
V^{k+1}(s)=\sum_{a\in A}\pi(a|s)\left(r(s|a)+\gamma\sum_{s'\in
S}P(s'|s,a)V^k(s') \right)
\]</span> (数学原理可以保证这个的成立)</p>
<h4 id="策略提升">1.2 策略提升</h4>
<p>使用完全贪心的策略,直接贪心的在每个状态选择动作价值最大的那个动作
<span class="math display">\[
\pi'(s)=arg max_aQ^{\pi}(s,a)
\]</span></p>
<h4 id="策略迭代算法-1">1.3 策略迭代算法</h4>
<p>对当前的策略进行策略评估,得到其状态价值函数,然后根据该状态价值函数进行策略提升以得到一个更好的新策略,接着继续评估新策略、提升策略……直至最后收敛到最优策略</p>
<h4 id="价值迭代算法">1.4 价值迭代算法</h4>
<p>在贝尔曼最优方程上进行迭代 <span class="math display">\[
V^{k+1}(s)=max_{a\in A}\{r(s|a)+\gamma\sum_{s'\in
S}P(s'|s,a)V^k(s')\}
\]</span></p>
<h2 id="时序差分算法">时序差分算法</h2>
<p><strong>无模型的强化学习</strong>:对于大部分的强化学习现实场景,环境的奖励函数和状态转移函数是未知的,因此智能体只能通过和环境进行交互,通过采样到的数据进行学习</p>
<h3 id="时序差分方法">1. 时序差分方法</h3>
<h4 id="增量更新">1.1增量更新:</h4>
<p><span class="math display">\[
\begin{aligned}
Q_k &= \frac{1}{k} \sum_{i=1}^k r_i \\
&= \frac{1}{k} \left( r_k + \sum_{i=1}^{k-1} r_i \right) \\
&= \frac{1}{k} \left( r_k + (k-1)Q_{k-1} \right) \\
&= \frac{1}{k} \left( r_k + kQ_{k-1} - Q_{k-1} \right) \\
&= Q_{k-1} + \frac{1}{k} \left[ r_k - Q_{k-1} \right]
\end{aligned}
\]</span></p>
<p>把<span
class="math inline">\(Q_k\)</span>是一种平均值,假设我们的<span
class="math inline">\(r_i\)</span>是逐渐得到的,如果我们等到得到最后一个r的时候再去计算平均值就比较慢,因此,我们可以按照时序顺序来计算,用之前的平均值,加上当前的值与平均值的差距,再乘以一个小因子,相当于每次都给之前的平均值做一个调整。</p>
<h4 id="公式">1.2 公式</h4>
<p><span class="math display">\[
V(s_t)\leftarrow V(s_t)+\alpha[r_t+\gamma V(s_{t+1}-V(s_t)]
\]</span></p>
<h3 id="sarsa算法">2. Sarsa算法</h3>
<p>策略评估已经可以通过时序差分算法实现了,类似的我们可以使用时序差分算法去估计动作价值函数Q:
<span class="math display">\[
Q(s_t,a_t)\leftarrow
Q(s_t,a_t)+\alpha[r_t+Q(s_{t+1},a_{t+1})-Q(s_t,a_t)]
\]</span> 如果一直进行完全贪婪选择的话,可能会导致某些状态动作<span
class="math inline">\((s,a)\)</span>永远没有在序列中出现,导致无法对其动作价值进行估计,因此我们采用<span
class="math inline">\(\epsilon\)</span>贪婪策略</p>
<h3 id="q-learning算法">3. Q-learning算法</h3>
<p>Q-learning基于<strong>Bellman方程</strong>进行更新。</p>
<p><span class="math display">\[
Q(s, a) \leftarrow Q(s, a) + \alpha \left( r + \gamma \cdot
\max_{a'} Q(s', a') - Q(s, a) \right)
\]</span></p>
<ul>
<li><span class="math inline">\(\max_{a'} Q(s',
a')\)</span>:在下一个状态 ( s' )
下,所有可能动作中Q值最大的动作对应的Q值。</li>
</ul>
<h2 id="dqn算法">DQN算法</h2>
<h3 id="dqn">DQN</h3>
<p>参考公式30,我们的目标是使<span
class="math inline">\(Q(s,a)\)</span>和TD的目标<span
class="math inline">\(r+\gamma max_{a' \in
A}Q(s',a')\)</span>靠近,于是 <span class="math display">\[
w^*=arg min_{w}\frac{1}{2N}\sum^N_{i=1}\left[Q_w(s_i,a_i)-\left( r +
\gamma \cdot \max_{a'} Q(s', a') - Q(s, a) \right)\right]
\]</span></p>
<h3 id="经验回放">经验回放</h3>
<p>当前状态和上一个状态紧密相关,如果直接使用连续的样本进行训练,数据之间会高度相关,无法满足神经网络训练所需的独立同分布假设,通过经验回放(在训练神经网络的时候不使用agent最近收集的数据,而是从buffer中随机采样若干数据进行训练)打破样本之间的相关性,减少对神经网络训练的负面影响。</p>
<h3 id="目标网络">目标网络</h3>
<p>将损失函数分为两个部分,一个后半部分每次都更新,一个固定住</p>
<h3 id="double-dqn">Double DQN</h3>
<p>传统的DQN容易造成过高的估计,于是改写为 <span class="math display">\[
r+\gamma Q_{w^-}\left(s',arg max_{a'}Q_w(s',a')\right)
\]</span> 其中目标网络的参数记做<span
class="math inline">\(w^-\)</span>,训练网络的参数记做<span
class="math inline">\(w\)</span></p>
<h3 id="dueling-dqn">Dueling DQN</h3>
<p>在 Dueling DQN 中,Q 网络被建模为: <span class="math display">\[
Q_{\eta,\alpha,\beta}(s,a)=V_{\eta,\alpha}(s)+A_{\eta,\beta}(s,a)
\]</span> <img
src="/Users/sunyuanxu/Library/Application%20Support/typora-user-images/image-20240907180441685.png"
alt="image-20240907180441685" /></p>
<p>分别建模的好处:某些情境下智能体只会关注状态的价值,而并不关心不同动作导致的差异,此时将二者分开建模能够使智能体更好地处理与动作关联较小的状态。</p>
<p>对于这样的Q值的计算,同一个Q值可能对应不同的V,A,因此Dueling DQN
强制最优动作的优势函数的实际输出为 0: <span class="math display">\[
Q_{\eta,\alpha,\beta}(s,a)=V_{\eta,\alpha}(s)+A_{\eta,\beta}(s,a)-max_{a'}A_{\eta,\beta}(s,a')
\]</span> 也可以使用平均代替最大化操作: <span class="math display">\[
Q_{\eta,\alpha,\beta}(s,a)=V_{\eta,\alpha}(s)+A_{\eta,\beta}(s,a)-\frac{1}{|A|}\sum_{a'}A_{\eta,\beta}(s,a')
\]</span> 其中<span
class="math inline">\(|A|\)</span>表示动作空间中所有可能的动作数量。</p>
<h2 id="策略梯度算法">策略梯度算法</h2>
<p>基于策略的方法则是直接显式的学习一个目标策略</p>
<h3 id="策略梯度">策略梯度</h3>
<p>基于策略的方法首先需要将策略参数化。假设目标策略<span
class="math inline">\(\pi_{\theta}\)</span>是一个随机性策略,并且处处可微,将策略学习的目标函数定义为<span
class="math inline">\(J(\theta)=E_{s_0}[V^{\pi_{\theta}}(s_0)]\)</span>,对其求导,然后使用梯队上升方法来最大化这个目标函数。
<span class="math display">\[
\nabla_{\theta}
J(\theta)=E_{\pi_{\theta}}[Q^{\pi_{\theta}}(s,a)\nabla_{\theta}\ log\
\pi_{\theta}(a|s)]
\]</span>
直观的理解就是增大能够得到较高Q值的动作的概率,减少较低Q值的动作的概率</p>
<p>Reinforce算法:有限步数环境下采样轨迹计算相应的价值,利用蒙特卡洛采样
<span class="math display">\[
\nabla_{\theta}
J(\theta)=E_{\pi_{\theta}}\left[\sum^T_{t=0}\left(\sum^T_{t'=t}\gamma^{t'-t}r_{t'}\right)\nabla_{\theta}\
log\ \pi_{\theta}(a|s)\right]
\]</span> 使用当前策略采样,计算当前轨迹每个时刻t往后的回报,记作<span
class="math inline">\(\psi_t\)</span>,然后梯度上升 <span
class="math display">\[
\theta \leftarrow \theta+\alpha\sum_{t}^T\psi_t\nabla_{\theta}\ log\
\pi_{\theta}(a|s)
\]</span></p>
<h2 id="actor-critic算法">Actor-Critic算法</h2>
<p>优化一个带参数的策略,并且额外学习价值函数,帮助策略函数更好的学习</p>
<ul>
<li><p>Actor学习策略 <span class="math display">\[
\theta \leftarrow \theta+\alpha\sum_{t}^T\psi_t\nabla_{\theta}\ log\
\pi_{\theta}(a|s)
\]</span> 其中<span class="math inline">\(\psi_t\)</span>有多种</p></li>
<li><p>Critic学习价值函数,类似DQN,定义损失函数如下 <span
class="math display">\[
L(w)=\frac{1}{2}(r+\gamma V_{w}(s_{t+1})-V_w(s_t))^2
\]</span></p></li>
</ul>
<p> 梯度</p>
<p><br />
<span class="math display">\[
\nabla_w L(w)=-(r+\gamma V_{w}(s_{t+1})-V_w(s_t))\nabla_w V_w(s_t)
\]</span></p>
<h2 id="trpo算法">TRPO算法</h2>
<p>策略优化算法通过直接优化策略来找到最优策略,通常使用梯度下降的方法,然而有时会导致策略更新过大,从而使得新策略的性能不稳定甚至变差。因此需要保证新策略不会偏离当前策略太远,进而使得每次更新后策略的性能稳定提升。</p>
<p>定义新旧策略的目标函数的差距: <span class="math display">\[
\begin{align}
J(\theta')-J(\theta)&=E_{\pi_{\theta'}}\left[\sum^{\infty}_{t=0}\gamma^t[r(s_t,s_t)+\gamma
V^{\pi_{\theta}}(s_{t+1})-V^{\pi_{\theta}}(s_{t})]\right]\\
&:=E_{\pi_{\theta'}}\left[\sum^{\infty}_{t=0}\gamma^t
A^{\pi_{\theta}}(s_t,a_t) \right]\\
&=\frac{1}{1-\gamma}E_{s\sim v^{\pi_{\theta'}}}E_{a\sim
\pi_{\theta'}(·|s)}[A^{\pi_{\theta}}(s,a)]
\end{align}
\]</span> 利用<span
class="math inline">\(v^{\pi_{\theta}}(s)=(1-\gamma)\sum^{\infty}_{t=0}\gamma^tP^{\pi}_{t}(s)\)</span>因此,只要新的策略保证<span
class="math inline">\(E_{s\sim v^{\pi_{\theta'}}}E_{a\sim
\pi_{\theta'}}(·|s)[A^{\pi_{\theta}}(s,a)]\geq 0\)</span>即可。</p>
<p>假设:新旧策略非常接近,状态访问分布变化小。因此直接采用旧策略的状态分布,得到替代的优化目标
<span class="math display">\[
L_{\theta}(\theta')=J(\theta)+E_{s\sim v^{\pi_{\theta}}}E_{a\sim
\pi_{\theta}(·|s)}[\frac{\pi_{\theta'}(a|s)}{\pi_{\theta}(a|s)}A^{\pi_{\theta}}(s,a)]
\]</span> 为了限制新旧策略,因此引入KL散度,整体的优化公式 <span
class="math display">\[
max_{\theta'}L_{\theta}(\theta') s.t.E_{s\sim
v^{\pi_{\theta}}}\left[D_{KL}(\pi_{\theta},\pi_{\theta'})\right]
\]</span></p>
<h3 id="近似求解">近似求解</h3>
<p>参考<a
href="https://hrl.boyuai.com/chapter/2/trpo%E7%AE%97%E6%B3%95">动手学强化学习</a></p>
<h2 id="ppo">PPO</h2>
<p>直接将KL散度放到目标函数中, <span class="math display">\[
arg\ max_{\theta'}E_{s\sim v^{\pi_{\theta}}}E_{a\sim
\pi_{\theta}(·|s)}[\frac{\pi_{\theta'}(a|s)}{\pi_{\theta}(a|s)}A^{\pi_{\theta}}(s,a)-\beta
D_{KL}(\pi_{\theta},\pi_{\theta'})]
\]</span></p>
<h3 id="ppo惩罚">PPO惩罚</h3>
<p>令<span
class="math inline">\(d_k=D_{KL}^{v^{\pi_{\theta}}}(\pi_{\theta},\pi_{\theta'})\)</span>,<span
class="math inline">\(\beta\)</span>的更新规则如下: <span
class="math display">\[
\beta_{k+1}=
\begin{cases}
\frac{\beta_k}{2},\ 如果\ d_k < \frac{\delta}{1.5} \\
\beta_k*2,\ 如果\ d_k > \delta*1.5 \\
\beta_k, 否则\\
\end{cases}
\]</span></p>
<h3 id="ppo截断">PPO截断</h3>
<p><span class="math display">\[
\arg\max_{\theta} \mathbb{E}_{s \sim \nu} \mathbb{E}_{a \sim
\pi_{\theta_k}(\cdot|s)} \left[ \min \left(
\frac{\pi_{\theta}(a|s)}{\pi_{\theta_k}(a|s)} A^{\pi_{\theta_k}}(s, a),
\text{clip} \left( \frac{\pi_{\theta}(a|s)}{\pi_{\theta_k}(a|s)}, 1 -
\epsilon, 1 + \epsilon \right) A^{\pi_{\theta_k}}(s, a) \right) \right]
\]</span></p>
<p>相当于限制住优势函数,如果<span
class="math inline">\(A^{\pi_{\theta_k}}(s,
a)>0\)</span>,最大化这个式子会增加<span
class="math inline">\(\frac{\pi_{\theta}(a|s)}{\pi_{\theta_k}(a|s)}\)</span>,但是不会超过<span
class="math inline">\(1+\epsilon\)</span>,如果<span
class="math inline">\(A^{\pi_{\theta_k}}(s,
a)<0\)</span>,最大化这个式子会减小<span
class="math inline">\(\frac{\pi_{\theta}(a|s)}{\pi_{\theta_k}(a|s)}\)</span>,但是不会超过<span
class="math inline">\(1-\epsilon\)</span>。</p>
]]></content>
</entry>
<entry>
<title>Android介绍</title>
<url>/2024/07/20/android/</url>
<content><![CDATA[<p>此文章是暑陪的时候写的,但是实际上就是参考官网的教程copy了一份。
<span id="more"></span> # Android</p>
<h2 id="创建-android-应用">创建 Android 应用</h2>
<h3 id="使用模版创建项目">使用模版创建项目</h3>
<ol type="1">
<li>打开 Android Studio后,我们将看到类似的界面 <img
src="/images/kotlin/image-5.png" alt="alt text" /></li>
<li>点击 New project 之后,出现类似的界面 <img
src="/images/kotlin/image-6.png" alt="alt text" /></li>
<li>我们选择 Empty Activity ,看到如下界面 <img
src="/images/kotlin/image-7.png" alt="alt text" />
<ul>
<li>Name 字段用于输入项目名称。本次课程,请输入“Greeting Card”。</li>
<li>保持 Package name
字段不变。该字段用于指定文件在文件结构中的组织方式。在本例中,软件包名称将会指定为
com.example.greetingcard。</li>
<li>保持 Save location
字段不变。该字段用于指定保存与项目相关的所有文件的位置。请记下这些文件在计算机上的保存位置,以便查找文件。</li>
<li>在 Language 字段中,系统已选择
Kotlin。“Language”字段用于指定在构建项目时所采用的编程语言。由于 Compose
仅与 Kotlin 兼容,因此无法更改此字段。 然后点击完成,等待一会</li>
</ul></li>
<li>然后点击右上角的 <img src="/images/kotlin/image-8.png"
alt="alt text" />,可同时查看代码和设计。这个时候将会有三个区域 <img
src="/images/kotlin/image-9.png" alt="alt text" />
<ul>
<li>最左边的区域用于显示项目的文件和文件夹</li>
<li>中间的区域是修改代码的地方</li>
<li>右边的区域是预览应用外观的地方 <img
src="/images/kotlin/image-10.png" alt="alt text" />
可能最开始看到这样的界面,点击 Build &
Refresh。构建可能需要花一些时间,不过完成后,预览便会显示一个内容为
Hello Android! 的文本框。</li>
</ul></li>
</ol>
<h3 id="更新文本">更新文本</h3>
<p>打开 MainActivity.kt 文件的 Code
视图。此代码中有一些自动生成的函数,具体而言就是 onCreate() 和
setContent() 函数。 <img src="/images/kotlin/image-11.png"
alt="alt text" /> onCreate()
函数是此应用的入口点,并会调用其他函数来构建 UI。在 Kotlin
程序中,main() 函数是 Kotlin 编译器在代码中开始编译的特定位置;在
Android 应用中,则是由 onCreate() 函数来担任这个角色。</p>
<p>onCreate() 函数中的 setContent()
函数用于通过可组合函数定义布局。任何标有 <span class="citation"
data-cites="Composable">@Composable</span> 注解的函数都可通过
setContent() 函数或其他可组合函数进行调用。该注解可告知 Kotlin 编译器
Jetpack Compose 使用的这个函数会生成 UI。</p>
<p>接下来,查看 Greeting() 函数。Greeting()
函数是一种可组合函数;请留意它上方的 <span class="citation"
data-cites="Composable">@Composable</span>
注解。可组合函数会接受一些输入并生成屏幕上显示的内容。 <img
src="/images/kotlin/image-12.png" alt="alt text" />
虽然我们在前面已经学习了函数,但是可组合函数还有一些不同之处: - <span
class="citation" data-cites="Composable">@Composable</span>
函数名称采用首字母大写形式。 - 需在该函数前面添加 <span class="citation"
data-cites="Composable">@Composable</span> 注解。 - <span
class="citation" data-cites="Composable">@Composable</span>
函数无法返回任何内容。</p>
<p>大家可以尝试加入不同的文本,我就以下面的为例子 <img
src="/images/kotlin/image-13.png" alt="alt text" />
然后最右边的视框会更新文字。</p>
<p>GreetingPreview()
无需构建整个应用就能查看应用的外观。若要使其成为预览函数,需要添加 <span
class="citation" data-cites="Preview">@Preview</span> 注解。</p>
<p><span class="citation" data-cites="Preview">@Preview</span>
注解可以接收名为 showBackground 的参数。如果 showBackground 设置为
true,则会向应用预览添加背景。如果使用深色主题,就可以看到如下所示的区别了。</p>
<p>可以在 GreetingPreview() 更新名字,显示预览。</p>
<h3 id="更改背景颜色">更改背景颜色</h3>
<p>若要为自我介绍设置不同的背景颜色,需要使用 Surface
将文本包围起来。Surface
是一个容器,代表界面的某一部分,可以在其中更改外观(如背景颜色或边框)。
<img src="/images/kotlin/image-14.png" alt="alt text" />
如果有报错的话,悬停,然后 import 即可 <img
src="/images/kotlin/image-15.png" alt="alt text" />
然后我们把颜色参数传进去即可 <img src="/images/kotlin/image-16.png"
alt="alt text" /></p>
<h3 id="添加内边距">添加内边距</h3>
<p>Modifier 用于扩充或修饰可组合项。可以使用的其中一个 Modifier 是
padding
修饰符,它会在元素周围应用空格(在本例中,是在文本周围添加空格)。为此,请使用
Modifier.padding() 函数。 <img src="/images/kotlin/image-17.png"
alt="alt text" /></p>
<h3 id="在-android-模拟器上运行应用">在 Android 模拟器上运行应用</h3>
<p>我们将使用设备管理器来创建 Android 虚拟设备 (AVD)。AVD
是移动设备的软件版本(也称为模拟器),可在计算机上运行,以及模拟特定类型
Android 设备的配置。它可以是任何手机、平板电脑、电视、手表或 Android
Auto 设备。我们将使用 AVD 来运行 Greeting Card 应用。</p>
<h4 id="创建-avd">创建 AVD</h4>
<ol type="1">
<li><p>在 Android Studio 中,依次选择 Tools > Device Manager。 <img
src="/images/kotlin/image-18.png" alt="alt text" /> 系统随即会打开
Device Manager
对话框。如果以前创建过虚拟设备,则此对话框中会列出该设备。 <img
src="/images/kotlin/image-19.png" alt="alt text" /></p></li>
<li><p>我们点击左上角的加号,然后点击 Create virtual device 系统会显示出
Virtual Device Configuration 对话框。 <img
src="/images/kotlin/image-20.png" alt="alt text" />
该对话框会显示一个预配置设备的列表(按类别整理),可以从中选择。对于每种设备,该表都提供了相应列来分别显示其屏幕尺寸(以英寸为单位)、屏幕分辨率(以像素为单位)和像素密度(每英寸像素数)。</p></li>
<li><p>选择 Phone 类别。</p></li>
<li><p>选择所需手机(例如 Pixel 8),然后点击 Next。
此步骤会打开另一个屏幕,供选择在虚拟设备上运行的 Android
版本。这可在不同版本的 Android 系统上测试应用。 <img
src="/images/kotlin/image-21.png" alt="alt text" /> 大家 download
即可,点击 Next,看到如下界面,可以在其中为设备选择其他配置详情。 <img
src="/images/kotlin/image-22.png" alt="alt text" /></p></li>
<li><p>在 AVD Name 字段中,输入 AVD
的名称,或使用默认名称。保持其余字段不变。</p></li>
<li><p>点击 Finish。 系统会返回到 Android Virtual Device Manager
窗格。</p></li>
</ol>
<h4 id="在-android-模拟器上运行应用-1">在 Android 模拟器上运行应用</h4>
<ol type="1">
<li>在 Android Studio 窗口顶部选择创建的虚拟设备。 <img
src="/images/kotlin/image-23.png" alt="alt text" /></li>
<li>点击旁边的绿色三角 <img src="/images/kotlin/image-24.png"
alt="alt text" /></li>
<li>模拟器首次启动需要一些时间,有可能是几分钟。虚拟设备应该会在代码编辑器旁边打开。
<img src="/images/kotlin/image-25.png" alt="alt text" />
当应用准备就绪后,便会在虚拟设备上打开。 <img
src="/images/kotlin/image-26.png" alt="alt text" /></li>
</ol>
<h2 id="构建基本布局">构建基本布局</h2>
<p>构建一个显示文本和图像的、界面简单的 Android 应用。</p>
<h3 id="jetpack-compose-介绍">Jetpack Compose 介绍</h3>
<p>下面我们来介绍刚刚前面提到的 compose。</p>
<p>首先,Jetpack Compose 是用于构建 Android 界面的新款工具包。Compose
使用更少的代码、强大的工具和直观的 Kotlin 功能,可以帮助简化并加快
Android 界面开发。借助
Compose,可以通过定义一组函数来构建界面,这些函数称为可组合函数,它们会接受数据并描述界面元素。</p>
<h4 id="可组合函数">可组合函数</h4>
<p>在 Compose 中,可组合函数是界面的基本构建块。可组合函数: -
描述界面中的某一部分。 - 不会返回任何内容。 -
接受一些输入并生成屏幕上显示的内容。</p>
<h4 id="注解">注解</h4>
<p>注解是用于在代码中附加额外信息的方式。此类信息可以帮助 Jetpack
Compose 编译器等工具和其他开发者理解应用的代码。</p>
<p>若要应用注解,只需在要注解的声明开头为其名称(注解)添加 @
字符作为前缀即可。可以为包括属性、函数和类在内的不同代码元素添加注解。
<img src="/images/kotlin/image-27.png" alt="alt text" /></p>
<h5 id="带形参的注解">带形参的注解</h5>
<p>注解可以接受形参。形参可以为处理它们的工具提供额外信息。就像我们之前用到的
<span class="citation" data-cites="Preview">@Preview</span>
注解,可以加入不同的形参。 <img src="/images/kotlin/image-29.png"
alt="alt text" /> <img src="/images/kotlin/image-30.png"
alt="alt text" /> <img src="/images/kotlin/image-31.png"
alt="alt text" /></p>
<p>当然,也可以传递多个参数 <img src="/images/kotlin/image-32.png"
alt="alt text" /></p>
<h4 id="可组合函数示例">可组合函数示例</h4>
<p>可组合函数带有 <code>@Composable</code>
注解。所有可组合函数都必须带有此注解。此注解可告知 Compose
编译器:此函数用于将数据转换为界面。</p>
<p>以下代码段是一个简单的可组合函数示例,该函数接受传递的数据(<code>name</code>
函数参数)并用其在屏幕上渲染文本元素。</p>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Composable</span></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">Greeting</span><span class="params">(name: <span class="type">String</span>)</span></span> {</span><br><span class="line"> Text(text = <span class="string">"Hello <span class="variable">$name</span>!"</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>关于可组合函数的几点说明: - Jetpack Compose
是围绕可组合函数构建的。这些函数可让以程序化方式定义应用的界面,只需描述应用界面的外观,而不必关注界面的构建过程。如需创建可组合函数,只需将
<code>@Composable</code> 注解添加到函数名称中即可。 -
可组合函数可以接受一些实参,用来让应用逻辑描述或修改界面。在本例中,界面元素接受一个
<code>String</code>,以便在问候用户时称呼姓名。</p>
<h4 id="可组合函数名称">可组合函数名称</h4>
<p>不返回任何内容且带有 <code>@Composable</code> 注解的 Compose
函数必须使用 Pascal 命名法命名。Pascal
命名法是一种命名惯例,采用这种命名法时,复合词中每个单词的首字母大写。Pascal
命名法与骆驼命名法之间的区别在于:在 Pascal
命名法中,所有单词的首字母都大写;而在骆驼命名法中,首字母可以是大写或小写。</p>
<p>Compose 函数:</p>
<ul>
<li>必须是名词:<code>DoneButton()</code></li>
<li>不能是动词或动词短语:<code>DrawTextField()</code></li>
<li>不能是名词性介词:<code>TextFieldWithLink()</code></li>
<li>不能是形容词:<code>Bright()</code></li>
<li>不能是副词:<code>Outside()</code></li>
<li>名词可以添加描述性形容词作为前缀:<code>RoundIcon()</code></li>
</ul>
<h3 id="添加新的文本元素">添加新的文本元素</h3>
<ol type="1">
<li>删除 <code>Greeting</code> 函数以及调用,并将
<code>GreetingPreview</code> 替换为
<code>HappyBirthdayPreview</code>。</li>
<li>在 <code>BirthdayCardPreview()</code> 函数前,添加一个名为
<code>GreetingText()</code> 的新函数。不要忘记在该函数前添加
<code>@Composable</code> 注解,因为该函数是一个用于描述
<code>Text</code> 可组合项的 Compose 函数。</li>
</ol>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Composable</span></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">GreetingText</span><span class="params">()</span></span> {</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<ol start="3" type="1">
<li>最好让可组合项接受 <code>Modifier</code> 形参,并将该
<code>modifier</code> 传递给其第一个子项。</li>
</ol>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Composable</span></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">GreetingText</span><span class="params">(modifier: <span class="type">Modifier</span> = Modifier)</span></span> {</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<ol start="4" type="1">
<li>将类型为 <code>String</code> 的 <code>message</code> 形参添加到
<code>GreetingText()</code> 可组合函数中。</li>
</ol>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Composable</span></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">GreetingText</span><span class="params">(message: <span class="type">String</span>, modifier: <span class="type">Modifier</span> = Modifier)</span></span> {</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<ol start="5" type="1">
<li>在 <code>GreetingText()</code> 函数中,添加一个 <code>Text</code>
可组合项并传入文本消息作为具体实参。</li>
</ol>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Composable</span></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">GreetingText</span><span class="params">(message: <span class="type">String</span>, modifier: <span class="type">Modifier</span> = Modifier)</span></span> {</span><br><span class="line"> Text(</span><br><span class="line"> text = message</span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>此 <code>GreetingText()</code>
函数用于在界面中显示文本。为此,它会调用 <code>Text()</code>
可组合函数。</p>
<ol start="6" type="1">
<li><p>预览函数 在 <code>BirthdayCardPreview()</code> 函数中调用
<code>GreetingText()</code> 函数。 将一个 <code>String</code> 参数传递给
<code>GreetingText()</code> 函数。</p></li>
<li><p>更改字体大小 可以到 <code>GreetingText()</code> 函数中的
<code>Text()</code> 可组合项。向 <code>Text()</code> 函数传递
<code>fontSize</code> 实参作为第二个具名实参,并将其值设为
<code>100.sp</code>。</p></li>
</ol>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Composable</span></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">GreetingText</span><span class="params">(message: <span class="type">String</span>, modifier: <span class="type">Modifier</span> = Modifier)</span></span> {</span><br><span class="line"> Text(</span><br><span class="line"> text = message,</span><br><span class="line"> fontSize = <span class="number">100.</span>sp</span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><img src="/images/kotlin/image-33.png" alt="alt text" /> 8.
消息重叠的原因是需要指定行高。更新 <code>Text</code>
可组合项以包含行高。</p>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Composable</span></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">GreetingText</span><span class="params">(message: <span class="type">String</span>, modifier: <span class="type">Modifier</span> = Modifier)</span></span> {</span><br><span class="line"> Text(</span><br><span class="line"> text = message,</span><br><span class="line"> fontSize = <span class="number">100.</span>sp,</span><br><span class="line"> lineHeight = <span class="number">110.</span>sp,</span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><img src="/images/kotlin/image-34.png" alt="alt text" /> 9.
添加一个新的文本元素 在 <code>GreetingText()</code>
函数,向该函数传递一个类型为 <code>String</code> 的 <code>from</code>
参数作为的签名。</p>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">GreetingText</span><span class="params">(message: <span class="type">String</span>, from: <span class="type">String</span>, modifier: <span class="type">Modifier</span> = Modifier)</span></span></span><br></pre></td></tr></table></figure>
<p>在生日祝福语 <code>Text</code> 可组合项之后,再添加一个接受
<code>text</code> 实参(其值设为 <code>from</code>)的 <code>Text</code>
可组合项。</p>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Composable</span></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">GreetingText</span><span class="params">(message: <span class="type">String</span>, from: <span class="type">String</span>, modifier: <span class="type">Modifier</span> = Modifier)</span></span> {</span><br><span class="line"> Text(</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> )</span><br><span class="line"> Text(</span><br><span class="line"> text = from</span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>添加一个 <code>fontSize</code> 具名实参,并将其值设为
<code>36.sp</code>。</p>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line">Text(</span><br><span class="line"> text = from,</span><br><span class="line"> fontSize = <span class="number">36.</span>sp</span><br><span class="line">)</span><br></pre></td></tr></table></figure>
<p>在 <code>BirthdayCardPreview()</code> 函数再添加一个
<code>String</code> 实参来为生日卡签名。 <img
src="/images/kotlin/image-35.png" alt="alt text" />
一个可组合函数可能会描述多个界面元素。不过,如果未提供有关如何排列这些元素的指导,Compose
可能会以不喜欢的方式排列它们。例如,上面的代码生成了两个相互重叠的文本元素,因为没有提供有关如何排列这两个可组合项的指导。</p>
<h3 id="将文本元素排列成一行或一列">将文本元素排列成一行或一列</h3>
<h4 id="界面层次结构">界面层次结构</h4>
<p>界面层次结构基于包含机制,意即一个组件可以包含一个或多个组件,有时会用“父级”和“子级”这两个词来表述。这种说法是指,父界面元素包含子界面元素,而子界面元素还可以继续包含子界面元素。在此部分中,将了解可用作父界面元素的
<code>Column</code>、<code>Row</code> 和 <code>Box</code> 可组合项。</p>
<p>Compose 中的 3 个基本标准布局元素是
<code>Column</code>、<code>Row</code> 和 <code>Box</code> 可组合项。</p>
<p><code>Column</code>、<code>Row</code> 和 <code>Box</code>
都是接受可组合内容作为参数的可组合函数,因此可以在这些布局元素内放置项目。例如,<code>Row</code>
可组合项中的各个子元素彼此相邻地水平放置成一行。</p>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="comment">// Don't copy.</span></span><br><span class="line">Row {</span><br><span class="line"> Text(<span class="string">"First Column"</span>)</span><br><span class="line"> Text(<span class="string">"Second Column"</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure>
<img src="/images/kotlin/image-36.png" alt="alt text" />
<figcaption aria-hidden="true">alt text</figcaption>
</figure>
<p>因此,在我们的函数中可以使用 <code>Row</code>
对文字进行布局(暂时将生日祝福语的字体大小更改为
<code>30.sp</code>)。</p>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Composable</span></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">GreetingText</span><span class="params">(message: <span class="type">String</span>, from: <span class="type">String</span>, modifier: <span class="type">Modifier</span> = Modifier)</span></span> {</span><br><span class="line"> Row {</span><br><span class="line"> Text(</span><br><span class="line"> text = message,</span><br><span class="line"> fontSize = <span class="number">30.</span>sp,</span><br><span class="line"> lineHeight = <span class="number">110.</span>sp,</span><br><span class="line"> )</span><br><span class="line"> Text(</span><br><span class="line"> text = from,</span><br><span class="line"> fontSize = <span class="number">36.</span>sp</span><br><span class="line"> )</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><img src="/images/kotlin/image-37.png" alt="alt text" />
我们也可以使用 <code>Column</code> 来将文本元素排成一列。</p>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Composable</span></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">GreetingText</span><span class="params">(message: <span class="type">String</span>, from: <span class="type">String</span>, modifier: <span class="type">Modifier</span> = Modifier)</span></span> {</span><br><span class="line"> Column {</span><br><span class="line"> Text(</span><br><span class="line"> text = message,</span><br><span class="line"> fontSize = <span class="number">100.</span>sp,</span><br><span class="line"> lineHeight = <span class="number">110.</span>sp,</span><br><span class="line"> )</span><br><span class="line"> Text(</span><br><span class="line"> text = from,</span><br><span class="line"> fontSize = <span class="number">36.</span>sp</span><br><span class="line"> )</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure>
<img src="/images/kotlin/image-38.png" alt="alt text" />
<figcaption aria-hidden="true">alt text</figcaption>
</figure>
<h3 id="在模拟器上运行">在模拟器上运行</h3>
<p>我们可以回到 <code>onCreate()</code> 函数,从 <code>Scaffold</code>
代码块调用 <code>GreetingText()</code> 函数,传递
<code>GreetingText()</code> 函数、的生日祝福和签名。</p>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MainActivity</span> : <span class="type">ComponentActivity</span>() {</span><br><span class="line"> <span class="keyword">override</span> <span class="function"><span class="keyword">fun</span> <span class="title">onCreate</span><span class="params">(savedInstanceState: <span class="type">Bundle</span>?)</span></span> {</span><br><span class="line"> <span class="keyword">super</span>.onCreate(savedInstanceState)</span><br><span class="line"> enableEdgeToEdge()</span><br><span class="line"> setContent {</span><br><span class="line"> HappyBirthdayTheme {</span><br><span class="line"> Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -></span><br><span class="line"> GreetingText(</span><br><span class="line"> message = <span class="string">"Happy Birthday Sam!"</span>,</span><br><span class="line"> from = <span class="string">"From Emma"</span>,</span><br><span class="line"> modifier = Modifier.padding(innerPadding))</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><img src="/images/kotlin/image-39.png" alt="alt text" />
如需在屏幕中心对齐问候语,请添加一个名为
<code>verticalArrangement</code> 的形参,并将其设置为
<code>Arrangement.Center</code>。围绕列添加 <code>8.dp</code>
内边距。最好以 <code>4.dp</code> 为增量使用内边距值。</p>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Composable</span></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">GreetingText</span><span class="params">(message: <span class="type">String</span>, from: <span class="type">String</span>, modifier: <span class="type">Modifier</span> = Modifier)</span></span> {</span><br><span class="line"> Column(</span><br><span class="line"> verticalArrangement = Arrangement.Center,</span><br><span class="line"> modifier = modifier.padding(<span class="number">8.</span>dp)</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><br></pre></td></tr></table></figure>
<p>也可以使用 <code>textAlign</code> 将问候语文本居中对齐。</p>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line">Text(</span><br><span class="line"> text = message,</span><br><span class="line"> fontSize = <span class="number">100.</span>sp,</span><br><span class="line"> lineHeight = <span class="number">116.</span>sp,</span><br><span class="line"> textAlign = TextAlign.Center</span><br><span class="line">)</span><br></pre></td></tr></table></figure>
<p>为签名添加内边距,并使其右对齐。</p>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line">Text(</span><br><span class="line"> text = from,</span><br><span class="line"> fontSize = <span class="number">36.</span>sp,</span><br><span class="line"> modifier = Modifier</span><br><span class="line"> .padding(<span class="number">16.</span>dp)</span><br><span class="line"> .align(alignment = Alignment.End)</span><br><span class="line">)</span><br></pre></td></tr></table></figure>
<figure>
<img src="/images/kotlin/image-40.png" alt="alt text" />
<figcaption aria-hidden="true">alt text</figcaption>
</figure>
]]></content>
</entry>
<entry>
<title>Android Studio介绍</title>
<url>/2024/07/29/android_studio/</url>
<content><![CDATA[<p>此文章是暑陪的时候写的,但是实际上就是参考官网的教程copy了一份。
<span id="more"></span> ## Android Studio环境搭建</p>
<h3 id="指南">指南</h3>
<p>我们为各位同学提供谷歌的<a
href="https://developer.android.com/studio?hl=zh-cn">官方教程</a>进行参考,请按教程PDF中的第1.1节进行Android
Studio的配置。</p>
<p>此外,使用windows系统建议在C:.gradle.gradle文件(<a
href="https://cloud.tsinghua.edu.cn/f/ae3cb15f675946dbba9e/?dl=1">点击下载</a>),这样可以使用阿里云镜像提高gradle下载的速度,Mac版参考链接<a
href="https://blog.csdn.net/mickjoust/article/details/100917237">点击这里</a>。</p>
<h3 id="安装android-studio">2.1 安装Android Studio</h3>
<p>官方下载安装地址: <a
href="https://developer.android.com/studio?hl=zh-cn">https://developer.android.com/studio?hl=zh-cn</a></p>
<p>在用Android
Studio创建项目后可能遇到<code>gradle sync failed</code>错误,这是由于国内网络无法直连github.com。</p>
<h4 id="gradle换源">2.1.1 Gradle换源</h4>
<p>解决这个问题的方法之一是更换gradle的下载地址:</p>
<ol type="1">
<li>在用户目录<code>/.gradle/</code>文件夹下创建一个<code>init.gradle</code>文件</li>
<li>在<code>init.gradle</code>文件中输入以下内容</li>
</ol>
<figure class="highlight groovy"><table><tr><td class="code"><pre><span class="line">allprojects {</span><br><span class="line"> repositories {</span><br><span class="line"> <span class="keyword">def</span> ALIYUN_REPOSITORY_URL = <span class="string">'http://maven.aliyun.com/nexus/content/groups/public'</span></span><br><span class="line"> <span class="keyword">def</span> ALIYUN_JCENTER_URL = <span class="string">'http://maven.aliyun.com/nexus/content/repositories/jcenter'</span></span><br><span class="line"> all {</span><br><span class="line"> ArtifactRepository repo -></span><br><span class="line"> <span class="keyword">if</span> (repo <span class="keyword">instanceof</span> MavenArtifactRepository) {</span><br><span class="line"> <span class="keyword">def</span> url = repo.url.toString()</span><br><span class="line"> <span class="keyword">if</span> (url.startsWith(<span class="string">'https://repo1.maven.org/maven2'</span>)) {</span><br><span class="line"> project.logger.lifecycle <span class="string">"Repository ${repo.url} replaced by $ALIYUN_REPOSITORY_URL."</span></span><br><span class="line"> remove repo</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (url.startsWith(<span class="string">'https://jcenter.bintray.com/'</span>)) {</span><br><span class="line"> project.logger.lifecycle <span class="string">"Repository ${repo.url} replaced by $ALIYUN_JCENTER_URL."</span></span><br><span class="line"> remove repo</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"> maven {</span><br><span class="line"> allowInsecureProtocol = <span class="literal">true</span></span><br><span class="line"> url ALIYUN_REPOSITORY_URL</span><br><span class="line"> url ALIYUN_JCENTER_URL</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>配置完后点击重新同步,Android Studio便可以正常下载相关文件。</p>
<h3 id="android-studio配置代理">2.1.2 Android Studio配置代理</h3>
<p>解决这个问题的方法之一是为Android Studio配置代理:</p>
<ol type="1">
<li>选择 <code>file->settings</code></li>
<li>选择找到 <code>HTTP Proxy</code></li>
</ol>
<figure>
<img src="/images/kotlin/image-41.png" alt="alt text" />
<figcaption aria-hidden="true">alt text</figcaption>
</figure>
<p>配置完代理后点击重新同步,Android Studio便可以正常下载相关文件。</p>
<h3 id="直接下载gradle依赖包">2.1.3 直接下载Gradle依赖包</h3>
<p>可以参考这个教程: <a
href="https://blog.csdn.net/qq_42257666/article/details/129651505">https://blog.csdn.net/qq_42257666/article/details/129651505</a></p>
]]></content>
</entry>
<entry>
<title>常见命令</title>
<url>/2024/10/03/command/</url>
<content><![CDATA[<p>记录了常见的一些命令,包括docker,git,ssh,proxy,scp等。</p>
<h1 id="docker">docker</h1>
<h2 id="基础命令">基础命令</h2>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">docker run --gpus all --name LM -it --security-opt seccomp=unconfined -v /home/sunyuanxu/code:/workspace/code -v /raid/sunyuanxu:/workspace/raid nvcr.io/nvidia/pytorch:24.05-py3</span><br><span class="line"></span><br><span class="line">docker start <container_id_or_name></span><br><span class="line"></span><br><span class="line">docker <span class="built_in">exec</span> -it <container_id_or_name> /bin/bash</span><br></pre></td></tr></table></figure>
<span id="more"></span>
<h1 id="git">git</h1>
<h2 id="基础命令-1">基础命令</h2>
<h3 id="init">Init</h3>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">git init</span><br><span class="line">git remote add origin url</span><br><span class="line">git add .</span><br><span class="line">git commit -m "Initial commit"</span><br><span class="line">git checkout -b new-branch</span><br><span class="line">git push -u origin new-branch</span><br></pre></td></tr></table></figure>
<h3 id="branch">Branch</h3>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">git branch</span><br><span class="line">git branch -r(remote)</span><br></pre></td></tr></table></figure>
<h3 id="checkout">Checkout</h3>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">git checkout branch_name</span><br><span class="line">git checkout -b local_branch_name origin/remote_branch_name</span><br></pre></td></tr></table></figure>
<h3 id="lfs">LFS</h3>
<p>处理文件过大问题 <figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">git lfs install</span><br><span class="line">git lfs track "file"</span><br></pre></td></tr></table></figure> # ssh ## 常见命令</p>
<p>这个命令通过 <code>ssh</code>
进行远程连接,并设置了一个反向代理通道。详细解释如下:</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">ssh -R 7890:localhost:7890 username@ip -p port -A -i ~/.ssh/id_rsa</span><br></pre></td></tr></table></figure>
<h3 id="命令结构">1. 命令结构</h3>
<p><code>ssh</code> 是用于通过 SSH(Secure
Shell)协议进行远程连接的命令。这个命令的各个选项含义如下:</p>
<h4 id="r-7890localhost7890"><code>-R 7890:localhost:7890</code></h4>
<ul>
<li><strong>反向端口转发</strong>:<code>-R</code>
选项用于创建一个反向端口转发。
<ul>
<li><code>7890</code>(左边的部分):这是远程主机(<code>username@ip</code>
这台主机)上的端口号。</li>
<li><code>localhost</code>:这是指向 SSH
客户端机器的主机名,即本地主机(你正在运行这个命令的机器)。</li>
<li><code>7890</code>(右边的部分):这是本地机器上开放的端口号。</li>
</ul>
<strong>功能</strong>:
<ul>
<li>当你连接到远程主机 <code>username@ip</code> 后,远程主机上的
<code>7890</code> 端口就会被绑定到你的本地机器的 <code>7890</code>
端口。</li>
<li>任何连接到远程主机的 <code>7890</code> 端口的数据流都会通过 SSH
隧道安全地传递到本地主机的 <code>7890</code>
端口。这通常用于在远程主机上通过本地资源进行网络请求。</li>
</ul></li>
</ul>
<h4 id="usernameip"><code>username@ip</code></h4>
<ul>
<li><strong>用户名和 IP 地址</strong>:
<ul>
<li><code>username</code>:远程主机上的用户名,表示你要用哪个用户身份登录到远程服务器。</li>
<li><code>ip</code>:远程主机的 IP
地址或域名。你通过该地址来连接到远程服务器。</li>
</ul></li>
</ul>
<h4 id="p-port"><code>-p port</code></h4>
<ul>
<li><strong>指定端口</strong>:
<ul>
<li><code>-p</code> 用于指定远程主机上的 SSH 服务端口号。默认情况下,SSH
服务器使用端口 <code>22</code>,但有时会改为其他端口以提高安全性。</li>
</ul></li>
</ul>
<h4 id="a"><code>-A</code></h4>
<ul>
<li><strong>代理转发</strong>:
<ul>
<li><code>-A</code> 选项表示启用 SSH 代理转发(agent
forwarding)。代理转发使得你可以在登录远程主机后,通过该远程主机来访问其他服务器而不需要再次输入密码。</li>
<li>这样,当你通过该远程主机再连接其他服务器时,会自动使用你本地的 SSH
密钥,简化连接过程。</li>
</ul></li>
</ul>
<h4 id="i-.sshid_rsa"><code>-i ~/.ssh/id_rsa</code></h4>
<ul>
<li><strong>指定私钥文件</strong>:
<ul>
<li><code>-i</code> 用于指定一个 SSH 私钥文件路径。</li>
<li><code>~/.ssh/id_rsa</code>
是存储在你本地的私钥文件,用于身份验证。如果你使用其他名字的私钥文件,你需要修改这里的路径。</li>
</ul></li>
</ul>
<h1 id="安装flash-attn">安装flash-attn</h1>
<p>Install the pre-build wheel list in release page works for me, in my
case: <figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">pip install https://github.com/Dao-AILab/flash-attention/releases/download/v2.3.3/flash_attn-2.3.3+cu118torch2.0cxx11abiFALSE-cp38-cp38-linux_x86_64.whl</span><br></pre></td></tr></table></figure></p>
<h1 id="mac终端代理">Mac终端代理</h1>
<ol type="1">
<li>修改<code>!/.zshrc</code>,加入下面的命令 <figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># where proxy</span></span><br><span class="line"> <span class="function"><span class="title">proxy</span></span> () {</span><br><span class="line"> <span class="built_in">export</span> http_proxy=<span class="string">"http://127.0.0.1:7890"</span></span><br><span class="line"> <span class="built_in">export</span> https_proxy=<span class="string">"http://127.0.0.1:7890"</span></span><br><span class="line"> <span class="built_in">echo</span> <span class="string">"HTTP Proxy on"</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment"># where noproxy</span></span><br><span class="line"> <span class="function"><span class="title">noproxy</span></span> () {</span><br><span class="line"> <span class="built_in">unset</span> http_proxy</span><br><span class="line"> <span class="built_in">unset</span> https_proxy</span><br><span class="line"> <span class="built_in">echo</span> <span class="string">"HTTP Proxy off"</span></span><br><span class="line"> }</span><br></pre></td></tr></table></figure></li>
<li><code>source ~/.zshrc</code></li>
<li><code>proxy</code>(you will see "HTTP Proxy on")</li>
<li><code>curl ipinfo.io</code>(查看当前的IP)</li>
</ol>
<h1 id="scp">scp</h1>
<h2 id="两个服务器之间传输">两个服务器之间传输</h2>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">scp -3 sun:/raid/sunyuanxu/jsonl_sum/sum.jsonl code:/share/sunyuanxu/maxcoverage(配合~/.ssh/config使用)</span><br></pre></td></tr></table></figure>
]]></content>
</entry>
<entry>
<title>sftp</title>
<url>/2024/10/03/sftp/</url>
<content><![CDATA[<p>vscode的一个插件,每次我的代码有更新的时候,就需要重写scp,但是使用这个插件之后就不需要我自己手动的去scp了,每当我修改的时候就自动上传过去。
<span id="more"></span> ## 配置方法 1. 打开vscode,使用<code>shift+command+p</code>
2. <code>SFTP:Config</code> 3. 按照类似的方式配置 <figure class="highlight json"><table><tr><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"name"</span><span class="punctuation">:</span> <span class="string">"tj"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"host"</span><span class="punctuation">:</span> <span class="string">"server_ip"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"protocol"</span><span class="punctuation">:</span> <span class="string">"sftp"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"port"</span><span class="punctuation">:</span> <span class="number">2201</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"username"</span><span class="punctuation">:</span> <span class="string">"username"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"remotePath"</span><span class="punctuation">:</span> <span class="string">"path"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"uploadOnSave"</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"useTempFile"</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"openSsh"</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"interactiveAuth"</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"privateKeyPath"</span><span class="punctuation">:</span><span class="string">"~/.ssh/id_rsa"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"passphrase"</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line"> <span class="punctuation">}</span></span><br></pre></td></tr></table></figure></p>
]]></content>
</entry>
<entry>
<title>Kotlin 介绍</title>
<url>/2024/07/18/kotlin/</url>
<content><![CDATA[<p>此文章是暑培的时候写的,但是实际上就是参考官网的教程copy了一份。
<span id="more"></span> ## Kotlin 介绍</p>
<p>Kotlin 是一种现代且成熟的编程语言,由 JetBrains 公司于 2011
年设计和开发,并在 2016 年正式发布。在 2019 年的 Google I/O
大会上,Google 宣布 Kotlin 将成为 Android 开发的首选语言。包括 Google
地图、Google Home、Play、Google 云端硬盘和 Google
信息等应用。其中一个成功案例来自 Google Home
团队,他们将新功能开发工作迁移到 Kotlin 后,代码库大小减少了 33%,NPE
崩溃次数减少了 30%。Kotlin
以其简洁性和强大的功能而闻名,不仅能减少常见的代码错误,还能轻松集成到现有的应用程序中。如果打算构建
Android 应用,建议从 Kotlin 开始,充分利用其一流的功能。</p>
<p>开发者倾向于使用 Kotlin 的原因主要有以下几个:</p>
<ul>
<li><strong>富有表现力且简洁</strong>:使用更少的代码实现更多的功能,减少样板代码,表达更加清晰。</li>
<li><strong>更安全的代码</strong>:Kotlin
提供许多语言特性,帮助避免空指针异常等常见的编程错误。</li>
<li><strong>高度互操作</strong>:Kotlin 与 Java 完全互操作,可以在
Kotlin 代码中调用 Java 代码,或在 Java 代码中调用 Kotlin
代码,让可以在项目中无缝添加 Kotlin 代码。</li>
</ul>
<h2 id="kotlin-语言基础">Kotlin 语言基础</h2>
<p>此教程主要用于Kotlin速成,快速上手。 <a
href="https://play.kotlinlang.org/">在线kotlin</a>编辑器 ###
变量声明</p>
<p>在 Kotlin 中,变量的声明采用两种不同的关键字:<code>val</code> 和
<code>var</code>。</p>
<ul>
<li><code>val</code>
用于声明不可变的变量,即一旦赋值后就不能再更改。</li>
<li><code>var</code> 用于声明可变的变量,即可以多次赋值。</li>
</ul>
<p>例如,<code>count</code> 是一个 <code>Int</code> 类型的变量,初始值为
<code>10</code>:</p>
<figure class="highlight kotlin"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> count: <span class="built_in">Int</span> = <span class="number">10</span></span><br></pre></td></tr></table></figure>
<p><img src="/images/kotlin/image.png" alt="alt text" />
<code>Int</code> 是表示整数的类型之一。Kotlin 还提供了其他数值类型,如
<code>Byte</code>、<code>Short</code>、<code>Long</code>、<code>Float</code>
和
<code>Double</code>,以满足不同的数值需求。以下是这些类型的简要说明:</p>
<p>在 Kotlin
中,有一些常见的基本数据类型。下表逐行列明了各种不同的数据类型,并针对每种数据类型提供了可存储数据类型的说明和示例值。</p>
<table>
<colgroup>
<col style="width: 34%" />
<col style="width: 34%" />
<col style="width: 30%" />
</colgroup>
<thead>
<tr>
<th>Kotlin 数据类型</th>
<th>可包含的数据类型</th>
<th>字面量值示例</th>
</tr>
</thead>
<tbody>
<tr>
<td>String</td>
<td>文本</td>
<td>"Add contact"<br>"Search"<br>"Sign in"</td>
</tr>
<tr>
<td>Int</td>
<td>整数</td>
<td>32<br>1293490<br>-59281</td>
</tr>
<tr>
<td>Double</td>