欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 大语言模型(LLM)的训练和推理

大语言模型(LLM)的训练和推理

2025/4/16 9:22:21 来源:https://blog.csdn.net/Rhett_Butler0922/article/details/147200138  浏览:    关键词:大语言模型(LLM)的训练和推理

一、大语言模型简介

大语言模型(如GPT、BERT、LLaMA、Grok等)是基于深度神经网络(主要是Transformer架构)的模型,通过在大规模文本数据上训练,学习语言的统计规律、语义和上下文关系。它们可以完成多种任务,包括文本生成、分类、翻译、问答等。训练和推理是模型生命周期的两个核心阶段:

  • 训练:从海量数据中学习语言模式,优化模型参数。
  • 推理:使用训练好的模型处理新输入,生成输出。

二、大语言模型的训练过程

训练一个大语言模型是一个复杂的过程,涉及数据准备、模型架构设计、优化算法、分布式计算和微调等多个阶段。以下是详细分解:

1. 数据准备

数据是LLM训练的基础,其质量和规模直接影响模型性能。

(1) 数据收集

  • 来源
    • 网络爬取:如Common Crawl(数十TB的网页数据,包含论坛、博客、新闻等)。
    • 公开数据集:Wikipedia(多语言百科全书)、BooksCorpus(免费电子书)、ArXiv(学术论文)。
    • 专有数据:企业可能使用内部数据(如社交媒体帖子、客服对话)。
    • 多模态数据(新兴趋势):如图像-文本对(用于多模态LLM,如CLIP)。
  • 规模
    • GPT-3训练数据约45TB(压缩后约570GB),包含约5000亿个token(假设平均token长度为4字节)。
    • LLaMA-3(假设)可能使用更大规模数据,如100TB+。
  • 多样性
    • 覆盖多种语言(英语、汉语、西班牙语等)。
    • 包含多种领域(科技、文学、法律、日常对话)。
    • 风格多样(正式、口语、创意写作)。
  • 细节
    • 数据通常以纯文本或JSON格式存储。
    • 收集需要遵守版权和隐私法规(如GDPR)。
    • 工具:如wgetBeautifulSoup(Python爬虫)、Apache Nutch。

(2) 数据清洗

  • 去噪
    • 移除广告、导航菜单、HTML标签、乱码。
    • 示例:使用正则表达式过滤HTML标签(<.*?>)。
    • 工具:lxmlhtml2text
  • 去重
    • 使用哈希算法(如MinHash)或精确匹配检测重复文本。
    • 工具:datasketch(MinHash实现)。
    • 目的:避免模型记住重复模式,减少过拟合。
  • 过滤低质量内容
    • 移除语法错误严重的文本、过短的句子。
    • 使用语言模型(如BERT)评分文本质量,过滤低分内容。
  • 隐私保护
    • 移除个人信息(如姓名、电话号码)。
    • 工具:正则表达式、NER(命名实体识别)模型。
  • 示例
    • 原始文本:<p>Buy now for $99! Visit www.example.com</p>
    • 清洗后:Buy now for $99!

