噪声
\[\varepsilon^2=E_D\left[(y_D-y)^2\right]\]
偏差-方差窘境
-

- 偏向左侧时,训练数据的扰动不足以使学习器产生显著变化,此时偏差主导泛化误差,称为欠拟合现象
-
@@ -306,8 +306,8 @@
- 正则化在损失函数中加入一个与模型复杂度相关的惩罚项,以限制模型的复杂度并防止过拟合
参考文章
-
-
- L1正则化是指权值向量w中各个元素的绝对值之和,可以使得参数稀疏化,即得到的参数是一个稀疏矩阵,进而可以用于特征选择。二维平面图像:
- L2正则化是指权值向量w中各个元素的平方和然后再求平方根,让权值尽可能小,如果参数足够小,数据偏移得多一点也不会对结果造成什么影响,专业一点的说法是抗扰动能力强。二维平面图像:
- L1正则化是指权值向量w中各个元素的绝对值之和,可以使得参数稀疏化,即得到的参数是一个稀疏矩阵,进而可以用于特征选择。二维平面图像:
- L2正则化是指权值向量w中各个元素的平方和然后再求平方根,让权值尽可能小,如果参数足够小,数据偏移得多一点也不会对结果造成什么影响,专业一点的说法是抗扰动能力强。二维平面图像:
- L1正则化是指权值向量w中各个元素的绝对值之和,可以使得参数稀疏化,即得到的参数是一个稀疏矩阵,进而可以用于特征选择。二维平面图像:
偏差-方差窘境
模型训练
@@ -327,7 +327,7 @@强化学习
- 归一化奖励分数、将奖励分数做白化处理
+
RLHF
Reinforcement Learning from Human @@ -335,18 +335,18 @@
RLHF
OpenAI 提出的生成领域(Decoder_only)的新训练范式Policy Gradient
- -+ +
RM+PPO
步骤一、预训练语言模型
- -+ +
步骤二、训练奖励模型 RM
- -+ +
步骤三、用强化学习 PPO 微调
- -+ +
DPO
KTO
ORPO
diff --git a/DL-basic/o_L1.png b/-NLP/DL-basic/o_L1.png similarity index 100% rename from DL-basic/o_L1.png rename to -NLP/DL-basic/o_L1.png diff --git a/DL-basic/o_L2.png b/-NLP/DL-basic/o_L2.png similarity index 100% rename from DL-basic/o_L2.png rename to -NLP/DL-basic/o_L2.png diff --git a/DL-basic/overview_chatgpt.png b/-NLP/DL-basic/overview_chatgpt.png similarity index 100% rename from DL-basic/overview_chatgpt.png rename to -NLP/DL-basic/overview_chatgpt.png diff --git a/Design-Pattern/index.html b/-NLP/Design-Pattern/index.html similarity index 96% rename from Design-Pattern/index.html rename to -NLP/Design-Pattern/index.html index 648d646..757e974 100644 --- a/Design-Pattern/index.html +++ b/-NLP/Design-Pattern/index.html @@ -22,7 +22,7 @@ - + @@ -33,11 +33,11 @@ - + - +设计模式 | 闻 @@ -190,7 +190,7 @@- + @@ -283,8 +283,8 @@ 适配器模式
diff --git a/Faiss/image-20240911200426522.png b/-NLP/Faiss/image-20240911200426522.png similarity index 100% rename from Faiss/image-20240911200426522.png rename to -NLP/Faiss/image-20240911200426522.png diff --git a/Faiss/index.html b/-NLP/Faiss/index.html similarity index 97% rename from Faiss/index.html rename to -NLP/Faiss/index.html index 2dd4573..eb937ec 100644 --- a/Faiss/index.html +++ b/-NLP/Faiss/index.html @@ -22,24 +22,24 @@ - + - + - + - + - +@@ -343,7 +343,7 @@Faiss 向量数据库 | 闻 @@ -192,7 +192,7 @@- + @@ -326,7 +326,7 @@ BM25 实现
import jieba
from langchain.schema import Document
from langchain_community.retrievers import BM25Retriever
def create_bm25_retriever(docs, top_k):
bm25_retriever = BM25Retriever.from_documents(
docs,
preprocess_func=jieba.lcut_for_search,
)
bm25_retriever.k = top_k
return bm25_retriever
if __name__ == "__main__":
docs = [
Document(page_content="这是一篇关于机器学习的文档。"),
Document(page_content="自然语言处理是人工智能的一个重要领域。"),
Document(page_content="深度学习是机器学习的一个子集。"),
]
top_k = 2
bm25_retriever = create_bm25_retriever(docs, top_k)
query = "机器学习"
results = bm25_retriever.get_relevant_documents(query)
for rank, doc in enumerate(results, start=1):
print(f"Rank {rank}: {doc}")Debug 查看分词结果
-bm25_retriever.vectorizer.doc_freqs
+
BM25 实现
- + LLM 结构和创新点diff --git a/Java-Algorithm/index.html b/-NLP/Java-Algorithm/index.html similarity index 99% rename from Java-Algorithm/index.html rename to -NLP/Java-Algorithm/index.html index aff968e..48f90a0 100644 --- a/Java-Algorithm/index.html +++ b/-NLP/Java-Algorithm/index.html @@ -22,7 +22,7 @@ - + @@ -33,11 +33,11 @@ - + - +数据结构和算法 | 闻 @@ -191,7 +191,7 @@- + diff --git a/LLM-Application/image-20240424102449161.png b/-NLP/LLM-Application/image-20240424102449161.png similarity index 100% rename from LLM-Application/image-20240424102449161.png rename to -NLP/LLM-Application/image-20240424102449161.png diff --git a/LLM-Application/image-20240424102824838.png b/-NLP/LLM-Application/image-20240424102824838.png similarity index 100% rename from LLM-Application/image-20240424102824838.png rename to -NLP/LLM-Application/image-20240424102824838.png diff --git a/LLM-Application/image-20240424140419971.png b/-NLP/LLM-Application/image-20240424140419971.png similarity index 100% rename from LLM-Application/image-20240424140419971.png rename to -NLP/LLM-Application/image-20240424140419971.png diff --git a/LLM-Application/index.html b/-NLP/LLM-Application/index.html similarity index 96% rename from LLM-Application/index.html rename to -NLP/LLM-Application/index.html index 9636f15..9d93067 100644 --- a/LLM-Application/index.html +++ b/-NLP/LLM-Application/index.html @@ -22,26 +22,26 @@ - + - - - + + + - + - + - + LLM 应用开发实践 | 闻 @@ -194,7 +194,7 @@- + @@ -293,7 +293,7 @@ 解决思路
- 文本表征是对文本语义的向量表征,相似内容的文本具有相似的表征向量。这使我们可以在向量空间中比较文本的相似性。
- 向量数据库
-Vector Database
用来存储文档的文本块。对于给定的文档,我们首先将其分成较小的文本块chunks
,然后获取每个小文本块的文本表征,并将这些表征储存在向量数据库中。这个流程正是创建索引index
的过程。将文档分成小文本块的原因在于我们可能无法将整个文档传入语言模型进行处理。+
Langchain 中文本分割器
langchain.text_splitter
都根据 chunk_size(块大小) 和 chunk_overlap(块与块之间的重叠大小) 进行分割-
@@ -301,8 +301,8 @@
- chunk_overlap 指两个块之间共享的字符数量,用于保持上下文的连贯性,避免分割丢失上下文信息
解决思路
+ +
Q1:如何加强搜索结果的多样性?
A1:最大边际相关性
Maximum marginal relevance
@@ -336,7 +336,7 @@问题背景
模型)并不能理解场景相关的概念,也就无法构建有针对性的对话知识库,因此简单的导入外部数据无法实现多场景需求。解决思路
针对私有数据的多场景对话需求,可以构建并应用不同场景的知识图谱。
-+
基于 用户输入Query 和 图数据库 Schema 构建 Prompt,通过 LLM 获取简短、精要的实体和关系信息,后续再基于此生成对话响应。
@@ -378,7 +378,7 @@from langchain.chains import GraphCypherQAChain
from langchain.graphs import Neo4jGraph
graph = Neo4jGraph(
url="bolt://localhost:7687",
username="neo4j",
password=""
)
chain = GraphCypherQAChain.from_llm(
model, graph=graph, verbose=True,
)虚拟人设
diff --git a/LLM-Basic/image-20240714162218754.png b/-NLP/LLM-Basic/image-20240714162218754.png similarity index 100% rename from LLM-Basic/image-20240714162218754.png rename to -NLP/LLM-Basic/image-20240714162218754.png diff --git a/LLM-Basic/index.html b/-NLP/LLM-Basic/index.html similarity index 89% rename from LLM-Basic/index.html rename to -NLP/LLM-Basic/index.html index beb000f..fdf66eb 100644 --- a/LLM-Basic/index.html +++ b/-NLP/LLM-Basic/index.html @@ -22,24 +22,24 @@ - + - + - + - + - + - +LLM 基础知识 | 闻 @@ -142,7 +142,7 @@-@@ -192,7 +192,7 @@+- + @@ -228,7 +228,7 @@ 大模型核心技术点在于训练资源、数据清洗和数据配比等,其难点或许不在于模型训练和模型结构搭建
【变形金刚之神!Bless Me】
- -+ +
- 相较于 RNN,Transformer 直接将句子中任意两个单词的联系通过一个计算步骤直接联系起来,远距离依赖特征之间的距离被极大缩短,有利于有效地利用这些特征; @@ -365,6 +365,9 @@
- dense + activation
嵌入模型
相对位置编码
+相对位置编码具有外推性(extrapolation +ability)的原因在于它不是将位置信息编码为与序列中的绝对位置直接相关的固定模式,而是将注意力权重或其他模型组件与元素之间的相对距离联系起来。
编程
Transformers及相关库
@@ -406,13 +409,13 @@
LLaMA-Factory 源码
diff --git a/LLM-Model/2.png b/-NLP/LLM-Model/2.png similarity index 100% rename from LLM-Model/2.png rename to -NLP/LLM-Model/2.png diff --git a/LLM-Model/ROPE3.png b/-NLP/LLM-Model/ROPE3.png similarity index 100% rename from LLM-Model/ROPE3.png rename to -NLP/LLM-Model/ROPE3.png diff --git a/LLM-Model/dccdd5360d984d2c84a9f7338c55e665.jpeg b/-NLP/LLM-Model/dccdd5360d984d2c84a9f7338c55e665.jpeg similarity index 100% rename from LLM-Model/dccdd5360d984d2c84a9f7338c55e665.jpeg rename to -NLP/LLM-Model/dccdd5360d984d2c84a9f7338c55e665.jpeg diff --git a/LLM-Model/index.html b/-NLP/LLM-Model/index.html similarity index 93% rename from LLM-Model/index.html rename to -NLP/LLM-Model/index.html index 2d47a36..9b607bc 100644 --- a/LLM-Model/index.html +++ b/-NLP/LLM-Model/index.html @@ -22,28 +22,28 @@ - + - - - - - + + + + + - + - + - +LLM 结构和创新点 | 闻 @@ -196,7 +196,7 @@- + @@ -260,7 +260,7 @@ 滑动窗口注意力
sliding window attention: Longformer
-+
稀疏注意力
@@ -271,7 +271,7 @@稀疏注意力
class="math inline">\(V\)的计算上,(bs, head_num, seq_len, head_dim) 中的 seq_len 只选取连接模式中选择的。连接模式(注意力核)的选择:局部稀疏模式、分块稀疏模式、对角块稀疏模式
-+
Flash Attention
@@ -283,7 +283,7 @@Flash Attention
分块SoftMax算法,详细推导过程见技术博客。Qwen2 模块
-+
@@ -319,7 +319,7 @@modeling_qwen2.py
架构Qwen2 模块
分组查询注意力 GQA
MQA 将所有注意力头的键和值共享
GQA 的方式是将多个注意力头分成组,每组头共享同一组的键和值。
-+
实现方式:
@@ -340,8 +340,8 @@transformers.models.llama.modeling_llama.repeat_kv
复制多次 KV,使用expand
而不是repeat
是因为 KV 的参数是组内共享的旋转位置编码 PoRE
class="math inline">\((v_{510},v_{511})\)然后,通过旋转矩阵分别对每一对进行旋转,使得每一对的旋转角度与相对位置相对应。
- -+ +
代码层面,Qwen2 构造
Qwen2RotaryEmbedding
类和apply_rotary_pos_emb
方法,Qwen2RotaryEmbedding
类基于 seq_len 返回缓存的 cos 和 sin @@ -406,12 +406,12 @@激活函数 SwiGLU
- + Linux 开发工具- + Faiss 向量数据库diff --git a/LLM-Model/swa.png b/-NLP/LLM-Model/swa.png similarity index 100% rename from LLM-Model/swa.png rename to -NLP/LLM-Model/swa.png diff --git a/LLM-Model/v2-8a907719f9e3ced8347a051d9a66c732_720w.webp b/-NLP/LLM-Model/v2-8a907719f9e3ced8347a051d9a66c732_720w.webp similarity index 100% rename from LLM-Model/v2-8a907719f9e3ced8347a051d9a66c732_720w.webp rename to -NLP/LLM-Model/v2-8a907719f9e3ced8347a051d9a66c732_720w.webp diff --git a/LLM-PEFT/1596082-20240506233139617-864405376.png b/-NLP/LLM-PEFT/1596082-20240506233139617-864405376.png similarity index 100% rename from LLM-PEFT/1596082-20240506233139617-864405376.png rename to -NLP/LLM-PEFT/1596082-20240506233139617-864405376.png diff --git a/LLM-PEFT/640-17217147122181.png b/-NLP/LLM-PEFT/640-17217147122181.png similarity index 100% rename from LLM-PEFT/640-17217147122181.png rename to -NLP/LLM-PEFT/640-17217147122181.png diff --git a/LLM-PEFT/640-17217147122182.png b/-NLP/LLM-PEFT/640-17217147122182.png similarity index 100% rename from LLM-PEFT/640-17217147122182.png rename to -NLP/LLM-PEFT/640-17217147122182.png diff --git a/LLM-PEFT/640-17217147122194.png b/-NLP/LLM-PEFT/640-17217147122194.png similarity index 100% rename from LLM-PEFT/640-17217147122194.png rename to -NLP/LLM-PEFT/640-17217147122194.png diff --git a/LLM-PEFT/640-17217147122195.png b/-NLP/LLM-PEFT/640-17217147122195.png similarity index 100% rename from LLM-PEFT/640-17217147122195.png rename to -NLP/LLM-PEFT/640-17217147122195.png diff --git a/LLM-PEFT/640-17217147122196.png b/-NLP/LLM-PEFT/640-17217147122196.png similarity index 100% rename from LLM-PEFT/640-17217147122196.png rename to -NLP/LLM-PEFT/640-17217147122196.png diff --git a/LLM-PEFT/640.png b/-NLP/LLM-PEFT/640.png similarity index 100% rename from LLM-PEFT/640.png rename to -NLP/LLM-PEFT/640.png diff --git a/LLM-PEFT/PT.png b/-NLP/LLM-PEFT/PT.png similarity index 100% rename from LLM-PEFT/PT.png rename to -NLP/LLM-PEFT/PT.png diff --git a/LLM-PEFT/image-20240712160012402.png b/-NLP/LLM-PEFT/image-20240712160012402.png similarity index 100% rename from LLM-PEFT/image-20240712160012402.png rename to -NLP/LLM-PEFT/image-20240712160012402.png diff --git a/LLM-PEFT/image-20240712160245055.png b/-NLP/LLM-PEFT/image-20240712160245055.png similarity index 100% rename from LLM-PEFT/image-20240712160245055.png rename to -NLP/LLM-PEFT/image-20240712160245055.png diff --git a/LLM-PEFT/image-20240712160346485.png b/-NLP/LLM-PEFT/image-20240712160346485.png similarity index 100% rename from LLM-PEFT/image-20240712160346485.png rename to -NLP/LLM-PEFT/image-20240712160346485.png diff --git a/LLM-PEFT/image-20240712161951488.png b/-NLP/LLM-PEFT/image-20240712161951488.png similarity index 100% rename from LLM-PEFT/image-20240712161951488.png rename to -NLP/LLM-PEFT/image-20240712161951488.png diff --git a/LLM-PEFT/image-20240712162302772.png b/-NLP/LLM-PEFT/image-20240712162302772.png similarity index 100% rename from LLM-PEFT/image-20240712162302772.png rename to -NLP/LLM-PEFT/image-20240712162302772.png diff --git a/LLM-PEFT/image-20240712162725874.png b/-NLP/LLM-PEFT/image-20240712162725874.png similarity index 100% rename from LLM-PEFT/image-20240712162725874.png rename to -NLP/LLM-PEFT/image-20240712162725874.png diff --git a/LLM-PEFT/image-20240712170241205.png b/-NLP/LLM-PEFT/image-20240712170241205.png similarity index 100% rename from LLM-PEFT/image-20240712170241205.png rename to -NLP/LLM-PEFT/image-20240712170241205.png diff --git a/LLM-PEFT/image-20240712172913057.png b/-NLP/LLM-PEFT/image-20240712172913057.png similarity index 100% rename from LLM-PEFT/image-20240712172913057.png rename to -NLP/LLM-PEFT/image-20240712172913057.png diff --git a/LLM-PEFT/image-20240714150443014.png b/-NLP/LLM-PEFT/image-20240714150443014.png similarity index 100% rename from LLM-PEFT/image-20240714150443014.png rename to -NLP/LLM-PEFT/image-20240714150443014.png diff --git a/LLM-PEFT/image-20240714150638355.png b/-NLP/LLM-PEFT/image-20240714150638355.png similarity index 100% rename from LLM-PEFT/image-20240714150638355.png rename to -NLP/LLM-PEFT/image-20240714150638355.png diff --git a/LLM-PEFT/image-20240714162218754.png b/-NLP/LLM-PEFT/image-20240714162218754.png similarity index 100% rename from LLM-PEFT/image-20240714162218754.png rename to -NLP/LLM-PEFT/image-20240714162218754.png diff --git a/LLM-PEFT/image-20240715191912939.png b/-NLP/LLM-PEFT/image-20240715191912939.png similarity index 100% rename from LLM-PEFT/image-20240715191912939.png rename to -NLP/LLM-PEFT/image-20240715191912939.png diff --git a/LLM-PEFT/image-20240715191933199.png b/-NLP/LLM-PEFT/image-20240715191933199.png similarity index 100% rename from LLM-PEFT/image-20240715191933199.png rename to -NLP/LLM-PEFT/image-20240715191933199.png diff --git a/LLM-PEFT/image-20240715191936226.png b/-NLP/LLM-PEFT/image-20240715191936226.png similarity index 100% rename from LLM-PEFT/image-20240715191936226.png rename to -NLP/LLM-PEFT/image-20240715191936226.png diff --git a/LLM-PEFT/image-20240715192056550.png b/-NLP/LLM-PEFT/image-20240715192056550.png similarity index 100% rename from LLM-PEFT/image-20240715192056550.png rename to -NLP/LLM-PEFT/image-20240715192056550.png diff --git a/LLM-PEFT/image-20240716101659909.png b/-NLP/LLM-PEFT/image-20240716101659909.png similarity index 100% rename from LLM-PEFT/image-20240716101659909.png rename to -NLP/LLM-PEFT/image-20240716101659909.png diff --git a/LLM-PEFT/image-20240716101748533.png b/-NLP/LLM-PEFT/image-20240716101748533.png similarity index 100% rename from LLM-PEFT/image-20240716101748533.png rename to -NLP/LLM-PEFT/image-20240716101748533.png diff --git a/LLM-PEFT/image-20240718093213465.png b/-NLP/LLM-PEFT/image-20240718093213465.png similarity index 100% rename from LLM-PEFT/image-20240718093213465.png rename to -NLP/LLM-PEFT/image-20240718093213465.png diff --git a/LLM-PEFT/image-20240718143120945.png b/-NLP/LLM-PEFT/image-20240718143120945.png similarity index 100% rename from LLM-PEFT/image-20240718143120945.png rename to -NLP/LLM-PEFT/image-20240718143120945.png diff --git a/LLM-PEFT/image-20240718191324572.png b/-NLP/LLM-PEFT/image-20240718191324572.png similarity index 100% rename from LLM-PEFT/image-20240718191324572.png rename to -NLP/LLM-PEFT/image-20240718191324572.png diff --git a/LLM-PEFT/image-20240722165643744.png b/-NLP/LLM-PEFT/image-20240722165643744.png similarity index 100% rename from LLM-PEFT/image-20240722165643744.png rename to -NLP/LLM-PEFT/image-20240722165643744.png diff --git a/LLM-PEFT/image-20240723093258953.png b/-NLP/LLM-PEFT/image-20240723093258953.png similarity index 100% rename from LLM-PEFT/image-20240723093258953.png rename to -NLP/LLM-PEFT/image-20240723093258953.png diff --git a/LLM-PEFT/image-20240723100503853.png b/-NLP/LLM-PEFT/image-20240723100503853.png similarity index 100% rename from LLM-PEFT/image-20240723100503853.png rename to -NLP/LLM-PEFT/image-20240723100503853.png diff --git a/LLM-PEFT/image-20240723101505442.png b/-NLP/LLM-PEFT/image-20240723101505442.png similarity index 100% rename from LLM-PEFT/image-20240723101505442.png rename to -NLP/LLM-PEFT/image-20240723101505442.png diff --git a/LLM-PEFT/image-20240723102932924.png b/-NLP/LLM-PEFT/image-20240723102932924.png similarity index 100% rename from LLM-PEFT/image-20240723102932924.png rename to -NLP/LLM-PEFT/image-20240723102932924.png diff --git a/LLM-PEFT/image-20240723102934378.png b/-NLP/LLM-PEFT/image-20240723102934378.png similarity index 100% rename from LLM-PEFT/image-20240723102934378.png rename to -NLP/LLM-PEFT/image-20240723102934378.png diff --git a/LLM-PEFT/image-20240723103303792.png b/-NLP/LLM-PEFT/image-20240723103303792.png similarity index 100% rename from LLM-PEFT/image-20240723103303792.png rename to -NLP/LLM-PEFT/image-20240723103303792.png diff --git a/LLM-PEFT/image-20240723103450147.png b/-NLP/LLM-PEFT/image-20240723103450147.png similarity index 100% rename from LLM-PEFT/image-20240723103450147.png rename to -NLP/LLM-PEFT/image-20240723103450147.png diff --git a/LLM-PEFT/image-20240723104300363.png b/-NLP/LLM-PEFT/image-20240723104300363.png similarity index 100% rename from LLM-PEFT/image-20240723104300363.png rename to -NLP/LLM-PEFT/image-20240723104300363.png diff --git a/LLM-PEFT/image-20240723104910206.png b/-NLP/LLM-PEFT/image-20240723104910206.png similarity index 100% rename from LLM-PEFT/image-20240723104910206.png rename to -NLP/LLM-PEFT/image-20240723104910206.png diff --git a/LLM-PEFT/image-20240723110508921.png b/-NLP/LLM-PEFT/image-20240723110508921.png similarity index 100% rename from LLM-PEFT/image-20240723110508921.png rename to -NLP/LLM-PEFT/image-20240723110508921.png diff --git a/LLM-PEFT/image-20240723112054204.png b/-NLP/LLM-PEFT/image-20240723112054204.png similarity index 100% rename from LLM-PEFT/image-20240723112054204.png rename to -NLP/LLM-PEFT/image-20240723112054204.png diff --git a/LLM-PEFT/image-20240723112058468.png b/-NLP/LLM-PEFT/image-20240723112058468.png similarity index 100% rename from LLM-PEFT/image-20240723112058468.png rename to -NLP/LLM-PEFT/image-20240723112058468.png diff --git a/LLM-PEFT/image-20240723134459641.png b/-NLP/LLM-PEFT/image-20240723134459641.png similarity index 100% rename from LLM-PEFT/image-20240723134459641.png rename to -NLP/LLM-PEFT/image-20240723134459641.png diff --git a/LLM-PEFT/image-20240725102452954.png b/-NLP/LLM-PEFT/image-20240725102452954.png similarity index 100% rename from LLM-PEFT/image-20240725102452954.png rename to -NLP/LLM-PEFT/image-20240725102452954.png diff --git a/LLM-PEFT/image-20240725143254778.png b/-NLP/LLM-PEFT/image-20240725143254778.png similarity index 100% rename from LLM-PEFT/image-20240725143254778.png rename to -NLP/LLM-PEFT/image-20240725143254778.png diff --git a/LLM-PEFT/image-20240729142017433.png b/-NLP/LLM-PEFT/image-20240729142017433.png similarity index 100% rename from LLM-PEFT/image-20240729142017433.png rename to -NLP/LLM-PEFT/image-20240729142017433.png diff --git a/LLM-PEFT/image-20240903102620304.png b/-NLP/LLM-PEFT/image-20240903102620304.png similarity index 100% rename from LLM-PEFT/image-20240903102620304.png rename to -NLP/LLM-PEFT/image-20240903102620304.png diff --git a/LLM-PEFT/index.html b/-NLP/LLM-PEFT/index.html similarity index 88% rename from LLM-PEFT/index.html rename to -NLP/LLM-PEFT/index.html index 627c613..06c0670 100644 --- a/LLM-PEFT/index.html +++ b/-NLP/LLM-PEFT/index.html @@ -22,48 +22,48 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - +大模型微调 PEFT 方法 | 闻 @@ -216,7 +216,7 @@- + @@ -348,10 +348,10 @@ 背景
由于训练一小部分参数,极大程度降低了训练大模型的算力需求,不需要多机多卡,单卡即可完成对一些大模型的训练。不仅如此,少量的训练参数对存储的要求同样降低了很多,大多数的参数高效微调方法只需要保存训练部分的参数,与动辄几十 GB 的预训练大模型相比,几乎可以忽略。
当下流行 PEFT 结构一览:
-+
常用的参数高效微调方法:
- -+ +
- Selective:选择模型中的一部分参数进行微调;
- Additive:冻结模型原有参数,微调新增的参数和模块;
@@ -459,8 +459,8 @@
BitFit
LN-Tuning
单独调整 LayerNorm 模块的 weight 和 bias 参数,训练参数量少,便于和其他的微调方法一起使用。
- -+ +
实验表明,Prefix-Tuning + LN 的微调效果最佳。
优势
-
@@ -477,8 +477,8 @@
- 简化了不同任务之间的转换和迁移,使得模型可以更加灵活地应用于各种场景; @@ -494,7 +494,7 @@
- 通过 Encoder 将离散的 Prompt Embedding 转变为连续的,减少了 Prompt
@@ -516,8 +516,8 @@
Prefix Tuning
输入到下一次的计算中,这一技术又被称之为 kv cache。- -# 可训练模块:Embedding + MLP,与 P-Tuning 的区别是 prefix 映射到了模型的隐藏层上
self.embedding = torch.nn.Embedding(num_virtual_tokens, token_dim)
self.transform = torch.nn.Sequential(
torch.nn.Linear(token_dim, encoder_hidden_size),
torch.nn.Tanh(),
torch.nn.Linear(encoder_hidden_size, num_layers * 2 * token_dim),
)
# transformers.models.bloom.BloomAttention 源码实现
if layer_past is not None:
past_key, past_value = layer_past
key_layer = torch.cat((past_key, key_layer), dim=2)
value_layer = torch.cat((past_value, value_layer), dim=1)+ +
优势:
- 拟合速度快; @@ -534,8 +534,8 @@
- 移除重参数化的编码器,对于较小的模型,会影响模型的表现,且对于大模型提升不大; @@ -573,8 +573,8 @@
- 调节的参数少于 Lora,微调效果也不错; @@ -645,16 +645,16 @@
P-Tuning V2
最大的区别在于:移除重参数化的编码器,即没有MLP。通过共享连续提示同时优化多个任务,多任务学习是 P-Tuning v2 的可选功能,可以通过多任务共享前缀进一步提升性能。
- -+ +
优势:
LoRA
具体而言,冻结预训练的模型权重,并将可训练的秩分解矩阵注入到大模型的每个 Attention 层的线性变换中。输入分别与原始权重和两个低秩矩阵进行计算,共同得到最终结果。
- -+ +
训练完成后,可以将两个低秩矩阵与原始模型中的权重进行合并,合并后的模型与原始模型无异,避免了推理期间 Prompt 系列方法带来的额外计算量。
IA3 K、V、FFN 相乘,针对不同 batch 的同一位置进行相同的调整(即乘上相同可学习参数),训练过程中冻结原始模型的权重,只更新新增的参数。训练完成后,与 Lora 类似,可以将学习部分的参数与原始权重合并,没有额外推理开销。
- -+ +
优势:
AdaLora
P-I\right\|_\mathrm{F}^2+\left\|QQ^\top-I\right\|_\mathrm{F}^2\]
Prompt-Tuning
可训练模块:Embedding(virtual_token, hidden_size)
+ +
优势:
P-Tuning
可训练模块:Embedding(virtual_token, hidden_size) + MLP/LSTM
+
优势:
最终,微调的损失函数为
重要结论
- -+ +
AdaLoRA 总是倾向于将更多预算分配给 FFN 和顶层,即 FFN 模块和顶层的权重矩阵对于模型性能更为重要。
Adapter Tuning
在 Transformer Layer 的 Self-Attetion 和 FFN 之后插入一个先降维再升维的 MLP(以及一层残差和Layer Normalization)来学习模型微调的知识。
- -+ +
图中,Adapter 即插入的 FF Down + 非线性激活层 + FF up。在微调过程中,固定原始模型的参数,只微调适配层。
不足:
@@ -672,10 +672,10 @@AdapterFusion
分离知识提取和知识组合这两个阶段,可以以非破坏性的方式有效地利用从多个任务中学到的表示。知识提取阶段学习Adapter 任务特定参数,其封装了特定于任务的信息;知识组合阶段将不同任务的 Adapter 组合到一起。 - -- -
+ +
+ +
AdapterFusion 组件将在不同任务上训练的多个适配器的输出作为输入,并学习编码信息的参数化混合器,应用于单个任务多 Adapter 的场景和多任务混合的场景。单任务场景中,可以多个 Adapter @@ -689,8 +689,8 @@
AdapterFusion
AdapterDrop
该方法在不影响任务性能的前提下,动态高效的移除冗余的 Adapter,可以尽可能地减少模型的参数量,提高模型在反向传播(训练)和正向传播(推理)时的效率。
- -+ +
优势:
- 通过从较低的 Transformer 层删除可变数量的Adaper来提升推理速度。
@@ -698,16 +698,16 @@
AdapterDrop
MAM Adapter
分解了最先进的参数高效迁移学习方法的设计,并提出了一个在它们之间建立联系的统一框架。
- -+ +
UniPEFT
不同的 PEFT 方法在同一任务上的表现不同,因此为特定任务选择最合适的方法并非易事,特别是考虑到新 PEFT 方法和任务数量的快速增长。鉴于模型的多样性和模型选择的难度,UniPEFT 提出了一个统一的框架 UniPEFT,它将不同的PEFT 方法作为子模块,并通过门控机制学习激活最适合当前数据或任务设置的方法。
- -+ +
PISSA
peft 包中有 PISSA 初始化方法 @@ -728,8 +728,8 @@
PISSA
A、B,冻结参数量较大的残差矩阵 \[\text{Wres}\] ,就达成了用很少的参数近似全参数微调的效果。 - -+ +
优势
- 相比于 LoRA,收敛速度更快,性能更好 @@ -737,8 +737,8 @@
- VeRA显著减少了可训练参数的数量(LoRA相比参数减少了10倍),而精度没有损失; @@ -747,8 +747,8 @@
PISSA
VeRA
区别于Lora,Vera 将 A 和 B 矩阵按照高斯分布随机初始化并冻结,只训练两组直接和A、B相乘的一维参数。虽然直观看起来A和B像两个无用的张量,但实际上它们仍然是必不可少的,实验证明即使是随机张量也可以用于微调。
- -+ +
优势:
VeRA
DoRA
将每个高阶矩阵都分解为 1*k 大小矩阵和 d*k 方向矩阵的乘积,LoRA 倾向于同时改变幅度和方向,DoRA可以更容易地将二者分开调整,或者用另一个的负变化来补偿一个的变化。
- -+ +
SLORA
一个 GPU 上并行执行多个 lora adapters 的微调
S-LoRA 能够在单个 GPU 上或跨多个 GPU 以较小的开销为数千个 LoRA @@ -774,8 +774,8 @@
LoRA+
LoRA 中的适配器矩阵 A 和 B 以相同的学习率更新,实验表明对 A 和 B 使用相同的学习率并不能实现有效的特征学习,LoRA+ 通过精心选择的固定比率为 LoRA 适配器矩阵 A 和 B 设置不同的学习率,纠正 LoRA 的这种次优性。
- -+ +
LongLoRA
LongLoRA 扩展了模型的上下文,同时保留了其原始架构,并且与大多数现有技术兼容。一方面,虽然推理过程中需要密集的全局注意力,但微调过程更需要稀疏的局部注意力实现有效且高效反向传播。由此,该方法提出转移稀疏注意力
@@ -783,24 +783,24 @@LongLoRA
有效地实现了上下文扩展。另一方面,除了在线性层中训练 LoRA 权重之外,LongLoRA 还进一步使嵌入层和归一化层变得可训练,由此可以表现出较好的性能。从实现上来看,该方法在训练中只需两行代码即可实现,且在推理中是可选的,不会占用额外计算资源。
-+
RsLoRA
LoRA通过在选定层添加可训练的低秩Adapter来实现参数有效的微调。每个LoRA由两个低秩矩阵乘积组成,并乘以一个与秩相关的因子,传统的LoRA采用“直接除以秩的因子”的方法过于激进,导致高秩Adapter的学习速度减缓,性能受限。因此,在实际应用中,LoRA通常仅限于使用非常低的秩。
rsLoRA深入研究了 LoRA 的缩放因子对学习过程的影响,并证明了 LoRA 应该除以秩的平方根而不是秩,通过使用较大的秩在训练期间增加计算资源以获得更好的微调性能,同时不改变推理计算成本。
- -+ +
LLaMA Pro
该方法提出的Block Expansion方法,即块扩展,在保持预训练模型参数不变的基础上,增加新的block来适应新的训练任务。这些新加入的block与原有block协同工作,既保留了模型原有的知识,又能够适应新的训练数据和任务需求。
- -+ +
方法性能对比
从方法类型、是否存储高效、是否内存高效、反向传播成本、推理开销五个维度比较 PEFT 方法:
-+
各种参数高效方法的参与训练的参数量、最终模型与原始模型的改变参数(delta值)以及论文中参与评估的模型的范围:
-+
PEFT 方法在何种模型大小上进行过评估,以及在论文中通常使用的可训练参数数量。我们所说的可训练参数数量是指由梯度优化算法更新的参数数量,而不是我们用“更改参数”表示的原始模型与最终模型之间的差异。对于重参数化方法,我们报告了重参数化前后的参数数量。由于S4模型在不同层使用了不同的方法,因此估算其更新后的参数数量比较复杂。我们报告了在已发表的文献中对这些方法进行评估的范围。
近年来,基于Transformer架构的大语言模型(LLM),在众多自然语言处理(NLP)任务达到了最佳性能表现。目前,构建领域专用LLM的主流策略是:在海量通用数据集上预训练的大语言模型(PLM),并通过针对特定下游任务的微调(Fine-tuning)。相较于直接采用PLM,针对下游任务的微调能显著提升模型性能。然而,随着LLM参数规模急剧增长,在消费级硬件上进行微调变得不切实际。
@@ -854,7 +854,7 @@微调方法适配
基于 Langchain 的 RAG 架构底层原理 | 闻 @@ -196,7 +196,7 @@- + @@ -279,12 +279,12 @@ 概念
从原始数据到响应生成最常见的流程图如下:
-+
流程图2:
-+
RAG 测评指标:
- -+ +
Langchain
LangChain 采用组件化设计的思想,将语言模型开发分为多个子任务:对话历史 @@ -382,8 +382,8 @@
基于深度学习
Bert 输出 Sentence_Embedding,拟合 cos_Similarity(回归任务)
评价指标
二分类评价指标 AUC
- -+ +
可信度 RAG
当检索返回的结果有错误或信息丢失时,会导致LLM回复出现幻觉。
为解决这个问题的三个指标:可信度(Faithfulness)、答案相关性(Answer @@ -424,7 +424,7 @@
Q&A
- + LLM 应用开发实践diff --git a/LLM-RAG-Langchain/x7ta8v77.png b/-NLP/LLM-RAG-Langchain/x7ta8v77.png similarity index 100% rename from LLM-RAG-Langchain/x7ta8v77.png rename to -NLP/LLM-RAG-Langchain/x7ta8v77.png diff --git a/Linux-Tool/index.html b/-NLP/Linux-Tool/index.html similarity index 97% rename from Linux-Tool/index.html rename to -NLP/Linux-Tool/index.html index 8bfaec6..5f3c61b 100644 --- a/Linux-Tool/index.html +++ b/-NLP/Linux-Tool/index.html @@ -22,7 +22,7 @@ - + @@ -33,11 +33,11 @@ - + - +Linux 开发工具 | 闻 @@ -190,7 +190,7 @@- + @@ -374,12 +374,12 @@ 会话管理
- + LLM 结构和创新点diff --git a/paper-PAFT/image-20240815185100137.png b/-NLP/paper-PAFT/image-20240815185100137.png similarity index 100% rename from paper-PAFT/image-20240815185100137.png rename to -NLP/paper-PAFT/image-20240815185100137.png diff --git a/paper-PAFT/index.html b/-NLP/paper-PAFT/index.html similarity index 95% rename from paper-PAFT/index.html rename to -NLP/paper-PAFT/index.html index 9d432f1..b9ee62d 100644 --- a/paper-PAFT/index.html +++ b/-NLP/paper-PAFT/index.html @@ -22,24 +22,24 @@ - + - + - + - + - +论文阅读 RAFT | 闻 @@ -192,7 +192,7 @@- + @@ -287,7 +287,7 @@ 数据集
实验结果
DSF(Domain-Specific Finetuning):特定领域内微调
PAFT:特定领域微调+特定领域 RAG
-+
总结
将模型在特定领域的文档上做思维链微调
-
@@ -312,12 +312,12 @@
- Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。在对象被移动时(垃圾收集时移动对象是非常普遍的行为)只会改变句柄中的实例数据指针。
总结
- + Linux 开发工具diff --git a/-developer/JUC-Lock/index.html b/-developer/JUC-Lock/index.html index 135a796..9024d31 100644 --- a/-developer/JUC-Lock/index.html +++ b/-developer/JUC-Lock/index.html @@ -323,8 +323,8 @@ReentrantLock
public class ReentrantLock implements Lock {
// 同步控制器(指向公平锁或非公平锁)
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer{
final boolean nonfairTryAcquire(int acquires) {...}
protected final boolean tryRelease(int releases) {...}
}
// 不公平锁
static final class NonfairSync extends Sync{
final void lock() {...}
protected final boolean tryAcquire(int acquires) {...}
}
// 公平锁
static final class FairSync extends Sync {
final void lock() {...}
protected final boolean tryAcquire(int acquires) {...}
}
// 实现 Lock 接口
public void lock() {
sync.lock();
}
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
public void unlock() {
sync.release(1);
}
}
- -ReentrantLock
独占锁运行过程(可重入锁的state
表示==重入的次数==,会大于1)+ +
加锁失败时阻塞
@@ -409,8 +409,8 @@ReentrantLock
在 CAS 加锁失败之后会将 Thread 封装成一个Node
类型的对象加入CLH
队列中AbstractQueuedSynchronizer
线程调度逻辑: 当线程尝试获取资源失败时,会创建一个==Node节点==并将当前线程包装进去,然后利用==CAS算法==将其安全地加入到==等待队列的尾部==,并阻塞。Link
- -+ +
在释放资源时,AQS会根据资源管理策略从队列中选择合适的节点并唤醒对应线程。
CLH 锁
diff --git a/-developer/JUC-ThreadPool/index.html b/-developer/JUC-ThreadPool/index.html index b7e60b5..7142c5b 100644 --- a/-developer/JUC-ThreadPool/index.html +++ b/-developer/JUC-ThreadPool/index.html @@ -584,7 +584,7 @@
底层代码
ThreadLocal
原理
public class ThreadLocal<T> {
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
// 存放数据
private Entry[] table;
}
}整体结构图
- -+ +
引用关系图
- -+ +
Q&A
Entry的key为什么设计成弱引用?
ThreadLocal 变量生命周期结束后,ThreadLocal 对象就可以被回收;
diff --git a/-developer/JVM/index.html b/-developer/JVM/index.html index 81c1e5b..78d0803 100644 --- a/-developer/JVM/index.html +++ b/-developer/JVM/index.html @@ -343,14 +343,14 @@对象访问定位
+ +
- 直接指针访问方式最大的好处就是速度快,它节省了一次指针定位的时间开销,HotSpot 采用的是直接指针
+ +
对象的内存布局
Mark Word 是一个具有动态定义的数据结构,以便在极小的空间内存储尽量多的数据,根据对象的状态复用自己的存储空间。
@@ -523,8 +523,8 @@CMS
target="_blank" rel="noopener" href="https://heapdump.cn/article/1870333">FGC类加载过程
类的生命周期:加载、连接、初始化、使用、卸载 - -+ +
- 加载:通过全类名获取定义此类的二进制字节流;将字节流所代表的静态存储结构转换为方法区的运行时数据结构;在内存中生成一个代表该类的
Class
diff --git a/-developer/Java-DataStructure/index.html b/-developer/Java-DataStructure/index.html index 6921e2d..1321d90 100644 --- a/-developer/Java-DataStructure/index.html +++ b/-developer/Java-DataStructure/index.html @@ -364,8 +364,8 @@HashMap
JDK1.8 之前 HashMap 采用“拉链法”处理冲突,由 数组+链表 组成; JDK1.8 以后,若Table长度大于 64,会将链表转化为红黑树。
- -+ +
- key 和 value 可以为 null,但 null 作为 key 只能有一个,而 null 作为 value 可以有多个 @@ -499,7 +499,7 @@
- 了解垃圾回收机制吗?新生代和老年代的垃圾回收是怎么样的
- 简要描述线程与进程的关系,区别及优缺点?
- 线程之间哪些资源是共享的,哪些资源是私有的,为什么?
- 说一下你对于 AQS 原理的理解。
- 如何实现线程安全?
- 了解过消息中间件吗?说一下使用场景
- write pos ~ checkpoint 之间的部分(图中红色部分):记录新的更新操作; @@ -810,8 +810,8 @@
- 写入 Binlog:数据修改 -> 主库写 binlog 日志 -> commit 事务 -> 持久化本地数据 -> 提交事务成功; @@ -830,8 +830,8 @@
- 半同步复制:只要数据成功复制到任意一个从库上,主库的事务线程就可以返回给客户端;
- 图中的 write,把日志写入到 binlog 文件(文件系统的 page cache 里),但是并没有把数据持久化到磁盘; @@ -856,8 +856,8 @@
- Free Page(空闲页),表示此页未被使用,位于 Free 链表;
- Clean Page(干净页),表示此页已被使用,但是页面未发生修改,位于LRU
diff --git a/-developer/Redis/index.html b/-developer/Redis/index.html
index 49b4409..3650889 100644
--- a/-developer/Redis/index.html
+++ b/-developer/Redis/index.html
@@ -276,8 +276,8 @@
持久化
AOF 日志
将每条执行成功的写操作命令追加到日志文件中,持久化代码命令在主进程上执行
写回策略(防止AOF日志在持久化过程中丢失):
- -+ +
重写机制(防止AOF日志文件过大):
删去已经无意义的日志;
@@ -334,11 +334,11 @@ 传输层,关注链路级别的传输
- 解析 URL
- DNS 查询服务器 IP
@@ -372,11 +367,11 @@
传输层 TCP
TCP :面向连接的、可靠的、基于字节流的
三次握手
- -+ +
四次挥手【closed_wait;last_ack】
- -+ +
- 首先确认客户端不会再发送请求给服务端
- 然后服务端在发送完数据后,再向客户端发送断开连接 @@ -419,7 +414,7 @@
网络层 IP
diff --git a/OS/index.html b/OS/index.html index 1d36df8..1c67cdd 100644 --- a/OS/index.html +++ b/OS/index.html @@ -258,8 +258,8 @@虚拟内存
只会访问虚拟内存地址,在操作总线前,通过一个地址转换硬件将虚拟内存地址转换为物理内存地址进程隔离:将虚拟内存映射到物理内存,进程之间的地址空间相互隔离,互不干扰
虚拟内存空间:
- -+ +
用户态虚拟内存空间是相互隔离相互独立的;内核虚拟内存空间是各个进程共享的;
进程管理
数据结构 PCB
@@ -344,8 +344,8 @@I/O 多路复用
- 偏向左侧时,训练数据的扰动不足以使学习器产生显著变化,此时偏差主导泛化误差,称为欠拟合现象
-
-
-
- 增加模型的迭代次数;更换描述能力更强的模型;生成更多特征供训练使用;降低正则化水平 -
- - 偏向右侧时,模型的拟合能力非常强,数据轻微变化都能导致模型发生变化,如果过分学习训练数据的特点,则会发生过拟合现象
-
-
-
- 扩增训练集;减少训练使用的特征的数量;降低模型复杂度;提高正则化水平 -
- - K折交叉验证通过多次划分和验证,减少因数据划分不当而导致的性能估计偏差 -
- 正则化在损失函数中加入一个与模型复杂度相关的惩罚项,以限制模型的复杂度并防止过拟合
-参考文章
-
-
-
- L1正则化是指权值向量w中各个元素的绝对值之和,可以使得参数稀疏化,即得到的参数是一个稀疏矩阵,进而可以用于特征选择。二维平面图像:
- L2正则化是指权值向量w中各个元素的平方和然后再求平方根,让权值尽可能小,如果参数足够小,数据偏移得多一点也不会对结果造成什么影响,专业一点的说法是抗扰动能力强。二维平面图像:
- - L1正则化是指权值向量w中各个元素的绝对值之和,可以使得参数稀疏化,即得到的参数是一个稀疏矩阵,进而可以用于特征选择。二维平面图像:
- 归一化奖励分数、将奖励分数做白化处理 -
- 向量被分配到最近的聚类(同 IVF) -
- 每个向量被划分为 m -个子向量,分别在各自的子空间中进行量化,存储为对应的量化代码 -
- 查询向量通过倒排索引(IVF) 来确定最接近的聚类中心 -
- 查询向量被划分为 m 个子向量 -
- 查询子向量与存储的量化代码进行匹配,基于每个子空间的距离查表来计算近似距离 -
- 将所有子空间的距离相加,得到查询向量与候选向量的总距离 -
哨兵机制
自动完成故障发现和故障转移,并通知给应用方,从而实现高可用性
哨兵之间建立连接
- -+ +
哨兵与从节点建立连接
- -+ +
第一轮投票:判断主节点下线
主观下线:主节点或者从节点没有在规定的时间内响应哨兵的 PING 命令
客观下线:一个哨兵判断主节点为「主观下线」后,就会向其他哨兵发起命令,通过多个哨兵节点一起判断主节点是否下线。哨兵的赞同票数达到哨兵配置文件中的 @@ -472,8 +472,8 @@
发布者/订阅者
订阅命令:subscribe channel [channel ... ]
+ +
事务回滚
diff --git a/-developer/SpringMVC/index.html b/-developer/SpringMVC/index.html index 08af833..13b57e2 100644 --- a/-developer/SpringMVC/index.html +++ b/-developer/SpringMVC/index.html @@ -308,7 +308,7 @@系统权限
diff --git a/2024/03/index.html b/2024/03/index.html index f57b956..58686bf 100644 --- a/2024/03/index.html +++ b/2024/03/index.html @@ -224,7 +224,7 @@闻
diff --git a/2024/04/index.html b/2024/04/index.html index acaa637..8709ae0 100644 --- a/2024/04/index.html +++ b/2024/04/index.html @@ -264,7 +264,7 @@闻
- + LLM 应用开发实践@@ -284,7 +284,7 @@闻
diff --git a/2024/05/index.html b/2024/05/index.html index 6ce563b..46db95d 100644 --- a/2024/05/index.html +++ b/2024/05/index.html @@ -204,7 +204,7 @@闻
@@ -213,26 +213,6 @@闻
-- -- -- -- - - - -diff --git a/2024/06/index.html b/2024/06/index.html index da502de..06aa489 100644 --- a/2024/06/index.html +++ b/2024/06/index.html @@ -204,7 +204,7 @@diff --git a/2024/07/index.html b/2024/07/index.html index ab01a3b..a68a0dc 100644 --- a/2024/07/index.html +++ b/2024/07/index.html @@ -193,6 +193,26 @@闻
闻
2024 ++ ++ ++ ++ ++ + 开发面试常见问题和知识点 + ++ + +@@ -204,7 +224,7 @@@@ -224,7 +244,7 @@闻
闻
diff --git a/2024/08/index.html b/2024/08/index.html index 4118925..1e99d20 100644 --- a/2024/08/index.html +++ b/2024/08/index.html @@ -204,7 +204,7 @@闻
- + Linux 开发工具@@ -224,7 +224,7 @@闻
diff --git a/2024/09/index.html b/2024/09/index.html index f2341a6..ac48290 100644 --- a/2024/09/index.html +++ b/2024/09/index.html @@ -204,7 +204,7 @@闻
- + Faiss 向量数据库@@ -224,7 +224,7 @@闻
- + LLM 结构和创新点diff --git a/2024/index.html b/2024/index.html index bbf9e65..976a62d 100644 --- a/2024/index.html +++ b/2024/index.html @@ -204,7 +204,7 @@闻
- + Faiss 向量数据库@@ -224,7 +224,7 @@闻
- + LLM 结构和创新点@@ -244,7 +244,7 @@闻
- + Linux 开发工具@@ -264,7 +264,7 @@闻
@@ -273,6 +273,26 @@闻
+ ++ ++ ++ ++ + 开发面试常见问题和知识点 + ++ + +@@ -284,7 +304,7 @@@@ -304,7 +324,7 @@闻
闻
@@ -344,7 +364,7 @@闻
@@ -384,7 +404,7 @@闻
@@ -393,26 +413,6 @@闻
- -- -- -- - - - -@@ -524,7 +524,7 @@闻
- + LLM 应用开发实践@@ -544,7 +544,7 @@闻
diff --git a/2024/page/2/index.html b/2024/page/2/index.html index 09ef18f..5a89815 100644 --- a/2024/page/2/index.html +++ b/2024/page/2/index.html @@ -304,7 +304,7 @@闻
diff --git a/How-to-Work/index.html b/How-to-Work/index.html index 58961cf..f8bbc19 100644 --- a/How-to-Work/index.html +++ b/How-to-Work/index.html @@ -270,12 +270,12 @@diff --git a/Network/12.jpg b/Network/12.jpg deleted file mode 100644 index 4571dc3..0000000 Binary files a/Network/12.jpg and /dev/null differ diff --git a/Network/640.webp b/Network/640.webp deleted file mode 100644 index ed79b38..0000000 Binary files a/Network/640.webp and /dev/null differ diff --git "a/Network/TCP\344\270\211\346\254\241\346\217\241\346\211\213.drawio.png" "b/Network/TCP\344\270\211\346\254\241\346\217\241\346\211\213.drawio.png" deleted file mode 100644 index 2cd74fd..0000000 Binary files "a/Network/TCP\344\270\211\346\254\241\346\217\241\346\211\213.drawio.png" and /dev/null differ diff --git a/Network/format,png-20230309230614791.png b/Network/format,png-20230309230614791.png deleted file mode 100644 index 39e661c..0000000 Binary files a/Network/format,png-20230309230614791.png and /dev/null differ diff --git a/Network/image-20240508140301819.png b/Network/image-20240508140301819.png deleted file mode 100644 index 752ba20..0000000 Binary files a/Network/image-20240508140301819.png and /dev/null differ diff --git a/Network/image-20240730153032143.png b/Network/image-20240730153032143.png deleted file mode 100644 index ba2e573..0000000 Binary files a/Network/image-20240730153032143.png and /dev/null differ diff --git a/Network/index.html b/Network/index.html index 7dd5e12..59d66bf 100644 --- a/Network/index.html +++ b/Network/index.html @@ -26,16 +26,11 @@ - - - - - @@ -266,11 +261,11 @@diff --git a/a/index.html b/a/index.html index e0b216b..d9d3f5d 100644 --- a/a/index.html +++ b/a/index.html @@ -185,7 +185,7 @@应用数据转换到传输块的过程:
- -+ +
访问网站的过程
- -+ +
闻
- + @@ -203,7 +203,7 @@ 闻
- Faiss 向量数据库 + Faiss 向量数据库
@@ -246,7 +246,7 @@diff --git a/page/2/index.html b/page/2/index.html index d03fc4a..34ddb39 100644 --- a/page/2/index.html +++ b/page/2/index.html @@ -304,7 +304,7 @@faiss 索引类型、代码实践
@@ -277,7 +277,7 @@- + @@ -295,7 +295,7 @@ - LLM 结构和创新点 + LLM 结构和创新点
@@ -338,7 +338,7 @@diff --git a/os/index.html b/os/index.html index 1d36df8..1c67cdd 100644 --- a/os/index.html +++ b/os/index.html @@ -258,8 +258,8 @@LLM 相较于 Transformers 在结构上的创新点
@@ -369,7 +369,7 @@- + @@ -387,7 +387,7 @@ -- Linux 开发工具 + Linux 开发工具
@@ -430,7 +430,7 @@@@ -393,26 +413,6 @@Linux高效工具的使用方法
@@ -461,7 +461,7 @@- + @@ -479,7 +479,7 @@ - 论文阅读 RAFT + 论文阅读 RAFT
@@ -526,7 +526,7 @@@@ -384,7 +404,7 @@《Adapting Language Model to Domain Specific RAG》提出了检索增强微调(Retrieval Augmented Fine Tuning)方法,微调模型使其学习“如何忽略任何检索到的、无助于回答给定问题的文档,且不产生幻觉”,使 LLM 具有特定于域的 RAG 功能
@@ -557,7 +557,7 @@- + @@ -575,7 +575,7 @@ - LLM 基础知识 + 开发面试常见问题和知识点
@@ -586,14 +586,14 @@@@ -344,7 +364,7 @@发表于 - + 更新于 - + @@ -601,7 +601,7 @@
-@@ -273,6 +273,26 @@模型是如何诞生的,在训练过程中需要哪些技术
+汇总记录面试题,方便复习和面试模拟
@@ -649,7 +649,7 @@- + @@ -667,7 +667,7 @@ - 大模型微调 PEFT 方法 + LLM 基础知识
@@ -678,14 +678,14 @@发表于 - + 更新于 - + @@ -693,7 +693,7 @@
-微调的理论基础,总结了至今为止较优的参数高效微调(Parameter-Efficient Fine-Tuning)的方法和低精度微调量化
+模型是如何诞生的,在训练过程中需要哪些技术
@@ -741,7 +741,7 @@- + @@ -759,7 +759,7 @@ - 我爱上班 + 大模型微调 PEFT 方法
@@ -770,14 +770,14 @@发表于 - + 更新于 - + @@ -785,7 +785,7 @@
-diff --git a/index.html b/index.html index 5518529..8785e05 100644 --- a/index.html +++ b/index.html @@ -204,7 +204,7 @@工作与学习不同,不只是“唯分数论”,更要妥善处理人际关系、高效沟通等等。这并不是什么高大上的真理,而是和吃饭喝水一样普通的事情。
+微调的理论基础,总结了至今为止较优的参数高效微调(Parameter-Efficient Fine-Tuning)的方法和低精度微调量化
@@ -833,7 +833,7 @@- + @@ -851,7 +851,7 @@ - 深度学习基础概念 + 我爱上班
@@ -862,14 +862,14 @@diff --git "a/categories/\350\257\273\350\256\272\346\226\207/index.html" "b/categories/\350\257\273\350\256\272\346\226\207/index.html" index 835e2e8..02f67cd 100644 --- "a/categories/\350\257\273\350\256\272\346\226\207/index.html" +++ "b/categories/\350\257\273\350\256\272\346\226\207/index.html" @@ -205,7 +205,7 @@发表于 - + 更新于 - + @@ -877,7 +877,7 @@
-diff --git "a/categories/\350\257\273\350\256\272\346\226\207/LLM\345\276\256\350\260\203/index.html" "b/categories/\350\257\273\350\256\272\346\226\207/LLM\345\276\256\350\260\203/index.html" index c1d279f..a8df5da 100644 --- "a/categories/\350\257\273\350\256\272\346\226\207/LLM\345\276\256\350\260\203/index.html" +++ "b/categories/\350\257\273\350\256\272\346\226\207/LLM\345\276\256\350\260\203/index.html" @@ -205,7 +205,7 @@机器学习是采用真实世界中采样的一小部分数据,并且希望模型能够对于未知数据有不错的泛化性能。
+工作与学习不同,不只是“唯分数论”,更要妥善处理人际关系、高效沟通等等。这并不是什么高大上的真理,而是和吃饭喝水一样普通的事情。
@@ -925,7 +925,7 @@- + @@ -943,7 +943,7 @@ - Docker + 深度学习基础概念
@@ -954,14 +954,14 @@@@ -225,7 +225,7 @@发表于 - + 更新于 - + @@ -969,7 +969,7 @@
-容器虚拟化技术,待后续进一步学习 k8s
+机器学习是采用真实世界中采样的一小部分数据,并且希望模型能够对于未知数据有不错的泛化性能。
@@ -1017,7 +1017,7 @@- + @@ -1035,7 +1035,7 @@ - 设计模式 + Docker
@@ -1046,14 +1046,14 @@diff --git "a/categories/\345\267\245\344\275\234/index.html" "b/categories/\345\267\245\344\275\234/index.html" index 1cf184a..a5b2d0d 100644 --- "a/categories/\345\267\245\344\275\234/index.html" +++ "b/categories/\345\267\245\344\275\234/index.html" @@ -198,15 +198,15 @@发表于 - + 更新于 - + @@ -1061,7 +1061,7 @@
-diff --git "a/categories/LLM\345\276\256\350\260\203/index.html" "b/categories/LLM\345\276\256\350\260\203/index.html" index d62ec13..c188200 100644 --- "a/categories/LLM\345\276\256\350\260\203/index.html" +++ "b/categories/LLM\345\276\256\350\260\203/index.html" @@ -205,7 +205,7 @@项目架构的设计模式,和Java开发中的具体实现
+容器虚拟化技术,待后续进一步学习 k8s
diff --git a/a/page/2/index.html b/a/page/2/index.html index cba84b2..363a8a8 100644 --- a/a/page/2/index.html +++ b/a/page/2/index.html @@ -185,7 +185,7 @@闻
- + @@ -203,7 +203,7 @@ 闻
- Java 面试常见问题和知识点 + 设计模式
@@ -214,14 +214,14 @@发表于 - + 更新于 - + @@ -229,7 +229,7 @@
-汇总记录面试题,方便复习和面试模拟
+项目架构的设计模式,和Java开发中的具体实现
@@ -737,7 +737,7 @@- + @@ -755,7 +755,7 @@ - LLM 应用开发实践 + LLM 应用开发实践
@@ -798,7 +798,7 @@diff --git "a/categories/LLM\345\274\200\345\217\221/index.html" "b/categories/LLM\345\274\200\345\217\221/index.html" index be80d98..1331f4a 100644 --- "a/categories/LLM\345\274\200\345\217\221/index.html" +++ "b/categories/LLM\345\274\200\345\217\221/index.html" @@ -205,7 +205,7 @@记录LLM应用开发过程遇到的问题,和对应的解决方法
@@ -829,7 +829,7 @@- + @@ -847,7 +847,7 @@ - 基于 Langchain 的 RAG 架构底层原理 + 基于 Langchain 的 RAG 架构底层原理
@@ -890,7 +890,7 @@@@ -245,7 +245,7 @@检索增强生成(RAG)是如何实现的,它与广搜推有什么区别?此外,还有专用于RAG开发的Langchain包的使用方法
diff --git a/a/page/3/index.html b/a/page/3/index.html index 69a19e4..e409be1 100644 --- a/a/page/3/index.html +++ b/a/page/3/index.html @@ -650,7 +650,7 @@- + @@ -668,7 +668,7 @@ - 数据结构和算法 + 数据结构和算法
@@ -711,7 +711,7 @@1.汇总用 Java 写算法的一些小技巧;2.总结语雀上的所有算法笔记。方便每次笔试之前复习总结
diff --git "a/categories/LLM\345\237\272\347\241\200/index.html" "b/categories/LLM\345\237\272\347\241\200/index.html" index 10a3d5f..a48904d 100644 --- "a/categories/LLM\345\237\272\347\241\200/index.html" +++ "b/categories/LLM\345\237\272\347\241\200/index.html" @@ -205,7 +205,7 @@LLM基础
- + LLM 结构和创新点@@ -225,7 +225,7 @@LLM基础
LLM基础
LLM开发
- + Faiss 向量数据库@@ -225,7 +225,7 @@LLM开发
- + LLM 应用开发实践@@ -245,7 +245,7 @@LLM开发
LLM微调
工作
开发工具
- + Linux 开发工具diff --git "a/categories/\347\274\226\347\250\213\346\200\235\346\203\263/index.html" "b/categories/\347\274\226\347\250\213\346\200\235\346\203\263/index.html" index 9c2585d..a5629e7 100644 --- "a/categories/\347\274\226\347\250\213\346\200\235\346\203\263/index.html" +++ "b/categories/\347\274\226\347\250\213\346\200\235\346\203\263/index.html" @@ -205,7 +205,7 @@编程思想
编程思想
LLM微调
读论文
闻
- + Faiss 向量数据库@@ -224,7 +224,7 @@闻
- + LLM 结构和创新点@@ -244,7 +244,7 @@闻
- + Linux 开发工具@@ -264,7 +264,7 @@闻
闻
++ ++ ++ ++ ++ + 开发面试常见问题和知识点 + ++ + +@@ -284,7 +304,7 @@@@ -304,7 +324,7 @@闻
闻
闻
闻
闻
- -- -- -- - - - -@@ -524,7 +524,7 @@闻
- + LLM 应用开发实践@@ -544,7 +544,7 @@闻
虚拟内存
只会访问虚拟内存地址,在操作总线前,通过一个地址转换硬件将虚拟内存地址转换为物理内存地址进程隔离:将虚拟内存映射到物理内存,进程之间的地址空间相互隔离,互不干扰
虚拟内存空间:
- -+ +
用户态虚拟内存空间是相互隔离相互独立的;内核虚拟内存空间是各个进程共享的;
进程管理
数据结构 PCB
@@ -344,8 +344,8 @@I/O 多路复用
闻
diff --git a/search.xml b/search.xml index 9daf3fd..fbbfc2c 100644 --- a/search.xml +++ b/search.xml @@ -1,235 +1,5 @@- - 深度学习基础概念 -/DL-basic/ -偏差方差 泛化误差
-模型的平方预测误差的期望
-\[Err(\mathbf{x})=E\left[\left(y-f(\mathbf{x};D)\right)^2\right]=\mathbb{E}_D\left[\left(f(\boldsymbol{x};D)-\bar{f}\left(\boldsymbol{x}\right)\right)^2\right]+\left(\bar{f}(\boldsymbol{x})-y\right)^2+\mathbb{E}_D\left[(y_D-y)^2\right]\]
-方差
--
-方差是指模型对于不同训练集的预测结果的波动程度(即泛化能力),刻画了数据扰动所造成的影响。高方差意味着模型过于复杂,对训练数据中的噪声和细节过于敏感,表示模型过拟合
-使用样本数相同的不同训练集产生的方差
-\[\mathrm{var}(\mathbf{x})=\mathrm{E}_\mathrm{D}\left[\left(\mathrm{f}(\mathbf{x};\mathrm{D})-\overline{\mathrm{f}}(\mathbf{x})\right)^2\right]\]
-其中,算法 𝑓 对测试样本 𝑥 的期望预测(不同训练集 𝐷 上模型 𝑓 -对测试样本 𝑥 的预测输出的期望)\(\overline{f}(\mathbf{x})=E_D[f\left(\mathbf{x};D\right)]\)
-偏差
--
-偏差是指模型的预测值与真实值之间的差异,模型本身的拟合能力。高偏差意味着模型过于简单,无法捕捉到数据的复杂模式,表示模型欠拟合
-期望预测与真实标记的误差
-\[\mathrm{bias}^2(\mathbf{x})=\left(\overline{\mathrm{f}}(\mathbf{x})-\mathrm{y}\right)^2\]
-噪声
--
-表达了当前任务上任何模型所能达到的期望泛化误差的下界,刻画了学习问题本身的难度。
-真实标记与数据集中的实际标记间的偏差
-\[\varepsilon^2=E_D\left[(y_D-y)^2\right]\]
-偏差-方差窘境
--
-
-
为了解决“偏差和方差在一定程度上是有冲突的”的问题,可以采用K折交叉验证或正则化,它们分别从数据划分和模型复杂度两个角度入手,提升模型的泛化能力和稳健性:
--
-
模型训练
-优化器
-Adam:自适应学习率,通过计算梯度的一阶矩(均值)和二阶矩(未中心化的方差)来调整学习率
-AdamW:带有权重衰减和学习率预热的Adam优化器。改进了Adam,将权重衰退和梯度更新解耦,把L2正则化移到权重更新时而不是梯度计算时
-训练方法
-监督学习
-训练数据既有特征(feature)又有标签(label),通过训练,让机器可以自己找到特征和标签之间的联系,在面对只有特征没有标签的数据时,可以判断出标签。
-无监督学习
-数据只有特征(feature)无标签(label),是一种机器学习的训练方式,它本质上是一个统计手段,在没有标签的数据里可以发现潜在的一些结构的一种训练方式。
-半监督学习
-利用同时包含有标签和无标签的数据来构建一个模型,使得模型能够在测试阶段更好地泛化到新的、未见过的数据。
-强化学习
-让一个智能体(agent)在环境(Enviroment)中通过尝试和错误来学习行为(Action)策略。智能体通过与环境进行交互,根据奖励信号来调整其行为策略,以达到最大化累积奖励的目标。
-针对 PPO 算法的优化:
--
-
-
RLHF
--
-Reinforcement Learning from Human -Feedback,以强化学习方式依据人类反馈优化语言模型,是 -OpenAI 提出的生成领域(Decoder_only)的新训练范式
-Policy Gradient
- --
RM+PPO
-步骤一、预训练语言模型
- --
步骤二、训练奖励模型 RM
- --
步骤三、用强化学习 PPO 微调
- --
DPO
-KTO
-ORPO
-损失函数
-MSELoss 回归任务
-CrossEntropyLoss 单标签分类
-BCEWithLogitsLoss 多标签分类
-Torch
-
-]]> -torch.nn.Parameter()
将一个不可训练的 tensor -转换成可以训练的类型 parameter,并将这个 parameter 绑定到这个 module -里面- -LLM基础 -- - -深度学习基础 -- -设计模式 -/Design-Pattern/ -单例模式 - -双重校验锁
--private volatile static Singleton uniqueInstance;
if (uniqueInstance == null) {
//类对象加锁
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}模板方法模式
--
-抽象出步骤的执行顺序作为抽象方法,具体的实现方法交给子类实现
-实现 AQS 抽象类的锁,需要重写 CLH 锁的 -
-tryAcquire-tryRelease
、tryAcquireShared-tryReleaseShared
、isHeldExclusively
-方法。重写钩子方法,可以自定义
-state
-的含义:值为多少时代表加锁成功/失败 or -解锁成功/失败,也可以实现共享锁或独占锁。观察者模式
-具体查看 JUC_Lock 博客的
-CompletableFuture
-的底层实现适配器模式
-具体查看 SpringMVC 博客的
-HandlerAdapter
的底层实现开闭原则:新增代替修改
-]]>- -编程思想 -- -设计模式 -- Faiss 向量数据库 -/Faiss/ -Faiss 索引类型 - - -平面索引 FLAT
-平面索引就是暴力搜索,将
-queries
于 -database
中的所有向量计算,时间复杂度是 \(O({n^2})\)。不同索引计算相似度的方法不同,
-IndexFlatIP
-是点积,IndexFlatL2
是 L2 -距离,如果需要计算余弦相似度则需要在点积前 L2 归一化 -faiss.normalize_L2(vector)
,L2 归一化公式为 \(\mathbf{X}=\left(\frac{x_1}{\left\|\mathbf{x}\right\|},\frac{x_2}{\left\|\mathbf{x}\right\|},\cdots,\frac{x_n}{\left\|\mathbf{x}\right\|}\right)\)-index = faiss.IndexFlatL2(d)
index.add(database)
D, I = index.search(queries[:5], k)\(D\) -表示具体的相似度
-D.shape = (query_len, similarity)
,取值范围是 -[0, 1]\(I\) 表示与 \(D\) 相对应的索引 -
-I.shape = (query_len, index)
,取值范围是 [0, data_num]分区索引 IVF
-对索引数据进行分区优化,将数据通过“沃罗诺伊图单元”(也被叫做泰森多边形)来进行切割(类似传统数据库分库分表)。在搜索时,仅将查询 -queries 所在单元中包含的数据库向量 database -以及一些相邻的向量与查询向量进行比较,找到 queries -向量所属的泰森多边形单元就是在质心集中找到该向量的最近邻居。
-
-index.train()
训练了一个聚类模型,如 -K-means。生成多个聚类中心,聚类的数量由索引的nlist
-参数决定。倒排索引(IVF)把“文档→单词”的形式变为“单词→文档”的形式。
-
-search
有两个参数:nlist
(单元格数量)和 -nprobe
-(为执行搜索而访问的质心集单元数量,在nlist
之外),设置 -nprobe = nlist
给出与暴力搜索相同的结果。-quantizer = faiss.IndexFlatL2(d)
index = faiss.IndexIVFFlat(quantizer, d, nlist, faiss.METRIC_L2)
index.train(database)
index.add(database)
index.nprobe = 10
D, I = index.search(queries, k)量化索引 PQ
-基于乘积量化器的有损压缩来压缩存储的向量,压缩方法和量化级别参考论文。
-建立索引时:
--
-
查询时:
--
-
这个例子,将 64 个 32 位浮点数压缩为 8 个字节,因此压缩因子为 -32。
--# d 必须是 m 的倍数
quantizer = faiss.IndexFlatL2(d)
# 量化器数量 m、指定每个子向量编码为 8 byte(32 bit)
index = faiss.IndexIVFPQ(quantizer, d, nlist, m, 8)
# 可以简写为 index = faiss.index_factory(d, "IVF100,PQ8")
index.train(database)
index.add(database)
index.nprobe = 10
D, I = index.search(queries, k)功能
-索引的量化功能
-对向量进行编码量化
--index.sa_encode(vectors)
针对非量化索引,也会返回
-uint8
-类型的更紧凑的离散表示-xq[0][:5]
## array([0.81432974, 0.7409969 , 0.8915324 , 0.02642949, 0.24954738], dtype=float32)
index.sa_encode(xq[:1, :])[0, :5]
## array([ 93, 234, 119, 80, 63], dtype=uint8)获取原始数据/向量
-基于根据 index
--index.reconstruct(vector_id)
为了追求更快的查询性能,IndexIVF 和向量 ID IndexBinaryIVF -都存储在倒排列表中,无法通过向量 ID -来反查索引中的内容,如果我们想要得到某个数据的内容,需要手动重建索引
--index.make_direct_map()
index.reconstruct(vector_id)获取原文档
-FAISS 内置了
-docstore
和 -index_to_docstore_id
,在每次加入向量时同时存储 doc -内容,且以字典的形式储存 index 与 doc -的映射关系,方便后续查找原文档。BM25 实现
-额外记录一下
-BM25
的实现方法-import jieba
from langchain.schema import Document
from langchain_community.retrievers import BM25Retriever
def create_bm25_retriever(docs, top_k):
bm25_retriever = BM25Retriever.from_documents(
docs,
preprocess_func=jieba.lcut_for_search,
)
bm25_retriever.k = top_k
return bm25_retriever
if __name__ == "__main__":
docs = [
Document(page_content="这是一篇关于机器学习的文档。"),
Document(page_content="自然语言处理是人工智能的一个重要领域。"),
Document(page_content="深度学习是机器学习的一个子集。"),
]
top_k = 2
bm25_retriever = create_bm25_retriever(docs, top_k)
query = "机器学习"
results = bm25_retriever.get_relevant_documents(query)
for rank, doc in enumerate(results, start=1):
print(f"Rank {rank}: {doc}")Debug 查看分词结果 -
-bm25_retriever.vectorizer.doc_freqs
-]]>
- -LLM开发 -- -faiss -我爱上班 /How-to-Work/ @@ -249,3347 +19,4141 @@ href="https://inria.hal.science/inria-00514462v2/document">论文。 - mid=(left+right)>>2;if -(nums[left]<nums[mid]) left=mid+1; -else right=mid;【找左边】 -
- mid=(left+right+1)>>2;if -(nums[left]<=nums[mid]) left=mid; else -right=mid-1;【找右边】 +
- 进程是资源(包括内存、打开的文件等)分配的最小单位,线程是 CPU +调度的最小单位; +
- 进程拥有一个完整的资源平台,而线程只独享必不可少的资源,如寄存器和栈,线程之间共享地址空间和文件等资源; +
- 线程同样具有就绪、阻塞、执行三种基本状态,同样具有状态之间的转换关系; +
- 线程能减少并发执行的时间和空间开销;
- 确定dp数组(dp table)以及下标的含义 -
- 确定递推公式 -
- dp数组如何初始化 -
- 确定遍历顺序 -
- 举例推导dp数组 +
- epoll +只在初始时完成一次文件描述符的注册,避免了每次调用时的拷贝开销; +
- 当有一个或多个文件描述符就绪时,会调用回调函数将 Socket +集合一次性传递到就绪事件列表中,并通知用户空间,这使得 epoll +在处理大量文件描述符时仍然能保持高效; +
- 当用户调用 epoll_wait() +返回有事件发生的文件描述符的个数,明确指出了哪些文件描述符是就绪的,无需像 +select 和 poll 遍历所有 socket 集合; +
- 边缘触发【epoll】:只有当文件描述符的状态从不就绪变为就绪时,epoll +才会发出通知;一旦通知过后,除非状态再次发生变化,否则不会再次通知; +
- 水平触发【select/poll】:只要文件描述符处于就绪状态,epoll就会持续发出通知,直到数据处理完毕; +
- 【124】求二叉树中最大的路径和。改左右子树的深度为节点值的和,若和为负数则返回 -0 -
- 【2245】一般树的最长路径。遍历所有邻居(过滤掉父节点),取最长、次长两条路径相加,结果为最长路径。此外,根据题意还要去除父子结点相同的情况。 -
- 向零截断,直接保留整数位
1/2 == -1/2 == 0
+ - 不需要凸显自己的能力、表达自己的个性,更多的是团队合作 +
- 遇到挫折要坚持,遇到问题会咨询 +
- 热爱工作,吃苦耐劳,积极向上
- 下列代码的返回值 +
- SQL 语句 +
- 初始资金 M,N 天价格信息,K 次交易后,能赚多少钱?(动态规划) +
- 给你 n 个数,这 n 个数要被拆成 k +份,对每份中的数字求异或,求各份异或总和的最大值(和恒生第二题的思路基本一样) +
- 讲一讲和算法相关的经历 +
- int double:0 -
- boolean:false +
- 专利:基于异构图网络的情绪支持对话 +
- 项目:LLM应用开发
- 这个项目都在使用别人开发好的技术,那么你在其中有什么贡献? +
- 包装类型常量池:Byte, Short, Integer [-128,127], Long, Character, -Boolean -
- 字符串常量池 +
- 目前很多开源项目只停留在科研方面,如何落地到具体项目中,就比如 LLM +出现错误宕机的时候,重启容器化运行的 LLM +实例并采用一致性轮询方法,访问其他正常运行的容器
- 做过最大的项目 +
- 成员变量(定义在类里方法外的变量)一定要进行初始化的,如果不显式的进行初始化,那么虚拟机会进行默认的初始化 +
- 实习的时候做的数据中台项目 +
- 对未来的计划 +
- 基本数据类型一般是给予默认值 -
- 引用类型初始值为 null -
- 局部变量不会自动初始化,所以在声明局部变量时要注意,可以不在声明时初始化,但在使用之前一定要进行初始化,否则会报编译错误 +
- 作为一个刚进入工作的学生,要不断学习拓宽自己的技术面
- 泛型必须是引用类型,不能是基本类型 -
- 泛型通过类型擦除实现 +
- 让我调了下摄像头,好展示我的颜,然后自我介绍 +
- 手撕算法(由于太紧张写代码一直在絮絮叨叨)
- 文本表征是对文本语义的向量表征,相似内容的文本具有相似的表征向量。这使我们可以在向量空间中比较文本的相似性。 -
- 向量数据库
Vector Database
用来存储文档的文本块。对于给定的文档,我们首先将其分成较小的文本块chunks
,然后获取每个小文本块的文本表征,并将这些表征储存在向量数据库中。这个流程正是创建索引index
的过程。将文档分成小文本块的原因在于我们可能无法将整个文档传入语言模型进行处理。
+ - 算法思路讲一遍,中间做错了删掉的代码也要讲为什么做错了,然后把代码截了个图 +
- 说一下自己的技术栈
- chunk_size 指每个块包含的字符或 Token(如单词、句子等)的数量 -
- chunk_overlap -指两个块之间共享的字符数量,用于保持上下文的连贯性,避免分割丢失上下文信息 +
- 挑一个自己熟悉的讲一讲,选了 MySQL 索引
- 音视频上传 +
- 如果让你建一张表,你会如何设计索引 +
- 语音转文字 FFmpeg -
- 【初始化时】声纹构建 -
- 语音转文字 Whisper -
- 特征语料库构建 -
- 语料 + Chroma 向量库相似度 + KNN 距离匹配 -
- 组成输入,LLM 响应结果 +
- IOC 容器的理解 -]]>
- 相较于 RNN,Transformer -直接将句子中任意两个单词的联系通过一个计算步骤直接联系起来,远距离依赖特征之间的距离被极大缩短,有利于有效地利用这些特征; -
- Self Attention -大大提升了计算的并行,通过上三角mask可以同时训练一句话中的所有token; +
- 那为什么不直接用单例模式而用 IOC 容器的 Bean
- 输入输出:sbh*2 byte -
- 模型大小:n*2 GB -
- 梯度大小:n*2 GB -
- 优化器大小:(4+4+4) *n -GB。模型更新时,梯度很小,学习率也很小,精度丢失会影响模型收敛效果,所以优化器中的数据全都是 -fp32 精度。 -
- 激活值大小:sbh(34+5*a*s/h)*L byte 分析 -
- [PAD] 填充至固定长度 -
- [CLS] 分类任务 -
- [SEP] 分隔符 -
- [MASK] 自监督任务,序列填空 -
- [BOS] / [EOS] 自回归任务,约束文本生成的边界 -
- [UNK] 无法识别的词 -
- [SPE] 词汇表预留的标志 +
- 用 Python 能否实现 AOP
- 训练阶段,每一轮的 batch 都是独立的,
attention mask
-会把与有效序列无关的部分都屏蔽了,因此两者都行;
- - 推理阶段,存在自回归的推理过程,当并发
batch infer
-时,左 padding 可以直接将推理得到的下一跳 Token 合并到 -input_ids
尾部,简化编码过程;
+ - 设计模式讲一下
- BertEmbeddings
-
-
-
- word_embeddings -
- position_embeddings -
- token_type_embeddings -
- LayerNorm + dropout -
- - BertEncoder
-
-
-
- attention -
- MLP -
- LayerNorm + dropout -
- - BertPooler
+
讲了 SpringMVC 中 HanderAdapter 用到的适配器模式
-
-
- dense + activation -
+ - Rest 和 Rpc 有什么区别
Qwen2RMSNorm: RMS归一化层
-Qwen2RotaryEmbedding: 旋转位置编码
-Attention
+- OS 为什么需要虚拟地址 +
Qwen2Attention: 注意力层
-Qwen2FlashAttention2: 使用Flash Attention -2.0版本加速的注意力层
-Qwen2SdpaAttention: 使用Sdpa(pytorch自带的加速, Scaled -Dot-Product Attention)加速的注意力层
-Qwen2DecoderLayer: 编码层,核心结构,之后就是堆叠
-Qwen2PreTrainedModel: 预训练类
-Qwen2Model: 不带head的Qwen2模型
-Qwen2ForCausalLM: 带Causal LM head的Qwen2模型
-Qwen2ForSequenceClassification: 带序列分类头的Qwen2模型
+- 会什么语言 -
_get_unpad_data: 在flash attention的数据预处理中会用到。主要是对 -attention mask 进行一些操作;
-rotate_half: 在旋转位置编码中用到;
-apply_rotary_pos_emb: 对数据主要是注意力运算中的 q,k -做旋转位置编码;
-repeat_kv: 主要是在 MQA(Multi-Query Attention)和 -GQA(Group-Query Attention)中用到,因为 q head 数量是 k,v head -的数量的整数倍
+- 反问,进去需要什么技术栈
自我介绍
+深入讲一下实习经历(完全没想到会问这个)
+- 第 1 对:\((v_0,v_1)\) -
- 第 2 对:\((v_2,v_3)\) -
- ... -
- 第 256 对:\((v_{510},v_{511})\) +
- 了解项目架构,微服务和多模块开发,数据流过程 +
- 尝试开发字典结构 +
- AOP 日志:运行时间、调用接口、速度、ip +
- 调用微服务获取运维大屏数据,并展示:线程池、CompletableFuture +线程先后调用关系
- 日志 AOP,能不能查找、过滤逻辑,为什么不用 +ELK。如果有监控平台的话,为什么不存到监控平台里(看得出来面试官很奇怪怎么只有 +AOP 记录日志,没有其他的相关功能) +
- AOP 底层原理 +
- 行,继续说(我超,怎么说啊说啥啊) +
- 有 A 类中的 BC 方法。B 方法使用注解代理,再用 C 方法通过 this.B() +调用,会出现什么逻辑 +
- 那如何让 this.B() 的代理生效呢 +
- 修改一个数据,存储层、缓存层一起用的话怎么办 +
- 单例模式实际应用场景,Spring 底层的设计有哪些用到了单例模式 +
- 底层创建 Bean 是线程安全的吗?一定会用到
synchronized
+吗?
+ - 启动时直接把所有 Bean 都创建好,可不可以保证线程安全? +
- MySQL 的索引机制 +
- B+ 和 B 树的区别 +
- MySQL 乐观锁和悲观锁 +
- update 用的是行锁还是表锁 +
- 二级索引、联合索引、最左前缀匹配原则 +
- Redis 怎么实现过期删除策略(不是内存淘汰策略) +
- 缓存穿透 +
- Redis 大 Key 问题的定义,解决方法 +
- 线程池的核心线程池的个数是如何设置的? +
- LayerNorm -通过均值和标准差对输入进行标准化,确保输入具有零均值和单位方差,这对稳定训练有帮助。 -
- RMSNorm -则通过均方根进行归一化,不关注均值,仅对幅值进行规范化,避免了对数据的中心化处理,减少了计算复杂度,并且在某些模型中表现优越。 +
- CPU密集型任务:N+1 +
- IO密集型任务:2N
- x 是输入向量(通常是模型中每一层的输出)。 -
- \(\mu\) 是输入向量的均值。 -
- \(\sigma\) -是输入向量的标准差。 -
- \(\gamma\) 和 \(\beta\) 是可学习的缩放和偏移参数。 +
- 把大 key 拆分成一个一个小 key; +
- 将大 Key 拆分成多个小 Key 并用 Hash 结构存储; +
- 定时检查 Redis 是否存在大 key ,如果该大 key 是可以删除的,不要使用 +DEL 命令删除,因为该命令删除过程会阻塞主线程,而是用 unlink 命令(Redis +4.0+)删除大 key,因为该命令的删除过程是异步的,不会阻塞主线程;
- \(\text{RMS}(x) = \sqrt{\frac{1}{n} -\sum_{i=1}^n x_i^2}\)是输入向量的均方根; -
- $$ 是可学习的缩放参数; -
- 不使用均值和偏移参数 \(\beta\) -; +
- 应用服务:Redis 是单线程的,大 Key +写入和删除会阻塞其他命令;内存分布不均,失去内存时空局部性特性;网络阻塞,IO +压力大; +
- 持久化:Always 参数下数据同步到硬盘时会阻塞主线程;经常性触发AOF +重写机制;AOF 重写机制和 RDB 快照(bgsave 命令)的过程,都会分别通过 +fork() +函数创建一个子进程来处理任务,会导致阻塞父进程(主线程);集群模式下内存分布不均
- 自我介绍 +
- Rpc 项目具体是什么 +
- 如何分析 dump 文件 +
- synchronized Reentrantlock 的具体使用场景有什么不同 +
- MySQL 调优 +
- 索引:用于引入源数据并对其进行索引的管道 +
- 分布式微服务架构复杂 === 请教前辈、打断点弄明白数据流; +
- 多线程并发,编排任务执行流程 === 美团技术博客 CompletableFuture +原理和实践; +
- 沟通协作,和同事交流,理解别人的想法的同时清楚地表达自己的想法;让领导清楚自己在做什么,工作量和重难点在哪 +=== 多沟通多交流,先理清自己的想法再和同事、领导沟通; +
- 加载:将数据库中的大段文本读入系统 -
- 拆分:大块数据不便于搜索,且模型的上下文窗口有限,因此需要拆分数据 -
- 存储:采用向量数据库和索引存储数据 -
- 检索和生成:实际的 RAG -链,它在运行时接受用户查询并从索引中检索相关数据,然后将其传递给模型 +
- LLM 部署,技术选型 FastChat、FastApi、VLLM 加速 === +实践尝试,选择最合适的方法; +
- 思考如何实现需求 === +参考别人发表的经验和思路,比如看论文、技术博客、线上宣讲会、开源项目等,在针对需求改进和优化; +
- Prompt 构建,数据切分、数据集构建:分词、分段、Embedding 计算 + +
- 检索:将用户的查询通过嵌入模型转化为向量,以便与向量数据库中的其他上下文信息进行比对。通过这种相似性搜索,可以找到向量数据库中最匹配的前 -k 个数据 -
- 生成:将用户的查询和检索到的额外信息一起嵌入到一个预设的提示模板中,这个经过检索增强的提示内容会被输入到大语言模型 -(LLM) 中,以生成所需的输出 -
- Netty 数据传输 +
- RPC架构==Bean 生命周期,分布式注册中心:zk(CP、zab算法) -
get_format_instructions() -> str
:方法,返回一个包含有关如何格式化语言模型输出的字符串,即提示 -Prompt。
-parse(str) -> Any
:方法,接受一个字符串(假定为语言模型的响应)并将其解析为某个结构。
-parse_with_prompt(str) -> Any
:一个方法,它接受一个字符串(假设是语言模型的响应)和一个提示(假设是生成这样的响应的提示),并将其解析为某种结构。提示在此大多数情况下是为了提供信息以便 -OutputParser 重新尝试或以某种方式修复输出。
+- 数据库缓存一致性设计 +
- 新需求的开发
- 使用工具并观察其输出 -
- 生成相应返回给用户 +
- 以客户为中心,以奋斗者为本,长期艰苦奋斗,坚持自我批判
- 缺陷:文档越长,TF 越大;解决:除以文档长度,归一化;\(\sum_{t\in -Q}\frac{\mathrm{tf}_{t,d}}{l_d}\) -
- 缺陷:每个词重要性不同;解决:语义重要性(term -weight),在文档中出现的越多,权重越低; +
- 我认为艰苦奋斗是一种积极向上、不断进取的品质,是为了实现自身价值,努力过上充实且有意义的人生,而不仅仅是为了眼前的利益; +
- 结合我自己的经历来看,虽然中考失利了,但我仍保持努力拼搏的信念,在后续的高考、考研中不断超越自己,才有机会接触到了更多有挑战有意义的事情;
- batch size 大,并行计算; -
- 模型参数量大,每个参数都需要存储空间(精度不同占用空间不同 fp32 fp16 -bf16 int8 int4); -
- 计算过程产生大量的中间变量(如激活值、梯度等),这些中间变量也需要存储在显存中,以便进行后续的计算; -
- 优化器所需的额外信息多(如动量、学习率等); -
- 模型复杂,反向传播的计算图占用更多显存; -
- 不需要存储它们的梯度; -
- 不需要为不可训练参数分配额外的内存来存储优化状态(如动量、学习率等); -
- 不需要存储中间激活值(激活值用于在后向传播过程中,计算梯度,进而更新模型的参数); -
- 梯度累计技术:将多个小批量训练数据的梯度进行累积,在达到指定累积次数后,使用累积梯度统一更新一次模型参数,从而达到与大批量数据训练相近的效果; +
担任角色;负责的工作;项目背景;前期调研;创新点
+项目有哪些难点
+开发过程中遇到问题;如何解决
+科研过程中遇到问题;如何解决
-
-
- 相当于降低了 batch size,因而减少了显存占用; -
- 多个小批量的可训练参数的梯度是存在一起的,不额外占用显存; +
- 一开始对科研内容一窍不通,通过不断的学习试错总结慢慢积累了经验
-- 梯度检查点 -gradient_checkpoint:在后向传播过程中重新计算前向传播中的某些中间激活值,从而减少显存占用;
全量微调大模型虽然效果还不错,但需要大量的计算资源和训练数据(训练数据中通用数据和领域数据都要有);
-为了降低计算资源,只微调模型的某几层参数时,无法得到较好的微调结果,会出现欠拟合或泛化能力降低的情况,模型无法有效学习领域数据的知识,且可能会破坏了预训练模型的通用语言语义能力;
-当修改了输入 Embedding -或大模型每一层的某些部分时,可以在有限的计算资源上,得到与全量微调近似的微调效果,这便是 -PEFT 存在的理由;
-不同领域的全量微调模型需要分开部署,资源占用量大;由于只修改了部分参数,PEFT -中的方法,都具有“一次部署,多领域共用”的能力,只需要一次就能加载所有参数,针对不同领域的调用切换不同的 -PEFT 参数,即采用该领域微调所增加的小部分参数;
+- 专利修改,秋招找工作,写大论文+毕业答辩 +
- 学习大数据技术栈(Hadoop、Map-Reduce、Hbase),出国旅行
- 高效微调 PEFT; +
- 进入优秀的团队中工作学习; +
- 前四年深耕技术,不断学习,沉淀技术栈,拓宽视野; +
- 抓住机遇,第六、七年应聘管理层,接业务,带团队,一个人的力量终究是有限的,只有激发团队的力量才能办成大事; +
- Lora -
- Prefix-Tuning -
- 前向激活值; +
- 学习大数据相关的技术栈; +
- 抓住现有机会,积极投身工作中,不断提升技术能力,扩大人脉。耐心地等待机遇,当机遇来临时果断抓住它; + +
- Gradient Accumulation -
- Gradient Checkpoints -
- Data Length -
- 优化器状态; +
- 大一只有中游水平,后面几年排名逐年上升,大三拿到了学业奖学金并考研成功。在读研期间也能有中上游的绩点,拿到了学业奖学金; + +
- Adafactor Optiomizer -
- 前向激活值 + 梯度; +
- 无论是在芯片、操作系统还是在手机、汽车等领域,华为都是中国的一线品牌,华为当下在做的事情相当于五十年前的核武器研究; +
- 参加华为举办的竞赛感受到华为的人文关怀做得很好,比赛场地布置的很用心,比赛结束后还举办了活动,吃了大餐,临走还送和一袋纪念品,包括所有人的合照; +
- 体验大厂的氛围和管理制度,和优秀的团队一起成长,努力工作,争取毕业留在华为; + +
- Freeze Model -
- 参数量化; +
- 半年,立刻到岗 + +
- QLora -
- 对大语言模型很感兴趣;LLM +的训练和微调对硬件和数据集的要求高,但实验室只有 A6000,更加适合 LLM +的应用开发,看了很多论文、开源项目和技术博客,最终让基于大语言模型实现一个具体需求的过程非常有成就感; -
- Selective:选择模型中的一部分参数进行微调; -
- Additive:冻结模型原有参数,微调新增的参数和模块; +
- 对语言模型没有任何了解,实验室也是第一次接语言模型的项目,没有任何沉淀,一开始上手很艰难,只能不断重复去看网课和教程; +
- Adapters: -
- Soft Prompt: -
- Reparameterzation: +
- 论文、技术博客、开源项目、社群宣讲会 -
微调图像大模型 Stable Diffusion:lokr loha;
-将文本到图像的扩散模型适应下游任务:正交矩阵OFT、蝴蝶微调 Boft -;
+- 技术博客,因为它更加贴近实际落地的工作,大佬们留下的经验往往给我灵感
- 简单高效,资源占用量小; -
- 泛化性强,适用各种场景; +
- 人生中最大的挫折应该是中考,我当初冲重高保底优高,最后发挥失常只考上了职高; +
- 高中 +保持学习的劲头,稳扎稳打,高考超重点线;这段经历让我任何时候都不会轻言放弃,即使失败了也没事,总结反思之后再出发,家人和朋友一直都在,成功与否只是我自己的选择;
- 可解释性差; -
- 强依赖于大模型自身的质量; +
- 跑步、爬山、骑行
- 参数量低,效果不错; -
- 简化了不同任务之间的转换和迁移,使得模型可以更加灵活地应用于各种场景; -
- 3.1 overall
-
-
- 预训练模型较小或在Few-shot场景下,微调结果不佳; +
- 提出xxx,有效解决xxx,比别人好在哪xxx。包含了三个模块,介绍xxx,数据流xxx,提高了哪些xxx;由于这三个特征不能有效表示xxx,所以用异构图网络xxx,可得到两个状态,xxx。因此,提出的模型,有一样也有有不一样【总分总】 +
+ - 3.2 archieve +
- 3.3 +
- 3.4 -
- 通过 Encoder 将离散的 Prompt Embedding 转变为连续的,减少了 Prompt -Embedding 初始化对微调性能的影响,提高了训练的稳定性; + +
- 指标,解释,为什么好,好在哪
- 增加的 Prompt Encoder 需要额外的计算资源; +
应用层,直接服务于用户。唯一运行在用户态的层:HTTP、FTP、Telnet、DNS、SMTP、DHCP
+传输层,应用层的技术支持。应用层数据超过 MSS 会将其切分成 TCP +段,传输层报文中包括了端口号,用于区分报文属于哪个应用:TCP、UDP
+网络层,负责数据在网络中的传输,即寻址和路由。超过 MTU +会切分,IP地址代表网络号和主机号:IP、ARP、ICMP
+传输层,关注链路级别的传输
- 解析 URL +
- DNS 查询服务器 IP +地址(本地域名服务器->根域名服务器->顶级域名服务器) +
- 操作系统协议栈,包括传输层和网络层协议实现 +
- TCP 建立连接(SYN_SEND、SYN_RECE、ESTABLISHED) +
- 基于端口的 TCP 可靠传输 +
- 基于地址的 IP 定位传输 +
- 头部加上发送和接收方的 MAC 头部,ARP 查找接收端的 MAC +
- 网卡,帧校验符 +
- 交换机,以太网设备,基于 MAC 地址表转发,没有缓存就广播 +
- 路由器,和网卡类似,各个端口都具有 MAC 和 +IP。通过路由表确定要到目的地 IP 需要走哪个端口,并替换帧的源、目标 +MAC +
- TCP 四次挥手(FIN_WAIT_1、FIN_RECE、FIN_WAIR_2、LAST_ACK) +
- 将用户待发送的数据从用户态拷贝到内核态 sk_buff +内存,并将其加入到发送缓冲区; +
- 克隆一份 sk_buff 的副本,用于网络层传输,传输层保留原始 sk_buff +直到接收到 ACK,以保证可靠传输; +
- 当 IP 层发现数据包大于 MTU 时,会申请额外的 +sk_buff,并将原来的数据包拆分成多个小的 sk_buff; +
- 拟合速度快; +
- 长连接,复用 TCP 连接 +
- 缓存:强制缓存和协商缓存 +
- 压缩 +
- 管道传输 +
- 灵活、易于扩展
- 直接修改模型结构,依赖预训练模型本身的结构; -
- 实现复杂,相比于直接修改输入 Prompt Embedding 没有显著优势; -
- 相比于其他的 Soft Prompt 方法,Prefix Tuning -可训练参数量大,每一层的 K V 都需要可训练前缀; +
- 头部压缩 +
- 并发传输 +
- 服务端主动推送 +
- 二进制帧格式传输
- 移除重参数化的编码器,对于较小的模型,会影响模型的表现,且对于大模型提升不大; -
- 引入多任务学习概念,先在多任务的Prompt上进行预训练,然后再适配下游任务; -
- 提出了 QUIC 传输层协议代替
+tcp。quic是基于udp实现的,在无连接的基础上实现了可靠和安全
-
-
- prefix长度在 100~200 -时,微调结果最优,但由于模型可接受的最大输入长度有限,随着软提示的参数量增多,实际输入序列的最大长度也会相应减小; -
- 直接优化 prompt 和 prefix 是非单调的,比较难以收敛; +
- 更快的请求多路复用 +
- 避免队头阻塞 +
- 更快的建立连接 +
- - 需要底层实现来加速非结构化稀疏矩阵的计算,不能直接使用现有的框架; -
- 训练过程中需要存储完整的∆矩阵,相比于Full -finetune并没有降低计算成本; -
- 加密传输:在应用层和传输层之间加了 SSL/TLS 安全协议;建立连接时需要 +SSL/TLS 的握手过程;使用时需要向 CA 申请数字证书 +
- 摘要算法 + 数字签名
-
-
- 可以将原权重与训练后权重合并,在推理时不存在额外的计算开销; -
- 不增加输入参数,不改变模型结构,简单易用,泛化性强; -
- 提出低秩分解矩阵的思路,在减少计算资源需求的同时,不会丢失预训练原有的通用能力; -
不足:
+ - 混合加密:建立连接用非对称加密:公钥和私钥;传输数据用对称加密:一个密钥 +
- 摘要算法:用摘要算法(哈希函数)来计算出内容的哈希值,哈希值是唯一的,且无法通过哈希值推导出内容 +
- 数字签名:通过「私钥加密,公钥解密」的方式,来确认消息的身份 +
- 数字证书:通过第三方 CA 保证服务器的公钥私钥没有被别人替换过 + +
- 建立连接:RSA算法
-
-
- 预先指定每个增量矩阵的内在秩 r -相同,忽略了在微调预训练模型时,权重矩阵的重要性在不同模块和层之间存在显著差异,在实验中可以发现 -Wq -的秩更大,即存储的信息更多;因此无法完全捕捉预训练模型的特征,或无法有效地将原始模型的知识迁移到目标任务上; -
- 只训练了self-attention,没有训练 feed-forward networks,事实上 FFN -更重要; +
- ClientHello:客户端生产随机数 Client Random +
- SeverHello:服务端生产随机数 Server Random、数字证书 +
- 客户端回应:获取证书中的服务器公钥、加密通信算法改变通知、公钥加密随机数 +pre-master key +
- 三个随机数算出会话密钥,双方都通知对方后续请求都使用会话密钥加密通信 +
- - 调节的参数少于 Lora,微调效果也不错; +
- 首先确认客户端不会再发送请求给服务端 +
- 然后服务端在发送完数据后,再向客户端发送断开连接
- 学习率对微调效率影响较大,论文中的建议是 3e-3; +
- 在 Encoder 和 Decoder 之间加了一层 GCNConv 和 RGCNConv
- 需要修改原有模型结构,会增加模型参数量; -
目前研究的缺陷
-
-
- Paper:仅在 -MLP 模块之后和 LayerNorm 之后使用适配器层 -
AdapterFusion
-整合来自多个任务的知识的方法时,常遇到灾难性遗忘和多任务数据集平衡方面的困难。AdapterFusion -分离知识提取和知识组合这两个阶段,可以以非破坏性的方式有效地利用从多个任务中学到的表示。知识提取阶段学习Adapter -任务特定参数,其封装了特定于任务的信息;知识组合阶段将不同任务的 Adapter -组合到一起。
- -- -
-
AdapterFusion -组件将在不同任务上训练的多个适配器的输出作为输入,并学习编码信息的参数化混合器,应用于单个任务多 -Adapter 的场景和多任务混合的场景。单任务场景中,可以多个 Adapter -可用于提取同一下游任务不同维度的信息,再将他们融合起来。
-优势:
+- 关注序列上下文信息,忽略了全局原因和局部心理意图与其的层次关系 + +
本文
-
-
- 优于在单任务和多任务中训练的 Adapter -模型,可以视为多Adapter提取不同维度的信息,AdapterFusion -将他们融合起来。 +
- 提出了一个全局到局部的层次图网络来捕获多源信息(全局原因、局部意图和对话历史)并建模它们之间的层次关系,该网络由一个多源编码器、一个层次图推理器和一个全局引导解码器组成 +
- 设计了一个新的训练目标来监测全局的语义信息 ## Introduction +
+探索求助者情绪问题的原因:全局地控制情感支持对话的整个流程
+了解求助者的心理意图:帮助系统局部了解求助者当前时的心理状态
+本文目标
+-
+
- 捕获全局原因和局部心理意图 +
- 建模全局与局部之间的关系 +
+解决方法【全局到局部层次图网络GLHG】
+-
+
- 多源编码器:COMET提取局部心理意图 +
- 层次图推理机:全局原因(对话级)、局部心理意图(句子级)和对话历史之间的层次关系进行建模 +
- 解码器中设计了一个新的训练目标来监控全局原因的语义信息 ## Related +Work +
+图建模对话
+-
+
- GCN 利用自我和对话者间依赖性来模拟会话上下文 +
- EGAE 使用图网络捕获面向任务对话中的对话模式 +
+常识性知识
+-
+
- 与本人有关的心理状态:xReact、xIntent ## Approach +
+问题定义
+多源编码器
+-
+
- BlenderBot Encoder + Max-pooling +
- 上下文 + 全局原因 + 局部原因 +
+分层图推理机
+-
+
- GAT +图注意力网络:其他邻域信息的特征传播到当前节点,具有确定节点之间重要性和相关性的优点 +
+注意力函数(2017出版)
++
+注意力机制
++注意力机制
+
+Global-guide 解码器
+-
+
- 响应生成
,v表示图神经网络得到的全局变量
+ - 监督全局语义信息:预测问题类型
+- 响应生成
联合训练
+-
+
- 对数似然损失+交叉熵损失 +
+
+
Experiments
+
+指标:plexity (PPL), BLEU-n (B-n), ROUGE-L (R-L), +Distinct-1(D-1), and Distinct-2 (D-2)
+由于有了意图特征,提出建议更具体有效 ## Conclusion
+全局到局部的层次图网络(Global-to-Local Hierarchical Graph +network, GLHG)来捕获多源信息并从全局到局部的角度建模层次关系
+新的训练目标“预测Seeker遇到问题的类型” # 关注的问题 / +本文的优势
-- 通过从较低的 Transformer 层删除可变数量的Adaper来提升推理速度。 -当对多个任务执行推理时,动态地减少了运行时的计算开销,并在很大程度上保持了任务性能; +
- 多源编码器利用情境信息并将心理意图与COMET结合,捕获全局原因和局部意图 +
- 分层图推理机在全局原因、局部心理意图和对话历史之间进行交互,建模不同层次的关系(hierarchical +graph reasoner) # 实验结论
- 利用LLM进行数据增强,使用公开的对话帖子触发各种主题的对话 +
目前工作的缺陷
+-
+
- 成本高、耗时长 +
- 预算限制,所收集的对话规模小,主题少 +
+本文主要贡献
+-
+
- 关键发现 +
- 使用 GPT-J 和公开对话帖子触发各种主题的对话 +
- 构建机器增强数据集AUGES,具有更广泛和多样化的主题覆盖范围,可以提供更有效的情感支持 +## Related Work +
+预训练模型
+预训练模型的数据增强 ## Key Findings
+语言模型优于对话模型
+-
+
- 语言模型存储了从大规模训练语料库中学习到的更丰富的知识,有助于更好地泛化到各种对话主题 +
- 与会话模型 BlenderBot +相比,gpt生成的对话具有更好的对话连贯性和一致性 +
+语言模型比交互式仿真更适合开放式对话数据增强
+提示GPT不如微调GPT模型
+-
+
- 提示型GPT-3生成可控性差 +
- 只有微调才能掌握任务场景和所需特征 +
+少样本(Few-shot)微调导致更好的泛化和更高的多样性
+-
+
- 保持语言模型的内在知识 +
- 增加调优样本或训练步骤会导致对域外主题的泛化能力差 +
- 在大规模自动数据增强的帮助下,训练对话模型可能只需要少量手动策划的对话样本 +
+信息性查询(第一个对话帖子)是触发主题对话的必要条件
+-
+
- 泛型和无信息的查询往往导致离题和肤浅的对话 ## Methodology +
+主干模型:GPT-3,微调后的GPT-J
+提示模板:对话场景+情感支持
+将第一个对话框作为触发查询,模型生成后续的对话
+不采用Prompt提示,使用ESConv微调GPT-J
+触发Query
+-
+
- 数据来源:EmpatheticDialogues(移情对话数据集)Reddit(心理健康相关的帖子) +
- 保留带有负面情绪的Query +
+过滤结果,删除非法对话 ## AUGESC +相比ESConv对话轮次更少,内容更长。语料库规模的扩大导致唯一二元分词的数量
+ESConv中的对话话题与数据收集时期(如covid, pandemic, +christmas)密切相关
+AUGESC-ED +涵盖了更多关于日常生活的主题(例如,汽车、狗、房子、邻居)
+AUGESC-Reddit 涵盖了关于心理健康的主题(例如,抑郁、焦虑、治疗师) +## Quality Evaluation 在信息一致性、话题一致性和对话基础等方面存在问题 +## Interactive Evaluation > +AUGESC是对ESConv的一种补充,用AUGESC+ESConv训练出来的模型表现优于只使用ESConv的模型
+- 关注的问题
+
-
+
- 动态建模对用户状态,包含个体的意图和情感 +
- 综合各类因素选择最合适的支持策略 +
+ - 提出的方法【基于异构图注意力网络的深度Q-learning情感支持对话生成】
+
-
+
- 为了捕获用户意图、情感和历史对话之间的交互关系,基于意图词典和情感分类器,构建了异构图注意力网络 +
- 采用基于DQN的最优响应策略以指导响应生成,优于传统的基于规则或启发式方法 +## Introduction +
+ - 目前研究
+
-
+
- ESC任务要求能够确定求助者的心理意图和情绪状态,以便提供适当的支持。因此整合意图识别和情感识别对于提高情感支持对话的质量至关重要,且目前的方法对用户状态建模不充分。 +
+ - 关注的问题
+
-
+
- 建模用户状态 +
- 选择最优策略,以产生有效的保障响应 +
+ - 提出的方法
+
-
+
- 设计了基于注意力的异构图网络,与用户的意图、情感和历史对话交互,可以有效地捕获和建模图中不同类型的节点和边 +
- 构建意图词典和情感分类器来捕捉求助者在语境中的细微情感表达 +
- DQN算法对用户未来反馈的期望值进行估计,帮助系统选择获得最优长期值的策略。其允许系统从用户的反馈中学习,调整其策略,以提供最有效的支持响应。 +
+ - 主要贡献
+
-
+
- 提出了一种新的方法DQ-HGAN,将意图和情感识别与策略生成相结合,以提高情感支持对话系统的质量和个性化 +
- 构建意图词典和情感分类器,捕捉求助者在语境中的细微情感表达并跟踪其状态 +
- 设计了一种基于注意力机制的异构图网络,与用户的意图、情感和历史对话进行交互,并选择最优的支持策略以生成有效的支持响应 +
- ESC生成中使用ESC生成中使用强化学习,具体来说,使用DQN算法(Deep +Q-Network)估计用户未来反馈的期望值,动态调整策略以提供最有效的支持响应 +## Related Work +
+ - 对话中的意图和情感识别【在模型中融合了“意图”这个特征】
+
-
+
- 多头注意力机制
+
-
+
- 多头注意力机制来捕捉用户的意图和情感。缺点:缺乏有效捕捉用户细微情感表达的能力 +
- 使用预训练模型,增强PLM对话相关性,识别对话意图、推断对话情感。缺点:不是专门为ESC任务定制的,性能差 +
+ - 词典
+
-
+
- 词典包含特定意图或情感相关的词汇和短语,利用基于规则的算法将context与意图词典进行匹配,并分配相应的意图标签。缺点:只将单个单词与标签匹配,可能会忽略整个句子的意图或情感含义 +
+
+ - 多头注意力机制
+
- 图建模【捕获会话系统中用户意图、情感和对话历史之间的复杂关系】
+
-
+
- 同构图【忽略了用户意图和情感的异构性】
+
-
+
- GAT +图注意力网络,利用自注意力机制来捕获对话图中意图和情感节点之间的交互 +
- GCN +图卷积网络,利用图结构在节点之间传播信息,并捕获对话数据中的上下文依赖 +
+ - 异构图注意力网络是专为表示图中不同类型的节点和边而设计的,它擅长对不同的节点类型进行建模,如用户话语、系统响应、情感状态和意图,从而更全面地了解用户的情感状态;还擅长捕捉不同类型的边,包括顺序依赖、自依赖和状态依赖,从而能够更准确地表示用户的情感状态。此外,它还包含了一种注意力机制来进行重要性加权,允许它在聚合过程中专注于最相关的信息,从而更全面地了解用户的状态。 +
+ - 同构图【忽略了用户意图和情感的异构性】
+
- 策略选择
+
-
+
- 基于规则或启发式方法 +
- 强化学习方法(如:Q-learning)
+
-
+
- 采用DQN估计不同对话动作的期望值,并学习了一种最大化该值的策略。从用户反馈中学习,并生成更有吸引力和信息量的响应 +
+
+ - 响应生成
+
-
+
- 目前流行的Encoder-Decoder模型往往专注于根据对话历史生成回复,而没有考虑用户的意图、情感以及合适的支持策略 +## Preliminaries +
+ - ESConv:标记对话,并将其转换为词嵌入,以将其输入到模型中 +
- COMET:使用COMET初始化模型的词嵌入,并在ESConv数据集上进行微调,以提高其构建意图词典的有效性 +
- ATOMIC:得到意图或目的(xIntent) +
- NRC VAD +词典:得到情感词典,每个单词对应的效价-觉醒-支配(Valence-Arousal-Dominance) +
- 问题定义:上下文+策略+Query
+=>响应Yt。最优策略基于当前状态和期望的长期回报(通过Q-learning预测)
+## Method
- transformer编码器(TransformerEncoder)
+
-
+
- ht = TransformerEncoder(Ht) +
+ - 意图词典(COMET):通过对ATOMIC
+微调,同去意图关键词,构建意图词典(意图关键词,对应的词嵌入)
+
-
+
- \[g_{t}=TransformerEncoder\left(\sum_{w_{i}\in\mathscr{F}}\operatorname{softmax}\left(c_{i}^{T} +h_{t}\right)c_{i}\right) \] +
+ - 情感分类器(NRC VAD词典)
+
-
+
- \[e_{t}=\text{TransformerEncoder}\left(\sum_{w_{k} +\in \mathscr{Z}}\operatorname{softmax}\left(z_{k}^{T} h_{t}\right) +g_{t}\right) \text { }\] +
+ 双层反馈策略选择器:通过反馈信息预测策略
+双层控制阅读器:通过策略约束上下文响应
+策略词典:丰富策略的语义信息 ## Introduction ## Related Work ## +Problem Formulation ## Approach
+上下文编码器
+-
+
- BlenderBot预训练编码器编码上下文历史对话U,得到Ht +
+双层反馈策略选择器
+-
+
- 策略选择
+
-
+
- 输入
+
-
+
- BlenderBot Encoder 编码上下文历史对话U,得到隐状态Ht +
- BlenderBot Encoder 编码策略S +
- EmoBERTa Encoder 编码上下文对话U +
+ - 公式
+
-
+
- 上下文编码器(策略S同理):\[\boldsymbol{H}=\operatorname{Enc}_{cxt}\left(\boldsymbol{[CLS]},
+\boldsymbol{u}_{1}, \boldsymbol{[SEP]}, \boldsymbol{u}_{2}, ...,
+\boldsymbol{u}_{M}\right)\],M为对话数
+
-
+
- \[\boldsymbol{H}=\left(\boldsymbol{u}_{1},..., +\boldsymbol{u}_{T}\right)\],T为Token数 +
+ - 情感编码器:\[\boldsymbol{E}=\operatorname{EmoBERTa}\left(\boldsymbol{[CLS]},
+\boldsymbol{u}_{1}, \boldsymbol{[SEP]}, \boldsymbol{u}_{2}, ...,
+\boldsymbol{u}_{M}\right)\],M为对话数
+
-
+
- \[\boldsymbol{E}=\left(\boldsymbol{e}_{1},..., +\boldsymbol{e}_{T}\right)\],T为Token数 +
+ - 分类:\[\boldsymbol{o}=\operatorname{MLP}\left(\tanh
+\left(\boldsymbol{W}_{o}^{T}[\boldsymbol{s} ; \boldsymbol{c} ;
+\boldsymbol{r}]+\boldsymbol{b}_{\boldsymbol{o}}\right)\right)\]
+
-
+
- s、c、r 为策略S、上下文H、情感分类E。编码+平均池化操作后得到 +
+
+ - 上下文编码器(策略S同理):\[\boldsymbol{H}=\operatorname{Enc}_{cxt}\left(\boldsymbol{[CLS]},
+\boldsymbol{u}_{1}, \boldsymbol{[SEP]}, \boldsymbol{u}_{2}, ...,
+\boldsymbol{u}_{M}\right)\],M为对话数
+
+ - 输入
+
- 双层反馈
+
-
+
- 回合级反馈:局部变量,当前用户的感受。包含每轮对话Seeker情感Δe和Seeker评分变化Δr +
- 对话级反馈:全局变量Δc,用户的全局状态。包含Seeker在谈话后的情绪压力、Supporter对话题的回应的相关性、Supporter对Seeker感受的理解和共情 +
- 融合adapter:整合回合级和会话级反馈的两类语义信息。Δs = Δe + Δr + +uΔc【计算损失时,给予正向或负向的反馈】 +
+
+- 策略选择
+
双控读取器(模仿情感聊天机器ECM)
+-
+
- context-to-strategy:利用上下文信息来选择上下文相关的策略
+
-
+
- \[\boldsymbol{g}^{c} = +\operatorname{sigmoid}\left( +\boldsymbol{W}_{c}^{T} \boldsymbol{c} + \boldsymbol{b}_{c} +\right)\] +
+ - strategy-to-context:编码阶段可以关注与策略相关的上下文,从而生成策略约束的响应
+
-
+
- \[\boldsymbol{g}^{o} = +\operatorname{sigmoid}\left( +\boldsymbol{W}_{o}^{T} \boldsymbol{o} + \boldsymbol{b}_{o} +\right)\] +
+ - 残差连接:在原始信息和更新信息之间进行权衡
+
-
+
- \[\begin{array}{r} +o^{\prime}=(1-\beta) \cdot o+\beta \cdot g^{c} \otimes o \\ +h_{t}^{\prime}=(1-\alpha) \cdot h_{t}+\alpha \cdot g^{o} \otimes h_{t} +\end{array}\] +
+
+- context-to-strategy:利用上下文信息来选择上下文相关的策略
+
策略字典
+-
+
- 输入策略令牌的描述, +而不是策略令牌,以便模型对策略进行更深入的理解 +
- Encoder-Decoder +之间的状态传输类似于MISC,采用cross-attention代替self-attentionMISC: +A MIxed Strategy-Aware Model Integrating COMET for Emotional Support +Conversation +
+响应生成
+-
+
- BlenderBot Decoder:\[\boldsymbol{p}\left(y_{z} \mid +\boldsymbol{y}_{<z}, \boldsymbol{h}_{\boldsymbol{t}}^{\prime}, +\boldsymbol{V}\right)=\text { Generator }\left(\boldsymbol{W}_{y<z}, +\boldsymbol{h}_{\boldsymbol{t}}^{\prime}, +\boldsymbol{V}\right)\] +
+联合训练
+-
+
- 策略预测:反馈感知负对数似然 feedback-aware negative log-likelihood
+
-
+
- \[\mathcal{L}_{1}=\left\{\begin{array}{ccc} +-\hat{o} \log +\left(\operatorname{softmax}\left(\boldsymbol{o}^{\prime}\right)\right) +& \text { if } & \Delta s>0 \\ +-\hat{o} \log +\left(1-\operatorname{softmax}\left(\boldsymbol{o}^{\prime}\right)\right) +& \text { if } & \Delta s \leq 0 +\end{array}\right.\\\] +
+ - 响应生成:标准交叉熵损失优化 cross-entropy
+
-
+
- \[\mathcal{L}_{2}=-\sum_{z=1}^{Z} \log +\boldsymbol{p}\left(y_{z} \mid \boldsymbol{y}_{<z}, +\boldsymbol{h}_{\boldsymbol{t}}^{\prime}, \boldsymbol{V}\right)\] +## Experiment +
+
+- 策略预测:反馈感知负对数似然 feedback-aware negative log-likelihood
+
采用EmoBERTa-base作为特征提取器,以获取Seeker的情感得分和情感表征,情感得分由softmax函数使用EmoBERTa-base的[CLS]表示获得 +## Experimental Results ## Analyses ## conclusion # 关注的问题
+预测策略只依靠对话历史,而不考虑求助者反馈,导致预测的结果与用户无关
+建模过程只关注上下文到策略,而不关注策略到上下文和与策略相关的上下文 +# 解决方法
+双层反馈策略选择器:利用回合级和会话级反馈信息来激励或惩罚策略
+双层控制阅读器:策略到上下文流来生成策略约束响应 # 创新点 / +本文的优势
+先前工作的局限性
+-
+
- 采用对话级别的情感标签,这种标签过于粗粒度,无法捕捉用户的即时精神状态 +
- 大多侧重于在回应中表达同理心,而不是逐渐减轻用户的痛苦 +
+本文提出了MISC
+-
+
- 首先推断用户的细粒度情感状态,然后使用混合策略巧妙地响应 +
- 在基准数据集上的实验结果证明了方法的有效性,并揭示了细粒度情感理解和混合策略建模的好处 +## Introduction +
+目前的工作不适用于ESC
+-
+
- 粗粒度静态的对话级情感标签无法关注到对话过程中用户情感发生的变化 +
- 只有移情反应,而不考虑解决求助者的情感问题 +
+本文提出的解决方法
+-
+
- 有选择地采用COMET(预训练生成式常识推理模型)生成的知识元组进行细粒度情感理解 +
- 混合策略,而不是预测单一策略 +
- 设计一套注意力机制 +
+实验分析
+-
+
- 回答策略建模的重要性,能够提高模型的共情能力 ## Related Work +
+情绪感知响应生成
+NLP中的常识性知识
+策略感知对话模型 ## Preliminaries
+ESConv数据集
+问题设定
-
-
- 相比于 LoRA,收敛速度更快,性能更好 -
VeRA
-区别于Lora,Vera 将 A 和 B -矩阵按照高斯分布随机初始化并冻结,只训练两组直接和A、B相乘的一维参数。虽然直观看起来A和B像两个无用的张量,但实际上它们仍然是必不可少的,实验证明即使是随机张量也可以用于微调。
- --
优势:
+- 通过对话历史、场景、求助者最后一句话,预测回复策略和回复内容 ## +Model: MISC +
情感状态增强Encoder
-
-
- VeRA显著减少了可训练参数的数量(LoRA相比参数减少了10倍),而精度没有损失; -
- 缩放向量尺寸小,可以将许多版本驻留在单个GPU的有限内存中,从而大大提高了服务效率,适合于需要频繁交换大量微调模型的场景,比如针对个人用户个性化的基于云的人工智能服务; +
- 利用COMET提取场景situation和语句x的常识性知识,将常识性知识输入Encoder得到H's和H'x +
-- 节省内存(三倍); -
- 性能不错; -
- 将H's和H'x分别与历史对话c做cross-attention,得到Hs和Hx +
- 将历史对话c输入Encoder得到C +
- 混合策略学习模块【从VQ-VAE's codebook文章中抄来的】
-
-
- 训练速度慢(三倍); +
- C输入多层感知机+softmax得到Pg(Pg大小是strategy_size) +
- Pg作为概率分布,hg=Pg*T(T为策略嵌入)
+
-
+
- 长对话回复中可以引入多种策略,且模型学习灵活方便 +
+
+ - 多因素感知Decoder
+
-
+
- 将情绪状态和策略表征传入Decoder里的Cross-attention ## +Experiments +
+ - ESConv中的每十个话语作为一个样本 +
- 评价指标
+
-
+
- 策略预测精度:Acc +
- 传统NLP指标:PPL、BLEU、ROUGE-L +
- 相应多样性:Distinct +
- 人类评估 +
+ - 基准模型
+
-
+
- MT Transformer、MoEL、MIME、BlenderBot-Joint +
+ - 具体实现 +
- 实验结果
+
-
+
- 动态细粒度情感标签更能准确给予用户回应 +
- 细粒度共情,多策略平稳过渡策略,可以更自然地表达共情并提供帮助 +
- 策略作为单独的任务进行预测比单一预测更有利 +
- MISC的知识Know得分最高,成功学习到了COMET中的心理状态知识 ## +Analysis +
+ - 消融实验 +
- 案例研究 +
- 细粒度情感理解
+
-
+
- 用粗粒度的情感标签代替细粒度的心理信息可以显著提高指标 +
+ - 混合策略感知移情反应
+
-
+
- 混合策略有利于平滑的情感支持 +
- 混合策略比单一策略更有效 +
- 混合策略适用于ESC框架 ## Conclusions +
+ - 引入COMET来捕捉用户的即时心理状态 +
- 设计了一个混合策略感知解码器来产生支持响应 # 解决了什么问题 / +怎么解决的 -
- 4位NormalFloat(NF4):这是一种针对正态分布权重设计的信息理论上最优的量化数据类型。相较于传统的4位整数和4位浮点数,NF4为正态分布数据提供了更优异的实证性能。 -
- 双重量化:QLora引入了对量化常数的二次量化,进一步减小了缓存占用。这种双重量化机制包含对普通参数的一次量化和对量化常数的再量化,从而在不牺牲精度的前提下进一步压缩模型。 -
- 分页优化器:这是一种智能的内存管理技术,当GPU内存不足时,它可以将部分数据移到系统内存中,并在需要时调回GPU内存。这有助于处理长序列或大批量数据时的内存峰值问题。 +
长对话中的过度更加顺畅 # 有什么创新点
+提出seq2seq模型MISC,在ESC中添加了常识性知识和混合反应策略
+提出了不同的策略模型并在对话中给予提示 # +实验结果好在哪里,怎么证明的
+从SOTA延续下来的细粒度情感表现较粗粒度静态情感更好 # +相关工作分析
- 提出了高效且有效的量化技术,使在单个GPU上微调超大型参数模型成为可能; +
- 以动态的方式学习混合响应策略
i
:进入插入模式,从光标前插入文本。
-a
:进入插入模式,从光标后插入文本。
-Esc
:退出插入模式,回到正常模式。
-v
:进入可视模式,用于选择文本块。
-V
或 -vv
:进入可视行模式,选择整行文本。
-Ctrl + v
:进入可视块模式,选择矩形区域。
-相比于seq2seq的不确定性,聊天机器人利用知识图谱进行推理,被视为端到端模型的高效、万无一失的解决方案
+提出HEAL知识图谱
-
-
w
:光标移动到下一个单词的开头。
-b
:光标移动到上一个单词的开头。
-0
:移动到行首。
-$
:移动到行尾。
-gg
:移动到文件的第一行。
-G
:移动到文件的最后一行。
-H
:移动到屏幕的顶部。
-M
:移动到屏幕的中部。
-L
:移动到屏幕的底部。
-
编辑文本
+- 基于1M痛苦叙述及其相应的安慰回应而开发的知识图谱 +
- 图谱可视化:表现了对话双方的情绪动态和帮助缓解情绪的有效方法 +
- 组成部分
-
-
x
:删除光标所在的字符。
-dw
:删除从光标到单词末尾的内容。
-dd
:删除当前行。
-d$
:删除从光标到行末的内容。
-yy
:复制当前行。
-p
:粘贴到光标之后。
-u
:撤销上一步操作。
-Ctrl + r
:重做撤销的操作。
-r
:替换光标下的字符。
-ciw
:删除光标所在的单词并进入插入模式。
-c$
:删除从光标到行尾的内容并进入插入模式。
-
搜索和替换
+ - 22k Node 节点:识别不同类型的stressors, speaker expectations, +responses, feedback types +
- 104k Edge 连接:不同类型的节点之间的关系 +
- 每个节点和41种情绪状态相关联 ## Introduction + + +
神经网络架构模型缺乏可控性和黑箱性质,导致其并不可靠
+使用常识推理和知识图结构表示,可以生成适合的、可预测的、多策略的回应
+相关工作
-
-
/pattern
:向下搜索 -pattern
。
-?pattern
:向上搜索 -pattern
。
-n
:跳到下一个搜索结果。
-N
:跳到上一个搜索结果。
-:s/old/new/g
:将当前行的所有 -old
替换为new
。
-:%s/old/new/g
:将整个文件中的所有 -old
替换为new
。
-
文件操作
+- ConceptNet、ATOMIC主要是通过捕获事实知识,在开放对话中嵌入常识推理辅助对话,不适用于移情对话 + +
本文,通过子Reddit精心选择的对压力事件叙述和回应,生成了一个压力对话管理知识图谱HEAL
+-
+
- 五类节点:压力源、期望、回应类型、反馈类型、情感状态 +
- 可以准确描述以痛苦为导向对话的潜在背景,使对话模型可以检索到更具体的上下文响应。提取响应会导致的反馈类型和是否能达到期望等信息,从而产生更为合适的反应 +## Related Work +
+知识图谱可以帮助NLP理解用户的输入,拓展用户输入中的事实和常识性知识
+目前工作关注于知识感知和推理对话,不会捕捉情感推理和移情反应 ## +Methodology
+数据集管理
+-
+
- 采用reddit数据集,通过Pushshift +API,收集和处理8个子reddit对话主题:mentalhealthsupport、offmychest、sad、anxietyhelp、depression、suicidewatch、depressed、depressionhelp +
- 数据预处理 +
+概要
+-
+
- 针对过长而超出预训练语言模型输入上限的对话,本文采用SMMRY摘要算法保留叙事本质 +
+凝聚聚类
+-
+
- 自动聚类:区分对话中的压力源、期望、响应和反馈类型 +
- 凝聚聚类法:递归地合并增加最小链接距离的簇对 +
- 链接距离:对SentenceBERT生成的embedding使用余弦相似度计算 +
+定义压力源
+-
+
- 每个阈值计算了各种聚类质量指标,结果显示以0.85的相似度阈值区分压力源最合适,将压力源中的4.7%分为了4363个类。 +
- 将聚类结果按照TF-IDF建模,可以明显区分压力源,表明聚类结果的可靠性。 +
+期望、回复、反馈类型
-
-
:w
:保存文件。
-:q
:退出 Vim。
-:wq
:保存并退出。
-:q!
:不保存强制退出。
-:e filename
:打开文件 -filename
。
-:r filename
:在当前文件中插入 -filename
的内容。
-
Screen
-基本命令
+- 提取带有❓的句子作为问题,以此问题提取相关的响应和反馈。使用NLTK分离响应和反馈中的单个对话,方便后续对其进行单一种类的聚类。 +
- 聚类方法与压力源一致,每个集群至少有两个不同的集群元素。 + +
情感状态建模
-
-
screen
:启动一个新的 -screen
会话。
-screen -S session_name
:启动一个命名为 -session_name
的screen
会话。
-screen -ls
:列出当前所有的 -screen
会话。
-screen -r
:重新连接到一个 -screen
会话(如果只有一个会话)。
-screen -r session_name
:重新连接到一个名为 -session_name
的screen
会话。
-screen -d session_name
:在其他地方的终端断开某个会话的连接。
-screen -d -r session_name
:强制从其他地方的终端断开并重新连接到 -session_name
会话。
-screen -X quit
:关闭所有 -screen
会话
-
在
-screen
会话中操作在
+screen
会话中,所有命令都以Ctrl + a
-开头(表示“前缀键”),然后跟随其他按键来执行操作。- 使用Pu提出的基于BERT的情感分类器,将每一个簇与某一情感状态相关联,共有41种情感状态。先将每一个簇下的每个文本进行分类,再按照情感出现次数和分类置信度排序,选取最相关的情感状态。 +## Statistical Analysis + +
HEAL知识图谱:2.2k集群节点和情感状态,104k连接
+反馈集群中,负面情绪明显减少,证明HEAL中存在帮助人们降低负面情感状态的有用响应 +## Visualization and Interpretation
+表示大多数回答都是正向积极反馈 ## Evaluating the Utility of HEAL +in Responding to Distress Prompts
+获取共情响应
-
-
Ctrl + a, X
:关闭当前的分割窗口。
-Ctrl + a, c
:创建一个新的窗口。
-Ctrl + a, n
:切换到下一个窗口。
-Ctrl + a, p
:切换到上一个窗口。
-Ctrl + a, "
:列出当前所有窗口,允许选择切换。
-Ctrl + a, 0-9
:切换到指定编号的窗口(例如 -Ctrl + a, 1
切换到窗口 1)。
-Ctrl + a, d
:将当前 -screen
会话断开(detach),会话继续在后台运行。
-Ctrl + a, A
:重命名当前窗口。
-Ctrl + a, K
:关闭当前窗口。
-Ctrl + a, S
:水平分割当前窗口。
-Ctrl + a, |
:垂直分割当前窗口。
-Ctrl + a, tab
:在分割的窗口间切换焦点。
-Ctrl + a, Q
:关闭除了当前窗口外的所有分割窗口。
-Ctrl + a, X
:关闭当前的分割窗口。
+- 从测试集中选取和压力源中现有叙述相似性高于0.75的新对话 +
- 根据压力源和响应之间边权的权重、响应簇大小进行排序,选择排名高的响应 +
+自动评估
+-
+
- HEAL的响应更加多样化,可以根据给定的情况给出特定的响应 +
- 在其他自动指标BLEU、METEOR和ROUGE方面表现不佳 +
+人类评估【DOI: 10.18653/v1/d16-1230】
+-
+
- HEAL模型变现更好 ## Discussion and Conclusion +
+HEAL:利用Reddit上约1M个与痛苦相关的对话得出的知识图谱。在不同类型的压力源、说话者期望、求助者反应和求助者反馈类型之间形成联系,同时将每个节点与41种情感状态中的一种联系起来
+
-Ctrl + a, :quit
或 -Ctrl + a, d
:结束当前screen
-会话。
-Ctrl + a, :kill
:强制关闭当前窗口。
-exit
:退出当前screen
-会话。
+端到端对话经常会产生通用和重复性对话,缺乏可控性。使用常识推理和知识图结构表示,可以生成适合的、可预测的、多策略的回应。
+目前的知识图谱不适用于移情对话。移情领域缺乏数据集和模型帮助产生移情反应,还缺乏具有上下文-相应之间关系的知识图谱。 +# 解决方法 / 创新点
+开发大规模知识图谱HEAL,识别不同的压力源、期望、响应、反馈和该对话的情感状态
+统计和可视化分析,识别导致情绪强度降低的有利反应
+评估通过HEAL检索到的回应,在解决情感困扰问题上的共情性、多样性、可靠性 +# 实验结论
+与RoBERTa、Blender进行比较,HEAL能够产生更多样化、更移情的反应
+统计和可视化分析证实了在HEAL中存在有用的反应策略,这些策略降低了遭受痛苦的人的负面情感状态
+使用纯生成模型来解决痛苦存在危险,HEAL通过战略性地识别与给定提示相关的特定压力源来避免不适当的反应 +# 有待提升的部分
+只使用了压力源与回复的边缘权重,进一步可以通过将边缘权重与说话者的期望和反馈结合起来来开发
+知识图的信息可以用于增强神经反应生成模型,并为这些模型引入更多的可控性和可解释性,从而提高可靠性
+仅限于识别≈4K的压力源,可以从网络上获取更多数据来增强知识图谱,这将帮助其能够处理更大范围的压力源和期望
应用层,直接服务于用户。唯一运行在用户态的层:HTTP、FTP、Telnet、DNS、SMTP、DHCP
-传输层,应用层的技术支持。应用层数据超过 MSS 会将其切分成 TCP -段,传输层报文中包括了端口号,用于区分报文属于哪个应用:TCP、UDP
-网络层,负责数据在网络中的传输,即寻址和路由。超过 MTU -会切分,IP地址代表网络号和主机号:IP、ARP、ICMP
-传输层,关注链路级别的传输
-- 解析 URL -
- DNS 查询服务器 IP -地址(本地域名服务器->根域名服务器->顶级域名服务器) -
- 操作系统协议栈,包括传输层和网络层协议实现 -
- TCP 建立连接(SYN_SEND、SYN_RECE、ESTABLISHED) -
- 基于端口的 TCP 可靠传输 -
- 基于地址的 IP 定位传输 -
- 头部加上发送和接收方的 MAC 头部,ARP 查找接收端的 MAC -
- 网卡,帧校验符 -
- 交换机,以太网设备,基于 MAC 地址表转发,没有缓存就广播 -
- 路由器,和网卡类似,各个端口都具有 MAC 和 -IP。通过路由表确定要到目的地 IP 需要走哪个端口,并替换帧的源、目标 -MAC -
- TCP 四次挥手(FIN_WAIT_1、FIN_RECE、FIN_WAIR_2、LAST_ACK) -
- 将用户待发送的数据从用户态拷贝到内核态 sk_buff -内存,并将其加入到发送缓冲区; -
- 克隆一份 sk_buff 的副本,用于网络层传输,传输层保留原始 sk_buff -直到接收到 ACK,以保证可靠传输; -
- 当 IP 层发现数据包大于 MTU 时,会申请额外的 -sk_buff,并将原来的数据包拆分成多个小的 sk_buff; -
混和主动性:按照说话者角色和主动类型分为四类
+提出四个情绪支持指标
+提出一种用于 ESC 的知识增强混合主动框架 (KEMI) ## +Introduction
+ESC系统
+-
+
- 在适当的时候发起讨论,目的是提出建议,并解决问题 +
+相关工作
+-
+
- CIS(conversational +information-seeking)可以主动发起对话,澄清交互并探索更多的信息 +
- 情感推理用来生成共情反应 +
- identifying the dialogue acts of the utterances +
- ESC 系统预测下一个对话策略 +
+ESC问题的三个挑战
+-
+
- 系统应该在对话过程中何时采取主动? +
- 系统发起子对话需要什么样的信息? +
- 系统如何促进混合主动交互? +
+解决方法
+-
+
- 策略预测:确定下一回合混合主动策略 +
- 知识选择:收集下一回合的必要知识 +
- 响应生成:在适当的混合主动策略和知识下产生情感支持响应 +
+提出的新东西
+-
+
- 混合主动性特征
+
-
+
- EAFR模式:话语注释为不同类型的说话者角色和主动类型 +
- Expression, Action, Reflection, Feedback +
+ - 情感支持指标
+
-
+
- Proactivity, Information, Repetition, Relaxation +
+ - KEMI
+
-
+
- 使用生成的常识知识作为查询图来扩展用户话语,在知识图谱上执行子图检索 +
- 响应生成模块以序列到序列的方式,对策略预测和响应生成进行【多任务学习】,以生成具有外部知识的混合主动响应 +
+
+- 混合主动性特征
+
主要贡献
+-
+
- EAFR 注释模式和四种情感支持指标 +
- 使用用常识知识扩展的查询图,通过子图检索从心理健康知识图谱中检索外部知识 +## Related Works +
+ESC
+-
+
- 检测用户情绪 +
- 将情感信号放入Respond中 +
- 情绪感知反应,情感风格转移 +
- 共情对话系统
+
-
+
- 情感推理技巧 +
- 利用外部知识来提高情绪推理的建模能力:知识图、常识性模型、特定领域知识、常识性知识 +
+
+混合主动对话 ## Preliminary Analysis
+EAFR
+-
+
- 四种注释方法:按照角色和主动类型区分 +
- 四种评价指标:【待看】 +
+混合主动性分析
+混和主动性的挑战
+-
+
- 系统何时采取主动? +
- 系统发起子对话时,需要什么信息?
+
-
+
- 情感识别:识别用户情感状态 +
- 因果识别:导致情感状态的压力源 +
- 认知识别:解决问题的过程 +
+ - 根据历史对话,系统自发判断响应的主动或被动 +
+问题定义
+-
+
- 给定历史对话C和用户情况s,产生相应r
-
-
- 长连接,复用 TCP 连接 -
- 缓存:强制缓存和协商缓存 -
- 压缩 -
- 管道传输 -
- 灵活、易于扩展 -
HTTP/2 优化
+ - 策略预测y,细粒度主动性 +
- 知识选择k +
- 使用y和k生成混合主动相应r ## Method +
+
+- 给定历史对话C和用户情况s,产生相应r
知识获取
-
-
- 头部压缩 -
- 并发传输 -
- 服务端主动推送 -
- 二进制帧格式传输 -
HTTP/3 优化
+- 检索心理健康知识图谱HEAL,弥补常识性知识的不足
-
-
- 提出了 QUIC 传输层协议代替 -tcp。quic是基于udp实现的,在无连接的基础上实现了可靠和安全 +
- COMET常识性知识扩展查询:Cp = COMET(p, ut) +
- 构造查询图:û = {ut, {Cp}}
-
-
- 更快的请求多路复用 -
- 避免队头阻塞 -
- 更快的建立连接 +
- expectation:ut +
- affective:[xReact] +
- stressor:[xIntent] +
- responses:[xWant] [xNeed] [xEffect]
-
HTTPS
+ - 子图检索
-
-
- 加密传输:在应用层和传输层之间加了 SSL/TLS 安全协议;建立连接时需要 -SSL/TLS 的握手过程;使用时需要向 CA 申请数字证书 -
- 摘要算法 + 数字签名 +
- 相似度计算:sentence-BERT +
- 针对每个 ût +中的抽象描述,获取与其最相似的top-K个HEAL中的实体,基于HEAL中的边缘连接,构成候选子图 +
- 针对每个 E +中的类型节点,按照子图中的每个节点相似度得分之和排序子图,选择top-N作为检索到的知识K +
+
+
+ 混合主动响应生成
-
-
- 混合加密:建立连接用非对称加密:公钥和私钥;传输数据用对称加密:一个密钥 -
- 摘要算法:用摘要算法(哈希函数)来计算出内容的哈希值,哈希值是唯一的,且无法通过哈希值推导出内容 -
- 数字签名:通过「私钥加密,公钥解密」的方式,来确认消息的身份 -
- 数字证书:通过第三方 CA 保证服务器的公钥私钥没有被别人替换过 +
- 使用基于上下文的编码器,编码上下文对话C和知识K +
- X:[CLS]
[know.]<know.>;Y:[strategy]y[response]r
+ - 优化损失函数,最大化负对数似然函数L ## Experiment
-- 建立连接:RSA算法 +
实验基础
-
-
- ClientHello:客户端生产随机数 Client Random -
- SeverHello:服务端生产随机数 Server Random、数字证书 -
- 客户端回应:获取证书中的服务器公钥、加密通信算法改变通知、公钥加密随机数 -pre-master key -
- 三个随机数算出会话密钥,双方都通知对方后续请求都使用会话密钥加密通信 +
- 数据集:ESConv、MI +
- 评估参数:流利度Perplexity (PPL)、内容保留度BLEU-n +(B-n)、内容保留度ROUGE-L (R-L)
-
-总体表现
-
-
- 首先确认客户端不会再发送请求给服务端 -
- 然后服务端在发送完数据后,再向客户端发送断开连接 -
为什么这么设计?因为TCP是双向通信的可靠的协议,需要确保客户端和服务端都有收发数据包的能力;为后续传输做准备:序列号
-流量控制、超时重传、拥塞控制
-拥塞控制:慢开始(每经过一个传输轮次,拥塞窗口 -cwnd 就加倍)、拥塞避免(慢开始门限 -ssthresh)、快重传(连续收到三个重复确认就立即重传对方尚未收到的报文段,不等待重传计时器到期)、快恢复
-网络层 IP
--
-负责路径传输过程中路径和节点的选择,实现设备到设备的数据传输
-寻址能力:网络号+主机号(子网掩码)
-路由:数据包每到达一个节点,通过路由算法决定下一步走哪条路径
-分片重组:以太网的 MTU(最大传输单元)是 1500 -字节。在分片传输中,一旦某个分片丢失,则会造成整个 IP -数据报作废,所以 TCP 引入了 MSS 也就是在 TCP 层进行分片不由 IP -层分片,那么对于 UDP 我们尽量不要发送一个大于 MTU 的数据报文
-ICMP:诊断和通知出错
-NAT:网络地址转换
-DHCP:动态获取 IP 地址
-ARP:下一跳的 MAC 地址
-DNS:域名解析
-IGMP:组播
-]]>- BlenderBot优于Transformer +
- GLHG、MISI有效地利用了常识性知识 +
- 基于策略的联合学习可以提高性能 +
- KEMI明显优于其他方法:HEAL知识相比常识性知识更有效地支持了预测策略,减轻了对预训练大模型的依赖 + +
人工评价
-
-
- 进程是资源(包括内存、打开的文件等)分配的最小单位,线程是 CPU -调度的最小单位; -
- 进程拥有一个完整的资源平台,而线程只独享必不可少的资源,如寄存器和栈,线程之间共享地址空间和文件等资源; -
- 线程同样具有就绪、阻塞、执行三种基本状态,同样具有状态之间的转换关系; -
- 线程能减少并发执行的时间和空间开销; -
进程间通信方式
-匿名管道 / 命名管道
-消息队列
-共享内存+信号量
-Socket
-乐观锁悲观锁
-CAS 是乐观锁没错,但是 CAS 和自旋锁不同之处,自旋锁基于 CAS 加了while -或者睡眠 CPU -的操作而产生自旋的效果,加锁失败会忙等待直到拿到锁,自旋锁是要需要事先拿到锁才能修改数据的,所以算悲观锁。
-线程崩溃
-1、如果线程是非法访问内存引起的崩溃,其对应进程一定会崩溃。
-2、进程崩溃的本质是:操作系统对进程发出了信号,例如非法访问内存的信号是 -SIGSEGV(序号 11)
-3、想要防止进程奔溃,需要自定义信号处理函数去拦截 SIGSEGV 信号。参考 -JVM 中线程崩溃但 JVM 进程不会崩溃
-网络系统
-I/O 多路复用
-单个进程或线程同时监视多个文件描述符,如网络连接或文件句柄。当这些描述符中的任何一个就绪时,比如有数据可读或可写,多路复用机制就能够通知应用程序进行相应的读写操作。常见的IO多路复用技术包括 -select、poll 和 epoll 等。
-select
-将已连接的 Socket 都放到一个文件描述符集合,然后调用 select -函数将文件描述符集合拷贝到内核里,让内核来检查是否有网络事件产生,检查的方式很粗暴,就是通过遍历文件描述符集合的方式,当检查到有事件产生后,将此 -Socket 标记为可读或可写, -接着再把整个文件描述符集合拷贝回用户态里,然后用户态还需要再通过遍历的方法找到可读或可写的 -Socket,然后再对其处理。2 -次「遍历」文件描述符集合,2 -次「拷贝」文件描述符集合。
-poll
-它使用一个 pollfd -结构来表示被监视的文件描述符及其事件,与select相比,poll没有文件描述符数量的限制,因为它基于链表来存储。都是使用「线性结构」存储进程关注的 -Socket 集合,因此都需要遍历文件描述符集合来找到可读或可写的 -Socket,时间复杂度为 -O(n),而且也需要在用户态与内核态之间拷贝文件描述符集合
-epoll
-+
- 从流畅度、辨识度、舒适度、建议有效性、总体回应五个方面与BlenderBot-joint、MISC进行对比,MISC完胜 + +
消融实验
-
-
- epoll -只在初始时完成一次文件描述符的注册,避免了每次调用时的拷贝开销; -
- 当有一个或多个文件描述符就绪时,会调用回调函数将 Socket -集合一次性传递到就绪事件列表中,并通知用户空间,这使得 epoll -在处理大量文件描述符时仍然能保持高效; -
- 当用户调用 epoll_wait() -返回有事件发生的文件描述符的个数,明确指出了哪些文件描述符是就绪的,无需像 -select 和 poll 遍历所有 socket 集合; -
触发时机
+- HEAL可以有效提升策略预测准确度 +
- 舍弃COMET,可以提高ppl准确度,因为常识性知识不是自然语句;但会降低内容保留度,因为简洁的常识性知识更为精确 +
- 认知识别是最有效的 +
- 对比Oracle,还有很大的提升空间 + +
混和主动性分析
-
-
- 边缘触发【epoll】:只有当文件描述符的状态从不就绪变为就绪时,epoll -才会发出通知;一旦通知过后,除非状态再次发生变化,否则不会再次通知; -
- 水平触发【select/poll】:只要文件描述符处于就绪状态,epoll就会持续发出通知,直到数据处理完毕; -
- 情感支持指标分析
+
-
+
- KEMI有效的平衡了主动性和非主动性回复 +
- KEMI回复的信息更加丰富 +
- KEMI容易生成重复性回复 +
- KEMI有效地帮助用户解决情绪问题 +
+ - 会话进度
+
-
+
- 相比BlenderBot和MISC,KEMI在对话过程中,主动性和非主动性的分布更加平衡 +
- KEMI在对话中后期更能主动相应并缓解用户负面情绪 +
+
+ 案例分析 ## Conclusions
+首次提出ESC中混和主动性的特点,并阐述其重要性
+KEMI框架
+-
+
- 通过查询扩展和子图检索,从大规模心理健康图谱中检索实际病例知识 +
- 通过检索到的知识,进行策略预测和响应生成的多任务学习 +
+结合实际案例和分析指标,结果证明KEMI优于现有方法,并在混合主动交互方面具有优势 +## Limitations
+评价指标有待改进
+没有考虑不同知识检索方法的不同
+从复杂的KG图中检索知识的方法有待提高
+某些应用的知识图难以获取
+知识库的建立需要具有专业知识的人员 ## Appendix
+混和主动性
-
-
- 通过特定领域微调,模型可以学会如何做“开卷考试“; -
- 当领域内数据发生一些变化时,模型依然能找到答案,即使没有正确答案也不会出现幻觉; -
- 可以认为,模型需要专业的微调来训练其在特定领域的 -RAG(开卷考试)能力; +
- 对话主动性分析
+
-
+
- 主动性分析模型:在ESConv数据集增加混合主动的类型属性,把历史对话和当前话语作为二元输入,判断主动性。微调RoBERTTalarge,分别训练两个模型,判断用户和系统的主动性 +
- 情绪强度预测模型:根据用户话语预测负面情绪强度 +
- 用户模拟并注释四种评价指标 :【待看】 +
+ - 对话流分析
+
-
+
- ESC在对话中充当主动角色;ED在对话中充当被动角色 +
+ - 对话过程
+
-
+
- 研究内容:主动性和情绪强度变化的关系 +
- 结论
+
-
+
- 交互时间很重要 +
- 情绪缓解后才更有利于解决问题 +
+
+ - ES指标 +
+COMET
+-
+
- 常识性关系 +
+HEAL
+-
+
- 情绪压力和安慰回应之间的知识图谱 +
- 表现了对话双方的情绪动态,确定缓解情绪的方法 # 解决了什么问题 +
+常识性知识是相当抽象的,没有详细的信息,因此它对ESC系统产生有意义和信息丰富的响应的帮助不大。在这项工作中,我们采用生成式常识模型进行查询扩展,从外部知识图中检索实际案例知识。 +# 怎么解决的 / 该方法的优势
+常识知识生成器 COMET:
+常识性知识获取 HEAL: # 有什么创新点
+提出ESC知识增强混合主动框架
+-
+
- 人类和系统都可以主动引导交互方向 +
- 通过子图检索从心理健康知识图谱中检索外部知识 +
+新的分析方法 > 保留评估 和 混合主动性分析 +方面均有效优于现有方法
+-
+
- 按照说话者角色和主动类型将话语注释为不同类型
+
-
+
- Expression:用户主动 +
- Action:系统主动 +
- Feedback:用户非主动 +
- Reflection:系统非主动 +
+ - 提出四个情感支持指标来衡量ESC中主动性和非主动性交互的特征
+
-
+
- Proactivity:系统主动的对话占系统对话的比例 +
- Information:系统首次提出的频繁词占比 +
- Repetition:系统重复用户提出的术语的频次占比 +
- Relaxation:情绪强度的改善 # 实验结果好在哪里,怎么证明的 +
+
+- 按照说话者角色和主动类型将话语注释为不同类型
+
- 不需要凸显自己的能力、表达自己的个性,更多的是团队合作 -
- 遇到挫折要坚持,遇到问题会咨询 -
- 热爱工作,吃苦耐劳,积极向上 -
- 下列代码的返回值 -
- SQL 语句 -
- 初始资金 M,N 天价格信息,K 次交易后,能赚多少钱?(动态规划) -
- 给你 n 个数,这 n 个数要被拆成 k -份,对每份中的数字求异或,求各份异或总和的最大值(和恒生第二题的思路基本一样) -
开放域聊天机器人需要良好的谈话技巧:提出有吸引力的要点,倾听别人的意见,适当展示知识、同理性和个性,保持前后一致
+本文证实:基于适当的训练数据和生成策略,大模型可以学习上述技巧 ## +Introduction
+研究的主要内容
+-
+
- 混合技巧:模型专注于个性和吸引力、知识、同理心。采用 Blended Skill +Talk +实现,具体是通过提供训练数据和初始化上下文来实现。这种方法可以减少从大语料库中学习到不良特征。 +
- 生成策略:解码算法非常重要,对话长度强相关于对话质量,本文实验表明采样优于束搜索 +
+本文的优势和存在的问题 ## Model architectures
+检索
+-
+
- 将训练集作为候选响应集,每个可能的候选响应都参与Encoder,并做聚类【poly-encoder】 +
+生成
+-
+
- 使用标准的Seq2Seq Transformer架构生成响应 +
+检索和提炼
+-
+
- 帮助模型访问没有嵌入其模型参数的外部知识 +
- 对话检索:通过检索模型生成响应,并将其附加到Decoder的输入序列中,并用分隔符分开。使用修改后的输入序列生成正常的响应 +
- 知识检索:检索Wiki生成初始候选集,使用上文提到的检索模型,排序候选词并选择条件生成的句子。此外,训练一个分类器,通过上下文判断何时需要检索知识 +## Training Objectives +
+检索排序
+-
+
- 模型训练使用本文回答作为正例,其他对话回答作为负例 +
+响应生成模型的似然训练
+-
+
- 建模整个序列的概率分布 +
+α-混合检索和提炼
+-
+
- 生成模型常常不考虑对话检索语句,为确保其被使用,将检索相应中的α%替换成真实响应,α为超参数 +
- 知识检索的数据集里,知识条件和响应之间有明确的对应关系 +
- 因此训练阶段只使用知识检索的数据,充实模型参数中学到的知识 +
+响应生成模型的非似然损失
+-
+
- 使用高于真实数据数量的n元语法中的token作为候选负样本,修正已知的偏差 +## Decoding 选择解码方法对给定的历史对话的响应 +
+确定性解码方法
+-
+
- 束搜索 +
- 贪心搜索 +
+采样
+-
+
- 多项采样:根据预测结果概率分布,定义候选Token被选中的概率。防止采样到低概率Token,可以将采样限制在词汇表的子集内,并根据子集概率重采样 +
- 平滑分布采样:Temparature+SoftMax+multinomial +
- top-k +sampling:Temparature+Top-k+SoftMax+multinomial,将top-k外的token概率置为0 +
- sample-and-rank:多次采样,取最高概率的响应 +
+响应长度
+-
+
- 约束最小生成长度:在实现最小序列长度之前,强制不生成结束标记 +
- 预测长度:根据上下文预测相应长度,这是一个四分类问题 +
+子序列分块
+-
+
- n-grams:考虑响应和输入上下文中对于n-grams的重复性 ## Training +Details +
+预训练排序模型
+预训练生成模型
+微调
+-
+
- Fairseq-style混合精度训练 +
+
+- 成对比较和人性方面优于Meena # 解决方法 / 创新点 +
- 如果对话中深入询问某一方面,由于缺乏知识模型没法给出详细的回答 +
- 模型倾向于简单的回答 +
- 模型倾向于产生重复易混淆的句子 +
- 利用LLM进行数据增强,使用公开的对话帖子触发各种主题的对话 -
- Abstract
-
-
目前工作的缺陷
+- 本文关注于情感支持对话,提供了一个带策略的情绪支持数据集 +
+ - Introduction
-
-
- 成本高、耗时长 -
- 预算限制,所收集的对话规模小,主题少 +
- 情感支持应用广泛 +
- 情绪支持数据集应该包括exploration、understand、suggestion三个过程,还包括有用户的情绪强度变化 +
- 目前的研究模型中没有具体有效的情绪支持方法;采集数据集时需要训练有素的支持者 +
- ESC框架:三个阶段,多种策略;众包做数据集;在情绪支持方面有提升
- 本文主要贡献
+- Related Work
-
-
- 关键发现 -
- 使用 GPT-J 和公开对话帖子触发各种主题的对话 -
- 构建机器增强数据集AUGES,具有更广泛和多样化的主题覆盖范围,可以提供更有效的情感支持 -## Related Work +
- 移情、同感对话 +
- 情绪支持的数据集 +
- 情绪支持对话
+
-
+
- 任务定义 +
- ESC框架
+
-
+
- 三个阶段:探索、理解、建议 +
- 八种策略
- 预训练模型
-预训练模型的数据增强 ## Key Findings
-语言模型优于对话模型
+
+
+ - Data Collection
-
-
- 语言模型存储了从大规模训练语料库中学习到的更丰富的知识,有助于更好地泛化到各种对话主题 -
- 与会话模型 BlenderBot -相比,gpt生成的对话具有更好的对话连贯性和一致性 +
- 获取数据集的方法
- 语言模型比交互式仿真更适合开放式对话数据增强
-提示GPT不如微调GPT模型
+- Data Characteristics
-
-
- 提示型GPT-3生成可控性差 -
- 只有微调才能掌握任务场景和所需特征 +
- 数据展示
- 少样本(Few-shot)微调导致更好的泛化和更高的多样性
+- Experiments
-
-
- 保持语言模型的内在知识 -
- 增加调优样本或训练步骤会导致对域外主题的泛化能力差 -
- 在大规模自动数据增强的帮助下,训练对话模型可能只需要少量手动策划的对话样本 +
- 基准模型:BlenderBot、DialoGPT +
- 模型变种:不带策略:Vanilla;带策略:Random、Joint、Oracle +
- 评估指标:PPL、B-2、R-L、Extrema +
- 实验结果:
+
-
+
- 带策略的Oracle优于不带策略的Vanilla +
- 带策略的Oracle稍微弱于不带策略的Vanilla,因为一旦策略预测错误,respond会完全不同 +
- BlenderBot 变体始终比 DialoGPT 变体表现更好
- 信息性查询(第一个对话帖子)是触发主题对话的必要条件
+- 人类互动评价结果:
-
-
- 泛型和无信息的查询往往导致离题和肤浅的对话 ## Methodology +
- 微调后ES能力提升 +
- 带策略微调后能更加适合用户需求 +
- 正确的策略更重要
- 主干模型:GPT-3,微调后的GPT-J
-提示模板:对话场景+情感支持
-将第一个对话框作为触发查询,模型生成后续的对话
-不采用Prompt提示,使用ESConv微调GPT-J
-触发Query
+
+ - Conclusion
-
-
- 数据来源:EmpatheticDialogues(移情对话数据集)Reddit(心理健康相关的帖子) -
- 保留带有负面情绪的Query +
- 三个阶段、多种策略、ESConv +
- 道德评估 # 解决了什么问题
- 过滤结果,删除非法对话 ## AUGESC -相比ESConv对话轮次更少,内容更长。语料库规模的扩大导致唯一二元分词的数量
-ESConv中的对话话题与数据收集时期(如covid, pandemic, -christmas)密切相关
-AUGESC-ED -涵盖了更多关于日常生活的主题(例如,汽车、狗、房子、邻居)
-AUGESC-Reddit 涵盖了关于心理健康的主题(例如,抑郁、焦虑、治疗师) -## Quality Evaluation 在信息一致性、话题一致性和对话基础等方面存在问题 -## Interactive Evaluation > -AUGESC是对ESConv的一种补充,用AUGESC+ESConv训练出来的模型表现优于只使用ESConv的模型
-目前的对话系统没有针对情感支持的任务和语料库,因此ESC方向还没有被探索到,对话场景中缺乏情感支持。
+情感支持(ES)旨在减少个人的情绪困扰,帮助他们理解和应对所面临的挑战。目前的模型大都只能表示共情而不能解决问题。
+通过社交而不是专业咨询的方式提供情感支持。 # +怎么解决的/该方法的优势
+基于Hill的帮助技能理论,提出了ESC框架
+-
+
- 情感支持过程
+
-
+
- 理解遇到的困难,exploration +
- 表达理解和同情,insight/comforting +
- 提出解决问题的方法,action +
+
+- 情感支持过程
+
构建ESConv数据集,有丰富的注释(支持策略)
+-
+
- 每个聊天会都会标记:
+
-
+
- 问题类别 +
- 用户情绪类别 +
- 用户情绪强度 +
- 遇到困难的简介 +
+
+- 每个聊天会都会标记:
+
ESC系统
+-
+
- 选择支持策略,生成策略约束Respond +
- 情绪状态建模,跟踪用户情绪变化【待分析】 +
- 提出了评估ES实验效果的新方法 # 有什么创新点 +
+- 表达情感
+
-
+
- ECM:情感对话,可以生成情感反应。有情商而不只是智商 +
- ES:有情绪支持的能力,可以减少用户情绪困扰 +
+ - 共情能力
+
-
+
- 反应出同情心,不能做情绪支持 +
+ - 数据集
+
-
+
- 数据集中的对话短,不适合ES任务 +
+ - ESC系统
+
-
+
- 大多研究都人为预先规定好的规则和回复词典 # 可以提升的地方 +
+ - 讲一讲和算法相关的经历 -
- 专利:基于异构图网络的情绪支持对话 -
- 项目:LLM应用开发 -
- 这个项目都在使用别人开发好的技术,那么你在其中有什么贡献? -
- 目前很多开源项目只停留在科研方面,如何落地到具体项目中,就比如 LLM -出现错误宕机的时候,重启容器化运行的 LLM -实例并采用一致性轮询方法,访问其他正常运行的容器 -
- 做过最大的项目 -
- 实习的时候做的数据中台项目 -
- 对未来的计划 -
- 作为一个刚进入工作的学生,要不断学习拓宽自己的技术面 -
- 让我调了下摄像头,好展示我的颜,然后自我介绍 -
- 手撕算法(由于太紧张写代码一直在絮絮叨叨) -
- 算法思路讲一遍,中间做错了删掉的代码也要讲为什么做错了,然后把代码截了个图 -
- 说一下自己的技术栈 -
- 挑一个自己熟悉的讲一讲,选了 MySQL 索引 -
- 如果让你建一张表,你会如何设计索引 -
- IOC 容器的理解 -
- 那为什么不直接用单例模式而用 IOC 容器的 Bean +
- Docker +Compose:用于定义和运行多容器 Docker +应用程序的工具,使多个容器可以在隔离环境中一起运行; +
- Dockerfile:用来构建镜像的文本文件,包含了一条条构建镜像所需的指令和说明; +
- Docker +Machine:是一个简化 Docker +安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker;可以集中管理所有的 +docker 主机,比如快速的给 100 台服务器安装上 docker;
- 用 Python 能否实现 AOP +
- [-d] 后台运行容器 +
- [-p] 指定端口映射 +
- [-v] 映射主机文件卷 +
- [--name <NAME>] 命名容器 +
- [-e] 设置环境变量
- 设计模式讲一下 +
- [-a] 显示所有的容器,包括未运行的
- Rest 和 Rpc 有什么区别 +
- [-f] 强制删除正在运行的容器 +
- [-v] 删除容器挂载的卷
- OS 为什么需要虚拟地址 +
- [-f] 指定要使用的 Dockerfile 路径 +
- [--rm] 设置镜像成功后删除中间容器
- 会什么语言 +
- [-o <xxx.tar>]
- 反问,进去需要什么技术栈 +
- [-i <xxx.tar>] 指定导入的文件
自我介绍
-深入讲一下实习经历(完全没想到会问这个)
-- 了解项目架构,微服务和多模块开发,数据流过程 -
- 尝试开发字典结构 -
- AOP 日志:运行时间、调用接口、速度、ip -
- 调用微服务获取运维大屏数据,并展示:线程池、CompletableFuture -线程先后调用关系 -
- 日志 AOP,能不能查找、过滤逻辑,为什么不用 -ELK。如果有监控平台的话,为什么不存到监控平台里(看得出来面试官很奇怪怎么只有 -AOP 记录日志,没有其他的相关功能) -
- AOP 底层原理 -
- 行,继续说(我超,怎么说啊说啥啊) -
- 有 A 类中的 BC 方法。B 方法使用注解代理,再用 C 方法通过 this.B() -调用,会出现什么逻辑 -
- 那如何让 this.B() 的代理生效呢 -
- 修改一个数据,存储层、缓存层一起用的话怎么办 -
- 单例模式实际应用场景,Spring 底层的设计有哪些用到了单例模式 -
- 底层创建 Bean 是线程安全的吗?一定会用到
synchronized
-吗?
- - 启动时直接把所有 Bean 都创建好,可不可以保证线程安全? -
- MySQL 的索引机制 -
- B+ 和 B 树的区别 -
- MySQL 乐观锁和悲观锁 -
- update 用的是行锁还是表锁 -
- 二级索引、联合索引、最左前缀匹配原则 -
- Redis 怎么实现过期删除策略(不是内存淘汰策略) -
- 缓存穿透 -
- Redis 大 Key 问题的定义,解决方法 -
- 线程池的核心线程池的个数是如何设置的? -
- CPU密集型任务:N+1 -
- IO密集型任务:2N -
- 把大 key 拆分成一个一个小 key; -
- 将大 Key 拆分成多个小 Key 并用 Hash 结构存储; -
- 定时检查 Redis 是否存在大 key ,如果该大 key 是可以删除的,不要使用 -DEL 命令删除,因为该命令删除过程会阻塞主线程,而是用 unlink 命令(Redis -4.0+)删除大 key,因为该命令的删除过程是异步的,不会阻塞主线程; -
- 应用服务:Redis 是单线程的,大 Key -写入和删除会阻塞其他命令;内存分布不均,失去内存时空局部性特性;网络阻塞,IO -压力大; -
- 持久化:Always 参数下数据同步到硬盘时会阻塞主线程;经常性触发AOF -重写机制;AOF 重写机制和 RDB 快照(bgsave 命令)的过程,都会分别通过 -fork() -函数创建一个子进程来处理任务,会导致阻塞父进程(主线程);集群模式下内存分布不均 -
- 集中化版本控制(CVCS)缺点
-
-
- 自我介绍 -
面试官看了简历,说“不愧是软件工程内容比别人多多了”,面试官真的是很认真的把简历从头看到尾(泪目)
--
-
- Rpc 项目具体是什么 +
- 中央服务器的单点故障就无法协同工作 +
- 本地只有快照,项目整体和其变更历史只保存在服务器上 +
+ - 分布式版本控制(DVCS)优点
+
-
+
- 代码仓库完整地镜像下来,包括完整的历史记录 +
- 用户在本地保存了所有改动,每一次的克隆都是对仓库的完整备份 +
- 可以指定和若干不同的远端代码仓库进行交互 +
- - 如何分析 dump 文件 +
- 并行开发 +
- 完全分布式 +
- 速度快 +
- 数据量大
- synchronized Reentrantlock 的具体使用场景有什么不同 +
- 大多版本控制工具都是基于差异的,存储文件随时间变化的差异,而Git储存项目快照或索引 +
- Git 安全性优,只做增不做删;完整性好,使用SHA-1 哈希算法 +
- 文件的四种状态:已提交(committed)、已修改(modified)、已暂存(staged)、未跟踪(untracked) +
- 项目的三个阶段:工作目录、暂存区域以及 Git 仓库 +
- 工作流程:修改文件、暂存文件、将暂存区文件快照永久存在Git目录
- MySQL 调优 +
- /etc/gitconfig 系统通用配置 git config --system +
- ~/.gitconfig 当前用户配置 git config --global +
- .git/config 当前项目配置 git config --local
- 分布式微服务架构复杂 === 请教前辈、打断点弄明白数据流; -
- 多线程并发,编排任务执行流程 === 美团技术博客 CompletableFuture -原理和实践; -
- 沟通协作,和同事交流,理解别人的想法的同时清楚地表达自己的想法;让领导清楚自己在做什么,工作量和重难点在哪 -=== 多沟通多交流,先理清自己的想法再和同事、领导沟通; -
- LLM 部署,技术选型 FastChat、FastApi、VLLM 加速 === -实践尝试,选择最合适的方法; -
- 思考如何实现需求 === -参考别人发表的经验和思路,比如看论文、技术博客、线上宣讲会、开源项目等,在针对需求改进和优化; -
- Prompt 构建,数据切分、数据集构建:分词、分段、Embedding 计算 -
- Netty 数据传输 -
- RPC架构==Bean 生命周期,分布式注册中心:zk(CP、zab算法) -
- 数据库缓存一致性设计 -
- 新需求的开发 -
- 以客户为中心,以奋斗者为本,长期艰苦奋斗,坚持自我批判 -
- 我认为艰苦奋斗是一种积极向上、不断进取的品质,是为了实现自身价值,努力过上充实且有意义的人生,而不仅仅是为了眼前的利益; -
- 结合我自己的经历来看,虽然中考失利了,但我仍保持努力拼搏的信念,在后续的高考、考研中不断超越自己,才有机会接触到了更多有挑战有意义的事情; +
- [-b master]克隆指定分支
担任角色;负责的工作;项目背景;前期调研;创新点
-项目有哪些难点
-开发过程中遇到问题;如何解决
-科研过程中遇到问题;如何解决
+git status [OPTIONS] 【查看文件状态 】
-
-
- 一开始对科研内容一窍不通,通过不断的学习试错总结慢慢积累了经验 -
+- [-s] 简要文件状态信息
- 专利修改,秋招找工作,写大论文+毕业答辩 -
- 学习大数据技术栈(Hadoop、Map-Reduce、Hbase),出国旅行 +
- [--staged] 显示暂存区和上一次提交的差异
- 进入优秀的团队中工作学习; -
- 前四年深耕技术,不断学习,沉淀技术栈,拓宽视野; -
- 抓住机遇,第六、七年应聘管理层,接业务,带团队,一个人的力量终究是有限的,只有激发团队的力量才能办成大事; +
- [ -L 200,300 <file>] 追踪某些行代码修改的历史 commit
- 学习大数据相关的技术栈; -
- 抓住现有机会,积极投身工作中,不断提升技术能力,扩大人脉。耐心地等待机遇,当机遇来临时果断抓住它; +
- [-f] 强制移除存在未提交修改的文件 +
- [ --cached] 文件保留在工作区中,从Git仓库和暂存区中删除
- 大一只有中游水平,后面几年排名逐年上升,大三拿到了学业奖学金并考研成功。在读研期间也能有中上游的绩点,拿到了学业奖学金; +
- [--soft] 回退到某个版本 +
- [--mixed] +默认,用于重置暂存区的文件与上一次的提交保持一致(取消暂存),工作区文件内容保持不变 +
- [--hard] +撤销工作区中所有未提交的修改内容,将暂存区与工作区都回到上一次版本,并删除之前的所有信息提交
- 无论是在芯片、操作系统还是在手机、汽车等领域,华为都是中国的一线品牌,华为当下在做的事情相当于五十年前的核武器研究; -
- 参加华为举办的竞赛感受到华为的人文关怀做得很好,比赛场地布置的很用心,比赛结束后还举办了活动,吃了大餐,临走还送和一袋纪念品,包括所有人的合照; -
- 体验大厂的氛围和管理制度,和优秀的团队一起成长,努力工作,争取毕业留在华为; +
- [.] 放弃所有工作区的修改 +
- [-f] 放弃工作区和暂存区的所有修改 +
- [<branch-name>] 从当前分支切换到指定的分支 +
- [-b <local_new_branch_name> <remote_new_branch_name>] +将远程仓库里指定的分支拉取到本地,并在本地创建一个分支与指定远程仓库分支关联起来,并切换到新建的本地分支中
- 半年,立刻到岗 +
- [-v] 列出当前仓库中已配置的远程仓库,并显示它们的 URL +
- [add <remote_name> <remote_url>] +添加远程仓库,指定一个远程仓库的名称和 URL,将其添加到当前仓库中 +
- [remane <old_name> <new_name>] +将已配置的远程仓库重命名 +
- [show <remote_name>] 显示指定远程仓库的详细信息,包括 URL +和跟踪分支 +
- [remove <remote_name>] 从当前仓库中删除指定的远程仓库 +
- [
] 修改指定远程仓库的 URL - 对大语言模型很感兴趣;LLM -的训练和微调对硬件和数据集的要求高,但实验室只有 A6000,更加适合 LLM -的应用开发,看了很多论文、开源项目和技术博客,最终让基于大语言模型实现一个具体需求的过程非常有成就感; +
- [--all] 获取远程的所有分支
- 对语言模型没有任何了解,实验室也是第一次接语言模型的项目,没有任何沉淀,一开始上手很艰难,只能不断重复去看网课和教程; +
[<remote_name> +<local_branch_name>:<remote_branch_name>]
+[<remote_name> --delete <branch_name>] +删除远程分支
+[-u <remote_name> --all] +本地的仓库和远程仓库进行关联
+[--set-upstream <remote_repository> +<local_branch_name>] 将本地分支与远程分支关联
+[--force] 强制提交,会覆盖所有 behind 的提交
- 论文、技术博客、开源项目、社群宣讲会 +
- [-l <通配符>] 查询某些对应标签 +
- [<version>] 轻量标签(提交校验和存储到一个文件中) +
- [-a <version> -m <comment>] +创建附注标签(数据库中的一个完整对象, 可以被校验) +
- [-d] 删除标签
- 技术博客,因为它更加贴近实际落地的工作,大佬们留下的经验往往给我灵感 +
- [-c] 创建一个新分支并切换到该分支
- 人生中最大的挫折应该是中考,我当初冲重高保底优高,最后发挥失常只考上了职高; -
- 高中 -保持学习的劲头,稳扎稳打,高考超重点线;这段经历让我任何时候都不会轻言放弃,即使失败了也没事,总结反思之后再出发,家人和朋友一直都在,成功与否只是我自己的选择; +
- [<branch_name>] 创建本地分支 +
- [-b <branch_name>] 创建本地分支并切换 +
- [-v] 每个分支的最后一次提交 +
- [-vv] 跟踪信息 +
- [-r] 查看远程分支 +
- [-D <branch_name>] 删除分支 +
- [--set-upstream-to <remotename>/<remote_branch> +<local_branch>] +跟踪远程分支。在本地新建一个分支后,需要做远程分支关联,目的是在执行git +pull, git push操作时就不需要指定对应的远程分支 +
- [--merged --no-merged] 合并/未合并到当前分支的其他分支 +
- [-m <old_branch_name> <new_branch_name>] 改名
- 跑步、爬山、骑行 +
- [list] 列出所有贮藏 +
- [apply] 恢复贮藏
- Git 中 HEAD是一个指针,指向当前工作位置 +
- git mergetool 图形化冲突解决工具 +
- 有 Git 特性演化出的开发工作流:长期分支、主题分支 +
- 3.1 overall +
- 早起,立即开始工作。早起会立即给自己一个潜意识的信号,让自己在那天努力工作。 +
- 制定一个行动计划。用 10 +分钟来筹划接下来的几个小时要做的事情,让事情可以推动自己前进。 +
- 提前完成一连串的工作。清晨就处理完当天最紧要的工作,白天的时间就会显得从容,这也会产生积极的启动,这将持续一整天。 +
- 提出xxx,有效解决xxx,比别人好在哪xxx。包含了三个模块,介绍xxx,数据流xxx,提高了哪些xxx;由于这三个特征不能有效表示xxx,所以用异构图网络xxx,可得到两个状态,xxx。因此,提出的模型,有一样也有有不一样【总分总】 -
- 3.2 archieve -
- 3.3 -
- 3.4 +
- 避免参与式的休息。短视频,游戏,微信等会占据头脑的东西都会打断做事的势头。 +
- 专注于放松。走一小段路、喝一杯水或伸展身体都是不错的选择,可以很容易地从休息中抽身出来回去工作。 -
- 指标,解释,为什么好,好在哪 +
- 使任务处于活动状态。将被动学习任务转换为主动学习任务,如写提纲、记录重点。 +
- 穿插活动任务。将被动学习与主动任务穿插在一起,以定期提高注意力,如表达自己见解、用自己的话复述一遍。
保证休息,应对大量工作任务的办法是保证自己有休息时间。如果你白天不好好工作,却逼迫自己整夜学习的话,你很容易就会筋疲力尽的。无论压力再大任务再多,都要保证休息时间,一颗清醒的大脑决定了工作的质量。
+使用时间分块法或每周/每日目标法,将工作和生活清晰地分离开,好好工作好好玩。
+- 在 Encoder 和 Decoder 之间加了一层 GCNConv 和 RGCNConv +
- 设置 menu 菜单栏 +
- 打开 code 代码复制
目前研究的缺陷
--
-
- 关注序列上下文信息,忽略了全局原因和局部心理意图与其的层次关系 -
-本文
--
-
- 提出了一个全局到局部的层次图网络来捕获多源信息(全局原因、局部意图和对话历史)并建模它们之间的层次关系,该网络由一个多源编码器、一个层次图推理器和一个全局引导解码器组成 -
- 设计了一个新的训练目标来监测全局的语义信息 ## Introduction -
-探索求助者情绪问题的原因:全局地控制情感支持对话的整个流程
-了解求助者的心理意图:帮助系统局部了解求助者当前时的心理状态
-本文目标
--
-
- 捕获全局原因和局部心理意图 -
- 建模全局与局部之间的关系 -
-解决方法【全局到局部层次图网络GLHG】
--
-
- 多源编码器:COMET提取局部心理意图 -
- 层次图推理机:全局原因(对话级)、局部心理意图(句子级)和对话历史之间的层次关系进行建模 -
- 解码器中设计了一个新的训练目标来监控全局原因的语义信息 ## Related -Work -
-图建模对话
--
-
- GCN 利用自我和对话者间依赖性来模拟会话上下文 -
- EGAE 使用图网络捕获面向任务对话中的对话模式 -
-常识性知识
+Debug
++hexo clean --debug
hexo s --debugGit 上传插件
++npm install hexo-deployer-git --save
latex 公式
+安装
+hexo-renderer-markdown-it-plus
后,Katex 与 mathJax +会重复,需要在 next 中配置+mathjax:
enable: false
tags: none
katex:
enable: true
copy_tex: false本地图片
+ ++npm install hexo-asset-img --save // 代替 hexo-asset-image
Markdown 文字高亮
+ ++npm un hexo-renderer-marked --save
npm install hexo-renderer-markdown-it-plus --save_config.yml
++markdown:
preset: "default"
plugins:
- markdown-it-mark添加Sitemap
+为自己的网站配置sitemap,可以有效地提升SEO
++npm install hexo-generator-sitemap --save
npm install hexo-generator-baidu-sitemap --save并在站点配置文件
+_config.yml
的末尾添加:+sitemap:
path: sitemap.xml
baidusitemap:
path: baidusitemap.xml改 blockquote 颜色
++blockquote {
background: #d0a7020d;
border-left: 4px solid #d0a702;
color: var(--blockquote-color);
margin: 0;
padding: 0 15px;
cite::before {
content: '-';
padding: 0 5px;
}
}备份本地博客
+ ++MKLINK [[/D] | [/H] | [/J]] Link Target
/D 创建目录符号链接。默认为文件符号链接。
/H 创建硬链接而非符号链接。
/J 创建目录联接。
Link 指定新的符号链接名称。
Target 指定新链接引用的路径
(相对或绝对)。管理员 PowerShell
+cmd /c mklink /D 目标地址 源地址
+将博客硬链接到 OneDrive 文件夹下备份更新主题 Next
++
+由于 NexT 以前使用的 swig 模版引擎停止维护,去年迁移到了 +Nunjucks,但是 +目录下的模版文件后缀名没有更改。原因是修改后缀名影响太广,会使用户在执行 +进行更新时产生大量的冲突。这次更换仓库为了解决这些历史遗留问题,没有保留之前的 +commit 历史。
+2024.4.23 按照官网配置
+DeBug
+ +]]>- 与本人有关的心理状态:xReact、xIntent ## Approach -
问题定义
-多源编码器
+- 偏向左侧时,训练数据的扰动不足以使学习器产生显著变化,此时偏差主导泛化误差,称为欠拟合现象
-
-
- BlenderBot Encoder + Max-pooling -
- 上下文 + 全局原因 + 局部原因 +
- 增加模型的迭代次数;更换描述能力更强的模型;生成更多特征供训练使用;降低正则化水平
- 分层图推理机
+- 偏向右侧时,模型的拟合能力非常强,数据轻微变化都能导致模型发生变化,如果过分学习训练数据的特点,则会发生过拟合现象
-
-
- GAT -图注意力网络:其他邻域信息的特征传播到当前节点,具有确定节点之间重要性和相关性的优点 -
-注意力函数(2017出版)
--
-注意力机制
--注意力机制
-- 扩增训练集;减少训练使用的特征的数量;降低模型复杂度;提高正则化水平
- Global-guide 解码器
+ +为了解决“偏差和方差在一定程度上是有冲突的”的问题,可以采用K折交叉验证或正则化,它们分别从数据划分和模型复杂度两个角度入手,提升模型的泛化能力和稳健性:
-
-
- 响应生成
,v表示图神经网络得到的全局变量
- - 监督全局语义信息:预测问题类型
-- 响应生成
联合训练
+- K折交叉验证通过多次划分和验证,减少因数据划分不当而导致的性能估计偏差 +
- 正则化在损失函数中加入一个与模型复杂度相关的惩罚项,以限制模型的复杂度并防止过拟合
+参考文章
-
-
- 对数似然损失+交叉熵损失 -
-
-
Experiments
+- L1正则化是指权值向量w中各个元素的绝对值之和,可以使得参数稀疏化,即得到的参数是一个稀疏矩阵,进而可以用于特征选择。二维平面图像:
- L2正则化是指权值向量w中各个元素的平方和然后再求平方根,让权值尽可能小,如果参数足够小,数据偏移得多一点也不会对结果造成什么影响,专业一点的说法是抗扰动能力强。二维平面图像:
- 指标:plexity (PPL), BLEU-n (B-n), ROUGE-L (R-L), -Distinct-1(D-1), and Distinct-2 (D-2)
-由于有了意图特征,提出建议更具体有效 ## Conclusion
-全局到局部的层次图网络(Global-to-Local Hierarchical Graph -network, GLHG)来捕获多源信息并从全局到局部的角度建模层次关系
-新的训练目标“预测Seeker遇到问题的类型” # 关注的问题 / -本文的优势
-- 多源编码器利用情境信息并将心理意图与COMET结合,捕获全局原因和局部意图 -
- 分层图推理机在全局原因、局部心理意图和对话历史之间进行交互,建模不同层次的关系(hierarchical -graph reasoner) # 实验结论 +
- 归一化奖励分数、将奖励分数做白化处理
- 关注的问题
-
-
-
- 动态建模对用户状态,包含个体的意图和情感 -
- 综合各类因素选择最合适的支持策略 -
- - 提出的方法【基于异构图注意力网络的深度Q-learning情感支持对话生成】
-
-
-
- 为了捕获用户意图、情感和历史对话之间的交互关系,基于意图词典和情感分类器,构建了异构图注意力网络 -
- 采用基于DQN的最优响应策略以指导响应生成,优于传统的基于规则或启发式方法 -## Introduction -
- - 目前研究
-
-
-
- ESC任务要求能够确定求助者的心理意图和情绪状态,以便提供适当的支持。因此整合意图识别和情感识别对于提高情感支持对话的质量至关重要,且目前的方法对用户状态建模不充分。 -
- - 关注的问题
-
-
-
- 建模用户状态 -
- 选择最优策略,以产生有效的保障响应 -
- - 提出的方法
-
-
-
- 设计了基于注意力的异构图网络,与用户的意图、情感和历史对话交互,可以有效地捕获和建模图中不同类型的节点和边 -
- 构建意图词典和情感分类器来捕捉求助者在语境中的细微情感表达 -
- DQN算法对用户未来反馈的期望值进行估计,帮助系统选择获得最优长期值的策略。其允许系统从用户的反馈中学习,调整其策略,以提供最有效的支持响应。 -
- - 主要贡献
-
-
-
- 提出了一种新的方法DQ-HGAN,将意图和情感识别与策略生成相结合,以提高情感支持对话系统的质量和个性化 -
- 构建意图词典和情感分类器,捕捉求助者在语境中的细微情感表达并跟踪其状态 -
- 设计了一种基于注意力机制的异构图网络,与用户的意图、情感和历史对话进行交互,并选择最优的支持策略以生成有效的支持响应 -
- ESC生成中使用ESC生成中使用强化学习,具体来说,使用DQN算法(Deep -Q-Network)估计用户未来反馈的期望值,动态调整策略以提供最有效的支持响应 -## Related Work -
- - 对话中的意图和情感识别【在模型中融合了“意图”这个特征】
-
-
-
- 多头注意力机制
-
-
-
- 多头注意力机制来捕捉用户的意图和情感。缺点:缺乏有效捕捉用户细微情感表达的能力 -
- 使用预训练模型,增强PLM对话相关性,识别对话意图、推断对话情感。缺点:不是专门为ESC任务定制的,性能差 -
- - 词典
-
-
-
- 词典包含特定意图或情感相关的词汇和短语,利用基于规则的算法将context与意图词典进行匹配,并分配相应的意图标签。缺点:只将单个单词与标签匹配,可能会忽略整个句子的意图或情感含义 -
-
- - 多头注意力机制
-
- 图建模【捕获会话系统中用户意图、情感和对话历史之间的复杂关系】
-
-
-
- 同构图【忽略了用户意图和情感的异构性】
+
数据结构和算法 +/-NLP/Java-Algorithm/ +算法 + 链表
+快慢指针
+链表倒数第n个数
+分治法
+排序
+二分查找
+【1】目标不存在于数组中,找第一个大于它的下标
+【2】有多个目标存在于数组中,找第一个等于它的下标
+【思路】基于二分查找,优化寻找 mid 指针和收敛 left right +指针的步骤,具体问题具体分析
-
-
- GAT -图注意力网络,利用自注意力机制来捕获对话图中意图和情感节点之间的交互 -
- GCN -图卷积网络,利用图结构在节点之间传播信息,并捕获对话数据中的上下文依赖 -
- - 异构图注意力网络是专为表示图中不同类型的节点和边而设计的,它擅长对不同的节点类型进行建模,如用户话语、系统响应、情感状态和意图,从而更全面地了解用户的情感状态;还擅长捕捉不同类型的边,包括顺序依赖、自依赖和状态依赖,从而能够更准确地表示用户的情感状态。此外,它还包含了一种注意力机制来进行重要性加权,允许它在聚合过程中专注于最相关的信息,从而更全面地了解用户的状态。 -
- - 同构图【忽略了用户意图和情感的异构性】
+
- 策略选择 +
- mid=(left+right)>>2;if +(nums[left]<nums[mid]) left=mid+1; +else right=mid;【找左边】 +
- mid=(left+right+1)>>2;if +(nums[left]<=nums[mid]) left=mid; else +right=mid-1;【找右边】 +
- 确定dp数组(dp table)以及下标的含义 +
- 确定递推公式 +
- dp数组如何初始化 +
- 确定遍历顺序 +
- 举例推导dp数组 +
- 基于规则或启发式方法 -
- 强化学习方法(如:Q-learning) +
- 【124】求二叉树中最大的路径和。改左右子树的深度为节点值的和,若和为负数则返回 +0 +
- 【2245】一般树的最长路径。遍历所有邻居(过滤掉父节点),取最长、次长两条路径相加,结果为最长路径。此外,根据题意还要去除父子结点相同的情况。 +
- 采用DQN估计不同对话动作的期望值,并学习了一种最大化该值的策略。从用户反馈中学习,并生成更有吸引力和信息量的响应 -
- 响应生成 +
- 向零截断,直接保留整数位
1/2 == -1/2 == 0
+
+ - 目前流行的Encoder-Decoder模型往往专注于根据对话历史生成回复,而没有考虑用户的意图、情感以及合适的支持策略 -## Preliminaries -
- ESConv:标记对话,并将其转换为词嵌入,以将其输入到模型中 -
- COMET:使用COMET初始化模型的词嵌入,并在ESConv数据集上进行微调,以提高其构建意图词典的有效性 -
- ATOMIC:得到意图或目的(xIntent) -
- NRC VAD -词典:得到情感词典,每个单词对应的效价-觉醒-支配(Valence-Arousal-Dominance) -
- 问题定义:上下文+策略+Query
-=>响应Yt。最优策略基于当前状态和期望的长期回报(通过Q-learning预测)
-## Method
- int double:0 +
- boolean:false -
- transformer编码器(TransformerEncoder) +
- 包装类型常量池:Byte, Short, Integer [-128,127], Long, Character, +Boolean +
- 字符串常量池 +
- ht = TransformerEncoder(Ht) -
- 意图词典(COMET):通过对ATOMIC -微调,同去意图关键词,构建意图词典(意图关键词,对应的词嵌入) +
- 成员变量(定义在类里方法外的变量)一定要进行初始化的,如果不显式的进行初始化,那么虚拟机会进行默认的初始化
-
-
- \[g_{t}=TransformerEncoder\left(\sum_{w_{i}\in\mathscr{F}}\operatorname{softmax}\left(c_{i}^{T} -h_{t}\right)c_{i}\right) \] +
- 基本数据类型一般是给予默认值 +
- 引用类型初始值为 null
- - 情感分类器(NRC VAD词典) +
- 局部变量不会自动初始化,所以在声明局部变量时要注意,可以不在声明时初始化,但在使用之前一定要进行初始化,否则会报编译错误 + +
- \[e_{t}=\text{TransformerEncoder}\left(\sum_{w_{k} -\in \mathscr{Z}}\operatorname{softmax}\left(z_{k}^{T} h_{t}\right) -g_{t}\right) \text { }\] -
- 泛型必须是引用类型,不能是基本类型 +
- 泛型通过类型擦除实现 -
双层反馈策略选择器:通过反馈信息预测策略
-双层控制阅读器:通过策略约束上下文响应
-策略词典:丰富策略的语义信息 ## Introduction ## Related Work ## -Problem Formulation ## Approach
-上下文编码器
--
-
- BlenderBot预训练编码器编码上下文历史对话U,得到Ht -
-双层反馈策略选择器
--
-
- 策略选择
-
-
-
- 输入
-
-
-
- BlenderBot Encoder 编码上下文历史对话U,得到隐状态Ht -
- BlenderBot Encoder 编码策略S -
- EmoBERTa Encoder 编码上下文对话U -
- - 公式
-
-
-
- 上下文编码器(策略S同理):\[\boldsymbol{H}=\operatorname{Enc}_{cxt}\left(\boldsymbol{[CLS]},
-\boldsymbol{u}_{1}, \boldsymbol{[SEP]}, \boldsymbol{u}_{2}, ...,
-\boldsymbol{u}_{M}\right)\],M为对话数
-
-
-
- \[\boldsymbol{H}=\left(\boldsymbol{u}_{1},..., -\boldsymbol{u}_{T}\right)\],T为Token数 -
- - 情感编码器:\[\boldsymbol{E}=\operatorname{EmoBERTa}\left(\boldsymbol{[CLS]},
-\boldsymbol{u}_{1}, \boldsymbol{[SEP]}, \boldsymbol{u}_{2}, ...,
-\boldsymbol{u}_{M}\right)\],M为对话数
-
-
-
- \[\boldsymbol{E}=\left(\boldsymbol{e}_{1},..., -\boldsymbol{e}_{T}\right)\],T为Token数 -
- - 分类:\[\boldsymbol{o}=\operatorname{MLP}\left(\tanh
-\left(\boldsymbol{W}_{o}^{T}[\boldsymbol{s} ; \boldsymbol{c} ;
-\boldsymbol{r}]+\boldsymbol{b}_{\boldsymbol{o}}\right)\right)\]
-
-
-
- s、c、r 为策略S、上下文H、情感分类E。编码+平均池化操作后得到 -
-
- - 上下文编码器(策略S同理):\[\boldsymbol{H}=\operatorname{Enc}_{cxt}\left(\boldsymbol{[CLS]},
-\boldsymbol{u}_{1}, \boldsymbol{[SEP]}, \boldsymbol{u}_{2}, ...,
-\boldsymbol{u}_{M}\right)\],M为对话数
-
- - 输入
-
- 双层反馈
-
-
-
- 回合级反馈:局部变量,当前用户的感受。包含每轮对话Seeker情感Δe和Seeker评分变化Δr -
- 对话级反馈:全局变量Δc,用户的全局状态。包含Seeker在谈话后的情绪压力、Supporter对话题的回应的相关性、Supporter对Seeker感受的理解和共情 -
- 融合adapter:整合回合级和会话级反馈的两类语义信息。Δs = Δe + Δr + -uΔc【计算损失时,给予正向或负向的反馈】 -
-
-- 策略选择
-
双控读取器(模仿情感聊天机器ECM)
--
-
- context-to-strategy:利用上下文信息来选择上下文相关的策略
-
-
-
- \[\boldsymbol{g}^{c} = -\operatorname{sigmoid}\left( -\boldsymbol{W}_{c}^{T} \boldsymbol{c} + \boldsymbol{b}_{c} -\right)\] -
- - strategy-to-context:编码阶段可以关注与策略相关的上下文,从而生成策略约束的响应
-
-
-
- \[\boldsymbol{g}^{o} = -\operatorname{sigmoid}\left( -\boldsymbol{W}_{o}^{T} \boldsymbol{o} + \boldsymbol{b}_{o} -\right)\] -
- - 残差连接:在原始信息和更新信息之间进行权衡
+
Faiss 向量数据库 +/-NLP/Faiss/ +Faiss 索引类型 + + 平面索引 FLAT
+平面索引就是暴力搜索,将
+queries
于 +database
中的所有向量计算,时间复杂度是 \(O({n^2})\)。不同索引计算相似度的方法不同,
+IndexFlatIP
+是点积,IndexFlatL2
是 L2 +距离,如果需要计算余弦相似度则需要在点积前 L2 归一化 +faiss.normalize_L2(vector)
,L2 归一化公式为 \(\mathbf{X}=\left(\frac{x_1}{\left\|\mathbf{x}\right\|},\frac{x_2}{\left\|\mathbf{x}\right\|},\cdots,\frac{x_n}{\left\|\mathbf{x}\right\|}\right)\)+index = faiss.IndexFlatL2(d)
index.add(database)
D, I = index.search(queries[:5], k)\(D\) +表示具体的相似度
+D.shape = (query_len, similarity)
,取值范围是 +[0, 1]\(I\) 表示与 \(D\) 相对应的索引 +
+I.shape = (query_len, index)
,取值范围是 [0, data_num]分区索引 IVF
+对索引数据进行分区优化,将数据通过“沃罗诺伊图单元”(也被叫做泰森多边形)来进行切割(类似传统数据库分库分表)。在搜索时,仅将查询 +queries 所在单元中包含的数据库向量 database +以及一些相邻的向量与查询向量进行比较,找到 queries +向量所属的泰森多边形单元就是在质心集中找到该向量的最近邻居。
+
+index.train()
训练了一个聚类模型,如 +K-means。生成多个聚类中心,聚类的数量由索引的nlist
+参数决定。倒排索引(IVF)把“文档→单词”的形式变为“单词→文档”的形式。
+
+search
有两个参数:nlist
(单元格数量)和 +nprobe
+(为执行搜索而访问的质心集单元数量,在nlist
之外),设置 +nprobe = nlist
给出与暴力搜索相同的结果。+quantizer = faiss.IndexFlatL2(d)
index = faiss.IndexIVFFlat(quantizer, d, nlist, faiss.METRIC_L2)
index.train(database)
index.add(database)
index.nprobe = 10
D, I = index.search(queries, k)量化索引 PQ
+基于乘积量化器的有损压缩来压缩存储的向量,压缩方法和量化级别参考论文。
+建立索引时:
-
-
- \[\begin{array}{r} -o^{\prime}=(1-\beta) \cdot o+\beta \cdot g^{c} \otimes o \\ -h_{t}^{\prime}=(1-\alpha) \cdot h_{t}+\alpha \cdot g^{o} \otimes h_{t} -\end{array}\] -
-
-- context-to-strategy:利用上下文信息来选择上下文相关的策略
-
策略字典
+- 向量被分配到最近的聚类(同 IVF) +
- 每个向量被划分为 m +个子向量,分别在各自的子空间中进行量化,存储为对应的量化代码 +
- 输入策略令牌的描述, -而不是策略令牌,以便模型对策略进行更深入的理解 -
- Encoder-Decoder -之间的状态传输类似于MISC,采用cross-attention代替self-attentionMISC: -A MIxed Strategy-Aware Model Integrating COMET for Emotional Support -Conversation -
响应生成
+- 查询向量通过倒排索引(IVF) 来确定最接近的聚类中心 +
- 查询向量被划分为 m 个子向量 +
- 查询子向量与存储的量化代码进行匹配,基于每个子空间的距离查表来计算近似距离 +
- 将所有子空间的距离相加,得到查询向量与候选向量的总距离 + +
- BlenderBot Decoder:\[\boldsymbol{p}\left(y_{z} \mid -\boldsymbol{y}_{<z}, \boldsymbol{h}_{\boldsymbol{t}}^{\prime}, -\boldsymbol{V}\right)=\text { Generator }\left(\boldsymbol{W}_{y<z}, -\boldsymbol{h}_{\boldsymbol{t}}^{\prime}, -\boldsymbol{V}\right)\] -
联合训练
+- 文本表征是对文本语义的向量表征,相似内容的文本具有相似的表征向量。这使我们可以在向量空间中比较文本的相似性。 +
- 向量数据库
Vector Database
用来存储文档的文本块。对于给定的文档,我们首先将其分成较小的文本块chunks
,然后获取每个小文本块的文本表征,并将这些表征储存在向量数据库中。这个流程正是创建索引index
的过程。将文档分成小文本块的原因在于我们可能无法将整个文档传入语言模型进行处理。
+
+ - 策略预测:反馈感知负对数似然 feedback-aware negative log-likelihood +
- chunk_size 指每个块包含的字符或 Token(如单词、句子等)的数量 +
- chunk_overlap +指两个块之间共享的字符数量,用于保持上下文的连贯性,避免分割丢失上下文信息 +
- \[\mathcal{L}_{1}=\left\{\begin{array}{ccc} --\hat{o} \log -\left(\operatorname{softmax}\left(\boldsymbol{o}^{\prime}\right)\right) -& \text { if } & \Delta s>0 \\ --\hat{o} \log -\left(1-\operatorname{softmax}\left(\boldsymbol{o}^{\prime}\right)\right) -& \text { if } & \Delta s \leq 0 -\end{array}\right.\\\] -
- 响应生成:标准交叉熵损失优化 cross-entropy +
- 音视频上传
-
-
- \[\mathcal{L}_{2}=-\sum_{z=1}^{Z} \log -\boldsymbol{p}\left(y_{z} \mid \boldsymbol{y}_{<z}, -\boldsymbol{h}_{\boldsymbol{t}}^{\prime}, \boldsymbol{V}\right)\] -## Experiment -
+ - 语音转文字 FFmpeg +
- 【初始化时】声纹构建 +
- 语音转文字 Whisper +
- 特征语料库构建 -
采用EmoBERTa-base作为特征提取器,以获取Seeker的情感得分和情感表征,情感得分由softmax函数使用EmoBERTa-base的[CLS]表示获得 -## Experimental Results ## Analyses ## conclusion # 关注的问题
+- 语料 + Chroma 向量库相似度 + KNN 距离匹配 +
- 组成输入,LLM 响应结果 -
预测策略只依靠对话历史,而不考虑求助者反馈,导致预测的结果与用户无关
-建模过程只关注上下文到策略,而不关注策略到上下文和与策略相关的上下文 -# 解决方法
-双层反馈策略选择器:利用回合级和会话级反馈信息来激励或惩罚策略
-双层控制阅读器:策略到上下文流来生成策略约束响应 # 创新点 / -本文的优势
-相比于seq2seq的不确定性,聊天机器人利用知识图谱进行推理,被视为端到端模型的高效、万无一失的解决方案
-提出HEAL知识图谱
--
-
- 基于1M痛苦叙述及其相应的安慰回应而开发的知识图谱 -
- 图谱可视化:表现了对话双方的情绪动态和帮助缓解情绪的有效方法 -
- 组成部分
-
-
-
- 22k Node 节点:识别不同类型的stressors, speaker expectations, -responses, feedback types -
- 104k Edge 连接:不同类型的节点之间的关系 -
- 每个节点和41种情绪状态相关联 ## Introduction -
-
-神经网络架构模型缺乏可控性和黑箱性质,导致其并不可靠
-使用常识推理和知识图结构表示,可以生成适合的、可预测的、多策略的回应
-相关工作
--
-
- ConceptNet、ATOMIC主要是通过捕获事实知识,在开放对话中嵌入常识推理辅助对话,不适用于移情对话 -
-本文,通过子Reddit精心选择的对压力事件叙述和回应,生成了一个压力对话管理知识图谱HEAL
--
-
- 五类节点:压力源、期望、回应类型、反馈类型、情感状态 -
- 可以准确描述以痛苦为导向对话的潜在背景,使对话模型可以检索到更具体的上下文响应。提取响应会导致的反馈类型和是否能达到期望等信息,从而产生更为合适的反应 -## Related Work -
-知识图谱可以帮助NLP理解用户的输入,拓展用户输入中的事实和常识性知识
-目前工作关注于知识感知和推理对话,不会捕捉情感推理和移情反应 ## -Methodology
-数据集管理
--
-
- 采用reddit数据集,通过Pushshift -API,收集和处理8个子reddit对话主题:mentalhealthsupport、offmychest、sad、anxietyhelp、depression、suicidewatch、depressed、depressionhelp -
- 数据预处理 -
-概要
--
-
- 针对过长而超出预训练语言模型输入上限的对话,本文采用SMMRY摘要算法保留叙事本质 -
-凝聚聚类
--
-
- 自动聚类:区分对话中的压力源、期望、响应和反馈类型 -
- 凝聚聚类法:递归地合并增加最小链接距离的簇对 -
- 链接距离:对SentenceBERT生成的embedding使用余弦相似度计算 -
-定义压力源
+LLM 基础知识 +/-NLP/LLM-Basic/ ++ 大模型核心技术点在于训练资源、数据清洗和数据配比等,其难点或许不在于模型训练和模型结构搭建
+ +【变形金刚之神!Bless Me】
+ +-
-
- 每个阈值计算了各种聚类质量指标,结果显示以0.85的相似度阈值区分压力源最合适,将压力源中的4.7%分为了4363个类。 -
- 将聚类结果按照TF-IDF建模,可以明显区分压力源,表明聚类结果的可靠性。 -
-期望、回复、反馈类型
+- 相较于 RNN,Transformer +直接将句子中任意两个单词的联系通过一个计算步骤直接联系起来,远距离依赖特征之间的距离被极大缩短,有利于有效地利用这些特征; +
- Self Attention +大大提升了计算的并行,通过上三角mask可以同时训练一句话中的所有token; +
- 输入输出:sbh*2 byte +
- 模型大小:n*2 GB +
- 梯度大小:n*2 GB +
- 优化器大小:(4+4+4) *n +GB。模型更新时,梯度很小,学习率也很小,精度丢失会影响模型收敛效果,所以优化器中的数据全都是 +fp32 精度。 +
- 激活值大小:sbh(34+5*a*s/h)*L byte 分析 +
- 提取带有❓的句子作为问题,以此问题提取相关的响应和反馈。使用NLTK分离响应和反馈中的单个对话,方便后续对其进行单一种类的聚类。 -
- 聚类方法与压力源一致,每个集群至少有两个不同的集群元素。 -
情感状态建模
+- [PAD] 填充至固定长度 +
- [CLS] 分类任务 +
- [SEP] 分隔符 +
- [MASK] 自监督任务,序列填空 +
- [BOS] / [EOS] 自回归任务,约束文本生成的边界 +
- [UNK] 无法识别的词 +
- [SPE] 词汇表预留的标志 + +
- 使用Pu提出的基于BERT的情感分类器,将每一个簇与某一情感状态相关联,共有41种情感状态。先将每一个簇下的每个文本进行分类,再按照情感出现次数和分类置信度排序,选取最相关的情感状态。 -## Statistical Analysis -
HEAL知识图谱:2.2k集群节点和情感状态,104k连接
-反馈集群中,负面情绪明显减少,证明HEAL中存在帮助人们降低负面情感状态的有用响应 -## Visualization and Interpretation
-表示大多数回答都是正向积极反馈 ## Evaluating the Utility of HEAL -in Responding to Distress Prompts
-获取共情响应
+- 训练阶段,每一轮的 batch 都是独立的,
attention mask
+会把与有效序列无关的部分都屏蔽了,因此两者都行;
+ - 推理阶段,存在自回归的推理过程,当并发
batch infer
+时,左 padding 可以直接将推理得到的下一跳 Token 合并到 +input_ids
尾部,简化编码过程;
+
+ - 从测试集中选取和压力源中现有叙述相似性高于0.75的新对话 -
- 根据压力源和响应之间边权的权重、响应簇大小进行排序,选择排名高的响应 -
自动评估
+- BertEmbeddings
-
-
- HEAL的响应更加多样化,可以根据给定的情况给出特定的响应 -
- 在其他自动指标BLEU、METEOR和ROUGE方面表现不佳 +
- word_embeddings +
- position_embeddings +
- token_type_embeddings +
- LayerNorm + dropout
- 人类评估【DOI: 10.18653/v1/d16-1230】
+- BertEncoder
-
-
- HEAL模型变现更好 ## Discussion and Conclusion +
- attention +
- MLP +
- LayerNorm + dropout
- HEAL:利用Reddit上约1M个与痛苦相关的对话得出的知识图谱。在不同类型的压力源、说话者期望、求助者反应和求助者反馈类型之间形成联系,同时将每个节点与41种情感状态中的一种联系起来
-
-
-- BertPooler
-
-
端到端对话经常会产生通用和重复性对话,缺乏可控性。使用常识推理和知识图结构表示,可以生成适合的、可预测的、多策略的回应。
-目前的知识图谱不适用于移情对话。移情领域缺乏数据集和模型帮助产生移情反应,还缺乏具有上下文-相应之间关系的知识图谱。 -# 解决方法 / 创新点
-开发大规模知识图谱HEAL,识别不同的压力源、期望、响应、反馈和该对话的情感状态
-统计和可视化分析,识别导致情绪强度降低的有利反应
-评估通过HEAL检索到的回应,在解决情感困扰问题上的共情性、多样性、可靠性 -# 实验结论
-与RoBERTa、Blender进行比较,HEAL能够产生更多样化、更移情的反应
-统计和可视化分析证实了在HEAL中存在有用的反应策略,这些策略降低了遭受痛苦的人的负面情感状态
-使用纯生成模型来解决痛苦存在危险,HEAL通过战略性地识别与给定提示相关的特定压力源来避免不适当的反应 -# 有待提升的部分
-只使用了压力源与回复的边缘权重,进一步可以通过将边缘权重与说话者的期望和反馈结合起来来开发
-知识图的信息可以用于增强神经反应生成模型,并为这些模型引入更多的可控性和可解释性,从而提高可靠性
-仅限于识别≈4K的压力源,可以从网络上获取更多数据来增强知识图谱,这将帮助其能够处理更大范围的压力源和期望
+- dense + activation +
+ 混和主动性:按照说话者角色和主动类型分为四类
-提出四个情绪支持指标
-提出一种用于 ESC 的知识增强混合主动框架 (KEMI) ## -Introduction
-ESC系统
--
-
- 在适当的时候发起讨论,目的是提出建议,并解决问题 -
-相关工作
--
-
- CIS(conversational -information-seeking)可以主动发起对话,澄清交互并探索更多的信息 -
- 情感推理用来生成共情反应 -
- identifying the dialogue acts of the utterances -
- ESC 系统预测下一个对话策略 -
-ESC问题的三个挑战
--
-
- 系统应该在对话过程中何时采取主动? -
- 系统发起子对话需要什么样的信息? -
- 系统如何促进混合主动交互? -
-解决方法
--
-
- 策略预测:确定下一回合混合主动策略 -
- 知识选择:收集下一回合的必要知识 -
- 响应生成:在适当的混合主动策略和知识下产生情感支持响应 -
-提出的新东西
--
-
- 混合主动性特征
-
-
-
- EAFR模式:话语注释为不同类型的说话者角色和主动类型 -
- Expression, Action, Reflection, Feedback -
- - 情感支持指标
-
-
-
- Proactivity, Information, Repetition, Relaxation -
- - KEMI
+
LLM 结构和创新点 +/-NLP/LLM-Model/ +优化技术 + +
+大模型领域针对 Transformer 计算过程的一些优化
+滑动窗口注意力
+sliding window attention: Longformer
++ +
稀疏注意力
+Generating Long Sequences with Sparse +Transformers,核心是只让设置好的像素点参与自注意力的计算(注意这里不是只选取设置好位置上的像素点,其他mask掉,因为这样并不能降低模型的复杂度),引入一个名为连接模式(Connectivity +Pattern)的变量,连接模式只作用在\(K\)和\(V\)的计算上,(bs, head_num, seq_len, +head_dim) 中的 seq_len 只选取连接模式中选择的。
+连接模式(注意力核)的选择:局部稀疏模式、分块稀疏模式、对角块稀疏模式
++ +
Flash Attention
+其核心思想是将原始的注意力矩阵分解成更小的子矩阵,然后分别对这些子矩阵进行计算,只要这个子矩阵的大小可以在 +SRAM 内存放,那么不就可以在计算过程中只访问 SRAM 了。
+采用了 Recomputation +(重算)方法,这算是在深度学习优化中的老概念了,它是一种算力换内存的把戏。
+Tiling 方法将 NxN 的 softmax 分数矩阵划分为块,核心是 +分块SoftMax算法,详细推导过程见技术博客。
+Qwen2 模块
++ +
modeling_qwen2.py
架构-
-
- 使用生成的常识知识作为查询图来扩展用户话语,在知识图谱上执行子图检索 -
- 响应生成模块以序列到序列的方式,对策略预测和响应生成进行【多任务学习】,以生成具有外部知识的混合主动响应 -
-
-- 混合主动性特征
-
主要贡献
+Qwen2RMSNorm: RMS归一化层
+Qwen2RotaryEmbedding: 旋转位置编码
+Attention
-
-
- EAFR 注释模式和四种情感支持指标 -
- 使用用常识知识扩展的查询图,通过子图检索从心理健康知识图谱中检索外部知识 -## Related Works +
Qwen2Attention: 注意力层
+Qwen2FlashAttention2: 使用Flash Attention +2.0版本加速的注意力层
+Qwen2SdpaAttention: 使用Sdpa(pytorch自带的加速, Scaled +Dot-Product Attention)加速的注意力层
-ESC
--
-
- 检测用户情绪 -
- 将情感信号放入Respond中 -
- 情绪感知反应,情感风格转移 -
- 共情对话系统 +
Qwen2DecoderLayer: 编码层,核心结构,之后就是堆叠
+Qwen2PreTrainedModel: 预训练类
+Qwen2Model: 不带head的Qwen2模型
+Qwen2ForCausalLM: 带Causal LM head的Qwen2模型
+Qwen2ForSequenceClassification: 带序列分类头的Qwen2模型
+
功能函数
-
-
- 情感推理技巧 -
- 利用外部知识来提高情绪推理的建模能力:知识图、常识性模型、特定领域知识、常识性知识 -
-混合主动对话 ## Preliminary Analysis
-EAFR
+_get_unpad_data: 在flash attention的数据预处理中会用到。主要是对 +attention mask 进行一些操作;
+rotate_half: 在旋转位置编码中用到;
+apply_rotary_pos_emb: 对数据主要是注意力运算中的 q,k +做旋转位置编码;
+repeat_kv: 主要是在 MQA(Multi-Query Attention)和 +GQA(Group-Query Attention)中用到,因为 q head 数量是 k,v head +的数量的整数倍
+
+- 四种注释方法:按照角色和主动类型区分 -
- 四种评价指标:【待看】 -
混合主动性分析
-混和主动性的挑战
+- 第 1 对:\((v_0,v_1)\) +
- 第 2 对:\((v_2,v_3)\) +
- ... +
- 第 256 对:\((v_{510},v_{511})\) + +
- 系统何时采取主动? -
- 系统发起子对话时,需要什么信息? +
- LayerNorm +通过均值和标准差对输入进行标准化,确保输入具有零均值和单位方差,这对稳定训练有帮助。 +
- RMSNorm +则通过均方根进行归一化,不关注均值,仅对幅值进行规范化,避免了对数据的中心化处理,减少了计算复杂度,并且在某些模型中表现优越。 +
- 情感识别:识别用户情感状态 -
- 因果识别:导致情感状态的压力源 -
- 认知识别:解决问题的过程 -
- 根据历史对话,系统自发判断响应的主动或被动 - -
问题定义
+- x 是输入向量(通常是模型中每一层的输出)。 +
- \(\mu\) 是输入向量的均值。 +
- \(\sigma\) +是输入向量的标准差。 +
- \(\gamma\) 和 \(\beta\) 是可学习的缩放和偏移参数。 + +
- 给定历史对话C和用户情况s,产生相应r +
- \(\text{RMS}(x) = \sqrt{\frac{1}{n} +\sum_{i=1}^n x_i^2}\)是输入向量的均方根; +
- $$ 是可学习的缩放参数; +
- 不使用均值和偏移参数 \(\beta\) +; +
- 策略预测y,细粒度主动性 -
- 知识选择k -
- 使用y和k生成混合主动相应r ## Method -
知识获取
+- batch size 大,并行计算; +
- 模型参数量大,每个参数都需要存储空间(精度不同占用空间不同 fp32 fp16 +bf16 int8 int4); +
- 计算过程产生大量的中间变量(如激活值、梯度等),这些中间变量也需要存储在显存中,以便进行后续的计算; +
- 优化器所需的额外信息多(如动量、学习率等); +
- 模型复杂,反向传播的计算图占用更多显存; + +
- 检索心理健康知识图谱HEAL,弥补常识性知识的不足 +
- 不需要存储它们的梯度; +
- 不需要为不可训练参数分配额外的内存来存储优化状态(如动量、学习率等); +
- 不需要存储中间激活值(激活值用于在后向传播过程中,计算梯度,进而更新模型的参数); +
- COMET常识性知识扩展查询:Cp = COMET(p, ut) -
- 构造查询图:û = {ut, {Cp}} +
- 梯度累计技术:将多个小批量训练数据的梯度进行累积,在达到指定累积次数后,使用累积梯度统一更新一次模型参数,从而达到与大批量数据训练相近的效果;
-
-
- expectation:ut -
- affective:[xReact] -
- stressor:[xIntent] -
- responses:[xWant] [xNeed] [xEffect] +
- 相当于降低了 batch size,因而减少了显存占用; +
- 多个小批量的可训练参数的梯度是存在一起的,不额外占用显存;
- - 子图检索 +
- 梯度检查点 +gradient_checkpoint:在后向传播过程中重新计算前向传播中的某些中间激活值,从而减少显存占用; +
- 相似度计算:sentence-BERT -
- 针对每个 ût -中的抽象描述,获取与其最相似的top-K个HEAL中的实体,基于HEAL中的边缘连接,构成候选子图 -
- 针对每个 E -中的类型节点,按照子图中的每个节点相似度得分之和排序子图,选择top-N作为检索到的知识K -
混合主动响应生成
+全量微调大模型虽然效果还不错,但需要大量的计算资源和训练数据(训练数据中通用数据和领域数据都要有);
+为了降低计算资源,只微调模型的某几层参数时,无法得到较好的微调结果,会出现欠拟合或泛化能力降低的情况,模型无法有效学习领域数据的知识,且可能会破坏了预训练模型的通用语言语义能力;
+当修改了输入 Embedding +或大模型每一层的某些部分时,可以在有限的计算资源上,得到与全量微调近似的微调效果,这便是 +PEFT 存在的理由;
+不同领域的全量微调模型需要分开部署,资源占用量大;由于只修改了部分参数,PEFT +中的方法,都具有“一次部署,多领域共用”的能力,只需要一次就能加载所有参数,针对不同领域的调用切换不同的 +PEFT 参数,即采用该领域微调所增加的小部分参数;
+
+- 使用基于上下文的编码器,编码上下文对话C和知识K -
- X:[CLS]
[know.]<know.>;Y:[strategy]y[response]r
- - 优化损失函数,最大化负对数似然函数L ## Experiment +
- 高效微调 PEFT;
+
-
+
- Lora +
- Prefix-Tuning
- 实验基础
+- 前向激活值;
-
-
- 数据集:ESConv、MI -
- 评估参数:流利度Perplexity (PPL)、内容保留度BLEU-n -(B-n)、内容保留度ROUGE-L (R-L) +
- Gradient Accumulation +
- Gradient Checkpoints +
- Data Length
- 总体表现
+- 优化器状态;
-
-
- BlenderBot优于Transformer -
- GLHG、MISI有效地利用了常识性知识 -
- 基于策略的联合学习可以提高性能 -
- KEMI明显优于其他方法:HEAL知识相比常识性知识更有效地支持了预测策略,减轻了对预训练大模型的依赖 +
- Adafactor Optiomizer
- 人工评价
+- 前向激活值 + 梯度;
-
-
- 从流畅度、辨识度、舒适度、建议有效性、总体回应五个方面与BlenderBot-joint、MISC进行对比,MISC完胜 +
- Freeze Model
- 消融实验
+- 参数量化;
-
-
- HEAL可以有效提升策略预测准确度 -
- 舍弃COMET,可以提高ppl准确度,因为常识性知识不是自然语句;但会降低内容保留度,因为简洁的常识性知识更为精确 -
- 认知识别是最有效的 -
- 对比Oracle,还有很大的提升空间 +
- QLora
- 混和主动性分析
+- 情感支持指标分析 +
- Selective:选择模型中的一部分参数进行微调; +
- Additive:冻结模型原有参数,微调新增的参数和模块;
-
-
- KEMI有效的平衡了主动性和非主动性回复 -
- KEMI回复的信息更加丰富 -
- KEMI容易生成重复性回复 -
- KEMI有效地帮助用户解决情绪问题 +
- Adapters: +
- Soft Prompt:
- - 会话进度 +
- Reparameterzation: +
- 相比BlenderBot和MISC,KEMI在对话过程中,主动性和非主动性的分布更加平衡 -
- KEMI在对话中后期更能主动相应并缓解用户负面情绪 -
案例分析 ## Conclusions
-首次提出ESC中混和主动性的特点,并阐述其重要性
-KEMI框架
+微调图像大模型 Stable Diffusion:lokr loha;
+将文本到图像的扩散模型适应下游任务:正交矩阵OFT、蝴蝶微调 Boft +;
+
+- 通过查询扩展和子图检索,从大规模心理健康图谱中检索实际病例知识 -
- 通过检索到的知识,进行策略预测和响应生成的多任务学习 -
结合实际案例和分析指标,结果证明KEMI优于现有方法,并在混合主动交互方面具有优势 -## Limitations
-评价指标有待改进
-没有考虑不同知识检索方法的不同
-从复杂的KG图中检索知识的方法有待提高
-某些应用的知识图难以获取
-知识库的建立需要具有专业知识的人员 ## Appendix
-混和主动性
+- 简单高效,资源占用量小; +
- 泛化性强,适用各种场景; + +
- 对话主动性分析 +
- 可解释性差; +
- 强依赖于大模型自身的质量; +
- 主动性分析模型:在ESConv数据集增加混合主动的类型属性,把历史对话和当前话语作为二元输入,判断主动性。微调RoBERTTalarge,分别训练两个模型,判断用户和系统的主动性 -
- 情绪强度预测模型:根据用户话语预测负面情绪强度 -
- 用户模拟并注释四种评价指标 :【待看】 -
- 对话流分析 +
- 参数量低,效果不错; + +
- ESC在对话中充当主动角色;ED在对话中充当被动角色 -
- 对话过程 +
- 简化了不同任务之间的转换和迁移,使得模型可以更加灵活地应用于各种场景; + +
- 研究内容:主动性和情绪强度变化的关系 -
- 结论 +
- 预训练模型较小或在Few-shot场景下,微调结果不佳; +
- 交互时间很重要 -
- 情绪缓解后才更有利于解决问题 -
- ES指标 - -
COMET
+- 通过 Encoder 将离散的 Prompt Embedding 转变为连续的,减少了 Prompt +Embedding 初始化对微调性能的影响,提高了训练的稳定性; + +
- 常识性关系 -
HEAL
+- 增加的 Prompt Encoder 需要额外的计算资源; + +
- 情绪压力和安慰回应之间的知识图谱 -
- 表现了对话双方的情绪动态,确定缓解情绪的方法 # 解决了什么问题 -
常识性知识是相当抽象的,没有详细的信息,因此它对ESC系统产生有意义和信息丰富的响应的帮助不大。在这项工作中,我们采用生成式常识模型进行查询扩展,从外部知识图中检索实际案例知识。 -# 怎么解决的 / 该方法的优势
+- 拟合速度快; -
常识知识生成器 COMET:
-常识性知识获取 HEAL: # 有什么创新点
-提出ESC知识增强混合主动框架
--
-
- 人类和系统都可以主动引导交互方向 -
- 通过子图检索从心理健康知识图谱中检索外部知识 -
-新的分析方法 > 保留评估 和 混合主动性分析 -方面均有效优于现有方法
--
-
- 按照说话者角色和主动类型将话语注释为不同类型
-
-
-
- Expression:用户主动 -
- Action:系统主动 -
- Feedback:用户非主动 -
- Reflection:系统非主动 -
- - 提出四个情感支持指标来衡量ESC中主动性和非主动性交互的特征
-
-
-
- Proactivity:系统主动的对话占系统对话的比例 -
- Information:系统首次提出的频繁词占比 -
- Repetition:系统重复用户提出的术语的频次占比 -
- Relaxation:情绪强度的改善 # 实验结果好在哪里,怎么证明的 -
-
-- 按照说话者角色和主动类型将话语注释为不同类型
-
先前工作的局限性
+- 直接修改模型结构,依赖预训练模型本身的结构; +
- 实现复杂,相比于直接修改输入 Prompt Embedding 没有显著优势; +
- 相比于其他的 Soft Prompt 方法,Prefix Tuning +可训练参数量大,每一层的 K V 都需要可训练前缀; +
- 采用对话级别的情感标签,这种标签过于粗粒度,无法捕捉用户的即时精神状态 -
- 大多侧重于在回应中表达同理心,而不是逐渐减轻用户的痛苦 -
本文提出了MISC
+- 移除重参数化的编码器,对于较小的模型,会影响模型的表现,且对于大模型提升不大; +
- 引入多任务学习概念,先在多任务的Prompt上进行预训练,然后再适配下游任务; + +
- 首先推断用户的细粒度情感状态,然后使用混合策略巧妙地响应 -
- 在基准数据集上的实验结果证明了方法的有效性,并揭示了细粒度情感理解和混合策略建模的好处 -## Introduction -
目前的工作不适用于ESC
+- prefix长度在 100~200 +时,微调结果最优,但由于模型可接受的最大输入长度有限,随着软提示的参数量增多,实际输入序列的最大长度也会相应减小; +
- 直接优化 prompt 和 prefix 是非单调的,比较难以收敛; + +
- 粗粒度静态的对话级情感标签无法关注到对话过程中用户情感发生的变化 -
- 只有移情反应,而不考虑解决求助者的情感问题 -
本文提出的解决方法
+- 需要底层实现来加速非结构化稀疏矩阵的计算,不能直接使用现有的框架; +
- 训练过程中需要存储完整的∆矩阵,相比于Full +finetune并没有降低计算成本; + +
- 有选择地采用COMET(预训练生成式常识推理模型)生成的知识元组进行细粒度情感理解 -
- 混合策略,而不是预测单一策略 -
- 设计一套注意力机制 -
实验分析
+- 可以将原权重与训练后权重合并,在推理时不存在额外的计算开销; +
- 不增加输入参数,不改变模型结构,简单易用,泛化性强; +
- 提出低秩分解矩阵的思路,在减少计算资源需求的同时,不会丢失预训练原有的通用能力; + +
- 回答策略建模的重要性,能够提高模型的共情能力 ## Related Work -
情绪感知响应生成
-NLP中的常识性知识
-策略感知对话模型 ## Preliminaries
-ESConv数据集
-问题设定
+- 预先指定每个增量矩阵的内在秩 r +相同,忽略了在微调预训练模型时,权重矩阵的重要性在不同模块和层之间存在显著差异,在实验中可以发现 +Wq +的秩更大,即存储的信息更多;因此无法完全捕捉预训练模型的特征,或无法有效地将原始模型的知识迁移到目标任务上; +
- 只训练了self-attention,没有训练 feed-forward networks,事实上 FFN +更重要; + +
- 通过对话历史、场景、求助者最后一句话,预测回复策略和回复内容 ## -Model: MISC -
情感状态增强Encoder
+- 调节的参数少于 Lora,微调效果也不错; + +
- 利用COMET提取场景situation和语句x的常识性知识,将常识性知识输入Encoder得到H's和H'x -
- 学习率对微调效率影响较大,论文中的建议是 3e-3; +
- 将H's和H'x分别与历史对话c做cross-attention,得到Hs和Hx -
- 将历史对话c输入Encoder得到C -
- 混合策略学习模块【从VQ-VAE's codebook文章中抄来的】
+class="math display">\[S_{k,i}=s\left(\lambda_{k,i}\right)+\frac{1}{d_1}\sum_{j=1}^{d_1}s\left(P_{k,ji}\right)+\frac{1}{d_2}\sum_{j=1}^{d_2}s\left(Q_{k,ij}\right)\]
+
通过灵敏度平滑和不确定性量化,加入累计灵敏度的影响来解决随机采样和复杂的训练动态导致灵敏度估计的变异性大、不确定性大的问题
+\[\begin{aligned}&\bar{I}^{(t)}\left(w_{ij}\right)=\beta_1\bar{I}^{(t-1)}\left(w_{ij}\right)+\left(1-\beta_1\right)I^{(t)}\left(w_{ij}\right)\\&\bar{U}^{(t)}\left(w_{ij}\right)=\beta_2\bar{U}^{(t-1)}\left(w_{ij}\right)+\left(1-\beta_2\right)\left|I^{(t)}\left(w_{ij}\right)-\bar{I}^{(t)}\left(w_{ij}\right)\right|\end{aligned}\]
+\[s^{(t)}\left(w_{ij}\right)=\bar{I}^{(t)}\left(w_{ij}\right)\cdot\bar{U}^{(t)}\left(w_{ij}\right)\]
+可以通过梯度下降的方式对\(P, \Lambda, +Q\)进行更新,将不需要的奇异值 λ 剪裁 Mask,后续仍可以加入训练
+\[\Lambda_k^{(t+1)}=\mathcal{T}\left(\tilde{\Lambda}_k^{(t)},S_k^{(t)}\right),\text{ +with +}\mathcal{T}\left(\tilde{\Lambda}_k^{(t)},S_k^{(t)}\right)_{ii}=\begin{cases}\tilde{\Lambda}_{k,ii}^{(t)}&S_{k,i}^{(t)}\text{ +is in the top- }b^{(t)}\text{ of }S^{(t)}\\0&\text{ +otherwise}&\end{cases}\]
+训练损失中添加了额外的惩罚项,以规范奇异矩阵P和Q的正交性,从而避免SVD的大量计算并稳定训练。
+\[R(P,Q)=\left\|P^\top +P-I\right\|_\mathrm{F}^2+\left\|QQ^\top-I\right\|_\mathrm{F}^2\]
+最终,微调的损失函数为
+重要结论
+ ++
AdaLoRA 总是倾向于将更多预算分配给 FFN 和顶层,即 FFN +模块和顶层的权重矩阵对于模型性能更为重要。
+Adapter Tuning
+在 Transformer Layer 的 Self-Attetion 和 FFN +之后插入一个先降维再升维的 MLP(以及一层残差和Layer +Normalization)来学习模型微调的知识。
+ ++
图中,Adapter 即插入的 FF Down + 非线性激活层 + FF +up。在微调过程中,固定原始模型的参数,只微调适配层。
+不足:
-
-
- C输入多层感知机+softmax得到Pg(Pg大小是strategy_size) -
- Pg作为概率分布,hg=Pg*T(T为策略嵌入) +
- 需要修改原有模型结构,会增加模型参数量; +
变体:
-
-
- 长对话回复中可以引入多种策略,且模型学习灵活方便 -
- - 多因素感知Decoder +
- Paper:仅在 +MLP 模块之后和 LayerNorm 之后使用适配器层 + +
- 将情绪状态和策略表征传入Decoder里的Cross-attention ## -Experiments -
- ESConv中的每十个话语作为一个样本 -
- 评价指标 +
- 优于在单任务和多任务中训练的 Adapter +模型,可以视为多Adapter提取不同维度的信息,AdapterFusion +将他们融合起来。 + +
- 策略预测精度:Acc -
- 传统NLP指标:PPL、BLEU、ROUGE-L -
- 相应多样性:Distinct -
- 人类评估 -
- 基准模型 +
- 通过从较低的 Transformer 层删除可变数量的Adaper来提升推理速度。 +当对多个任务执行推理时,动态地减少了运行时的计算开销,并在很大程度上保持了任务性能; + +
- MT Transformer、MoEL、MIME、BlenderBot-Joint -
- 具体实现 -
- 实验结果 +
- 相比于 LoRA,收敛速度更快,性能更好 + +
- 动态细粒度情感标签更能准确给予用户回应 -
- 细粒度共情,多策略平稳过渡策略,可以更自然地表达共情并提供帮助 -
- 策略作为单独的任务进行预测比单一预测更有利 -
- MISC的知识Know得分最高,成功学习到了COMET中的心理状态知识 ## -Analysis -
- 消融实验 -
- 案例研究 -
- 细粒度情感理解 +
- VeRA显著减少了可训练参数的数量(LoRA相比参数减少了10倍),而精度没有损失; +
- 缩放向量尺寸小,可以将许多版本驻留在单个GPU的有限内存中,从而大大提高了服务效率,适合于需要频繁交换大量微调模型的场景,比如针对个人用户个性化的基于云的人工智能服务; + +
- 用粗粒度的情感标签代替细粒度的心理信息可以显著提高指标 -
- 混合策略感知移情反应 +
- 节省内存(三倍); +
- 性能不错; + +
- 混合策略有利于平滑的情感支持 -
- 混合策略比单一策略更有效 -
- 混合策略适用于ESC框架 ## Conclusions -
- 引入COMET来捕捉用户的即时心理状态 -
- 设计了一个混合策略感知解码器来产生支持响应 # 解决了什么问题 / -怎么解决的 +
- 训练速度慢(三倍); -
长对话中的过度更加顺畅 # 有什么创新点
-提出seq2seq模型MISC,在ESC中添加了常识性知识和混合反应策略
-提出了不同的策略模型并在对话中给予提示 # -实验结果好在哪里,怎么证明的
-从SOTA延续下来的细粒度情感表现较粗粒度静态情感更好 # -相关工作分析
+- 4位NormalFloat(NF4):这是一种针对正态分布权重设计的信息理论上最优的量化数据类型。相较于传统的4位整数和4位浮点数,NF4为正态分布数据提供了更优异的实证性能。 +
- 双重量化:QLora引入了对量化常数的二次量化,进一步减小了缓存占用。这种双重量化机制包含对普通参数的一次量化和对量化常数的再量化,从而在不牺牲精度的前提下进一步压缩模型。 +
- 分页优化器:这是一种智能的内存管理技术,当GPU内存不足时,它可以将部分数据移到系统内存中,并在需要时调回GPU内存。这有助于处理长序列或大批量数据时的内存峰值问题。
- 以动态的方式学习混合响应策略 +
- 提出了高效且有效的量化技术,使在单个GPU上微调超大型参数模型成为可能;
开放域聊天机器人需要良好的谈话技巧:提出有吸引力的要点,倾听别人的意见,适当展示知识、同理性和个性,保持前后一致
-本文证实:基于适当的训练数据和生成策略,大模型可以学习上述技巧 ## -Introduction
-研究的主要内容
+Linux 开发工具 +/-NLP/Linux-Tool/ +Vim + 基本模式切换
-
-
- 混合技巧:模型专注于个性和吸引力、知识、同理心。采用 Blended Skill -Talk -实现,具体是通过提供训练数据和初始化上下文来实现。这种方法可以减少从大语料库中学习到不良特征。 -
- 生成策略:解码算法非常重要,对话长度强相关于对话质量,本文实验表明采样优于束搜索 -
-本文的优势和存在的问题 ## Model architectures
-检索
+i
:进入插入模式,从光标前插入文本。
+a
:进入插入模式,从光标后插入文本。
+Esc
:退出插入模式,回到正常模式。
+v
:进入可视模式,用于选择文本块。
+V
或 +vv
:进入可视行模式,选择整行文本。
+Ctrl + v
:进入可视块模式,选择矩形区域。
+- 将训练集作为候选响应集,每个可能的候选响应都参与Encoder,并做聚类【poly-encoder】 -
生成
+w
:光标移动到下一个单词的开头。
+b
:光标移动到上一个单词的开头。
+0
:移动到行首。
+$
:移动到行尾。
+gg
:移动到文件的第一行。
+G
:移动到文件的最后一行。
+H
:移动到屏幕的顶部。
+M
:移动到屏幕的中部。
+L
:移动到屏幕的底部。
+
+- 使用标准的Seq2Seq Transformer架构生成响应 -
检索和提炼
+x
:删除光标所在的字符。
+dw
:删除从光标到单词末尾的内容。
+dd
:删除当前行。
+d$
:删除从光标到行末的内容。
+yy
:复制当前行。
+p
:粘贴到光标之后。
+u
:撤销上一步操作。
+Ctrl + r
:重做撤销的操作。
+r
:替换光标下的字符。
+ciw
:删除光标所在的单词并进入插入模式。
+c$
:删除从光标到行尾的内容并进入插入模式。
+
+- 帮助模型访问没有嵌入其模型参数的外部知识 -
- 对话检索:通过检索模型生成响应,并将其附加到Decoder的输入序列中,并用分隔符分开。使用修改后的输入序列生成正常的响应 -
- 知识检索:检索Wiki生成初始候选集,使用上文提到的检索模型,排序候选词并选择条件生成的句子。此外,训练一个分类器,通过上下文判断何时需要检索知识 -## Training Objectives -
检索排序
+/pattern
:向下搜索 +pattern
。
+?pattern
:向上搜索 +pattern
。
+n
:跳到下一个搜索结果。
+N
:跳到上一个搜索结果。
+:s/old/new/g
:将当前行的所有 +old
替换为new
。
+:%s/old/new/g
:将整个文件中的所有 +old
替换为new
。
+
+- 模型训练使用本文回答作为正例,其他对话回答作为负例 -
响应生成模型的似然训练
+:w
:保存文件。
+:q
:退出 Vim。
+:wq
:保存并退出。
+:q!
:不保存强制退出。
+:e filename
:打开文件 +filename
。
+:r filename
:在当前文件中插入 +filename
的内容。
+
+- 建模整个序列的概率分布 -
α-混合检索和提炼
+screen
:启动一个新的 +screen
会话。
+screen -S session_name
:启动一个命名为 +session_name
的screen
会话。
+screen -ls
:列出当前所有的 +screen
会话。
+screen -r
:重新连接到一个 +screen
会话(如果只有一个会话)。
+screen -r session_name
:重新连接到一个名为 +session_name
的screen
会话。
+screen -d session_name
:在其他地方的终端断开某个会话的连接。
+screen -d -r session_name
:强制从其他地方的终端断开并重新连接到 +session_name
会话。
+screen -X quit
:关闭所有 +screen
会话
+
+- 生成模型常常不考虑对话检索语句,为确保其被使用,将检索相应中的α%替换成真实响应,α为超参数 -
- 知识检索的数据集里,知识条件和响应之间有明确的对应关系 -
- 因此训练阶段只使用知识检索的数据,充实模型参数中学到的知识 -
响应生成模型的非似然损失
+Ctrl + a, X
:关闭当前的分割窗口。
+Ctrl + a, c
:创建一个新的窗口。
+Ctrl + a, n
:切换到下一个窗口。
+Ctrl + a, p
:切换到上一个窗口。
+Ctrl + a, "
:列出当前所有窗口,允许选择切换。
+Ctrl + a, 0-9
:切换到指定编号的窗口(例如 +Ctrl + a, 1
切换到窗口 1)。
+Ctrl + a, d
:将当前 +screen
会话断开(detach),会话继续在后台运行。
+Ctrl + a, A
:重命名当前窗口。
+Ctrl + a, K
:关闭当前窗口。
+Ctrl + a, S
:水平分割当前窗口。
+Ctrl + a, |
:垂直分割当前窗口。
+Ctrl + a, tab
:在分割的窗口间切换焦点。
+Ctrl + a, Q
:关闭除了当前窗口外的所有分割窗口。
+Ctrl + a, X
:关闭当前的分割窗口。
+
+- 使用高于真实数据数量的n元语法中的token作为候选负样本,修正已知的偏差 -## Decoding 选择解码方法对给定的历史对话的响应 -
确定性解码方法
+Ctrl + a, :quit
或 +Ctrl + a, d
:结束当前screen
+会话。
+Ctrl + a, :kill
:强制关闭当前窗口。
+exit
:退出当前screen
+会话。
+
+]]>- 束搜索 -
- 贪心搜索 -
采样
+- 索引:用于引入源数据并对其进行索引的管道
-
-
- 多项采样:根据预测结果概率分布,定义候选Token被选中的概率。防止采样到低概率Token,可以将采样限制在词汇表的子集内,并根据子集概率重采样 -
- 平滑分布采样:Temparature+SoftMax+multinomial -
- top-k -sampling:Temparature+Top-k+SoftMax+multinomial,将top-k外的token概率置为0 -
- sample-and-rank:多次采样,取最高概率的响应 +
- 加载:将数据库中的大段文本读入系统 +
- 拆分:大块数据不便于搜索,且模型的上下文窗口有限,因此需要拆分数据 +
- 存储:采用向量数据库和索引存储数据
- 响应长度
+- 检索和生成:实际的 RAG
+链,它在运行时接受用户查询并从索引中检索相关数据,然后将其传递给模型
-
-
- 约束最小生成长度:在实现最小序列长度之前,强制不生成结束标记 -
- 预测长度:根据上下文预测相应长度,这是一个四分类问题 +
- 检索:将用户的查询通过嵌入模型转化为向量,以便与向量数据库中的其他上下文信息进行比对。通过这种相似性搜索,可以找到向量数据库中最匹配的前 +k 个数据 +
- 生成:将用户的查询和检索到的额外信息一起嵌入到一个预设的提示模板中,这个经过检索增强的提示内容会被输入到大语言模型 +(LLM) 中,以生成所需的输出
- 子序列分块
+ +从原始数据到响应生成最常见的流程图如下:
++
流程图2:
++
RAG 测评指标:
+ ++
Langchain
+LangChain +采用组件化设计的思想,将语言模型开发分为多个子任务:对话历史 +Memory、提示工程 Prompt、输出解析 Parase、LLM链 Chain、索引 +Indexes、代理 Agents。Langchain +模块化设计的中心思想是提升代码维护、扩展和重用的能力,可以快速开发多轮提示以及解析输出的应用。
+此外,Langchain +还提供了对话过程中需要的基本功能,如:文档加载器 +UnstructuredBaseLoader、文档分割器 TextSplitter、向量数据库存储和搜索 +BaseChatMemory、多种工具类链调用 MapReduceDocumentsChain
+还有额外的功能:API 用量记录、数据流返回 acall、缓存 +SQLite、支持多种模型接口 +OpenAI、向量数据库接口langchain.vectorstores
+模型链 Chain
+链(Chains)通常将大语言模型(LLM)与其他组件组合在一起来构建更复杂的链。比如,LLMChain +允许我们对创建的 Prompt 使用大模型;
+Chain 基类是所有 Chain +对象的起点,处理输入、输出、历史和回调等功能,支持同步和异步调用,内部组件也可以通过回调进行交互;
+自定义 Chain 需要继承 Chain 基类,实现 _call/_acall +方法定义调用逻辑;
+对话历史 Memory
+根据需求可以将历史存储在 +SQLite、qdrant等数据库中,下面代码将历史存储在缓存中:
++from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(
memory_key="history", # 与 prompt 的输入变量保持一致。
return_messages=True # 将以消息列表的形式返回聊天记录,而不是单个字符串
)提示工程 Prompt
+Prompt 很少是写明不变的,通常从多个组件构建而成的。 PromptTemplate +负责构建这个输入。
+输出解析 Parase 是提示工程的一种:
-
-
- n-grams:考虑响应和输入上下文中对于n-grams的重复性 ## Training -Details -
-预训练排序模型
-预训练生成模型
-微调
+get_format_instructions() -> str
:方法,返回一个包含有关如何格式化语言模型输出的字符串,即提示 +Prompt。
+parse(str) -> Any
:方法,接受一个字符串(假定为语言模型的响应)并将其解析为某个结构。
+parse_with_prompt(str) -> Any
:一个方法,它接受一个字符串(假设是语言模型的响应)和一个提示(假设是生成这样的响应的提示),并将其解析为某种结构。提示在此大多数情况下是为了提供信息以便 +OutputParser 重新尝试或以某种方式修复输出。
+
+- Fairseq-style混合精度训练 -
- 使用工具并观察其输出 +
- 生成相应返回给用户 -
- 成对比较和人性方面优于Meena # 解决方法 / 创新点 +
- 缺陷:文档越长,TF 越大;解决:除以文档长度,归一化;\(\sum_{t\in +Q}\frac{\mathrm{tf}_{t,d}}{l_d}\) +
- 缺陷:每个词重要性不同;解决:语义重要性(term +weight),在文档中出现的越多,权重越低;
- 如果对话中深入询问某一方面,由于缺乏知识模型没法给出详细的回答 -
- 模型倾向于简单的回答 -
- 模型倾向于产生重复易混淆的句子 +
- 通过特定领域微调,模型可以学会如何做“开卷考试“; +
- 当领域内数据发生一些变化时,模型依然能找到答案,即使没有正确答案也不会出现幻觉; +
- 可以认为,模型需要专业的微调来训练其在特定领域的 +RAG(开卷考试)能力;
- Abstract
-
-
-
- 本文关注于情感支持对话,提供了一个带策略的情绪支持数据集 -
- - Introduction
-
-
-
- 情感支持应用广泛 -
- 情绪支持数据集应该包括exploration、understand、suggestion三个过程,还包括有用户的情绪强度变化 -
- 目前的研究模型中没有具体有效的情绪支持方法;采集数据集时需要训练有素的支持者 -
- ESC框架:三个阶段,多种策略;众包做数据集;在情绪支持方面有提升 -
- - Related Work
-
-
-
- 移情、同感对话 -
- 情绪支持的数据集 -
- 情绪支持对话
-
-
-
- 任务定义 -
- ESC框架
-
-
-
- 三个阶段:探索、理解、建议 -
- 八种策略 -
-
-
- - Data Collection
-
-
-
- 获取数据集的方法 -
- - Data Characteristics
-
-
-
- 数据展示 -
- - Experiments
-
-
-
- 基准模型:BlenderBot、DialoGPT -
- 模型变种:不带策略:Vanilla;带策略:Random、Joint、Oracle -
- 评估指标:PPL、B-2、R-L、Extrema -
- 实验结果:
-
-
-
- 带策略的Oracle优于不带策略的Vanilla -
- 带策略的Oracle稍微弱于不带策略的Vanilla,因为一旦策略预测错误,respond会完全不同 -
- BlenderBot 变体始终比 DialoGPT 变体表现更好 -
- - 人类互动评价结果:
-
-
-
- 微调后ES能力提升 -
- 带策略微调后能更加适合用户需求 -
- 正确的策略更重要 -
-
- - Conclusion
-
-
-
- 三个阶段、多种策略、ESConv -
- 道德评估 # 解决了什么问题 -
- 目前的对话系统没有针对情感支持的任务和语料库,因此ESC方向还没有被探索到,对话场景中缺乏情感支持。
-情感支持(ES)旨在减少个人的情绪困扰,帮助他们理解和应对所面临的挑战。目前的模型大都只能表示共情而不能解决问题。
-通过社交而不是专业咨询的方式提供情感支持。 # -怎么解决的/该方法的优势
-基于Hill的帮助技能理论,提出了ESC框架
--
-
- 情感支持过程
-
-
-
- 理解遇到的困难,exploration -
- 表达理解和同情,insight/comforting -
- 提出解决问题的方法,action -
-
-- 情感支持过程
-
构建ESConv数据集,有丰富的注释(支持策略)
--
-
- 每个聊天会都会标记:
-
-
-
- 问题类别 -
- 用户情绪类别 -
- 用户情绪强度 -
- 遇到困难的简介 -
-
-- 每个聊天会都会标记:
-
ESC系统
--
-
- 选择支持策略,生成策略约束Respond -
- 情绪状态建模,跟踪用户情绪变化【待分析】 -
- 提出了评估ES实验效果的新方法 # 有什么创新点 -
-- 表达情感
-
-
-
- ECM:情感对话,可以生成情感反应。有情商而不只是智商 -
- ES:有情绪支持的能力,可以减少用户情绪困扰 -
- - 共情能力
-
-
-
- 反应出同情心,不能做情绪支持 -
- - 数据集
-
-
-
- 数据集中的对话短,不适合ES任务 -
- - ESC系统
-
-
-
- 大多研究都人为预先规定好的规则和回复词典 # 可以提升的地方 -
- - Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。在对象被移动时(垃圾收集时移动对象是非常普遍的行为)只会改变句柄中的实例数据指针。 - -
- 直接指针访问方式最大的好处就是速度快,它节省了一次指针定位的时间开销,HotSpot 采用的是直接指针
- 加载:通过全类名获取定义此类的二进制字节流;将字节流所代表的静态存储结构转换为方法区的运行时数据结构;在内存中生成一个代表该类的
Class
@@ -4733,33 +5173,6 @@ href="https://javaguide.cn/java/jvm/classloader.html#%E6%89%93%E7%A0%B4%E5%8F%8CJVM - 了解垃圾回收机制吗?新生代和老年代的垃圾回收是怎么样的 -
- 简要描述线程与进程的关系,区别及优缺点? -
- 线程之间哪些资源是共享的,哪些资源是私有的,为什么? -
- 说一下你对于 AQS 原理的理解。 -
- 如何实现线程安全? -
- 了解过消息中间件吗?说一下使用场景 -
- key 和 value 可以为 null,但 null 作为 key 只能有一个,而 null 作为 value 可以有多个 @@ -4975,248 +5388,101 @@ get、newNode、afterNodeAccess、afterNodeInsertion、afterNodeRemoval
- 每次修改都将元素删除后重新插入
- 将
accessOrder
设置为 true 并重写 -removeEldestEntry
方法当链表大小超过容量时返回 true
- - 写操作资源占用多,复制数据时占用内存 -
- 数据一致性问题,修改后需要等到赋值给原数组才能访问到修改 -
- Java 编译器 Javac 是用 Java 实现的,用于将 .java 文件编译成字节码 -.class -
- .class 通过解释器对这些字节码进行解释执行 -
- Java 的运行环境 JVM 如 HotSpot VM,实现了其跨平台的特性 -
- 多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法(A -a=new B(),A是父类,B是子类) -
- 静态绑定:对象属性和 static private final -修饰的对象方法(构造函数),哪里声明,哪里使用 -
- 动态绑定:运行时 JVM -实现绑定。若子类实现了这个方法,则调用子类的内存地址,若没有则调用当前对象(父类)的方法。只能调用父类的属性,虽然实际实现的是子类,如果父类没有这个属性,那就无法调用。如果要获取子类属性,就要重写子类方法获取该属性,前提是这个方法在父类中同样存在。 -
- 数据库查询返回结果为 Null,无法拆箱 -
- 三目运算符可能出现问题:flag ? 0 : i(应使用 flag ? new Integer(0) : -i) -
- JDK
-动态代理:通过生成一个实现被代理类接口的对象来拦截被代理类的方法调用
-
-
-
- 封装:Proxy.newProxyInstance() 指定 ClassLoader 对象和一组 -interface -
- 调用:InvocationHandler 接口 invoke 方法 -
- - CGLIB
-动态代理:通过生成一个被代理类的子类来拦截被代理类的方法调用(字节码实现,不能被
-final 修饰,编译速度慢,运行速度快)
-
-
-
- 封装:Enhancer 类 -
- 调用:MethodInterceptor 接口 intercept 方法 -
- - JDK:运行时动态解析,无法应用一些 JVM 优化 -
- CGLib:ASM 开源包,代理对象类的 class -文件加载时,修改其字节码生成代理子类(ASM -是在编译期处理字节码的,可以认为是一种编译期的 AOP 技术) -
- 因为 JDK 动态代理类已经继承了 Proxy -这个类,所以只能通过接口来与被代理类建立联系(两个类建立起联系,一是继承的关系【jdk已经不能通过这个方式了,因为java仅支持单继承】,另一种就是实现同一个接口【JDK动态代理选这种】),所以必须要求被代理类也得实现一个接口 -
- sort(list) -
- reverse(list) -
- binarySearch(list, target) -
- max(list) -
- sort(array, (o1, o2)->o1-o2) -
- copyOf(array, Length) -
- binarySearch(array, value) -
- fill(array, value) -
- Comparator 类级别
-
-
-
- 针对不同的比较,单独定义一个比较类 -
- int compare(T o1, T o2);
-
-
-
- 返回值为正数,交换 o1 o2 的顺序 -
- 返回值为负数或零,不需要调整 -
- 返回升序 o1-o2,降序 o2-o1 -
-
- - Comparable 方法级别
-
-
-
- 若一个类实现了Comparable接口,就意味着“该类支持排序”,可以用Arrays.sort()排序 -
- public int compareTo(T o); -
- - 共同点
-
-
-
- 都不能被实例化 -
- 都可以包含抽象方法 -
- 方法可以有默认实现的 -
- - 区别
-
-
-
- 接口主要用于对类的行为进行约束,你实现了某个接口就具有了对应的行为。抽象类主要用于代码复用,强调的是从属关系。 -
- 一个类只能继承一个类,但是可以实现多个接口。 -
- 接口中的成员变量只能是 public static final -类型的,不能被修改且必须有初始值,而抽象类的成员变量默认 -default,可在子类中被重新定义,也可被重新赋值。 -
- - 接口中的所有成员变量都默认是由public static final修饰的 -
- 接口中的所有方法都默认是由public abstract修饰的 -
- 接口没有构造方法 -
- 实现接口的类中必须提供接口中所有方法的具体实现内容 -
- 多个无关的类可以实现同一个接口 -
- 一个类可以实现多个无关的接口 -
- 与继承关系类似,接口与实现类之间存在多态性 -
- 接口可以继承多个接口,使用extends关键字 -
- Java8 -后,接口可以拥有普通方法,实现类不需要重写,可以被实现类继承 +
- 只能在构造器中使用 -this(参数列表);即在一个构造器中访问本类的另外一个构造器。 -
- 显示使用 this() 时,默认的 super() 就被覆盖 -
- this(参数列表)和 super(参数列表)在构造器中有且只能存在一个。 -
- 若在构造器中使用 this(参数列表),则此语句只能位于构造器第一行 +
- 写操作资源占用多,复制数据时占用内存 +
- 数据一致性问题,修改后需要等到赋值给原数组才能访问到修改
- 了解垃圾回收机制吗?新生代和老年代的垃圾回收是怎么样的 +
- 简要描述线程与进程的关系,区别及优缺点? +
- 线程之间哪些资源是共享的,哪些资源是私有的,为什么? +
- 说一下你对于 AQS 原理的理解。 +
- 如何实现线程安全? +
- 了解过消息中间件吗?说一下使用场景 +
- write pos ~ checkpoint 之间的部分(图中红色部分):记录新的更新操作; @@ -5772,8 +6038,8 @@ binlog,等之后事务提交的时候,会将该事物执行过程中产生 是全量日志,保存了所有数据变更的情况,可以恢复整个数据库所有数据;
- 写入 Binlog:数据修改 -> 主库写 binlog 日志 -> commit 事务 -> 持久化本地数据 -> 提交事务成功; @@ -5792,8 +6058,8 @@ binlog,并更新从库中的数据。
- 半同步复制:只要数据成功复制到任意一个从库上,主库的事务线程就可以返回给客户端;
- 图中的 write,把日志写入到 binlog 文件(文件系统的 page cache 里),但是并没有把数据持久化到磁盘; @@ -5818,8 +6084,8 @@ fsync; 个阶段,分别是准备阶段和提交阶段(不是 commit 语句),每个阶段都由协调者和参与者共同完成。
- 若不在,将数据页从磁盘读入到 buffer pool;
- 若更新前与更新后数据不同,调用 存储引擎 执行更新操作;
- 开启事务,记录 undo log,同时将 Undo 页的修改记录存在 redo log -中; -
- 存储引擎更新数据,并标记数据页为脏页,同时将数据页的修改记录存在
-redo log 中;
-
-
-
- 为了减少磁盘I/O,脏页选择合适时间持久化到硬盘,持久化后删除对应的 -redo log; -
- - 记录更新完毕,记录 binlog 至 binlog cache; -
- 事务提交,将 redolog binlog 持久化到硬盘(两阶段提交;组提交)
-
-
-
- prepare 阶段 -
- commit 阶段 -
-
- - Redo log 满了; -
- BufferPool满了; -
- MySQL空闲; -
- 后台线程定时 checkpoint; -
- 事务提交时(一般不选); -
- Free List (空闲页链表),管理空闲页; -
- Flush List (脏页链表),管理脏页; -
- LRU -List,管理脏页+干净页,将经常查询或可能将要查询的数据缓存在其中,而不常查询的数据就淘汰出去; -
- Free Page(空闲页),表示此页未被使用,位于 Free 链表; -
- Clean Page(干净页),表示此页已被使用,但是页面未发生修改,位于LRU -链表。 -
- Dirty -Page(脏页),表示此页「已被使用」且「已经被修改」,其数据和磁盘上的数据已经不一致。当脏页上的数据写入磁盘后,内存数据和磁盘数据一致,那么该页就变成了干净页。脏页同时存在于 -LRU 链表和 Flush 链表。 -
- 预读失效:加载访问数据页时,提前加载进来的相邻数据页,即预读页,但后续并没有访问预读页; -
- Buffer Pool 污染:某一个 SQL 语句扫描了大量的数据时,将 Buffer Pool
-里的所有页都替换出去,导致大量热数据被淘汰了,后续热数据被访问时会产生大量磁盘
-I/O;
-
-
-
- 索引失效批量扫描的时候会出现污染 -
- - 将 LRU 划分了 2 个区域:old 区域 和 young -区域。划分这两个区域后,预读的页就只需要加入到 old -区域的头部,当页被真正访问的时候,才将页插入 young 区域的头部。 -
- 只有同时满足被访问与在 old 区域停留时间超过
-
innodb_old_blocks_time
秒两个条件,才会被插入到 -young 区域头部
- - young 区域优化:为了防止 young 区域节点频繁移动到头部。young -区域前面 1/4 被访问不会移动到链表头部,只有后面的 3/4被访问了才会 -
- 大部分操作都在内存中完成(制约 Redis 性能的瓶颈并不是 -CPU,而是内存和网络带宽) -
- 避免了多线程之间的竞争 -
- I/O 多路复用机制 -
删去已经无意义的日志;
-重写操作由后台子进程完成,子进程共享父进程内存(为什么不用线程?父子进程以只读的方式共享数据,如果任意一方修改了该共享内存,父子进程会有独立的数据副本,即写时复制,注意这里只会复制主进程修改的物理内存数据,没修改物理内存还是与子进程共享的。而线程共享内存需要加锁);
-AOF -重写缓冲区用于保存重写子进程启动后,新产生的AOF日志,并在重写结束后追加到新的AOF文件中;
-- bgsave 命令创建子进程来做生成 RDB 文件的工作,是异步工作的 -
- 设置复制延迟限制
min-slaves-max-lag
- - 客户端降级措施,当 master 不可写,就把数据存到本地或 kafka -中等待主节点正常后再消费 -
- 哪个哨兵节点判断主节点为「客观下线」,这个哨兵节点就是候选者,所谓的候选者就是想当 -Leader 的哨兵。 -
- 候选者会向其他哨兵发送命令,表明希望成为 Leader
-来执行主从切换,并让所有其他哨兵对它进行投票。Raft 算法选择哨兵 Leader:
-
-
-
- 第一,拿到半数以上的赞成票; -
- 第二,拿到的票数同时还需要大于等于哨兵配置文件中的 quorum 值。 -
- - 第一步:在已下线主节点(旧主节点)属下的所有「从节点」里面,挑选出一个从节点,并将其转换为主节点,选择的规则:
-
-
-
- 过滤掉已经离线的从节点; -
- 过滤掉历史网络连接状态不好的从节点; -
- 将剩下的从节点,进行三轮考察:优先级、复制进度、ID -号。在每一轮考察过程中,如果找到了一个胜出的从节点,就将其作为新主节点。 -
- - 第二步:让已下线主节点属下的所有「从节点」修改复制目标,修改为复制「新主节点」; -
- 第三步:将新主节点的 IP -地址和信息,通过「发布者/订阅者机制」通知给客户端; -
- 第四步:继续监视旧主节点,当这个旧主节点重新上线时,将它设置为新主节点的从节点; -
- 同一个分区内的 Redis -节点之间的数据完全一样,多个节点保证了数据有多份副本冗余保存,且可以提供高可用保障; -
- 不同分片之间的数据不相同; -
- 通过水平增加多个分片的方式,可以实现整体集群容量的扩展; -
- 开启事务,记录 undo log,同时将 Undo 页的修改记录存在 redo log +中; +
- 存储引擎更新数据,并标记数据页为脏页,同时将数据页的修改记录存在
+redo log 中;
-
-
- 切片 slot 槽,共有16384个槽位; -
- 数据 key 通过 “CRC16 算法 + 16384 取模”,得到对应存储的哈希槽; -
- 数据存储在该槽位对应的 Redis -分区中,每个分区都有独立的主从哨兵保证高可用; -
一致性Hash
-虚拟节点
-缓存
-缓存雪崩、击穿、穿透
-缓存穿透:大量请求了缓存和数据库里都没有的数据,请求穿透缓存和数据库
+ - 为了减少磁盘I/O,脏页选择合适时间持久化到硬盘,持久化后删除对应的 +redo log; + +
- 记录更新完毕,记录 binlog 至 binlog cache; +
- 事务提交,将 redolog binlog 持久化到硬盘(两阶段提交;组提交)
-
-
- 参数校验:参数不合法直接抛出异常 -
- 缓存无效 key:适用于 key 变化不频繁 -
- 布隆过滤器:校验 Key -是否合法(有误差,可能会把未存的值当作已有,即不合法的 key -当作合法的) -
- 接口限流:固定窗口算法、滑动窗口算法、漏桶算法、令牌桶算法 +
- prepare 阶段 +
- commit 阶段 +
- - 热点数据永不过期或过期时间长 -
- 预热热点数据:定时任务预热(定时触发缓存预热的逻辑,将数据库中的热点数据查询出来并存入缓存中)、kafka -异步预热(将数据库中的热点数据的主键或者 ID -发送到消息队列中,然后由缓存服务消费消息队列中的数据,根据主键或者 ID -查询数据库并更新缓存) -
- 访问数据库互斥锁 +
- Redo log 满了; +
- BufferPool满了; +
- MySQL空闲; +
- 后台线程定时 checkpoint; +
- 事务提交时(一般不选);
- Redis 集群 -
- 限流 -
- 多级缓存:本地缓存+Redis -
- 热点数据失效时间长 -
- 预热热点数据 +
- Free List (空闲页链表),管理空闲页; +
- Flush List (脏页链表),管理脏页; +
- LRU +List,管理脏页+干净页,将经常查询或可能将要查询的数据缓存在其中,而不常查询的数据就淘汰出去;
- 消息队列确保缓存删除成功 -
- 订阅 MySQL 的 binlog,数据修改时删除缓存 +
- Free Page(空闲页),表示此页未被使用,位于 Free 链表; +
- Clean Page(干净页),表示此页已被使用,但是页面未发生修改,位于LRU +链表。 +
- Dirty +Page(脏页),表示此页「已被使用」且「已经被修改」,其数据和磁盘上的数据已经不一致。当脏页上的数据写入磁盘后,内存数据和磁盘数据一致,那么该页就变成了干净页。脏页同时存在于 +LRU 链表和 Flush 链表。
- 单机的 redis 是 cp 的,但是集群情况下 redis 是 ap 的,所以运行 -Redisson -的节点必须是主节点,不能有从节点,防止主节点加锁成功未同步从节点就宕机,而客户端却收到加锁成功,导致数据不一致。 -
- 预读失效:加载访问数据页时,提前加载进来的相邻数据页,即预读页,但后续并没有访问预读页; +
- Buffer Pool 污染:某一个 SQL 语句扫描了大量的数据时,将 Buffer Pool
+里的所有页都替换出去,导致大量热数据被淘汰了,后续热数据被访问时会产生大量磁盘
+I/O;
-
-
- 由于 Redis 单线程处理,大 Key -的增删改查都很耗时,会导致工作线程阻塞、客户响应超时、网络传输阻塞; -
- 内存分布不均,集群场景下 slot 槽数据量不均; -
- 持久化阻塞主线程,会主线程的两个阶段耗时增加:创建子进程复制页表结构、修改共享数据写时复制; +
- 索引失效批量扫描的时候会出现污染 +
- - 拆分大 key; -
- 及时/定时清理大 key,unlink 异步删除代替 del 同步删除; +
- 将 LRU 划分了 2 个区域:old 区域 和 young +区域。划分这两个区域后,预读的页就只需要加入到 old +区域的头部,当页被真正访问的时候,才将页插入 young 区域的头部。 +
- 只有同时满足被访问与在 old 区域停留时间超过
+
innodb_old_blocks_time
秒两个条件,才会被插入到 +young 区域头部
+ - young 区域优化:为了防止 young 区域节点频繁移动到头部。young +区域前面 1/4 被访问不会移动到链表头部,只有后面的 3/4被访问了才会
- 一致性(Consistency):所有节点访问同一份最新的数据副本 -
- 可用性(Availability):非故障的节点在合理的时间内返回合理的响应(不是错误或者超时的响应) -
- 分区容错性(Partition -Tolerance):分布式系统出现网络分区的时候,仍然能够对外提供服务。 +
- Java 编译器 Javac 是用 Java 实现的,用于将 .java 文件编译成字节码 +.class +
- .class 通过解释器对这些字节码进行解释执行 +
- Java 的运行环境 JVM 如 HotSpot VM,实现了其跨平台的特性
- 缓存:缓存是一种提高数据读取性能的技术,通过在内存中存储经常访问的数据,可以减少对数据库或者其他存储系统的访问,从而提高系统的响应速度。缓存可以应用在多个层次,例如浏览器缓存、CDN -缓存、反向代理缓存、应用缓存等。 -
- 降级:降级是在系统压力过大或者部分服务不可用的情况下,暂时关闭一些非核心的服务,以保证核心服务的正常运行。降级可以在多个层次进行,例如页面降级、功能降级、服务降级等。 -
- 限流:限流是一种控制系统处理请求的速率的技术,以防止系统过载。限流可以通过多种算法实现,例如固定窗口、滑动窗口、漏桶算法、令牌桶算法等。 +
- 多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法(A +a=new B(),A是父类,B是子类) +
- 静态绑定:对象属性和 static private final +修饰的对象方法(构造函数),哪里声明,哪里使用 +
- 动态绑定:运行时 JVM +实现绑定。若子类实现了这个方法,则调用子类的内存地址,若没有则调用当前对象(父类)的方法。只能调用父类的属性,虽然实际实现的是子类,如果父类没有这个属性,那就无法调用。如果要获取子类属性,就要重写子类方法获取该属性,前提是这个方法在父类中同样存在。
- Client Stub -主要是将客户端的请求参数、请求服务地址、请求服务名称做一个封装,并发送给 -Server Stub -
- Server Stub 主要用于接收 Client Stub 发送的数据并解析,去调用 Server -端的本地方法 +
- 数据库查询返回结果为 Null,无法拆箱 +
- 三目运算符可能出现问题:flag ? 0 : i(应使用 flag ? new Integer(0) : +i)
开发人员使用方没有配置接口的 protocol -字段,而是写在接口实现类上
-
+dubbo-3.0.4
框架:- JDK
+动态代理:通过生成一个实现被代理类接口的对象来拦截被代理类的方法调用
-
-
- 若没有指定 protocol 字段,会创建服务端提供的所有协议的 invoker -
- EasyREST 包
createClientInvoker
创建 REST 协议的 invoker -时需要 HttpMethod 参数
- - 由于注解写在实现类而不是接口上面,导致消费端无法共享相应的 REST -配置信息,即 HttpMethod 为 null,因此 RESTClient 创建失败 -
- 在服务更新过程中,客户端每次都是全量更新注册中心的服务端信息,这个过程中如果
-invoker
-一直注册失败,会不断将失败的
Client
存到List<ResteasyClient>
中,如果有 -n 台机器需要依次更新,这时客户端的数组中会存 n*n -个失败的连接实例,从而导致 OOM
+ - 封装:Proxy.newProxyInstance() 指定 ClassLoader 对象和一组 +interface +
- 调用:InvocationHandler 接口 invoke 方法
- - CGLIB
+动态代理:通过生成一个被代理类的子类来拦截被代理类的方法调用(字节码实现,不能被
+final 修饰,编译速度慢,运行速度快)
-
-
- ResteasyClient 对象由 RestProtocol 协议对象持有,针对没有创建成功 -invoker 的场景应把其对应的 ResteasyClient 销毁掉 +
- 封装:Enhancer 类 +
- 调用:MethodInterceptor 接口 intercept 方法 +
- - 用
Map<String, ResteasyClient>
代替 -List<ResteasyClient>
,同一个服务端只存一次
- - 用
WeakHashMap<String, ResteasyClient>
自动回收不用的 -ResteasyClient(参考pr)
+ - JDK:运行时动态解析,无法应用一些 JVM 优化 +
- CGLib:ASM 开源包,代理对象类的 class +文件加载时,修改其字节码生成代理子类(ASM +是在编译期处理字节码的,可以认为是一种编译期的 AOP 技术)
- 直接通过
Executors
构造 固定数量+无限长等待队列 -线程池,该线程池在共享的无界队列上操作的固定数量的线程。在任何时候,最多nThreads线程将处于活动处理任务状态。如果在所有线程都处于活动状态时提交额外的任务,它们将在队列中等待,直到有线程可用。
+ - 因为 JDK 动态代理类已经继承了 Proxy +这个类,所以只能通过接口来与被代理类建立联系(两个类建立起联系,一是继承的关系【jdk已经不能通过这个方式了,因为java仅支持单继承】,另一种就是实现同一个接口【JDK动态代理选这种】),所以必须要求被代理类也得实现一个接口
- 并发调用 Rpc 接口获取返回值 +
- sort(list) +
- reverse(list) +
- binarySearch(list, target)
- 数据查询任务中存在父子调用关系,数据查询任务同步调用 Redis
-查询缓存和 Rpc 调用微服务获得数据。如果本地 Redis
-缓存中能获得数据,就直接返回缓存值并取消 Rpc 调用
-
future.cancel(true)
。
+ - max(list) +
- sort(array, (o1, o2)->o1-o2) +
- copyOf(array, Length) +
- binarySearch(array, value) +
- fill(array, value)
- 父子任务分开并发执行,耗时的异步线程应做好线程池隔离 -
CompletableFuture.anyOf(task1,tsak2)
-优先取先完成的那个任务的返回值
-- Comparator 类级别
-
-
- 转换过程中会根据具体的
protocol
创建对应的 -invoker
,如 Rest 和 Dubbo 需要解析不同的参数。
-
服务注册地址发生改变时:会通知给消费者,dubbo -协议里面明确讲到服务发生改变会全量更新所有客户端的缓存
-Netty 数据传输
--
-在网络通信中,序列化和编码通常是结合使用的。序列化将对象转换为字节流,编码将字节流转换为网络传输所需的格式(如按照协议规定的格式进行编码)。在接收端,解码将网络传输的数据解析为原始的格式(如解码成对象),以便进行进一步的处理和使用。
-Netty 是一个高性能事件驱动型非阻塞 IO 框架:
+ - 转换过程中会根据具体的
- 针对不同的比较,单独定义一个比较类 +
- int compare(T o1, T o2);
-
-
- 提供了 ByteBuf 容器,更方便地处理数据。
ByteBuf
-在重写编解码器的 encoder/decoder 方法中作为参数传入。
- - channel -
编码:先序列化,再压缩,最后写进 ByteBuf 对象中
-解码:从 ByteBuf 对象中读,然后转成我们需要的对象
-代理模式
-静态代理
--
-静态代理中,我们对目标对象的每个方法的增强都是手动完成的(后面会具体演示代码),非常不灵活(比如接口一旦新增加方法,目标对象和代理对象都要进行修改)且麻烦(需要对每个目标类都单独写一个代理类)。 -实际应用场景非常非常少,日常开发几乎看不到使用静态代理的场景。
-从 JVM 层面来说, -静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的 class -文件。
-静态代理的步骤
+ - 提供了 ByteBuf 容器,更方便地处理数据。
- 返回值为正数,交换 o1 o2 的顺序 +
- 返回值为负数或零,不需要调整 +
- 返回升序 o1-o2,降序 o2-o1 + + +
- Comparable 方法级别
-
-
- 定义一个接口及其实现类; -
- 创建一个代理类同样实现这个接口 -
- 将目标对象注入进代理类,然后在代理类的对应方法调用目标类中的对应方法。这样的话,我们就可以通过代理类屏蔽对目标对象的访问,并且可以在目标方法执行前后做一些自己想做的事情。 +
- 若一个类实现了Comparable接口,就意味着“该类支持排序”,可以用Arrays.sort()排序 +
- public int compareTo(T o); +
- - 定义一个接口及其实现类; -
- 自定义 InvocationHandler 并重写 invoke 方法,在 invoke -方法中我们会调用原生方法(被代理类的方法)并自定义一些处理逻辑; -
- 通过
-
Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
-方法创建代理对象;
+ - 共同点
+
-
+
- 都不能被实例化 +
- 都可以包含抽象方法 +
- 方法可以有默认实现的 +
+ - 区别
+
-
+
- 接口主要用于对类的行为进行约束,你实现了某个接口就具有了对应的行为。抽象类主要用于代码复用,强调的是从属关系。 +
- 一个类只能继承一个类,但是可以实现多个接口。 +
- 接口中的成员变量只能是 public static final +类型的,不能被修改且必须有初始值,而抽象类的成员变量默认 +default,可在子类中被重新定义,也可被重新赋值。 +
+ - 接口中的所有成员变量都默认是由public static final修饰的 +
- 接口中的所有方法都默认是由public abstract修饰的 +
- 接口没有构造方法 +
- 实现接口的类中必须提供接口中所有方法的具体实现内容 +
- 多个无关的类可以实现同一个接口 +
- 一个类可以实现多个无关的接口 +
- 与继承关系类似,接口与实现类之间存在多态性 +
- 接口可以继承多个接口,使用extends关键字 +
- Java8 +后,接口可以拥有普通方法,实现类不需要重写,可以被实现类继承
- 在实例化 bean 之后,postProcessAfterInitialization 方法被调用。 -
- 对于每个 bean 类的字段,检查是否标记了 @RpcReference 注解。 -
- 如果发现标记了 @RpcReference -注解的字段,根据注解中的信息创建相应的 RpcServiceConfig 对象。 -
- 通过 RpcClientProxy 创建了一个代理对象 -clientProxy,这个代理对象实现了 declaredField.getType() -所表示的接口,这个接口可能就是 HelloService 接口或其它接口,取决于 -helloService 字段的类型。 -
- 这个代理对象 clientProxy 会在方法调用时委托给 RpcClientProxy 的 -invoke 方法,该方法负责处理远程调用的逻辑。 -
- 通过反射设置 clientProxy 到 HelloController 类的 helloService -字段上,替换了原来的字段值。 -
- 序列化:将数据结构或对象转化为二进制字节流 -
- 反序列化:将在序列化过程中生成的二进制字节流转化为数据结构或对象 +
- 只能在构造器中使用 +this(参数列表);即在一个构造器中访问本类的另外一个构造器。 +
- 显示使用 this() 时,默认的 super() 就被覆盖 +
- this(参数列表)和 super(参数列表)在构造器中有且只能存在一个。 +
- 若在构造器中使用 this(参数列表),则此语句只能位于构造器第一行
- 单例 Singleton、多例/原型 Prototype Bean +
- 一致性(Consistency):所有节点访问同一份最新的数据副本 +
- 可用性(Availability):非故障的节点在合理的时间内返回合理的响应(不是错误或者超时的响应) +
- 分区容错性(Partition +Tolerance):分布式系统出现网络分区的时候,仍然能够对外提供服务。
- 缓存:缓存是一种提高数据读取性能的技术,通过在内存中存储经常访问的数据,可以减少对数据库或者其他存储系统的访问,从而提高系统的响应速度。缓存可以应用在多个层次,例如浏览器缓存、CDN +缓存、反向代理缓存、应用缓存等。 +
- 降级:降级是在系统压力过大或者部分服务不可用的情况下,暂时关闭一些非核心的服务,以保证核心服务的正常运行。降级可以在多个层次进行,例如页面降级、功能降级、服务降级等。 +
- 限流:限流是一种控制系统处理请求的速率的技术,以防止系统过载。限流可以通过多种算法实现,例如固定窗口、滑动窗口、漏桶算法、令牌桶算法等。 +
- Aware 其实就是一个标识;只有满足 Aware -规范或者其子类规范的才能进行相关的赋值操作,这样做的话可以少写很多判断,并且可以在一个地方进行统一的判断赋值; -
- BeanPostProcessor -前置处理器的关键实现类:ApplicationContextAwareProcessor -
- BeanPostProcessor -后置处理器的关键实现类:AbstractAutoProxyCreator。这个方法负责帮我们创建代理,底层采用对象cglib -或动态代理【AOP其实就是 IOC -整体流程(Bean生命周期)里的一个扩展点】 -
- InitializingBean 接口中的 afterPropertiesSet -方法:在这个方法里面去编写我们的业务逻辑,以及进行相关的属性赋值等等 +
- Client Stub +主要是将客户端的请求参数、请求服务地址、请求服务名称做一个封装,并发送给 +Server Stub +
- Server Stub 主要用于接收 Client Stub 发送的数据并解析,去调用 Server +端的本地方法
- AbstractAutowireCapableBeanFactory 内的 initializeBean 调用了所有 -BeanPostProcessor 的实现类 -
- ApplicationContext 类型容器的内部维护了一个 BeanFactory -类型的容器(AnnotationConfigApplicationContext 的父类 -GenericApplicationContext 维护了一个 Bean -工厂实现类:DefaultListableBeanFactory) -
- DefaultListableBeanFactory:Spring 默认的 BeanFactory 实现 -
- DefaultSingletonBeanRegistry:DefaultListableBeanFactory -单例模式存储关系的地方 Map<String(BeanName),Object(instance)> -
- AbstractApplicationContext.refresh() 方法 +
开发人员使用方没有配置接口的 protocol +字段,而是写在接口实现类上
+dubbo-3.0.4
框架:-
-
- 配置了对 BeanFactoryPostProcessor 的实现 -postProcessBeanFactory(beanFactory) 和处理 -invokeBeanFactoryPostProcessors(beanFactory)。BeanFactoryPostProcessor -可以自定义 ApplicationContext 容器中的 BeanFactory -进行处理,在还没有对任何Bean进行实例化之前(ConfigurationClassPostProcessor -通过注解解析配置类;PropertySourcesPlaceholderConfigurer:xml配置文件中导入的 -properties 文件进行解析,并替换bean定义中的占位符) -
- 配置了对 BeanPostProcessor 的实现 +
- 若没有指定 protocol 字段,会创建服务端提供的所有协议的 invoker +
- EasyREST 包
createClientInvoker
创建 REST 协议的 invoker +时需要 HttpMethod 参数
+ - 由于注解写在实现类而不是接口上面,导致消费端无法共享相应的 REST +配置信息,即 HttpMethod 为 null,因此 RESTClient 创建失败 +
- 在服务更新过程中,客户端每次都是全量更新注册中心的服务端信息,这个过程中如果
+invoker
+一直注册失败,会不断将失败的
Client
存到List<ResteasyClient>
中,如果有 +n 台机器需要依次更新,这时客户端的数组中会存 n*n +个失败的连接实例,从而导致 OOM
- (1-1)依赖注入:@Autowired;@Resource -
- 事务 @Transactional、@Configuration -
- (1-2)单例 Singleton、多例/原型 Prototype Bean -
- jvm类加载器classloader:bootstrap ext app 博客 -
- “约定优于配置”理念 -
- @EnableAutoConfiguration -
- 自动将一些配置类的bean注册进ioc容器 +
- ResteasyClient 对象由 RestProtocol 协议对象持有,针对没有创建成功 +invoker 的场景应把其对应的 ResteasyClient 销毁掉 +
- 用
Map<String, ResteasyClient>
代替 +List<ResteasyClient>
,同一个服务端只存一次
+ - 用
WeakHashMap<String, ResteasyClient>
自动回收不用的 +ResteasyClient(参考pr) - 一级缓存,缓存正常的 bean 实例 -
- 二级缓存,缓存还未进行依赖注入和初始化方法调用的 bean 实例 -
- 三级缓存,缓存 bean 实例的 ObjectFactory,用于解决 BeanPostProcessor -代理类时正确地依赖注入 +
- 直接通过
Executors
构造 固定数量+无限长等待队列 +线程池,该线程池在共享的无界队列上操作的固定数量的线程。在任何时候,最多nThreads线程将处于活动处理任务状态。如果在所有线程都处于活动状态时提交额外的任务,它们将在队列中等待,直到有线程可用。 - 由
DispatcherServlet
-从HandlerMappings
中匹配对应的Handler
。此时只是获取到了对应的Handler
,然后拿着这个Handler
去寻找对应的适配器,即:HandlerAdapter
:让固定参数的 -Servlet 处理方法调用灵活的 Handler 来处理;
- - 执行
Controller
处理业务逻辑, 执行完成之后返回一个 -ModeAndView
或 Json 格式数据;
+ - 并发调用 Rpc 接口获取返回值
- Docker -Compose:用于定义和运行多容器 Docker -应用程序的工具,使多个容器可以在隔离环境中一起运行; -
- Dockerfile:用来构建镜像的文本文件,包含了一条条构建镜像所需的指令和说明; -
- Docker -Machine:是一个简化 Docker -安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker;可以集中管理所有的 -docker 主机,比如快速的给 100 台服务器安装上 docker; +
- 数据查询任务中存在父子调用关系,数据查询任务同步调用 Redis
+查询缓存和 Rpc 调用微服务获得数据。如果本地 Redis
+缓存中能获得数据,就直接返回缓存值并取消 Rpc 调用
+
future.cancel(true)
。 - [-d] 后台运行容器 -
- [-p] 指定端口映射 -
- [-v] 映射主机文件卷 -
- [--name <NAME>] 命名容器 -
- [-e] 设置环境变量 +
- 父子任务分开并发执行,耗时的异步线程应做好线程池隔离 +
CompletableFuture.anyOf(task1,tsak2)
+优先取先完成的那个任务的返回值- [-a] 显示所有的容器,包括未运行的 +
- 转换过程中会根据具体的
protocol
创建对应的 +invoker
,如 Rest 和 Dubbo 需要解析不同的参数。 - [-f] 强制删除正在运行的容器 -
- [-v] 删除容器挂载的卷 +
- 提供了 ByteBuf 容器,更方便地处理数据。
ByteBuf
+在重写编解码器的 encoder/decoder 方法中作为参数传入。
+ - channel
- [-f] 指定要使用的 Dockerfile 路径 -
- [--rm] 设置镜像成功后删除中间容器 +
- 定义一个接口及其实现类; +
- 创建一个代理类同样实现这个接口 +
- 将目标对象注入进代理类,然后在代理类的对应方法调用目标类中的对应方法。这样的话,我们就可以通过代理类屏蔽对目标对象的访问,并且可以在目标方法执行前后做一些自己想做的事情。
- [-o <xxx.tar>] +
- 定义一个接口及其实现类; +
- 自定义 InvocationHandler 并重写 invoke 方法,在 invoke +方法中我们会调用原生方法(被代理类的方法)并自定义一些处理逻辑; +
- 通过
+
Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
+方法创建代理对象; - 在实例化 bean 之后,postProcessAfterInitialization 方法被调用。 +
- 对于每个 bean 类的字段,检查是否标记了 @RpcReference 注解。 +
- 如果发现标记了 @RpcReference +注解的字段,根据注解中的信息创建相应的 RpcServiceConfig 对象。 +
- 通过 RpcClientProxy 创建了一个代理对象 +clientProxy,这个代理对象实现了 declaredField.getType() +所表示的接口,这个接口可能就是 HelloService 接口或其它接口,取决于 +helloService 字段的类型。 +
- 这个代理对象 clientProxy 会在方法调用时委托给 RpcClientProxy 的 +invoke 方法,该方法负责处理远程调用的逻辑。 +
- 通过反射设置 clientProxy 到 HelloController 类的 helloService +字段上,替换了原来的字段值。 +
- [-i <xxx.tar>] 指定导入的文件 +
- 序列化:将数据结构或对象转化为二进制字节流 +
- 反序列化:将在序列化过程中生成的二进制字节流转化为数据结构或对象
- 集中化版本控制(CVCS)缺点
-
-
-
- 中央服务器的单点故障就无法协同工作 -
- 本地只有快照,项目整体和其变更历史只保存在服务器上 -
- - 分布式版本控制(DVCS)优点
-
-
-
- 代码仓库完整地镜像下来,包括完整的历史记录 -
- 用户在本地保存了所有改动,每一次的克隆都是对仓库的完整备份 -
- 可以指定和若干不同的远端代码仓库进行交互 -
- - 并行开发 -
- 完全分布式 -
- 速度快 -
- 数据量大 -
- 大多版本控制工具都是基于差异的,存储文件随时间变化的差异,而Git储存项目快照或索引 -
- Git 安全性优,只做增不做删;完整性好,使用SHA-1 哈希算法 -
- 文件的四种状态:已提交(committed)、已修改(modified)、已暂存(staged)、未跟踪(untracked) -
- 项目的三个阶段:工作目录、暂存区域以及 Git 仓库 -
- 工作流程:修改文件、暂存文件、将暂存区文件快照永久存在Git目录 -
- /etc/gitconfig 系统通用配置 git config --system -
- ~/.gitconfig 当前用户配置 git config --global -
- .git/config 当前项目配置 git config --local -
- [-b master]克隆指定分支 +
- 大部分操作都在内存中完成(制约 Redis 性能的瓶颈并不是 +CPU,而是内存和网络带宽) +
- 避免了多线程之间的竞争 +
- I/O 多路复用机制
- [-s] 简要文件状态信息 +
删去已经无意义的日志;
+重写操作由后台子进程完成,子进程共享父进程内存(为什么不用线程?父子进程以只读的方式共享数据,如果任意一方修改了该共享内存,父子进程会有独立的数据副本,即写时复制,注意这里只会复制主进程修改的物理内存数据,没修改物理内存还是与子进程共享的。而线程共享内存需要加锁);
+AOF +重写缓冲区用于保存重写子进程启动后,新产生的AOF日志,并在重写结束后追加到新的AOF文件中;
- [--staged] 显示暂存区和上一次提交的差异 +
- bgsave 命令创建子进程来做生成 RDB 文件的工作,是异步工作的
- 设置复制延迟限制
min-slaves-max-lag
+ - 客户端降级措施,当 master 不可写,就把数据存到本地或 kafka +中等待主节点正常后再消费 +
- 哪个哨兵节点判断主节点为「客观下线」,这个哨兵节点就是候选者,所谓的候选者就是想当 +Leader 的哨兵。 +
- 候选者会向其他哨兵发送命令,表明希望成为 Leader
+来执行主从切换,并让所有其他哨兵对它进行投票。Raft 算法选择哨兵 Leader:
-
-
- [ -L 200,300 <file>] 追踪某些行代码修改的历史 commit +
- 第一,拿到半数以上的赞成票; +
- 第二,拿到的票数同时还需要大于等于哨兵配置文件中的 quorum 值。 +
- [-f] 强制移除存在未提交修改的文件 -
- [ --cached] 文件保留在工作区中,从Git仓库和暂存区中删除 -
- 第一步:在已下线主节点(旧主节点)属下的所有「从节点」里面,挑选出一个从节点,并将其转换为主节点,选择的规则:
-
-
- [--soft] 回退到某个版本 -
- [--mixed] -默认,用于重置暂存区的文件与上一次的提交保持一致(取消暂存),工作区文件内容保持不变 -
- [--hard] -撤销工作区中所有未提交的修改内容,将暂存区与工作区都回到上一次版本,并删除之前的所有信息提交 +
- 过滤掉已经离线的从节点; +
- 过滤掉历史网络连接状态不好的从节点; +
- 将剩下的从节点,进行三轮考察:优先级、复制进度、ID +号。在每一轮考察过程中,如果找到了一个胜出的从节点,就将其作为新主节点。 +
+ - 第二步:让已下线主节点属下的所有「从节点」修改复制目标,修改为复制「新主节点」; +
- 第三步:将新主节点的 IP +地址和信息,通过「发布者/订阅者机制」通知给客户端; +
- 第四步:继续监视旧主节点,当这个旧主节点重新上线时,将它设置为新主节点的从节点; -
- [.] 放弃所有工作区的修改 -
- [-f] 放弃工作区和暂存区的所有修改 -
- [<branch-name>] 从当前分支切换到指定的分支 -
- [-b <local_new_branch_name> <remote_new_branch_name>] -将远程仓库里指定的分支拉取到本地,并在本地创建一个分支与指定远程仓库分支关联起来,并切换到新建的本地分支中 +
- 同一个分区内的 Redis +节点之间的数据完全一样,多个节点保证了数据有多份副本冗余保存,且可以提供高可用保障; +
- 不同分片之间的数据不相同; +
- 通过水平增加多个分片的方式,可以实现整体集群容量的扩展;
- [-v] 列出当前仓库中已配置的远程仓库,并显示它们的 URL -
- [add <remote_name> <remote_url>] -添加远程仓库,指定一个远程仓库的名称和 URL,将其添加到当前仓库中 -
- [remane <old_name> <new_name>] -将已配置的远程仓库重命名 -
- [show <remote_name>] 显示指定远程仓库的详细信息,包括 URL -和跟踪分支 -
- [remove <remote_name>] 从当前仓库中删除指定的远程仓库 -
- [
] 修改指定远程仓库的 URL
+ - 切片 slot 槽,共有16384个槽位; +
- 数据 key 通过 “CRC16 算法 + 16384 取模”,得到对应存储的哈希槽; +
- 数据存储在该槽位对应的 Redis +分区中,每个分区都有独立的主从哨兵保证高可用;
- [--all] 获取远程的所有分支 +
- 参数校验:参数不合法直接抛出异常 +
- 缓存无效 key:适用于 key 变化不频繁 +
- 布隆过滤器:校验 Key +是否合法(有误差,可能会把未存的值当作已有,即不合法的 key +当作合法的) +
- 接口限流:固定窗口算法、滑动窗口算法、漏桶算法、令牌桶算法
[<remote_name> -<local_branch_name>:<remote_branch_name>]
-[<remote_name> --delete <branch_name>] -删除远程分支
-[-u <remote_name> --all] -本地的仓库和远程仓库进行关联
-[--set-upstream <remote_repository> -<local_branch_name>] 将本地分支与远程分支关联
-[--force] 强制提交,会覆盖所有 behind 的提交
+- 热点数据永不过期或过期时间长 +
- 预热热点数据:定时任务预热(定时触发缓存预热的逻辑,将数据库中的热点数据查询出来并存入缓存中)、kafka +异步预热(将数据库中的热点数据的主键或者 ID +发送到消息队列中,然后由缓存服务消费消息队列中的数据,根据主键或者 ID +查询数据库并更新缓存) +
- 访问数据库互斥锁
- [-l <通配符>] 查询某些对应标签 -
- [<version>] 轻量标签(提交校验和存储到一个文件中) -
- [-a <version> -m <comment>] -创建附注标签(数据库中的一个完整对象, 可以被校验) -
- [-d] 删除标签 +
- Redis 集群 +
- 限流 +
- 多级缓存:本地缓存+Redis +
- 热点数据失效时间长 +
- 预热热点数据
- [-c] 创建一个新分支并切换到该分支 +
- 消息队列确保缓存删除成功 +
- 订阅 MySQL 的 binlog,数据修改时删除缓存
- [<branch_name>] 创建本地分支 -
- [-b <branch_name>] 创建本地分支并切换 -
- [-v] 每个分支的最后一次提交 -
- [-vv] 跟踪信息 -
- [-r] 查看远程分支 -
- [-D <branch_name>] 删除分支 -
- [--set-upstream-to <remotename>/<remote_branch> -<local_branch>] -跟踪远程分支。在本地新建一个分支后,需要做远程分支关联,目的是在执行git -pull, git push操作时就不需要指定对应的远程分支 -
- [--merged --no-merged] 合并/未合并到当前分支的其他分支 -
- [-m <old_branch_name> <new_branch_name>] 改名 +
- 单机的 redis 是 cp 的,但是集群情况下 redis 是 ap 的,所以运行 +Redisson +的节点必须是主节点,不能有从节点,防止主节点加锁成功未同步从节点就宕机,而客户端却收到加锁成功,导致数据不一致。
- [list] 列出所有贮藏 -
- [apply] 恢复贮藏 +
- 由于 Redis 单线程处理,大 Key +的增删改查都很耗时,会导致工作线程阻塞、客户响应超时、网络传输阻塞; +
- 内存分布不均,集群场景下 slot 槽数据量不均; +
- 持久化阻塞主线程,会主线程的两个阶段耗时增加:创建子进程复制页表结构、修改共享数据写时复制;
- Git 中 HEAD是一个指针,指向当前工作位置 -
- git mergetool 图形化冲突解决工具 -
- 有 Git 特性演化出的开发工作流:长期分支、主题分支 -
- 设置 menu 菜单栏 -
- 打开 code 代码复制 +
- 拆分大 key; +
- 及时/定时清理大 key,unlink 异步删除代替 del 同步删除;
- 早起,立即开始工作。早起会立即给自己一个潜意识的信号,让自己在那天努力工作。 -
- 制定一个行动计划。用 10 -分钟来筹划接下来的几个小时要做的事情,让事情可以推动自己前进。 -
- 提前完成一连串的工作。清晨就处理完当天最紧要的工作,白天的时间就会显得从容,这也会产生积极的启动,这将持续一整天。 +
- 单例 Singleton、多例/原型 Prototype Bean
- 避免参与式的休息。短视频,游戏,微信等会占据头脑的东西都会打断做事的势头。 -
- 专注于放松。走一小段路、喝一杯水或伸展身体都是不错的选择,可以很容易地从休息中抽身出来回去工作。 +
- Aware 其实就是一个标识;只有满足 Aware +规范或者其子类规范的才能进行相关的赋值操作,这样做的话可以少写很多判断,并且可以在一个地方进行统一的判断赋值; +
- BeanPostProcessor +前置处理器的关键实现类:ApplicationContextAwareProcessor +
- BeanPostProcessor +后置处理器的关键实现类:AbstractAutoProxyCreator。这个方法负责帮我们创建代理,底层采用对象cglib +或动态代理【AOP其实就是 IOC +整体流程(Bean生命周期)里的一个扩展点】 +
- InitializingBean 接口中的 afterPropertiesSet +方法:在这个方法里面去编写我们的业务逻辑,以及进行相关的属性赋值等等
- 使任务处于活动状态。将被动学习任务转换为主动学习任务,如写提纲、记录重点。 -
- 穿插活动任务。将被动学习与主动任务穿插在一起,以定期提高注意力,如表达自己见解、用自己的话复述一遍。 +
- AbstractAutowireCapableBeanFactory 内的 initializeBean 调用了所有 +BeanPostProcessor 的实现类 +
- ApplicationContext 类型容器的内部维护了一个 BeanFactory +类型的容器(AnnotationConfigApplicationContext 的父类 +GenericApplicationContext 维护了一个 Bean +工厂实现类:DefaultListableBeanFactory) +
- DefaultListableBeanFactory:Spring 默认的 BeanFactory 实现 +
- DefaultSingletonBeanRegistry:DefaultListableBeanFactory +单例模式存储关系的地方 Map<String(BeanName),Object(instance)> +
- AbstractApplicationContext.refresh() 方法
+
-
+
- 配置了对 BeanFactoryPostProcessor 的实现 +postProcessBeanFactory(beanFactory) 和处理 +invokeBeanFactoryPostProcessors(beanFactory)。BeanFactoryPostProcessor +可以自定义 ApplicationContext 容器中的 BeanFactory +进行处理,在还没有对任何Bean进行实例化之前(ConfigurationClassPostProcessor +通过注解解析配置类;PropertySourcesPlaceholderConfigurer:xml配置文件中导入的 +properties 文件进行解析,并替换bean定义中的占位符) +
- 配置了对 BeanPostProcessor 的实现 +
- (1-1)依赖注入:@Autowired;@Resource +
- 事务 @Transactional、@Configuration +
- (1-2)单例 Singleton、多例/原型 Prototype Bean +
- jvm类加载器classloader:bootstrap ext app 博客 +
保证休息,应对大量工作任务的办法是保证自己有休息时间。如果你白天不好好工作,却逼迫自己整夜学习的话,你很容易就会筋疲力尽的。无论压力再大任务再多,都要保证休息时间,一颗清醒的大脑决定了工作的质量。
-使用时间分块法或每周/每日目标法,将工作和生活清晰地分离开,好好工作好好玩。
+- “约定优于配置”理念 +
- @EnableAutoConfiguration +
- 自动将一些配置类的bean注册进ioc容器 +
- 一级缓存,缓存正常的 bean 实例 +
- 二级缓存,缓存还未进行依赖注入和初始化方法调用的 bean 实例 +
- 三级缓存,缓存 bean 实例的 ObjectFactory,用于解决 BeanPostProcessor +代理类时正确地依赖注入
- 由
DispatcherServlet
+从HandlerMappings
中匹配对应的Handler
。此时只是获取到了对应的Handler
,然后拿着这个Handler
去寻找对应的适配器,即:HandlerAdapter
:让固定参数的 +Servlet 处理方法调用灵活的 Handler 来处理;
+ - 执行
Controller
处理业务逻辑, 执行完成之后返回一个 +ModeAndView
或 Json 格式数据;
+
PriorityQueue
- + LLM 应用开发实践diff --git a/-developer/Java-Interview/index.html b/-developer/Java-Interview/index.html index 518abbe..98ca552 100644 --- a/-developer/Java-Interview/index.html +++ b/-developer/Java-Interview/index.html @@ -21,13 +21,13 @@ - + - - + + @@ -37,10 +37,10 @@ - + -Java 面试常见问题和知识点 | 闻 +开发面试常见问题和知识点 | 闻 @@ -140,7 +140,7 @@- +@@ -203,12 +203,12 @@ - +- Java 面试常见问题和知识点 + 开发面试常见问题和知识点
@@ -219,14 +219,14 @@发表于 - + 更新于 - + @@ -248,22 +248,63 @@
-
Java-basic
-JVM
+@@ -280,13 +321,13 @@Knowledge
+Java
+JVM
+JUC
+MySQL
+Redis
+消息队列
+OS
+进程线程
+零拷贝
+【传统文件传输】磁盘缓冲区 => 内核缓冲区 => 用户缓冲区 => +Socket 缓冲区 => 网卡缓冲区,所有都由 CPU 控制;
+【DMA 拷贝】 基于 DMA 控制器而不是 CPU 实现 +“将数据从磁盘控制器缓冲区转移至内核缓冲区中”,与硬件设备之间的数据搬运工作从 +CPU 转交给 DMA 控制器;
+【零拷贝】
+mmap + write
+用户态直接共享内核的缓冲区,不需要再存入用户缓冲区,减少一次数据拷贝的消耗;sendfile
+调用一次内核命令,数据直接从内核缓冲区复制到 Socket +缓冲区,而不经过用户区,减少一次数据拷贝和两次上下文切换的消耗;Zero-copy
+网卡控制器直接读取内核缓冲区中的数据,实现最高效的传输,应用于 Nginx 和 +Kafka;【PageCache】内核缓冲区,缓存和预读磁盘数据,以提升磁盘读取速度;大文件传输不应采用 +PageCache,而是基于异步和直接 IO;
+网络模型
+【优化路线】子进程 => 子线程 => 线程池 => IO多路复用
+【select/poll】采用 BitsMap 或链表的形式储存所有 Socket +集合,每次检查都需要在内核态遍历文件描述符集合,以找到可读或可写的 +Socket;在用户态和内核态之间拷贝整一个集合,在用户态处理应用任务,在内核态检查是否有事件产生;
+【epoll】在内核中使用红黑树跟踪所有待检测的文件描述符,避免每次都要遍历所有 +Socket +集合;基于事件驱动,采用回调函数,每次都只需要从就绪任务链表中取已准备好的 +Socket;
+网络
+【TCP 四次握手三次挥手】
+Questions
+Java
+JVM
JUC
+JUC
中间件
+MySQL
+Redis
+消息队列
OS
+进程线程+零拷贝+网络模型
+网络
+Answer
中间件
diff --git a/-developer/MySQL/index.html b/-developer/MySQL/index.html index 46afae2..a771c27 100644 --- a/-developer/MySQL/index.html +++ b/-developer/MySQL/index.html @@ -291,8 +291,8 @@MySQL 数据文件
中每一张表的数据都存放在一个独立的 .ibd 文件。表空间文件的结构
- -+ +
InnoDB 行格式
共有 Redundant、Compact、Dynamic、Compressed 四种,下图时 Compact 行格式的结构
@@ -300,8 +300,8 @@InnoDB 行格式
InnoDB 页格式
InnoDB 的数据是按「数据页」为单位来读写的,数据页的默认大小是 16KB
- -+ +
@@ -784,8 +784,8 @@ 重做日志文件组
对应的记录也就没用了,这时候我们需要擦除这些旧记录,以腾出空间记录新的更新操作。重做日志文件组由有 2 个 redo log 文件组成,以循环写的方式工作,从头开始写,写到末尾就又回到开头,相当于一个环形。 - -+ +
归档日志 Bin log
是全量日志,保存了所有数据变更的情况,可以恢复整个数据库所有数据;主从复制
- -+ +
主从复制
binlog 刷盘
- -+ +
两阶段提交
个阶段,分别是准备阶段和提交阶段(不是 commit 语句),每个阶段都由协调者和参与者共同完成。内部 XA 事务
- -+ +
为了保证这两个日志的一致性,MySQL 使用了内部 XA 事务。内部 XA 事务由 binlog 作为协调者,存储引擎是参与者,可以实现跨数据库事务。将 redo log 的写入拆成了两个状态:prepare 和 @@ -948,15 +948,15 @@
内存
每当需要从磁盘中加载一个页到 Buffer Pool 中时,就从 Free链表中取一个空闲的缓存页,并且把该缓存页对应的控制块的信息填上,然后把该缓存页对应的控制块从 Free 链表中移除
- -+ +
Flush 链表:使用链表结构,快速找到脏页;(结构类似于 Free 链表)
脏页落盘时,后台线程遍历 Flush 链表
提高缓存命中率
Buffer Pool 有三种页和链表用来管理数据
- -+ +
- +数据结构和算法 -/Java-Algorithm/ -算法 - 链表
-快慢指针
-链表倒数第n个数
-分治法
-排序
-二分查找
-【1】目标不存在于数组中,找第一个大于它的下标
-【2】有多个目标存在于数组中,找第一个等于它的下标
-【思路】基于二分查找,优化寻找 mid 指针和收敛 left right -指针的步骤,具体问题具体分析
+操作系统知识点 +/OS/ +重点:线程进程、死锁 + +内存管理
+虚拟内存
+CPU +只会访问虚拟内存地址,在操作总线前,通过一个地址转换硬件将虚拟内存地址转换为物理内存地址
+进程隔离:将虚拟内存映射到物理内存,进程之间的地址空间相互隔离,互不干扰
+虚拟内存空间:
+ ++
用户态虚拟内存空间是相互隔离相互独立的;内核虚拟内存空间是各个进程共享的;
+进程管理
+数据结构 PCB
+进程和线程的区别
+线程是调度的基本单位,而进程则是资源拥有的基本单位。
-
-
堆排序
-数组实现大根堆的两个主要方法(注意动态扩容)
--class Heap {
int[] data;
public void downHeapify(int i) {
// 下标从0开始,子节点下标为2i+1和2i+2
int l = i*2 + 1, r = i*2 + 2, largest = i;
if (l < heapSize && data[l] > data[largest]) {
largest = l;
}
if (r < heapSize && data[r] > data[largest]) {
largest = r;
}
if (largest != i) {
swap(i, largest);
maxHeapify(largest);
}
}
public void upHeapify(int i) {
// 父节点下标为(i-1)/2
int parent = (i-1)/2, min = i;
if (parent>=0 && data[parent] < data[i]) {
min = parent;
}
if (min != i) {
swap(min, i);
upHeapify(min);
}
}
}动态规划
-思路:动规的中心思想就是把一个复杂问题拆分成多个简单、可以逐步堆叠得到答案的子问题。
-做题步骤
--
-
进程间通信方式
+匿名管道 / 命名管道
+消息队列
+共享内存+信号量
+Socket
+乐观锁悲观锁
+CAS 是乐观锁没错,但是 CAS 和自旋锁不同之处,自旋锁基于 CAS 加了while +或者睡眠 CPU +的操作而产生自旋的效果,加锁失败会忙等待直到拿到锁,自旋锁是要需要事先拿到锁才能修改数据的,所以算悲观锁。
+线程崩溃
+1、如果线程是非法访问内存引起的崩溃,其对应进程一定会崩溃。
+2、进程崩溃的本质是:操作系统对进程发出了信号,例如非法访问内存的信号是 +SIGSEGV(序号 11)
+3、想要防止进程奔溃,需要自定义信号处理函数去拦截 SIGSEGV 信号。参考 +JVM 中线程崩溃但 JVM 进程不会崩溃
+网络系统
+I/O 多路复用
+单个进程或线程同时监视多个文件描述符,如网络连接或文件句柄。当这些描述符中的任何一个就绪时,比如有数据可读或可写,多路复用机制就能够通知应用程序进行相应的读写操作。常见的IO多路复用技术包括 +select、poll 和 epoll 等。
+select
+将已连接的 Socket 都放到一个文件描述符集合,然后调用 select +函数将文件描述符集合拷贝到内核里,让内核来检查是否有网络事件产生,检查的方式很粗暴,就是通过遍历文件描述符集合的方式,当检查到有事件产生后,将此 +Socket 标记为可读或可写, +接着再把整个文件描述符集合拷贝回用户态里,然后用户态还需要再通过遍历的方法找到可读或可写的 +Socket,然后再对其处理。2 +次「遍历」文件描述符集合,2 +次「拷贝」文件描述符集合。
+poll
+它使用一个 pollfd +结构来表示被监视的文件描述符及其事件,与select相比,poll没有文件描述符数量的限制,因为它基于链表来存储。都是使用「线性结构」存储进程关注的 +Socket 集合,因此都需要遍历文件描述符集合来找到可读或可写的 +Socket,时间复杂度为 +O(n),而且也需要在用户态与内核态之间拷贝文件描述符集合
+epoll
++
-
+
触发时机
+-
+
+ +八股文 ++ +操作系统 ++ +实习笔试题汇总 +/%E5%AE%9E%E4%B9%A0%E7%AC%94%E8%AF%95%E9%A2%98%E6%B1%87%E6%80%BB/ ++ - +0-1背包
+2024.4.27 美团笔试
+和携程差不多,签到题速通,后续疯狂折磨人,过不了一点。感觉题目难度差的好大,要么我秒杀它,要么它秒杀我
+第三题
-
-每个物品只能用一次
+回溯写了半天,结果只能过20%。看别人是用前缀和+dp,那就是和腾讯第四题类似了,当时学会了现在又忘了,真难崩。
下标含义:dp[物品 i ][容量 j ] 。如果 -物品价值==物品种类,dp数组可以直接用 boolean[][],不相等用 int[][]
-状态转移方程:
-dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i]]
初始化:物品 0 和容量 0 的情况
-遍历顺序:二维数组先遍历物品和容量都可以,一维数组只能先遍历容量
-树形 dp
-题型:树的直径
-思路:可以看作是再求树的深度,在求深度的同时“更新树的最长直径”。
-代码模板
--class LongestPath {
List<Integer>[] g;
int longestPath = 0;
int dfs(int x) {
// 两种思路:1.记录最大和次大长的路径;2.记录最大长 max,max+当前结果 和 result 比大小
int max = 0;
for (int child:g[x]) {
int cur = dfs(child) + 1;
longestPath = Math.max(longestPath, max + cur);
max = Math.max(max, cur);
}
return max;
}
void solve() {
int[] relate = {-1, 2, 4, 2, 3}; // 边的关系(题目给出)
// 构建关系,List 存儿子节点,可以拓展到一般树的情况
g = new ArrayList[relate.length];
Arrays.setAll(g, e -> new ArrayList<>());
for (int i = 1; i<relate.length; i++) {
g[relate[i]].add(i);
}
dfs(0);
System.out.println(longestPath);
}
}拓展:
--
-
题型:树上最大独立集(从图中选择尽量多的点,使得这些点互不相邻)
-题型:树上最小支配集(从图中选择尽量少的点,使得这些点和其父子结点包括了整棵树)
-二维 dp
-题型:最长公共子序列
-思路:定义
-dp[i][j]
表示text1[0:i-1]
和 -text2[0:j-1]
的最长公共子序列前缀和
+小美拿到了一个数组,她每次操作可以将两个相邻元素合并为一个元素,合并后的元素为原来两个元素之和。小美希望最终数组的最小值不小于 +k。她想知道有多少种不同的合并结果?
+输入描述:第一行输入两个正整数n,k,代表数组大小和数组的最大值。第二行输入几个正整数q:,代表小美拿到的数组。1 +≤ n,k,ai < 200
+输出描述:输出一个整数,代表小美可以得到多少种不同的结果。由于结果可能很大,输出对10^9+7取模的结果。
+eg:
++4 4
2 3 4 5输出 4
+回溯解法,只过20%(加了dp保存过程值也没用)
++class Solution_3 {
int[] dp;
int[] a;
int k;
void solve(int[] a, int k) {
this.dp = new int[a.length];
this.a = a;
this.k = k;
Arrays.fill(dp, -1);
System.out.println(backtrack(0, 0));
}
int backtrack(int sum, int index) {
if (index==a.length) return 1;
if (sum==0 && dp[index]!=-1)
return dp[index];
int cnt=0;
boolean isBegin = sum==0;
for (int i=index; i<a.length; i++) {
sum += a[i];
if (sum>=k) {
cnt += backtrack(0, i+1);
}
}
if (isBegin) dp[index] = cnt;
return cnt;
}
}
class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt(), k = in.nextInt();
int[] a = new int[n];
for (int i=0; i<n; i++) {
a[i] = in.nextInt();
}
new Solution_3().solve(a, k);
}
}自己试试写前缀和+dp(思路重要真的很重要,二十分钟就写出来了)
-
-应用题型:连续子数组
+dp[i] 表示
数字 0-i 的方案数[0, i) +的字串可以拆分的种类,状态转移方程为\(dp[i] = +\sum dp[j]\)(j-i 大于等于 k 的数量总和,用前缀和求出)并查集
++class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt(), k = in.nextInt();
int[] sum = new int[n+1];
sum[1] = in.nextInt();
for (int i=2; i<=n; i++) {
sum[i] += sum[i-1] + in.nextInt();
}
int[] dp = new int[n+1];
dp[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < i; j++) {
if (sum[i] - sum[j] >= k) {
dp[i] += dp[j];
}
}
}
System.out.println(dp[n]);
}
}Q1:前缀和算法初始化时为什么都要设置 +
+[0, 0] = 1
呢? 如:dp[0] = 1
or +map.put(0,1)
A1:想不明白呢,需要对状态转移数组 dp[] +的理解非常正确才行
+第四题
+小美拿到了一棵树,其中有一些节点被染成红色。
-
-应用题型:检查树是否连通;构造最小生成树
-扩展:带权并查集
+大佬的思路:预打表小质数,然后dfs遍历连通块,统计块内每个红点的质因子,得到结点编号的乘积的质因子分解形式,根据质因子数量计算因子个数。对于我来说,需要背一下并查集的模板。
数据结构模板
--class Node {
int[] tab;
Node (int size) {
this.tab = new int[size];
}
int find(int i) {
return i==tab[i] ? i : (tab[i] = find(tab[i]));
}
void union(int x, int y) {
tab[find(x)] = find(y);
}
}Java 技巧
-强制类型转换
+小美定义一个红色连通块的权值为:所有节点编号乘积的因子数量。小美想知道,所有红色连通块的权值之和是多少?由于答案过大,请对10^9+ +7取模。
+输入描述:
+第一行输入一个正整数n,代表节点数量。 +第二行输入一个长度为几的、仅由'R"和"W组成的字符串,第i个字符为'R'代表;号节点被染成红色,"W代表未被染色。保证至少有一个节点被染成红色。
+接下来的n - +1行,每行输入2个正整数4,U,代表u号节点和u号节点有一条边连接。1 ≤n ≤ +10^5, 1 ≤u,v≤n
+输出描述:
+一个整数,代表所有红色连通块的权值之和。
+2024.4.25 华为测评
+华子免笔试,只有测评了。看网上好多人测评挂了我都惊呆了,还好没和其他的厂一样直接做测评而是上我搜了下,其他的厂可以不去但华子我必然拿下(小心谨慎哈哈哈)
+华子要什么样性格的人?(前后回答要一致)
-
-
基本数据类型的默认值
+(准备了又好像没准备,就这样吧,希望能过!阿弥陀佛财神爷保佑!)
+复盘:有些过于没有压力了,前面每一题都认真思考结果 +40min 过完才做了一半,人家都是 40min +就做完了,实在是有些拖拉(但这个要认真选真的很难啊,得回忆自己平常的所思所想所做才然后选个答案,后续时间紧张直接主观臆断速度还是很快的)。只要时间不紧张就慢慢做,一旦时间紧张了才开始全神贯注做,这可真的是一个坏毛病,得改。
+后续学习工作中都应该有这个意识,主动养成专注的习惯,要做就认真仔细专注的做事情!
+2024.4.16 携程笔试
+前两道签到题,后面一个半小时纯折磨
+第三题
+游游拿到了一个数组,她每次操作可以将相邻的两个素数元素进山314行合并,合并后的新数为原来的两个数之和,并删除原来两个数。游游希望最终数组的元素数量尽可能少,你能帮帮她吗?
++
+第一行输入一个正整数n,代表数组的大小。 +第二行输入几个正整数a_i,代表数组的元素 1 ≤ n < 10^5 1 ≤ a_i < +10^6
+返回合并结束后的元素的数量
+题目分析:素数是只能被1和自身整除的数。针对这道题可以用到,它的一大特性:除了 +2 之外两个素数之和一定是偶数(即,一定不是素数)
+因此只要先把所有 2 +和素数合并,后续只需要判断还有多少相邻的素数即可。
+做题的时候没有考虑到
+7 2 2 3
这种情况,即素数和 2 +合并完的结果如果是素数,还需要和判断他的左边还有没有 +2,有的话还要合并,即代码中的i--
部分。+class PrimeMerge {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
List<Integer> numbers = new ArrayList<>();
// 读取数组元素
for (int i = 0; i < n; i++) {
numbers.add(scanner.nextInt());
}
// 合并素数,优先处理2
mergePrimesWithPriorityToTwo(numbers);
// 输出最终数组
for (int num : numbers) {
System.out.print(num + " ");
}
}
// 检查一个数是否是素数的辅助函数
static boolean isPrime(int num) {
if (num <= 1) return false;
for (int i = 2; i * i <= num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
private static void mergePrimesWithPriorityToTwo(List<Integer> numbers) {
// 合并2与其相邻的素数,得到一个新的素数
for (int i = 0; i < numbers.size(); ) {
if (numbers.get(i) == 2) {
// 检查左边是否有素数可以合并
if (i > 0 && isPrime(numbers.get(i - 1)) && isPrime(numbers.get(i - 1) + 2)) {
numbers.set(i - 1, numbers.get(i - 1) + 2);
numbers.remove(i);
i--;
} else if (i < numbers.size() - 1 && isPrime(numbers.get(i + 1)) && isPrime(numbers.get(i + 1) + 2)) {
// 检查右边是否有素数可以合并
numbers.set(i, numbers.get(i) + numbers.get(i + 1));
numbers.remove(i + 1);
i--;
} else {
// 没有可以合并的素数,继续下一个数
i++;
}
} else {
i++;
}
}
// 合并剩余的素数对
for (int i = 0; i < numbers.size() - 1; ) {
if (isPrime(numbers.get(i)) && isPrime(numbers.get(i + 1))) {
numbers.set(i, numbers.get(i) + numbers.get(i + 1));
numbers.remove(i + 1);
} else {
i++;
}
}
}
}第四题
+定义一棵树的直径为:任意两个节点的距离的最大值。现在定义f(i):对i号节点上再连接一个新的子叶节点后,树的直径长度。现在要求f(1)到f(n)的值。
+输入描述:第一行输入一个正整数n,代表树的节点数量。
+接下来的n-1行,每行输入两个正整数u和v,代表u号节点和v号节点之间有一条长度为1的边连接。
+变量的范围:1≤n≤10的五次方,1≤u,v≤n。
+题目分析: 树的直径引出树形 dp 算法
++class TreeNode {
int val;
List<TreeNode> children;
public TreeNode(int val) {
this.val = val;
children = new ArrayList<>();
}
}
public class TreeDiameter {
public static int[] f; // 存储每个节点的最大直径
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt(); // 树的节点数量
f = new int[n + 1];
TreeNode[] nodes = new TreeNode[n + 1];
for (int i = 1; i <= n; i++) {
nodes[i] = new TreeNode(i);
}
// 连接节点之间的关系
for (int i = 0; i < n - 1; i++) {
int u = scanner.nextInt();
int v = scanner.nextInt();
nodes[u].children.add(nodes[v]);
nodes[v].children.add(nodes[u]);
}
// 遍历每个节点,添加一个新的子叶节点,计算f(i)
for (int i = 1; i <= n; i++) {
// 添加新的子叶节点
nodes[i].children.add(new TreeNode(-1));
// 计算当前最大直径
dfs(nodes[i], null, i);
// 删除添加的子叶节点
nodes[i].children.remove(nodes[i].children.size()-1);
}
for (int i = 1; i <= n; i++) {
System.out.print(f[i] + " ");
}
}
// 递归计算以当前节点为根的子树的直径
public static int dfs(TreeNode node, TreeNode parent, int i) {
int maxDepth1 = 0; // 最大深度
int maxDepth2 = 0; // 次大深度
// 遍历当前节点的子节点
for (TreeNode child : node.children) {
if (child == parent) continue; // 不访问父节点,防止死循环
int childDepth = dfs(child, node, i) + 1; // 递归计算子节点的深度
if (childDepth > maxDepth1) {
maxDepth2 = maxDepth1;
maxDepth1 = childDepth;
} else if (childDepth > maxDepth2) {
maxDepth2 = childDepth;
}
}
// 更新当前状态的最大直径
f[i] = Math.max(f[i], maxDepth1 + maxDepth2);
return maxDepth1;
}
}2024.4.9 恒生笔试
+-
+
+int count() {
try {
return 5/0;
} catch (Exception e) {
return 2*3;
} finally {
return 3;
}
}根据Java语言规范文档规定。在 +try-catch-finally 语句块中,finally 语句块中的 +return/抛出异常(立即结束语句)的优先级最高,程序会优先返回 finally +语句块中的立即结束语句的结果,此时 try-catch 语句块中的 +return/抛出异常(立即结束语句)的结果就会被丢弃掉。
+-
+
联结语法、INNER JOIN 语法
+-
+
+/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 根据输入计算最大收益
* @param M double浮点型 初始资金
* @param N int整型 历史价格天数
* @param historyPrices double浮点型一维数组 N天历史价格
* @param K int整型 最大允许交易次数
* @return double浮点型
*/
public double get_max_profit (double M, int N, double[] historyPrices, int K) {
double[][] dp = new double[K+1][N];
for (int j=1; j<N; j++) {
dp[0][j] = M;
}
for (int i=0; i<=K; i++) {
dp[i][0] = M;
}
for (int i=1; i<=K; i++) {
for (int j=1; j<N; j++) {
double max = dp[i][j-1];
for (int t=0; t<j; t++) {
double rest = dp[i-1][t]%historyPrices[t], buy = (dp[i-1][t]-rest)/historyPrices[t];
max = Math.max(max, buy*historyPrices[j]+rest);
}
dp[i][j] = max;
}
}
return dp[K][N-1]-dp[0][0];
}2024.3.31 腾讯笔试
+没做好记录,只记了没做出来的第四题,其他四道题 AC +了三道,还有一道通过 97% 我怀疑是样例有问题[手动狗头]
+-
+
+]]>public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int k = in.nextInt();
long[][] dp = new long[k + 1][n + 1];
for (int i = 0; i < n; i++) {
dp[1][i + 1] = in.nextInt() ^ dp[1][i];
}
long[] prefix = dp[1];
// 拆分为 i 份
for (int i = 2; i <= k; i++) {
// 从头到尾遍历:将第 1~j 个元素拆成 i 份
for (int j = i; j <= n; j++) {
long max = 0;
// 将第 [1,s] 个元素拆成 i-1 份,(s,j] 是最后一份
for (int s = j - 1; s >= i - 1; s--) {
// 异或的优先级小于加减法
max = Math.max(max, dp[i - 1][s] + (prefix[j] ^ prefix[s]));
}
dp[i][j] = max;
}
}
System.out.println(dp[k][n]);
}+ +工作 ++ +笔试 ++ 实习面试题汇总 +/%E5%AE%9E%E4%B9%A0%E9%9D%A2%E8%AF%95%E9%A2%98%E6%B1%87%E6%80%BB/ +2024.6.24 海康技术主管面 + 2024.6.13 谐云技主管面
+-
+
-
-
常量池
+-
+
-
-
初始化
+-
+
-
-
-
+
-
-
数组、列表快速初始化
--int[] array = {1,2,3};
int[] array = new int[]{1,2,3};
int[][] array = {{1,2},{2,3}};-List<> list = Arrays.asList(1,2,3); // 返回的是Arrays的内部类【无法增删】
List<> list = new ArrayList<>(){{
add(1);
add(2);
add(3);
}};初始化小根堆
-使用优先级队列
-PriorityQueue
实现小根堆-PriorityQueue<int[]> queue = new PriorityQueue<>((pair1,pair2) -> pair1[1]-pair2[1]); // 数组
PriorityQueue<ListNode> queue = new PriorityQueue<>((o1, o2) -> o1.val-o2.val); // 节点
queue.offer(data) // 节点入堆
data = queue.poll() // 头节点出堆List 转数组
--// 基本数据类型需要手动拆箱
int[] array = list.stream().mapToInt(Integer::valueOf).toArray();-// 流式
String[] array = list.stream().toArray(String[]::new);
// 串行【规定好数组大小,zhuan'hua速度更快】
String[] array = list.toArray(new String[list.size()]);
String[] array = list.toArray(new String[0]);数组转 List
--// 基本数据类型需要手动装箱
int[] arr = { 1, 2, 3, 4, 5 };
List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList());-Integer[] integers = new Integer[]{3,8,20,7,11,25};
List<Integer> list = Arrays.asList(integers);
// ArrayList<Object> list = new ArrayList<>();
// Collections.addAll(list, a);位运算值交换
--ch[a] ^= ch[b];
ch[b] ^= ch[a];
ch[a] ^= ch[b];泛型&占位符
-泛型:T E K V > -泛型的初衷就是为了能在编译器检查出类型安全问题,并通过编译错误提示程序员
+2024.5.22 华为主管面
+2024.5.21 谐云技术面
+并发
+2024.5.10 华为技术面
-
-
占位符:?
-TODO lambda stream 流式计算 详解
-位运算判断奇偶
--num & 1 == 0
十进制数转 char
--char t = Character.forDigit(i, 10);
Collection 转 List
--Collection<T> collection = map.values();
List<T> list = new ArrayList<T>(collection);Map 遍历方法
--for (Map.Entry<Key.class, Value.class> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}在条件语句中赋值
-不能直接在
-if
语句的条件部分进行声明和赋值,需要在 -if
语句之前声明变量,并在条件语句中只进行赋值或比较操作-int dis;
if ((dis = i - dp[i - 1]) > 1 && s.charAt(dis - 2) == '(') {
// ... 使用 dis 进行操作 ...
}StringBuilder/StringBuffer -常用方法
--]]> -s.append(char c) // 将 char 追加到此序列
s.charAt(int index) // 返回指定索引处的此序列中的 char 值
s.deleteCharAt(int index) // 按此顺序删除指定位置的 char
s.setCharAt(int index, char ch) // 指定索引处的字符设置为 ch- -编程思想 -- - -算法 -- -LLM 应用开发实践 -/LLM-Application/ -实验室项目对话模块的主要工作和创新点,先大致记录一下思路,后续慢慢完善 - -何为LLM应用开发
-网上不少人认为,与其去做 Prompt 应用不如去提升 LLM 的智能,Prompt -应用对于大语言模型能力提升的作用有限。但我不以为然,获得 Prompt -的加持之后,LLM -可以应用现实生活的所有工具;可以按步骤正确处理一个复杂问题(因为 -LLM -不同于人类对话,只有构造出非常详细且周密的过程约束,才能得到最正确的答案,不然会出现“幻觉”现象);可以引导 -LLM 自我规划(下文的长文本对话),目前 Prompt -最常应用在
-Dynamic Few-Shot Examples
领域中,可以快速定位与 -Query 最相关的小样本,不使不相关的内容分散 LLM -的注意力,而不只局限于“聊天机器人”和“搜索引擎”这类看似没啥么太大用处的名头。一言以蔽之,应用开发就是将 LLM -聪明的大脑装上可随时替换的手脚、五官和前额叶、海马体,它可以变成任何人,使用任何工具。
-长文本对话
-问题背景
-虽然模型都支持32k的上下文,但是无法要求模型一次性输出超长文本。若给模型输入:“给我讲讲中国五千年历史,字数不得少于五千”,是无法得到想要的回答,模型最多生成一两千的字,而且由于所有输出都是一次返回的,上下文逻辑和内容都不尽人意。
-解决思路
-先调用模型生成一次大纲,再拆分大纲分批次输入模型,每次模型的输出只需要关注一小块内容,因此可以获得更优结果。
--OutlinePrompt = ChatPromptTemplate.from_template(f'请根据{query},按照以下格式对问题提炼目录。回答内容尽量简短\n \
开始生成大纲:\n \
1. XXX\n 1.1xxx 1.2xxx 1.3xxx ...\n \
2. XXX\n 2.1xxx 2.2xxx 2.3xxx ...\n \
.......\n')
chain = LLMChain(prompt=OutlinePrompt, llm=model1, memory=None, verbose=True)由于需要结构化解析输出结果并链式调用模型扩写子论点,采用结构化输出解析器 -
-from langchain.output_parsers import StructuredOutputParser, ResponseSchema
-和模型调用链 -from langchain.chains import SimpleSequentialChain, SequentialChain
-,该方法相较于直接 for -循环调用模型更加麻烦,但是便于整体项目的开发、调用和维护。-chat_prompt = PromptTemplate.from_template(f'请以{title}的{contexts}为主要内容,帮我扩写到{num}字')
combined_prompt = PromptTemplate.from_template(f'写一段过渡段,从{title}自然过渡到{next_title},内容简短')
chat_chain = LLMChain(llm=llm, prompt=chat_prompt, output_key="chat")
combined_chain = LLMChain(llm=llm, prompt=combined_prompt, output_key="combined")
single_chain = SequentialChain(
chains=[chat_chain, combined_chain],
input_variables=["title", "contexts", "num", "next_title"],
output_variables=["chat", "combined"],
verbose=True
)目前还是通过 for 循环遍历大纲,后续考虑采用路由链 -
-LLMRouterChain
,-router_prompt = PromptTemplate(
template=router_template,
input_variables=["input"],
output_parser=RouterOutputParser(),
)
chain = MultiPromptChain(
router_chain=router_chain, # 路由链路
destination_chains=destination_chains, # 目标链路(LLmChain 数组)
default_chain=default_chain, # 默认链路
verbose=True
)私有数据知识库
-问题背景
-离线私有数据不能直接作为语料库训练模型,LLM -需要具有基于私有数据返回的能力。
-解决思路
-知识库系统要包括文档加载、切分、存储、检索和存储聊天记录模块,具体通过向量表征 -
+Embeddings
和向量存储Vector Store
实现+业务发送数据到对端,由于网络原因会出现概率丢包;现发送1W条数据到对端,指定输入N为丢包数量,随后列出丢包数据的具体位置;你有机会进行补包,M为可补包的数量,请返回补包后最大可连续发送数据的数量
无需实现交互式输入,只需实现如下函数
int maxContinuousPackages(int n, int[] lostPackages, int m)测试样例
++
示例1:
3
1 5 10
1
-----
9995
本示例中,丢包数量N为3,丢包位置分布为第1、5、10三个位置,补包数量M为1;在第10个位置补包后可连续发包数量最大,为10000 - 5 = 9995
示例2:
4
4 6 20 9990
2
-----
9994
示例3:
4
1500 4100 5000 8000
2
---
6499
示例4:
4
4 699 700 9990
2
---
9985
示例5:
6
100 2700 5100 7498 7499 7500
2
---
7397AC 代码,中途写错了还考虑了动态规划,导致三十分钟用满了,说是最多 30 +min 再满一点我就 GG 了
+int maxContinuousPackages(int n, int[] lostPackages, int m) {
int len = lostPackages.length, ans = 0;
int[] data = new int[len+1];
data[0] = lostPackages[0]-1;
data[data.length-1] = 10000 - lostPackages[len-1];
for (int i=1; i<data.length-1; i++) {
data[i] = lostPackages[i] - lostPackages[i-1] - 1;
}
m++;
int sum = 0;
for (int i=0; i<m; i++) {
sum += data[i];
}
ans = sum;
for (int i=m; i<data.length; i++) {
sum -= data[i-m];
sum += data[i];
ans = Math.max(ans, sum);
}
return ans+m-1;
}-
-
-
Langchain 中文本分割器
+langchain.text_splitter
都根据 -chunk_size(块大小) 和 chunk_overlap(块与块之间的重叠大小) 进行分割Java基础、JUC、JVM、SpringBoot、MySQL
-
-
-
Q1:如何加强搜索结果的多样性?
-A1:最大边际相关性 -
-Maximum marginal relevance
-,过滤搜索结果中相似度很高的文档,可以同时满足查询的相关性和结果的多样性Q2:如何将查询限定在某些文档中?如 LLM -在查询时可能同时查找 -浙江省财政报告、江苏省财政报告,但问题只与浙江省相关
-A2:通过
-SelfQueryRetriever
参数 -document_content_description
-指定元素的不同字段(source)以及它们对应的位置(page)-metadata_field_info_chinese = [
AttributeInfo(
name="source",
description="文章来源于 `index-浙江省财政报告`, `index-江苏省财政报告` 的其中之一",
type="string",
),
AttributeInfo(
name="page",
description="文章中的哪一页",
type="integer",
),
]Q3:如何通过过获取到的文档得到 LLM 响应
-A3:采用 检索式问答链
-RetrievalQA
-template = """使用以下上下文片段来回答最后的问题。如果你不知道答案,只需说不知道,不要试图编造答案。答案最多使用三个句子。尽量简明扼要地回答。在回答的最后一定要说"感谢您的提问!"
{context}
问题:{question}
有用的回答:"""
QA_CHAIN_PROMPT = PromptTemplate.from_template(template)
# RetrievalQA 内部使用了 QA_CHAIN_PROMPT
qa_chain = RetrievalQA.from_chain_type(
llm,
retriever=vectordb.as_retriever()
)
result = qa_chain({"query": question})Q4:如果文档太多,无法将它们全部适配到上下文窗口中怎么办?
-A4:采用 -
-MapReduce
,首先将每个独立的文档单独发送到语言模型以获取原始答案。然后,将答案通过最终对语言模型的一次调用组合成最终的答案-qa_chain_mr = RetrievalQA.from_chain_type(
llm,
retriever=vectordb.as_retriever(),
chain_type="map_reduce"
)如果信息分布在两个文档之间,无法在同一上下文中获取到所有的信息,也就没法给出正确答案。为解决这个问题,可以采用 -
- -Refine 检索式问答链
,Refine 文档链类似于 MapReduce -链,对于每一个文档,会调用一次 LLM,但有所改进的是,我们每次发送给 LLM -的最终提示是一个序列,这个序列会将先前的响应与新数据结合在一起,并请求得到改进后的响应。这种方法类似于 -RNN,我们增强了上下文,从而解决信息分布在不同文档的问题。多场景知识图谱
-问题背景
-参考 Langchain 外部知识库开源项目的 Issue,可以发现,由于单一的文档切分方法和已训练好的分词器切分方法(项目中用的是 -bge-large-zh-v1.5 -模型)并不能理解场景相关的概念,也就无法构建有针对性的对话知识库,因此简单的导入外部数据无法实现多场景需求。
-解决思路
-针对私有数据的多场景对话需求,可以构建并应用不同场景的知识图谱。
--
基于 用户输入Query 和 图数据库 Schema 构建 Prompt,通过 LLM -获取简短、精要的实体和关系信息,后续再基于此生成对话响应。
--from langchain.chains import GraphCypherQAChain
from langchain.graphs import Neo4jGraph
graph = Neo4jGraph(
url="bolt://localhost:7687",
username="neo4j",
password=""
)
chain = GraphCypherQAChain.from_llm(
model, graph=graph, verbose=True,
)Langchain 底层针对图数据库对话的 Prompt
--CYPHER_GENERATION_TEMPLATE = """Task:Generate Cypher statement to query a graph database.
Instructions:
Use only the provided relationship types and properties in the schema.
Do not use any other relationship types or properties that are not provided.
Schema:
{schema}
Note: Do not include any explanations or apologies in your responses.
Do not respond to any questions that might ask anything else than for you to construct a Cypher statement.
Do not include any text except the generated Cypher statement.
The question is:
{question}"""Langchain 底层针对上下文问答的 Prompt
--CYPHER_QA_TEMPLATE = """You are an assistant that helps to form nice and human understandable answers.
The information part contains the provided information that you must use to construct an answer.
The provided information is authoritative, you must never doubt it or try to use your internal knowledge to correct it.
Make the answer sound as a response to the question. Do not mention that you based the result on the given information.
If the provided information is empty, say that you don't know the answer.
Information:
{context}
Question: {question}
Helpful Answer:"""多轮对话
-采用 qdrant 向量库保存对话历史
--class CustomQdrantMemory(BaseChatMemory):
# 访问数据库抽取最相关联的 message_limit 条数据
def buffer(self, inputs: Dict[str, Any]) -> List[BaseMessage]:
chat_messages: List[BaseMessage] = []
if not inputs:
return chat_messages
hits = self.qdrant.search(
collection_name=self.conversation_id,
query_vector=self.encoder.encode(inputs['input']).tolist(),
limit=self.message_limit,
)
hits = sorted(hits, key=lambda x:x.id)
for hit in hits:
chat_messages.append(HumanMessage(content=hit.payload['human']))
chat_messages.append(AIMessage(content=hit.payload['assistant']))
curr_buffer_length = self.llm.get_num_tokens(get_buffer_string(chat_messages))
# 如果超出模型最长上下文,则弹出最早的对话历史
if curr_buffer_length > self.max_token_limit:
pruned_memory = []
while curr_buffer_length > self.max_token_limit and chat_messages:
pruned_memory.append(chat_messages.pop())
curr_buffer_length = self.llm.get_num_tokens(get_buffer_string(chat_messages))
return chat_messages虚拟人设
- -流程
+B+ 树结构,聚簇索引、二级索引、和 B 树的对比
-
-
联合索引、覆盖索引、前缀索引
-
-
- -LLM开发 -- -Langchain -- -LLM 基础知识 -/LLM-Basic/ -- -大模型核心技术点在于训练资源、数据清洗和数据配比等,其难点或许不在于模型训练和模型结构搭建
- -【变形金刚之神!Bless Me】
- -+
代理所有单例的创建,防止频 GC
-
-
NLP -任务:情感分析、文本生成、命名体识别、阅读理解、掩码填充、文本摘要、机器翻译、特征提取、对话机器人。
-NLP -数据集大多是未标注的文档,因此采用自监督学习的方式训练模型,如预测下一个词 -LM、完形填空 MLM。早些年,流行的是词嵌入 Word -Embedding,目标是采用向量的形式表示词元,采用一组向量表示一段话,可以用于计算词/句子相似度。
-现阶段,Transformer 的出现促使三种类型的模型的出现:前缀语言模型 -Encoder-Decoder(prefix-lm);掩码语言模型/自编码模型 -Encoder-Only;因果语言模型/自回归模型 Decoder-Only。Encoder-only -适用于机器翻译、句子分类、命名体识别和问答(大概);Decoder-only -适用于文本预测;Encoder-Decoder 适用于文本压缩。
-基础知识
-预训练显存占用
-样例:大小为 n B的模型,Adam 优化器,混合精度 fp16, -b(batch_size),s(sequence len),h(hidden size)
--
-
数据获取和清洗
--
-少量高质量数据优于大量低质量数据
-Tokenizer
-特殊 Token
+还能实现 Bean 的生命周期管理,可以实现 AOP
-
-
[Q] Tokenizer 是选左 Padding 还是右 Padding?
-训练和推理阶段的 <PAD> 标记是填充在左边还是右边都可以
+我说不能,AOP 实现需要操作字节码,他说行,我道歉
-
-
优化器
-在石器时代,人们直接使用
-loss.backward()
-计算梯度,乘以固定的学习率,得到所有参数更新的幅度。然而,使用固定的学习率,在梯度变化剧烈的地方,会导致更新不稳定或收敛慢。为提高收敛效果,出现了很多优化器,它们被收藏在 -
-torch.optim
里面,最出名的应该是 -Adam
、AdamW
、SGD
三大天王,待我娓娓道来。Adam
-自适应学习率: Adam -通过计算一阶和二阶矩估计来为每个参数自适应地调整学习率;
-偏差校正: -初始阶段梯度估计可能偏低,通过偏差校正可以加速初期的学习速率;
-适应性强: Adam 在很多不同的模型和数据集上都表现出了良好的性能;
-减少显存占用
-混合精度训练:FP16 -速度快,占用小,适合前向传播、反向传播、矩阵计算;FP32 -精度高,适合梯度累积、权重更新、归一化、softmax(可以通过动态损失缩放减少精度损失)
-梯度累积: -
-loss = loss / self.args.gradient_accumulation_steps
,更稳定的梯度估计梯度检查点:
-gradient_checkpointing=True
-只保存计算代价大且显存占用少的中间激活值,在反向传播时重新计算未保存的激活值采样
-top_k -(int):每次保留概率最大的几个序列,再按照概率选择保留的序列(不适用于概率分布平滑的情况)
-top_p (float: 0~1):保留前n个概率和大于 p -的序列,再按照概率选择保留的序列(适用于概率分布平滑的情况,按照概率采样,提高响应多样性)
-temperature:优化了 Softmax 函数改为 \(p(x_i)=\frac{e^{\frac{x_i}t}}{\sum_{j=1}^ne^{\frac{x_j}t}}\),温度越小 -softmax 的概率分配越尖锐(确定性),反之越平滑(随机性)
-num_beams:每次保留概率最大的几个序列,最后输出概率最大的值(上面三个方法已足够,束搜索未包含在 -OpenAI API 中)
-嵌入模型
--
-提示词在嵌入模型中扮演着关键角色,提供上下文、指导生成的格式、增强模型效果、适应不同任务并减少噪声。通过使用合适的提示词,可以提高嵌入模型的性能和实用性。
-
-bge-large-zh-v1.5
嵌入模型的架构:-
-
编程
-Transformers及相关库
-- -
-Transformers:核心库,模型加载、模型训练、流水线并行等
-Tokenizer:分词器,对数据进行预处理,文本到token序列的互相转换。具体工作包括:分词、索引、填充截断、attention_mask、token_type
-Datasets:数据集库,提供了数据集的加载、处理等方法
-Evaluate:评估函数,提供各种评价指标的计算函数
-Trainer:将模型训练流程打包,包括:创建优化器、创建DataLoader、tensor转移到CUDA上
-PEFT:高效微调模型的库,提供了几种高效微调的方法,小参数量动大模型
-Accelerate:分布式训练,提供了分布式训练解决方案,包括大模型的加载与推理解决方案
-Optimum:优化加速库,支持多种后端,如Onnxruntime、OpenVino等
-Gradio:可视化部署库,几行代码快速实现基于Web交互的算法演示系统
-分布式训练
-Accelerate 包,融合了 Deepspeed、DDP、FSDP;
-LLaMA-Factory 源码
-trainargs.main_process_first() -内的代码只在主进程里面运行,适用于数据处理;
-为实现高效打包,替换 transformers 包内模型的 -
-]]>_get_unpad_data
方法,实现4Dmask,以区分每个 batch -中的不同序列;- -LLM基础 -- -大模型基础 -- -LLM 结构和创新点 -/LLM-Model/ -优化技术 - --
-大模型领域针对 Transformer 计算过程的一些优化
-滑动窗口注意力
-sliding window attention: Longformer
-- -
稀疏注意力
-Generating Long Sequences with Sparse -Transformers,核心是只让设置好的像素点参与自注意力的计算(注意这里不是只选取设置好位置上的像素点,其他mask掉,因为这样并不能降低模型的复杂度),引入一个名为连接模式(Connectivity -Pattern)的变量,连接模式只作用在\(K\)和\(V\)的计算上,(bs, head_num, seq_len, -head_dim) 中的 seq_len 只选取连接模式中选择的。
-连接模式(注意力核)的选择:局部稀疏模式、分块稀疏模式、对角块稀疏模式
-- -
Flash Attention
-其核心思想是将原始的注意力矩阵分解成更小的子矩阵,然后分别对这些子矩阵进行计算,只要这个子矩阵的大小可以在 -SRAM 内存放,那么不就可以在计算过程中只访问 SRAM 了。
-采用了 Recomputation -(重算)方法,这算是在深度学习优化中的老概念了,它是一种算力换内存的把戏。
-Tiling 方法将 NxN 的 softmax 分数矩阵划分为块,核心是 -分块SoftMax算法,详细推导过程见技术博客。
-Qwen2 模块
-- -
+modeling_qwen2.py
架构首先说了实习的时候 Rpc 底层有用到 Rest +传输数据包,而这没有本质区别
+http 头部冗余,效率低;但 http3 效率挺好但没普及
+Rpc 更适合后台内部调用,效率高;Rest 适合所有场景,适配做的好
-
-
没复习到的八股,说了下虚拟地址映射到物理地址,页的映射,道歉
-
-
功能函数
+还会点 Python,不懂 C
-
-
优化注意力机制,降低处理长序列时的计算复杂度。
-分组查询注意力 GQA
-MQA 将所有注意力头的键和值共享
-GQA 的方式是将多个注意力头分成组,每组头共享同一组的键和值。
--
实现方式:
-transformers.models.llama.modeling_llama.repeat_kv
-复制多次 KV,使用expand
而不是repeat
是因为 -KV 的参数是组内共享的旋转位置编码 PoRE
+Java 微服务开发等
+2024.4.29 小红书一面
-
-通过旋转编码,使得每个 token -既有相对位置信息,又有绝对位置信息,Qwen2 的位置信息编码是在 attention -中计算到 KV 中的
+以后有机会的话可以问问 HR +这个部门是干什么的,再做相应的准备,不然临时抱佛脚可能抱错佛了。
例如,对于一个维度为 512 的向量\(v=(v_0,v_1,v_2,v_3,...,v_{511})\),RoPE -可能将其看作:
+他温我哭,面试官又帅又贴心,看到我紧张也不催我。但是他一直在叹气,搞得我压力好大。面试总共30min,后续手撕了一道算法题20min,==已经好几次算法题读题不准确了,连续字串和子序列最容易理解错==
+-
+
数据中台项目
-
-
然后,通过旋转矩阵分别对每一对进行旋转,使得每一对的旋转角度与相对位置相对应。
- --
代码层面,Qwen2 构造
-Qwen2RotaryEmbedding
类和 -apply_rotary_pos_emb
方法, -Qwen2RotaryEmbedding
类基于 seq_len 返回缓存的 cos 和 sin -数据,apply_rotary_pos_emb
方法将位置信息作用到\(K\)和\(V\)上。均方根归一化 RMSNorm
-矩阵计算要进行归一化防止不同特征的取值过大,常用的是 layer -norm,也就是每一项减去样本的均值,再除以样本的方差;而 RMS -则是去除了减去均值的操作,以便提升效率。
+-
+
Leader 安排的,直接存到 MySQL 中即可(搪塞一下)
+-
+
CGLib、Java 原生,SpringBoot 中只使用 CGLib 代理(一定要说 Spring +是可以配置的)
+-
+
扯到 Rpc 服务端接口代理;底层原理,编译成字节码,读入 JVM +前做一层代理
+-
+
会直接调用 B 方法
+-
+
获取到被代理的 Bean,再调用 B 方法【如何获取被 AOP 代理的 +Bean?】
+-
+
双删一致性
+-
+
Spring 单例模式的实现
++public static sychronize Singleton getInstace(){
if(instance==null){
synchronized(Singleton.class){
if(instance==null) instance=new Singleton();
}
}
return instance;
}==底层针对单例模式的使用:IOC +容器、BeanFactory==、工具类、线程池、ApplicationContext自身、
+-
+
Bean +生命周期中,初始化和依赖注入是两个阶段,不会相互影响,因此是安全的
+-
+
聚簇索引;相比于跳表,B+ 树可以有效降低树的高度;【InnoDB 的 B+ +树到达四层的情况下能装下多少数据?】
+-
+
顺序访问叶子节点;中间节点不会存到下层节点
+-
+
+MVCC+时间戳或版本号字段;间隙锁行锁表锁【悲观锁底层如何实现的?】-
+
在 update 语句的 where +条件没有使用索引,就会全表扫描,于是就会对所有记录加上 next-key +锁(记录锁 + 间隙锁),相当于把整个表锁住了
+-
+
太紧张了,回答成缓存雪崩了
+-
+
线程等待时间所占比例越高,需要越多线程;线程计算时间所占比例越高,需要越少线程;
-
-
\(\text{LN}(x) = \frac{x - \mu}{\sigma} -\cdot \gamma + \beta\)
--
-
手撕算法:【300. 最长递增子序列】一开始贪心没写出来,后面用 dp +写出来的
++int n = in.nextInt();
int[] data = new int[n];
for(int i=0; i<n; i++) {
data[i] = in.nextInt();
}
int ans = 0;
int[] dp = new int[n];
for (int i=0; i<n; i++) {
dp[i] = 1;
for (int j=0; j<i; j++) {
if (data[j]<data[i]) {
dp[i] = Math.max(dp[i], dp[j]+1);
}
}
ans = Math.max(ans, dp[i]);
}
System.out.println(ans);总结QA
+Q:JDK 动态代理和 cglib 的底层实现的区别?
+A:JDK:目标类加载后,使用 Native +方法在运行时动态生成代理类,将切面织入到代理类中;CGLib:目标类加载后,字节码构建框架 +ASM +构建字节码文件,并生成目标类的子类,将切面逻辑加入到子类中;AspectJ:编译期间,将切面织入代理类中,得到代理后的字节码;
+Q:类上有 AOP +注解,如何分别获取被代理前和代理后的这个类呢?
+A:代理前:直接 new 一个对象;代理后:通过 +
+ApplicationContext
或@Autowired
+注解来获取代理 Bean +对象,即容器中只会存放被代理过的类;Q:单例模式 Bean 是线程安全的吗?
+A:主要取决于 Bean 是否是无状态的,即 Bean +中是否包含可变的状态信息;
+Q:MySQL 如何实现乐观锁和悲观锁?
+A:乐观锁:版本号或时间戳字段;悲观锁:InnoDB +所有的行锁算法都是基于索引实现的,锁定的都是索引或索引区间;
+Q:update 用的是行锁还是表锁【TODO】
+A:Where +条件判断有索引就走索引,走索引就锁索引,索引锁了就是行锁,不然就是表锁
+Q:Redis 怎么实现过期删除策略
+A:惰性删除+定期删除(不采用定时删除)
+Q:Redis 大 Key 问题的定义,解决方法
+A:从应用服务、持久化角度分别作答
+定义:某个 key 所对应的 value 过大。具体来说,对于 +String 类型的数据,如果其大小超过 10KB,一般被认为是大 key;而对于 +set、zset、hash 等集合类型的数据,如果其包含的元素数量超过 5000 +条,也通常被视为大 key。
+解决办法:
+-
+
LN 会计算整个输入的均值 \(\mu\) -和标准差 $ $,并用它们对输入进行标准化。
-\(\text{RMSNorm}(x) = -\frac{x}{\text{RMS}(x)} \cdot \gamma\)
+造成的不良影响:
-
-
RMSNorm 只关注输入的 -范数(幅值),而不考虑均值,避免了对数据的中心化处理。
-它是一种更轻量级的标准化方法,在某些情况下可以提高训练效率和收敛速度。
-激活函数 SwiGLU
-SwiGLU 将 GLU 的门控改为
-Swish
,后验证实其在 GLU -的众多变体里效果最好,优于 Transformer 一开始使用的 -ReLU
。\(F.silu(self.w1(x)) * -self.w2(x)\),其中 silu 公式为 \(\mathrm{Swish}_\beta(x)=x\otimes\sigma(\beta -x)\)
-]]>- -LLM基础 -- -大模型结构 -- -基于 Langchain 的 RAG 架构底层原理 -/LLM-RAG-Langchain/ -当下,微调(Fine-Tuning)和检索增强生成(Retrieval-Augmented -Generation,简称RAG)是大型语言模型(LLM)与专有数据之间融合贯通的最主流的两种方法。微调对数据集和硬件要求高,如果没有足够大的平台很难深入研究,因此本文主要涉及检索增强生成(RAG架构)领域知识。 - -概念
-RAG 是一种使用额外数据增强 LLM 知识的技术,是 2020 年发表的论文 面向知识密集型 NLP -任务的检索增强生成中提出的新思想。LLM -通过外部知识源获取额外信息,从而生成更准确、更符合上下文的答案,并减少错误信息(或称为“幻觉”,即模型对用户意图的误解或在处理特定指示时产生了不准确的推断)。典型的 -RAG 应用程序有两个主要组件:
+2024.4.10 恒生一面
+虽然面试只有 +17min,但感觉再长一点我真的要蚌埠住了,哭(在杭电十二教线下面的)
+反思:自我介绍准备不足,都要开始面试了还在考虑怎么改(其实也怪他们面试通知太晚了,不怪我嘻嘻)平时学的不扎实,说不出 +AQS 的底层实现原理我可以接受,但连 AQS +都没提到实在是太蠢了,果然还是准备的不够充分。谢谢恒生一巴掌拍醒了我,认清了自己还是个小菜鸡。摆正心态,继续努力!!!
+-
+
面试官看了简历,说“不愧是软件工程内容比别人多多了”,面试官真的是很认真的把简历从头看到尾(泪目)
+-
+
因为自我介绍里说了为什么要做 RPC 项目,面试官顺势问了。
+简单说了上段实习中用到了自定义 Cluster 集群策略,因为 Dubbo 自带的 +ClusterRules(广播、失败立刻返回)没有涉及到轮询检查离线任务是否完成的功能,所以 +Leader 让我利用 Dubbo 的 SPI +机制做了一个查询微服务的计算过程是否完成的方法,然后挂载在 +META-INF/dubbo 下就 Dubbo +框架就可以直接调用该集群执行方式(当时说的并没有这么清晰,还是太菜了呜呜)
+-
+
感觉简历里唯一吸引面试官的就是如何处理 OOM Crash 了。
+测试报服务异常,线程池等待队列过长;Leader 带我用 jstack +获得线程的状态;发现该线程池中的所有线程都处在阻塞状态,并且都阻塞在父线程;查看父子线程调用关系和 +Executors.newFixedThreadPool(25) 底层原理,发现 FixedThreadPool +使用了无限长的阻塞队列,父线程未执行完成,且子线程只能在队列中等待,造成死锁所以队列一直在变长
+-
+
只知道底层实现原理不同且都是可重入锁,并不知道具体使用场景的区别(哪来的这么真实业务多场景啊喂)
+-
+
愚蠢的我只知道构建索引、优化表结构和增大 +BufferPool,好在后续上网也没找到什么很好的方法。或许==预编译 SQL +语句==是个不错的想法,根据 MySQL 运行过程推出的优化方法。
+面试 Prepare
+自我介绍
++
+由于错误使用 Dubbo 注解导致的 JVM 异常问题;Rpc 中间件采用 Netty +传输数据、Zookeeper +注册服务;调度各微服务,聚合并缓存数据;我还和同事一起分析解决了线上告警事故;
+面试官您好,很荣幸能来参加华为的面试,我叫王哲文,目前在杭州电子科技大学读研,本科就读于浙大城市学院。
+本科期间我加入了黑胡桃实验室,参与了智慧实验室和时间序列预测等项目,还在实验室举办的 +2020 +年谷歌开发者大会上分享了自己的项目经验。我在浙江华坤道威数据科技有限公司实习期间,主要负责日志切面和运维大屏的开发,在这期间我积累了企业级分布式微服务项目的开发经验。
+在读研期间,我加入了大数据与城市计算实验室,主要负责三友阴极板项目的后端开发和某涉密项目的大语言模型应用开发。在项目开发过程中,我不仅更加深入掌握了 +SpringBoot、MySQL、Redis 等主流技术,还了解了 Langchain、PyTorch、Milvus +等前沿技术。在工作之余,我还学习了 Rpc +中间件的架构和设计思想,并开发了一个简易的轻量级 Rpc +中间件。此外,我还搭建了个人博客网站,定期发布学习笔记和技术总结,不断沉淀自己的开发经验。
+最后,我非常希望能有机会加入华为,将所学知识应用到实际工作中,并与优秀的团队一起共同成长。谢谢!
+项目困难/解决方法
+实习
-
-
LLM 应用开发
-
-
RPC 中间件
-
-
从原始数据到响应生成最常见的流程图如下:
--
流程图2:
--
RAG 测评指标:
- --
Langchain
-LangChain -采用组件化设计的思想,将语言模型开发分为多个子任务:对话历史 -Memory、提示工程 Prompt、输出解析 Parase、LLM链 Chain、索引 -Indexes、代理 Agents。Langchain -模块化设计的中心思想是提升代码维护、扩展和重用的能力,可以快速开发多轮提示以及解析输出的应用。
-此外,Langchain -还提供了对话过程中需要的基本功能,如:文档加载器 -UnstructuredBaseLoader、文档分割器 TextSplitter、向量数据库存储和搜索 -BaseChatMemory、多种工具类链调用 MapReduceDocumentsChain
-还有额外的功能:API 用量记录、数据流返回 acall、缓存 -SQLite、支持多种模型接口 -OpenAI、向量数据库接口langchain.vectorstores
-模型链 Chain
-链(Chains)通常将大语言模型(LLM)与其他组件组合在一起来构建更复杂的链。比如,LLMChain -允许我们对创建的 Prompt 使用大模型;
-Chain 基类是所有 Chain -对象的起点,处理输入、输出、历史和回调等功能,支持同步和异步调用,内部组件也可以通过回调进行交互;
-自定义 Chain 需要继承 Chain 基类,实现 _call/_acall -方法定义调用逻辑;
-对话历史 Memory
-根据需求可以将历史存储在 -SQLite、qdrant等数据库中,下面代码将历史存储在缓存中:
--from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(
memory_key="history", # 与 prompt 的输入变量保持一致。
return_messages=True # 将以消息列表的形式返回聊天记录,而不是单个字符串
)提示工程 Prompt
-Prompt 很少是写明不变的,通常从多个组件构建而成的。 PromptTemplate -负责构建这个输入。
-输出解析 Parase 是提示工程的一种:
+三友
-
-
索引 Indexes
-结构化文档,以便 LLM 可以与外部文档交互。 -LangChain有许多模块可帮助您加载、结构化、存储和检索文档。
-代理 Agents
-代理涉及 LLM -做出行动决策(Observation)、执行该行动(Action)、查看一个观察结果(Observation),并重复该过程直到完成。LangChain -提供了一个标准的代理接口,一系列可供选择的代理,以及端到端代理的示例。
+Q&A
+-
-
文本召回
--
-RAG -将匹配分为多个阶段,可分为:粗召回、细召回、粗排序、精排序、再排序。该任务包括多个子任务,如文本相似度计算、问答匹配、对话匹配,类似于RAG的文本抽取式阅读理解和多项选择
-RAG 采取召回(IF-IDF、BM25)、粗排(双塔 Bert -模型、Sentence-Bert、text2vec、uniem)、精排(单塔 Bert -模型),得到相关的文档输入 LLM 中。
-基于词匹配
--
-传统方法将词匹配、词距等分数作为特征,用线性模型或树模型预测相关性,效果远不如深度学习。
-将查询文本分词,词在文档 d 中出现的次数越多,则查询文本和文档 d -越相关
-IF-IDF
-概念
-词袋模型:(bag of words)只考虑词频,不考虑词的顺序和上下文
-词频 TF:每个词在文档中出现的次数的集合;\(\sum_{t\in\mathcal{Q}}\operatorname{tf}_{t,d}\)
+说说自己对于艰苦奋斗的看法(精神上的)
-
-
文档频率 DF:词 t 在多少文档中出现过,定义“词”区别文档的能力;
-逆文档排序 IDF:衡量一个词在 N 个文档中的重要性;\(\mathrm{idf}_t=\mathrm{log}\frac -N{\mathrm{df}_t}\)
-\(\mathrm{TFIDF}(\mathcal{Q},d) = -\sum_{t\in\mathcal{Q}} \frac{\mathrm{tf}_{t,d}}{l_{d}} \cdot -\mathrm{idf}_{t}.\)
-其中,查询词q的分词后得到 Q 集合,它与文档 d 的相关性用 TF-IDF -衡量;结果还取决于所采取的分词算法;
-BM25
-IF-IDF 的变种,k 和 b 是参数(通常设置为 k∈[1.2, 2],b=0.75)
-\(\sum_{t\in -Q}\frac{\mathrm{tf}_{t,d}\cdot(k+1)}{\mathrm{tf}_{t,d}+k\cdot\left(1-b+b\cdot\frac{l_d}{\mathrm{mean}(l_d)}\right)}\cdot\ln\left(1+\frac{N-\mathrm{df}_t+0.5}{\mathrm{df}_t+0.5}\right)\)
-基于词距
-两个词在文档中出现位置之间,间隔的词越少越可能相关;
-简而言之,查询词切分后的 term -在文档中出现的次数越多越好,任意两个词之间的距离越近越好;
-eg:OkaTP
-基于深度学习
-基于交互策略的单塔模型 准确度更高
-Bert 输出 similarity,二分类任务(相似/不相似)
-基于向量匹配的双塔模型 速度更快
-Bert 输出 Sentence_Embedding,拟合 cos_Similarity(回归任务)
-评价指标
-二分类评价指标 AUC
- --
可信度 RAG
-当检索返回的结果有错误或信息丢失时,会导致LLM回复出现幻觉。
-为解决这个问题的三个指标:可信度(Faithfulness)、答案相关性(Answer -Relevance)、上下文相关性(Context Relevance)
-Query 预处理
-同义Query,
-意图识别
-召回
-索引技术:倒排索引、压缩倒排索
-检索模型:BM25、BERT
-引入上下文信息,更好地理解用户意图
-Langchain-chatchat 源码解读
-Q&A
-Embedding 模型怎么保持加载的:EmbeddingPool;
-metaData 存在哪里:MySQL 数据库;
-LLMChain 怎么区分chatprompt和prompt的:ChatOpenAI、OpenAI;
-docstore 和
-]]>index_to_docstore_id
存在哪里:本地文件 -{index_name}.pkl
;- -LLM开发 -- -RAG架构 -LLM应用开发 -- +大模型微调 PEFT 方法 -/LLM-PEFT/ -- +因此,近年来研究者们提出了各种各样的参数高效迁移学习方法,即固定住预训练模型的大部分参数,仅调整模型的一小部分参数来达到与全部参数的微调接近的效果。调整的可以是模型自有的参数,也可以是额外加入的一些参数。目前的微调方法分为加性方法、选择性方法、重参数化方法和混合方法。
- -Q&A
-[Q] 什么情况下模型显存占用大?
--
-
[Q] 为什么减少了可训练参数就会减少显存占用?
--
-
-以 LP32 精度全量微调一个 1.3B 的模型需要占用多少显存?
模型权重:1.2G * 4B = 4.8GB
梯度:1.2G * 4B = 4.8GB
优化器状态:1.2G * 4B * 2 = 9.6GB
前向激活值:取决于序列长度、隐层维度、batch size
实际加载后,占用大约 20GB 的显存[Q] 模型训练过程中有什么有效的减少显存占用的方法?
+科研&项目:
-
-
[Q] 为什么需要 PEFT?
+接下来的一年里有什么计划
-
-
[Q] 有哪些显存优化策略?
+未来职业规划
-
-
为了达成这些规划具体会做些行动
-
-
绩点排名
-
-
如何看待华为公司?为什么想来华为公司进行实习?
-
-
能够实习多长时间?
-
-
对什么感兴趣并做了什么努力?
-
-
背景
-2018年Bert问世后,NLP -研究的趋势转变为“预训练模型+微调”。虽然更大的模型带来了更好的性能,但以传统的方式对模型进行全量微调会消耗巨大的计算和存储资源,过高的硬件门槛不利于该领域的研究和发展。
-在此背景下,参数高效微调和量化技术应运而生,参数高效微调方法仅对模型的一小部分参数(这一小部分可能是模型自身的,也可能是外部引入的)进行训练,便可以为模型带来显著的性能变化,一些场景下甚至不输于全量微调,颇有一种四两拨千斤的感觉。
-由于训练一小部分参数,极大程度降低了训练大模型的算力需求,不需要多机多卡,单卡即可完成对一些大模型的训练。不仅如此,少量的训练参数对存储的要求同样降低了很多,大多数的参数高效微调方法只需要保存训练部分的参数,与动辄几十 -GB 的预训练大模型相比,几乎可以忽略。
-当下流行 PEFT 结构一览:
--
常用的参数高效微调方法:
- -+
科研期间最大的困难
-
-
如何获取资料
-
-
实现方法
-开源工具
--
-- - -- - - - - - -开源项目 -微调方法 -实现方法 -- -Llama -Factory -GaLore、BAdam、DoRA、LongLoRA、LLaMA -Pro、Mixture-of-Depths、LoRA+、LoftQ、PiSSA -peft 包、编写 LongLoRA、LlamaPro -流程【重点是对微调流程的整体架构,包括量化、数据预处理、加速训练、评估和模型存储等,用户可以开箱即用】 -- -Swift -LoRA、LoRA+、LLaMA -Pro、GaLore、LISA、UnSloth、SCEdit、NEFTune、LongLoRA、Adapter、IA3、AdaLoRA -peft 包、编写 LongLoRA、LoRA、LlamaPro、Adapter 流程 -- -llama-recipes -LoRA、QLoRA、IA3、AdaLoRA -peft 包 -- -Firefly -LoRA、QLoRA -直接操作模型结构,为所有全连接添加 Adapter -- - -Axolotl -LoRA、QLoRA、ReLoRA -peft 包、编写 ReLoRA 流程 -开发包
-Bitsandbytes:训练过程中的参数量化、压缩和加速
-Peft(没有Adapter方法的实现):参数高效微调技术,旨在通过最小化微调参数的数量和计算复杂度来提高预训练模型在新任务上的性能(可以实现)
-Adapters:HuggingFace Transformers -的附加库,将各种适配器方法集成到最先进的预训练语言模型中,以最小的训练和推理编码开销。
-DeepSpeed:提供了从训练到推理的全面优化方案,包括参数初始化、训练加速、内存优化等多个方面
-开源数据集
- -测评方法
-Acc、F1、PPL、Distinct-n、BLUE-n、Rouge-n、Rouge-L
-微调算法
--
-不包括:
+什么东西起了很大的作用
-
-
基于加法 -PEFT:增加额外可训练模型结构或参数(Embedding、MLP、LSTM),如:Prompt -Tuning、Prefix Tuning、Adapter;
-基于选择 PEFT:直接微调大模型中的一部分参数,如:BitFit、LN -Tuning;
-基于重参数化 -PEFT:在已经训练好的参数矩阵的基础上,增加可训练、可合并的参数,如:LoRA、AdaLoRA、PISSA、GaLore;
-融合上述三种方法的 PEFT:混合上述三种方法,如:MAM -Adapter、UniPELT;
-高效量化:不降低训练效果的前提下,降低计算资源的需求,如:QLoRA;
-并行训练:提升训练速度,SLoRA;
-工程系统角度的优化:梯度检查点、内存卸载;
-可训练参数量比较:IA3 < BitFit < Prompt-Tuning < Lora = -Prefix-Tuning
-BitFit
-只训练模型中的 bias 部分,冻结其他参数。
-优势:
+重大的挫折
-
-
不足:
+压力特别大的时候
-
-
LN-Tuning
-单独调整 LayerNorm 模块的 weight 和 bias -参数,训练参数量少,便于和其他的微调方法一起使用。
- --
实验表明,Prefix-Tuning + LN 的微调效果最佳。
-优势
--
-
Prompt-Tuning
-冻结预训练大模型的全部参数,在训练的输入数据前加入一小段 -Prompt,只训练 Prompt 的表示层,即一个 Embedding -模块。
-其中,Prompt 存在两种形式,分别是 hard prompt 和 soft prompt。hard -prompt 通过人工输入的提示词初始化 prompt,soft prompt 随机初始化 -prompt。二者相比,hard prompt 可控性更强,训练速度更快。为了优化Soft -prompt 的效果,后续研究提出了 P-Tuning。
--
- -可训练模块:Embedding(virtual_token, hidden_size)
--
优势:
+科研内容
+应用背景:将知识图谱应用在大模型领域,提升 LLM +响应的准确性和逻辑性;
+创新点:不同于目前流行 RAG架构 思想,并不是通过 Prompt +帮助模型获取外部知识,而是将知识图谱中的数据训练到模型中,微调后的模型不仅得到了图谱中的外部知识,还获取了图谱中节点之间的逻辑性(对话过程中的);
+具体实现:
+(1) +提出了动态策略模型,跟踪历史对话中用户语句多类特征的动态变化,抽取对话中深层次的关系和属性。
+(2)设计了一个基于注意力机制的异构图网络,将用户的意图、历史策略和上下文对话进行交互,选择最优的支持策略以生成有效的支持响应。
+(3)考虑到全局策略控制着整个对话流,DSA设计了监控全局策略信息的子任务和上下文到全局状态和全局状态到上下文的门限控制网络。
+实验:应用于情感支持对话领域,将情感支持策略视作一种类型的知识图谱,同时引入常识性知识图谱,微调 +BlenderBot 模型学习知识图谱的节点特征,提高模型的在 ESConv +数据集上的指标;
+步骤
+【3】
+3 Method【2】
-
-
不足:
+P-Tuning
-在 Prompt-Tuning 的 Soft Prompt 基础上,对 Prompt -部分进行进一步的编码计算,加速收敛。具体来说,PEFT -包中支持两种编码方式,一种是 LSTM,一种是 MLP。
--
-可训练模块:Embedding(virtual_token, hidden_size) + MLP/LSTM
--
优势:
+4 实验【3】
-
-
不足:
+5 结果【1】
+6 总结【3】
+]]>+ +工作 ++ +面试 ++ +计算机网络知识点 +/Network/ +概览 + +OSI +七层模型:应用层、表示层、会话层、传输层、网罗层、数据链路层、物理层
+TCP/IP 四层模型:应用层、传输层、网络层、网络接口层
-
-
Prefix Tuning
-将可学习的前缀以 past_key_values 的形式放到模型的 attention 的 KV -头部,每个 MHA 中的注意力层共享同一组前缀。
+应用数据转换到传输块的过程:
+ + +访问网站的过程
+ + +-
+
在网络包传输的过程中,源 IP 和目标 IP 始终是不会变的(前提:没有使用 +NAT 网络的),一直变化的是 MAC 地址,因为需要 MAC +地址在以太网内进行两个设备之间的包传输
+校验过程:MAC 地址、IP 地址、序列号、端口
+-
+
Linux 实现数据包收发
+发送
+NAPI +机制:不采用中断的方式读取数据,而是首先采用中断唤醒数据接收的服务程序,然后 +poll 的方法来轮询数据
+DMA 技术:将网络包写入到指定的内存地址,接着网卡向 CPU +发起硬件中断,当 CPU +收到硬件中断请求后,根据中断表,调用已经注册的中断处理函数
+硬中断先把收到的数据存在内存中,暂时屏蔽 CPU +中断,后续软中断统一处理先前的数据
+接收
+-
+
应用层 HTTP
-
-past _key_values:Transformer 模型中历史计算过的 key 和 value -的结果,最早是用于生成类模型解码加速,解码逻辑是根据历史输入,每次预测一个新的 -Token,然后将新的 Token 加入输入,再预测下一个 -Token。这个过程中,会存在大量的重复计算,因此可以将 key 和 value -的计算结果缓存,作为 past_key_values -输入到下一次的计算中,这一技术又被称之为 kv cache。
+HTTP +是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」
- -# 可训练模块:Embedding + MLP,与 P-Tuning 的区别是 prefix 映射到了模型的隐藏层上
self.embedding = torch.nn.Embedding(num_virtual_tokens, token_dim)
self.transform = torch.nn.Sequential(
torch.nn.Linear(token_dim, encoder_hidden_size),
torch.nn.Tanh(),
torch.nn.Linear(encoder_hidden_size, num_layers * 2 * token_dim),
)
# transformers.models.bloom.BloomAttention 源码实现
if layer_past is not None:
past_key, past_value = layer_past
key_layer = torch.cat((past_key, key_layer), dim=2)
value_layer = torch.cat((past_value, value_layer), dim=1)-
优势:
+常用字段
+Content-Length:HTTP 协议通过设置回车符、换行符作为 +HTTP header 的边界,通过 Content-Length 字段作为 HTTP body +的边界,这两个方式都是为了解决“粘包”的问题。
+HTTP/1.1 优化
-
-
不足:
+HTTP/2 优化
-
-
P-Tuning V2
-与 Prefix Tuning -最大的区别在于:移除重参数化的编码器,即没有MLP。
-通过共享连续提示同时优化多个任务,多任务学习是 P-Tuning v2 -的可选功能,可以通过多任务共享前缀进一步提升性能。
- --
优势:
+HTTP/3 优化
-
-
不足:
+Diff pruning
-不是修改模型的结构,而是通过一个特定任务的 diff -向量扩展基础模型。学习特定于任务的差异向量,该向量扩展了原始预训练参数。diff -向量 \[\delta_{task}\] -在训练过程中自适应修剪,并加入 𝐿0 范数惩罚的可微近似来鼓励稀疏性。
-\[\theta_{task}=\theta_{pretrained}+\delta_{task}\]
-不足:
+HTTPS
-
-
LoRA
-深度网络由大量 Dense -层构成,这些参数矩阵通常是低秩的。相关工作表明,在适应特定任务时,预训练模型是过度参数化的,hidden_size -实际上存在于一个较低的内在维度上,即高维数据实际是在低维子空间中。
-因此,将 \(\Delta\mathbf{W}\) -用两个更参数量更小的矩阵 \(\mathbf{A}\in\mathbb{R}^{d\times r}\) 和 -\(\mathbf{B}\in\mathbb{R}^{r\times d}\) -低秩近似(r<d)。其中,矩阵 B 通过高斯函数初始化,矩阵 A -为全零初始化,使得训练开始之前旁路对原模型不造成影响。
-具体而言,冻结预训练的模型权重,并将可训练的秩分解矩阵注入到大模型的每个 -Attention -层的线性变换中。输入分别与原始权重和两个低秩矩阵进行计算,共同得到最终结果。
- --
训练完成后,可以将两个低秩矩阵与原始模型中的权重进行合并,合并后的模型与原始模型无异,避免了推理期间 -Prompt 系列方法带来的额外计算量。
-\[\mathbf{h}=(\mathbf{W}_0+\Delta\mathbf{W})\mathbf{x}=\mathbf{W}_0\mathbf{x}+\mathbf{B}\mathbf{A}\mathbf{x}\]
-优势:
+IA3
+传输层 TCP
-
-由于不同大模型结构不同,源码实现有差别。bloom 预训练模型的 QKV 共用 -Linear 层 (hidden_size, hidden_size*3),IA3 -的可训练参数同时作用于三者之上
+负责为应用层提供网络支持,实现应用到应用的数据传输
抑制和放大内部激活,通过可学习的向量对激活值进行抑制或放大。具体来说,通过一组可训练参数直接于 -K、V、FFN 相乘,针对不同 batch -的同一位置进行相同的调整(即乘上相同可学习参数),训练过程中冻结原始模型的权重,只更新新增的参数。训练完成后,与 -Lora 类似,可以将学习部分的参数与原始权重合并,没有额外推理开销。
- --
优势:
+TCP :面向连接的、可靠的、基于字节流的
+三次握手
+ + +四次挥手【closed_wait;last_ack】
+ +-
-
不足:
+为什么这么设计?因为TCP是双向通信的可靠的协议,需要确保客户端和服务端都有收发数据包的能力;为后续传输做准备:序列号
+流量控制、超时重传、拥塞控制
+拥塞控制:慢开始(每经过一个传输轮次,拥塞窗口 +cwnd 就加倍)、拥塞避免(慢开始门限 +ssthresh)、快重传(连续收到三个重复确认就立即重传对方尚未收到的报文段,不等待重传计时器到期)、快恢复
+网络层 IP
++
+负责路径传输过程中路径和节点的选择,实现设备到设备的数据传输
+寻址能力:网络号+主机号(子网掩码)
+路由:数据包每到达一个节点,通过路由算法决定下一步走哪条路径
+分片重组:以太网的 MTU(最大传输单元)是 1500 +字节。在分片传输中,一旦某个分片丢失,则会造成整个 IP +数据报作废,所以 TCP 引入了 MSS 也就是在 TCP 层进行分片不由 IP +层分片,那么对于 UDP 我们尽量不要发送一个大于 MTU 的数据报文
+ICMP:诊断和通知出错
+NAT:网络地址转换
+DHCP:动态获取 IP 地址
+ARP:下一跳的 MAC 地址
+DNS:域名解析
+IGMP:组播
+]]>+ +八股文 ++ +计算机网络 ++ +论文阅读 Control Globally, Understand Locally +/-2023/Control%20Globally,%20Understand%20Locally/ +《Control Globally, Understand Locally. A Global-to-Local +Hierarchical Graph Network for Emotional Support Conversation.》 + +创新点:
-
-
AdaLora
-AdaLora -在微调过程中,采用“先探索参数空间,再关注最重要的权重”的方法,不预先指定矩阵的秩,而是动态更新增量矩阵的秩,因为研究发现权重矩阵的重要性在不同模块和层之间存在显著差异。在该微调方法中,需要先找到更加重要的矩阵,给其分配更多的参数(更大的秩),并裁剪不重要的矩阵。相比于Lora,该方法在提升模型效果的同时,降低了参数计算量。
-区别于 Lora 的低秩矩阵分解,AdaLora -采用参数化矩阵来模拟奇异值分解(SVD),并舍弃不重要的奇异值,保留奇异向量。由于对一个大矩阵进行精确 -SVD -分解的计算消耗非常大,这种方法可以加速计算,同时保留未来恢复的可能性并稳定训练。
-\[W=W^{(0)}+\Delta=W^{(0)}+P \Lambda -Q\]
-计算三元组 QKV -的重要性分数,修剪不太重要的奇异值,将更多预算留给优先级较高的增量矩阵。
-\[S_{k,i}=s\left(\lambda_{k,i}\right)+\frac{1}{d_1}\sum_{j=1}^{d_1}s\left(P_{k,ji}\right)+\frac{1}{d_2}\sum_{j=1}^{d_2}s\left(Q_{k,ij}\right)\]
-通过灵敏度平滑和不确定性量化,加入累计灵敏度的影响来解决随机采样和复杂的训练动态导致灵敏度估计的变异性大、不确定性大的问题
-\[\begin{aligned}&\bar{I}^{(t)}\left(w_{ij}\right)=\beta_1\bar{I}^{(t-1)}\left(w_{ij}\right)+\left(1-\beta_1\right)I^{(t)}\left(w_{ij}\right)\\&\bar{U}^{(t)}\left(w_{ij}\right)=\beta_2\bar{U}^{(t-1)}\left(w_{ij}\right)+\left(1-\beta_2\right)\left|I^{(t)}\left(w_{ij}\right)-\bar{I}^{(t)}\left(w_{ij}\right)\right|\end{aligned}\]
-\[s^{(t)}\left(w_{ij}\right)=\bar{I}^{(t)}\left(w_{ij}\right)\cdot\bar{U}^{(t)}\left(w_{ij}\right)\]
-可以通过梯度下降的方式对\(P, \Lambda, -Q\)进行更新,将不需要的奇异值 λ 剪裁 Mask,后续仍可以加入训练
-\[\Lambda_k^{(t+1)}=\mathcal{T}\left(\tilde{\Lambda}_k^{(t)},S_k^{(t)}\right),\text{ -with -}\mathcal{T}\left(\tilde{\Lambda}_k^{(t)},S_k^{(t)}\right)_{ii}=\begin{cases}\tilde{\Lambda}_{k,ii}^{(t)}&S_{k,i}^{(t)}\text{ -is in the top- }b^{(t)}\text{ of }S^{(t)}\\0&\text{ -otherwise}&\end{cases}\]
-训练损失中添加了额外的惩罚项,以规范奇异矩阵P和Q的正交性,从而避免SVD的大量计算并稳定训练。
-\[R(P,Q)=\left\|P^\top -P-I\right\|_\mathrm{F}^2+\left\|QQ^\top-I\right\|_\mathrm{F}^2\]
-最终,微调的损失函数为
-重要结论
- --
AdaLoRA 总是倾向于将更多预算分配给 FFN 和顶层,即 FFN -模块和顶层的权重矩阵对于模型性能更为重要。
-Adapter Tuning
-在 Transformer Layer 的 Self-Attetion 和 FFN -之后插入一个先降维再升维的 MLP(以及一层残差和Layer -Normalization)来学习模型微调的知识。
- --
图中,Adapter 即插入的 FF Down + 非线性激活层 + FF -up。在微调过程中,固定原始模型的参数,只微调适配层。
-不足:
++ +
论文速览
+Abstract
-
-
变体:
+AdapterDrop
-该方法在不影响任务性能的前提下,动态高效的移除冗余的 -Adapter,可以尽可能地减少模型的参数量,提高模型在反向传播(训练)和正向传播(推理)时的效率。
- --
优势:
+解决方法 / 创新点
-
-
MAM Adapter
-分解了最先进的参数高效迁移学习方法的设计,并提出了一个在它们之间建立联系的统一框架。
- --
UniPEFT
-不同的 PEFT -方法在同一任务上的表现不同,因此为特定任务选择最合适的方法并非易事,特别是考虑到新 -PEFT 方法和任务数量的快速增长。鉴于模型的多样性和模型选择的难度,UniPEFT -提出了一个统一的框架 UniPEFT,它将不同的PEFT -方法作为子模块,并通过门控机制学习激活最适合当前数据或任务设置的方法。
- --
PISSA
+有待提升的部分
+]]>+ +读论文 ++ +情绪支持对话 +异构图神经网络 ++ +论文阅读 AugESC +/-2023/AugESC/ +Title: Large-scale Data Augmentation for Emotional +Support Conversation with Pre-trained Language Models +-
-peft 包中有 PISSA 初始化方法 -
+self.pissa_init(adapter_name, init_lora_weights)
研究开放式对话数据增强,采用大语言模型 GPT-3 拓展了 ESConv +数据集大小
PISSA 和 LoRA 主要的区别是初始化方式不同。同样基于低秩特性的假设,但 -PISSA 不是去近似,而是直接基于原矩阵操作。
-PiSSA 对预训练模型的参数矩阵\[W\in -R^{m\times n}\] 进行奇异值分解,其中前 r -个奇异值和奇异向量用来初始化适配器 (adapter) 的两个矩阵\[A\in R^{m\times r}\] 和\[B\in R^{r\times n}\] ,; \[r\ll\min(m,n)\] -剩余的奇异值和奇异向量用来构造残差矩阵\[W^{res}\in R^{m\times n}\] ,使得\[W=AB+W^{res}\] -。因此,适配器中的参数包含了模型的核心参数,而残差矩阵中的参数是修正参数。通过微调参数量较小的核心适配器 -A、B,冻结参数量较大的残差矩阵 \[\text{Wres}\] -,就达成了用很少的参数近似全参数微调的效果。
- --
优势
+ +论文速览
+Abstract
+-
+
Introduction
+-
+
Conclusion
+AUGESC能够显著增强对话模型提供情感支持的能力
+]]>+ +读论文 ++ +情绪支持对话 +对话数据集增强 ++ +论文阅读 DQ-HGAN +/-2023/DQ-HGAN/ +Title: A heterogeneous graph attention network based +deep Q-learning for emotional support conversation generation + + +论文速览
+Abstract
+-
+
多源编码器
++
-
+
基于异构图的用户状态跟踪
+DQN强化学习
+响应生成解码器
+Experiments
+Conclusion
+关注的问题 / 本文的优势
+解决方法 / 创新点
+实验结论
+有待提升的部分
+]]>+ +读论文 ++ +情绪支持对话 +异构图神经网络 ++ +论文阅读 Feedback-Aware Double +/-2023/FADO/ +Title: Feedback-Aware Double COntrolling Network for +Emotional Support Conversation + ++ +
论文速览
+Abstract
+-
+
-
+
实验结论
+有待提升的部分
+]]>+ +读论文 ++ +情绪支持对话 ++ 论文阅读 MISC +/-2023/MISC_%20A%20MIxed%20Strategy-Aware%20Model%20Integrating%20COMET%20for%20Emotional%20Support%20Conversation/ +Title: A MIxed Strategy-Aware Model Integrating +COMET for Emotional Support Conversation + + +
论文速览
+Abstract
+-
+
DoRA
-将每个高阶矩阵都分解为 1*k 大小矩阵和 d*k 方向矩阵的乘积,LoRA -倾向于同时改变幅度和方向,DoRA可以更容易地将二者分开调整,或者用另一个的负变化来补偿一个的变化。
- --
SLORA
-一个 GPU 上并行执行多个 lora adapters 的微调
-S-LoRA 能够在单个 GPU 上或跨多个 GPU 以较小的开销为数千个 LoRA -适配器提供服务。该方法将所有 LoRA -模块存储在主内存中,并将当前运行的查询使用的适配器获取到 GPU -内存,提出采用统一分页技术,使用统一的内存池来管理具有不同等级的动态适配器权重和具有不同序列长度的 -KV 缓存张量。此外,该方法采用新颖的张量并行策略和高度优化的定制 CUDA -内核,可视为定制化的 LoRA微调高效计算流程。
-GaLore
-梯度低秩投影(GaLore)是一种全量参数学习的训练策略,但比常见的低秩自适应方法(LoRA)更节省内存。其关键思想是利用权重矩阵 -W 的梯度 \[G\in \mathbb{R}^{m\times -n}\] 缓慢变化的低秩结构,而不是试图将权重矩阵本身近似为低秩。
-优势:
+\[\boldsymbol{B}^{s}=\bigcup_{j=1}^{N_{r}}\operatorname{COMET}\left(\mathrm{rel}_{j},\boldsymbol{s}\right)\]
-
-
不足:
+LoRA+
-LoRA 中的适配器矩阵 A 和 B 以相同的学习率更新,实验表明对 A 和 B -使用相同的学习率并不能实现有效的特征学习,LoRA+ 通过精心选择的固定比率为 -LoRA 适配器矩阵 A 和 B 设置不同的学习率,纠正 LoRA 的这种次优性。
- --
LongLoRA
-LongLoRA -扩展了模型的上下文,同时保留了其原始架构,并且与大多数现有技术兼容。一方面,虽然推理过程中需要密集的全局注意力,但微调过程更需要稀疏的局部注意力实现有效且高效反向传播。由此,该方法提出转移稀疏注意力
-\[S^2-Attn\]
-有效地实现了上下文扩展。另一方面,除了在线性层中训练 LoRA -权重之外,LongLoRA -还进一步使嵌入层和归一化层变得可训练,由此可以表现出较好的性能。从实现上来看,该方法在训练中只需两行代码即可实现,且在推理中是可选的,不会占用额外计算资源。
--
RsLoRA
-LoRA通过在选定层添加可训练的低秩Adapter来实现参数有效的微调。每个LoRA由两个低秩矩阵乘积组成,并乘以一个与秩相关的因子,传统的LoRA采用“直接除以秩的因子”的方法过于激进,导致高秩Adapter的学习速度减缓,性能受限。因此,在实际应用中,LoRA通常仅限于使用非常低的秩。
-rsLoRA深入研究了 LoRA 的缩放因子对学习过程的影响,并证明了 LoRA -应该除以秩的平方根而不是秩,通过使用较大的秩在训练期间增加计算资源以获得更好的微调性能,同时不改变推理计算成本。
- --
LLaMA Pro
-该方法提出的Block -Expansion方法,即块扩展,在保持预训练模型参数不变的基础上,增加新的block来适应新的训练任务。这些新加入的block与原有block协同工作,既保留了模型原有的知识,又能够适应新的训练数据和任务需求。
- --
方法性能对比
-从方法类型、是否存储高效、是否内存高效、反向传播成本、推理开销五个维度比较 -PEFT 方法:
--
各种参数高效方法的参与训练的参数量、最终模型与原始模型的改变参数(delta值)以及论文中参与评估的模型的范围:
--
PEFT -方法在何种模型大小上进行过评估,以及在论文中通常使用的可训练参数数量。我们所说的可训练参数数量是指由梯度优化算法更新的参数数量,而不是我们用“更改参数”表示的原始模型与最终模型之间的差异。对于重参数化方法,我们报告了重参数化前后的参数数量。由于S4模型在不同层使用了不同的方法,因此估算其更新后的参数数量比较复杂。我们报告了在已发表的文献中对这些方法进行评估的范围。
-近年来,基于Transformer架构的大语言模型(LLM),在众多自然语言处理(NLP)任务达到了最佳性能表现。目前,构建领域专用LLM的主流策略是:在海量通用数据集上预训练的大语言模型(PLM),并通过针对特定下游任务的微调(Fine-tuning)。相较于直接采用PLM,针对下游任务的微调能显著提升模型性能。然而,随着LLM参数规模急剧增长,在消费级硬件上进行微调变得不切实际。
-为应对此挑战,研究者们近年来提出了参数高效微调技术(Parameter-Efficient -Fine-Tuning, -PEFT),其核心思想在于固定PLM的大部分参数,仅调整一小部分关键参数或引入额外参数,以接近直接微调PLM的效果。这种方法不仅保留了PLM的广泛知识库,还显著降低了计算与存储需求,为在资源受限环境下高效微调LLM开辟了新路径。
-高效量化
-QLoRA
-创新点:
+该方法的优势
-
-
优势:
+可以提升的地方
-
-
LoftQ
-该方法一种新的量化框架,在对 LLM 进行量化的同时,为 LoRA -微调找到合适的低秩初始化。这种初始化减轻了量化模型和全精度模型之间的差异,并显着提高了下游任务的泛化能力。
-GPTQ
-AWQ
-GGUF
-微调方法适配
--
-如何将微调模型应用在 自定义/未被官方适配 的大模型上
-通过
-target_modules
和modules_to_save
-实现自定义可训练参数和模块Merge Peft Model:将预训练好的 Lora 或 IA3 -的模型参数融入预训练模型中,实现不修改原模型的结构和参数量
]]>- LLM微调 +读论文 - 大模型微调 +情绪支持对话 - Linux 开发工具 -/Linux-Tool/ -Vim - 基本模式切换
+论文阅读 HEAL +/-2023/HEAL_%20A%20Knowledge%20Graph%20for%20Distress%20Management%20Conversations/ +Title: A Knowledge Graph for Distress Management +Conversations + + 论文速览
+Abstract
-
-
光标移动
+会话管理
+关注的问题 / 本文的优势
-
-
- 开发工具 +读论文 - Linux工具 +情绪支持对话 +知识图谱 - -计算机网络知识点 -/Network/ -概览 - OSI -七层模型:应用层、表示层、会话层、传输层、网罗层、数据链路层、物理层
-TCP/IP 四层模型:应用层、传输层、网络层、网络接口层
+论文阅读 KEMI +/-2023/Knowledge-enhanced%20Mixed-initiative%20Dialogue%20System%20for%20Emotional%20Support%20Conversations/ +Title: Knowledge-enhanced Mixed-initiative Dialogue +System for Emotional Support Conversations + -+ +
论文速览
+Abstract
-
-
应用数据转换到传输块的过程:
- --
访问网站的过程
- --
-
-
在网络包传输的过程中,源 IP 和目标 IP 始终是不会变的(前提:没有使用 -NAT 网络的),一直变化的是 MAC 地址,因为需要 MAC -地址在以太网内进行两个设备之间的包传输
-校验过程:MAC 地址、IP 地址、序列号、端口
--
-
Linux 实现数据包收发
-发送
-NAPI -机制:不采用中断的方式读取数据,而是首先采用中断唤醒数据接收的服务程序,然后 -poll 的方法来轮询数据
-DMA 技术:将网络包写入到指定的内存地址,接着网卡向 CPU -发起硬件中断,当 CPU -收到硬件中断请求后,根据中断表,调用已经注册的中断处理函数
-硬中断先把收到的数据存在内存中,暂时屏蔽 CPU -中断,后续软中断统一处理先前的数据
-接收
--
-
应用层 HTTP
--
-HTTP -是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」
-常用字段
-Content-Length:HTTP 协议通过设置回车符、换行符作为 -HTTP header 的边界,通过 Content-Length 字段作为 HTTP body -的边界,这两个方式都是为了解决“粘包”的问题。
-HTTP/1.1 优化
+传输层 TCP
--
-负责为应用层提供网络支持,实现应用到应用的数据传输
-TCP :面向连接的、可靠的、基于字节流的
-三次握手
- --
四次挥手【closed_wait;last_ack】
- -+
- -八股文 -- -计算机网络 -- -操作系统知识点 -/OS/ -重点:线程进程、死锁 - -内存管理
-虚拟内存
-CPU -只会访问虚拟内存地址,在操作总线前,通过一个地址转换硬件将虚拟内存地址转换为物理内存地址
-进程隔离:将虚拟内存映射到物理内存,进程之间的地址空间相互隔离,互不干扰
-虚拟内存空间:
- --
用户态虚拟内存空间是相互隔离相互独立的;内核虚拟内存空间是各个进程共享的;
-进程管理
-数据结构 PCB
-进程和线程的区别
-线程是调度的基本单位,而进程则是资源拥有的基本单位。
+- -八股文 -- -操作系统 -- 论文阅读 RAFT -/paper-PAFT/ -Paper - 创新点
-提出了新颖的特定 RAG 场景下的大模型微调方法(有明确文档域的 -RAG);
-基于 COT,进一步完善了模型的推理能力;
-背景
-当前的开放域对话模型做的是”闭卷考试“;
-RAG 做的是”开卷考试“,其结果依赖于检索器的效果;
-PAFT -应用于”特定领域的开卷考试“,模型先在特定域文档内学习如何做”开卷考试“,可以提高模型 -RAG 的能力,还能减少幻觉的产生;
-实验
-方法
-前置条件:\(\mathrm{Q}\)问题; \(\mathrm{A}^{*}\) 答案; \(\mathrm{D}^{*}\) 答案来源文档; \(D_n\) 无关文档。
-正例样本:\(Q+ \mathrm{D^*} -+D_1+D_2+\dots+D_k=>\mathrm{A}^{*}\)
-负例样本: \(\mathrm{Q}+\mathbf{D}_{1}+\mathbf{D}_{2}+\dots+\mathbf{D}_{\mathbf{k}}=>\mathbf{A}^{\star}\)
-论文中基于数据集做全量 SFT 训练
-数据集
--Question: The Oberoi family is part of a hotel company that has a head office in what city?
context: [The Oberoi family is an Indian family that is famous for its involvement in hotels, namely through The Oberoi Group]...[It is located in city center of Jakarta, near Mega Kuningan, adjacent to the sister JW Marriott Hotel. It is operated by The Ritz-Carlton Hotel Company. The complex has two towers that comprises a hotel and the Airlangga Apartment respectively]...[The Oberoi Group is a hotel company with its head office in Delhi.]
Instruction: Given the question, context and answer above, provide a logical reasoning for that answer. Please use the format of: ##Reason: {reason} ##Answer: {answer}.
CoT Answer: ##Reason: The document ##begin_quote## The Oberoi family is an Indian family that is famous for its involvement in hotels, namely through The Oberoi Group. ##end_quote## establishes that the Oberoi family is involved in the Oberoi group, and the document ##begin_quote## The Oberoi Group is a hotel company with its head office in Delhi. ##end_quote## establishes the head office of The Oberoi Group. Therefore, the Oberoi family is part of a hotel company whose head office is in Delhi. ##Answer: Delhi从数据集
-Answer
-中可以看出,提问者引导模型以思维链的方式去回答问题,先说原因 -Reason
再说答案Answer
文中采用 ##begin_quote## 和 ##end_quote## -表示直接从上下文复制粘贴的引用,研究人员发现这是防止模型产生幻觉并坚持提供的上下文的有效方法。
-实验结果
-DSF(Domain-Specific Finetuning):特定领域内微调
-PAFT:特定领域微调+特定领域 RAG
--
总结
-将模型在特定领域的文档上做思维链微调
+-
+
相关工作分析
+可以提升的地方
]]>读论文 -LLM微调 - 大模型微调 +情绪支持对话 - 实习笔试题汇总 -/%E5%AE%9E%E4%B9%A0%E7%AC%94%E8%AF%95%E9%A2%98%E6%B1%87%E6%80%BB/ -- - - 2024.4.27 美团笔试
-和携程差不多,签到题速通,后续疯狂折磨人,过不了一点。感觉题目难度差的好大,要么我秒杀它,要么它秒杀我
-第三题
--
-回溯写了半天,结果只能过20%。看别人是用前缀和+dp,那就是和腾讯第四题类似了,当时学会了现在又忘了,真难崩。
-小美拿到了一个数组,她每次操作可以将两个相邻元素合并为一个元素,合并后的元素为原来两个元素之和。小美希望最终数组的最小值不小于 -k。她想知道有多少种不同的合并结果?
-输入描述:第一行输入两个正整数n,k,代表数组大小和数组的最大值。第二行输入几个正整数q:,代表小美拿到的数组。1 -≤ n,k,ai < 200
-输出描述:输出一个整数,代表小美可以得到多少种不同的结果。由于结果可能很大,输出对10^9+7取模的结果。
-eg:
--4 4
2 3 4 5输出 4
-回溯解法,只过20%(加了dp保存过程值也没用)
--class Solution_3 {
int[] dp;
int[] a;
int k;
void solve(int[] a, int k) {
this.dp = new int[a.length];
this.a = a;
this.k = k;
Arrays.fill(dp, -1);
System.out.println(backtrack(0, 0));
}
int backtrack(int sum, int index) {
if (index==a.length) return 1;
if (sum==0 && dp[index]!=-1)
return dp[index];
int cnt=0;
boolean isBegin = sum==0;
for (int i=index; i<a.length; i++) {
sum += a[i];
if (sum>=k) {
cnt += backtrack(0, i+1);
}
}
if (isBegin) dp[index] = cnt;
return cnt;
}
}
class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt(), k = in.nextInt();
int[] a = new int[n];
for (int i=0; i<n; i++) {
a[i] = in.nextInt();
}
new Solution_3().solve(a, k);
}
}自己试试写前缀和+dp(思路重要真的很重要,二十分钟就写出来了)
--
-dp[i] 表示
-数字 0-i 的方案数[0, i) -的字串可以拆分的种类,状态转移方程为\(dp[i] = -\sum dp[j]\)(j-i 大于等于 k 的数量总和,用前缀和求出)-class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt(), k = in.nextInt();
int[] sum = new int[n+1];
sum[1] = in.nextInt();
for (int i=2; i<=n; i++) {
sum[i] += sum[i-1] + in.nextInt();
}
int[] dp = new int[n+1];
dp[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < i; j++) {
if (sum[i] - sum[j] >= k) {
dp[i] += dp[j];
}
}
}
System.out.println(dp[n]);
}
}Q1:前缀和算法初始化时为什么都要设置 -
-[0, 0] = 1
呢? 如:dp[0] = 1
or -map.put(0,1)
A1:想不明白呢,需要对状态转移数组 dp[] -的理解非常正确才行
-第四题
-小美拿到了一棵树,其中有一些节点被染成红色。
+论文阅读 BlenderBot +/-2023/Recipes%20for%20building%20an%20open-domain%20chatbot/ +Title: Recipes for building an open-domain +chatbot -
-大佬的思路:预打表小质数,然后dfs遍历连通块,统计块内每个红点的质因子,得到结点编号的乘积的质因子分解形式,根据质因子数量计算因子个数。对于我来说,需要背一下并查集的模板。
+FaceBook 在本文中提出了 BlenderBot 编解码器模型
小美定义一个红色连通块的权值为:所有节点编号乘积的因子数量。小美想知道,所有红色连通块的权值之和是多少?由于答案过大,请对10^9+ -7取模。
-输入描述:
-第一行输入一个正整数n,代表节点数量。 -第二行输入一个长度为几的、仅由'R"和"W组成的字符串,第i个字符为'R'代表;号节点被染成红色,"W代表未被染色。保证至少有一个节点被染成红色。
-接下来的n - -1行,每行输入2个正整数4,U,代表u号节点和u号节点有一条边连接。1 ≤n ≤ -10^5, 1 ≤u,v≤n
-输出描述:
-一个整数,代表所有红色连通块的权值之和。
-2024.4.25 华为测评
-华子免笔试,只有测评了。看网上好多人测评挂了我都惊呆了,还好没和其他的厂一样直接做测评而是上我搜了下,其他的厂可以不去但华子我必然拿下(小心谨慎哈哈哈)
-华子要什么样性格的人?(前后回答要一致)
+ +论文速览
+Abstract
-
-
(准备了又好像没准备,就这样吧,希望能过!阿弥陀佛财神爷保佑!)
-复盘:有些过于没有压力了,前面每一题都认真思考结果 -40min 过完才做了一半,人家都是 40min -就做完了,实在是有些拖拉(但这个要认真选真的很难啊,得回忆自己平常的所思所想所做才然后选个答案,后续时间紧张直接主观臆断速度还是很快的)。只要时间不紧张就慢慢做,一旦时间紧张了才开始全神贯注做,这可真的是一个坏毛病,得改。
-后续学习工作中都应该有这个意识,主动养成专注的习惯,要做就认真仔细专注的做事情!
-2024.4.16 携程笔试
-前两道签到题,后面一个半小时纯折磨
-第三题
-游游拿到了一个数组,她每次操作可以将相邻的两个素数元素进山314行合并,合并后的新数为原来的两个数之和,并删除原来两个数。游游希望最终数组的元素数量尽可能少,你能帮帮她吗?
--
-第一行输入一个正整数n,代表数组的大小。 -第二行输入几个正整数a_i,代表数组的元素 1 ≤ n < 10^5 1 ≤ a_i < -10^6
-返回合并结束后的元素的数量
-题目分析:素数是只能被1和自身整除的数。针对这道题可以用到,它的一大特性:除了 -2 之外两个素数之和一定是偶数(即,一定不是素数)
-因此只要先把所有 2 -和素数合并,后续只需要判断还有多少相邻的素数即可。
-做题的时候没有考虑到
-7 2 2 3
这种情况,即素数和 2 -合并完的结果如果是素数,还需要和判断他的左边还有没有 -2,有的话还要合并,即代码中的i--
部分。-class PrimeMerge {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
List<Integer> numbers = new ArrayList<>();
// 读取数组元素
for (int i = 0; i < n; i++) {
numbers.add(scanner.nextInt());
}
// 合并素数,优先处理2
mergePrimesWithPriorityToTwo(numbers);
// 输出最终数组
for (int num : numbers) {
System.out.print(num + " ");
}
}
// 检查一个数是否是素数的辅助函数
static boolean isPrime(int num) {
if (num <= 1) return false;
for (int i = 2; i * i <= num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
private static void mergePrimesWithPriorityToTwo(List<Integer> numbers) {
// 合并2与其相邻的素数,得到一个新的素数
for (int i = 0; i < numbers.size(); ) {
if (numbers.get(i) == 2) {
// 检查左边是否有素数可以合并
if (i > 0 && isPrime(numbers.get(i - 1)) && isPrime(numbers.get(i - 1) + 2)) {
numbers.set(i - 1, numbers.get(i - 1) + 2);
numbers.remove(i);
i--;
} else if (i < numbers.size() - 1 && isPrime(numbers.get(i + 1)) && isPrime(numbers.get(i + 1) + 2)) {
// 检查右边是否有素数可以合并
numbers.set(i, numbers.get(i) + numbers.get(i + 1));
numbers.remove(i + 1);
i--;
} else {
// 没有可以合并的素数,继续下一个数
i++;
}
} else {
i++;
}
}
// 合并剩余的素数对
for (int i = 0; i < numbers.size() - 1; ) {
if (isPrime(numbers.get(i)) && isPrime(numbers.get(i + 1))) {
numbers.set(i, numbers.get(i) + numbers.get(i + 1));
numbers.remove(i + 1);
} else {
i++;
}
}
}
}第四题
-定义一棵树的直径为:任意两个节点的距离的最大值。现在定义f(i):对i号节点上再连接一个新的子叶节点后,树的直径长度。现在要求f(1)到f(n)的值。
-输入描述:第一行输入一个正整数n,代表树的节点数量。
-接下来的n-1行,每行输入两个正整数u和v,代表u号节点和v号节点之间有一条长度为1的边连接。
-变量的范围:1≤n≤10的五次方,1≤u,v≤n。
-题目分析: 树的直径引出树形 dp 算法
--class TreeNode {
int val;
List<TreeNode> children;
public TreeNode(int val) {
this.val = val;
children = new ArrayList<>();
}
}
public class TreeDiameter {
public static int[] f; // 存储每个节点的最大直径
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt(); // 树的节点数量
f = new int[n + 1];
TreeNode[] nodes = new TreeNode[n + 1];
for (int i = 1; i <= n; i++) {
nodes[i] = new TreeNode(i);
}
// 连接节点之间的关系
for (int i = 0; i < n - 1; i++) {
int u = scanner.nextInt();
int v = scanner.nextInt();
nodes[u].children.add(nodes[v]);
nodes[v].children.add(nodes[u]);
}
// 遍历每个节点,添加一个新的子叶节点,计算f(i)
for (int i = 1; i <= n; i++) {
// 添加新的子叶节点
nodes[i].children.add(new TreeNode(-1));
// 计算当前最大直径
dfs(nodes[i], null, i);
// 删除添加的子叶节点
nodes[i].children.remove(nodes[i].children.size()-1);
}
for (int i = 1; i <= n; i++) {
System.out.print(f[i] + " ");
}
}
// 递归计算以当前节点为根的子树的直径
public static int dfs(TreeNode node, TreeNode parent, int i) {
int maxDepth1 = 0; // 最大深度
int maxDepth2 = 0; // 次大深度
// 遍历当前节点的子节点
for (TreeNode child : node.children) {
if (child == parent) continue; // 不访问父节点,防止死循环
int childDepth = dfs(child, node, i) + 1; // 递归计算子节点的深度
if (childDepth > maxDepth1) {
maxDepth2 = maxDepth1;
maxDepth1 = childDepth;
} else if (childDepth > maxDepth2) {
maxDepth2 = childDepth;
}
}
// 更新当前状态的最大直径
f[i] = Math.max(f[i], maxDepth1 + maxDepth2);
return maxDepth1;
}
}2024.4.9 恒生笔试
--
-
-int count() {
try {
return 5/0;
} catch (Exception e) {
return 2*3;
} finally {
return 3;
}
}根据Java语言规范文档规定。在 -try-catch-finally 语句块中,finally 语句块中的 -return/抛出异常(立即结束语句)的优先级最高,程序会优先返回 finally -语句块中的立即结束语句的结果,此时 try-catch 语句块中的 -return/抛出异常(立即结束语句)的结果就会被丢弃掉。
--
-
联结语法、INNER JOIN 语法
--
-
-/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 根据输入计算最大收益
* @param M double浮点型 初始资金
* @param N int整型 历史价格天数
* @param historyPrices double浮点型一维数组 N天历史价格
* @param K int整型 最大允许交易次数
* @return double浮点型
*/
public double get_max_profit (double M, int N, double[] historyPrices, int K) {
double[][] dp = new double[K+1][N];
for (int j=1; j<N; j++) {
dp[0][j] = M;
}
for (int i=0; i<=K; i++) {
dp[i][0] = M;
}
for (int i=1; i<=K; i++) {
for (int j=1; j<N; j++) {
double max = dp[i][j-1];
for (int t=0; t<j; t++) {
double rest = dp[i-1][t]%historyPrices[t], buy = (dp[i-1][t]-rest)/historyPrices[t];
max = Math.max(max, buy*historyPrices[j]+rest);
}
dp[i][j] = max;
}
}
return dp[K][N-1]-dp[0][0];
}2024.3.31 腾讯笔试
-没做好记录,只记了没做出来的第四题,其他四道题 AC -了三道,还有一道通过 97% 我怀疑是样例有问题[手动狗头]
--
-
+public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int k = in.nextInt();
long[][] dp = new long[k + 1][n + 1];
for (int i = 0; i < n; i++) {
dp[1][i + 1] = in.nextInt() ^ dp[1][i];
}
long[] prefix = dp[1];
// 拆分为 i 份
for (int i = 2; i <= k; i++) {
// 从头到尾遍历:将第 1~j 个元素拆成 i 份
for (int j = i; j <= n; j++) {
long max = 0;
// 将第 [1,s] 个元素拆成 i-1 份,(s,j] 是最后一份
for (int s = j - 1; s >= i - 1; s--) {
// 异或的优先级小于加减法
max = Math.max(max, dp[i - 1][s] + (prefix[j] ^ prefix[s]));
}
dp[i][j] = max;
}
}
System.out.println(dp[k][n]);
}Training Data Safety Characteristics Evaluation Methods Related Work +Results & Analysis Released code and models Discussion # 关注的问题 +/ 本文的优势
+-
+
实验结论
+有待提升的部分
+-
+
- 工作 +读论文 - 笔试 +情绪支持对话 - 论文阅读 AugESC -/-2023/AugESC/ -Title: Large-scale Data Augmentation for Emotional -Support Conversation with Pre-trained Language Models - -
+研究开放式对话数据增强,采用大语言模型 GPT-3 拓展了 ESConv -数据集大小
-论文阅读 ESConv +/-2023/Towards%20Emotional%20Support%20Dialog%20Systems/ +Title: Towards Emotional Support Dialog Systems 论文速览
-Abstract
-
-
Introduction
+Conclusion
-AUGESC能够显著增强对话模型提供情感支持的能力
+-
+
实验结果好在哪里,怎么证明的
+相关工作分析
+-
+
读论文 情绪支持对话 -对话数据集增强 - +实习面试题汇总 -/%E5%AE%9E%E4%B9%A0%E9%9D%A2%E8%AF%95%E9%A2%98%E6%B1%87%E6%80%BB/ -2024.6.24 海康技术主管面 - 2024.6.13 谐云技主管面
--
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2024.5.22 华为主管面
-2024.5.21 谐云技术面
-并发
-2024.5.10 华为技术面
--
-
-业务发送数据到对端,由于网络原因会出现概率丢包;现发送1W条数据到对端,指定输入N为丢包数量,随后列出丢包数据的具体位置;你有机会进行补包,M为可补包的数量,请返回补包后最大可连续发送数据的数量
无需实现交互式输入,只需实现如下函数
int maxContinuousPackages(int n, int[] lostPackages, int m)测试样例
--
示例1:
3
1 5 10
1
-----
9995
本示例中,丢包数量N为3,丢包位置分布为第1、5、10三个位置,补包数量M为1;在第10个位置补包后可连续发包数量最大,为10000 - 5 = 9995
示例2:
4
4 6 20 9990
2
-----
9994
示例3:
4
1500 4100 5000 8000
2
---
6499
示例4:
4
4 699 700 9990
2
---
9985
示例5:
6
100 2700 5100 7498 7499 7500
2
---
7397AC 代码,中途写错了还考虑了动态规划,导致三十分钟用满了,说是最多 30 -min 再满一点我就 GG 了
--int maxContinuousPackages(int n, int[] lostPackages, int m) {
int len = lostPackages.length, ans = 0;
int[] data = new int[len+1];
data[0] = lostPackages[0]-1;
data[data.length-1] = 10000 - lostPackages[len-1];
for (int i=1; i<data.length-1; i++) {
data[i] = lostPackages[i] - lostPackages[i-1] - 1;
}
m++;
int sum = 0;
for (int i=0; i<m; i++) {
sum += data[i];
}
ans = sum;
for (int i=m; i<data.length; i++) {
sum -= data[i-m];
sum += data[i];
ans = Math.max(ans, sum);
}
return ans+m-1;
}-
-
Java基础、JUC、JVM、SpringBoot、MySQL
--
-
B+ 树结构,聚簇索引、二级索引、和 B 树的对比
--
-
联合索引、覆盖索引、前缀索引
--
-
代理所有单例的创建,防止频 GC
+Docker +/-2024/Docker/ +-
-
还能实现 Bean 的生命周期管理,可以实现 AOP
+常用命令
+docker run <IMAGE> [COMMAND] +[ARG...]【创建一个新的容器并运行一个命令】
-
-
我说不能,AOP 实现需要操作字节码,他说行,我道歉
+docker ps [OPTIONS]【列出容器】
-
-
讲了 SpringMVC 中 HanderAdapter 用到的适配器模式
+docker rm [OPTIONS] <CONTAINER > +【删除一个或多个已经停止的容器】
-
-
首先说了实习的时候 Rpc 底层有用到 Rest -传输数据包,而这没有本质区别
-http 头部冗余,效率低;但 http3 效率挺好但没普及
-Rpc 更适合后台内部调用,效率高;Rest 适合所有场景,适配做的好
+docker build [OPTIONS] <PATH> 【创建镜像】
-
-
没复习到的八股,说了下虚拟地址映射到物理地址,页的映射,道歉
+docker save [OPTIONS] <IMAGE> 【将指定镜像保存成 tar +归档文件】
-
-
还会点 Python,不懂 C
+docker load [OPTIONS] 【导入镜像】
-
-
Java 微服务开发等
-2024.4.29 小红书一面
+docker top [OPTIONS] <CONTAINER> +【查看容器中运行的进程信息,支持 ps 命令参数】
+实践
+如何容器化 Java 应用
+Docker Compose:
++version: '3'
services:
db:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: mydb
MYSQL_USER: myuser
MYSQL_PASSWORD: mypassword
ports:
- "3608:3306" # 将宿主机的 3608 端口映射到容器的 3306 端口
java-app:
build:
context: . # 假设 Dockerfile 在当前目录下
dockerfile: Dockerfile
depends_on:
- db
environment:
DB_HOST: db # Java 程序将连接到名为 "db" 的服务(即 MySQL 容器)
DB_PORT: 3306 # 在容器内部,MySQL 仍然监听 3306 端口
DB_USER: myuser
DB_PASSWORD: mypassword
DB_NAME: mydb
ports:
- "8080:8080" # 假设 Java 程序监听 8080 端口Dockerfile:
++]]># 基础镜像Java 8
FROM java:8
# 设置工作目录
WORKDIR /app
# 复制文件到工作目录
COPY . /app
# 设置Java环境变量
ENV PATH=$PATH:$JAVA_HOME/bin
ENV JRE_HOME=${JAVA_HOME}/jre
ENV CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
# 暴露端口
EXPOSE 8080
# 运行
ENTRYPOINT ['/usr/lib/jvm/java-9-openjdk-amd64/bin/javac','-jar','app.jar']+ +开发工具 ++ +容器虚拟化 ++ +Git 文档阅读 +/-2024/Git/ +Git 中文文档 +-
-以后有机会的话可以问问 HR -这个部门是干什么的,再做相应的准备,不然临时抱佛脚可能抱错佛了。
+有空可以看看这个 Git +笔记汇总
他温我哭,面试官又帅又贴心,看到我紧张也不催我。但是他一直在叹气,搞得我压力好大。面试总共30min,后续手撕了一道算法题20min,==已经好几次算法题读题不准确了,连续字串和子序列最容易理解错==
+ ++
Chapter 1 起步
+版本控制
-
-
数据中台项目
--
-
-
-
Leader 安排的,直接存到 MySQL 中即可(搪塞一下)
--
-
CGLib、Java 原生,SpringBoot 中只使用 CGLib 代理(一定要说 Spring -是可以配置的)
--
-
扯到 Rpc 服务端接口代理;底层原理,编译成字节码,读入 JVM -前做一层代理
--
-
会直接调用 B 方法
--
-
获取到被代理的 Bean,再调用 B 方法【如何获取被 AOP 代理的 -Bean?】
--
-
双删一致性
--
-
Spring 单例模式的实现
--public static sychronize Singleton getInstace(){
if(instance==null){
synchronized(Singleton.class){
if(instance==null) instance=new Singleton();
}
}
return instance;
}==底层针对单例模式的使用:IOC -容器、BeanFactory==、工具类、线程池、ApplicationContext自身、
--
-
Bean -生命周期中,初始化和依赖注入是两个阶段,不会相互影响,因此是安全的
--
-
聚簇索引;相比于跳表,B+ 树可以有效降低树的高度;【InnoDB 的 B+ -树到达四层的情况下能装下多少数据?】
--
-
顺序访问叶子节点;中间节点不会存到下层节点
--
-
-MVCC-时间戳或版本号字段;间隙锁行锁表锁【悲观锁底层如何实现的?】-
-
在 update 语句的 where -条件没有使用索引,就会全表扫描,于是就会对所有记录加上 next-key -锁(记录锁 + 间隙锁),相当于把整个表锁住了
--
-
太紧张了,回答成缓存雪崩了
--
-
线程等待时间所占比例越高,需要越多线程;线程计算时间所占比例越高,需要越少线程;
--
-
手撕算法:【300. 最长递增子序列】一开始贪心没写出来,后面用 dp -写出来的
--int n = in.nextInt();
int[] data = new int[n];
for(int i=0; i<n; i++) {
data[i] = in.nextInt();
}
int ans = 0;
int[] dp = new int[n];
for (int i=0; i<n; i++) {
dp[i] = 1;
for (int j=0; j<i; j++) {
if (data[j]<data[i]) {
dp[i] = Math.max(dp[i], dp[j]+1);
}
}
ans = Math.max(ans, dp[i]);
}
System.out.println(ans);总结QA
-Q:JDK 动态代理和 cglib 的底层实现的区别?
-A:JDK:目标类加载后,使用 Native -方法在运行时动态生成代理类,将切面织入到代理类中;CGLib:目标类加载后,字节码构建框架 -ASM -构建字节码文件,并生成目标类的子类,将切面逻辑加入到子类中;AspectJ:编译期间,将切面织入代理类中,得到代理后的字节码;
-Q:类上有 AOP -注解,如何分别获取被代理前和代理后的这个类呢?
-A:代理前:直接 new 一个对象;代理后:通过 -
-ApplicationContext
或@Autowired
-注解来获取代理 Bean -对象,即容器中只会存放被代理过的类;Q:单例模式 Bean 是线程安全的吗?
-A:主要取决于 Bean 是否是无状态的,即 Bean -中是否包含可变的状态信息;
-Q:MySQL 如何实现乐观锁和悲观锁?
-A:乐观锁:版本号或时间戳字段;悲观锁:InnoDB -所有的行锁算法都是基于索引实现的,锁定的都是索引或索引区间;
-Q:update 用的是行锁还是表锁【TODO】
-A:Where -条件判断有索引就走索引,走索引就锁索引,索引锁了就是行锁,不然就是表锁
-Q:Redis 怎么实现过期删除策略
-A:惰性删除+定期删除(不采用定时删除)
-Q:Redis 大 Key 问题的定义,解决方法
-A:从应用服务、持久化角度分别作答
-定义:某个 key 所对应的 value 过大。具体来说,对于 -String 类型的数据,如果其大小超过 10KB,一般被认为是大 key;而对于 -set、zset、hash 等集合类型的数据,如果其包含的元素数量超过 5000 -条,也通常被视为大 key。
-解决办法:
--
-
造成的不良影响:
--
-
2024.4.10 恒生一面
-虽然面试只有 -17min,但感觉再长一点我真的要蚌埠住了,哭(在杭电十二教线下面的)
-反思:自我介绍准备不足,都要开始面试了还在考虑怎么改(其实也怪他们面试通知太晚了,不怪我嘻嘻)平时学的不扎实,说不出 -AQS 的底层实现原理我可以接受,但连 AQS -都没提到实在是太蠢了,果然还是准备的不够充分。谢谢恒生一巴掌拍醒了我,认清了自己还是个小菜鸡。摆正心态,继续努力!!!
+因为自我介绍里说了为什么要做 RPC 项目,面试官顺势问了。
-简单说了上段实习中用到了自定义 Cluster 集群策略,因为 Dubbo 自带的 -ClusterRules(广播、失败立刻返回)没有涉及到轮询检查离线任务是否完成的功能,所以 -Leader 让我利用 Dubbo 的 SPI -机制做了一个查询微服务的计算过程是否完成的方法,然后挂载在 -META-INF/dubbo 下就 Dubbo -框架就可以直接调用该集群执行方式(当时说的并没有这么清晰,还是太菜了呜呜)
--
-
Git 简史
+-
+
感觉简历里唯一吸引面试官的就是如何处理 OOM Crash 了。
-测试报服务异常,线程池等待队列过长;Leader 带我用 jstack -获得线程的状态;发现该线程池中的所有线程都处在阻塞状态,并且都阻塞在父线程;查看父子线程调用关系和 -Executors.newFixedThreadPool(25) 底层原理,发现 FixedThreadPool -使用了无限长的阻塞队列,父线程未执行完成,且子线程只能在队列中等待,造成死锁所以队列一直在变长
--
-
Git 简介
+-
+
只知道底层实现原理不同且都是可重入锁,并不知道具体使用场景的区别(哪来的这么真实业务多场景啊喂)
--
-
Git 配置
++
+git config --list --show-origin
+-
+
愚蠢的我只知道构建索引、优化表结构和增大 -BufferPool,好在后续上网也没找到什么很好的方法。或许==预编译 SQL -语句==是个不错的想法,根据 MySQL 运行过程推出的优化方法。
-面试 Prepare
-自我介绍
+Chapter 2 基础
-
-由于错误使用 Dubbo 注解导致的 JVM 异常问题;Rpc 中间件采用 Netty -传输数据、Zookeeper -注册服务;调度各微服务,聚合并缓存数据;我还和同事一起分析解决了线上告警事故;
+Git命令只能控制当前文件夹和子文件夹内的修改
面试官您好,很荣幸能来参加华为的面试,我叫王哲文,目前在杭州电子科技大学读研,本科就读于浙大城市学院。
-本科期间我加入了黑胡桃实验室,参与了智慧实验室和时间序列预测等项目,还在实验室举办的 -2020 -年谷歌开发者大会上分享了自己的项目经验。我在浙江华坤道威数据科技有限公司实习期间,主要负责日志切面和运维大屏的开发,在这期间我积累了企业级分布式微服务项目的开发经验。
-在读研期间,我加入了大数据与城市计算实验室,主要负责三友阴极板项目的后端开发和某涉密项目的大语言模型应用开发。在项目开发过程中,我不仅更加深入掌握了 -SpringBoot、MySQL、Redis 等主流技术,还了解了 Langchain、PyTorch、Milvus -等前沿技术。在工作之余,我还学习了 Rpc -中间件的架构和设计思想,并开发了一个简易的轻量级 Rpc -中间件。此外,我还搭建了个人博客网站,定期发布学习笔记和技术总结,不断沉淀自己的开发经验。
-最后,我非常希望能有机会加入华为,将所学知识应用到实际工作中,并与优秀的团队一起共同成长。谢谢!
-项目困难/解决方法
-实习
--
-
LLM 应用开发
--
-
RPC 中间件
--
-
三友
--
-
Q&A
- --
-
说说自己对于艰苦奋斗的看法(精神上的)
+常用命令
+git init 【初始化仓库】
+git clone [OPTIONS] <url>【克隆仓库】
-
-
科研&项目:
--
-
接下来的一年里有什么计划
+git add <file> +【跟踪新文件、已修改的文件放到暂存区、合并时把有冲突的文件标记为已解决状态 +】
+git diff [OPTIONS] +<file>【已修改文件与已暂存文件的内容差异】
-
-
未来职业规划
+git blame [OPTIONS]【追踪代码提交历史】
-
-
为了达成这些规划具体会做些行动
+git rm [OPTIONS] <file> 【删除文件】
-
-
绩点排名
+git commit [OPTIONS] 【提交文件】 - [-m <message>] 提交备注 - +[--amend] 追加提交 - [-a] 直接将工作区和暂存区的所有修改一起提交
+git mv <oldfilename> <newfilename> 【移动文件/改名】
+git log [OPTIONS] 【回顾提交历史】 - [--stat] 显示每次提交的简要信息 +- [-p] 显示每次提交的详细信息 - [--pretty=format:"xxx"] 自定义信息格式 - +[--oneline --graph --all] +显示提交历史、各个分支的指向以及项目的分支分叉情况 - [--since] +限制时间
+git reset [OPTIONS] +<HEAD>【回退版本,可以指定退回某一次提交的版本,直接删除某些commit的内容】
-
-
如何看待华为公司?为什么想来华为公司进行实习?
+git checkout +[OPTIONS]【在不同的分支之间切换、恢复文件、创建新分支,git switch 和 git +restore 可以代替它】
-
-
能够实习多长时间?
+git remote [OPTIONS] +【列出当前仓库中已配置的远程仓库】
-
-
对什么感兴趣并做了什么努力?
+git fetch <remote_name> <local_branch_name> +【获取远程仓库的更新,但不自动合并到你的工作】
-
-
科研期间最大的困难
+git push [OPTIONS]【推送到远程分支】
-
-
如何获取资料
+git pull <remote_name> <branch>【
+git fetch
+和git merge
的组合,拉取到本地分支并合并】git tag [OPTIONS]【列出已有的标签】
-
-
什么东西起了很大的作用
+git rebase <cur_branch> <target_branch> +【将提交到某一分支上的所有修改都移至另一分支上】
+git revert +<commit_id>【生成一次新的commit冲抵原来的commit,不会修改原有的提交历史,而是通过添加新的提交来撤销更改】
+git merge <branch> 【合并指定分支到当前分支】
+git switch [OPTIONS] <branch-name> 【切换分支,与 git checkout +类似,但提供了更清晰的语义和错误检查】
-
-
重大的挫折
+git show +【对于提交,它显示日志消息和文本差异;对于标签,它显示标签消息和引用对象】
+git restore [OPTIONS] 【恢复或撤销文件的更改】 - [.] +还原所有未提交的更改 - [<filename>] 丢弃工作区修改 - [--staged +<filename>] 将暂存区的修改放回工作区 - [--source=<commit> +<file>] 将文件恢复到特定提交的状态
+git branch [OPTIONS] 【查看本地分支】
-
-
压力特别大的时候
+git stash [OPTIONS] 【贮藏工作】
-
-
科研内容
-应用背景:将知识图谱应用在大模型领域,提升 LLM -响应的准确性和逻辑性;
-创新点:不同于目前流行 RAG架构 思想,并不是通过 Prompt -帮助模型获取外部知识,而是将知识图谱中的数据训练到模型中,微调后的模型不仅得到了图谱中的外部知识,还获取了图谱中节点之间的逻辑性(对话过程中的);
-具体实现:
-(1) -提出了动态策略模型,跟踪历史对话中用户语句多类特征的动态变化,抽取对话中深层次的关系和属性。
-(2)设计了一个基于注意力机制的异构图网络,将用户的意图、历史策略和上下文对话进行交互,选择最优的支持策略以生成有效的支持响应。
-(3)考虑到全局策略控制着整个对话流,DSA设计了监控全局策略信息的子任务和上下文到全局状态和全局状态到上下文的门限控制网络。
-实验:应用于情感支持对话领域,将情感支持策略视作一种类型的知识图谱,同时引入常识性知识图谱,微调 -BlenderBot 模型学习知识图谱的节点特征,提高模型的在 ESConv -数据集上的指标;
-步骤
-【3】
-3 Method【2】
+忽略/不跟踪文件
+.gitignore 正则表达式:官方样例文件
+Chapter 3 分支
++
+相关命令合并到 Chapter2 中
+-
+
变基
+如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基。只对尚未推送或分享给别人的本地修改执行变基操作清理历史, +从不对已推送至别处的提交执行变基操作。
+工作原理:提取<topicbranch>内的修改并存为临时文件,然后将HEAD指向<basebranch>,最后以此将之前另存为临时文件的修改依序应用
+Chapter 6 GitHub
+]]>+ +开发工具 ++ +版本管理 ++ 如何保持专注 +/-2024/Stay-Focused/ +磨刀不误砍柴工,弄明白如何做事比糊里糊涂的做更重要。当下的目标是通过不断实践试错并总结纠错,从而找到最适合我的高效专注的做事方法。在此,再以高中的座右铭激励自己:当你觉得为时已晚的时候,恰恰是最早的时候。从学生变成社会人、从孩子变成家庭支柱、从做事的变成管人的(总会有那天的啦),我还有很多要改进要学习的地方(如何清楚明确的表达自己的工作内容,如何高效明确的和别人沟通),这些变化不是为了适应社会的表演,而是成年人的责任。 (tmd这文字像是初中生写出来的,文化沙漠了属于是,有时间还是得多看看书捏)++
+Thought is already is late, exactly is the earliest time.
+启动
+布置好工作环境,安排好工作内容,让自己发自内心得希望把事情完成。
-
-
无干扰休息
+休息可以帮助自己以新的方式思考问题,可以清醒头脑,从而重新集中注意力。无干扰的休息意味着休息不会扼杀你的动力,这样你就可以重新振作起来,而不会陷入拖延的弯路。
-
-
4 实验【3】
+休息不是为了玩得开心,这才是真正休息的目的。休息是关于战略性地恢复你的能量和注意力,以重新处理手头的工作。把电视、游戏和娱乐活动留给晚上可以无愧疚地放松的时候。
+积极工作
+被动任务比主动任务更难集中注意力。改变这种状况的关键是,或者。
-
-
-
5 结果【1】
-6 总结【3】
++ +
+Step1: choose your concept【写下你要学习的概念】
+Step2: Pretend You're Teaching the ldea to a New +Student【假象你在教一位不懂这件事情的人这个概念,尝试将这件事情说明白】
+Step3: If You Get Stuck, Go Back to the +Book【如果你在这个过程中遇到了困难,回到课本和视频中进一步学习】
+Step4: Simplify and Create +Analogies【尝试精简自己的解释,并将其与其他概念做类比,从而更好地理解概念】
+总结一下,当你可以教会某人一个ta完全不懂的概念的时候,说明你真正掌握了这个概念
+固定日程安排
+努力工作的最好方式就是拥有生活
+-
+
+
+ ]]>时间分块法
+将一天分成更小的时间分块法。在每一段时间里,专注于一项任务或一组相似的任务。其重点是规划出需要完成的任务,然后划分特定的时间段专注完成这些任务。
+当你把一整天分成时间段后,它会让你专注于任务,并限制其他人占用你的时间。
+时间分块法让你每天都有一个要完成的具体任务的时间表,而不是遵循一个不断扩大的待办事项列表,你只需要关注于当下应该做的事情。
+- 工作 +思考 - 面试 +保持专注 - +论文阅读 Control Globally, Understand Locally -/-2023/Control%20Globally,%20Understand%20Locally/ -《Control Globally, Understand Locally. A Global-to-Local -Hierarchical Graph Network for Emotional Support Conversation.》 - 创新点:
+Hexo 使用指南 +/-2024/Hexo/ ++ + + +常用命令
++ +
++ + + +方法 +代码 ++ +快速部署 +hexo g -d ++ +清除缓存 +hexo clean ++ +预览 +hexo s ++ +部署 +hexo d ++ + +生成静态页面 +hexo generate +初始化配置
+初始化项目结构
++hexo init
新增标签页,设置属性(type: "tags")
++hexo new page tags
新增分类,设置属性(type: "categories")
++hexo new page categories
配置 next 主题设置
-
-
- -
论文速览
-Abstract
--
-
+ +开发工具 ++ +hexo ++ +设计模式 +/-NLP/Design-Pattern/ +单例模式 + +双重校验锁
++private volatile static Singleton uniqueInstance;
if (uniqueInstance == null) {
//类对象加锁
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}模板方法模式
++
+抽象出步骤的执行顺序作为抽象方法,具体的实现方法交给子类实现
+实现 AQS 抽象类的锁,需要重写 CLH 锁的 +
+tryAcquire-tryRelease
、tryAcquireShared-tryReleaseShared
、isHeldExclusively
+方法。重写钩子方法,可以自定义
+state
+的含义:值为多少时代表加锁成功/失败 or +解锁成功/失败,也可以实现共享锁或独占锁。观察者模式
+具体查看 JUC_Lock 博客的
+CompletableFuture
+的底层实现适配器模式
+具体查看 SpringMVC 博客的
+HandlerAdapter
的底层实现开闭原则:新增代替修改
+]]>+ +编程思想 ++ +设计模式 ++ 深度学习基础概念 +/-NLP/DL-basic/ +偏差方差 + + 泛化误差
+模型的平方预测误差的期望
+\[Err(\mathbf{x})=E\left[\left(y-f(\mathbf{x};D)\right)^2\right]=\mathbb{E}_D\left[\left(f(\boldsymbol{x};D)-\bar{f}\left(\boldsymbol{x}\right)\right)^2\right]+\left(\bar{f}(\boldsymbol{x})-y\right)^2+\mathbb{E}_D\left[(y_D-y)^2\right]\]
+方差
++
+方差是指模型对于不同训练集的预测结果的波动程度(即泛化能力),刻画了数据扰动所造成的影响。高方差意味着模型过于复杂,对训练数据中的噪声和细节过于敏感,表示模型过拟合
+使用样本数相同的不同训练集产生的方差
+\[\mathrm{var}(\mathbf{x})=\mathrm{E}_\mathrm{D}\left[\left(\mathrm{f}(\mathbf{x};\mathrm{D})-\overline{\mathrm{f}}(\mathbf{x})\right)^2\right]\]
+其中,算法 𝑓 对测试样本 𝑥 的期望预测(不同训练集 𝐷 上模型 𝑓 +对测试样本 𝑥 的预测输出的期望)\(\overline{f}(\mathbf{x})=E_D[f\left(\mathbf{x};D\right)]\)
+偏差
++
+偏差是指模型的预测值与真实值之间的差异,模型本身的拟合能力。高偏差意味着模型过于简单,无法捕捉到数据的复杂模式,表示模型欠拟合
+期望预测与真实标记的误差
+\[\mathrm{bias}^2(\mathbf{x})=\left(\overline{\mathrm{f}}(\mathbf{x})-\mathrm{y}\right)^2\]
+噪声
++
+表达了当前任务上任何模型所能达到的期望泛化误差的下界,刻画了学习问题本身的难度。
+真实标记与数据集中的实际标记间的偏差
+\[\varepsilon^2=E_D\left[(y_D-y)^2\right]\]
+偏差-方差窘境
+-
-
解决方法 / 创新点
+模型训练
+优化器
+Adam:自适应学习率,通过计算梯度的一阶矩(均值)和二阶矩(未中心化的方差)来调整学习率
+AdamW:带有权重衰减和学习率预热的Adam优化器。改进了Adam,将权重衰退和梯度更新解耦,把L2正则化移到权重更新时而不是梯度计算时
+训练方法
+监督学习
+训练数据既有特征(feature)又有标签(label),通过训练,让机器可以自己找到特征和标签之间的联系,在面对只有特征没有标签的数据时,可以判断出标签。
+无监督学习
+数据只有特征(feature)无标签(label),是一种机器学习的训练方式,它本质上是一个统计手段,在没有标签的数据里可以发现潜在的一些结构的一种训练方式。
+半监督学习
+利用同时包含有标签和无标签的数据来构建一个模型,使得模型能够在测试阶段更好地泛化到新的、未见过的数据。
+强化学习
+让一个智能体(agent)在环境(Enviroment)中通过尝试和错误来学习行为(Action)策略。智能体通过与环境进行交互,根据奖励信号来调整其行为策略,以达到最大化累积奖励的目标。
+针对 PPO 算法的优化:
-
-
有待提升的部分
++
RLHF
++
+Reinforcement Learning from Human +Feedback,以强化学习方式依据人类反馈优化语言模型,是 +OpenAI 提出的生成领域(Decoder_only)的新训练范式
+Policy Gradient
+ ++
RM+PPO
+步骤一、预训练语言模型
+ ++
步骤二、训练奖励模型 RM
+ ++
步骤三、用强化学习 PPO 微调
+ ++
DPO
+KTO
+ORPO
+损失函数
+MSELoss 回归任务
+CrossEntropyLoss 单标签分类
+BCEWithLogitsLoss 多标签分类
+Torch
+
]]>torch.nn.Parameter()
将一个不可训练的 tensor +转换成可以训练的类型 parameter,并将这个 parameter 绑定到这个 module +里面- 读论文 +LLM基础 - 情绪支持对话 -异构图神经网络 +深度学习基础 - 论文阅读 DQ-HGAN -/-2023/DQ-HGAN/ -Title: A heterogeneous graph attention network based -deep Q-learning for emotional support conversation generation - - 论文速览
-Abstract
--
-
堆排序
+数组实现大根堆的两个主要方法(注意动态扩容)
++class Heap {
int[] data;
public void downHeapify(int i) {
// 下标从0开始,子节点下标为2i+1和2i+2
int l = i*2 + 1, r = i*2 + 2, largest = i;
if (l < heapSize && data[l] > data[largest]) {
largest = l;
}
if (r < heapSize && data[r] > data[largest]) {
largest = r;
}
if (largest != i) {
swap(i, largest);
maxHeapify(largest);
}
}
public void upHeapify(int i) {
// 父节点下标为(i-1)/2
int parent = (i-1)/2, min = i;
if (parent>=0 && data[parent] < data[i]) {
min = parent;
}
if (min != i) {
swap(min, i);
upHeapify(min);
}
}
}动态规划
+思路:动规的中心思想就是把一个复杂问题拆分成多个简单、可以逐步堆叠得到答案的子问题。
+做题步骤
+-
+
0-1背包
++
+每个物品只能用一次
+下标含义:dp[物品 i ][容量 j ] 。如果 +物品价值==物品种类,dp数组可以直接用 boolean[][],不相等用 int[][]
+状态转移方程:
+dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i]]
初始化:物品 0 和容量 0 的情况
+遍历顺序:二维数组先遍历物品和容量都可以,一维数组只能先遍历容量
+树形 dp
+题型:树的直径
+思路:可以看作是再求树的深度,在求深度的同时“更新树的最长直径”。
+代码模板
++class LongestPath {
List<Integer>[] g;
int longestPath = 0;
int dfs(int x) {
// 两种思路:1.记录最大和次大长的路径;2.记录最大长 max,max+当前结果 和 result 比大小
int max = 0;
for (int child:g[x]) {
int cur = dfs(child) + 1;
longestPath = Math.max(longestPath, max + cur);
max = Math.max(max, cur);
}
return max;
}
void solve() {
int[] relate = {-1, 2, 4, 2, 3}; // 边的关系(题目给出)
// 构建关系,List 存儿子节点,可以拓展到一般树的情况
g = new ArrayList[relate.length];
Arrays.setAll(g, e -> new ArrayList<>());
for (int i = 1; i<relate.length; i++) {
g[relate[i]].add(i);
}
dfs(0);
System.out.println(longestPath);
}
}拓展:
-
-
题型:树上最大独立集(从图中选择尽量多的点,使得这些点互不相邻)
+题型:树上最小支配集(从图中选择尽量少的点,使得这些点和其父子结点包括了整棵树)
+二维 dp
+题型:最长公共子序列
+思路:定义
+dp[i][j]
表示text1[0:i-1]
和 +text2[0:j-1]
的最长公共子序列前缀和
++
+应用题型:连续子数组
+并查集
++
+应用题型:检查树是否连通;构造最小生成树
+扩展:带权并查集
+数据结构模板
++class Node {
int[] tab;
Node (int size) {
this.tab = new int[size];
}
int find(int i) {
return i==tab[i] ? i : (tab[i] = find(tab[i]));
}
void union(int x, int y) {
tab[find(x)] = find(y);
}
}Java 技巧
+强制类型转换
-
-
基本数据类型的默认值
-
-
多源编码器
-+
常量池
-
-
初始化
-
-
数组、列表快速初始化
++int[] array = {1,2,3};
int[] array = new int[]{1,2,3};
int[][] array = {{1,2},{2,3}};+List<> list = Arrays.asList(1,2,3); // 返回的是Arrays的内部类【无法增删】
List<> list = new ArrayList<>(){{
add(1);
add(2);
add(3);
}};初始化小根堆
+使用优先级队列
+PriorityQueue
实现小根堆+PriorityQueue<int[]> queue = new PriorityQueue<>((pair1,pair2) -> pair1[1]-pair2[1]); // 数组
PriorityQueue<ListNode> queue = new PriorityQueue<>((o1, o2) -> o1.val-o2.val); // 节点
queue.offer(data) // 节点入堆
data = queue.poll() // 头节点出堆List 转数组
++// 基本数据类型需要手动拆箱
int[] array = list.stream().mapToInt(Integer::valueOf).toArray();+// 流式
String[] array = list.stream().toArray(String[]::new);
// 串行【规定好数组大小,zhuan'hua速度更快】
String[] array = list.toArray(new String[list.size()]);
String[] array = list.toArray(new String[0]);数组转 List
++// 基本数据类型需要手动装箱
int[] arr = { 1, 2, 3, 4, 5 };
List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList());+Integer[] integers = new Integer[]{3,8,20,7,11,25};
List<Integer> list = Arrays.asList(integers);
// ArrayList<Object> list = new ArrayList<>();
// Collections.addAll(list, a);位运算值交换
++ch[a] ^= ch[b];
ch[b] ^= ch[a];
ch[a] ^= ch[b];泛型&占位符
+泛型:T E K V > +泛型的初衷就是为了能在编译器检查出类型安全问题,并通过编译错误提示程序员
-
-
基于异构图的用户状态跟踪
-DQN强化学习
-响应生成解码器
-Experiments
-Conclusion
-关注的问题 / 本文的优势
-解决方法 / 创新点
-实验结论
-有待提升的部分
+占位符:?
+TODO lambda stream 流式计算 详解
+位运算判断奇偶
++num & 1 == 0
十进制数转 char
++char t = Character.forDigit(i, 10);
Collection 转 List
++Collection<T> collection = map.values();
List<T> list = new ArrayList<T>(collection);Map 遍历方法
++for (Map.Entry<Key.class, Value.class> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}在条件语句中赋值
+不能直接在
+if
语句的条件部分进行声明和赋值,需要在 +if
语句之前声明变量,并在条件语句中只进行赋值或比较操作+int dis;
if ((dis = i - dp[i - 1]) > 1 && s.charAt(dis - 2) == '(') {
// ... 使用 dis 进行操作 ...
}StringBuilder/StringBuffer +常用方法
+]]>s.append(char c) // 将 char 追加到此序列
s.charAt(int index) // 返回指定索引处的此序列中的 char 值
s.deleteCharAt(int index) // 按此顺序删除指定位置的 char
s.setCharAt(int index, char ch) // 指定索引处的字符设置为 ch- 读论文 +编程思想 - 情绪支持对话 -异构图神经网络 +算法 - +论文阅读 Feedback-Aware Double -/-2023/FADO/ -Title: Feedback-Aware Double COntrolling Network for -Emotional Support Conversation - +- -
论文速览
-Abstract
--
-
查询时:
-
-
这个例子,将 64 个 32 位浮点数压缩为 8 个字节,因此压缩因子为 +32。
++# d 必须是 m 的倍数
quantizer = faiss.IndexFlatL2(d)
# 量化器数量 m、指定每个子向量编码为 8 byte(32 bit)
index = faiss.IndexIVFPQ(quantizer, d, nlist, m, 8)
# 可以简写为 index = faiss.index_factory(d, "IVF100,PQ8")
index.train(database)
index.add(database)
index.nprobe = 10
D, I = index.search(queries, k)功能
+索引的量化功能
+对向量进行编码量化
++index.sa_encode(vectors)
针对非量化索引,也会返回
+uint8
+类型的更紧凑的离散表示+xq[0][:5]
## array([0.81432974, 0.7409969 , 0.8915324 , 0.02642949, 0.24954738], dtype=float32)
index.sa_encode(xq[:1, :])[0, :5]
## array([ 93, 234, 119, 80, 63], dtype=uint8)获取原始数据/向量
+基于根据 index
++index.reconstruct(vector_id)
为了追求更快的查询性能,IndexIVF 和向量 ID IndexBinaryIVF +都存储在倒排列表中,无法通过向量 ID +来反查索引中的内容,如果我们想要得到某个数据的内容,需要手动重建索引
++index.make_direct_map()
index.reconstruct(vector_id)获取原文档
+FAISS 内置了
+docstore
和 +index_to_docstore_id
,在每次加入向量时同时存储 doc +内容,且以字典的形式储存 index 与 doc +的映射关系,方便后续查找原文档。BM25 实现
+额外记录一下
+BM25
的实现方法+import jieba
from langchain.schema import Document
from langchain_community.retrievers import BM25Retriever
def create_bm25_retriever(docs, top_k):
bm25_retriever = BM25Retriever.from_documents(
docs,
preprocess_func=jieba.lcut_for_search,
)
bm25_retriever.k = top_k
return bm25_retriever
if __name__ == "__main__":
docs = [
Document(page_content="这是一篇关于机器学习的文档。"),
Document(page_content="自然语言处理是人工智能的一个重要领域。"),
Document(page_content="深度学习是机器学习的一个子集。"),
]
top_k = 2
bm25_retriever = create_bm25_retriever(docs, top_k)
query = "机器学习"
results = bm25_retriever.get_relevant_documents(query)
for rank, doc in enumerate(results, start=1):
print(f"Rank {rank}: {doc}")Debug 查看分词结果 +
+bm25_retriever.vectorizer.doc_freqs
+]]>
+ +LLM开发 ++ +faiss ++ LLM 应用开发实践 +/-NLP/LLM-Application/ +实验室项目对话模块的主要工作和创新点,先大致记录一下思路,后续慢慢完善 + 何为LLM应用开发
+网上不少人认为,与其去做 Prompt 应用不如去提升 LLM 的智能,Prompt +应用对于大语言模型能力提升的作用有限。但我不以为然,获得 Prompt +的加持之后,LLM +可以应用现实生活的所有工具;可以按步骤正确处理一个复杂问题(因为 +LLM +不同于人类对话,只有构造出非常详细且周密的过程约束,才能得到最正确的答案,不然会出现“幻觉”现象);可以引导 +LLM 自我规划(下文的长文本对话),目前 Prompt +最常应用在
+Dynamic Few-Shot Examples
领域中,可以快速定位与 +Query 最相关的小样本,不使不相关的内容分散 LLM +的注意力,而不只局限于“聊天机器人”和“搜索引擎”这类看似没啥么太大用处的名头。一言以蔽之,应用开发就是将 LLM +聪明的大脑装上可随时替换的手脚、五官和前额叶、海马体,它可以变成任何人,使用任何工具。
+长文本对话
+问题背景
+虽然模型都支持32k的上下文,但是无法要求模型一次性输出超长文本。若给模型输入:“给我讲讲中国五千年历史,字数不得少于五千”,是无法得到想要的回答,模型最多生成一两千的字,而且由于所有输出都是一次返回的,上下文逻辑和内容都不尽人意。
+解决思路
+先调用模型生成一次大纲,再拆分大纲分批次输入模型,每次模型的输出只需要关注一小块内容,因此可以获得更优结果。
++OutlinePrompt = ChatPromptTemplate.from_template(f'请根据{query},按照以下格式对问题提炼目录。回答内容尽量简短\n \
开始生成大纲:\n \
1. XXX\n 1.1xxx 1.2xxx 1.3xxx ...\n \
2. XXX\n 2.1xxx 2.2xxx 2.3xxx ...\n \
.......\n')
chain = LLMChain(prompt=OutlinePrompt, llm=model1, memory=None, verbose=True)由于需要结构化解析输出结果并链式调用模型扩写子论点,采用结构化输出解析器 +
+from langchain.output_parsers import StructuredOutputParser, ResponseSchema
+和模型调用链 +from langchain.chains import SimpleSequentialChain, SequentialChain
+,该方法相较于直接 for +循环调用模型更加麻烦,但是便于整体项目的开发、调用和维护。+chat_prompt = PromptTemplate.from_template(f'请以{title}的{contexts}为主要内容,帮我扩写到{num}字')
combined_prompt = PromptTemplate.from_template(f'写一段过渡段,从{title}自然过渡到{next_title},内容简短')
chat_chain = LLMChain(llm=llm, prompt=chat_prompt, output_key="chat")
combined_chain = LLMChain(llm=llm, prompt=combined_prompt, output_key="combined")
single_chain = SequentialChain(
chains=[chat_chain, combined_chain],
input_variables=["title", "contexts", "num", "next_title"],
output_variables=["chat", "combined"],
verbose=True
)目前还是通过 for 循环遍历大纲,后续考虑采用路由链 +
+LLMRouterChain
,+router_prompt = PromptTemplate(
template=router_template,
input_variables=["input"],
output_parser=RouterOutputParser(),
)
chain = MultiPromptChain(
router_chain=router_chain, # 路由链路
destination_chains=destination_chains, # 目标链路(LLmChain 数组)
default_chain=default_chain, # 默认链路
verbose=True
)私有数据知识库
+问题背景
+离线私有数据不能直接作为语料库训练模型,LLM +需要具有基于私有数据返回的能力。
+解决思路
+知识库系统要包括文档加载、切分、存储、检索和存储聊天记录模块,具体通过向量表征 +
Embeddings
和向量存储Vector Store
实现-
-
+
Langchain 中文本分割器
langchain.text_splitter
都根据 +chunk_size(块大小) 和 chunk_overlap(块与块之间的重叠大小) 进行分割-
-
+
Q1:如何加强搜索结果的多样性?
+A1:最大边际相关性 +
+Maximum marginal relevance
+,过滤搜索结果中相似度很高的文档,可以同时满足查询的相关性和结果的多样性Q2:如何将查询限定在某些文档中?如 LLM +在查询时可能同时查找 +浙江省财政报告、江苏省财政报告,但问题只与浙江省相关
+A2:通过
+SelfQueryRetriever
参数 +document_content_description
+指定元素的不同字段(source)以及它们对应的位置(page)+metadata_field_info_chinese = [
AttributeInfo(
name="source",
description="文章来源于 `index-浙江省财政报告`, `index-江苏省财政报告` 的其中之一",
type="string",
),
AttributeInfo(
name="page",
description="文章中的哪一页",
type="integer",
),
]Q3:如何通过过获取到的文档得到 LLM 响应
+A3:采用 检索式问答链
+RetrievalQA
+template = """使用以下上下文片段来回答最后的问题。如果你不知道答案,只需说不知道,不要试图编造答案。答案最多使用三个句子。尽量简明扼要地回答。在回答的最后一定要说"感谢您的提问!"
{context}
问题:{question}
有用的回答:"""
QA_CHAIN_PROMPT = PromptTemplate.from_template(template)
# RetrievalQA 内部使用了 QA_CHAIN_PROMPT
qa_chain = RetrievalQA.from_chain_type(
llm,
retriever=vectordb.as_retriever()
)
result = qa_chain({"query": question})Q4:如果文档太多,无法将它们全部适配到上下文窗口中怎么办?
+A4:采用 +
+MapReduce
,首先将每个独立的文档单独发送到语言模型以获取原始答案。然后,将答案通过最终对语言模型的一次调用组合成最终的答案+qa_chain_mr = RetrievalQA.from_chain_type(
llm,
retriever=vectordb.as_retriever(),
chain_type="map_reduce"
)如果信息分布在两个文档之间,无法在同一上下文中获取到所有的信息,也就没法给出正确答案。为解决这个问题,可以采用 +
+ +Refine 检索式问答链
,Refine 文档链类似于 MapReduce +链,对于每一个文档,会调用一次 LLM,但有所改进的是,我们每次发送给 LLM +的最终提示是一个序列,这个序列会将先前的响应与新数据结合在一起,并请求得到改进后的响应。这种方法类似于 +RNN,我们增强了上下文,从而解决信息分布在不同文档的问题。多场景知识图谱
+问题背景
+参考 Langchain 外部知识库开源项目的 Issue,可以发现,由于单一的文档切分方法和已训练好的分词器切分方法(项目中用的是 +bge-large-zh-v1.5 +模型)并不能理解场景相关的概念,也就无法构建有针对性的对话知识库,因此简单的导入外部数据无法实现多场景需求。
+解决思路
+针对私有数据的多场景对话需求,可以构建并应用不同场景的知识图谱。
++
基于 用户输入Query 和 图数据库 Schema 构建 Prompt,通过 LLM +获取简短、精要的实体和关系信息,后续再基于此生成对话响应。
++from langchain.chains import GraphCypherQAChain
from langchain.graphs import Neo4jGraph
graph = Neo4jGraph(
url="bolt://localhost:7687",
username="neo4j",
password=""
)
chain = GraphCypherQAChain.from_llm(
model, graph=graph, verbose=True,
)Langchain 底层针对图数据库对话的 Prompt
++CYPHER_GENERATION_TEMPLATE = """Task:Generate Cypher statement to query a graph database.
Instructions:
Use only the provided relationship types and properties in the schema.
Do not use any other relationship types or properties that are not provided.
Schema:
{schema}
Note: Do not include any explanations or apologies in your responses.
Do not respond to any questions that might ask anything else than for you to construct a Cypher statement.
Do not include any text except the generated Cypher statement.
The question is:
{question}"""Langchain 底层针对上下文问答的 Prompt
++CYPHER_QA_TEMPLATE = """You are an assistant that helps to form nice and human understandable answers.
The information part contains the provided information that you must use to construct an answer.
The provided information is authoritative, you must never doubt it or try to use your internal knowledge to correct it.
Make the answer sound as a response to the question. Do not mention that you based the result on the given information.
If the provided information is empty, say that you don't know the answer.
Information:
{context}
Question: {question}
Helpful Answer:"""多轮对话
+采用 qdrant 向量库保存对话历史
++class CustomQdrantMemory(BaseChatMemory):
# 访问数据库抽取最相关联的 message_limit 条数据
def buffer(self, inputs: Dict[str, Any]) -> List[BaseMessage]:
chat_messages: List[BaseMessage] = []
if not inputs:
return chat_messages
hits = self.qdrant.search(
collection_name=self.conversation_id,
query_vector=self.encoder.encode(inputs['input']).tolist(),
limit=self.message_limit,
)
hits = sorted(hits, key=lambda x:x.id)
for hit in hits:
chat_messages.append(HumanMessage(content=hit.payload['human']))
chat_messages.append(AIMessage(content=hit.payload['assistant']))
curr_buffer_length = self.llm.get_num_tokens(get_buffer_string(chat_messages))
# 如果超出模型最长上下文,则弹出最早的对话历史
if curr_buffer_length > self.max_token_limit:
pruned_memory = []
while curr_buffer_length > self.max_token_limit and chat_messages:
pruned_memory.append(chat_messages.pop())
curr_buffer_length = self.llm.get_num_tokens(get_buffer_string(chat_messages))
return chat_messages虚拟人设
+ +流程
-
-
-
-
实验结论
-有待提升的部分
]]>- 读论文 +LLM开发 - 情绪支持对话 +Langchain - 论文阅读 HEAL -/-2023/HEAL_%20A%20Knowledge%20Graph%20for%20Distress%20Management%20Conversations/ -Title: A Knowledge Graph for Distress Management -Conversations - - 论文速览
-Abstract
--
-
NLP +任务:情感分析、文本生成、命名体识别、阅读理解、掩码填充、文本摘要、机器翻译、特征提取、对话机器人。
+NLP +数据集大多是未标注的文档,因此采用自监督学习的方式训练模型,如预测下一个词 +LM、完形填空 MLM。早些年,流行的是词嵌入 Word +Embedding,目标是采用向量的形式表示词元,采用一组向量表示一段话,可以用于计算词/句子相似度。
+现阶段,Transformer 的出现促使三种类型的模型的出现:前缀语言模型 +Encoder-Decoder(prefix-lm);掩码语言模型/自编码模型 +Encoder-Only;因果语言模型/自回归模型 Decoder-Only。Encoder-only +适用于机器翻译、句子分类、命名体识别和问答(大概);Decoder-only +适用于文本预测;Encoder-Decoder 适用于文本压缩。
+基础知识
+预训练显存占用
+样例:大小为 n B的模型,Adam 优化器,混合精度 fp16, +b(batch_size),s(sequence len),h(hidden size)
+-
+
数据获取和清洗
++
+少量高质量数据优于大量低质量数据
+Tokenizer
+特殊 Token
-
-
[Q] Tokenizer 是选左 Padding 还是右 Padding?
+训练和推理阶段的 <PAD> 标记是填充在左边还是右边都可以
-
-
优化器
+在石器时代,人们直接使用
+loss.backward()
+计算梯度,乘以固定的学习率,得到所有参数更新的幅度。然而,使用固定的学习率,在梯度变化剧烈的地方,会导致更新不稳定或收敛慢。为提高收敛效果,出现了很多优化器,它们被收藏在 +
+torch.optim
里面,最出名的应该是 +Adam
、AdamW
、SGD
三大天王,待我娓娓道来。Adam
+自适应学习率: Adam +通过计算一阶和二阶矩估计来为每个参数自适应地调整学习率;
+偏差校正: +初始阶段梯度估计可能偏低,通过偏差校正可以加速初期的学习速率;
+适应性强: Adam 在很多不同的模型和数据集上都表现出了良好的性能;
+减少显存占用
+混合精度训练:FP16 +速度快,占用小,适合前向传播、反向传播、矩阵计算;FP32 +精度高,适合梯度累积、权重更新、归一化、softmax(可以通过动态损失缩放减少精度损失)
+梯度累积: +
+loss = loss / self.args.gradient_accumulation_steps
,更稳定的梯度估计梯度检查点:
+gradient_checkpointing=True
+只保存计算代价大且显存占用少的中间激活值,在反向传播时重新计算未保存的激活值采样
+top_k +(int):每次保留概率最大的几个序列,再按照概率选择保留的序列(不适用于概率分布平滑的情况)
+top_p (float: 0~1):保留前n个概率和大于 p +的序列,再按照概率选择保留的序列(适用于概率分布平滑的情况,按照概率采样,提高响应多样性)
+temperature:优化了 Softmax 函数改为 \(p(x_i)=\frac{e^{\frac{x_i}t}}{\sum_{j=1}^ne^{\frac{x_j}t}}\),温度越小 +softmax 的概率分配越尖锐(确定性),反之越平滑(随机性)
+num_beams:每次保留概率最大的几个序列,最后输出概率最大的值(上面三个方法已足够,束搜索未包含在 +OpenAI API 中)
+嵌入模型
++
+提示词在嵌入模型中扮演着关键角色,提供上下文、指导生成的格式、增强模型效果、适应不同任务并减少噪声。通过使用合适的提示词,可以提高嵌入模型的性能和实用性。
+bge-large-zh-v1.5
嵌入模型的架构:-
-
关注的问题 / 本文的优势
+相对位置编码
+相对位置编码具有外推性(extrapolation +ability)的原因在于它不是将位置信息编码为与序列中的绝对位置直接相关的固定模式,而是将注意力权重或其他模型组件与元素之间的相对距离联系起来。
+编程
+Transformers及相关库
++ +
+Transformers:核心库,模型加载、模型训练、流水线并行等
+Tokenizer:分词器,对数据进行预处理,文本到token序列的互相转换。具体工作包括:分词、索引、填充截断、attention_mask、token_type
+Datasets:数据集库,提供了数据集的加载、处理等方法
+Evaluate:评估函数,提供各种评价指标的计算函数
+Trainer:将模型训练流程打包,包括:创建优化器、创建DataLoader、tensor转移到CUDA上
+PEFT:高效微调模型的库,提供了几种高效微调的方法,小参数量动大模型
+Accelerate:分布式训练,提供了分布式训练解决方案,包括大模型的加载与推理解决方案
+Optimum:优化加速库,支持多种后端,如Onnxruntime、OpenVino等
+Gradio:可视化部署库,几行代码快速实现基于Web交互的算法演示系统
+分布式训练
+Accelerate 包,融合了 Deepspeed、DDP、FSDP;
+LLaMA-Factory 源码
+trainargs.main_process_first() +内的代码只在主进程里面运行,适用于数据处理;
+为实现高效打包,替换 transformers 包内模型的 +
]]>_get_unpad_data
方法,实现4Dmask,以区分每个 batch +中的不同序列;- 读论文 +LLM基础 - 情绪支持对话 -知识图谱 +大模型基础 - +论文阅读 KEMI -/-2023/Knowledge-enhanced%20Mixed-initiative%20Dialogue%20System%20for%20Emotional%20Support%20Conversations/ -Title: Knowledge-enhanced Mixed-initiative Dialogue -System for Emotional Support Conversations - +- -
论文速览
-Abstract
--
-
优化注意力机制,降低处理长序列时的计算复杂度。
+分组查询注意力 GQA
+MQA 将所有注意力头的键和值共享
+GQA 的方式是将多个注意力头分成组,每组头共享同一组的键和值。
++
实现方式:
+transformers.models.llama.modeling_llama.repeat_kv
+复制多次 KV,使用expand
而不是repeat
是因为 +KV 的参数是组内共享的旋转位置编码 PoRE
++
+通过旋转编码,使得每个 token +既有相对位置信息,又有绝对位置信息,Qwen2 的位置信息编码是在 attention +中计算到 KV 中的
+例如,对于一个维度为 512 的向量\(v=(v_0,v_1,v_2,v_3,...,v_{511})\),RoPE +可能将其看作:
-
-
然后,通过旋转矩阵分别对每一对进行旋转,使得每一对的旋转角度与相对位置相对应。
+ ++
代码层面,Qwen2 构造
+Qwen2RotaryEmbedding
类和 +apply_rotary_pos_emb
方法, +Qwen2RotaryEmbedding
类基于 seq_len 返回缓存的 cos 和 sin +数据,apply_rotary_pos_emb
方法将位置信息作用到\(K\)和\(V\)上。均方根归一化 RMSNorm
+矩阵计算要进行归一化防止不同特征的取值过大,常用的是 layer +norm,也就是每一项减去样本的均值,再除以样本的方差;而 RMS +则是去除了减去均值的操作,以便提升效率。
-
-
\(\text{LN}(x) = \frac{x - \mu}{\sigma} +\cdot \gamma + \beta\)
-
-
LN 会计算整个输入的均值 \(\mu\) +和标准差 $ $,并用它们对输入进行标准化。
+\(\text{RMSNorm}(x) = +\frac{x}{\text{RMS}(x)} \cdot \gamma\)
-
-
RMSNorm 只关注输入的 +范数(幅值),而不考虑均值,避免了对数据的中心化处理。
+它是一种更轻量级的标准化方法,在某些情况下可以提高训练效率和收敛速度。
+激活函数 SwiGLU
+SwiGLU 将 GLU 的门控改为
+Swish
,后验证实其在 GLU +的众多变体里效果最好,优于 Transformer 一开始使用的 +ReLU
。\(F.silu(self.w1(x)) * +self.w2(x)\),其中 silu 公式为 \(\mathrm{Swish}_\beta(x)=x\otimes\sigma(\beta +x)\)
+]]>+ +LLM基础 ++ +大模型结构 ++ -大模型微调 PEFT 方法 +/-NLP/LLM-PEFT/ ++ -因此,近年来研究者们提出了各种各样的参数高效迁移学习方法,即固定住预训练模型的大部分参数,仅调整模型的一小部分参数来达到与全部参数的微调接近的效果。调整的可以是模型自有的参数,也可以是额外加入的一些参数。目前的微调方法分为加性方法、选择性方法、重参数化方法和混合方法。
+ +Q&A
+[Q] 什么情况下模型显存占用大?
-
-
[Q] 为什么减少了可训练参数就会减少显存占用?
-
-
+以 LP32 精度全量微调一个 1.3B 的模型需要占用多少显存?
模型权重:1.2G * 4B = 4.8GB
梯度:1.2G * 4B = 4.8GB
优化器状态:1.2G * 4B * 2 = 9.6GB
前向激活值:取决于序列长度、隐层维度、batch size
实际加载后,占用大约 20GB 的显存[Q] 模型训练过程中有什么有效的减少显存占用的方法?
-
-
[Q] 为什么需要 PEFT?
-
-
[Q] 有哪些显存优化策略?
-
-
背景
+2018年Bert问世后,NLP +研究的趋势转变为“预训练模型+微调”。虽然更大的模型带来了更好的性能,但以传统的方式对模型进行全量微调会消耗巨大的计算和存储资源,过高的硬件门槛不利于该领域的研究和发展。
+在此背景下,参数高效微调和量化技术应运而生,参数高效微调方法仅对模型的一小部分参数(这一小部分可能是模型自身的,也可能是外部引入的)进行训练,便可以为模型带来显著的性能变化,一些场景下甚至不输于全量微调,颇有一种四两拨千斤的感觉。
+由于训练一小部分参数,极大程度降低了训练大模型的算力需求,不需要多机多卡,单卡即可完成对一些大模型的训练。不仅如此,少量的训练参数对存储的要求同样降低了很多,大多数的参数高效微调方法只需要保存训练部分的参数,与动辄几十 +GB 的预训练大模型相比,几乎可以忽略。
+当下流行 PEFT 结构一览:
++
常用的参数高效微调方法:
+ +-
-
实现方法
+开源工具
++
++ + ++ + + + + + +开源项目 +微调方法 +实现方法 ++ +Llama +Factory +GaLore、BAdam、DoRA、LongLoRA、LLaMA +Pro、Mixture-of-Depths、LoRA+、LoftQ、PiSSA +peft 包、编写 LongLoRA、LlamaPro +流程【重点是对微调流程的整体架构,包括量化、数据预处理、加速训练、评估和模型存储等,用户可以开箱即用】 ++ +Swift +LoRA、LoRA+、LLaMA +Pro、GaLore、LISA、UnSloth、SCEdit、NEFTune、LongLoRA、Adapter、IA3、AdaLoRA +peft 包、编写 LongLoRA、LoRA、LlamaPro、Adapter 流程 ++ +llama-recipes +LoRA、QLoRA、IA3、AdaLoRA +peft 包 ++ +Firefly +LoRA、QLoRA +直接操作模型结构,为所有全连接添加 Adapter ++ + +Axolotl +LoRA、QLoRA、ReLoRA +peft 包、编写 ReLoRA 流程 +开发包
+Bitsandbytes:训练过程中的参数量化、压缩和加速
+Peft(没有Adapter方法的实现):参数高效微调技术,旨在通过最小化微调参数的数量和计算复杂度来提高预训练模型在新任务上的性能(可以实现)
+Adapters:HuggingFace Transformers +的附加库,将各种适配器方法集成到最先进的预训练语言模型中,以最小的训练和推理编码开销。
+DeepSpeed:提供了从训练到推理的全面优化方案,包括参数初始化、训练加速、内存优化等多个方面
+开源数据集
+ +测评方法
+Acc、F1、PPL、Distinct-n、BLUE-n、Rouge-n、Rouge-L
+微调算法
++
+不包括:
-
-
基于加法 +PEFT:增加额外可训练模型结构或参数(Embedding、MLP、LSTM),如:Prompt +Tuning、Prefix Tuning、Adapter;
+基于选择 PEFT:直接微调大模型中的一部分参数,如:BitFit、LN +Tuning;
+基于重参数化 +PEFT:在已经训练好的参数矩阵的基础上,增加可训练、可合并的参数,如:LoRA、AdaLoRA、PISSA、GaLore;
+融合上述三种方法的 PEFT:混合上述三种方法,如:MAM +Adapter、UniPELT;
+高效量化:不降低训练效果的前提下,降低计算资源的需求,如:QLoRA;
+并行训练:提升训练速度,SLoRA;
+工程系统角度的优化:梯度检查点、内存卸载;
+可训练参数量比较:IA3 < BitFit < Prompt-Tuning < Lora = +Prefix-Tuning
+BitFit
+只训练模型中的 bias 部分,冻结其他参数。
+优势:
-
-
不足:
-
-
LN-Tuning
+单独调整 LayerNorm 模块的 weight 和 bias +参数,训练参数量少,便于和其他的微调方法一起使用。
+ ++
实验表明,Prefix-Tuning + LN 的微调效果最佳。
+优势
-
-
Prompt-Tuning
+冻结预训练大模型的全部参数,在训练的输入数据前加入一小段 +Prompt,只训练 Prompt 的表示层,即一个 Embedding +模块。
+其中,Prompt 存在两种形式,分别是 hard prompt 和 soft prompt。hard +prompt 通过人工输入的提示词初始化 prompt,soft prompt 随机初始化 +prompt。二者相比,hard prompt 可控性更强,训练速度更快。为了优化Soft +prompt 的效果,后续研究提出了 P-Tuning。
++
+ +可训练模块:Embedding(virtual_token, hidden_size)
++
优势:
-
-
不足:
-
-
P-Tuning
+在 Prompt-Tuning 的 Soft Prompt 基础上,对 Prompt +部分进行进一步的编码计算,加速收敛。具体来说,PEFT +包中支持两种编码方式,一种是 LSTM,一种是 MLP。
++
+可训练模块:Embedding(virtual_token, hidden_size) + MLP/LSTM
++
优势:
-
-
不足:
-
-
Prefix Tuning
+将可学习的前缀以 past_key_values 的形式放到模型的 attention 的 KV +头部,每个 MHA 中的注意力层共享同一组前缀。
++
+past _key_values:Transformer 模型中历史计算过的 key 和 value +的结果,最早是用于生成类模型解码加速,解码逻辑是根据历史输入,每次预测一个新的 +Token,然后将新的 Token 加入输入,再预测下一个 +Token。这个过程中,会存在大量的重复计算,因此可以将 key 和 value +的计算结果缓存,作为 past_key_values +输入到下一次的计算中,这一技术又被称之为 kv cache。
++ +# 可训练模块:Embedding + MLP,与 P-Tuning 的区别是 prefix 映射到了模型的隐藏层上
self.embedding = torch.nn.Embedding(num_virtual_tokens, token_dim)
self.transform = torch.nn.Sequential(
torch.nn.Linear(token_dim, encoder_hidden_size),
torch.nn.Tanh(),
torch.nn.Linear(encoder_hidden_size, num_layers * 2 * token_dim),
)
# transformers.models.bloom.BloomAttention 源码实现
if layer_past is not None:
past_key, past_value = layer_past
key_layer = torch.cat((past_key, key_layer), dim=2)
value_layer = torch.cat((past_value, value_layer), dim=1)+
优势:
-
-
-
-
相关工作分析
-可以提升的地方
-]]>- -读论文 -- -情绪支持对话 -- 论文阅读 MISC -/-2023/MISC_%20A%20MIxed%20Strategy-Aware%20Model%20Integrating%20COMET%20for%20Emotional%20Support%20Conversation/ -Title: A MIxed Strategy-Aware Model Integrating -COMET for Emotional Support Conversation - - -
论文速览
-Abstract
+不足:
-
-
P-Tuning V2
+与 Prefix Tuning +最大的区别在于:移除重参数化的编码器,即没有MLP。
+通过共享连续提示同时优化多个任务,多任务学习是 P-Tuning v2 +的可选功能,可以通过多任务共享前缀进一步提升性能。
+ ++
优势:
-
-
不足:
-
-
Diff pruning
+不是修改模型的结构,而是通过一个特定任务的 diff +向量扩展基础模型。学习特定于任务的差异向量,该向量扩展了原始预训练参数。diff +向量 \[\delta_{task}\] +在训练过程中自适应修剪,并加入 𝐿0 范数惩罚的可微近似来鼓励稀疏性。
+\[\theta_{task}=\theta_{pretrained}+\delta_{task}\]
+不足:
-
-
LoRA
+深度网络由大量 Dense +层构成,这些参数矩阵通常是低秩的。相关工作表明,在适应特定任务时,预训练模型是过度参数化的,hidden_size +实际上存在于一个较低的内在维度上,即高维数据实际是在低维子空间中。
+因此,将 \(\Delta\mathbf{W}\) +用两个更参数量更小的矩阵 \(\mathbf{A}\in\mathbb{R}^{d\times r}\) 和 +\(\mathbf{B}\in\mathbb{R}^{r\times d}\) +低秩近似(r<d)。其中,矩阵 B 通过高斯函数初始化,矩阵 A +为全零初始化,使得训练开始之前旁路对原模型不造成影响。
+具体而言,冻结预训练的模型权重,并将可训练的秩分解矩阵注入到大模型的每个 +Attention +层的线性变换中。输入分别与原始权重和两个低秩矩阵进行计算,共同得到最终结果。
+ ++
训练完成后,可以将两个低秩矩阵与原始模型中的权重进行合并,合并后的模型与原始模型无异,避免了推理期间 +Prompt 系列方法带来的额外计算量。
+\[\mathbf{h}=(\mathbf{W}_0+\Delta\mathbf{W})\mathbf{x}=\mathbf{W}_0\mathbf{x}+\mathbf{B}\mathbf{A}\mathbf{x}\]
+优势:
-
-
不足:
-
-
IA3
++
+由于不同大模型结构不同,源码实现有差别。bloom 预训练模型的 QKV 共用 +Linear 层 (hidden_size, hidden_size*3),IA3 +的可训练参数同时作用于三者之上
+抑制和放大内部激活,通过可学习的向量对激活值进行抑制或放大。具体来说,通过一组可训练参数直接于 +K、V、FFN 相乘,针对不同 batch +的同一位置进行相同的调整(即乘上相同可学习参数),训练过程中冻结原始模型的权重,只更新新增的参数。训练完成后,与 +Lora 类似,可以将学习部分的参数与原始权重合并,没有额外推理开销。
+ ++
优势:
-
-
不足:
-
-
AdaLora
+AdaLora +在微调过程中,采用“先探索参数空间,再关注最重要的权重”的方法,不预先指定矩阵的秩,而是动态更新增量矩阵的秩,因为研究发现权重矩阵的重要性在不同模块和层之间存在显著差异。在该微调方法中,需要先找到更加重要的矩阵,给其分配更多的参数(更大的秩),并裁剪不重要的矩阵。相比于Lora,该方法在提升模型效果的同时,降低了参数计算量。
+区别于 Lora 的低秩矩阵分解,AdaLora +采用参数化矩阵来模拟奇异值分解(SVD),并舍弃不重要的奇异值,保留奇异向量。由于对一个大矩阵进行精确 +SVD +分解的计算消耗非常大,这种方法可以加速计算,同时保留未来恢复的可能性并稳定训练。
+\[W=W^{(0)}+\Delta=W^{(0)}+P \Lambda +Q\]
+计算三元组 QKV +的重要性分数,修剪不太重要的奇异值,将更多预算留给优先级较高的增量矩阵。
\[\boldsymbol{B}^{s}=\bigcup_{j=1}^{N_{r}}\operatorname{COMET}\left(\mathrm{rel}_{j},\boldsymbol{s}\right)\]
--
-
AdapterFusion
+整合来自多个任务的知识的方法时,常遇到灾难性遗忘和多任务数据集平衡方面的困难。AdapterFusion +分离知识提取和知识组合这两个阶段,可以以非破坏性的方式有效地利用从多个任务中学到的表示。知识提取阶段学习Adapter +任务特定参数,其封装了特定于任务的信息;知识组合阶段将不同任务的 Adapter +组合到一起。
+ ++ +
+
AdapterFusion +组件将在不同任务上训练的多个适配器的输出作为输入,并学习编码信息的参数化混合器,应用于单个任务多 +Adapter 的场景和多任务混合的场景。单任务场景中,可以多个 Adapter +可用于提取同一下游任务不同维度的信息,再将他们融合起来。
+优势:
-
-
AdapterDrop
+该方法在不影响任务性能的前提下,动态高效的移除冗余的 +Adapter,可以尽可能地减少模型的参数量,提高模型在反向传播(训练)和正向传播(推理)时的效率。
+ ++
优势:
-
-
MAM Adapter
+分解了最先进的参数高效迁移学习方法的设计,并提出了一个在它们之间建立联系的统一框架。
+ ++
UniPEFT
+不同的 PEFT +方法在同一任务上的表现不同,因此为特定任务选择最合适的方法并非易事,特别是考虑到新 +PEFT 方法和任务数量的快速增长。鉴于模型的多样性和模型选择的难度,UniPEFT +提出了一个统一的框架 UniPEFT,它将不同的PEFT +方法作为子模块,并通过门控机制学习激活最适合当前数据或任务设置的方法。
+ ++
PISSA
++
+peft 包中有 PISSA 初始化方法 +
+self.pissa_init(adapter_name, init_lora_weights)
PISSA 和 LoRA 主要的区别是初始化方式不同。同样基于低秩特性的假设,但 +PISSA 不是去近似,而是直接基于原矩阵操作。
+PiSSA 对预训练模型的参数矩阵\[W\in +R^{m\times n}\] 进行奇异值分解,其中前 r +个奇异值和奇异向量用来初始化适配器 (adapter) 的两个矩阵\[A\in R^{m\times r}\] 和\[B\in R^{r\times n}\] ,; \[r\ll\min(m,n)\] +剩余的奇异值和奇异向量用来构造残差矩阵\[W^{res}\in R^{m\times n}\] ,使得\[W=AB+W^{res}\] +。因此,适配器中的参数包含了模型的核心参数,而残差矩阵中的参数是修正参数。通过微调参数量较小的核心适配器 +A、B,冻结参数量较大的残差矩阵 \[\text{Wres}\] +,就达成了用很少的参数近似全参数微调的效果。
+ ++
优势
-
-
VeRA
+区别于Lora,Vera 将 A 和 B +矩阵按照高斯分布随机初始化并冻结,只训练两组直接和A、B相乘的一维参数。虽然直观看起来A和B像两个无用的张量,但实际上它们仍然是必不可少的,实验证明即使是随机张量也可以用于微调。
+ ++
优势:
-
-
DoRA
+将每个高阶矩阵都分解为 1*k 大小矩阵和 d*k 方向矩阵的乘积,LoRA +倾向于同时改变幅度和方向,DoRA可以更容易地将二者分开调整,或者用另一个的负变化来补偿一个的变化。
+ ++
SLORA
+一个 GPU 上并行执行多个 lora adapters 的微调
+S-LoRA 能够在单个 GPU 上或跨多个 GPU 以较小的开销为数千个 LoRA +适配器提供服务。该方法将所有 LoRA +模块存储在主内存中,并将当前运行的查询使用的适配器获取到 GPU +内存,提出采用统一分页技术,使用统一的内存池来管理具有不同等级的动态适配器权重和具有不同序列长度的 +KV 缓存张量。此外,该方法采用新颖的张量并行策略和高度优化的定制 CUDA +内核,可视为定制化的 LoRA微调高效计算流程。
+GaLore
+梯度低秩投影(GaLore)是一种全量参数学习的训练策略,但比常见的低秩自适应方法(LoRA)更节省内存。其关键思想是利用权重矩阵 +W 的梯度 \[G\in \mathbb{R}^{m\times +n}\] 缓慢变化的低秩结构,而不是试图将权重矩阵本身近似为低秩。
+优势:
-
-
不足:
-
-
该方法的优势
+LoRA+
+LoRA 中的适配器矩阵 A 和 B 以相同的学习率更新,实验表明对 A 和 B +使用相同的学习率并不能实现有效的特征学习,LoRA+ 通过精心选择的固定比率为 +LoRA 适配器矩阵 A 和 B 设置不同的学习率,纠正 LoRA 的这种次优性。
+ ++
LongLoRA
+LongLoRA +扩展了模型的上下文,同时保留了其原始架构,并且与大多数现有技术兼容。一方面,虽然推理过程中需要密集的全局注意力,但微调过程更需要稀疏的局部注意力实现有效且高效反向传播。由此,该方法提出转移稀疏注意力
+\[S^2-Attn\]
+有效地实现了上下文扩展。另一方面,除了在线性层中训练 LoRA +权重之外,LongLoRA +还进一步使嵌入层和归一化层变得可训练,由此可以表现出较好的性能。从实现上来看,该方法在训练中只需两行代码即可实现,且在推理中是可选的,不会占用额外计算资源。
++
RsLoRA
+LoRA通过在选定层添加可训练的低秩Adapter来实现参数有效的微调。每个LoRA由两个低秩矩阵乘积组成,并乘以一个与秩相关的因子,传统的LoRA采用“直接除以秩的因子”的方法过于激进,导致高秩Adapter的学习速度减缓,性能受限。因此,在实际应用中,LoRA通常仅限于使用非常低的秩。
+rsLoRA深入研究了 LoRA 的缩放因子对学习过程的影响,并证明了 LoRA +应该除以秩的平方根而不是秩,通过使用较大的秩在训练期间增加计算资源以获得更好的微调性能,同时不改变推理计算成本。
+ ++
LLaMA Pro
+该方法提出的Block +Expansion方法,即块扩展,在保持预训练模型参数不变的基础上,增加新的block来适应新的训练任务。这些新加入的block与原有block协同工作,既保留了模型原有的知识,又能够适应新的训练数据和任务需求。
+ ++
方法性能对比
+从方法类型、是否存储高效、是否内存高效、反向传播成本、推理开销五个维度比较 +PEFT 方法:
++
各种参数高效方法的参与训练的参数量、最终模型与原始模型的改变参数(delta值)以及论文中参与评估的模型的范围:
++
PEFT +方法在何种模型大小上进行过评估,以及在论文中通常使用的可训练参数数量。我们所说的可训练参数数量是指由梯度优化算法更新的参数数量,而不是我们用“更改参数”表示的原始模型与最终模型之间的差异。对于重参数化方法,我们报告了重参数化前后的参数数量。由于S4模型在不同层使用了不同的方法,因此估算其更新后的参数数量比较复杂。我们报告了在已发表的文献中对这些方法进行评估的范围。
+近年来,基于Transformer架构的大语言模型(LLM),在众多自然语言处理(NLP)任务达到了最佳性能表现。目前,构建领域专用LLM的主流策略是:在海量通用数据集上预训练的大语言模型(PLM),并通过针对特定下游任务的微调(Fine-tuning)。相较于直接采用PLM,针对下游任务的微调能显著提升模型性能。然而,随着LLM参数规模急剧增长,在消费级硬件上进行微调变得不切实际。
+为应对此挑战,研究者们近年来提出了参数高效微调技术(Parameter-Efficient +Fine-Tuning, +PEFT),其核心思想在于固定PLM的大部分参数,仅调整一小部分关键参数或引入额外参数,以接近直接微调PLM的效果。这种方法不仅保留了PLM的广泛知识库,还显著降低了计算与存储需求,为在资源受限环境下高效微调LLM开辟了新路径。
+高效量化
+QLoRA
+创新点:
-
-
可以提升的地方
+优势:
-
-
LoftQ
+该方法一种新的量化框架,在对 LLM 进行量化的同时,为 LoRA +微调找到合适的低秩初始化。这种初始化减轻了量化模型和全精度模型之间的差异,并显着提高了下游任务的泛化能力。
+GPTQ
+AWQ
+GGUF
+微调方法适配
++
+如何将微调模型应用在 自定义/未被官方适配 的大模型上
+通过
+target_modules
和modules_to_save
+实现自定义可训练参数和模块Merge Peft Model:将预训练好的 Lora 或 IA3 +的模型参数融入预训练模型中,实现不修改原模型的结构和参数量
]]>- 读论文 +LLM微调 - 情绪支持对话 +大模型微调 - +论文阅读 BlenderBot -/-2023/Recipes%20for%20building%20an%20open-domain%20chatbot/ -Title: Recipes for building an open-domain -chatbot - +-
- -FaceBook 在本文中提出了 BlenderBot 编解码器模型
-论文速览
-Abstract
--
-
光标移动
-
-
编辑文本
-
-
搜索和替换
-
-
文件操作
-
-
Screen
+基本命令
-
-
在
+screen
会话中操作在
screen
会话中,所有命令都以Ctrl + a
+开头(表示“前缀键”),然后跟随其他按键来执行操作。-
-
会话管理
-
-
+ +开发工具 ++ +Linux工具 ++ +基于 Langchain 的 RAG 架构底层原理 +/-NLP/LLM-RAG-Langchain/ +当下,微调(Fine-Tuning)和检索增强生成(Retrieval-Augmented +Generation,简称RAG)是大型语言模型(LLM)与专有数据之间融合贯通的最主流的两种方法。微调对数据集和硬件要求高,如果没有足够大的平台很难深入研究,因此本文主要涉及检索增强生成(RAG架构)领域知识。 + +概念
+RAG 是一种使用额外数据增强 LLM 知识的技术,是 2020 年发表的论文 面向知识密集型 NLP +任务的检索增强生成中提出的新思想。LLM +通过外部知识源获取额外信息,从而生成更准确、更符合上下文的答案,并减少错误信息(或称为“幻觉”,即模型对用户意图的误解或在处理特定指示时产生了不准确的推断)。典型的 +RAG 应用程序有两个主要组件:
-
-
索引 Indexes
+结构化文档,以便 LLM 可以与外部文档交互。 +LangChain有许多模块可帮助您加载、结构化、存储和检索文档。
+代理 Agents
+代理涉及 LLM +做出行动决策(Observation)、执行该行动(Action)、查看一个观察结果(Observation),并重复该过程直到完成。LangChain +提供了一个标准的代理接口,一系列可供选择的代理,以及端到端代理的示例。
-
-
Training Data Safety Characteristics Evaluation Methods Related Work -Results & Analysis Released code and models Discussion # 关注的问题 -/ 本文的优势
+文本召回
++
+RAG +将匹配分为多个阶段,可分为:粗召回、细召回、粗排序、精排序、再排序。该任务包括多个子任务,如文本相似度计算、问答匹配、对话匹配,类似于RAG的文本抽取式阅读理解和多项选择
+RAG 采取召回(IF-IDF、BM25)、粗排(双塔 Bert +模型、Sentence-Bert、text2vec、uniem)、精排(单塔 Bert +模型),得到相关的文档输入 LLM 中。
+基于词匹配
++
+传统方法将词匹配、词距等分数作为特征,用线性模型或树模型预测相关性,效果远不如深度学习。
+将查询文本分词,词在文档 d 中出现的次数越多,则查询文本和文档 d +越相关
+IF-IDF
+概念
+词袋模型:(bag of words)只考虑词频,不考虑词的顺序和上下文
+词频 TF:每个词在文档中出现的次数的集合;\(\sum_{t\in\mathcal{Q}}\operatorname{tf}_{t,d}\)
-
-
实验结论
-有待提升的部分
+文档频率 DF:词 t 在多少文档中出现过,定义“词”区别文档的能力;
+逆文档排序 IDF:衡量一个词在 N 个文档中的重要性;\(\mathrm{idf}_t=\mathrm{log}\frac +N{\mathrm{df}_t}\)
+\(\mathrm{TFIDF}(\mathcal{Q},d) = +\sum_{t\in\mathcal{Q}} \frac{\mathrm{tf}_{t,d}}{l_{d}} \cdot +\mathrm{idf}_{t}.\)
+其中,查询词q的分词后得到 Q 集合,它与文档 d 的相关性用 TF-IDF +衡量;结果还取决于所采取的分词算法;
+BM25
+IF-IDF 的变种,k 和 b 是参数(通常设置为 k∈[1.2, 2],b=0.75)
+\(\sum_{t\in +Q}\frac{\mathrm{tf}_{t,d}\cdot(k+1)}{\mathrm{tf}_{t,d}+k\cdot\left(1-b+b\cdot\frac{l_d}{\mathrm{mean}(l_d)}\right)}\cdot\ln\left(1+\frac{N-\mathrm{df}_t+0.5}{\mathrm{df}_t+0.5}\right)\)
+基于词距
+两个词在文档中出现位置之间,间隔的词越少越可能相关;
+简而言之,查询词切分后的 term +在文档中出现的次数越多越好,任意两个词之间的距离越近越好;
+eg:OkaTP
+基于深度学习
+基于交互策略的单塔模型 准确度更高
+Bert 输出 similarity,二分类任务(相似/不相似)
+基于向量匹配的双塔模型 速度更快
+Bert 输出 Sentence_Embedding,拟合 cos_Similarity(回归任务)
+评价指标
+二分类评价指标 AUC
+ ++
可信度 RAG
+当检索返回的结果有错误或信息丢失时,会导致LLM回复出现幻觉。
+为解决这个问题的三个指标:可信度(Faithfulness)、答案相关性(Answer +Relevance)、上下文相关性(Context Relevance)
+Query 预处理
+同义Query,
+意图识别
+召回
+索引技术:倒排索引、压缩倒排索
+检索模型:BM25、BERT
+引入上下文信息,更好地理解用户意图
+Langchain-chatchat 源码解读
+Q&A
+Embedding 模型怎么保持加载的:EmbeddingPool;
+metaData 存在哪里:MySQL 数据库;
+LLMChain 怎么区分chatprompt和prompt的:ChatOpenAI、OpenAI;
+docstore 和
+]]>index_to_docstore_id
存在哪里:本地文件 +{index_name}.pkl
;+ +LLM开发 ++ +RAG架构 +LLM应用开发 ++ 论文阅读 RAFT +/-NLP/paper-PAFT/ +Paper + 创新点
+提出了新颖的特定 RAG 场景下的大模型微调方法(有明确文档域的 +RAG);
+基于 COT,进一步完善了模型的推理能力;
+背景
+当前的开放域对话模型做的是”闭卷考试“;
+RAG 做的是”开卷考试“,其结果依赖于检索器的效果;
+PAFT +应用于”特定领域的开卷考试“,模型先在特定域文档内学习如何做”开卷考试“,可以提高模型 +RAG 的能力,还能减少幻觉的产生;
+实验
+方法
+前置条件:\(\mathrm{Q}\)问题; \(\mathrm{A}^{*}\) 答案; \(\mathrm{D}^{*}\) 答案来源文档; \(D_n\) 无关文档。
+正例样本:\(Q+ \mathrm{D^*} ++D_1+D_2+\dots+D_k=>\mathrm{A}^{*}\)
+负例样本: \(\mathrm{Q}+\mathbf{D}_{1}+\mathbf{D}_{2}+\dots+\mathbf{D}_{\mathbf{k}}=>\mathbf{A}^{\star}\)
+论文中基于数据集做全量 SFT 训练
+数据集
++Question: The Oberoi family is part of a hotel company that has a head office in what city?
context: [The Oberoi family is an Indian family that is famous for its involvement in hotels, namely through The Oberoi Group]...[It is located in city center of Jakarta, near Mega Kuningan, adjacent to the sister JW Marriott Hotel. It is operated by The Ritz-Carlton Hotel Company. The complex has two towers that comprises a hotel and the Airlangga Apartment respectively]...[The Oberoi Group is a hotel company with its head office in Delhi.]
Instruction: Given the question, context and answer above, provide a logical reasoning for that answer. Please use the format of: ##Reason: {reason} ##Answer: {answer}.
CoT Answer: ##Reason: The document ##begin_quote## The Oberoi family is an Indian family that is famous for its involvement in hotels, namely through The Oberoi Group. ##end_quote## establishes that the Oberoi family is involved in the Oberoi group, and the document ##begin_quote## The Oberoi Group is a hotel company with its head office in Delhi. ##end_quote## establishes the head office of The Oberoi Group. Therefore, the Oberoi family is part of a hotel company whose head office is in Delhi. ##Answer: Delhi从数据集
+Answer
+中可以看出,提问者引导模型以思维链的方式去回答问题,先说原因 +Reason
再说答案Answer
文中采用 ##begin_quote## 和 ##end_quote## +表示直接从上下文复制粘贴的引用,研究人员发现这是防止模型产生幻觉并坚持提供的上下文的有效方法。
+实验结果
+DSF(Domain-Specific Finetuning):特定领域内微调
+PAFT:特定领域微调+特定领域 RAG
++
总结
+将模型在特定领域的文档上做思维链微调
-
-
读论文 +LLM微调 - 情绪支持对话 +大模型微调 @@ -3663,8 +4227,8 @@ href="https://www.cnblogs.com/yescode/p/14474104.html#autoid-0-0-0">锁升级策 -public class ReentrantLock implements Lock {
// 同步控制器(指向公平锁或非公平锁)
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer{
final boolean nonfairTryAcquire(int acquires) {...}
protected final boolean tryRelease(int releases) {...}
}
// 不公平锁
static final class NonfairSync extends Sync{
final void lock() {...}
protected final boolean tryAcquire(int acquires) {...}
}
// 公平锁
static final class FairSync extends Sync {
final void lock() {...}
protected final boolean tryAcquire(int acquires) {...}
}
// 实现 Lock 接口
public void lock() {
sync.lock();
}
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
public void unlock() {
sync.release(1);
}
}
- -ReentrantLock
独占锁运行过程(可重入锁的state
表示==重入的次数==,会大于1)+ +
加锁失败时阻塞
@@ -3749,8 +4313,8 @@ CLH 锁实现线程阻塞等待以及被唤醒时锁分配。ReentrantLock
在 CAS 加锁失败之后会将 Thread 封装成一个Node
类型的对象加入CLH
队列中线程调度逻辑: 当线程尝试获取资源失败时,会创建一个==Node节点==并将当前线程包装进去,然后利用==CAS算法==将其安全地加入到==等待队列的尾部==,并阻塞。Link
- -+ +
在释放资源时,AQS会根据资源管理策略从队列中选择合适的节点并唤醒对应线程。
CLH 锁
@@ -3861,143 +4425,19 @@ href="https://juejin.cn/post/7023021536231555086">Link Redis +Lua 来做限流)
CountDownLatch
倒计时器:
-await()
阻塞当前线程,当 -count
为零(即 state)时,唤醒所有被阻塞的线程。
-CountDownLatch
-是一次性的,计数器的值只能在构造方法中初始化一次,之后没有任何机制再次对其设置值,当 -CountDownLatch
使用完毕后,它不能再次被使用CyclicBarrier
-循环栅栏:让==一组线程==到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程都会继续干活。
-]]> -- -Java基础 -- -Java并发 -Java并发锁 -- 论文阅读 ESConv -/-2023/Towards%20Emotional%20Support%20Dialog%20Systems/ -Title: Towards Emotional Support Dialog Systems - - 论文速览
--
-
-
-
实验结果好在哪里,怎么证明的
-相关工作分析
--
-
count
为零(即 state)时,唤醒所有被阻塞的线程。 +
+CountDownLatch
+是一次性的,计数器的值只能在构造方法中初始化一次,之后没有任何机制再次对其设置值,当 +CountDownLatch
使用完毕后,它不能再次被使用CyclicBarrier
+循环栅栏:让==一组线程==到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程都会继续干活。
]]>- 读论文 +Java基础 - 情绪支持对话 +Java并发 +Java并发锁 @@ -4324,11 +4764,11 @@ ThreadLocalMap 里面 -原理
public class ThreadLocal<T> {
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
// 存放数据
private Entry[] table;
}
}整体结构图
- -+ +
引用关系图
- -+ +
Q&A
Entry的key为什么设计成弱引用?
ThreadLocal 变量生命周期结束后,ThreadLocal 对象就可以被回收;
@@ -4484,14 +4924,14 @@ TLAB)+ +
+ +
对象的内存布局
Mark Word 是一个具有动态定义的数据结构,以便在极小的空间内存储尽量多的数据,根据对象的状态复用自己的存储空间。
@@ -4664,8 +5104,8 @@ href="https://heapdump.cn/article/1661497">YGC、FGC类加载过程
类的生命周期:加载、连接、初始化、使用、卸载 - -+ +
- Java 面试常见问题和知识点 -/-developer/Java-Interview/ -Java-basic - -JVM
--
-
JUC
--
-
中间件
--
-
- -工作 -- -面试 -Java 常用数据结构的底层实现 /-developer/Java-DataStructure/ @@ -4877,8 +5290,8 @@ O(1),其他情况增删元素的平均时间复杂度都是 O(n) 。JDK1.8 之前 HashMap 采用“拉链法”处理冲突,由 数组+链表 组成; JDK1.8 以后,若Table长度大于 64,会将链表转化为红黑树。
- -+ +
CopyOnWriteList
--
-并发安全的 -
-List
,针对读多写少的场景,类比读写锁的思想,实现 -读读不互斥、读写不互斥、写写互斥 的写时复制 -Copy-On-Write 策略。此外还有Collections.synchronizedList
-,可以将任何List
包装成一个线程安全的List
add 方法内部用到了 ReentrantLock -加锁,避免了多线程写的时候会复制出多个副本,导致并发问题
-写时复制的缺点
--
-
写多读少的场景下,应该用什么数据结构实现并发数组?
-分段读写锁 ReadWriteLock(由于 Arrays.copyOf() -是操作系统实现,数据量少的话依然可用写时复制)
-PriorityQueue
-]]> -- -Java基础 -- -Java数据结构 -- +Java 语言 -/-developer/Java/ -基础 - 基本数据类型
-除八个基本类型,Java 的所有数据类型都是引用,Java -中没有指针的概念,所有数据传输都是传值(引用可以看作是地址值,所有引用值都占四个字节)
-基本数据类型的包装类 Byte Short Integer Long Character 有常量池
-编译运行
--
-
三大特性
-封装
-将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体;
-继承
-支持类之间的单继承,但支持接口之间的多继承;
-类可以实现多个接口,抽象类不能实例化但可以有构造方法,内部类只能通过外部类创建;
-Object 是超类,是所有类的父类(无父类的子类默认继承 -Object。jdk6之前是编译器处理,jdk7之后是虚拟机处理);
-Java8 之后接口可以有默认方法,允许在接口中声明静态方法;
-多态
-全面支持动态绑定,动态绑定是实现多态(一个接口,多种实现)的基础;
--
-
关键字
--
-- - -- - - - - -关键字 -说明 -- -final -常量 -- -static -静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝;静态方法,不能使用类的非静态变量,类名直接调用,不需要进行实例化对象。 -- -native -本地、原生方法(非 Java 实现) -- -strictfp -严格浮点、精准浮点 -- -synchronized -线程、同步 -- -transient -修饰的成员属性变量不被序列化,仅存于调用者的内存中而不会写到磁盘里持久化,防止敏感信息泄露(与Serilizable接口一同使用)当对象被反序列化时,被 -transient 修饰的变量值不会被持久化和恢复,直接设置为默认值。static -不属于任何对象,因此永远不会被序列化。 -- -volatile -变量在 CPU -的寄存器中是不确定的,必须从主存中读取。保证多线程环境下变量的可见性;禁止指令重排序。 -- - -instanceof -实例 -运算符优先级
--
自动装箱/拆箱
--
-jdk1.5 i = Integer.valueOf(3) -128-127
-自动装箱通常也不会通过显式的 valueOf -方法调用实现。编译器生成的字节码可能直接使用内部指令或方法来处理装箱和拆箱,而不是通过Java方法调用机制。因此,在 -valueOf 方法上设置断点通常不会捕获到自动装箱的过程。 -
-new String("abc")
和String.valueOf("abc")
-的区别:前者在堆中创建了新的对象,后者返回字符串常量池对象的引用。拆箱:xxxValue();装箱:valueOf()-public void zhuangXiang() {
Integer a1 = 128;
Integer a2 = 128;
Integer a3 = 256;
Integer a4 = a1 + a2;
System.out.println(a1 == a2); // false
System.out.println(a4 == a3); // false
System.out.println(a1 + a2 == a3); // true 发生拆箱
}NPE 问题
--
-
动态代理
-静态代理:编译时完成 动态代理:运行时动态生成类字节码,并加载到 JVM -中
--
-
二者的具体实现
--
-
为什么 JDK 动态代理,要求被代理对象必须实现一个接口?
--
-
原生工具类
-Collections 集合操作类
--
-
Arrays 数组操作类
--
-
比较器 集合排序工具
--
-
接口实现
-接口和抽象类的关系
--
-
removeEldestEntry
方法当链表大小超过容量时返回 true构造器
-this(参数列表)来访问本类构造器需要注意以下几点
+CopyOnWriteList
++
+并发安全的 +
+List
,针对读多写少的场景,类比读写锁的思想,实现 +读读不互斥、读写不互斥、写写互斥 的写时复制 +Copy-On-Write 策略。此外还有Collections.synchronizedList
+,可以将任何List
包装成一个线程安全的List
add 方法内部用到了 ReentrantLock +加锁,避免了多线程写的时候会复制出多个副本,导致并发问题
+写时复制的缺点
-
-
动态加载
-反射(运行时获取类的信息、创建对象、调用方法)
-类加载器 ClassLoader
+写多读少的场景下,应该用什么数据结构实现并发数组?
+分段读写锁 ReadWriteLock(由于 Arrays.copyOf() +是操作系统实现,数据量少的话依然可用写时复制)
+PriorityQueue
]]>Java基础 - +Java语言 +Java数据结构 ++ 开发面试常见问题和知识点 +/-developer/Java-Interview/ +Knowledge + +Java
+JVM
+JUC
+MySQL
+Redis
+消息队列
+OS
+进程线程
+零拷贝
+【传统文件传输】磁盘缓冲区 => 内核缓冲区 => 用户缓冲区 => +Socket 缓冲区 => 网卡缓冲区,所有都由 CPU 控制;
+【DMA 拷贝】 基于 DMA 控制器而不是 CPU 实现 +“将数据从磁盘控制器缓冲区转移至内核缓冲区中”,与硬件设备之间的数据搬运工作从 +CPU 转交给 DMA 控制器;
+【零拷贝】
+mmap + write
+用户态直接共享内核的缓冲区,不需要再存入用户缓冲区,减少一次数据拷贝的消耗;sendfile
+调用一次内核命令,数据直接从内核缓冲区复制到 Socket +缓冲区,而不经过用户区,减少一次数据拷贝和两次上下文切换的消耗;Zero-copy
+网卡控制器直接读取内核缓冲区中的数据,实现最高效的传输,应用于 Nginx 和 +Kafka;【PageCache】内核缓冲区,缓存和预读磁盘数据,以提升磁盘读取速度;大文件传输不应采用 +PageCache,而是基于异步和直接 IO;
+网络模型
+【优化路线】子进程 => 子线程 => 线程池 => IO多路复用
+【select/poll】采用 BitsMap 或链表的形式储存所有 Socket +集合,每次检查都需要在内核态遍历文件描述符集合,以找到可读或可写的 +Socket;在用户态和内核态之间拷贝整一个集合,在用户态处理应用任务,在内核态检查是否有事件产生;
+【epoll】在内核中使用红黑树跟踪所有待检测的文件描述符,避免每次都要遍历所有 +Socket +集合;基于事件驱动,采用回调函数,每次都只需要从就绪任务链表中取已准备好的 +Socket;
+网络
+【TCP 四次握手三次挥手】
+Questions
+Java
+JVM
+-
+
JUC
+-
+
MySQL
+Redis
+消息队列
+-
+
OS
+进程线程+零拷贝+网络模型
+网络
+Answer
+]]>+ +工作 ++ 面试 @@ -5253,8 +5519,8 @@ MySQL 5.6.6 版本开始,它的默认值就是 1 了,因此从这个版本 中每一张表的数据都存放在一个独立的 .ibd 文件。 表空间文件的结构
- -+ +
InnoDB 行格式
共有 Redundant、Compact、Dynamic、Compressed 四种,下图时 Compact 行格式的结构
@@ -5262,8 +5528,8 @@ MySQL 5.6.6 版本开始,它的默认值就是 1 了,因此从这个版本InnoDB 页格式
InnoDB 的数据是按「数据页」为单位来读写的,数据页的默认大小是 16KB
- -+ +
@@ -5746,8 +6012,8 @@ Pool 的脏页刷新到了磁盘中,redo log 对应的记录也就没用了,这时候我们需要擦除这些旧记录,以腾出空间记录新的更新操作。重做日志文件组由有 2 个 redo log 文件组成,以循环写的方式工作,从头开始写,写到末尾就又回到开头,相当于一个环形。 - - + +
主从复制
- -+ +
binlog 刷盘
- -+ +
内部 XA 事务
- -+ +
为了保证这两个日志的一致性,MySQL 使用了内部 XA 事务。内部 XA 事务由 binlog 作为协调者,存储引擎是参与者,可以实现跨数据库事务。将 redo log 的写入拆成了两个状态:prepare 和 @@ -5871,1145 +6137,923 @@ binlog 中已经有了事务记录,MySQL会在重启后通过 redo log
脏页刷盘的时机
--
-
内存
-Buffer Pool 缓存的内容包括:索引页、数据页、Undo -页、插入缓存页、自适应哈希索引、锁信息等。
-innodb_buffer_pool_size
-默认 128MB。为了管理这些在 Buffer Pool 中的缓存页,InnoDB -为每一个缓存页都创建了一个控制块,控制块信息包括:缓存页的表空间、页号、缓存页地址、链表节点等等。用三种链表管理不同状态的缓存块:
--
-
Free 链表:使用链表结构,快速找到空闲的缓存页;
-每当需要从磁盘中加载一个页到 Buffer Pool 中时,就从 -Free链表中取一个空闲的缓存页,并且把该缓存页对应的控制块的信息填上,然后把该缓存页对应的控制块从 -Free 链表中移除
- --
Flush 链表:使用链表结构,快速找到脏页;(结构类似于 -Free 链表)
-脏页落盘时,后台线程遍历 Flush 链表
-提高缓存命中率
-Buffer Pool 有三种页和链表用来管理数据
- --
-
-
普通的LRU 算法会出现以下两个问题
--
-
解决办法
--
-
优化
-磁盘IO、索引、数据分页(查询大量数据)、锁竞争、内存使用下·
-]]> -- -数据库 -- - -MySQL -- Redis -/-developer/Redis/ -Redis 的特性:单线程、原子性、基于内存、优化数据结构、I/O -多路复用的非关系型数据库; - 6.0 版本前网络 I/O 和命令处理都是单线程,6.0 版本后网络 I/O -改用多个线程处理
--
-
数据结构
-5 -种基础数据类型:String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合) -3 种特殊数据类型:HyperLogLog(基数统计)、Bitmap (位图)、Geospatial -(地理位置)
-持久化
-保证即使在服务器重启的情况下也不会丢失数据(或少量损失)
-AOF 日志
-将每条执行成功的写操作命令追加到日志文件中,持久化代码命令在主进程上执行
-写回策略(防止AOF日志在持久化过程中丢失):
- --
重写机制(防止AOF日志文件过大):
--
-
RDB 快照
-某一时刻内存数据的快照(二进制数据),恢复时直接读入内存即可
-执行 bgsave 时,想要修改数据,需采用写时复制(Copy-On-Write, -COW),以减少性能损耗
-混合持久化
-在AOF日志重写过程中,将新的含有 RDB 格式和 AOF 格式的 AOF -文件替换旧的的 AOF 文件,前半部分是 RDB 格式的全量数据,后半部分是 AOF -格式的增量数据,即重写缓冲区数据。
-策略
-过期删除策略
-惰性删除+定期删除
-内存淘汰策略
-仅淘汰过期数据:random、ttl、lru、lfu
-淘汰所有数据:lru、lfu
-高可用
-主从复制
-模式一:全量复制【多用于初始化】
--
-
-
为了避免过多的从服务器和主服务器进行数据同步(全量复制),可以把一部分从服务器升级成分发节点,利用从节点分担读取操作的压力
-模式二:基于长连接的命令传播【多用于保持同步】
-主从服务器在完成第一次同步后,双方之间就会维护一个 TCP -连接,保证第一次同步后的主从服务器的数据一致性。
-模式三:连接恢复时可以采用增量复制:repl_backlog_buffer -环形缓冲区保存了最近传播的写命令,若其中存着从服务器请求的 -offset,就采用增量复制;否则采用全量复制。若想降低主从服务器断开后全量同步的概率,需要增大 -repl_backlog_buffer
-QA
-如何应对异步复制导致的主从数据不一致?
-外部程序来监控主从节点间的复制进度
-主从切换如何减少数据丢失?
--
-
集群脑裂导致数据丢失
-主节点必须要有至少
-min-slaves-to-write
-个从节点连接,主从数据复制和同步的延迟不能超过 -min-slaves-max-lag
-秒。否则原主节点就会被限制接收客户端写请求,客户端也就不能在原主节点中写入新数据,等到新的主节点上线一切恢复正常。哨兵机制
--
-自动完成故障发现和故障转移,并通知给应用方,从而实现高可用性
-哨兵之间建立连接
- --
哨兵与从节点建立连接
- --
第一轮投票:判断主节点下线
-主观下线:主节点或者从节点没有在规定的时间内响应哨兵的 PING 命令
-客观下线:一个哨兵判断主节点为「主观下线」后,就会向其他哨兵发起命令,通过多个哨兵节点一起判断主节点是否下线。哨兵的赞同票数达到哨兵配置文件中的 -quorum 配置项设定的值则判断主节点客观下线
-第二轮投票:选出哨兵 leader
--
-
由哨兵 leader -进行主从故障转移
--
-
集群
--
-
-
集群数据分布策略
-Hash 槽
+缓存击穿:瞬间大量请求未缓存的数据库数据,请求击穿缓存直接打到数据库上
+脏页刷盘的时机
-
-
缓存雪崩:缓存在同一时间大面积的失效,导致大量的请求都直接落到了数据库上
+内存
+Buffer Pool 缓存的内容包括:索引页、数据页、Undo +页、插入缓存页、自适应哈希索引、锁信息等。
+innodb_buffer_pool_size
+默认 128MB。为了管理这些在 Buffer Pool 中的缓存页,InnoDB +为每一个缓存页都创建了一个控制块,控制块信息包括:缓存页的表空间、页号、缓存页地址、链表节点等等。用三种链表管理不同状态的缓存块:
-
-
如何保证数据库和缓存一致性
--
-采用 Cache Aside -旁路缓存策略:以数据库中的数据为准,缓存中的数据是按需加载的;缺点:数据写入频繁时,缓存中的数据会被频繁的清理,降低缓存命中率;
-更新数据库+删除缓存:延迟双删
-更新数据库+更新缓存:分布式锁
-更新数据库+不更新缓存:较短的缓存有效期
-删除缓存的时候失败了怎么办?
-采用异步删除:
+Free 链表:使用链表结构,快速找到空闲的缓存页;
+每当需要从磁盘中加载一个页到 Buffer Pool 中时,就从 +Free链表中取一个空闲的缓存页,并且把该缓存页对应的控制块的信息填上,然后把该缓存页对应的控制块从 +Free 链表中移除
+ ++
Flush 链表:使用链表结构,快速找到脏页;(结构类似于 +Free 链表)
+脏页落盘时,后台线程遍历 Flush 链表
+提高缓存命中率
+Buffer Pool 有三种页和链表用来管理数据
+ +-
-
缓存预热
-提高访问速度,平滑流量峰值,减少后端压力,保证数据的时效性
-Redis 缓存预热的方法:系统启动时加载;定时任务加载;
-实战
-分布式锁
--
-Redis + Lua -脚本,可以以原子性的方式执行一组命令,可用于保证锁释放操作的原子性(Lua -脚本在处理的过程中不会被任意其它请求打断),但无法用于事务执行失败的回滚。Redisson -采用的就是这种方法保证分布式锁的原子性。
-SET 命令的 NX 参数可以实现:key -不存在才插入,可以用于实现分布式锁
-优点:性能高效、实现方便、分布式高可用
-缺点:不好设置超时时间(解决方法:守护线程定期续约)、主从异步复制可能导致不可靠性(解决方法如下)
-提高可靠性(Redlock 算法):客户端和多个独立的 Redis -节点依次请求申请加锁,如果客户端能够和半数以上的节点成功地完成加锁操作,那么就认为,客户端成功地获得分布式锁,否则加锁失败,所有的 -redis 实例都会进行解锁;
+普通的LRU 算法会出现以下两个问题
-
-
-@Resource
private RedissonClient redisson;延迟队列
-有序集合 Zset;score 存储延迟执行的时间
-大 Key 问题
-会导致的问题
+解决办法
+解决办法
-
-
发布者/订阅者
--
- -订阅命令:subscribe channel [channel ... ]
-- -
事务回滚
-Redis 不支持回滚,事务没有原子性(要么全部成功要么全部失败)
-管道
-批处理技术,可以一次处理多个 Redis -命令,减少多个命令执行时的网络等待
+优化
+磁盘IO、索引、数据分页(查询大量数据)、锁竞争、内存使用下·
]]>数据库 - Redis +MySQL - -Rpc 中间件 -/-developer/Rpc/ -- 分布式系统的 CAP 理论
+Java 语言 +/-developer/Java/ +基础 + 基本数据类型
+除八个基本类型,Java 的所有数据类型都是引用,Java +中没有指针的概念,所有数据传输都是传值(引用可以看作是地址值,所有引用值都占四个字节)
+基本数据类型的包装类 Byte Short Integer Long Character 有常量池
+编译运行
-
-
分布式保证服务高并发稳定性
+三大特性
+封装
+将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体;
+继承
+支持类之间的单继承,但支持接口之间的多继承;
+类可以实现多个接口,抽象类不能实例化但可以有构造方法,内部类只能通过外部类创建;
+Object 是超类,是所有类的父类(无父类的子类默认继承 +Object。jdk6之前是编译器处理,jdk7之后是虚拟机处理);
+Java8 之后接口可以有默认方法,允许在接口中声明静态方法;
+多态
+全面支持动态绑定,动态绑定是实现多态(一个接口,多种实现)的基础;
-
-
Nacos 配置中心 注册中心
-RPC 框架
+关键字
++
++ + ++ + + + + +关键字 +说明 ++ +final +常量 ++ +static +静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝;静态方法,不能使用类的非静态变量,类名直接调用,不需要进行实例化对象。 ++ +native +本地、原生方法(非 Java 实现) ++ +strictfp +严格浮点、精准浮点 ++ +synchronized +线程、同步 ++ +transient +修饰的成员属性变量不被序列化,仅存于调用者的内存中而不会写到磁盘里持久化,防止敏感信息泄露(与Serilizable接口一同使用)当对象被反序列化时,被 +transient 修饰的变量值不会被持久化和恢复,直接设置为默认值。static +不属于任何对象,因此永远不会被序列化。 ++ +volatile +变量在 CPU +的寄存器中是不确定的,必须从主存中读取。保证多线程环境下变量的可见性;禁止指令重排序。 ++ + +instanceof +实例 +运算符优先级
++
自动装箱/拆箱
-
-泛指调用远程的函数的方法,对编解码和网络层有特殊的优化,从而有更高的效率。
+jdk1.5 i = Integer.valueOf(3) -128-127
RPC 框架主要由 Server、Client、Server Stub、Client Stub 组件组成
+自动装箱通常也不会通过显式的 valueOf +方法调用实现。编译器生成的字节码可能直接使用内部指令或方法来处理装箱和拆箱,而不是通过Java方法调用机制。因此,在 +valueOf 方法上设置断点通常不会捕获到自动装箱的过程。 +
+new String("abc")
和String.valueOf("abc")
+的区别:前者在堆中创建了新的对象,后者返回字符串常量池对象的引用。拆箱:xxxValue();装箱:valueOf()+public void zhuangXiang() {
Integer a1 = 128;
Integer a2 = 128;
Integer a3 = 256;
Integer a4 = a1 + a2;
System.out.println(a1 == a2); // false
System.out.println(a4 == a3); // false
System.out.println(a1 + a2 == a3); // true 发生拆箱
}NPE 问题
-
-
层次结构:代理曾、注册中心层(服务发现、注册、管理)、
-RPC 协议定制化程度高,可以采用体积更小的 Protobuf -或其他序列化协议去保存结构体数据,同时也不需要像 HTTP -那样考虑各种浏览器行为,如 302 -重定向跳转。因此性能也会更好一些。其底层不仅可以通过 tcp udp -实现,也可以通过 http 实现。
-RPC -协议会建个连接池,在请求量大的时候,建立多条连接放在池内,要发数据的时候就从池里取一条连接出来,用完放回去,下次再复用,可以说非常环保。
-目前,对外一般用 HTTP 协议,而内部集群的微服务之间则采用 RPC -协议进行通讯。
-Dubbo 上线问题
-记录、学习、汇总实习和技术博客中看到的 Dubbo 实战遇到的问题
-服务端接口不指定通讯协议导致 -OOM
-问题背景:
-问题描述:
+动态代理
+静态代理:编译时完成 动态代理:运行时动态生成类字节码,并加载到 JVM +中
-
-
解决方法(针对框架,开发人员需要牢记 Dubbo 配置必须在接口上):
+销毁方法
+二者的具体实现
-
-
父子线程并发 RPC 调用死锁
-问题描述:
+为什么 JDK 动态代理,要求被代理对象必须实现一个接口?
-
-
+public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}原生工具类
+Collections 集合操作类
-
-
+Future<String> future = executor.submit(()->{
return 数据查询任务;
})Arrays 数组操作类
-
-
解决办法
+比较器 集合排序工具
-
-
尝试开发基础版 Rpc 中间件
-服务发现流程:使用远程服务的时候首先需要配置一个 -dubbo.xml -文件或者在使用的类加上
-@Reference
,二者都是用来对dubbo消费者引用服务进行一些配置,然后应用在启动的时候会将配置信息转化为一个ReferenceBean
对象,并调用createProxy
方法创建一个远程服务接口的代理对象。代理对象的 invoke -创建:启动时主动订阅注册中心,会显示地调用一次
+notify
接口,这个接口会尝试将远程服务注册的url
转换成一个本地的invoker
。JDK 动态代理
+接口实现
+接口和抽象类的关系
-
-
-public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
public class RpcClientProxy implements InvocationHandler {
// 在代理类内,根据传入的类 clazz,获得代理对象
public <T> T getProxy(Class<T> clazz) {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, this);
}
// 当通过代理类调用的所有方法,实际上调用的是这个invoke(传入的只是服务接口,具体的实现在服务端实现类中)
public Object invoke(Object proxy, Method method, Object[] args) {...}
}那么是如何调用服务端实现类的代码的呢?注入
--
-
-Object clientProxy = rpcClientProxy.getProxy(declaredField.getType());
declaredField.setAccessible(true);
try {
declaredField.set(bean, clientProxy);
} catch (IllegalAccessException e) {
e.printStackTrace();
}传输协议
--* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
* +-----+-----+-----+-----+--------+----+----+----+------+-----------+-------+-------+-----+---+-----+----+
* | magic code |version | full length | messageType| codec|compress| RequestId |
* +-----------------------+--------+---------------------+-----------+-----------+-----------+------------+
* | body |
* +-------------------------------------------------------------------------------------------------------+
* 4B magic code(魔法数) 1B version(版本) 4B full length(消息长度) 1B messageType(消息类型)
* 1B compress(压缩类型) 1B codec(序列化类型) 4B requestId(请求的Id)注册中心
-服务注册:在 zk 里面创建一个对应的持久节点
-当我们的服务被注册进 zookeeper -的时候,我们将完整的服务名称 rpcServiceName (class -name+group+version)作为根节点 -,子节点是对应的服务地址(ip+端口号)。相关代码在 -
-ZkServiceProviderImpl.publishService()
中。如果我们要获得某个服务对应的地址的话,就直接根据完整的服务名称来获取到其下的所有子节点,然后通过具体的负载均衡策略取出一个就可以了。相关代码在 -
-ZkServiceDiscoveryImpl.lookupService()
中。Zookeeper 客户端
--
-Curator 是 Netflix -公司开源的一套zookeeper客户端框架,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重连、反复注册Watcher和NodeExistsException异常等等。项目内采用 -CuratorUtils 类调用 Curator。
-重试策略:ExponentialBackoffRetry是指数退避重试策略
--// zk的对外接口,后面我们要干什么只需要通过单例模式获得这个类,然后用这个类的方法
public interface ServiceProvider {
// 添加到本地 serviceMap 中(远程Rpc调用,获取本地的调用类)
void addService(RpcServiceConfig rpcServiceConfig);
Object getService(String rpcServiceName);
// 注册服务到 zookeeper 中(服务发现与注册)
void publishService(RpcServiceConfig rpcServiceConfig);
}负载均衡
-随机选取策略 轮询策略 加权轮询策略 最少活跃连接策略 一致性 Hash -策略
-序列化
+构造器
+this(参数列表)来访问本类构造器需要注意以下几点
-
-
数据传输过程中,可能会出现粘包和半包问题,你是如何解决的?
-自定义消息结构(其他的还有固定长度传输、特殊字符分割):MagicNumber -魔数、ContentLength 请求长度
+动态加载
+反射(运行时获取类的信息、创建对象、调用方法)
+类加载器 ClassLoader
]]>- -Java开发 -- -远程过程调用框架 -- +Spring 开发框架 -/-developer/Spring/ -SpringCore 主要提供 IoC 依赖注入功能的支持 SpringMVC 快速构建 MVC -架构的 Web 程序 SpringBoot 简化 Spring 开发,减少配置文件,开箱即用 - IOC 控制反转
--
-当一个对象创建时,它所依赖的对象由外部传递给它,而非自己去创建所依赖的对象(比如通过new操作)。因此,也可以说在对象如何获取它的依赖对象这件事情上,控制权反转了。这便不难理解控制反转和依赖注入这两个名字的由来了。
-将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC -容器完成对象的注入 Bean 工厂模式
+Java基础 + ++ +Java语言 ++ -Rpc 中间件 +/-developer/Rpc/ ++ -分布式系统的 CAP 理论
-
-
AOP 面向切面编程
-将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。 -实现方式:基于动态代理,有接口用 jdk 原生的代理方法,没借口用 CGLib -
-Bean 生命周期
+分布式保证服务高并发稳定性
+-
+
Nacos 配置中心 注册中心
+RPC 框架
-
-自动装配:@Component;@Service;@Controller;@Configure + @Bean
+泛指调用远程的函数的方法,对编解码和网络层有特殊的优化,从而有更高的效率。
-
xxx.class --> 默认无参构造方法 --> 普通对象 --> -依赖注入(属性赋值) --> 初始化前 --> 初始化 --> 初始化后 ---> 代理对象 --> 得到Bean(源码) -实例化 Bean -对象:默认调用无参构造器;若使用有参构造器,参数必须是容器中有的Bean【按参数查找 -Bean 时,先按照 classname 后按照参数名】 初始化前中后:BeanPostProcessor -的 postProcessAfterInitialization() --> @PostConstruct 注解 --> -InitializingBean 的 afterPropertiesSet() 方法 --> BeanPostProcessor -的 postProcessAfterInitialization()(实现了 AOP 代理)
+RPC 框架主要由 Server、Client、Server Stub、Client Stub 组件组成
-
-
底层实现
+层次结构:代理曾、注册中心层(服务发现、注册、管理)、
+RPC 协议定制化程度高,可以采用体积更小的 Protobuf +或其他序列化协议去保存结构体数据,同时也不需要像 HTTP +那样考虑各种浏览器行为,如 302 +重定向跳转。因此性能也会更好一些。其底层不仅可以通过 tcp udp +实现,也可以通过 http 实现。
+RPC +协议会建个连接池,在请求量大的时候,建立多条连接放在池内,要发数据的时候就从池里取一条连接出来,用完放回去,下次再复用,可以说非常环保。
+目前,对外一般用 HTTP 协议,而内部集群的微服务之间则采用 RPC +协议进行通讯。
+Dubbo 上线问题
+记录、学习、汇总实习和技术博客中看到的 Dubbo 实战遇到的问题
+服务端接口不指定通讯协议导致 +OOM
+问题背景:
+问题描述:
-
-
--
-
TODO Spring 启动流程 Springboot 和 Spring 最大的区别就是不需要 xml -配置 Springboot 自动配置
+解决方法(针对框架,开发人员需要牢记 Dubbo 配置必须在接口上):
-
-
销毁方法
+-
+
logback是 slf4j 的官方实现,log4j 是另一个实现,logback 和 log4j -才是二选一,slf4j 是门面日志的 api。
-TODO https://www.cnblogs.com/tuyang1129/p/12861617.html -https://www.cnblogs.com/tuyang1129/p/12866484.html
-Spring 事务
-Spring 的声明式事务信息是存在 ThreadLocal -中的,所以一个线程永远只能有一个事务,所以 Spring -的事务是无法实现事务一致性(同时提交、同时回滚)的
-解决方法:可以通过编程式事务,或者通过分布式事务的思路:二阶段提交方式
-如何解决循环依赖
+href="https://tech.youzan.com/ji-ci-dubbofu-wu-fa-xian-dao-zhi-de-oom/">参考 +父子线程并发 RPC 调用死锁
+问题描述:
-
-
-
-]]>循环依赖的情况下,不管使用三级缓存还是两级缓存,代理类逻辑都必须提前曝光
-- -Java开发 -- -Spring -- -SpringMVC -/-developer/SpringMVC/ -Tomcat - -Tomcat 是基于 HTTP 协议的 Web 服务器,工作流程图 Link
--
Servlet
-Servlet 接口定义了 Servlet 与 servlet容器 -之间的契约。这个契约是:Servlet容器将Servlet类载入内存,并产生 Servlet -实例和调用它具体的方法。但是要注意的是,在一个应用程序中,每种 -Servlet 类型只能有一个实例。类比 SpringMVC 中每一个 Mapping -对应一个控制层方法【不确定】
-对于每一个应用程序,Servlet容器还会创建一个ServletContext对象。这个对象中封装了上下文(应用程序)的环境详情。每个应用程序只有一个ServletContext。每个Servlet对象也都有一个封装Servlet配置的ServletConfig对象。
-SpringMVC
-流程图
-+
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}-
-
HandlerMapping/HandlerAdapter 的适配器模式:
-SpringMVC 的 Handler 有多种实现方式(如继承 Controller 接口、继承 -HttpRequestHandler 接口、基于注解 @Controller -的控制器)。由于实现方式不一样,调用方式就不确定,就需要适配器模式将所有实现方式都统一成同一个接口。把任何一个 -Handler -都适配成一个HandlerAdapter,从而可以做统一的流程处理,不用耦合具体的处理器,模糊掉具体的实现。
-Spring MVC会为每一个标记了 @Controller -的类创建一个控制器实例(bean),并且根据这些类中的 @RequestMapping -注解来配置 URL 到方法的映射。这些映射信息通常会被存储在一个叫做 -
-HandlerMapping
的组件中系统权限
-JWT 是无状态的,适合在分布式系统中使用
-]]>- -Java开发 -- -SpringMVC -- Docker -/-2024/Docker/ -+ Future<String> future = executor.submit(()->{
return 数据查询任务;
})-
-
常用命令
-docker run <IMAGE> [COMMAND] -[ARG...]【创建一个新的容器并运行一个命令】
+解决办法
-
-
docker ps [OPTIONS]【列出容器】
+ +尝试开发基础版 Rpc 中间件
+服务发现流程:使用远程服务的时候首先需要配置一个 +dubbo.xml +文件或者在使用的类加上
+@Reference
,二者都是用来对dubbo消费者引用服务进行一些配置,然后应用在启动的时候会将配置信息转化为一个ReferenceBean
对象,并调用createProxy
方法创建一个远程服务接口的代理对象。代理对象的 invoke +创建:启动时主动订阅注册中心,会显示地调用一次
notify
接口,这个接口会尝试将远程服务注册的url
转换成一个本地的invoker
。-
-
docker rm [OPTIONS] <CONTAINER > -【删除一个或多个已经停止的容器】
+服务注册地址发生改变时:会通知给消费者,dubbo +协议里面明确讲到服务发生改变会全量更新所有客户端的缓存
+Netty 数据传输
++
+在网络通信中,序列化和编码通常是结合使用的。序列化将对象转换为字节流,编码将字节流转换为网络传输所需的格式(如按照协议规定的格式进行编码)。在接收端,解码将网络传输的数据解析为原始的格式(如解码成对象),以便进行进一步的处理和使用。
+Netty 是一个高性能事件驱动型非阻塞 IO 框架:
-
-
docker build [OPTIONS] <PATH> 【创建镜像】
+编码:先序列化,再压缩,最后写进 ByteBuf 对象中
+解码:从 ByteBuf 对象中读,然后转成我们需要的对象
+代理模式
+静态代理
++
+静态代理中,我们对目标对象的每个方法的增强都是手动完成的(后面会具体演示代码),非常不灵活(比如接口一旦新增加方法,目标对象和代理对象都要进行修改)且麻烦(需要对每个目标类都单独写一个代理类)。 +实际应用场景非常非常少,日常开发几乎看不到使用静态代理的场景。
+从 JVM 层面来说, +静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的 class +文件。
+静态代理的步骤
-
-
docker save [OPTIONS] <IMAGE> 【将指定镜像保存成 tar -归档文件】
+JDK 动态代理
-
-
docker load [OPTIONS] 【导入镜像】
++public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
public class RpcClientProxy implements InvocationHandler {
// 在代理类内,根据传入的类 clazz,获得代理对象
public <T> T getProxy(Class<T> clazz) {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, this);
}
// 当通过代理类调用的所有方法,实际上调用的是这个invoke(传入的只是服务接口,具体的实现在服务端实现类中)
public Object invoke(Object proxy, Method method, Object[] args) {...}
}那么是如何调用服务端实现类的代码的呢?注入
+-
+
+Object clientProxy = rpcClientProxy.getProxy(declaredField.getType());
declaredField.setAccessible(true);
try {
declaredField.set(bean, clientProxy);
} catch (IllegalAccessException e) {
e.printStackTrace();
}传输协议
++* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
* +-----+-----+-----+-----+--------+----+----+----+------+-----------+-------+-------+-----+---+-----+----+
* | magic code |version | full length | messageType| codec|compress| RequestId |
* +-----------------------+--------+---------------------+-----------+-----------+-----------+------------+
* | body |
* +-------------------------------------------------------------------------------------------------------+
* 4B magic code(魔法数) 1B version(版本) 4B full length(消息长度) 1B messageType(消息类型)
* 1B compress(压缩类型) 1B codec(序列化类型) 4B requestId(请求的Id)注册中心
+服务注册:在 zk 里面创建一个对应的持久节点
+当我们的服务被注册进 zookeeper +的时候,我们将完整的服务名称 rpcServiceName (class +name+group+version)作为根节点 +,子节点是对应的服务地址(ip+端口号)。相关代码在 +
+ZkServiceProviderImpl.publishService()
中。如果我们要获得某个服务对应的地址的话,就直接根据完整的服务名称来获取到其下的所有子节点,然后通过具体的负载均衡策略取出一个就可以了。相关代码在 +
+ZkServiceDiscoveryImpl.lookupService()
中。Zookeeper 客户端
++
+Curator 是 Netflix +公司开源的一套zookeeper客户端框架,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重连、反复注册Watcher和NodeExistsException异常等等。项目内采用 +CuratorUtils 类调用 Curator。
+重试策略:ExponentialBackoffRetry是指数退避重试策略
++// zk的对外接口,后面我们要干什么只需要通过单例模式获得这个类,然后用这个类的方法
public interface ServiceProvider {
// 添加到本地 serviceMap 中(远程Rpc调用,获取本地的调用类)
void addService(RpcServiceConfig rpcServiceConfig);
Object getService(String rpcServiceName);
// 注册服务到 zookeeper 中(服务发现与注册)
void publishService(RpcServiceConfig rpcServiceConfig);
}负载均衡
+随机选取策略 轮询策略 加权轮询策略 最少活跃连接策略 一致性 Hash +策略
+序列化
-
-
docker top [OPTIONS] <CONTAINER> -【查看容器中运行的进程信息,支持 ps 命令参数】
-实践
-如何容器化 Java 应用
-Docker Compose:
--version: '3'
services:
db:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: mydb
MYSQL_USER: myuser
MYSQL_PASSWORD: mypassword
ports:
- "3608:3306" # 将宿主机的 3608 端口映射到容器的 3306 端口
java-app:
build:
context: . # 假设 Dockerfile 在当前目录下
dockerfile: Dockerfile
depends_on:
- db
environment:
DB_HOST: db # Java 程序将连接到名为 "db" 的服务(即 MySQL 容器)
DB_PORT: 3306 # 在容器内部,MySQL 仍然监听 3306 端口
DB_USER: myuser
DB_PASSWORD: mypassword
DB_NAME: mydb
ports:
- "8080:8080" # 假设 Java 程序监听 8080 端口Dockerfile:
-+# 基础镜像Java 8
FROM java:8
# 设置工作目录
WORKDIR /app
# 复制文件到工作目录
COPY . /app
# 设置Java环境变量
ENV PATH=$PATH:$JAVA_HOME/bin
ENV JRE_HOME=${JAVA_HOME}/jre
ENV CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
# 暴露端口
EXPOSE 8080
# 运行
ENTRYPOINT ['/usr/lib/jvm/java-9-openjdk-amd64/bin/javac','-jar','app.jar']数据传输过程中,可能会出现粘包和半包问题,你是如何解决的?
+自定义消息结构(其他的还有固定长度传输、特殊字符分割):MagicNumber +魔数、ContentLength 请求长度
]]>- 开发工具 +Java开发 - 容器虚拟化 +远程过程调用框架 - -Git 文档阅读 -/-2024/Git/ -Git 中文文档 - -
- -有空可以看看这个 Git -笔记汇总
--
Chapter 1 起步
-版本控制
--
-
Git 简史
--
-
Git 简介
--
-
Git 配置
--
-git config --list --show-origin
--
-
Chapter 2 基础
--
-Git命令只能控制当前文件夹和子文件夹内的修改
-常用命令
-git init 【初始化仓库】
-git clone [OPTIONS] <url>【克隆仓库】
+Redis +/-developer/Redis/ +Redis 的特性:单线程、原子性、基于内存、优化数据结构、I/O +多路复用的非关系型数据库; + -6.0 版本前网络 I/O 和命令处理都是单线程,6.0 版本后网络 I/O +改用多个线程处理
-
-
git status [OPTIONS] 【查看文件状态 】
+数据结构
+5 +种基础数据类型:String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合) +3 种特殊数据类型:HyperLogLog(基数统计)、Bitmap (位图)、Geospatial +(地理位置)
+持久化
+保证即使在服务器重启的情况下也不会丢失数据(或少量损失)
+AOF 日志
+将每条执行成功的写操作命令追加到日志文件中,持久化代码命令在主进程上执行
+写回策略(防止AOF日志在持久化过程中丢失):
+ ++
重写机制(防止AOF日志文件过大):
-
-
git add <file> -【跟踪新文件、已修改的文件放到暂存区、合并时把有冲突的文件标记为已解决状态 -】
-git diff [OPTIONS] -<file>【已修改文件与已暂存文件的内容差异】
+RDB 快照
+某一时刻内存数据的快照(二进制数据),恢复时直接读入内存即可
+执行 bgsave 时,想要修改数据,需采用写时复制(Copy-On-Write, +COW),以减少性能损耗
+混合持久化
+在AOF日志重写过程中,将新的含有 RDB 格式和 AOF 格式的 AOF +文件替换旧的的 AOF 文件,前半部分是 RDB 格式的全量数据,后半部分是 AOF +格式的增量数据,即重写缓冲区数据。
+策略
+过期删除策略
+惰性删除+定期删除
+内存淘汰策略
+仅淘汰过期数据:random、ttl、lru、lfu
+淘汰所有数据:lru、lfu
+高可用
+主从复制
+模式一:全量复制【多用于初始化】
+-
-
git blame [OPTIONS]【追踪代码提交历史】
+为了避免过多的从服务器和主服务器进行数据同步(全量复制),可以把一部分从服务器升级成分发节点,利用从节点分担读取操作的压力
+模式二:基于长连接的命令传播【多用于保持同步】
+主从服务器在完成第一次同步后,双方之间就会维护一个 TCP +连接,保证第一次同步后的主从服务器的数据一致性。
+模式三:连接恢复时可以采用增量复制:repl_backlog_buffer +环形缓冲区保存了最近传播的写命令,若其中存着从服务器请求的 +offset,就采用增量复制;否则采用全量复制。若想降低主从服务器断开后全量同步的概率,需要增大 +repl_backlog_buffer
+QA
+如何应对异步复制导致的主从数据不一致?
+外部程序来监控主从节点间的复制进度
+主从切换如何减少数据丢失?
+-
+
集群脑裂导致数据丢失
+主节点必须要有至少
+min-slaves-to-write
+个从节点连接,主从数据复制和同步的延迟不能超过 +min-slaves-max-lag
+秒。否则原主节点就会被限制接收客户端写请求,客户端也就不能在原主节点中写入新数据,等到新的主节点上线一切恢复正常。哨兵机制
++
+自动完成故障发现和故障转移,并通知给应用方,从而实现高可用性
+哨兵之间建立连接
+ ++
哨兵与从节点建立连接
+ ++
第一轮投票:判断主节点下线
+主观下线:主节点或者从节点没有在规定的时间内响应哨兵的 PING 命令
+客观下线:一个哨兵判断主节点为「主观下线」后,就会向其他哨兵发起命令,通过多个哨兵节点一起判断主节点是否下线。哨兵的赞同票数达到哨兵配置文件中的 +quorum 配置项设定的值则判断主节点客观下线
+第二轮投票:选出哨兵 leader
+-
+
git rm [OPTIONS] <file> 【删除文件】
+由哨兵 leader +进行主从故障转移
-
-
git commit [OPTIONS] 【提交文件】 - [-m <message>] 提交备注 - -[--amend] 追加提交 - [-a] 直接将工作区和暂存区的所有修改一起提交
-git mv <oldfilename> <newfilename> 【移动文件/改名】
-git log [OPTIONS] 【回顾提交历史】 - [--stat] 显示每次提交的简要信息 -- [-p] 显示每次提交的详细信息 - [--pretty=format:"xxx"] 自定义信息格式 - -[--oneline --graph --all] -显示提交历史、各个分支的指向以及项目的分支分叉情况 - [--since] -限制时间
-git reset [OPTIONS] -<HEAD>【回退版本,可以指定退回某一次提交的版本,直接删除某些commit的内容】
+git checkout -[OPTIONS]【在不同的分支之间切换、恢复文件、创建新分支,git switch 和 git -restore 可以代替它】
+集群
+-
-
git remote [OPTIONS] -【列出当前仓库中已配置的远程仓库】
+集群数据分布策略
+Hash 槽
-
-
git fetch <remote_name> <local_branch_name> -【获取远程仓库的更新,但不自动合并到你的工作】
+一致性Hash
+虚拟节点
+缓存
+缓存雪崩、击穿、穿透
+缓存穿透:大量请求了缓存和数据库里都没有的数据,请求穿透缓存和数据库
-
-
git push [OPTIONS]【推送到远程分支】
+缓存击穿:瞬间大量请求未缓存的数据库数据,请求击穿缓存直接打到数据库上
-
-
git pull <remote_name> <branch>【
-git fetch
-和git merge
的组合,拉取到本地分支并合并】git tag [OPTIONS]【列出已有的标签】
+缓存雪崩:缓存在同一时间大面积的失效,导致大量的请求都直接落到了数据库上
-
-
git rebase <cur_branch> <target_branch> -【将提交到某一分支上的所有修改都移至另一分支上】
-git revert -<commit_id>【生成一次新的commit冲抵原来的commit,不会修改原有的提交历史,而是通过添加新的提交来撤销更改】
-git merge <branch> 【合并指定分支到当前分支】
-git switch [OPTIONS] <branch-name> 【切换分支,与 git checkout -类似,但提供了更清晰的语义和错误检查】
+如何保证数据库和缓存一致性
++
+采用 Cache Aside +旁路缓存策略:以数据库中的数据为准,缓存中的数据是按需加载的;缺点:数据写入频繁时,缓存中的数据会被频繁的清理,降低缓存命中率;
+更新数据库+删除缓存:延迟双删
+更新数据库+更新缓存:分布式锁
+更新数据库+不更新缓存:较短的缓存有效期
+删除缓存的时候失败了怎么办?
+采用异步删除:
-
-
git show -【对于提交,它显示日志消息和文本差异;对于标签,它显示标签消息和引用对象】
-git restore [OPTIONS] 【恢复或撤销文件的更改】 - [.] -还原所有未提交的更改 - [<filename>] 丢弃工作区修改 - [--staged -<filename>] 将暂存区的修改放回工作区 - [--source=<commit> -<file>] 将文件恢复到特定提交的状态
-git branch [OPTIONS] 【查看本地分支】
+缓存预热
+提高访问速度,平滑流量峰值,减少后端压力,保证数据的时效性
+Redis 缓存预热的方法:系统启动时加载;定时任务加载;
+实战
+分布式锁
++
+Redis + Lua +脚本,可以以原子性的方式执行一组命令,可用于保证锁释放操作的原子性(Lua +脚本在处理的过程中不会被任意其它请求打断),但无法用于事务执行失败的回滚。Redisson +采用的就是这种方法保证分布式锁的原子性。
+SET 命令的 NX 参数可以实现:key +不存在才插入,可以用于实现分布式锁
+优点:性能高效、实现方便、分布式高可用
+缺点:不好设置超时时间(解决方法:守护线程定期续约)、主从异步复制可能导致不可靠性(解决方法如下)
+提高可靠性(Redlock 算法):客户端和多个独立的 Redis +节点依次请求申请加锁,如果客户端能够和半数以上的节点成功地完成加锁操作,那么就认为,客户端成功地获得分布式锁,否则加锁失败,所有的 +redis 实例都会进行解锁;
-
-
git stash [OPTIONS] 【贮藏工作】
++@Resource
private RedissonClient redisson;延迟队列
+有序集合 Zset;score 存储延迟执行的时间
+大 Key 问题
+会导致的问题
-
-
忽略/不跟踪文件
-.gitignore 正则表达式:官方样例文件
-Chapter 3 分支
--
-相关命令合并到 Chapter2 中
--
-
变基
-如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基。只对尚未推送或分享给别人的本地修改执行变基操作清理历史, -从不对已推送至别处的提交执行变基操作。
-工作原理:提取<topicbranch>内的修改并存为临时文件,然后将HEAD指向<basebranch>,最后以此将之前另存为临时文件的修改依序应用
-Chapter 6 GitHub
-]]>- -开发工具 -- -版本管理 -- Hexo 使用指南 -/-2024/Hexo/ -- - - 常用命令
-- -
-- - - -方法 -代码 -- -快速部署 -hexo g -d -- -清除缓存 -hexo clean -- -预览 -hexo s -- -部署 -hexo d -- - -生成静态页面 -hexo generate -初始化配置
-初始化项目结构
--hexo init
新增标签页,设置属性(type: "tags")
--hexo new page tags
新增分类,设置属性(type: "categories")
--hexo new page categories
配置 next 主题设置
+解决办法
-
-
Debug
--hexo clean --debug
hexo s --debugGit 上传插件
--npm install hexo-deployer-git --save
latex 公式
-安装
-hexo-renderer-markdown-it-plus
后,Katex 与 mathJax -会重复,需要在 next 中配置-mathjax:
enable: false
tags: none
katex:
enable: true
copy_tex: false本地图片
- --npm install hexo-asset-img --save // 代替 hexo-asset-image
Markdown 文字高亮
- --npm un hexo-renderer-marked --save
npm install hexo-renderer-markdown-it-plus --save_config.yml
--markdown:
preset: "default"
plugins:
- markdown-it-mark添加Sitemap
-为自己的网站配置sitemap,可以有效地提升SEO
--npm install hexo-generator-sitemap --save
npm install hexo-generator-baidu-sitemap --save并在站点配置文件
-_config.yml
的末尾添加:-sitemap:
path: sitemap.xml
baidusitemap:
path: baidusitemap.xml改 blockquote 颜色
--blockquote {
background: #d0a7020d;
border-left: 4px solid #d0a702;
color: var(--blockquote-color);
margin: 0;
padding: 0 15px;
cite::before {
content: '-';
padding: 0 5px;
}
}备份本地博客
- --MKLINK [[/D] | [/H] | [/J]] Link Target
/D 创建目录符号链接。默认为文件符号链接。
/H 创建硬链接而非符号链接。
/J 创建目录联接。
Link 指定新的符号链接名称。
Target 指定新链接引用的路径
(相对或绝对)。管理员 PowerShell
-cmd /c mklink /D 目标地址 源地址
-将博客硬链接到 OneDrive 文件夹下备份更新主题 Next
+发布者/订阅者
-
-由于 NexT 以前使用的 swig 模版引擎停止维护,去年迁移到了 -Nunjucks,但是 -目录下的模版文件后缀名没有更改。原因是修改后缀名影响太广,会使用户在执行 -进行更新时产生大量的冲突。这次更换仓库为了解决这些历史遗留问题,没有保留之前的 -commit 历史。
+订阅命令:subscribe channel [channel ... ]
2024.4.23 按照官网配置
-DeBug
- + ++ +
事务回滚
+Redis 不支持回滚,事务没有原子性(要么全部成功要么全部失败)
+管道
+批处理技术,可以一次处理多个 Redis +命令,减少多个命令执行时的网络等待
]]>- 开发工具 +数据库 - hexo +Redis - +如何保持专注 -/-2024/Stay-Focused/ -磨刀不误砍柴工,弄明白如何做事比糊里糊涂的做更重要。当下的目标是通过不断实践试错并总结纠错,从而找到最适合我的高效专注的做事方法。在此,再以高中的座右铭激励自己:当你觉得为时已晚的时候,恰恰是最早的时候。从学生变成社会人、从孩子变成家庭支柱、从做事的变成管人的(总会有那天的啦),我还有很多要改进要学习的地方(如何清楚明确的表达自己的工作内容,如何高效明确的和别人沟通),这些变化不是为了适应社会的表演,而是成年人的责任。 (tmd这文字像是初中生写出来的,文化沙漠了属于是,有时间还是得多看看书捏)+Spring 开发框架 +/-developer/Spring/ +SpringCore 主要提供 IoC 依赖注入功能的支持 SpringMVC 快速构建 MVC +架构的 Web 程序 SpringBoot 简化 Spring 开发,减少配置文件,开箱即用 + IOC 控制反转
-
-Thought is already is late, exactly is the earliest time.
+当一个对象创建时,它所依赖的对象由外部传递给它,而非自己去创建所依赖的对象(比如通过new操作)。因此,也可以说在对象如何获取它的依赖对象这件事情上,控制权反转了。这便不难理解控制反转和依赖注入这两个名字的由来了。
启动
-布置好工作环境,安排好工作内容,让自己发自内心得希望把事情完成。
+将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC +容器完成对象的注入 Bean 工厂模式
-
-
无干扰休息
-休息可以帮助自己以新的方式思考问题,可以清醒头脑,从而重新集中注意力。无干扰的休息意味着休息不会扼杀你的动力,这样你就可以重新振作起来,而不会陷入拖延的弯路。
+AOP 面向切面编程
+将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。 +实现方式:基于动态代理,有接口用 jdk 原生的代理方法,没借口用 CGLib +
+Bean 生命周期
++
+自动装配:@Component;@Service;@Controller;@Configure + @Bean
++
xxx.class --> 默认无参构造方法 --> 普通对象 --> +依赖注入(属性赋值) --> 初始化前 --> 初始化 --> 初始化后 +--> 代理对象 --> 得到Bean(源码) +实例化 Bean +对象:默认调用无参构造器;若使用有参构造器,参数必须是容器中有的Bean【按参数查找 +Bean 时,先按照 classname 后按照参数名】 初始化前中后:BeanPostProcessor +的 postProcessAfterInitialization() --> @PostConstruct 注解 --> +InitializingBean 的 afterPropertiesSet() 方法 --> BeanPostProcessor +的 postProcessAfterInitialization()(实现了 AOP 代理)
-
-
休息不是为了玩得开心,这才是真正休息的目的。休息是关于战略性地恢复你的能量和注意力,以重新处理手头的工作。把电视、游戏和娱乐活动留给晚上可以无愧疚地放松的时候。
-积极工作
-被动任务比主动任务更难集中注意力。改变这种状况的关键是,或者。
+底层实现
-
-
- -
-Step1: choose your concept【写下你要学习的概念】
-Step2: Pretend You're Teaching the ldea to a New -Student【假象你在教一位不懂这件事情的人这个概念,尝试将这件事情说明白】
-Step3: If You Get Stuck, Go Back to the -Book【如果你在这个过程中遇到了困难,回到课本和视频中进一步学习】
-Step4: Simplify and Create -Analogies【尝试精简自己的解释,并将其与其他概念做类比,从而更好地理解概念】
-总结一下,当你可以教会某人一个ta完全不懂的概念的时候,说明你真正掌握了这个概念
-固定日程安排
-努力工作的最好方式就是拥有生活
+
+-
+
TODO Spring 启动流程 Springboot 和 Spring 最大的区别就是不需要 xml +配置 Springboot 自动配置
-
-
logback是 slf4j 的官方实现,log4j 是另一个实现,logback 和 log4j +才是二选一,slf4j 是门面日志的 api。
+TODO https://www.cnblogs.com/tuyang1129/p/12861617.html +https://www.cnblogs.com/tuyang1129/p/12866484.html
+Spring 事务
+Spring 的声明式事务信息是存在 ThreadLocal +中的,所以一个线程永远只能有一个事务,所以 Spring +的事务是无法实现事务一致性(同时提交、同时回滚)的
+解决方法:可以通过编程式事务,或者通过分布式事务的思路:二阶段提交方式
+如何解决循环依赖
+ +-
+
-
- ]]>时间分块法
-将一天分成更小的时间分块法。在每一段时间里,专注于一项任务或一组相似的任务。其重点是规划出需要完成的任务,然后划分特定的时间段专注完成这些任务。
-当你把一整天分成时间段后,它会让你专注于任务,并限制其他人占用你的时间。
-时间分块法让你每天都有一个要完成的具体任务的时间表,而不是遵循一个不断扩大的待办事项列表,你只需要关注于当下应该做的事情。
+循环依赖的情况下,不管使用三级缓存还是两级缓存,代理类逻辑都必须提前曝光
- 思考 +Java开发 - +保持专注 +Spring ++ diff --git "a/tags/LLM\345\272\224\347\224\250\345\274\200\345\217\221/index.html" "b/tags/LLM\345\272\224\347\224\250\345\274\200\345\217\221/index.html" index 1287767..82e4be3 100644 --- "a/tags/LLM\345\272\224\347\224\250\345\274\200\345\217\221/index.html" +++ "b/tags/LLM\345\272\224\347\224\250\345\274\200\345\217\221/index.html" @@ -205,7 +205,7 @@SpringMVC +/-developer/SpringMVC/ +Tomcat + +Tomcat 是基于 HTTP 协议的 Web 服务器,工作流程图 Link
++
Servlet
+Servlet 接口定义了 Servlet 与 servlet容器 +之间的契约。这个契约是:Servlet容器将Servlet类载入内存,并产生 Servlet +实例和调用它具体的方法。但是要注意的是,在一个应用程序中,每种 +Servlet 类型只能有一个实例。类比 SpringMVC 中每一个 Mapping +对应一个控制层方法【不确定】
+对于每一个应用程序,Servlet容器还会创建一个ServletContext对象。这个对象中封装了上下文(应用程序)的环境详情。每个应用程序只有一个ServletContext。每个Servlet对象也都有一个封装Servlet配置的ServletConfig对象。
+SpringMVC
+流程图
++
-
+
HandlerMapping/HandlerAdapter 的适配器模式:
+SpringMVC 的 Handler 有多种实现方式(如继承 Controller 接口、继承 +HttpRequestHandler 接口、基于注解 @Controller +的控制器)。由于实现方式不一样,调用方式就不确定,就需要适配器模式将所有实现方式都统一成同一个接口。把任何一个 +Handler +都适配成一个HandlerAdapter,从而可以做统一的流程处理,不用耦合具体的处理器,模糊掉具体的实现。
+Spring MVC会为每一个标记了 @Controller +的类创建一个控制器实例(bean),并且根据这些类中的 @RequestMapping +注解来配置 URL 到方法的映射。这些映射信息通常会被存储在一个叫做 +
+HandlerMapping
的组件中系统权限
+JWT 是无状态的,适合在分布式系统中使用
+]]>+ +Java开发 ++ SpringMVC LLM应用开发 diff --git a/tags/Langchain/index.html b/tags/Langchain/index.html index d13ade9..01e4438 100644 --- a/tags/Langchain/index.html +++ b/tags/Langchain/index.html @@ -205,7 +205,7 @@
Langchain
- + LLM 应用开发实践diff --git "a/tags/Linux\345\267\245\345\205\267/index.html" "b/tags/Linux\345\267\245\345\205\267/index.html" index 5888193..ce5bba7 100644 --- "a/tags/Linux\345\267\245\345\205\267/index.html" +++ "b/tags/Linux\345\267\245\345\205\267/index.html" @@ -205,7 +205,7 @@Linux工具
- + Linux 开发工具diff --git "a/tags/RAG\346\236\266\346\236\204/index.html" "b/tags/RAG\346\236\266\346\236\204/index.html" index fcf9d31..78f06da 100644 --- "a/tags/RAG\346\236\266\346\236\204/index.html" +++ "b/tags/RAG\346\236\266\346\236\204/index.html" @@ -205,7 +205,7 @@RAG架构 diff --git a/tags/faiss/index.html b/tags/faiss/index.html index 5e7615e..d24a44b 100644 --- a/tags/faiss/index.html +++ b/tags/faiss/index.html @@ -205,7 +205,7 @@
faiss
- + Faiss 向量数据库diff --git "a/tags/\345\244\247\346\250\241\345\236\213\345\237\272\347\241\200/index.html" "b/tags/\345\244\247\346\250\241\345\236\213\345\237\272\347\241\200/index.html" index 66c5027..842f754 100644 --- "a/tags/\345\244\247\346\250\241\345\236\213\345\237\272\347\241\200/index.html" +++ "b/tags/\345\244\247\346\250\241\345\236\213\345\237\272\347\241\200/index.html" @@ -205,7 +205,7 @@大模型基础 diff --git "a/tags/\345\244\247\346\250\241\345\236\213\345\276\256\350\260\203/index.html" "b/tags/\345\244\247\346\250\241\345\236\213\345\276\256\350\260\203/index.html" index d083df0..65a5f91 100644 --- "a/tags/\345\244\247\346\250\241\345\236\213\345\276\256\350\260\203/index.html" +++ "b/tags/\345\244\247\346\250\241\345\236\213\345\276\256\350\260\203/index.html" @@ -205,7 +205,7 @@
大模型微调 @@ -225,7 +225,7 @@
大模型微调 diff --git "a/tags/\345\244\247\346\250\241\345\236\213\347\273\223\346\236\204/index.html" "b/tags/\345\244\247\346\250\241\345\236\213\347\273\223\346\236\204/index.html" index 4dc8641..d2c323e 100644 --- "a/tags/\345\244\247\346\250\241\345\236\213\347\273\223\346\236\204/index.html" +++ "b/tags/\345\244\247\346\250\241\345\236\213\347\273\223\346\236\204/index.html" @@ -205,7 +205,7 @@
大模型结构
- + LLM 结构和创新点diff --git "a/tags/\346\267\261\345\272\246\345\255\246\344\271\240\345\237\272\347\241\200/index.html" "b/tags/\346\267\261\345\272\246\345\255\246\344\271\240\345\237\272\347\241\200/index.html" index e5fe752..f73a03e 100644 --- "a/tags/\346\267\261\345\272\246\345\255\246\344\271\240\345\237\272\347\241\200/index.html" +++ "b/tags/\346\267\261\345\272\246\345\255\246\344\271\240\345\237\272\347\241\200/index.html" @@ -205,7 +205,7 @@深度学习基础 diff --git "a/tags/\347\256\227\346\263\225/index.html" "b/tags/\347\256\227\346\263\225/index.html" index a88b0f0..de0f264 100644 --- "a/tags/\347\256\227\346\263\225/index.html" +++ "b/tags/\347\256\227\346\263\225/index.html" @@ -205,7 +205,7 @@
算法 diff --git "a/tags/\350\256\276\350\256\241\346\250\241\345\274\217/index.html" "b/tags/\350\256\276\350\256\241\346\250\241\345\274\217/index.html" index bab479d..514b530 100644 --- "a/tags/\350\256\276\350\256\241\346\250\241\345\274\217/index.html" +++ "b/tags/\350\256\276\350\256\241\346\250\241\345\274\217/index.html" @@ -205,7 +205,7 @@
设计模式 diff --git "a/tags/\351\235\242\350\257\225/index.html" "b/tags/\351\235\242\350\257\225/index.html" index 46e182f..04e13a2 100644 --- "a/tags/\351\235\242\350\257\225/index.html" +++ "b/tags/\351\235\242\350\257\225/index.html" @@ -198,15 +198,15 @@
面试
- 正则化在损失函数中加入一个与模型复杂度相关的惩罚项,以限制模型的复杂度并防止过拟合
参考文章