(3) 数据预处理

  • 分词(Tokenization)
    • 目标:将文本分割成token(单词、子词或字符)。
    • 算法
      • Byte-Pair Encoding (BPE)
        • 初始将文本拆分为字符,迭代合并高频字符对。
        • 示例:单词“unhappiness”可能拆为“un”+“happi”+“ness”。
        • 实现:sentencepiece库、tokenizers(Hugging Face)。
      • WordPiece(BERT使用):
        • 类似BPE,但优化交叉熵损失。
      • Unigram(SentencePiece使用):
        • 从大词汇表开始,逐步删除低概率token。
    • 词汇表
      • 大小:通常为3万到10万(GPT-3约5万,BERT约3万)。
      • 包含特殊token,如[CLS](分类)、[SEP](分隔)、<|start|>(开始)。
    • 代码示例(使用Hugging Face tokenizers):
      from tokenizers import Tokenizer
      from tokenizers.models import BPE
      from tokenizers.trainers import BpeTrainertokenizer = Tokenizer(BPE())
      trainer = BpeTrainer(vocab_size=30000, special_tokens=["<|start|>", "<|end|>"])
      tokenizer.train(files=["corpus.txt"], trainer=trainer)
      encoded = tokenizer.encode("Hello, world!")
      print(encoded.tokens)  # ['Hel', 'lo', ',', 'wor', 'ld', '!']
      
  • 序列化
    • 将token映射为数字ID。
    • 示例:Hello → 1001,, → 1002。
    • 存储为张量(如PyTorch的torch.tensor)。
  • 分组
    • 将文本切分为固定长度序列(最大长度如512或2048 token)。
    • 填充(Padding):短序列补齐到最大长度,使用[PAD]
    • 截断(Truncation):长序列截断,保留关键部分。
    • 注意力掩码(Attention Mask)
      • 生成掩码张量,标记有效token(1)和填充token(0)。
      • 示例:输入[Hello, world, [PAD]],掩码为[1, 1, 0]
    • 代码示例
      import torch
      tokens = [1001, 1002, 1003]  # Hello, world
      padded = tokens + [0] * (512 - len(tokens))  # 填充到512
      attention_mask = [1] * len(tokens) + [0] * (512 - len(tokens))
      input_tensor = torch.tensor([padded])
      mask_tensor = torch.tensor([attention_mask])
      

2. 模型架构

LLM通常基于Transformer架构,以下是详细分解。

(1) Transformer核心组件

  • 自注意力机制(Self-Attention)
    • 原理
      • 每个token的表示通过查询(Query)、键(Key)、值(Value)向量计算。
      • 注意力分数衡量token间的相关性。
    • 数学公式
      • 输入:嵌入矩阵X ∈ ℝ^{n×d},n为序列长度,d为嵌入维度。
      • 计算Q、K、V:
        • Q = XW_Q, K = XW_K, V = XW_V,其中W_Q, W_K, W_V ∈ ℝ^{d×d_k}
      • 注意力权重:
        • Attention(Q, K, V) = softmax(QK^T / √d_k)V
        • √d_k为缩放因子,防止数值过大。
    • 代码示例(简化的自注意力):
      import torch
      import torch.nn as nnclass SelfAttention(nn.Module):def __init__(self, d_model, d_k):super().__init__()self.d_k = d_kself.W_q = nn.Linear(d_model, d_k)self.W_k = nn.Linear(d_model, d_k)self.W_v = nn.Linear(d_model, d_k)def forward(self, x):Q = self.W_q(x)  # [batch, seq_len, d_k]K = self.W_k(x)V = self.W_v(x)scores = torch.matmul(Q, K.transpose(-2, -1)) / (self.d_k ** 0.5)attn_weights = torch.softmax(scores, dim=-1)output = torch.matmul(attn_weights, V)return output
      
  • 多头注意力(Multi-Head Attention)
    • 将注意力分为h个头(head),每头独立计算:
      • head_i = Attention(QW_Q^i, KW_K^i, VW_V^i)
      • 合并:MultiHead(Q, K, V) = Concat(head_1, ..., head_h)W_O
    • 参数:
      • 头数h:如12(BERT)或96(GPT-3)。
      • 每头维度:d_k = d_model / h
    • 优势:捕捉不同的语义关系(如语法、语义)。
  • 前馈神经网络(FFN)
    • 逐位置应用:
      • FFN(x) = max(0, xW_1 + b_1)W_2 + b_2
    • 参数:
      • 中间维度通常为4 * d_model(如BERT的3072)。
    • 实现:
      class FeedForward(nn.Module):def __init__(self, d_model, d_ff):super().__init__()self.linear1 = nn.Linear(d_model, d_ff)self.linear2 = nn.Linear(d_ff, d_model)self.relu = nn.ReLU()def forward(self, x):return self.linear2(self.relu(self.linear1(x)))
      
  • 层归一化(Layer Normalization)
    • 稳定训练:
      • LayerNorm(x) = γ * (x - μ) / σ + β,其中μ、σ为均值和标准差,γ、β为可学习参数。
    • 位置:通常在注意力后和FFN后。
  • 残差连接(Residual Connection)
    • x = x + Sublayer(x),避免梯度消失。
  • 位置编码(Positional Encoding)
    • 固定正弦/余弦编码:
      • PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
      • PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))
    • 可学习编码:直接优化嵌入向量。
    • 实现:
      def get_positional_encoding(seq_len, d_model):pos = torch.arange(seq_len).unsqueeze(1)div_term = torch.exp(torch.arange(0, d_model, 2) * (-math.log(10000.0) / d_model))pe = torch.zeros(seq_len, d_model)pe[:, 0::2] = torch.sin(pos * div_term)pe[:, 1::2] = torch.cos(pos * div_term)return pe
      

(2) 模型类型

  • 仅解码器模型(如GPT):
    • 单向自回归,适合生成任务。
    • 注意力掩码:因果掩码(Causal Mask),只关注前文。
  • 仅编码器模型(如BERT):
    • 双向建模,适合理解任务。
    • 注意力掩码:全连接(无掩码)。
  • 编码器-解码器模型(如T5):
    • 适合序列到序列任务。
    • 编码器:双向;解码器:自回归。

(3) 模型规模

  • 参数量
    • GPT-3:1750亿。
    • LLaMA-3-70B:700亿。
    • 参数分布:嵌入层约20%,注意力层约40%,FFN约40%。
  • 层数与维度
    • GPT-3:96层,d_model=12288h=96
    • BERT:12层(Base)或24层(Large),d_model=768或1024。
  • 计算复杂度
    • 自注意力:O(n^2 * d),n为序列长度。
    • FFN:O(n * d * d_ff)
    • 序列长度增加会显著提高成本。

3. 训练目标

训练目标定义了模型优化的方向。以下是详细分析:

(1) 自回归语言建模(Causal Language Modeling)

  • 目标
    • 预测下一个token,给定前文:
      • P(x_t | x_1, ..., x_{t-1})
  • 损失函数
    • 交叉熵损失:
      • L = -∑_{t=1}^T log P(x_t | x_1, ..., x_{t-1})
    • 对每个token计算softmax概率:
      • P(x_t) = softmax(W_o * h_t),其中h_t为Transformer输出。
  • 实现
    class LanguageModel(nn.Module):def __init__(self, vocab_size, d_model):super().__init__()self.transformer = TransformerDecoder(...)  # 简化的Transformerself.output = nn.Linear(d_model, vocab_size)def forward(self, x):h = self.transformer(x)logits = self.output(h)return logitscriterion = nn.CrossEntropyLoss()
    logits = model(input_ids)  # [batch, seq_len, vocab_size]
    loss = criterion(logits.view(-1, vocab_size), target_ids.view(-1))
    
  • 细节
    • 输入和目标偏移一位(target_ids = input_ids[1:])。
    • 因果掩码确保只关注前文。

(2) 掩码语言建模(Masked Language Modeling)

  • 目标
    • 随机掩盖15%的token,预测原始token。
    • 示例:输入The cat [MASK] on the mat.,预测sat
  • 损失函数
    • 仅对掩码token计算交叉熵:
      • L = -∑_{i∈masked} log P(x_i | x)
  • 细节
    • 掩码策略:
      • 80%替换为[MASK]
      • 10%替换为随机token。
      • 10%保持不变。
    • 实现:
      def mask_tokens(inputs, tokenizer, mlm_prob=0.15):labels = inputs.clone()mask = torch.rand(inputs.shape) < mlm_probinputs[mask] = tokenizer.mask_token_idreturn inputs, labels
      

(3) 序列到序列建模

  • 目标
    • 将输入序列映射到输出序列:
      • P(y_1, ..., y_m | x_1, ..., x_n)
  • 损失函数
    • 交叉熵:
      • L = -∑_{t=1}^m log P(y_t | y_1, ..., y_{t-1}, x)
  • 实现
    • 编码器处理输入,解码器生成输出。
    • 使用teacher forcing:训练时输入真实目标序列。

4. 优化算法

(1) 随机梯度下降(SGD)与Adam

  • Adam
    • 结合一阶动量(均值)和二阶动量(方差)。
    • 更新规则:
      • m_t = β_1 m_{t-1} + (1 - β_1) g_t
      • v_t = β_2 v_{t-1} + (1 - β_2) g_t^2
      • θ_t = θ_{t-1} - η * m_t / (√v_t + ε)
    • 参数:β_1=0.9, β_2=0.999, ε=1e-8
  • 实现
    optimizer = torch.optim.Adam(model.parameters(), lr=6e-4, betas=(0.9, 0.999))
    

(2) 学习率调度

  • Warm-up
    • 初始阶段线性增加学习率:
      • lr_t = lr_max * t / T_warmup
    • 示例:前10%步数从0到6e-4。
  • 衰减
    • 余弦退火:
      • lr_t = lr_min + 0.5 * (lr_max - lr_min) * (1 + cos(π * t / T))
    • 实现:
      from torch.optim.lr_scheduler import CosineAnnealingLRscheduler = CosineAnnealingLR(optimizer, T_max=100000, eta_min=1e-6)
      

(3) 批量大小

  • 大批量
    • GPT-3使用约3.2M token/batch。
    • 提高并行效率,稳定梯度。
  • 梯度累积
    • 显存不足时,分多次计算小批量:
      optimizer.zero_grad()
      for i, batch in enumerate(data):loss = model(batch).lossloss.backward()if (i + 1) % accumulation_steps == 0:optimizer.step()optimizer.zero_grad()
      

(4) 混合精度训练

  • 原理
    • 使用FP16/BF16计算,FP32存储权重。
    • 减少显存,加速计算。
  • 实现
    from torch.cuda.amp import autocast, GradScalerscaler = GradScaler()
    for batch in data:optimizer.zero_grad()with autocast():loss = model(batch).lossscaler.scale(loss).backward()scaler.step(optimizer)scaler.update()
    

5. 分布式训练

(1) 数据并行

  • 每个GPU处理不同数据子集,同步梯度:
    • All-Reduce聚合梯度。
  • 实现:PyTorch DDP:
    import torch.distributed as dist
    from torch.nn.parallel import DistributedDataParallel as DDPdist.init_process_group(backend="nccl")
    model = DDP(model)
    

(2) 模型并行

  • 流水线并行
    • 将层分配到不同设备:
      • GPU 1:层1-10,GPU 2:层11-20。
    • 实现:DeepSpeed Pipe。
  • 张量并行
    • 将矩阵运算分割:
      • 注意力头的W_Q、W_K分割到不同GPU。
    • 实现:Megatron-LM。

(3) ZeRO(Zero Redundancy Optimizer)

  • 分片优化器状态、梯度和参数:
    • ZeRO-1:分片优化器状态。
    • ZeRO-2:分片梯度。
    • ZeRO-3:分片参数。
  • 实现:DeepSpeed:
    from deepspeed import init_distributed
    import deepspeedmodel_engine, optimizer, _, _ = deepspeed.initialize(model=model, config=ds_config)
    

(4) 通信优化

  • Ring All-Reduce
    • 环形拓扑减少通信开销。
  • NVLink
    • NVIDIA GPU间高速互联。
  • InfiniBand
    • 集群间高速网络。

6. 训练中的挑战与解决方案

(1) 计算资源

  • 硬件
    • GPT-3训练可能使用8000块A100 GPU,耗时约1个月。
    • 成本:数百万美元。
  • 解决方案
    • 云服务:AWS(EC2 P4d)、Azure(NDv4)。
    • 高效算法:ZeRO、混合精度。

(2) 过拟合

  • Dropout
    • 随机丢弃神经元(概率如0.1)。
  • 权重衰减
    • L2正则化,惩罚大权重。
  • 数据增强
    • 动态掩码、文本替换。

(3) 稳定性

  • 梯度裁剪
    • 限制梯度范数(如1.0)。
    torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
    
  • 初始化
    • Xavier或He初始化,稳定初始梯度。

7. 微调

(1) 监督微调(SFT)

  • 数据:标注的问答对、翻译对。
  • 实现:
    from transformers import Trainer, TrainingArgumentstraining_args = TrainingArguments(output_dir="./sft",per_device_train_batch_size=8,num_train_epochs=3,
    )
    trainer = Trainer(model=model, args=training_args, train_dataset=dataset)
    trainer.train()
    

(2) 强化学习微调(RLHF)

  • 步骤
    • 收集人类偏好数据(比较模型输出)。
    • 训练奖励模型(Reward Model):
      • 输入:输出对,输出:偏好分数。
    • 使用PPO优化:
      • 最大化奖励,同时约束KL散度。
  • 实现:TRL库:
    from trl import PPOTrainerppo_trainer = PPOTrainer(model=model, ref_model=ref_model, config=ppo_config)
    ppo_trainer.train()
    

(3) 参数高效微调(PEFT)

  • LoRA
    • 冻结预训练权重,添加低秩矩阵:
      • W = W_0 + BA,B、A为小矩阵。
    • 实现:PEFT库:
      from peft import LoraConfig, get_peft_modellora_config = LoraConfig(r=8, lora_alpha=16, target_modules=["q", "v"])
      model = get_peft_model(model, lora_config)
      

三、大语言模型的推理过程

推理是使用训练好的模型处理输入,生成输出的过程。以下是详细分解:

1. 输入处理

(1) 分词

  • 使用训练时相同的分词器。
  • 示例:
    • 输入:“我爱学习人工智能”
    • 输出:["我", "爱", "学", "习", "人", "工", "智", "能"]

(2) 序列化

  • 转换为ID:
    • token_ids = tokenizer.convert_tokens_to_ids(tokens)

(3) 填充与截断

  • 固定长度(如2048):
    • 填充:[PAD]
    • 截断:保留前2048 token。
  • 注意力掩码:
    • attention_mask = [1, 1, ..., 0, 0]

2. 模型前向传播

(1) 嵌入层

  • 词嵌入
    • x = embedding(token_ids)x ∈ ℝ^{seq_len×d_model}
  • 位置嵌入
    • x = x + positional_encoding(seq_len, d_model)

(2) Transformer层

  • 每层:
    • 自注意力:h = MultiHeadAttention(x)
    • 残差:x = x + h
    • 层归一化:x = LayerNorm(x)
    • FFN:h = FeedForward(x)
    • 残差与归一化:x = LayerNorm(x + h)

(3) 输出层

  • 线性层+softmax:
    • logits = W_o * hprobs = softmax(logits)
  • 输出:词汇表概率分布。

3. 输出生成

(1) 自回归生成

  • 过程
    • 初始输入:x_1, ..., x_t
    • 预测:x_{t+1} ~ P(x_{t+1} | x_1, ..., x_t)
    • 加入新token,重复。
  • 解码策略
    • 贪心搜索
      • x_{t+1} = argmax(P(x_{t+1}))
    • 束搜索
      • 保留k个候选序列:
        • score = ∑ log P(x_t)
      • 参数:beam_size=5
    • 采样
      • 随机采样:x_{t+1} ~ P(x_{t+1})
      • Top-k:从前k个token采样。
      • Top-p:从累计概率p的token采样。
    • 温度
      • P'(x) = P(x)^(1/T) / ∑ P(x)^(1/T)
      • T<1:更确定,T>1:更随机。
    • 实现:
      from transformers import GPT2LMHeadModel, GPT2Tokenizermodel = GPT2LMHeadModel.from_pretrained("gpt2")
      tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
      inputs = tokenizer("Hello, world!", return_tensors="pt")
      outputs = model.generate(inputs["input_ids"],max_length=50,do_sample=True,top_k=50,top_p=0.95,temperature=0.7,
      )
      print(tokenizer.decode(outputs[0]))
      

(2) 非自回归生成

  • 一次性输出:
    • 示例:BERT预测[MASK]
  • 实现:
    from transformers import BertForMaskedLMmodel = BertForMaskedLM.from_pretrained("bert-base-uncased")
    inputs = tokenizer("The cat [MASK] on the mat.", return_tensors="pt")
    logits = model(**inputs).logits
    masked_idx = (inputs["input_ids"] == tokenizer.mask_token_id).nonzero()
    predicted_token = logits[0, masked_idx, :].argmax(dim=-1)
    

4. 推理优化

(1) 量化

  • INT8量化
    • 将FP32权重转换为INT8:
      • w_int8 = round(w_fp32 / scale)
  • 实现:torch.quantization

(2) 剪枝

  • 结构化剪枝
    • 删除整个注意力头或FFN单元。
  • 非结构化剪枝
    • 删除小权重。
  • 实现:torch.nn.utils.prune

(3) 蒸馏

  • 知识蒸馏
    • 学生模型优化:
      • L = α * L_CE + (1 - α) * L_KL(teacher_logits, student_logits)
  • 实现:Hugging Face DistilBERT。

(4) KV缓存

  • 原理
    • 缓存自注意力的K、V:
      • K_t = [K_1, ..., K_t], V_t = [V_1, ..., V_t]
  • 实现:
    class TransformerDecoderWithCache(nn.Module):def __init__(self):super().__init__()self.k_cache = []self.v_cache = []def forward(self, x, use_cache=True):if use_cache:k, v = self.attention(x)self.k_cache.append(k)self.v_cache.append(v)return self.attention(x, k_cache=self.k_cache, v_cache=self.v_cache)
    

(5) 硬件加速

  • TensorRT
    • 优化推理图,融合算子。
  • ONNX
    • 跨平台优化。

5. 推理中的挑战

(1) 计算成本

  • 显存
    • GPT-3推理需要约350GB(FP16)。
  • 解决方案
    • 模型并行、量化。

(2) 延迟

  • 实时要求
    • 对话系统需<200ms。
  • 解决方案
    • 高效解码、缓存。

(3) 输出质量

  • 幻觉(Hallucination)
    • 生成错误事实。
  • 解决方案
    • 微调、后处理。

四、案例分析:以LLaMA-3为例

1. 训练

  • 数据
    • 假设100TB,包含Common Crawl、Wikipedia、C4。
    • 清洗:去重(MinHash)、去噪(正则表达式)。
    • 分词:SentencePiece,词汇表约5万。
  • 架构
    • 仅解码器,70B参数,80层,d_model=8192h=64
  • 目标
    • 自回归建模,交叉熵损失。
  • 优化
    • AdamW,lr=3e-4,余弦衰减。
    • 混合精度(BF16)。
    • 批量大小:4M token。
  • 分布式
    • 4096块H100 GPU,ZeRO-3。
    • 训练约2个月。

2. 推理

  • 输入
    • “请解释量子力学”
    • 分词:["请", "解", "释", "量", "子", "力", "学"]
  • 前向传播
    • 嵌入:8192维向量。
    • Transformer:80层,KV缓存加速。
  • 生成
    • Top-p采样,p=0.9temperature=0.8
    • 输出:逐token生成,约100 token。
  • 优化
    • INT8量化,TensorRT加速。

五、学习建议

1. 理论

  • 书籍
    • 《Deep Learning》:数学基础。
    • 《Transformers for Natural Language Processing》:Transformer详解。
  • 论文
    • 《Scaling Laws for Neural Language Models》:规模效应。
    • 《LoRA: Low-Rank Adaptation》:高效微调。
  • 课程
    • CS231n(Stanford,CNN与Transformer)。
    • fast.ai NLP课程。

2. 实践

  • 框架:PyTorch(推荐)、JAX(高性能)。
  • 项目
    • 实现小型Transformer:
      class Transformer(nn.Module):def __init__(self, d_model, nhead, num_layers):super().__init__()self.encoder = nn.TransformerEncoder(nn.TransformerEncoderLayer(d_model, nhead), num_layers)def forward(self, src):return self.encoder(src)
      
    • 微调LLaMA:
      • 使用Hugging Face PEFT。
    • 推理优化:
      • 实现KV缓存。
  • 数据集
    • WikiText、C4。
  • 工具
    • Hugging Face、DeepSpeed。

3. 资源

  • 免费
    • Colab Pro(A100 GPU)。
    • Kaggle(TPU)。
  • 社区
    • CSDN平台(#NLP、#LLM)。
    • GitHub、Hugging Face、Meta AI。

六、总结

  • 训练
    • 数据:收集、清洗、分词(BPE)。
    • 架构:Transformer(自注意力、FFN)。
    • 目标:自回归、掩码建模。
    • 优化:Adam、混合精度、分布式(ZeRO)。
    • 微调:SFT、RLHF、LoRA。
  • 推理
    • 输入:分词、序列化。
    • 前向:嵌入、Transformer、输出。
    • 生成:贪心、束搜索、采样。
    • 优化:量化、KV缓存、TensorRT。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词