[{"content":"验证码_哔哩哔哩\n1. 大语言模型的推理加速方案 1.1. 为什么KV Cache不在training中使用只在inference中使用 回答：因为训练（Training）和推理（Inference）的计算方式完全不同。\n解释：\n训练 (Training) 是“并行”的： 为了高效利用 GPU，我们一次性将整个完整序列（例如，一个完整的句子）输入模型，并使用 Causal Mask (注意力掩码) 来防止位置 i 的 token \u0026ldquo;偷看\u0026rdquo; 到位置 j \u0026gt; i 的 token。\n推理 (Inference) 是“串行”的： 我们一次只生成一个新 token，然后把它添加到输入序列中，再生成下一个。\nKV Cache 正是为了优化这种“串行”的、逐字生成的推理过程而设计的。\nKV Cache的存储方式\n两个不同的句子是否需要重新计算所有的k和v的矩阵？\n新的句子中相同的字符是否需要重新计算QKV？\n回答：是的，必须重新计算。因为同一个词在句中的位置(Positional encoding)和上下文表示(Contextual representation)可能不同。\n换一种说法：\np1: what are the two steps in LLM inference?\nprefill and decode 预填充和解码\n由于self-attention, 多个token输入的时候，可以做成keys Matrix x Queries Matrix进行并行计算，\nPrefill (预填充) 阶段：负责创建和填充初始的 KV Cache。 Decode (解码) 阶段：负责使用和扩展这个 KV Cache。 怎么加速推理？\n关键在于延迟和吞吐量。\nLatency (延迟) 和 Throughput (吞吐量) 是衡量系统性能的两个关键指标，它们描述的是不同的东西：\nLatency关注的是响应时间。 Througtput关注的是单位时间内系统能处理的操作数量(流量)。 提问：\nWhy multi-head attention? 多角度看问题。multi-head attention是设置多个注意力机制，详见子空间。 Theory: subspace 子空间 每个注意力头都有自己的QKV矩阵 由于初始化矩阵不同，所以训练后会学到不同的投影方式。（如一个学会动词和主语之间关系，一个学会同义词之间的关联性） 多个注意力头在各自的小空间里独立学习，最后拼起来。怎么拼起来看下面。 Compute: parallel 并行计算多注意力头 gpu可以同时计算所有头，不是使用loop。而是批处理矩阵（batched matrix multiply, BMM）。比如原本要输入[BatchSize=2（两句句子）, SeqLen（每句10个词）, 512（模型维度）] [2,10,512]。 Reshape（逻辑拆分）。将维度拆分成多个头[2,10,8,64]。 Transpose（转置）。$QKV$ 都这么转 [2,8,10,64]。 矩阵乘法。 $Q\\cdot K^T$ 中的 $K^T$ [2,8,64,10]。相乘的时候pytorch会自动识别后两维是批次维度，并行处理完结果就是注意力分数矩阵 [2,8,10,10]。 How to use CUDA to optimized multi-head attention 由于MHA只有在计算 $Q\\cdot K^T$ 的时候是在显存里，读结果的scale, mask,softmax都是在内存，所以有优化空间。 FlashAttention 是 MHA 优化技术。 内核融合，将各步骤都融合到一个 CUDA 内核里完成。 分块（Tiling）：在计算 $Q\\cdot K^T$ 的时候，是一个大矩阵，可能放不进片上内存（SRAM，计算速度快）。将这个矩阵分成小块（Tiles），在SRAM上计算每个结果的Softmax，然后累加起来。 1.2. tensor parallelism和pipeline parallelism（并行） 这两个并行策略的作用：解决大模型过大一张显卡的显存装不下的问题。通过切分模型，分别在不同显卡中运算。\nPipeline parallelism（流水线并行）： 模型纵向切分 不同GPU处理不同层（GPU1: 1-10Layers, GPU2: 11-20Layers, …）。显卡之间是串行的，一个处理完传输结果到下一个，最后出结果。 优点：这样所有模型利用率拉满，在训练的时候用效果好。 缺点：推理的时候延迟很大 $T=T_1+T_2+T_3...$。 Tensor parallelism（张量并行）： 模型横向切分 所有GPU同时在一个Layer上工作，最后拼成结果。 就是利用了 BMM 的原理，把不同的头分出来，然后装到不同显卡里计算。 优点：延迟很低 $T=T_1$ 缺点：每一层处理的结果都必须共享并求和（All-Reduce），才能进行下一层计算，所以受通信速度的影响（需要NVLink的高速网络进行数据通信） 特性 Tensor Parallelism (TP, 张量并行) Pipeline Parallelism (PP, 流水线并行) 核心思想 层内并行 (Intra-layer Parallelism) 层间并行 (Inter-layer Parallelism) 切分方式 横向切分：把单层的权重矩阵（如 W_Q, W_K, W_V）“切碎” 纵向切分：把多层（Layers）“切断”成不同的“阶段” (Stage) 通信开销 极高且频繁。每计算完一层，GPU 间都需通信 (All-Reduce) 低且不频繁。只在两个“阶段”的边界处通信 (Point-to-Point) 带宽依赖 极高。必须使用 NVLink 这样的高速总线，基本限于单机 较低。可以使用 InfiniBand/Ethernet，可以跨服务器（节点） 主要优点 低延迟。所有 GPU 同时计算，响应快。 高吞吐 (训练时)。可跨节点扩展，装下超大模型。 主要缺点 扩展性差。受限于单机 GPU 数量 (如 8 卡) 延迟极高。串行计算，总延迟是所有阶段之和。 关键问题 通信是瓶颈。 “流水线气泡” (Bubble)：大量 GPU 处于空闲等待状态。 设备 最好是同一个host，多张显卡 可以是不同host Sequence parallelism（序列并行）：（最新方案，可输入超长tokens） 前面介绍的两种策略TP和PP，在每块GPU中都需要存储和处理完整序列长度（Full Sequence Length）的激活值（在训练反向传播时，模型必须在显存里保留所有中间计算结果（Attention layer, FFN layer的输出等），这就是激活值）。而激活值的显存占用量与序列长度 $S$ （输入的tokens长度）和批次大小 $B$ （一个GPU同时并行处理的独立样本数量）成正比。所以，当 $S$ 很长时，激活值会比模型权重还大，成为新的显存瓶颈。导致就算TP和PP把权重分得再碎，激活值都有可能让显存爆。 解决方法：既然 $S$ 很长，那把 $S$ 也切了。 问题是，self-attention对于上下文有依赖，切开会破坏这种依赖。 self-attention有依赖，但是FFM/MLP（前馈网络）的序列没有依赖，对每个token都是独立计算的。 SP和TP需要一起用。 FFN/MLP layer 输入：[S, B, H]\n切分：在输入FFN前，先把输入切成8份。\n每个GPU独立计算。\nAttention layer 将所有GPU的FFN结果拼回完整序列，并共享到所有GPU（All-Gather）。 使用TP策略。 通信（Reduce-Scatter）： 所有GPU执行一次 Reduce-Scatter（求和-分散）。就是所有TP结果相加，然后做切分（第1步的切分成8份）。输入下一个FFN。 1.2.1. FFN FFN 通常是一个非常简单的两层全连接神经网络 (MLP)：\n1.3. Quantization FP32 → FP4 大幅减少模型参数量来做到加速。\nFP32: -128～+127 （256）\nFP4: -8～+7 （16）\n操作步骤：\n关键点：在推理时，模型会用 INT8 整数进行极快的矩阵乘法（INT8 计算比 FP32 快得多），只在最后需要输出时，才用 S 和 Z 把结果“反量化”回 FP32。\n例子：\nzero point是将量化值和原始值对齐的操作。\n1.3.1. 量化的主要策略 1.3.1.1. Post-Trainging Quantization (PTQ - 训练后量化) 训练高精度模型后，冻结参数。 小批量样本推理，记录每一层的权重和激活值矩阵的最大和最小值。 根据量化值和记录的值计算S和Z。 所有权重从FP32转换为INT8，甚至INT4。 1.3.1.2. Quantization-aware training (QAT - 量化感知训练) 由于量化对精度的损失很大，所有需要QAT。\n策略：在训练时就模拟量化。\n前向传播 Forward pass 拿到FP32权重，量化为INT8，倒回FP32。 反向传播 Backward pass 计算梯度。（注意梯度回绕过round函数，因为它不可导） 使用梯度更新FP32权重 这样模型就会在训练中自己优化量化造成的误差。\n注意细节：\nS 和 Z 是针对谁设计的？\nPer-Tensor（逐张量） 就是整个权重只给一组S和Z。 缺点：这样如果权重中有异常值，导致原始值范围巨大 → S 巨大，导致其他值被压缩成0，精度崩塌。 Per-Channel / Per-Group（逐通道 / 逐组） LLM里的标准做法。\n对权重的**每一行（或每一列）**都独立计算一组S和Z。\n比如：nxn的矩阵，会获得n组S和Z。\n优点： 极大地隔离了异常值，精度保持得非常好。\n缺点：如下面的矩阵，最后一行转换后值相等了，就会不可取分。\n在LLM上量化会有巨大的损失（这里RTN是指Round-to-Nearest（四舍五入））\n针对 LLM 的特殊挑战：激活值异常点 (Outliers)\nLLM 的量化有一个大难题：\n权重 (Weights) 很“乖”，是漂亮的正态分布（钟形曲线），很容易量化。 激活值 (Activations)（即 MHA 和 FFN 的中间输出）很“野”。它们 99.9% 的值都接近 0，但有几个极其巨大的“异常值”。 这些异常值会毁了 Per-Tensor 的量化。\n解决方案 (如 LLM.int8() / SmoothQuant):\n这是一种“混合精度”量化。 它在计算时，动态地检测出这些“异常值”所在的维度。 99.9% 的“正常”计算用 INT8 完成。 0.1% 的“异常”计算，切换回 FP16 来处理。 这样既保证了速度，又保证了精度。 而更高级的 GPTQ / AWQ / QLoRA (NF4) 等 4-bit 量化，则是在 PTQ 的基础上，增加了“智能调整”步骤：它们会在量化前，就“重构”权重矩阵，把量化误差的伤害降到最低。\n策略：保留一部分全精度，如图loss降回原本的值。\n问题：哪些行保留？哪些行量化？\n看哪一行数值大就保留哪一行。→ 实验发现有26%要保留。 看X（取列的平均）乘这一行获得activation数值大（说明活跃）。（AWQ） 问题：这样权重里有的是FP32有的是INT8怎么办？\n如果这一行activation大，那这一行 S 值乘2来凸显出这一行重要。（AWQ）\n在数学约定中激活值是 $y=Wx$，但在工程约定中是 $Y=XW$（为了方便批处理）\n1.3.1.3. Activation-aware Weight Quantization (激活感知权重Z化 AWQ) AWQ 是一种极快且高精度的训练后量化 (PTQ) 方法。它的核心洞察是：“我们不需要保护所有的权重，我们只需要保护那些与‘异常激活值’相乘的 1% 的‘显著权重’(Salient Weights) 就够了。”\n原理：\n$$\rY = XW = X \\cdot (W / s) \\cdot s\r$$这个 s 是一个缩放因子 (Scale)。这个等式看起来毫无意义，但 AWQ 的魔力在于：\n这个 s 是逐通道 (Per-Channel) 的。 这个 s 是激活感知的。 AWQ的工作流程：\n推理前执行一次：\n搜索 (Search / Observe) 运用少量数据通过模型。 观察激活值X，识别出包含异常值的通道。 标记这些通道对应的权重为显著权重。 计算并缩放 (Scale \u0026amp; Apply) AWQ 为每一个权重通道（Channel） $W_c$ 计算一个最佳缩放因子 $s_c$。 目标：找到一个 ，使得预缩放后的权重 $W'_c = W_c / s_c$ 在被四舍五入 (RTN) 时，误差最小。 量化与保存 (Quantize \u0026amp; Save) 将预缩放后的 $W' = W / s$ 矩阵，用最简单、最快的 RTN 量化为 INT4 整数 $W'_q$。 将这个 $W'_q$ (INT4 矩阵) 和 s (FP16 向量) 保存下来。 推理时：\n加载 INT4 权重 $W'_q$ 和 FP16 缩放 $s$。 执行计算 $Y = X \\cdot (W'_q \\cdot s)$。 这个 $(W'_q \\cdot s)$ 操作可以被 CUDA 内核高度优化（先反量化 $W'$，再与 $X$ 相乘），速度极快。 1.4. Flash Attention vllm一般用的都是flash attention。\n简单来说，Flash Attention 的核心贡献是：让注意力计算变得又快又省显存，从而使处理超长序列（如 128K 甚至更长的上下文）成为可能。\n它的发明人 Tri Dao 的核心洞察是：标准注意力的瓶颈不在于计算（FLOPs），而在于显存的读写（Memory I/O）。\n标准注意力的操作过程：\n出现的问题是：GPU 的计算核心（SRAM，片上内存）速度极快，但容量很小；而 GPU 的显存（HBM）容量很大，但速度相对很慢。更糟糕的是，它必须在 HBM 中完整地创建（物化）那个 $N \\times N$ 的 S 和 P 矩阵。当序列长度 N 很大时（比如 64K），$N^2$ 是一个天文数字，这会耗尽所有显存。\n解决方法：\nFlashAttention 采用两种技术，将所有计算步骤“融合”到一个 CUDA 内核（Kernel）中：\n内核融合（Kernel Fusion）\nFlashAttention把所有计算步骤都放到GPU里不需要传进传出。\n分块/瓦片技术（Tiling）\n注意基础概念：\nCUDA概念：显卡的高带宽显存（HBM，速度慢容量大）；高速片上内存（on-chip memory）；这个内存中有静态RAM（SRAM，速度快容量小）。\nFlashAttention 简单来说就是用了两层for循环：第一层循环Q；第二层循环K和V。\n伪代码如下：\nimport torch import torch.nn as nn import math # --- 假设的超参数 (Hyperparameters) --- # 批次大小 (Batch Size): 8 # 序列长度 (Sequence Length): 100 # 模型维度 (d_model): 512 # 头的数量 (num_heads): 8 # 头的维度 (head_dim): 512 / 8 = 64 # ------------------------------------ class MultiHeadAttention(nn.Module): \u0026#34;\u0026#34;\u0026#34; 一个从零开始实现的多头注意力模块 (Python 伪代码) \u0026#34;\u0026#34;\u0026#34; def __init__(self, d_model, num_heads): super(MultiHeadAttention, self).__init__() # 确保 d_model 可以被 num_heads 整除 assert d_model % num_heads == 0, \u0026#34;d_model 必须能被 num_heads 整除\u0026#34; # 定义模型的关键维度 self.d_model = d_model # 模型的总维度 (512) self.num_heads = num_heads # 头的数量 (8) self.head_dim = d_model // num_heads # 每个头的维度 (64) # --- 1. 定义线性投影层 (W_q, W_k, W_v, W_o) --- # 这些是模型需要学习的“权重” # 它们将 (B, S, 512) 映射到 (B, S, 512) self.W_q = nn.Linear(d_model, d_model) # Query 投影层 self.W_k = nn.Linear(d_model, d_model) # Key 投影层 self.W_v = nn.Linear(d_model, d_model) # Value 投影层 # 这是 MHA 最后的“输出”投影层 self.W_o = nn.Linear(d_model, d_model) # Output 投影层 def forward(self, query, key, value, mask=None): \u0026#34;\u0026#34;\u0026#34; 前向传播 在“自注意力”中, query, key, 和 value 都是同一个输入 X 在“交叉注意力”中, query 是一个, 而 key 和 value 是另一个 \u0026#34;\u0026#34;\u0026#34; # --- 2. 获取批次大小 --- # query, key, value 的形状: [batch_size, seq_len, d_model] # 示例: [8, 100, 512] batch_size = query.shape[0] # --- 3. 线性投影 (Linear Projection) --- # (B, S, 512) -\u0026gt; (B, S, 512) Q = self.W_q(query) K = self.W_k(key) V = self.W_v(value) # --- 4. “拆分头”与“转置” (Split \u0026amp; Transpose for BMM) --- # 这是为了实现“单卡并行多头” (BMM技巧) 的关键一步 # 4a. 拆分 (Reshape): # (B, S, 512) -\u0026gt; (B, S, num_heads, head_dim) # 示例: (8, 100, 512) -\u0026gt; (8, 100, 8, 64) Q = Q.view(batch_size, -1, self.num_heads, self.head_dim) K = K.view(batch_size, -1, self.num_heads, self.head_dim) V = V.view(batch_size, -1, self.num_heads, self.head_dim) # 4b. 转置 (Transpose / Permute): # (B, S, H, D_h) -\u0026gt; (B, H, S, D_h) # 我们把“头的数量”(H) 提到“序列长度”(S) 之前， # 这样 GPU 就可以把 (B * H) 看作一个大批次，并行处理 8*8=64 个注意力计算 # 示例: (8, 100, 8, 64) -\u0026gt; (8, 8, 100, 64) Q = Q.permute(0, 2, 1, 3) K = K.permute(0, 2, 1, 3) V = V.permute(0, 2, 1, 3) # --- 5. 计算注意力分数 (Scaled Dot-Product Attention) --- # 5a. 矩阵乘法 Q @ K^T # Q 形状: (8, 8, 100, 64) # K^T 形状: (8, 8, 64, 100) # scores 形状: (8, 8, 100, 100) ##### 注意！这里用torch实现了2层for循环 ##### scores = torch.matmul(Q, K.transpose(-1, -2)) # 5b. 缩放 (Scaling) # 除以 head_dim 的平方根，防止梯度消失 scale_factor = math.sqrt(self.head_dim) scores = scores / scale_factor # 5c. 应用掩码 (Masking) # (这是可选的, 但在 Decoder 中必须有) if mask is not None: # mask 必须被塑造成 (8, 1, 1, 100) 或 (8, 8, 100, 100) scores = scores.masked_fill(mask == 0, float(\u0026#39;-1e9\u0026#39;)) # 5d. Softmax # 沿着最后一个维度 (K 的序列) 计算, 使每行的和为 1 # 形状不变: (8, 8, 100, 100) attention_weights = torch.softmax(scores, dim=-1) # --- 6. 将分数应用于 V (Apply to V) --- # attention_weights 形状: (8, 8, 100, 100) # V 形状: (8, 8, 100, 64) # context 形状: (8, 8, 100, 64) # 这是 MHA 的“加权求和”步骤 context = torch.matmul(attention_weights, V) # --- 7. “合并头” (Concatenate Heads) --- # 这是 BMM 技巧的“逆操作” # 7a. 转置 (Transpose / Permute): # (B, H, S, D_h) -\u0026gt; (B, S, H, D_h) # 示例: (8, 8, 100, 64) -\u0026gt; (8, 100, 8, 64) context = context.permute(0, 2, 1, 3) # 7b. 重塑 (Reshape / View): # 把所有头“拼接”回一个 d_model 向量 # (B, S, H, D_h) -\u0026gt; (B, S, H * D_h) -\u0026gt; (B, S, d_model) # 示例: (8, 100, 8, 64) -\u0026gt; (8, 100, 512) # .contiguous() 是在 permute 后必须的, 确保内存是连续的 context = context.contiguous().view(batch_size, -1, self.d_model) # --- 8. 最终线性层 (Final Linear Layer) --- # (B, S, 512) -\u0026gt; (B, S, 512) # 这一步 W_o 矩阵会“混合”所有头的信息 output = self.W_o(context) return output # --- 示例用法 --- if __name__ == \u0026#34;__main__\u0026#34;: # 1. 定义参数 BATCH_SIZE = 8 SEQ_LENGTH = 100 D_MODEL = 512 NUM_HEADS = 8 # 2. 创建 MHA 模块 mha = MultiHeadAttention(d_model=D_MODEL, num_heads=NUM_HEADS) # 3. 创建一个随机输入张量 X (用于自注意力) # 形状: (batch_size, seq_len, d_model) -\u0026gt; (8, 100, 512) X = torch.rand(BATCH_SIZE, SEQ_LENGTH, D_MODEL) print(f\u0026#34;输入 X 的形状: {X.shape}\u0026#34;) # 4. 执行前向传播 # 在自注意力 (self-attention) 中, Q, K, V 都是 X output = mha(query=X, key=X, value=X, mask=None) print(f\u0026#34;输出 O 的形状: {output.shape}\u0026#34;) # 预期输出: # 输入 X 的形状: torch.Size([8, 100, 512]) # 输出 O 的形状: torch.Size([8, 100, 512]) 2. Reinforcement learning frameworks TODO\n资料 谷歌ML电子书：https://jax-ml.github.io/scaling-book/index: 英伟达博客：https://developer.nvidia.com/blog/mastering-llm-techniques-inference-optimization/ Lilian网红博客：https://lilianweng.github.io/posts/2023-01-10-inference-optimization/ (long article with quantization, etc) 硬核ML博客：https://ralphmao.github.io/ML-software-system/ 论文\nDeepSeek V3 Technical Report Mooncake: KV cache DistServe: disaggregated serving ","permalink":"https://sqf.icu/article/2a108f6b-06fd-8004-b40a-d0e444ef8883/","summary":"\u003cp\u003e\u003ca href=\"https://www.bilibili.com/list/watchlater/?bvid=BV1hcWozpEdk\u0026amp;oid=115412465489382\u0026amp;watchlater_cfg=%7B%22viewed%22%3A0,%22key%22%3A%22%22,%22asc%22%3Afalse%7D\u0026amp;spm_id_from=333.881.0.0\"\u003e验证码_哔哩哔哩\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"1-大语言模型的推理加速方案\"\u003e1. 大语言模型的推理加速方案\u003c/h1\u003e\n\u003ch2 id=\"11-为什么kv-cache不在training中使用只在inference中使用\"\u003e1.1. 为什么KV Cache不在training中使用只在inference中使用\u003c/h2\u003e\n\u003cp\u003e回答：因为训练（Training）和推理（Inference）的计算方式完全不同。\u003c/p\u003e","title":"大语言模型的推理加速方案"},{"content":"September 29, 2025 3:26 AM\nSeptember 29, 2025 3:32 AM\nSeptember 29, 2025 4:06 AM\n","permalink":"https://sqf.icu/article/28308f6b-06fd-8065-8947-e7716a009313/","summary":"\u003cp\u003eSeptember 29, 2025 3:26 AM\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"fuji_normal_star_merge.jpg\" loading=\"lazy\" src=\"/media/8cc6794d3a7b8c7b83e82b69.jpg\"\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003eSeptember 29, 2025 3:32 AM\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"fuji_night_result_star_merged.jpg\" loading=\"lazy\" src=\"/media/77200a37fb912e706cdaa1c3.jpg\"\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003eSeptember 29, 2025 4:06 AM\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"fuji_light_result.jpg\" loading=\"lazy\" src=\"/media/f9eccec893446325a3ed7e3b.jpg\"\u003e\u003c/p\u003e","title":"Fuji Lake Hotel"},{"content":"GitHub - OpenGVLab/InternVL: [CVPR 2024 Oral] InternVL Family: A Pioneering Open-Source Alternative to GPT-4o. 接近GPT-4o表现的开源多模态对话模型\nFine-tune on a Custom Dataset — InternVL\n环境安装 推理环境安装 # 下载repo git clone https://github.com/OpenGVLab/InternVL.git # conde建一个虚拟环境 conda create -n internvl python==3.10.14 conda activate internvl cd InternVL/ pip install -r requirements.txt pip install flash-attn --no-build-isolation 如果flash-attn==2.3.6安装失败，可能是flash-attn找不到对应nvcc版本。\n如果版本不对，重新安装nvcc\nsudo apt-get remove --purge nvidia-cuda-toolkit # 或者离线安装run文件（更稳定） wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-keyring_1.1-1_all.deb sudo dpkg -i cuda-keyring_1.1-1_all.deb sudo apt-get update sudo apt-get install cuda-toolkit-12-1 安装后续库\npip install flash-attn --no-build-isolation pip install -U openmim mim install mmcv-full 微调环境安装 Tutorial/docs/L1/XTuner at camp3 · InternLM/Tutorial\n注意的是，可以将xtuner的分支改到最新tag，这样pip安装才会出现可执行的xtuner。\n建议微调和推理环境分开。\n数据集处理 Chat Data Format — InternVL\n如果需要输入坐标信息，可以将坐标信息归一化到[0, 1000]之间的整型，token中有0到1000的数字，这样文本的token数量不会太多\n微调 关键设计决策（先说结论） 视觉 LoRA 而非解冻全部视觉参数：你当前 freeze_visual_encoder=True，配合 visual_encoder_lora 是正确的方向 —— 冻结 base 参数、只训练 LoRA adapter，适合少样本场景且显存友好。 target_modules 用子串匹配就够：你列出的模块里，视觉的 attention 是 attn.qkv，mlp 是 mlp.fc1/fc2，用 [\u0026quot;attn.qkv\u0026quot;,\u0026quot;mlp.fc1\u0026quot;,\u0026quot;mlp.fc2\u0026quot;] 即可匹配所有层。 少样本时减小 LoRA 容量、再加低 LR 与更多 epoch：把视觉 LoRA 的 r / alpha 调小（例如 r=32, alpha=32），学习率降到 1e-5 ~ 5e-6，并增加 epoch（3~10，视样本数）或用更多 gradient_accumulation_steps。 把 bbox 显式写入训练 prompt：训练样本的文本（context）应包含 bbox 信息（格式化为 boxes: [[x1,y1,x2,y2,label], ...] 或自然语言描述），模型依据该 context 学习把视觉特征和 bbox 对齐。 数据量小 -\u0026gt; 强正则/数据增强/重复采样：对图片做轻微 augment（翻转/色彩 jitter）、使用重复采样或 upsampling 生成足够 batch。 遇到问题\n报错信息\n09/18 12:55:43 - mmengine - WARNING - \u0026#34;HardDiskBackend\u0026#34; is the alias of \u0026#34;LocalBackend\u0026#34; and the former will be deprecated in future. 09/18 12:55:43 - mmengine - INFO - Checkpoints will be saved to /mnt/d/Study/codes/home_codes/internvl_codes/xtuner/20250917_carton/work_dirs/20250918_internvl3. [rank0]: Traceback (most recent call last): [rank0]: File \u0026#34;/mnt/d/Study/codes/home_codes/internvl_codes/xtuner/xtuner/tools/train.py\u0026#34;, line 392, in \u0026lt;module\u0026gt; [rank0]: main() [rank0]: File \u0026#34;/mnt/d/Study/codes/home_codes/internvl_codes/xtuner/xtuner/tools/train.py\u0026#34;, line 388, in main [rank0]: runner.train() [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/mmengine/runner/_flexible_runner.py\u0026#34;, line 1200, in train [rank0]: model = self.train_loop.run() # type: ignore [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/mmengine/runner/loops.py\u0026#34;, line 289, in run [rank0]: self.run_iter(data_batch) [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/mmengine/runner/loops.py\u0026#34;, line 313, in run_iter [rank0]: outputs = self.runner.model.train_step( [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/mmengine/_strategy/deepspeed.py\u0026#34;, line 133, in train_step [rank0]: losses = self._run_forward(data, mode=\u0026#39;loss\u0026#39;) [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/mmengine/_strategy/deepspeed.py\u0026#34;, line 176, in _run_forward [rank0]: results = self.model(**data, mode=mode) [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/torch/nn/modules/module.py\u0026#34;, line 1773, in _wrapped_call_impl [rank0]: return self._call_impl(*args, **kwargs) [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/torch/nn/modules/module.py\u0026#34;, line 1784, in _call_impl [rank0]: return forward_call(*args, **kwargs) [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/deepspeed/utils/nvtx.py\u0026#34;, line 20, in wrapped_fn [rank0]: ret_val = func(*args, **kwargs) [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/deepspeed/runtime/engine.py\u0026#34;, line 2131, in forward [rank0]: loss = self.module(*inputs, **kwargs) [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/torch/nn/modules/module.py\u0026#34;, line 1773, in _wrapped_call_impl [rank0]: return self._call_impl(*args, **kwargs) [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/torch/nn/modules/module.py\u0026#34;, line 1879, in _call_impl [rank0]: return inner() [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/torch/nn/modules/module.py\u0026#34;, line 1827, in inner [rank0]: result = forward_call(*args, **kwargs) [rank0]: File \u0026#34;/mnt/d/Study/codes/home_codes/internvl_codes/xtuner/xtuner/model/internvl.py\u0026#34;, line 229, in forward [rank0]: outputs = self._llm_forward( [rank0]: File \u0026#34;/mnt/d/Study/codes/home_codes/internvl_codes/xtuner/xtuner/model/internvl.py\u0026#34;, line 267, in _llm_forward [rank0]: vit_embeds = self.model.extract_feature(pixel_values) [rank0]: File \u0026#34;/home/sun/.cache/huggingface/modules/transformers_modules/InternVL3-2B/modeling_internvl_chat.py\u0026#34;, line 186, in extract_feature [rank0]: vit_embeds = self.vision_model( [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/torch/nn/modules/module.py\u0026#34;, line 1773, in _wrapped_call_impl [rank0]: return self._call_impl(*args, **kwargs) [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/torch/nn/modules/module.py\u0026#34;, line 1784, in _call_impl [rank0]: return forward_call(*args, **kwargs) [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/peft/peft_model.py\u0026#34;, line 2721, in forward [rank0]: return self.base_model( [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/torch/nn/modules/module.py\u0026#34;, line 1773, in _wrapped_call_impl [rank0]: return self._call_impl(*args, **kwargs) [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/torch/nn/modules/module.py\u0026#34;, line 1784, in _call_impl [rank0]: return forward_call(*args, **kwargs) [rank0]: File \u0026#34;/home/sun/miniconda3/envs/xtuner/lib/python3.10/site-packages/peft/tuners/tuners_utils.py\u0026#34;, line 197, in forward [rank0]: return self.model.forward(*args, **kwargs) [rank0]: TypeError: InternVisionModel.forward() got an unexpected keyword argument \u0026#39;input_ids\u0026#39; 明白了，你 _llm_forward 里已经把视觉模型和语言模型都混合在一起了，但问题是 PEFT 封装会把 input_ids、attention_mask 等参数传给整个模型，导致 InternVisionModel.forward() 报错。\n核心思路是：视觉模型只接受 pixel_values，语言模型只接受 inputs_embeds 或 input_ids，两者不要混用参数。\n你可以这样改 _llm_forward：\ndef _llm_forward( self, pixel_values: torch.FloatTensor, input_ids: torch.LongTensor = None, attention_mask: Optional[torch.Tensor] = None, position_ids: Optional[torch.LongTensor] = None, image_flags: Optional[torch.LongTensor] = None, past_key_values: Optional[List[torch.FloatTensor]] = None, labels: Optional[torch.LongTensor] = None, use_cache: Optional[bool] = None, output_attentions: Optional[bool] = None, output_hidden_states: Optional[bool] = None, return_dict: Optional[bool] = None, ) -\u0026gt; Union[Tuple, CausalLMOutputWithPast]: return_dict = return_dict if return_dict is not None else self.model.config.use_return_dict # --- 1. 视觉前向，只有 pixel_values --- vit_embeds = self.model.extract_feature(pixel_values) if image_flags is not None: image_flags = image_flags.squeeze(-1) vit_embeds = vit_embeds[image_flags == 1] vit_batch_size = pixel_values.shape[0] # --- 2. 文本嵌入 --- input_embeds = self.model.language_model.get_input_embeddings()(input_ids).clone() B, N, C = input_embeds.shape input_embeds = input_embeds.reshape(B * N, C) input_ids_flat = input_ids.reshape(B * N) selected = input_ids_flat == self.model.img_context_token_id if selected.any(): vit_embeds = vit_embeds.reshape(-1, C) n_token = selected.sum() input_embeds[selected] = input_embeds[selected] * 0.0 + vit_embeds[:n_token] input_embeds = input_embeds.reshape(B, N, C) # --- 3. 语言模型前向 --- outputs = self.model.language_model( inputs_embeds=input_embeds, attention_mask=attention_mask, position_ids=position_ids, past_key_values=past_key_values, use_cache=use_cache, output_attentions=output_attentions, output_hidden_states=output_hidden_states, return_dict=return_dict, ) logits = outputs.logits loss = None if labels is not None: shift_logits = logits[..., :-1, :].contiguous() shift_labels = labels[..., 1:].contiguous() loss_fct = CrossEntropyLoss() shift_logits = shift_logits.view(-1, self.model.language_model.config.vocab_size) shift_labels = shift_labels.view(-1).to(shift_logits.device) loss = loss_fct(shift_logits, shift_labels) if not return_dict: output = (logits,) + outputs[1:] return (loss,) + output if loss is not None else output return CausalLMOutputWithPast( loss=loss, logits=logits, past_key_values=outputs.past_key_values, hidden_states=outputs.hidden_states, attentions=outputs.attentions, ) ✅ 改动重点：\n视觉模型单独前向，不传 input_ids、attention_mask 等。 文本模型单独使用 inputs_embeds 前向。 LoRA/PEFT 调用 _llm_forward 时不会把不需要的参数传给视觉模型。 推理 # prompt = \u0026#34;\u0026#34;\u0026#34;Detect all objects in the image and output only bounding boxes as a list of integers. # Each box should tightly enclose the object but slightly expand to fully cover it. # Prioritize larger objects and boxes with higher confidence scores. # Avoid duplicate or overlapping boxes; each object should appear only once. # Format each box as [x1, y1, x2, y2] (top-left to bottom-right). # Coordinates normalized to 0-1000, integers, x1\u0026lt;x2, y1\u0026lt;y2. # Return [] if no objects are found. # Do NOT include any Markdown, quotes, or extra text. # Example: [[225, 315, 531, 633], [352, 836, 546, 995]]\u0026#34;\u0026#34;\u0026#34; 对于多边形的推理和微调\nLoRA 可以让模型学会 polygon 推理，但需要大量高质量 polygon 标注 + 格式约束，且训练难度高。 更实用的办法 是用 InternVL3 做 bbox 检测，再接 SAM / 语义分割网络 → polygon。 如果你只是想快速落地，建议优先用 检测 + SAM + mask2polygon，而不是直接逼 LLM 输出 polygon。 ","permalink":"https://sqf.icu/article/26d08f6b-06fd-80a7-bfaa-f893df120648/","summary":"\u003cp\u003e\u003ca href=\"https://github.com/OpenGVLab/InternVL?tab=readme-ov-file\"\u003eGitHub - OpenGVLab/InternVL: [CVPR 2024 Oral] InternVL Family: A Pioneering Open-Source Alternative to GPT-4o.  接近GPT-4o表现的开源多模态对话模型\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://internvl.readthedocs.io/en/latest/internvl3.0/finetune.html\"\u003eFine-tune on a Custom Dataset — InternVL\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"环境安装\"\u003e环境安装\u003c/h1\u003e\n\u003ch2 id=\"推理环境安装\"\u003e推理环境安装\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 下载repo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone https://github.com/OpenGVLab/InternVL.git\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# conde建一个虚拟环境\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econda create -n internvl python\u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e3.10.14\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econda activate internvl\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd InternVL/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip install -r requirements.txt\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip install flash-attn --no-build-isolation\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e如果flash-attn==2.3.6安装失败，可能是flash-attn找不到对应nvcc版本。\u003c/p\u003e","title":"internvl3 微调记录"},{"content":"安装软件\nsudo apt-get update sudo apt-get install parallel sudo apt-get install pigz 建立一个可执行文件，如compress_dirs.sh\n#!/bin/bash # Function to compress a directory using pigz compress_dir() { local dir=$1 tar -cf - \u0026#34;$dir\u0026#34; | pigz \u0026gt; \u0026#34;${dir}.tar.gz\u0026#34; } export -f compress_dir # Check if at least one argument (the root directory) is provided if [ \u0026#34;$#\u0026#34; -lt 1 ]; then echo \u0026#34;Usage: $0 root_directory [exclude_folder1 exclude_folder2 ...]\u0026#34; exit 1 fi # Get the root directory root_directory=$1 shift # Get the folders to exclude exclude_folders=(\u0026#34;$@\u0026#34;) # Build the find command with exclusion criteria find_command=\u0026#34;find \\\u0026#34;$root_directory\\\u0026#34; -maxdepth 1 -type d -not -path \u0026#39;$root_directory\u0026#39;\u0026#34; for folder in \u0026#34;${exclude_folders[@]}\u0026#34;; do find_command+=\u0026#34; -not -name \\\u0026#34;$(basename \u0026#34;$folder\u0026#34;)\\\u0026#34;\u0026#34; done # Execute the find command and compress the directories using parallel with progress bar and increased parallelism eval \u0026#34;$find_command\u0026#34; | parallel --bar compress_dir 使用方法\n./compress_dirs.sh /path/of/root/need/compress/dirs /path/of/exec/dir1 /path/of/exec/dir2 ... 例子\n~/Documents/test$ ls 1 2 3 ~/Documents/test$ ~/Documents/compress_dirs_2.sh . 1 ~/Documents/test$ ls 1 2 2.tar.gz 3 3.tar.gz ","permalink":"https://sqf.icu/article/bc20d785-c21b-46ca-9f88-328a8d0cff90/","summary":"\u003cp\u003e安装软件\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get update\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get install parallel\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get install pigz\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e建立一个可执行文件，如compress_dirs.sh\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#!/bin/bash\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Function to compress a directory using pigz\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecompress_dir\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    local dir\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e$1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    tar -cf - \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$dir\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e | pigz \u0026gt; \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003edir\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e.tar.gz\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport -f compress_dir\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Check if at least one argument (the root directory) is provided\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$#\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e -lt \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e; \u003cspan style=\"color:#66d9ef\"\u003ethen\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    echo \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Usage: \u003c/span\u003e$0\u003cspan style=\"color:#e6db74\"\u003e root_directory [exclude_folder1 exclude_folder2 ...]\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    exit \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efi\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Get the root directory\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eroot_directory\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e$1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eshift\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Get the folders to exclude\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexclude_folders\u003cspan style=\"color:#f92672\"\u003e=(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$@\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Build the find command with exclusion criteria\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efind_command\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;find \\\u0026#34;\u003c/span\u003e$root_directory\u003cspan style=\"color:#e6db74\"\u003e\\\u0026#34; -maxdepth 1 -type d -not -path \u0026#39;\u003c/span\u003e$root_directory\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e folder in \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003eexclude_folders[@]\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e; \u003cspan style=\"color:#66d9ef\"\u003edo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    find_command\u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34; -not -name \\\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003ebasename \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$folder\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e)\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\\\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edone\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Execute the find command and compress the directories using parallel with progress bar and increased parallelism\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eeval \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$find_command\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e | parallel --bar compress_dir\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e使用方法\u003c/p\u003e","title":"Ubuntu 批量压缩文件夹"},{"content":"基于以下文章使用\n树莓派4B 安装opencv完整教程基于python3（各种错误解决）-腾讯云开发者社区-腾讯云\n下载opencv_4.9.0, opencv_contrib_4.9.0, 在opencv文件夹下建立编译地址\ncd opencv mkdir build cd build 修改cmake命令\ncmake -D CMAKE_BUILD_TYPE=RELEASE \\ -D CMAKE_INSTALL_PREFIX=/usr/local \\ -D INSTALL_C_EXAMPLES=ON \\ -D INSTALL_PYTHON_EXAMPLES=ON \\ -D OPENCV_EXTRA_MODULES_PATH=/home/sun/Desktop/camera/downloads/opencv_contrib/modules \\ -D BUILD_EXAMPLES=ON \\ -D WITH_LIBV4L=ON \\ -D WITH_GSTREAMER=ON \\ -D PYTHON3_EXECUTABLE=/usr/bin/python3.11 \\ -D PYTHON_INCLUDE_DIR=/usr/include/python3.11 \\ -D PYTHON_LIBRARY=/usr/lib/aarch64-linux-gnu/libpython3.11.so \\ -D PYTHON3_NUMPY_INCLUDE_DIRS=/usr/lib/python3/dist-packages/numpy/core/include \\ .. cmake结束的时候会打印出, 要安装的opencv的插件.\n安装\nmake make install 查看安装是否成功\nimport cv2 print(cv2.__version__) print(cv2.getBuildInformation()) opencv调用gstreamer gstreamer代码\ngstreamer_pipeline = ( \u0026#34;v4l2src device=/dev/video0 ! \u0026#34; \u0026#34;queue max-size-buffers=1 leaky=downstream ! \u0026#34; # 将队列大小控制到1, 确保实时性 \u0026#34;video/x-raw, format=(string)UYVY, width=(int)1920, height=(int)1080, framerate=(fraction)30/1 ! \u0026#34; \u0026#34;videoconvert ! \u0026#34; \u0026#34;appsink\u0026#34; ) ","permalink":"https://sqf.icu/article/1d04a080-16d9-4aaa-b386-27009bbdd612/","summary":"\u003cp\u003e基于以下文章使用\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://cloud.tencent.com/developer/article/2036841\"\u003e树莓派4B 安装opencv完整教程基于python3（各种错误解决）-腾讯云开发者社区-腾讯云\u003c/a\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e下载opencv_4.9.0, opencv_contrib_4.9.0, 在opencv文件夹下建立编译地址\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-jsx\" data-lang=\"jsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ecd\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eopencv\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003emkdir\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebuild\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ecd\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebuild\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e修改cmake命令\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-jsx\" data-lang=\"jsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ecmake\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eD\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCMAKE_BUILD_TYPE\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eRELEASE\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\\\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eD\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCMAKE_INSTALL_PREFIX\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/usr/local \\\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eD\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eINSTALL_C_EXAMPLES\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eON\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\\\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eD\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eINSTALL_PYTHON_EXAMPLES\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eON\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\\\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eD\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eOPENCV_EXTRA_MODULES_PATH\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/home/sun/Desktop/camera/downloads/opencv_contrib/modules \\\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eD\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBUILD_EXAMPLES\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eON\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\\\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eD\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eWITH_LIBV4L\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eON\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\\\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eD\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eWITH_GSTREAMER\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eON\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\\\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eD\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePYTHON3_EXECUTABLE\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/usr/bin/python3.11 \\\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eD\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePYTHON_INCLUDE_DIR\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/usr/include/python3.11 \\\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eD\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePYTHON_LIBRARY\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/usr/lib/aarch64-linux-gnu/libpython3.11.so \\\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eD\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePYTHON3_NUMPY_INCLUDE_DIRS\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/usr/lib/python3/dist-packages/numpy/core/include \\\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e..\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003ecmake结束的时候会打印出, 要安装的opencv的插件.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e安装\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-jsx\" data-lang=\"jsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003emake\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003emake\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einstall\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e查看安装是否成功\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-jsx\" data-lang=\"jsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecv2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eprint\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecv2\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003e__version__\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eprint\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecv2\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003egetBuildInformation\u003c/span\u003e())\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":"树莓派5 编译安装opencv和gstreamer插件"},{"content":"1. 介绍以下配置 这次组机用的是 40 系列显卡 + 7000 系列 AMD 处理器。 2. 安装时遇到的一些问题 2.1. windows 部分 烧录系统镜像的时候，如果用的是 MacOS，需要将 U 盘格式设置成 NTFS 格式。\n因为现在 windows 的镜像中的存在大于 4 GB 的文件，所以 FAT32 无法使用。MacOS 需要安装支持 NTFS 的软件，有的需要购买，但是可以试用，用完卸载即可。\n安装结束后重启，可能会发现网卡和无线网卡搜索不到信号。\n因为驱动没有安装，需要上主板场商的官网下载，注意！一定要对应主板型号，不同型号的驱动大概率是没法驱动硬件的。\n2.2. Ubuntu 部分 7000 系列 cpu 存在支持问题。\n选择最新的版本的系统比较好，如：24.04; 23.10; 22.04 LTS.\n安装时会遇到 u盘加载镜像卡住的问题。\n选择安全模式进入\n安装结束后重启，可能会出现启动卡横杠卡图标的问题\n原因:\n显卡驱动没有安装\n解决方法:\n先要解决进入系统的问题\n启动前 grub 选择ubuntu项, e进入编辑, 在倒数第二行 Linux 的 ro 或quiet 参数后加上 nomodeset. 然后点 F10 进入.\n安装显卡驱动\nUbuntu18-22.04安装和干净卸载nvidia显卡驱动——超详细、最简单_ubuntu安装nvidia显卡驱动-CSDN博客\n中间显卡驱动下载可以用scp传一下.\n","permalink":"https://sqf.icu/article/7acae4a7-d2f2-46a1-8153-f9c528d7391c/","summary":"\u003ch1 id=\"1-介绍以下配置\"\u003e1. 介绍以下配置\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e这次组机用的是 40 系列显卡 + 7000 系列 AMD 处理器。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"2-安装时遇到的一些问题\"\u003e2. 安装时遇到的一些问题\u003c/h1\u003e\n\u003ch2 id=\"21-windows-部分\"\u003e2.1. windows 部分\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e烧录系统镜像的时候，如果用的是 MacOS，需要将 U 盘格式设置成 NTFS 格式。\u003c/p\u003e\n\u003cp\u003e因为现在 windows 的镜像中的存在大于 4 GB 的文件，所以 FAT32 无法使用。MacOS 需要安装支持 NTFS 的软件，有的需要购买，但是可以试用，用完卸载即可。\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e安装结束后重启，可能会发现网卡和无线网卡搜索不到信号。\u003c/p\u003e\n\u003cp\u003e因为驱动没有安装，需要上主板场商的官网下载，注意！一定要对应主板型号，不同型号的驱动大概率是没法驱动硬件的。\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"组装 pc 安装 Windows 和 Ubuntu 双系统可能会遇到的问题"},{"content":"B站首发！草履虫都能看懂的【傅里叶变换】讲解，清华大学李永乐老师教你如何理解傅里叶变换，辨清美颜和变声原理，！！_哔哩哔哩_bilibili\n1. 傅里叶级数 傅里叶级数可以将 所有周期性函数 转换为 三角函数的组合.\n周期性函数可以使用相位, 振幅和频率这三个参数表示.\n$$\r\\begin{align*} f(t)\u0026=\\frac{a_0}{2}+\\sum a_n \\cdot \\sin(n\\omega t+\\varphi_n) \\\\\u0026= \\frac{a_0}{2}+\\sum a_n\\sin n\\omega t + \\sum b_n\\cos n\\omega t \\\\ \u0026\\Rightarrow 1\\cdot \\sin n\\omega t \\cdot \\cos n\\omega t \\end{align*}\r$$ 经过变换, 函数就可以用 $1,\\sin n\\omega t , \\cos n\\omega t$ 这三个参数表示, 这三个参数互为标准正交基. 2. 傅里叶变换 傅里叶变换可以表示所有函数 (非周期函数可以理解为长度无限长的周期函数), 首先要搞懂欧拉公式\n所有的三角函数都可以用复数平面坐标系和复指数函数表示. (对于任意实数也是成立的)\n这里用的是实数A. 当 $\\theta=\\omega t$ 的时候, 就是点 A 逆时针旋转. 这时候公式就可以用作表示周期性函数. $\\theta=-\\omega t$ 的时候, 可以表示顺时针旋转. 这里假设一段含有多个三角函数的函数(不同频率的信号), 假设其中含有一个频率为 $\\omega$ 的 $\\sin$ 函数信号, 那么用频率为 $\\omega$ 的 $\\sin n \\omega t$ 去点乘这个信号, 就可以去掉其他所有的 $\\cos n \\omega t$. (把函数想象成频率空间的向量, 一个向量在另一个方向 $\\omega$ 上没有分量的话, 那么这个向量与方向 $\\omega$ 的单位向量内积为 0 是很自然的)\n而这里的欧拉公式里两种三角函数 ($\\sin \\cos$) 都有, 所以可以直接用在下面的公式里, 探测某个特定频率的信号是否存在.\n$$\r\\int_{-\\infty}^{+\\infty} f(t) e^{-j \\omega t} \\cdot d t\\left\\{\\begin{array}{l}=0\\ 不含\\omega \\\\\\neq 0\\ 含\\omega\\end{array}\\right.\r$$这时候用积分就很快, 因为积分可以直接计算整个时间长度. 这时如果结果为 0, 说明这个频率的信号不存在, 如果结果不为 0, 那么函数含有这个频率的信号.\n而傅里叶逆变换可以将某个特定频率的信号配合相位 (信号开始的位置), 下图的虚部就是相位. 实部就是真实的信号, $\\omega$ 就是频率.\n$$\rf(t)=\\int_{-\\infty}^{+\\infty} F_T(\\omega) e^{j \\omega t} \\cdot d \\omega\r$$ 上面两个公式只要遍历所有的频率就可以提取或还原出所有频率的信号了.\n","permalink":"https://sqf.icu/article/5a6ddc86-1a4b-4fee-b875-54a4b2b936a4/","summary":"\u003cp\u003e\u003ca href=\"https://www.bilibili.com/video/BV1aW4y1y7Hs/?spm_id_from=333.337.search-card.all.click\u0026amp;vd_source=0847973121d4fdd8364284ef7353ef09\"\u003eB站首发！草履虫都能看懂的【傅里叶变换】讲解，清华大学李永乐老师教你如何理解傅里叶变换，辨清美颜和变声原理，！！_哔哩哔哩_bilibili\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"1-傅里叶级数\"\u003e1. 傅里叶级数\u003c/h1\u003e\n\u003cp\u003e傅里叶级数可以将 所有周期性函数 转换为 三角函数的组合.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/1e7bfe6e8b3e854806f5e400.png\"\u003e\u003c/p\u003e\n\u003cp\u003e周期性函数可以使用相位, 振幅和频率这三个参数表示.\u003c/p\u003e\n$$\r\n\\begin{align*} f(t)\u0026=\\frac{a_0}{2}+\\sum a_n \\cdot \\sin(n\\omega t+\\varphi_n) \\\\\u0026= \\frac{a_0}{2}+\\sum a_n\\sin n\\omega t + \\sum b_n\\cos n\\omega t \\\\ \u0026\\Rightarrow 1\\cdot \\sin n\\omega t \\cdot \\cos n\\omega t \\end{align*}\r\n$$\u003cul\u003e\n\u003cli\u003e经过变换, 函数就可以用 $1,\\sin n\\omega t , \\cos n\\omega t$ 这三个参数表示, 这三个参数互为标准正交基.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"2-傅里叶变换\"\u003e2. 傅里叶变换\u003c/h1\u003e\n\u003cp\u003e傅里叶变换可以表示所有函数 (非周期函数可以理解为长度无限长的周期函数), 首先要搞懂欧拉公式\u003c/p\u003e","title":"傅里叶变换"},{"content":"1. 状态转移矩阵 从当前状态到下一个状态的转换.\n例子: 假设跟踪车辆形式\n车辆的状态矩阵, 位置变量 $p_t$; 速度变量 $v_t$.\n$$\rx_t=\\begin{bmatrix}\rp_t \\\\\rv_t\r\\end{bmatrix}\r$$ 假设车辆有加速度变量 $u_t$; 这里 $\\Delta t$ 是单位时间; 这里就可以从上一个单位时间的 $p_{t-1}v_{t-1}$ 推导出当前的 $p_tv_t$.\n$$\r\\begin{aligned}p_t=\u0026p_{t-1}+v_{t-1}\\times\\Delta t+u_t\\times\\frac{\\Delta t^2}{2}\\\\v_t=\u0026v_{t-1}+u_t\\times\\Delta t\\end{aligned}\r$$ 这里可以发现输出变量是输入变量的线性组合, 所以卡尔曼滤波器是线性滤波器, 只能描述状态与状态之间的线性关系. 由于是线性关系, 所以可以将公式写成矩阵的形式.\n$$\r\\left[\\begin{array}{c}p_t \\\\v_t\\end{array}\\right]=\\left[\\begin{array}{cc}1 \u0026 \\Delta t \\\\0 \u0026 1\\end{array}\\right]\\left[\\begin{array}{c}p_{t-1} \\\\v_{t-1}\\end{array}\\right]+\\left[\\begin{array}{c}\\frac{\\Delta t^2}{2} \\\\\\Delta t\\end{array}\\right] u_t\r$$ 提取公式中带时间参数矩阵之后, 就可以简化公式获得卡尔曼滤波器中的状态预测公式.\n$$\r\\begin{aligned}\u0026F_t=\\left[\\begin{array}{cc}1 \u0026 \\Delta t \\\\0 \u0026 1\\end{array}\\right], B_t=\\left[\\begin{array}{c}\\frac{\\Delta t^2}{2} \\\\\\Delta t\\end{array}\\right]\\\\\u0026\\hat{x}_t^{-}=F_t \\hat{x}_{t-1}+B_t u_t\\end{aligned} \\quad\\quad \\text{(1)}\r$$ 这里的 $\\hat{x}_t^{-}$ 表示, 这个值有 hat 符号是预测值, 并不是真实值; 右上角减号表示这个值是从 t-1 时刻的参数估计而来, 还需要 t 时刻的观测值进行修正.\n2. 协方差矩阵 协方差描述的是变量之间的相关程度.\n首先, 可以使用中心值核方差来描述一个变量的分布情况.\n而对于存在两个变量的分布情况, 需要用到二维坐标系. 可以在两个轴分别描述两个变量的中心值和方差. 如果两个变量没有明显线性关系时, 分布情况图为左一; 两变量分布正相关时, 图为中间; 分布为负相关时, 图为右一. 可以发现这三种情况用中间值和方差是无法体现的.\n为了描述两变量之间的相关程度, 使用了协方差. 协方差矩阵的公式如下\n$$\r\\operatorname{cov}(x, x)=\\left[\\begin{array}{ll}\\sigma_{11} \u0026 \\sigma_{12} \\\\\\sigma_{12} \u0026 \\sigma_{22}\\end{array}\\right]\r$$ 其中, $\\sigma_{12}$ 表示的就是两变量的协方差. 还是拿车辆速度举例, 由 $P^-_t$ 来表示不确定性在各个时间段内的传递关系, 是当前时刻先验估计协方差.\n$$\rP^-_t=F_tP_{t-1}F_t^T+Q_t \\quad\\quad \\text{(2)}\r$$ $F_t$ 表示的是状态转换矩阵里带时间变量的 $F_t$ 矩阵. 之所以两边都乘, 是因为协方差矩阵的性质. 协方差的更新方法, 如果要将每一个点都乘以矩阵 $A$, 公式如下: $$\rcov(x)=\\sum \\\\cov(Ax)=A\\sum A^T\r$$ $Q$ 是状态转移协方差, 用来描述状态转换矩阵和实际过程之间的误差. 这个值是可以设置的参数, 值越大, 表示我们对预测值的信任值越高. 因为这样会增大 $P^-_t$. 3. 观测矩阵 描述系统实际状态, 与观测到的数值之间的关系.\n例1, 地球上的汽车位置为 [经度, 纬度, 海拔], 但是地图导航软件常常默认海拔为 0, 也就是不需要观测数据中的海拔信息.\n那么地图需要的观测数据 $Z_t$ 如下:\n$$\rZ_t=\\begin{vmatrix}\r经度 \u0026 纬度 \u0026 海拔 \\\\\r1 \u0026 0 \u0026 0\\\\\r0 \u0026 1 \u0026 0 \\\\\r0 \u0026 0 \u0026 0\r\\end{vmatrix}.\\begin{vmatrix}经度值\\\\纬度值\\\\海拔值 \\end{vmatrix}\r$$ 例2, 还是车辆速度问题, 如果有个测距仪在每个时间段进行测距, 获得标量 $Z_t$.\n这时候, 观测矩阵为 $H=\\begin{vmatrix}1\u00260\\end{vmatrix}$, 因为车辆的状态矩阵中有用的只有位置变量 $p_t$.\n获得 $Z_t$ 公式如下:\n$$\rZ_t=Hx_t+c\r$$ $c$ 描述观测值和预测值的残差, 因为观测值也不一定准确. 这时候, $Z_t$ (观测值)和 $H\\hat{x}_t^-$ (预测值) 都是已知的, 所以可以算出:\n$$\rc = Z_t-H\\hat{x}_t^-\r$$ 测量噪声的协方差为 $R$, 可以手动设定的参数.\n4. 状态更新 计算出卡尔曼系数 $K_t$, 也叫滤波增益系数, 它的作用有两个\n权衡预测状态协方差 $P^-_t$ 和 观察值的残差协方差 $R$ 的大小, 来决定观测值的权重. (相信预测模型还是观测值, 如果相信预测模型多一点, 那么 $K_t$ 就会小一点; 反之则 $K_t$ 就会大一点)\n$$\rK_t=\\frac{P_t^{-} H^T}{H P_t^{-} H^T+R}\\quad\\quad \\text{(3)}\r$$ 将残差的表现形式从观测域转换为状态域. 因为, 观察值和状态值的维度可能就是不同的, 所以需要转换. 举车辆速度的例子来说, 观测值只有车辆的位置没有速度, 但是车辆状态有速度和位置. 这时候, $K_t$ 中包含了协方差矩阵 $P^-_t$ 的信息, 所以可以利用位置和速度的相关性, 从位置的残差 $c$ 推算出速度的残差.\n计算当前状态, 由 状态预测公式 $\\hat{x}_t^{-}$+ 卡尔曼系数 $K_t$ * 观测值和预测值的残差 $c$ 获得.\n$$\r\\hat{x}_t=\\hat{x}_t^{-}+K_t\\left(z_t-H \\hat{x}_t^{-}\\right) \\quad\\quad \\text{(4)}\r$$ 更新最佳估计值的噪声协方差矩阵 $P_t$, 在下一时刻作为 $P_{t-1}$ 用于 $P^-_t$ 的计算.\n$$\rP_t=(I-K_tH)P^-_t \\quad\\quad \\text{(5)}\r$$ 5. 实际使用 需要调试的参数\n$\\Delta t$: 其实修改的是转态转移矩阵, 不同的运动状态可以使用不同的矩阵\n$R$: 测量噪声的协方差, $R$ 取值越小收敛越快, $R$ 取值越大收敛越慢;\n$Q$: 状态转移协方差矩阵, 值越大, 表示我们对预测值的信任值越高; 当状态转换过程为已确定时, $Q$ 的取值越小越好; 转换状态不确定的时候, $Q$ 可以去随机值, 随时间变化, 这时滤波器变为自适应卡尔曼滤波器.\n使用测距仪获得单位时间车辆距离测距仪的距离, 预测车辆速度.\nimport numpy as np import matplotlib.pyplot as plt N = 100 gt_data = np.arange(0, N) noise = np.random.randn(1, N) # 制造一些观测误差 noise = noise * 20 gt_data_n = (noise + gt_data).reshape(N) gt_data_n_list = (noise + gt_data).tolist()[0] delta_t = 1 X = np.zeros((2, 1)) # 状态矩阵 P = np.array([[1, 0], [0, 1]]) # 状态协方差矩阵 F = np.array([[1, delta_t], [0, 1]]) # 状态转移矩阵, 初始单位时间为1 Q = np.array([[0.0001, 0], [0, 0.0001]]) # 状态转移协方差矩阵 H = np.array([[1, 0]]) # 观测矩阵 \u0026lt;- 注意这里数组必须套在数组里面, 不然无法转置 R = 10 # 观测噪声方差矩阵 \u0026lt;- 由于距离的噪声是一维的所以这里不用矩阵了 B = np.array([[0.5 * np.sqrt(delta_t)], [delta_t]]) # 控制量 U = 0 distances = [] speeds = [] for i in range(N): X_ = F @ X + B * U # 状态预测公式 P_ = F @ P @ F.T + Q # 预测状态协方差公式 K = (P_ @ H.T) @ np.linalg.inv(H @ P @ H.T + R) # 更新卡尔曼系数 X = X_ + K @ (gt_data_n_list[i] - H @ X_) # 更新状态预测公式 P = (np.eye(2) - K @ H) @ P_ # 更新状态协方差矩阵 distances.append(float(X[0])) speeds.append(float(X[1])) # 画图 plt.scatter(distances, speeds) plt.xlabel(\u0026#39;distances\u0026#39;) plt.ylabel(\u0026#39;speeds\u0026#39;) plt.axhline(1) # 画一条辅助线方便观察 plt.show() 对于有车有固定加速度的情况\nimport numpy as np import matplotlib.pyplot as plt N = 100 gt_data = np.arange(0, N) gt_data = np.square(gt_data) noise = np.random.randn(1, N) # 制造一些观测误差 noise = noise * 20 gt_data_n = (noise + gt_data).reshape(N) gt_data_n_list = (noise + gt_data).tolist()[0] delta_t = 1.42 X = np.zeros((2, 1)) # 状态矩阵 P = np.array([[1, 0], [0, 1]]) # 状态协方差矩阵 F = np.array([[1, delta_t], [0, 1]]) # 状态转移矩阵, 初始单位时间为1 Q = np.array([[0.0001, 0], [0, 0.0001]]) # 状态转移协方差矩阵 H = np.array([[1, 0]]) # 观测矩阵 \u0026lt;- 注意这里数组必须套在数组里面, 不然无法转置 R = 1 # 观测噪声方差矩阵 \u0026lt;- 由于距离的噪声是一维的所以这里不用矩阵了 B = np.array([[0.5 * np.sqrt(delta_t)], [delta_t]]) # 控制量 U = 1 distances = [] speeds = [] for i in range(N): X_ = F @ X + B * U # 状态预测公式 P_ = F @ P @ F.T + Q # 预测状态协方差公式 K = (P_ @ H.T) @ np.linalg.inv(H @ P @ H.T + R) # 更新卡尔曼系数 X = X_ + K @ (gt_data_n_list[i] - H @ X_) # 更新状态预测公式 P = (np.eye(2) - K @ H) @ P_ # 更新状态协方差矩阵 distances.append(float(X[0])) speeds.append(float(X[1])) # 画图 # 画预测值 plt.plot(distances, speeds, \u0026#34;x\u0026#34;, label=\u0026#34;prec\u0026#34;) # 画真实值 y=(2x)^(1/2) true_y = np.sqrt(2 * gt_data) plt.plot(gt_data, true_y, label=\u0026#34;gt\u0026#34;) # 画观测值 true_y_n = np.sqrt(2 * gt_data_n) plt.plot( gt_data_n, true_y_n, \u0026#34;o\u0026#34;, label=\u0026#34;obs\u0026#34;, ) plt.xlabel(\u0026#39;distances\u0026#39;) plt.ylabel(\u0026#39;speeds\u0026#39;) plt.legend() plt.show() print() 如果车的加速度是非线性变化 (前50s, a=1; 后50s, a=3) 的情况, 无法准确预测\nimport numpy as np import matplotlib.pyplot as plt N = 100 a_1 = 1 a_2 = 3 def cul_true_data(time1, time2): speed1 = a_1 * time1 speed2 = (a_1 * time1)[-1] + a_2 * time2 return np.append(speed1, speed2) gt_time = np.arange(0, N // 2) # 单位时间 0-50 gt_distance = 0.5 * np.square(a_1 * gt_time) # 加速度 a1 last_speed = (a_1 * gt_time)[-1] # gt_time_2 = np.arange(N // 2, N) # 单位时间 50-100 gt_distance_2 = gt_distance[-1] + last_speed * gt_time + 0.5 * np.square( a_2 * gt_time) # a2 gt_data_merge = np.append(gt_distance, gt_distance_2) noise = np.random.randn(1, N) # 制造一些观测误差 noise = noise * 5 gt_data_n = (noise + gt_data_merge).reshape(N) gt_data_n_list = (noise + gt_data_merge).tolist()[0] delta_t = 1.5 X = np.zeros((2, 1)) # 状态矩阵 P = np.array([[1, 0], [0, 1]]) # 状态协方差矩阵 F = np.array([[1, delta_t], [0, 1]]) # 状态转移矩阵, 初始单位时间为1 Q = np.array([[0.0001, 0], [0, 0.0001]]) # 状态转移协方差矩阵 H = np.array([[1, 0]]) # 观测矩阵 \u0026lt;- 注意这里数组必须套在数组里面, 不然无法转置 R = 1 # 观测噪声方差矩阵 \u0026lt;- 由于距离的噪声是一维的所以这里不用矩阵了 B = np.array([[0.5 * np.sqrt(delta_t)], [delta_t]]) # 控制量 U = 2 distances = [] speeds = [] for i in range(N): X_ = F @ X + B * U # 状态预测公式 P_ = F @ P @ F.T + Q # 预测状态协方差公式 K = (P_ @ H.T) @ np.linalg.inv(H @ P @ H.T + R) # 更新卡尔曼系数 X = X_ + K @ (gt_data_n_list[i] - H @ X_) # 更新状态预测公式 P = (np.eye(2) - K @ H) @ P_ # 更新状态协方差矩阵 distances.append(float(X[0])) speeds.append(float(X[1])) # 画图 # 画预测值 plt.plot(distances, speeds, \u0026#34;x\u0026#34;, label=\u0026#34;prec\u0026#34;) # 画真实值 true_y = cul_true_data(gt_time, gt_time) plt.plot(gt_data_merge, true_y, label=\u0026#34;gt\u0026#34;) plt.xlabel(\u0026#39;distances\u0026#39;) plt.ylabel(\u0026#39;speeds\u0026#39;) plt.legend() plt.show() print() 更复杂的应用可以看这里\n卡尔曼滤波应用及其matlab实现-腾讯云开发者社区-腾讯云\n6. 总结 优点：\n卡尔曼滤波器是一种最优的滤波器，具有最小均方误差，能够有效地消除噪声和抖动。 卡尔曼滤波器不仅可以估计状态，还可以估计状态的协方差，对于系统的不确定性有一定的鲁棒性。 卡尔曼滤波器可以实时地进行状态估计，响应速度较快。 缺点：\n卡尔曼滤波器的理论基础是线性高斯系统，对于非线性、非高斯的系统效果可能不佳。 卡尔曼滤波器需要准确的先验信息，如果先验信息不准确，则滤波结果也会不准确。 卡尔曼滤波器计算量较大，对计算能力有一定要求。 参考资料 1. 1. 1. 卡尔曼滤波器的原理以及在matlab中的实现_哔哩哔哩_bilibili\n深入理解卡尔曼滤波算法_卡尔曼算法-CSDN博客\n卡尔曼滤波器的优缺点有哪些？ - 知乎\n调参 卡尔曼滤波中关键参数的调整\n","permalink":"https://sqf.icu/article/5c88b7d2-6531-44bb-bb54-88c4e04f5e12/","summary":"\u003ch1 id=\"1-状态转移矩阵\"\u003e1. 状态转移矩阵\u003c/h1\u003e\n\u003cp\u003e从当前状态到下一个状态的转换.\u003c/p\u003e\n\u003cp\u003e例子: 假设跟踪车辆形式\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e车辆的状态矩阵, 位置变量 $p_t$; 速度变量 $v_t$.\u003c/p\u003e\n$$\r\n    x_t=\\begin{bmatrix}\r\n      p_t \\\\\r\n      v_t\r\n    \\end{bmatrix}\r\n    $$\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e假设车辆有加速度变量 $u_t$; 这里 $\\Delta t$ 是单位时间; 这里就可以从上一个单位时间的 $p_{t-1}v_{t-1}$ 推导出当前的 $p_tv_t$.\u003c/p\u003e\n$$\r\n    \\begin{aligned}p_t=\u0026p_{t-1}+v_{t-1}\\times\\Delta t+u_t\\times\\frac{\\Delta t^2}{2}\\\\v_t=\u0026v_{t-1}+u_t\\times\\Delta t\\end{aligned}\r\n    $$\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e这里可以发现输出变量是输入变量的线性组合, 所以卡尔曼滤波器是线性滤波器, 只能描述状态与状态之间的线性关系. 由于是线性关系, 所以可以将公式写成矩阵的形式.\u003c/p\u003e\n$$\r\n    \\left[\\begin{array}{c}p_t \\\\v_t\\end{array}\\right]=\\left[\\begin{array}{cc}1 \u0026 \\Delta t \\\\0 \u0026 1\\end{array}\\right]\\left[\\begin{array}{c}p_{t-1} \\\\v_{t-1}\\end{array}\\right]+\\left[\\begin{array}{c}\\frac{\\Delta t^2}{2} \\\\\\Delta t\\end{array}\\right] u_t\r\n    $$\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e提取公式中带时间参数矩阵之后, 就可以简化公式获得卡尔曼滤波器中的状态预测公式.\u003c/p\u003e\n$$\r\n    \\begin{aligned}\u0026F_t=\\left[\\begin{array}{cc}1 \u0026 \\Delta t \\\\0 \u0026 1\\end{array}\\right], B_t=\\left[\\begin{array}{c}\\frac{\\Delta t^2}{2} \\\\\\Delta t\\end{array}\\right]\\\\\u0026\\hat{x}_t^{-}=F_t \\hat{x}_{t-1}+B_t u_t\\end{aligned} \\quad\\quad \\text{(1)}\r\n    $$\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e这里的 $\\hat{x}_t^{-}$ 表示, 这个值有 hat 符号是预测值, 并不是真实值; 右上角减号表示这个值是从 t-1 时刻的参数估计而来, 还需要 t 时刻的观测值进行修正.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"卡尔曼滤波算法和应用"},{"content":"Mermaid 可以画很多类型的图, 详细可以查看官方说明书\nAbout Mermaid | Mermaid\n1. 调出 Mermaid 绘制界面 在 Notion 页面中输入/code 插入代码块. 左上角代码类型选择 Mermaid, 右边的 Split 表示代码和思维导图同时表示, 类似于 Markdown 编辑器一边编辑一边预览.\n2. Mermaid 代码编辑 部分的绘图开始申明, 需要写在第一行 → {图的类型} {图形的方向}\ngraph LR\r图的类型--\u0026gt;flowchart_流程图\r图的类型--\u0026gt;graph_简单思维导图 graph LR\r图的类型--\u0026gt;flowchart_流程图\r图的类型--\u0026gt;graph_简单思维导图 graph TB\r图形方向--\u0026gt;LR_从左向右\r图形方向--\u0026gt;RL_从右向左\r图形方向--\u0026gt;TB_从上向下\r图形方向--\u0026gt;BT_从下向上 graph TB\r图形方向--\u0026gt;LR_从左向右\r图形方向--\u0026gt;RL_从右向左\r图形方向--\u0026gt;TB_从上向下\r图形方向--\u0026gt;BT_从下向上 字体类型和语法\nflowchart LR\ra[\u0026#34;`第一行\r第二行`\u0026#34;]\raa[\u0026#34;`**粗体**`\u0026#34;]\rb[\u0026#34;`_斜体_`\u0026#34;]\rc([节点形状1])\rd(节点形状2)\re[[节点形状3]]\rf[(数据库形状)]\rg((圆形))\rh{菱形}\ri[使用\u0026amp;]\rj[b]\rk[c]\rl[d]\ra--\u0026gt;aa~~~b\rc==\u0026gt;d---e--text---f--text--\u0026gt;g-.-\u0026gt;h\ri--\u0026gt;j \u0026amp; k--\u0026gt;l flowchart LR\ra[\u0026#34;`第一行\r第二行`\u0026#34;]\raa[\u0026#34;`**粗体**`\u0026#34;]\rb[\u0026#34;`_斜体_`\u0026#34;]\rc([节点形状1])\rd(节点形状2)\re[[节点形状3]]\rf[(数据库形状)]\rg((圆形))\rh{菱形}\ri[使用\u0026amp;]\rj[b]\rk[c]\rl[d]\ra--\u0026gt;aa~~~b\rc==\u0026gt;d---e--text---f--text--\u0026gt;g-.-\u0026gt;h\ri--\u0026gt;j \u0026amp; k--\u0026gt;l Mindmaps 思维导图\nroot定格写; 一级内容前加一个空格; 二级内容前加两个空格\nmindmap\rroot((root))\rAAAA\rBBBB\rCCCC mindmap\rroot((root))\rAAAA\rBBBB\rCCCC Pie chart diagrams 饼图\npie title test title\r\u0026#34;class 1\u0026#34;: 50\r\u0026#34;class 2\u0026#34;: 50 pie title test title\r\u0026#34;class 1\u0026#34;: 50\r\u0026#34;class 2\u0026#34;: 50 Quadrant chart 象限图\nquadrantChart\rtitle Reach and engagement of campaigns\rx-axis Low Reach --\u0026gt; High Reach\ry-axis Low Engagement --\u0026gt; High Engagement\rquadrant-1 We should expand\rquadrant-2 Need to promote\rquadrant-3 Re-evaluate\rquadrant-4 May be improved\rCampaign A: [0.3, 0.6]\rCampaign B: [0.45, 0.23]\rCampaign C: [0.57, 0.69]\rCampaign D: [0.78, 0.34]\rCampaign E: [0.40, 0.34]\rCampaign F: [0.35, 0.78] quadrantChart\rtitle Reach and engagement of campaigns\rx-axis Low Reach --\u0026gt; High Reach\ry-axis Low Engagement --\u0026gt; High Engagement\rquadrant-1 We should expand\rquadrant-2 Need to promote\rquadrant-3 Re-evaluate\rquadrant-4 May be improved\rCampaign A: [0.3, 0.6]\rCampaign B: [0.45, 0.23]\rCampaign C: [0.57, 0.69]\rCampaign D: [0.78, 0.34]\rCampaign E: [0.40, 0.34]\rCampaign F: [0.35, 0.78] XY chart XY 图表\n数据前 line 表示折线; bar 表示条形图\nxychart-beta\rtitle \u0026#34;Sales Revenue\u0026#34;\rx-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]\ry-axis \u0026#34;Revenue (in $)\u0026#34; 4000 --\u0026gt; 11000\rbar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]\rline [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] ","permalink":"https://sqf.icu/article/3d1f1cc9-811e-4cd5-a2c4-e6153484b55c/","summary":"\u003cp\u003eMermaid 可以画很多类型的图, 详细可以查看官方说明书\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://mermaid.js.org/intro/\"\u003eAbout Mermaid | Mermaid\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"1-调出-mermaid-绘制界面\"\u003e1. 调出 Mermaid 绘制界面\u003c/h1\u003e\n\u003cp\u003e在 Notion 页面中输入\u003ccode\u003e/code\u003c/code\u003e 插入代码块. 左上角代码类型选择 \u003ccode\u003eMermaid\u003c/code\u003e, 右边的 \u003ccode\u003eSplit\u003c/code\u003e 表示代码和思维导图同时表示, 类似于 \u003ccode\u003eMarkdown\u003c/code\u003e 编辑器一边编辑一边预览.\u003c/p\u003e","title":"Notion Mermaid 绘制思维导图流程图"},{"content":"1. 安装Ubuntu 首先检查windows是否可以更新, 必须保持在可以更新的状态才可以下载ubuntu镜像.\n管理员模式打开终端, 查看wsl可以安装的linux版本\nPS C:\\wsl_ubuntu\u0026gt; wsl --list --online 以下是可安装的有效分发的列表。 请使用“wsl --install -d \u0026lt;分发\u0026gt;”安装。 NAME FRIENDLY NAME Ubuntu Ubuntu Debian Debian GNU/Linux kali-linux Kali Linux Rolling Ubuntu-18.04 Ubuntu 18.04 LTS Ubuntu-20.04 Ubuntu 20.04 LTS Ubuntu-22.04 Ubuntu 22.04 LTS OracleLinux_8_5 Oracle Linux 8.5 OracleLinux_7_9 Oracle Linux 7.9 SUSE-Linux-Enterprise-Server-15-SP4 SUSE Linux Enterprise Server 15 SP4 openSUSE-Leap-15.4 openSUSE Leap 15.4 openSUSE-Tumbleweed openSUSE Tumbleweed 安装ubuntu\n如果windows无法更新这里会出现错误代码: 0x80070005.\nPS C:\\wsl_ubuntu\u0026gt; wsl --install -d Ubuntu-20.04 正在安装: Ubuntu 20.04 LTS 已安装 Ubuntu 20.04 LTS。 正在启动 Ubuntu 20.04 LTS… 启动ubuntu\n安装完可能出现报错: WslRegisterDistribution failed with error: 0x800701bc\n原因: linux内核没有更新. https://github.com/microsoft/WSL/issues/5393 解决方法: 更新linux内核 2. 开启ssh 修改/etc/ssh/sshd_config结尾加上密码登录, 端口等参数\nPermitRootLogin no PasswordAuthentication yes PubkeyAuthentication no Port xxx 重启ssh\nsudo service ssh start 可能出现报错: sshd: no hostkeys available -- exiting 解决方法: sudo ssh-keygen -A wsl启动时，自动启动ssh\n在~/.bashrc或~/.profile添加以下命令\n# 检查 SSH 服务是否正在运行，如果没有，则启动它 if ! pgrep -x \u0026#34;sshd\u0026#34; \u0026gt; /dev/null; then sudo service ssh start fi 无sudo密码启动ssh服务\nsudo visudo # 添加以下内容，在[username]处填写自己的用户名 [username] ALL=(ALL) NOPASSWD: /usr/sbin/service ssh start 3. 自动化windows虚拟网卡ip修改+启动ssh服务 wsl的虚拟网卡在windows重启的时候, ip地址会自动改变. 编写bat文件, 管理员运行.\n由于每次wsl重启都会重置网卡配置, 所以可以写一个脚本自动修改网卡\n在 wsl Ubuntu home 目录下添加一个脚本set_eth0.sh(注意脚本保存的位置), 桥接网卡到host, 并打开 ssh 服务\n#!/bin/bash new_ip=192.168.31.xxx brd=192.168.31.255 gateway=192.168.31.1 nameserver=192.168.31.1 net_dev=eth0 echo \u0026#34;password\u0026#34; | sudo -S ip addr del $(ip addr show $net_dev | grep \u0026#39;inet\\b\u0026#39; | awk \u0026#39;{print $2}\u0026#39; | head -n 1) dev $net_dev sudo ip addr add $new_ip/24 broadcast $brd dev $net_dev sudo ip route add 0.0.0.0/0 via $gateway dev $net_dev sudo sed -i \u0026#34;\\$c nameserver $nameserver\u0026#34; /etc/resolv.conf sudo service ssh start powershell桥接网络脚本\n在windows中新建开启脚本: wsl-bridge-on.ps1\n# 检查并以管理员身份运行PS并带上参数 $currentWi = [Security.Principal.WindowsIdentity]::GetCurrent() $currentWp = [Security.Principal.WindowsPrincipal]$currentWi if( -not $currentWp.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { $boundPara = ($MyInvocation.BoundParameters.Keys | foreach{\u0026#39;-{0} {1}\u0026#39; -f $_ ,$MyInvocation.BoundParameters[$_]} ) -join \u0026#39; \u0026#39; $currentFile = $MyInvocation.MyCommand.Definition $fullPara = $boundPara + \u0026#39; \u0026#39; + $args -join \u0026#39; \u0026#39; Start-Process \u0026#34;$psHome\\powershell.exe\u0026#34; -ArgumentList \u0026#34;$currentFile $fullPara\u0026#34; -verb runas return } #首先随意执行一条wsl指令，确保wsl启动，这样后续步骤才会出现WSL网络 echo \u0026#34;正在检测wsl运行状态...\u0026#34; wsl --cd ~ -e ls echo \u0026#34;正在获取网卡信息...\u0026#34; Get-NetAdapter echo \u0026#34;`n正在将WSL网络桥接到以太网...\u0026#34; Set-VMSwitch WSL -NetAdapterName 以太网 echo \u0026#34;`n正在修改WSL网络配置...\u0026#34; wsl --cd ~ -e sh -c ./setup/set_eth0.sh echo \u0026#34;`ndone\u0026#34; 注意这里的Start-Process \u0026quot;$psHome\\powershell.exe\u0026quot; , 需要用终端输入$psHome 查看 powershell 路径, 该路径下是 powershell.exe 还是 pwsh.exe. powershell 取消桥接脚本, 可以不使用\n在 windows 中新建关闭脚本: wsl-bridge-off.ps1\n# 检查并以管理员身份运行PS并带上参数 $currentWi = [Security.Principal.WindowsIdentity]::GetCurrent() $currentWp = [Security.Principal.WindowsPrincipal]$currentWi if( -not $currentWp.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { $boundPara = ($MyInvocation.BoundParameters.Keys | foreach{\u0026#39;-{0} {1}\u0026#39; -f $_ ,$MyInvocation.BoundParameters[$_]} ) -join \u0026#39; \u0026#39; $currentFile = $MyInvocation.MyCommand.Definition $fullPara = $boundPara + \u0026#39; \u0026#39; + $args -join \u0026#39; \u0026#39; Start-Process \u0026#34;$psHome\\pwsh.exe\u0026#34; -ArgumentList \u0026#34;$currentFile $fullPara\u0026#34; -verb runas return } echo \u0026#34;正在解除wsl桥接...\u0026#34; Set-VMSwitch WSL -SwitchType Internal echo \u0026#34;正在重启wsl\u0026#34; wsl --shutdown wsl --cd ~ -e ls echo \u0026#34;`ndone\u0026#34; pause windows 下设置 ps1 文件运行程序\n分别右键 wsl-bridge-on.ps1 和 wsl-bridge-off.ps1 这两个脚本, 直接默认powershell运行 (或在打开方式中选择其它应用, 找到powershell安装路径下的可执行文件pwsh.exe, 勾选始终使用此应用打开.ps1文件, 这样就可以直接双击运行了).\n不过, 默认情况下 windows powershell 不允许执行自定义脚本, 所以需要修改设置打开执行权限.\n管理员方式打开 powershell, 执行 Set-ExecutionPolicy Unrestricted 或 Set-ExecutionPolicy RemoteSigned\n将 ps1 文件添加到开始屏幕\n给 ps1 文件创建一个快捷方式, 复制到C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs文件夹下, 修改文件名.\n之后, 开始菜单搜索目标文件名, 右键添加开始屏幕即可.\n3.1. mirror模式设置网络 https://blog.gazer.win/essay/wsl2-mirrored-network.html/comment-page-2#comments\n注意，设置的时候TUN模式需要关掉，防止wsl虚拟机的首选网卡从连接互联网的口变成TUN的虚拟网卡的口。可以通过ip addr来查看。\n4. WSL 安装 ubuntu 之后, ubuntu 内使用 nvidia-smi 失效 加入 .bachrc 文件中\nexport PATH=/usr/lib/wsl/lib:$PATH 5. WSL 无法 ping 通 Windows 宿主机 因为 windows 防火墙屏蔽了外来的 icmp 包, 需要给防火墙添加规则\nWSL2 网络异常排查 [ping 不通、网络地址异常、缺少默认路由、被宿主机防火墙拦截] - SocialistYouth - 博客园\n6. 安装图形化界面 7. WSL 中的cuda驱动是和宿主机共享 由于 CUDA 驱动的地址在 Windows 路径下, 所以安装 opencv 等 python 库关联的模块会出现各种环境问题. 如果需要做开发用的话, 不建议使用 WSL.\n安装opencv clone opencv和opencv_contrib 版本改为4.5.5\nmkdir build in opencv\nsudo apt-get update sudo apt install -y build-essential cmake git pkg-config libgtk-3-dev \\ libavcodec-dev libavformat-dev libswscale-dev libv4l-dev \\ libxvidcore-dev libx264-dev libjpeg-dev libpng-dev libtiff-dev \\ gfortran openexr libatlas-base-dev python3-dev python3-numpy \\ libtbb2 libtbb-dev libdc1394-22-dev gcc-8 g++-8 使用 update-alternatives 切换到 GCC 8：\nsudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 100 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-8 100 sudo update-alternatives --config gcc sudo update-alternatives --config g++ gcc --version g++ --version # 如果要切换回原来的 GCC 版本 sudo update-alternatives --config gcc sudo update-alternatives --config g++ cmake编译\ncmake -D CMAKE_BUILD_TYPE=Release \\ -D CMAKE_INSTALL_PREFIX=/usr/local \\ -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules \\ -D WITH_CUDA=ON \\ -D ENABLE_FAST_MATH=1 \\ -D CUDA_FAST_MATH=1 \\ -D WITH_CUBLAS=1 \\ -D BUILD_opencv_python3=ON \\ -D PYTHON3_EXECUTABLE=$(which python) \\ -D PYTHON3_INCLUDE_DIR=$(python -c \u0026#34;from distutils.sysconfig import get_python_inc; print(get_python_inc())\u0026#34;) \\ -D PYTHON3_LIBRARY=$(python -c \u0026#34;import distutils.sysconfig as sysconfig; print(sysconfig.get_config_var(\u0026#39;LIBDIR\u0026#39;))\u0026#34;) \\ -D CMAKE_CXX_FLAGS=\u0026#34;-Wno-unused-command-line-argument\u0026#34; \\ -D CMAKE_C_FLAGS=\u0026#34;-Wno-unused-command-line-argument\u0026#34; \\ .. 编译安装\nmake -j$(nproc) sudo make install 如果安装了图形化界面，再图形化界面使用终端会发现nvidia-smi不能用。\n所以需要安装cuda驱动\nsudo apt install nvidia-driver-535 sudo apt install nvidia-cuda-toolkit # 或者本地安装 - PATH includes /usr/local/cuda-12.8/bin - LD_LIBRARY_PATH includes /usr/local/cuda-12.8/lib64, or, add /usr/local/cuda-12.8/lib64 8. WSL 安装smb挂在ext4磁盘 挂载磁盘\nwmic diskdrive list brief # 找到物理连接的磁盘 wsl --mount \\\\.\\PHYSICALDRIVE0 --type ext4 --partition 2 # 挂载磁盘并注意分区 ","permalink":"https://sqf.icu/article/596f072e-c529-4e8d-9179-d3dca39099e5/","summary":"\u003ch1 id=\"1-安装ubuntu\"\u003e1. 安装Ubuntu\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e首先检查windows是否可以更新, 必须保持在可以更新的状态才可以下载ubuntu镜像.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e管理员模式打开终端, 查看wsl可以安装的linux版本\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePS C:\\wsl_ubuntu\u0026gt; wsl --list --online\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e以下是可安装的有效分发的列表\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e请使用\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e“\u003c/span\u003ewsl --install -d \u0026lt;分发\u0026gt;\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e”\u003c/span\u003e安装\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eNAME                                   FRIENDLY NAME\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUbuntu                                 Ubuntu\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDebian                                 Debian GNU/Linux\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ekali-linux                             Kali Linux Rolling\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUbuntu-\u003cspan style=\"color:#ae81ff\"\u003e18.04\u003c/span\u003e                           Ubuntu \u003cspan style=\"color:#ae81ff\"\u003e18.04\u003c/span\u003e LTS\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUbuntu-\u003cspan style=\"color:#ae81ff\"\u003e20.04\u003c/span\u003e                           Ubuntu \u003cspan style=\"color:#ae81ff\"\u003e20.04\u003c/span\u003e LTS\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUbuntu-\u003cspan style=\"color:#ae81ff\"\u003e22.04\u003c/span\u003e                           Ubuntu \u003cspan style=\"color:#ae81ff\"\u003e22.04\u003c/span\u003e LTS\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eOracleLinux_8_5                        Oracle Linux \u003cspan style=\"color:#ae81ff\"\u003e8.5\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eOracleLinux_7_9                        Oracle Linux \u003cspan style=\"color:#ae81ff\"\u003e7.9\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSUSE-Linux-Enterprise-Server-\u003cspan style=\"color:#ae81ff\"\u003e15\u003c/span\u003e-SP4    SUSE Linux Enterprise Server \u003cspan style=\"color:#ae81ff\"\u003e15\u003c/span\u003e SP4\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eopenSUSE-Leap-\u003cspan style=\"color:#ae81ff\"\u003e15.4\u003c/span\u003e                     openSUSE Leap \u003cspan style=\"color:#ae81ff\"\u003e15.4\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eopenSUSE-Tumbleweed                    openSUSE Tumbleweed\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e安装ubuntu\u003c/p\u003e\n\u003cp\u003e如果windows无法更新这里会出现错误代码: \u003ccode\u003e0x80070005\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePS C:\\wsl_ubuntu\u0026gt; wsl --install -d Ubuntu-\u003cspan style=\"color:#ae81ff\"\u003e20.04\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e正在安装\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e:\u003c/span\u003e Ubuntu \u003cspan style=\"color:#ae81ff\"\u003e20.04\u003c/span\u003e LTS\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e已安装 Ubuntu \u003cspan style=\"color:#ae81ff\"\u003e20.04\u003c/span\u003e LTS\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e正在启动 Ubuntu \u003cspan style=\"color:#ae81ff\"\u003e20.04\u003c/span\u003e LTS\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e…\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e启动ubuntu\u003c/p\u003e\n\u003cp\u003e安装完可能出现报错: \u003ccode\u003eWslRegisterDistribution failed with error: 0x800701bc\u003c/code\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e原因: linux内核没有更新. \u003ca href=\"https://github.com/microsoft/WSL/issues/5393\"\u003ehttps://github.com/microsoft/WSL/issues/5393\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e解决方法: \u003ca href=\"https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi\"\u003e更新linux内核\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"Windows 安装 WSL2 Ubuntu"},{"content":"论文PDF: Battle of the Backbones: A Large-Scale Comparison of Pretrained Models across Computer Vision Tasks\n爱可可 AI 前沿推介(11.2)\n动机 当前计算机视觉系统的构建通常依赖于预训练或随机初始化的特征提取器作为骨干网络, 而选择合适的骨干网络是一个困难的问题, 因此需要一个方法来比较不同的预训练模型, 以帮助从业者做出明智的选择.\n方法 本文提出一种名为 Battle of the Backbones 的方法, 通过对一系列预训练模型进行基准测试, 包括视觉-语言模型, 自监督学习模型和稳定扩散骨干等, 涵盖了从分类, 目标检测到 OOD 泛化等各种计算机视觉任务. 通过对1500多次训练运行的全面分析, 揭示了现有方法的优势和不足, 并为研究社区指明了前进的方向.\nOOD 检测任务: 在训练集和测试集非独立同分布的情况下, ODD 模型能够检测出异常样本. (能够找出训练时没有学过的样本)\n基于深度模型的Out of Distribution(OOD)检测相关方法介绍\n优势 该方法为从业者提供了一个更加明确和全面的选择预训练模型的依据, 同时揭示了传统卷积神经网络在大多数任务上仍然表现最好, 而自监督学习模型在相同架构和相似大小的预训练数据集上也具有竞争力. 此外, 该研究还提供了原始实验结果和代码, 使研究人员能对自己的骨干网络进行测试和比较.\n在分类, 检测, 分割, 域外推广和检索任务上比较了各种预训练模型的性能. 对于实践者来说，有监督 ConvNeXt, SwinV2 和 CLIP 的整体表现最好, 更小规模下, ConvNeXt-Tiny, SwinV2-Tiny 和 DINO ViT-Small 表现最好. 尽管Transformer和自监督学习越来越受欢迎, 但在大多数所考虑的任务上, 有监督卷积网络仍然优于其他方法. 与 CNN 相比, ViT 更依赖模型和数据集规模, CLIP 在没有大数据集的情况下也有竞争力. 在相似的训练设置下, 自监督学习可以优于有监督的预训练, 这意味着更先进的架构和更大的数据集可能会有帮助. 不同视觉任务之间的性能强烈相关, 支持通用模型. 选啥主干网络精度高? 选啥轻量化主干网络精度高? ","permalink":"https://sqf.icu/article/61dd6c0b-f460-44c6-8a15-84260e5be4b5/","summary":"\u003cp\u003e论文PDF: \u003ca href=\"https://arxiv.org/pdf/2310.19909.pdf\"\u003eBattle of the Backbones: A Large-Scale Comparison of Pretrained Models across Computer Vision Tasks\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://zhuanlan.zhihu.com/p/664613648\"\u003e爱可可 AI 前沿推介(11.2)\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"动机\"\u003e动机\u003c/h2\u003e\n\u003cp\u003e当前计算机视觉系统的构建通常依赖于预训练或随机初始化的特征提取器作为骨干网络, 而选择合适的骨干网络是一个困难的问题, 因此需要一个方法来比较不同的预训练模型, 以帮助从业者做出明智的选择.\u003c/p\u003e","title":"不同任务下主干网络的选择"},{"content":"对于一些Fork到自己项目的git项目更新的同步方法, 这里使用NotionNext作为例子进行简单介绍.\n1. 前置条件 Fork https://github.com/tangly1024/NotionNext 项目, 将自己的NotionNext项目克隆下来.\n新建一个分支new_branch\ngit checkout -b new_branch 所有对项目的修改都在这个分支上完成, commit and push.\n添加原项目的url到本地.\ngit remote add remote https://github.com/tangly1024/NotionNext.git git remote add [remote名称] [项目克隆url] git remote -v # 可以看到目前仓库的remote信息 2. 更新到项目最新版本 过了一段时间后, 原项目可能会修复一些bug或者加一些新功能.\n从原项目拉取最新版本的代码到本地自己项目的main分支\ngit checkout main git pull remote main 回到自己修改的分支new_branch, 将main分支合并到new_branch上.\ngit checkout new_branch git merge main vscode打开项目文件夹, 查看冲突的文件, 选择需要保留的部分, commit and push.\n","permalink":"https://sqf.icu/article/a7b27af0-4cbf-4b6b-a748-6a5a474b1734/","summary":"\u003cp\u003e对于一些Fork到自己项目的git项目更新的同步方法, 这里使用NotionNext作为例子进行简单介绍.\u003c/p\u003e\n\u003ch1 id=\"1-前置条件\"\u003e1. 前置条件\u003c/h1\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003eFork \u003ca href=\"https://github.com/tangly1024/NotionNext\"\u003ehttps://github.com/tangly1024/NotionNext\u003c/a\u003e 项目, 将自己的NotionNext项目克隆下来.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e新建一个分支\u003ccode\u003enew_branch\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit checkout \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eb new_branch\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e所有对项目的修改都在这个分支上完成, commit and push.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e添加原项目的url到本地.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit remote add remote https:\u003cspan style=\"color:#f92672\"\u003e//\u003c/span\u003egithub\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ecom\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003etangly1024\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eNotionNext\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003egit\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit remote add [remote名称] [项目克隆url]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit remote \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ev  \u003cspan style=\"color:#75715e\"\u003e# 可以看到目前仓库的remote信息\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/887e202cd0fcde5c425525cf.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e","title":"对于一些git项目更新的同步方法"},{"content":"1. 数据的预处理 对于缺失值 缺失量少，均值，中位数等填充； 缺失量多，离散化； 拟合模型填充. 对于异常值 基于统计的方法：3 sigma 聚类方法 isolation forest 等算法. 2. 特征工程 连续特征, 离散特征\n特征组合, 生成新的特征\n特征的归一化 (Normalization) 对于在一定范围内的特征\neg: 身高\n线性函数归一化 (Min-Max Scaling)\n$X_{norm}=\\frac{X-X_{min}}{X_{max}-X_{min}}$\n零均值归一化 (Z-Score Normalization) = 标准化 (Standardization)\n$z=\\frac{x-\\mu}{\\sigma}$\n$\\mu$: 均值. $\\sigma$: 标准差\n$\\sigma = \\sqrt{\\frac{\\sum (x_i-\\mu)^2}{N}}$\n优点:\n在变量更新速度不一致的情况下, 归一化能更好的实现梯度下降 线性变换不会改变原始数据的数值排序 类别型特征 (Categorical Feature) 对于只在有限选项内取值的特征\neg: 性别, 血型 特征的选择\nFilter(过滤法) 按照发散性或相关性对各个特征进行评分, 设定阈值或者待选择特征的个数进行筛选 就是, 算特征与特征之间的关系 Pearson()皮尔森相关系数: 单个变量之间的线性相关性，结果的取值区间为[-1,1] from scipy.stats import pearsonr 优点: 速度快 缺点: 只对线性关系敏感 卡方验证 类别型变量对类别型变量的相关性 最大信息系数 maximal information coefficient (MIC) from minepy import MINE Wrapper(包装法) 根据目标函数(往往是预测效果评分), 每次选择若干特征, 或者排除若干特征 Embedded(嵌入法) 先使用某些机器学习的模型进行训练, 得到各个特征的权值系数, 根据系数从大到小选择特征(类似于Filter, 只不过系数是通过训练得来的) word2vec 特征的降维\n","permalink":"https://sqf.icu/article/fc73927e-b575-4ed7-b32b-d4a958d8e137/","summary":"\u003ch1 id=\"1-数据的预处理\"\u003e1. 数据的预处理\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e对于缺失值\n\u003cul\u003e\n\u003cli\u003e缺失量少，均值，中位数等填充；\u003c/li\u003e\n\u003cli\u003e缺失量多，离散化；\u003c/li\u003e\n\u003cli\u003e拟合模型填充.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e对于异常值\n\u003cul\u003e\n\u003cli\u003e基于统计的方法：3 sigma\u003c/li\u003e\n\u003cli\u003e聚类方法\u003c/li\u003e\n\u003cli\u003eisolation forest 等算法.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"2-特征工程\"\u003e2. 特征工程\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e连续特征, 离散特征\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e特征组合, 生成新的特征\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/media/aa3fb43318aa943c53ca3b29.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e特征的归一化 (Normalization) 对于在一定范围内的特征\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eeg: 身高\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e线性函数归一化 (Min-Max Scaling)\u003c/p\u003e\n\u003cp\u003e$X_{norm}=\\frac{X-X_{min}}{X_{max}-X_{min}}$\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e零均值归一化 (Z-Score Normalization) = 标准化 (Standardization)\u003c/p\u003e\n\u003cp\u003e$z=\\frac{x-\\mu}{\\sigma}$\u003c/p\u003e\n\u003cp\u003e$\\mu$: 均值. $\\sigma$: 标准差\u003c/p\u003e\n\u003cp\u003e$\\sigma = \\sqrt{\\frac{\\sum (x_i-\\mu)^2}{N}}$\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e优点:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e在变量更新速度不一致的情况下, 归一化能更好的实现梯度下降\u003c/li\u003e\n\u003cli\u003e线性变换不会改变原始数据的数值排序\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e类别型特征 (Categorical Feature) 对于只在有限选项内取值的特征\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eeg: 性别, 血型\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e特征的选择\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eFilter(过滤法)\n\u003cul\u003e\n\u003cli\u003e按照发散性或相关性对各个特征进行评分, 设定阈值或者待选择特征的个数进行筛选\u003c/li\u003e\n\u003cli\u003e就是, 算特征与特征之间的关系\n\u003cul\u003e\n\u003cli\u003ePearson()皮尔森相关系数: 单个变量之间的线性相关性，结果的取值区间为[-1,1]\n\u003cul\u003e\n\u003cli\u003efrom scipy.stats import pearsonr\u003c/li\u003e\n\u003cli\u003e优点: 速度快\u003c/li\u003e\n\u003cli\u003e缺点: 只对线性关系敏感\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e卡方验证\n\u003cul\u003e\n\u003cli\u003e类别型变量对类别型变量的相关性\u003c/li\u003e\n\u003cli\u003e最大信息系数 maximal information coefficient (MIC)\n\u003cul\u003e\n\u003cli\u003efrom minepy import MINE\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eWrapper(包装法)\n\u003cul\u003e\n\u003cli\u003e根据目标函数(往往是预测效果评分), 每次选择若干特征, 或者排除若干特征\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eEmbedded(嵌入法)\n\u003cul\u003e\n\u003cli\u003e先使用某些机器学习的模型进行训练, 得到各个特征的权值系数, 根据系数从大到小选择特征(类似于Filter, 只不过系数是通过训练得来的) word2vec\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e特征的降维\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"一些数据预处理的方法"},{"content":"1. 行为识别 Human Action Recognition (HAR) 行为识别模型有两个方向: 第三人称动作识别和第一人称动作识别.\n使用的各方向和对应的方法大致如下图, 本篇文章只介绍第三人称动作识别 RGB 模态.\n详细可以参考调研论文. [1]\n2. 第三人称动作识别 RGB 模态 第三人称动作识别 RGB 模态方面的研究很多, 因为二维的视频数据相对来说更容易获得.\n2.1. Two-stream CNN-based 双流指的是空间流和时间流, 其中空间流获得单帧图片的特征图, 时间流获得光流图 (水平分量, 垂直分量, 这里计算的是稠密的光流图, 逐像素都进行计算) 的特征图, 两者 Softmax 结果融合. [2]\n特点是分析的是单帧图片和相邻帧获得的光流. 没有考虑较远的时间间隔帧之间的关系, 并且光流的生成消耗大量的计算性能.\n改进 时间段网络 TSN [18], 一个输入视频被分为 $K$ 个片段, 并且从每个片段中随机选择 1 帧.\n残差双流架构 (Two-stream ResNets) [4] (允许时间流信息流向空间流)\n在卷积层后加时空线性编码 (temporal linear encoding TLE) 模块 [6]\n视频中连续帧之间的动作幅度往往很小, 所以扩大采样帧的范围, 就可以提高动作的识别几率. 于是本文将视频所有帧一起编码, 用来捕捉长时间范围的动作. TLE 的优势在于:\n将整个视频编码为 紧凑的特征表示, 可学习语义和具有区分性的特征空间. 可用于 2D, 3D CNN 网络 不会丢失信息 这里将特征图按照帧顺序堆叠, 对这些特征图进行聚合运算. (方法有三种: 逐元素求平均, 逐元素求最大值, 逐元素相乘. 其中逐元素相乘效果最好) 将获得的时间聚合矩阵 (temporal aggregated matrix) $X$ 输入编码器, 获得线性编码特征向量 $y$. 使用的编码器双线性编码器.\n双线性编码器计算的是两个特征图的外积, 用来获得特征对之间的相关性.\n双线性池化（Bilinear Pooling）详解、改进及应用\n公式: $y=W[X\\otimes {X}']$, $W$ 表示权重; $X,{X}'$ 时间和空间流特征图的时间聚合矩阵; $\\otimes$ 表示外积; 方括号表示通过连接列, 将矩阵变为向量. 这种方法比全连接池化参数量少并且效果好.\n双流 CNN 方法的优点是在数据较少的情况下, 光流直接作为输入传递给时间流, 这样动作的特征更容易学习. 所以在数据较少的情况下, 双流 CNN 比 3D CNN 效果更好. [3]\n光流图如何生成?\n光流式空间运动物体在观察成平面上像素运动的瞬时速度, 是利用图像序列中像素在时间域上的变化. [5]\n光流图的生成需要两个假设\n假设相邻帧之间光的亮度不变 假设领域光流相似 传统方法有 稀疏光流估计算法 (Lucas Kanade Method) 和 稠密光流估计算法 (Gunnar Farneback Method). [7] 传统稠密光流估计函数 cv2.calcOpticalFlowFarneback, 性能由于稀疏光流估计, 但是速度较慢, 50w ppi 视频 CPU 9.75 fps; CUDA 170.22 fps\n传统的光流估算方法介绍\n假设一个物体的亮度为 $I(x,y,t)$, 它移动到了 $dx$ 和 $dy$ 处, 此时亮度为 ${I}(x+dx,y+dy,t+dt)$. 假设两帧之间的亮度不变, 则\n$$\rI(x,y,t)={I}(x+dx,y+dy,t+dt) \\quad\\quad \\text{(1)}\r$$移动后亮度使用泰勒近似可以获得\n$$\r{I}(x+dx,y+dy,t+dt)\\approx {I}(x,y,t)+\\frac{\\partial I}{\\partial x} d x+\\frac{\\partial I}{\\partial y} d y+\\frac{\\partial I}{\\partial t} d t\\quad\\quad \\text{(2)}\r$$将公式 (1) 带入公式 (2)\n$$\rI(x, y, t)+\\frac{\\partial I}{\\partial x} d x+\\frac{\\partial I}{\\partial y} d y+\\frac{\\partial I}{\\partial t} d t \\approx I(x, y, t)\r$$取消相同项可以获得\n$$\r\\frac{\\partial I}{\\partial x} d x+\\frac{\\partial I}{\\partial y} d y+\\frac{\\partial I}{\\partial t} d t=0\r$$两边除以 $dt$ 就可以获得光流方程\n$$\r\\frac{\\partial I}{\\partial x} u+\\frac{\\partial I}{\\partial y} v+\\frac{\\partial I}{\\partial t} =0\r$$ 其中 $u=dx/dt,v=dy/dt$ $dI/dx$ 是沿横轴的图像梯度, $dI/dy$ 是沿纵轴的图像梯度, $dI/dt$ 是沿时间的图像梯度. 转换为矩阵形式\n$$\r\\left[I_x^{\\prime}, I_y^{\\prime}\\right]\\left[\\begin{array}{l}u \\\\v\\end{array}\\right]=-\\Delta I_t\\quad\\quad \\text{(3)}\r$$这里需要计算每个像素点的 $u,v$ 这两个向量 (光流的水平分量和垂直分量), 两帧之间的时间 $t$ 已知, 但是只有一个公式是无法算出两个未知量的.\n这里需要用到领域光流相似的假设. [7] 就是以某一点为中心, 设定的 (如 3x3) 领域内所有像素点光流值一致.\n$$\r\\left[\\begin{array}{c}\rI_x^{\\prime(1)}, I_y^{\\prime(1)} \\\\\rI_x^{\\prime(2)}, I_y^{\\prime(2)} \\\\\r\\cdots \\\\\rI_x^{\\prime(n)}, I_y^{\\prime(n)}\r\\end{array}\\right]\\left[\\begin{array}{c}\ru \\\\\rv\r\\end{array}\\right]=\\left[\\begin{array}{c}\r-\\Delta I_t^{(1)} \\\\\r-\\Delta I_t^{(2)} \\\\\r\\cdots \\\\\r-\\Delta I_t^{(n)}\r\\end{array}\\right]\r$$上面的公式是 $Ax=B$ 的形式, 可以求得光流 $x=(u,v)$ 的最小二乘解.\n$$\rx=\\left(A^T A\\right)^{-1} A^T b \\quad\\quad \\text{(4)}\r$$但是必须要求 $\\left(A^T A\\right)$ 可逆, 否则公式 (4) 会出现多个解, 即孔径问题 (Aperture problem), 如下图, 相邻帧从圆孔中观察条纹变化, 发现没有变化, 从而无法计算出光流方向.\n所以, 亮度变化明显的角点更容易被计算出光流.\n深度学习方法: FlowNet 性能低于传统方法; FlowNet2 [10] 性能追平传统方法, 并且速度很快\n稀疏光流估计算法做了两个假设: 1. 亮度不变, 假设前后两帧同一物体亮度不变; 2. 领域光流相似, 假设一个像素点周围的8个像素点的移动方向与该像素点一致.\n2.2. 3D CNN-based 将具有空间维度和时间维度的视频帧一起输入 3D CNN 网络中. 可以更好的获取到视频中的时间信息 [9]. 但是 3D CNN 的计算成本高于 2D CNN (不包括光流图的计算).\n优化方案 TSM [8a][8b] 提供了一种既高效, 性能又好的模块. 这个模块可以注入 Backbone, 后面可以接行为识别或者物体检测 (用于应对运动模糊, 遮挡, 失焦等问题), 这个论文用的是二维卷积, 但是达到了三维卷积的效果.\n网络\n网络末尾做了一个自适应池化nn.AdaptiveAvgPool2d(1), 将结果拉成了一维, 用nn.Linear(feature_dim, num_class))作为全连接层, 最后softmax分类. 视频帧采样, 使用 long-range temporal 采样策略. 就是将视频均分为 $n$ 等分. 每一份片段中随机采样 1 帧 (这个和 TSN 一样), 获得网络输入 $224*224*n$.\nTemporal Shift Module (TSM)\n本论文最重要的贡献就是 TSM. 通过网络结构图可知, 每张图片都经过 Conv-2D, 获得的是一组按时间排列的二维特征图, 问题是为什么 TSM 能够实现在 Conv-2D 上对时空双方进行建模呢?\nShift: 对于矩阵 tensor(TCHW) C=3, TSM 沿着时间 (temporal) 维度移动部分的通道 (比如bi-direction 进行了时间维度上的 shift +/- 1), 使得每个时间维度上的矩阵 tensor(CH*W) 能够获得相邻帧的特征 (一般通道只有三条, 所以一条后退 1 帧, 一条前进 1 帧, 一条不动), 在时间维度上感受到 3 (-1 0 +1)帧的范围.\nMultiply-accumulate(乘法累加): 假设有一维卷积, kernel size 为 3, 则 $W=(w_1,w_2,w_3)$, 卷积算子 $Y=Conv(W,X)$, 假设输入是一维向量 (单通道), 算子的输出可以被写为 $Y_i=w_1X_{i-1}+w_2X_i+w_3X_{i+1}$.\n举例来说, Shift 移动的 3 个位置 $X_i^{-1}=X_{i-1}, X_i^{0}=X_{i}, X_i^{+1}=X_{i+1}$ 分别乘以这三个权重, 乘法累加的总和为 (输出)\n$$\rY=w_1 X^{-1}+w_2 X^0+w_3 X^{+1}\r$$ 但是这样简单的位移策略效率和性能都不高.\n模块的优化方案\n使用残差位移, 在残差分支内融合时间维度信息.\n对于实时的视频来说, shift 就只能单向了, 因为后一帧是未知\n性能和效率\nTDN [17] 提出了一种时间差分网络 (Temporal Difference Networks), 利用时间差分算子来设计有效的时间模块 (TDM). 为了充分捕捉视频的信息, TDN 使用了两级差分建模.\n预处理 稀疏采样, 将视频分为 $n$ 个区域, 在每个区域中随机采样一帧. 密集采样, 采样稀疏采样帧的前后的连续两帧, 就是一共连续 5 帧的密集采样. 网络结构 短期时差模块 (S-TDM) 连续帧上的时间差异用于为 2D-CNN 提供更精细的运动模式. 因为只用单帧无法获得局部的运动信息. 在相邻帧之间作差, 并堆叠起来用单一尺度的卷积层计算特征, 并与中间的那一帧的特征做融合. 这样就可以获得短期运动信息. 这里对连续帧之间的差值, 做了平均池化+堆叠+卷积 (这么做是为了提升效率), 论文中说, RGB 差异在运动区域非常明显, 所以特征在低分辨率下也不会有太大损失. 但是, 这个模块获得的特征无法学习到长期的运动信息. 长期时差模块 (L-TDM) 用较大时间间隔的短期运动信息来获得长时间的运动特征. L-TDM 是双向的, 多尺度的注意力机制. 双向是指: 对相邻的局部运动特征 由于间隔时间较大, 相邻的片段之间的空间位置可能没有对齐. 通过相邻的片段来计算对齐的时间差\n$$\rC(F_i,F_{i+1})=F_i-Conv(F_{i+1})\r$$ $C(F_i,F_{i+1})$ 表示 $F_i$ 对齐的时间差, $Conv$ 是用于空间平滑的通道卷积. 使用三个尺度的特征信息相融合获取长时间间隔的运动特征. 2.3. RNN-based 使用 LSTM 或变种, 输入一般和双流一样, RGB帧 + 光流图, 如 [11], 网络结构如下\n也有不使用光流图的, 如[12], 但是性能上不如较新的有光流图的网络结构.\n总之由于使用了 RNN 网络, 使模型的效率降低, 所以 RNN-based HAR 论文中一般都不会去标出效率指标.\n2.4. Transformer-based 将 ViT (用于图片分类的 transformer 模块) 扩展到了视频, 将视频分解成一连串帧级别的块, 使用分割注意力机制, 在模型的每个块内分别应用空间和时间的注意力. [13]\nViViT [14] 从视频中提取时空特征, 通过变换层进行编码.\nMTV-H [15] 引入了由多个独立编码器组成的多视图转换器, 可有效融合来自不同表示形式的信息, 包括视频的时空特征信息. [15]\nRViT 进行了效率优化, 它的 FLOPs 与 TSM 和 TDN 是相同级别, 并且性能高于 TDN. 目前平衡性能和效率的最佳选择. [16]\nRViT 在变压器中采用递归机制来实现视频动作识别任务. 这个机制导致了性能, 效率的提升并且降低了显存使用量.\n参考 [1] https://arxiv.org/pdf/2301.06082.pdf\n[2] https://proceedings.neurips.cc/paper_files/paper/2014/file/00ec53c4682d36f5c4359f4ae7bd7ba1-Paper.pdf\n[3] https://www.rtcdeveloper.cn/cn/community/blog/26097\n[4] https://arxiv.org/pdf/1611.02155.pdf\n[5] https://blog.csdn.net/qq_33757398/article/details/106332814\n[6] https://arxiv.org/pdf/1611.06678.pdf\n[7] https://zhuanlan.zhihu.com/p/74460341\n[8a] https://openaccess.thecvf.com/content_ICCV_2019/papers/Lin_TSM_Temporal_Shift_Module_for_Efficient_Video_Understanding_ICCV_2019_paper.pdf\n[8b] https://arxiv.org/pdf/1811.08383v1.pdf\n[9] https://arxiv.org/pdf/1412.0767.pdf\n[10] https://arxiv.org/pdf/1612.01925.pdf\n[11] https://openaccess.thecvf.com/content_ICCV_2017/papers/Sun_Lattice_Long_Short-Term_ICCV_2017_paper.pdf\n[12] https://openaccess.thecvf.com/content_ICCVW_2019/papers/HVU/Meng_Interpretable_Spatio-Temporal_Attention_for_Video_Action_Recognition_ICCVW_2019_paper.pdf\n[13] https://arxiv.org/pdf/2102.05095.pdf\n[14] https://arxiv.org/pdf/2103.15691.pdf\n[15] https://arxiv.org/pdf/2201.04288.pdf\n[16] https://openaccess.thecvf.com/content/CVPR2022/papers/Yang_Recurring_the_Transformer_for_Video_Action_Recognition_CVPR_2022_paper.pdf\n[17] https://openaccess.thecvf.com/content/CVPR2021/papers/Wang_TDN_Temporal_Difference_Networks_for_Efficient_Action_Recognition_CVPR_2021_paper.pdf\n[18] https://arxiv.org/pdf/1608.00859.pdf\n","permalink":"https://sqf.icu/article/12845fe7-3d14-489c-9832-f1c9289bc47a/","summary":"\u003ch1 id=\"1-行为识别-human-action-recognition-har\"\u003e1. 行为识别 Human Action Recognition (HAR)\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e行为识别模型有两个方向: 第三人称动作识别和第一人称动作识别.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e使用的各方向和对应的方法大致如下图, 本篇文章只介绍第三人称动作识别 RGB 模态.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/40dc5af5e9c8678f9897385c.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e详细可以参考调研论文. \u003ca href=\"https://arxiv.org/pdf/2301.06082.pdf\"\u003e[1]\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"行为识别模型简介"},{"content":"1. CRNN算法介绍 CRNN 全称为 Convolutional Recurrent Neural Network\n主要用于端到端地对不定长的文本序列进行识别, 不用先对单个文字进行切割, 而是将文本识别转化为时序依赖的序列学习问题, 就是基于图像的序列识别. 对于无字典和有字典的场景都有较好的表现. (不过无字典精度差有字典10%以上) 模型结构简单, 性能比Transformer等模型更好. 2. 传统的文字识别模型 有些模型基于DCNN 缺点: 这些模型需要一个很强的词语检测模型. 需要将图片中的词语准确检测出来. 需要做一个大范围的分类(英文单词有90K个, 中文1百万) 3. 模型结构 CRNN网络包括3个部分:\nCNN(卷积层), 使用深度CNN, 对输入图像提取特征, 得到特征图; RNN(循环层), 使用双向RNN(Bi-LSTM)对特征序列进行预测, 对序列中的每个特征向量进行学习, 并输出预测标签(真实值)分布; CTC loss(转录层), 使用 CTC 损失, 把从循环层获取的一系列标签分布转换成最终的标签序列. 3.1. CNN 每个特征向量对应于原图中的一个矩形区域 (感受野), 矩形区域从左到右和特征向量的顺序是一一对应的.\n由于卷积, 池化, 激活层都在局部区域运行, 所以通过卷积块之后特征图的每一列还是对应原始图像的那个矩形区域. 由于是要转换为序列, 所以原图的宽度可以不固定(短于设定的宽度大小即可), 但是原图的高度必须固定. 转换为序列的时候, 对应的特征向量序列被切割为宽度固定的单个像素. 3.2. RNN (Bi-LSTM) 通过RNN来使特征向量序列转为概率序列. 传统RNN层有梯度消失的问题, 所以使用LSTM来解决这个问题. Bi-LSTM可以双向遍历序列并存储上下文信息. 3.3. Transcription 转录 RNN对每个特征向量所做的预测转录为标签序列, 即根据RNN做出的每帧预测找到最高概率组合的标签序列.\n3.3.1. CTC (Connectionist Temporal Classification) 训练阶段 CTC 用于对齐预测的字母, 也就是多对一将字母对齐. 对齐后, 一个字母对应一个置信度, 用于后面的转录.\n英文字母有26个, 空白部分用减号表示, 所以最终要识别的字符合集是27个字符\n生成 $\\beta$ maps\n预测的过程中可能有很多种情况(因为同一列中识别出来的结果对应的字母概率不同), 这里的 $\\pi_i$ 是任意序列.\n对于多种情况使用 $\\beta$ maps 进行多对一映射.\n从RNN网络获取标签序列步骤如下:\n如果第二步的公式计算标签序列的概率的话, 就是暴力计算每一条路径, 时间复杂度为 $O(n^T)$. 需要使用向前-向后算法 (forward-backward algorithm) 来降低时间复杂度.\n向前向后算法是动态规划算法, 时间复杂度为 $O(nT)$.\n在实际源码中, 前向后向算法被应用在Pytorch.nn.CTCLoss()函数中, CTCLoss作为训练模型的损失函数.\n具体过程看以下链接中的 2.3 前向-后向算法\n4.OCR文本识别Connectionist Temporal Classification(CTC)算法-CSDN博客\n具体可以看源码解析\nPytorch中CTC Loss源码解析 - 海滨的Blog\n前向-后向算法解析视频\n机器学习-白板推导系列(十四)-隐马尔可夫模型HMM（Hidden Markov Model）_哔哩哔哩_bilibili\n机器学习-白板推导系列(十四)-隐马尔可夫模型HMM（Hidden Markov Model）笔记\n3.3.2. 无字典转录 (Lexicon-free transcription) 推理阶段 假设时间步为 $T$, 字符总数为 $N$.\n贪心搜索 (Greedy search) ← 本篇论文使用\n时间复杂度为 $O(N*T)$\n方法\n每次都直接在序列中找预测结果概率最大的字母. 拿翻译问题的图举例(把汉字”我恨你”换成时间步”1,2,3”即可):\n束搜索 (Beam-search) ← 可以不使用CTC就进行转录, 但是时间复杂度高, 本篇论文没有使用\nBeam-search 算法是以较少的代价在相对受限的搜索空间中找出近似最优解.\n它的搜索空间比贪心搜索更大, 但速度更慢.\n需要先设定一个超参数 $k$: 束宽 (beam size).\n时间复杂度为 $O(N*T*k)$.\n方法\n时间步1: 选择 $k$ 个概率最高的字符.\n时间步2: 从前面的 $k$ 个字符中分别会分裂出27个候选字符, 只抽取条件概率 (就是时间步1中选出的字符出现并且时间步2候选字符出现的概率(概率相乘)) 最高的 $k$ 个字符作为候选.\n以此类推, 下图假设预测分类中只有3个字符(2个字母和1个空白符).\n但是, 由于需要结合多个对齐能够映射到同一输出字符的这种情况, 需要把重复字符和空格符也考虑进来.\n最后一个时间步, 找到最大的候选序列条件概率就行了.\n3.3.3. 基于字典转录 (Lexicon-based transcription) 推理阶段 BK树: 被设计于快速查找近似字符串匹配 ← 本篇论文使用\nBK树查找的时间复杂度: $O(logn)$\n$n$ 是字典中的单词数量 Python代码可以参考:\n快速匹配字符串算法BK树 原理及python实现_bk树 python代码-CSDN博客\n建立一个字典, 保存所有单词 (比如所有英语单词)\n使用 Levenshtein 距离 (编辑距离) 计算任意一个根单词与字典中所有单词的距离, 建立BK树\nLevenshtein 距离表示通过对一个字符串只进行插入, 删除, 替换这3个操作, 从而使其与另一个字符串相等所需的最小编辑操作次数.\n例如, 从FAME到GATE需要两步 (两次替换), 从GAME到ACM则需要三步 (删除G和E再添加C) 编辑距离计算是一个动态规划问题. 建立BK树\n建树逻辑\nBK树中的每个节点都只有一个具有相同编辑距离的子节点. 如果我们在插入时遇到编辑距离的某些冲突, 我们将向冲突的叶子节点传播插入过程, 直到找到字符串节点的适当父节点.\nBK树详解-CSDN博客\n定理 $\\alpha$: d(x,y) + d(y,z) \u0026gt;= d(x,z). 三角不等式 (Triangle Inequality). 三角不等式表明 x 到 z 的路径不可能长于另一个中间点的任何路径 (从 x 到 y 再到 z). 看下三角形, 你不可能从一点到另外一点的两侧再画出一条比它更短的边来.\nd(query, root): 要查找的词和根节点的编辑距离 d(query, fit_word): 要查找的词和BK树上的所有词, 但是 n 是自己设定的, 编辑距离需要小于n. d(root, fit_word): 根据定理 $\\alpha$, 根节点与字典词的编辑距离一定是 d-n 到 d+n 之间. 记录这个距离为子节点编号. 查询步骤:\n计算待查词与根节点的编辑距离 d. 递归查找每个子节点编号为 d-n 到 d+n 的边. 如果找到编号符合的子节点, 就返回该节点, 并继续查找. PS: BK树是多路查找树, 并且是不规则的 (但通常是平衡的). 试验表明, 一个查询的搜索距离不会超过树的 5-8%, 两个错误查询的搜索距离不会超过树的 17-25%, 这样可以大幅增加查找性能. 如果要进行精确查找, 也可以非常有效地通过简单地将 n 设置为 0 进行.\n图片出处:\n超酷算法（1）：BK树 （及个人理解）-CSDN博客\n本论文测试了不同的BK树参数n对查找性能和精度的影响.\n3.4. 优化器 本论文源码有 3 个选项, Adam, Adadelta, RMSprop.\n4. 实现 网络配置已在具体结构总结图中给出。卷积层的架构是基于VGG-VeryDeep的，但是为了使其适用于识别英文文本，进行了调整，在第3、4个最大池化层中，采用1*2大小的矩形池化窗口，而不是传统的正方形，这样能够产生宽度较大的特征图，而拥有更长的特征序列。同时，矩形池化窗口产生的矩形感受野也有助于识别一些具有狭长形状的字母，例如‘i’和‘l’。（实际上论文作者给出的代码并不是这样实现的，而是k=(2,2),s=(2,1),p=(1,0)，作者的解释是” It’s a typo in the paper :) Should be “1 x 2 stride sizes”.”crnn issue #6）\n在第5、6个卷积层之后插入两个批归一化层，能够加快训练的速度。\n网络使用ADADELTA训练，参数ρ�设置为0.9。训练期间，所有图像都被缩放为100*32，以加快训练过程，需要大约50小时才能达到收敛。测试图像的高度缩放为32，宽度与高度成比例缩放，但至少为100像素。\nCRNN论文的阅读与学习\n5. ABINet 简单介绍一个带Transformer模块的模型.\nRead Like Humans: Autonomous, Bidirectional and Iterative Language Modeling for Scene Text Recognition\nABINet是一个基于自治的, 双向的, 迭代语言模型的文本识别模型.\n5.1. 传统文本识别模型的缺点 implicitly language modeling: 模型表达的含义很难被利用到 unidirectional feature representation: 如何表达上下文特征 language model with noise input: 真实世界中的文本可能存在缺失(如反光, 磨损导致看不到单词中的部分字母) 5.2. 模型 图片模型部分: 图3是详细的Vison Model结构, backbone是ResNet+Transformer提取特征,\nPosition Attention 关注的是切割后图的位置编码, 预测的是提取的特征应该融入第几个字母. (因为纵向切割可能将一个字母切成多份图, 构成序列)\nVision Prediction: 每个字母都是单条特征融合后和矩阵. (例如: 图片高度20, 第一个字母被纵向切割成10份, 那么融合后的矩阵应该是 20x10 的矩阵), 由字母平成一个单词.\n图片模型部分结构图\n语言模型部分: 使用 Multi-head Attention 模块计算注意力机制对单词中字母的权重重新分配\n如果单词权重出现变化, 重复 Text 模块. 反复矫正, 从而使单词更加正确.\n语言模型部分结构图\nAttention masks: 在对角线上加上mask, 对单词做完形填空. 意图就是用两边的字母(上下文)来预测中间的字母. 这个预测来对抗图片中的噪音. 融合模型部分:\nG 是一个可学习的权重值, 在 $F_f$ 中做加权用. 图片模块和文字模块输出的矩阵相加. ","permalink":"https://sqf.icu/article/7fa71d66-d62e-423a-8b3f-e648f3c83677/","summary":"\u003ch1 id=\"1-crnn算法介绍\"\u003e1. CRNN算法介绍\u003c/h1\u003e\n\u003cp\u003eCRNN 全称为 \u003cstrong\u003eConvolutional Recurrent Neural Network\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e主要用于端到端地对不定长的文本序列进行识别, 不用先对单个文字进行切割, 而是将文本识别转化为时序依赖的序列学习问题, 就是基于图像的序列识别.\u003c/li\u003e\n\u003cli\u003e对于无字典和有字典的场景都有较好的表现. (不过无字典精度差有字典10%以上)\u003c/li\u003e\n\u003cli\u003e模型结构简单, 性能比Transformer等模型更好.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"2-传统的文字识别模型\"\u003e2. 传统的文字识别模型\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e有些模型基于DCNN\n\u003cul\u003e\n\u003cli\u003e缺点:\n\u003cul\u003e\n\u003cli\u003e这些模型需要一个很强的词语检测模型. 需要将图片中的词语准确检测出来.\u003c/li\u003e\n\u003cli\u003e需要做一个大范围的分类(英文单词有90K个, 中文1百万)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"3-模型结构\"\u003e3. 模型结构\u003c/h1\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/f6bfe4dbe62c47ec0cb26ccc.png\"\u003e\u003c/p\u003e","title":"OCR文本识别和CRNN算法简介"},{"content":"Enzo_Mi的个人空间-Enzo_Mi个人主页-哔哩哔哩视频\n1. 双线性插值 双线性插值, 将目标尺寸图像的每个像素点映射回原图, 各像素点的值由它周围4个原图像素点进行线性插值获得.\n1.1. 角对齐和边对齐区别 角对齐使用像素的中心点进行对齐(分割左右距离最远的中心点). 边对齐使用像素的边缘进行对齐(分割左右距离最远像素边缘). 下图(红点是原像素中心点, $(0,0)$ 点是左上角第一个红点; 蓝点是目标对齐点):\nimport torch image_array = [[1,2,3],[4,5,6],[7,8,9]] image = torch.as_tensor(image_array, dtype=torch.float32).unsqueeze(0).unsqueeze(0) # 角对齐 result_c = torch.nn.functional.interpolate(image, size=(5,5), mode=\u0026#39;bilinear\u0026#39;, align_corners=True) print(result_c) # 边对齐 result_e = torch.nn.functional.interpolate(image, size=(5,5), mode=\u0026#39;bilinear\u0026#39;, align_corners=False) print(result_e) #################### tensor([[[[1.0000, 1.5000, 2.0000, 2.5000, 3.0000], [2.5000, 3.0000, 3.5000, 4.0000, 4.5000], [4.0000, 4.5000, 5.0000, 5.5000, 6.0000], [5.5000, 6.0000, 6.5000, 7.0000, 7.5000], [7.0000, 7.5000, 8.0000, 8.5000, 9.0000]]]]) tensor([[[[1.0000, 1.4000, 2.0000, 2.6000, 3.0000], [2.2000, 2.6000, 3.2000, 3.8000, 4.2000], [4.0000, 4.4000, 5.0000, 5.6000, 6.0000], [5.8000, 6.2000, 6.8000, 7.4000, 7.8000], [7.0000, 7.4000, 8.0000, 8.6000, 9.0000]]]]) 代码结果可以看出, 角对齐插值后, 像素值横纵方向上是线性的; 边对齐插值后, 边缘一圈在横纵方向上的像素值是非线性.\n所以, 对于目标检测这种少有物体出现在图像边缘的情况, 用两种对齐都行; 而对于图像分割, 边角的像素也会加入mIoU计算(也就是影响精度), 所以用角对齐更好.\n另外, OpenCV和PIL插值使用的都是边对齐. MXNet, PyTorch, TensorFlow两种方法都可选.\n1.2. 双线性插值计算过程 将目标图像大小缩放到原图像的尺寸, 这时候目标图像上的每一个像素都变成了在原图上的亚像 素点. 对这个亚像素点进行插值获得像素值. 进行两次横向的线性插值. 进行一次纵向的线性插值. 2. 双三次插值 双三次插值, 将目标尺寸图像的每个像素点映射回原图, 各像素点的值由它周围16个原图像素点(以目标像素点为中心)进行线性插值获得.\n2.1. 权重公式 $$\rW(x)= \\begin{cases}(a+2)|x|^3-(a+3)|x|^2+1 \u0026 \\text { for }|x| \\leq 1 \\\\ a|x|^3-5 a|x|^2+8 a|x|-4 a \u0026 \\text { for } 1 \\leq|x| \\leq 2 \\\\ 0 \\quad \\text { others } \u0026 \\end{cases}\r$$ $x$: 目标像素点与某个邻近像素点的距离 $a$: 平滑度, 默认取-0.5 (PyTorch默认使用-0.75) 2.2. 计算过程 将目标尺寸图像的每个像素点映射回原图, 各像素点的值由它周围16个原图像素点进行线性插值获得.\n假设某个像素点为$(x_n, y_n)$, 分别计算对应着16个原图像素点的 $x$ 轴方向和 $y$ 轴方向的距离, 带入权重公式.\n这样的话, 可以分开计算x轴和y轴方向的权重. 因为x轴方向权重每一列都是一样的; y轴方向权重每一行都是一样的(距离相同). 求得结果之后, 求和就可以获得结果 实际操作的时候, 全图基础上需要在周围加两圈 padding 用来解决边缘像素的问题, PyTroch 可以使用replicate参数, 复制边缘像素来填充边缘.\n3. 最邻近插值 3.1. 缩放过程 将目标尺寸的像素点映射到原图 目标像素点距离原图哪个像素点最近, 就使用哪个像素点的值. 具体细节\n遍历输出像素点, 将这些像素点缩放之后, 四舍五入到整数值, 这个整数的坐标对应原图的像素值就是目标像素值. 如果遍历的时候发现像素点越界, 就使用边缘像素的像素值 缺点 有锯齿, 效果不如双线性插值 优点 对于分割任务. 如果要对标注图像进行缩放的时候, 用最邻近插值可以防止出现额外的像素值\n","permalink":"https://sqf.icu/article/cae870f7-833a-4935-a3e5-cd004779088a/","summary":"\u003cp\u003e\u003ca href=\"https://space.bilibili.com/94779326/search/video?keyword=%E7%BA%BF%E6%80%A7%E6%8F%92%E5%80%BC\"\u003eEnzo_Mi的个人空间-Enzo_Mi个人主页-哔哩哔哩视频\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"1-双线性插值\"\u003e1. 双线性插值\u003c/h1\u003e\n\u003cp\u003e双线性插值, 将目标尺寸图像的每个像素点映射回原图, 各像素点的值由它周围4个原图像素点进行线性插值获得.\u003c/p\u003e\n\u003ch2 id=\"11-角对齐和边对齐区别\"\u003e1.1. 角对齐和边对齐区别\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e角对齐使用像素的中心点进行对齐(分割左右距离最远的中心点).\u003c/li\u003e\n\u003cli\u003e边对齐使用像素的边缘进行对齐(分割左右距离最远像素边缘).\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e下图(红点是原像素中心点, $(0,0)$ 点是左上角第一个红点; 蓝点是目标对齐点):\u003c/p\u003e","title":"插值算法介绍"},{"content":"1. 文本检测难点 文本的多样性: 颜色, 大小, 字体, 形状, 方向, 语言, 文本长度… 复杂的背景干扰: 图像失真, 模糊, 低分辨率, 阴影, 亮度… 密集文本或重叠文本 文字存在局部一致性: 文本行的一部分也可以是为独立的文本 2. 场景文本检测方法分类 基于回归的方法(regression-based methods) 基于回归的方法是一系列直接回归文本实例的边界框的模型. 论文 TextBoxes (Liao et al. 2017) 基于 SSD (Liu et al. 2016) 修改了锚点和卷积核的尺度来进行文本检测。 TextBoxes++（Liao, Shi, and Bai 2018）和 DMPNet（Liu and Jin 2017）应用四边形回归来检测多方向文本。 SSTD（He et al. 2017a）提出了一种注意力机制来粗略地识别文本区域。 RRD（Liao et al. 2018）通过使用旋转不变特征进行分类和使用旋转敏感特征进行回归来解耦分类和回归，以更好地处理多向和长文本实例。 EAST（Zhou et al. 2017）和 DeepReg（He et al. 2017b）是无锚方法, 它们对多方向文本实例应用像素级回归。 SegLink（Shi, Bai, and Belongie 2017）对片段边界框进行回归并预测它们的链接，以处理长文本实例。 DeRPN（Xie et al. 2019b）提出了一种维度分解区域提议网络来处理场景文本检测中的尺度问题。基于回归的方法通常采用简单的后处理算法（例如非极大值抑制）. 论文中的大多数在表示不规则图形（如曲线图形）的精确边界框时都受到了限制. 基于分割的方法(segmentation-based methods) 通常结合像素级预测和后处理算法来获取边界框. 论文 (Zhang et al. 2016) 通过语义分割和基于 MSER 的算法检测多向文本. (Xue, Lu, and Zhan 2018) 使用文本边框来分割文本实例. Mask TextSpotter (Lyu et al. 2018a; Liao et al. 2019) 基于 Mask R-CNN 以实例分割方式检测任意形状的文本实例. PSENet（Wang et al. 2019a）提出了通过使用不同尺度内核分割文本实例来进行渐进尺度扩展. (Tian et al. 2019) 中提出了像素嵌入, 以对分割结果中的像素进行聚类. PSENet (Wang et al. 2019a) 和 SAE (Tian et al. 2019) 针对分割结果提出了新的后处理算法, 导致推理速度较低. 基于分割的方法有一些通病: 消耗性能更高(DBNet做到了优化), 一些文本在另一次文本中间的时候, 几乎所有分割方法都是无法区分的. 快速场景文本检测方法(Fast scene text detection methods) 注重准确性和推理速度. TextBoxes (Liao et al. 2017)、TextBoxes++ (Liao, Shi, and Bai 2018)、SegLink (Shi, Bai, and Belongie 2017) 和 RRD (Liao et al. 2018) 通过使用SSD（Liu et al. 2016）检测架构实现了快速文本检测. EAST（Zhou et al. 2017）提出应用PVANet（Kim et al. 2016）来提高其速度。它们中的大多数不能处理不规则形状的文本实例，例如弯曲形状. 与之前的快速场景文本检测器相比，DBNet方法不仅运行速度更快，而且可以检测任意形状的文本实例. DBNet 是一种基于分割的方法, 分割的方法通常需要进行二值化, 而二值化是不可微分的. 不可微分就意味着不可以在网络中联合训练. DBNet 使用 DB (Differentiable Binarization) module. 这个方法替代标准的二值化函数, 可以自适应的学习每个像素点的二值化阈值. 使得二值化也加入网络一起训练, 来简化后处理的过程和提升模型推理性能. 3. DBNet模型 3.1. Backbone 骨干网络 模型的骨干网络使用FPN(CVPR2017), 也可以使用ResNet.\nFPN (Feature Pyramid Network): 在目标检测中融入了特征金字塔, 提高了目标检测的准确率, 尤其体现在小物体的检测上. 特征金字塔特性:\n高层 (顶部 远离原图) 特征包含丰富的语义信息, 但是由于分辨率低, 很难保存准确的物体位置信息. 低层 (底部 接近原图) 特征语义信息少, 但是由于分辨率高, 能够保存准确的物体位置信息. 动机:\n由于特征金字塔的特性, 将低层和高层特征融合, 就能得到一个识别和定位都准确的目标检测系统. 之前的多尺度融合方法一般都是将特征融合之后再做预测, 而FPN对不同的特征层都单独做了预测, 从而提高了准确率和性能. 结构:\n目标检测算法中的常见结构介绍\n获取特征的时候, 不同的卷积核(Kernel)获得的特征图(Feature Map)都不一样.\n不同的卷积核的合集叫过滤器(Filter).\nDBNet中的FPN网络中加入了可变形卷积(Deformable convolution)\nDeformable Convolution 关于可变形卷积\n原始feature map上的每个像素点学习的不是自身的偏移, 而是以自身为中心, 周围k*k大小所有点的偏移. 这样加完 offset 再卷积的时候, 卷积核的中心滑动到某点时, 并不是和这个点周围的9个点进行卷积, 而是和这个点的18个通道对应的9个offset算出来的值进行卷积.\n可以为模型提供灵活的感受野, 有利于长文本检测\n可变形卷积被应用于ResNet-18和ResNet-50\n可变形卷积的优势?\n传统卷积的限制: 卷积核形状和位置固定, 所以在卷积过程中, 每个卷积核的每个位置上采样的是相同的输入数据, 而无法适应不同尺度或形变的结构. 可变形卷积: 在卷积过程中, 可以动态调整形状和位置. 可变形卷积详细介绍\n一些常见深度学习的网络结构介绍 - 1.5. 可变形卷积\n3.2. Binarization Module 二值化模块 将1/4大小的特征图分别经过一系列的卷积和转置卷积获得概率图(Probability map, 分割图) P和阈值图(Threshold map) T, 目的是生成和原图一样大小的特征图 P 和 T.\n概率图(Probability map, 分割图) P的获取方法\n尽量完全在gt文字框内部 对于特征获得的分割结果做了腐蚀操作? 腐蚀后文本区域每个像素都为1, 外部区域都为0 阈值图(Threshold map) T的获取方法\n让模型理解文字的边缘\n对于特征获得的分割结果各做了腐蚀和膨胀操作, 缩小和增大的距离相同\n分割边缘阈值越大, 向周围扩散时阈值变小范围在 $(0, 1)$ 之间, 但取不到0和1.\n所以, 之后P-T的时候内部的文字部分一定大于0, 外部区域一定小于0\n之后的后处理会将结果再次扩大回原来的大小. 阈值图只在训练的时候有用.\n这么做的好处\n传统的二值化模块不能随着分割网络的训练进行更新, BD二值化模块可以. 类似于腐蚀膨胀操作, 可以防止两个单词被框到一起. 3.3. Post-processing 后处理 使用DB模块将 P 和 T 合并为近似二值图, 后处理获得文本的检测框\n传统管线 (Standard binarization): 图片进行分割获得 segmentation map → 设定固定的阈值获得 binarization map → 得到结果\n普通二值化方法公式:\n$$\rB_{i, j}= \\begin{cases}1 \u0026 \\text { if } P_{i, j}\u003e=t \\\\ 0 \u0026 \\text { otherwise }\\end{cases}\r$$ BD module (Differentiable binarization): 使用threshold map获得在每个像素点上自适应的阈值\nDB公式:\n$$\r\\hat{B}_{i, j}=\\cfrac{1}{1+e^{-k\\left(P_{i, j}-T_{i, j}\\right)}}\r$$k: 放大系数; P: 概率图; T: 阈值图\n图中, 橙色线是标准二值化方法; 蓝色线是DB函数. 可以看到DB函数和标准的二值化方法达到的效果是相似的. DB模块还可以改善网络性能, 可以从反向传播梯度的角度来解释. 令 $P_{i,j}-T_{i,j}=x$:\n$$\rf(x)=\\cfrac{1}{1+e^{-kx}}\r$$ 使用二元交叉熵来作为loss的情况下, 对于正样本的loss: $l_{+}$ 计算和负样本的loss: $l_{-}$ 计算可以表示成下两式:\n$$\rl_{+}=-\\log \\cfrac{1}{1+e^{-kx}}\r$$$$\rl_{-}=-\\log \\left(1-\\cfrac{1}{1+e^{-kx}}\\right)\r$$ 负号是为了让结果为正(log的真数为 $(0,1)$ 之间时, 结果为负), 看着方便. **loss对于 $x$ 求偏导\n$$\r\\cfrac{\\partial l_{+}}{\\partial x}=-kf(x) e^{-kx}\r$$$$\r\\cfrac{\\partial l_{-}}{\\partial x}=kf(x)\r$$ 上述两函数如下图中的 (b) 和 (c) 图所示, (b) 图表示 $\\frac{\\partial l_{+}}{\\partial x}$, (c) 图表示 $\\frac{\\partial l_{-}}{\\partial x}$. 从微分公式可以看出:\n$k$ 是梯度的增益因子 梯度因子对于错误预测的增益幅度很大, 可以看到正样本当 $x\u003c0$ 的时候和负样本 $x\u003e0$ 的时候, $k=50$ 的绝对值是很大的(正负只影响梯度的方向), 说明 $k=50$ 相对于 $k=1$ , 更加放大了错误时的梯度(梯度变大, 神经元的权重参数的更新幅度变大), 有利于模型的学习. 3.4. 损失函数 DBNet论文中的Loss是三个loss的加权平均.\n$$\rL=L_s+\\alpha \\times L_b+\\beta \\times L_t\r$$$L_s$是概率图的loss; $L_b$是二值图的loss; $L_t$是阈值图的loss.\n其中$L_s$和$L_b$是带OHEM的BCE loss; $L_t$是$L_1$ loss.\n$$\rL_s=L_b=\\sum_{i \\in S_l} y_i \\log x_i+\\left(1-y_i\\right) \\log \\left(1-x_i\\right)\r$$ PaddleOCR中$L_b$使用Dice Loss; $L_s$使用带OHEM (arxiv PDF: Online Hard Example Mining) 的Dice loss; $L_t$是$L_1$ loss.\nDice Loss 是比较预测结果跟标签之间的相似度, 常用于二值图像分割.\n$$\r\u003e \\text{dice\\_loss} = 1-\\cfrac{2 \\times \\text { intersection\\_area }}{\\text { total\\_area }}\r\u003e $$MaskL1 Loss 是计算预测值和标签间的 $L_1$ 距离.\nBalance Loss 是带OHEM的Dice Loss, 目的是为了改善正负样本不均衡的问题. OHEM 为一种特殊的自动采样方式, 可以自动的选择难样本进行Loss的计算, 从而提升模型的训练效果.\n$L_1$和$L_2$距离\n其中I1和I2是p维向量.\n带OHEM的loss计算\n对于每个训练迭代, 模型在所有样本上进行前向传播, 计算loss. 根据每个样本的loss值, 选择一部分损失最大的样本作为困难样本. 仅使用这些困难样本的loss来计算总损失. 执行反向传播和参数更新, 以改善模型性能. 3.5. 推理加速 在推理的阶段, 使用概率图或近似二值图都可以获得文本检测框(text bounding boxes). 所以可以直接使用概率图. 检测框形成步骤: 使用常数阈值对概率图进行二值化\n从二值图获得连通区域(缩小文本区域)\n收缩区域通过Vatti裁剪算法以一个偏移量进行膨胀\nVatti裁剪算法\n$$\rD=\\cfrac{A\\left(1-r^2\\right)}{L}\r$$$A$ 是原始多边形的面积; $L$ 是原始多边形周长; $r$ 默认 0.4.\n4. DBNet++ DBNet++在DBNet的基础上增加了ASF(Adaptive Scale Fusion 自适应尺度融合)模块. 不同尺度的特征通过ASF模块处理, 可以得到更佳的融合不同尺度的特征图.\nDBNet++模型图\nASF模块通过引入空间attention机制, 使得融合后的特征更加鲁棒.\n其中N表示要融合的特征数, 这里N=4, 表示从4个不同的分支引出的特征.\n对比DBNet模型图\n","permalink":"https://sqf.icu/article/9e37c57e-1c45-4565-b1e0-37fb713a229d/","summary":"\u003ch1 id=\"1-文本检测难点\"\u003e1. 文本检测难点\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e文本的多样性: 颜色, 大小, 字体, 形状, 方向, 语言, 文本长度…\u003c/li\u003e\n\u003cli\u003e复杂的背景干扰: 图像失真, 模糊, 低分辨率, 阴影, 亮度…\u003c/li\u003e\n\u003cli\u003e密集文本或重叠文本\u003c/li\u003e\n\u003cli\u003e文字存在局部一致性: 文本行的一部分也可以是为独立的文本\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"2-场景文本检测方法分类\"\u003e2. 场景文本检测方法分类\u003c/h1\u003e\n\u003cp\u003e\u003cimg alt=\"IMG_1143.jpg\" loading=\"lazy\" src=\"/media/22116e85557edc91c9264b31.jpg\"\u003e\u003c/p\u003e","title":"OCR文本检测和DBNet"},{"content":"1. 原始CNN 卷积结构的网络大致由 3 各网络层组成: 卷积层, 池化层和全连接层.\n1.1. 卷积层 Convolution layer 使用不同的卷积核依次进行卷积提取特征\n卷积操作涉及的参数如下:\n滑动窗口步长: 步长不同会导致特征图尺寸不同\n步长越小, 计算效率越低 卷积核尺寸\n边缘填充\n有些卷积核按照特定步长会导致漏掉一些原图的像素, 所以需要再边界补 $0$. $0$ 不会对卷积计算产生影响. 卷积核个数\n卷积核的个数决定了特征图的厚度 (第三个维度) 卷积的尺寸计算, 卷积有两种方式: VALID 和 SAME. VALID 不进行补 $0$, 会漏掉一些原图的参数, SAME 补 $0$, 多加一圈 $0$ 来补齐. 下面的公式是 SAME, 去掉 $2P$ 就是 VALID.\n长度:\n$$\rH_2=\\frac{H_1-F_H+2 P}{S}+1\r$$ 宽度:\n$$\rW_2=\\frac{W_1-F_W+2 P}{S}+1\r$$ $W_1,H_1$ 表示 input 的宽度和长度\n$W_2,H_2$ 表示输入特征图的宽度和长度\n$F$ 表示卷积核长和宽的大小\n$S$ 表示滑动窗口的步长\n$P$ 表示边界填充 (padding) 厚度\n卷积参数共享:\n如果图像是 $32*32*3$ 的图像, 卷积核有 $10$ 个, 尺寸都为 $5*5*3$ (就是对 RGB 三通道都做卷积). 这样的话, 每个卷积核需要 $5*5*3=75$ 个参数, 加上每个卷积核都有一个对应的偏置参数 $b$, 总共需要 $(75+1)*10$ 个参数. 所以卷积网络参数远少于全连接神经网络参数. 使用多个不同尺寸的卷积核之后全连接如何处理? (NLP 处理句子或 CV 处理图片时被使用到)\n使用多个不同尺寸的卷积核卷积后的全连接处理_多个卷积核_空字符（公众号：月来客栈）的博客-CSDN博客\n1.2. 池化层 Pooling layer 池化层的作用: 用于压缩 (下采样 Down sampling), 因为图片中并不是所有信息都有用.\n池化层没有用到矩阵的运算, 单纯的是一个筛选.\nMax pooling\n设置一个过滤器 (如 2*2), 取这个过滤器覆盖的数中最大的数\n为什么使用 Max pooling?\n因为神经网络中, 大的值往往更重要, 所以只提取大的值就是只采样重要的值.\nAverage pooling\n取过滤器中所有数的平均值\n但是在实际使用中, 基本上 Max pooling 的表现都优于 Average pooling. 池化计算\n如果池化层的卷积核设置为 $n$, 则输入的长宽都除以 $2$. 1.3. 全连接层 Fully Connected Layer 收尾的全连接层是无法对 $3$ 维特征作分类, 所以需要将结果展开成 $1$ 维.\n1.4. 一些多层网络上的知识 注意! 带参数计算的网络层才能被称为一层. 由于 RELU (激活函数) 和 POOL 层都没有数学计算, 所以不被计算在层数中. 所以上面的多层网络中, 只有 CONV 和 FC 层被计算层数. 这是一个七层网络.\n1.5. 一些经典的卷积网络 传统卷积网络结构大多为下图所示, 不断增加卷积提取更高层的特征.\nAlexNet (2012) 8层\n存在很大的问题 开始使用 $11*11$ 的卷积核, 但尺寸太大影响性能 引入了局部标准化层, 但是作用不明显 Vgg (2014) 16层\n所有卷积尺寸全部使用 $3*3$ 随着深度的加深, 增加卷积核获得更多的特征值个数, 来弥补损失的信息 但是由于网络参数变多, 性能变得更差 并且在网络深度超过 20 层后, 效果无法变得更好. ResNet(2015) 常见层数: 18, 50, 101\nresnet 起到了一个类似于跳接的功能 如果 x 输入并经过卷积层之后, 将输出和输入结果相加. 如果发现 loss 上升, 就设置输出结果为 0, 这样就等于 x 直接通过. YOLOv1(2015), YOLOv2(2016)\n2. Featurized image pyramid 从图像金字塔提取特征 将图片 resize 成不同尺寸 对每个图片提取不同尺度的特征 对每个不同尺度的特征都进行单独预测 优点: 能够获得不同尺度下特征的语义信息 缺点: 性能消耗很大 3. Pyramid feature hierarchy 特征金字塔 3.1. SSD (Single Shot MultiBox Detector) 算法 2015 解读SSD中的Default box（Prior Box） - stardsd - 博客园\nSSD (ECCD 2016) 性能远超 Faster RCNN (相同 mAP 下, 性能 7 倍)\nAP是什么?\n【精选】深度学习中的AP和mAP总结_balabalayou的博客-CSDN博客\n必要概念: IoU, 精度 (预测为 1 判断正确 / 所有预测为 1 (Positive) 的数量) 和召回 (预测为 1 判断正确 / 所有判断正确 (True) 的数量)\n预测 GT 判断 TP 1 1 正确 FP 1 0 错误 FN 0 1 错误 TN 0 0 正确 根据模型推理可得检测框和置信度, 计算它们和标注框的IoU\n使用 IoU 和事先设置的阈值对比, 获得检测框是预测正确还是预测错误 (TP or FP).\n按照检测框的置信度从大到小排列, 从第一行开始计算 Precision (累积 TP / 累积预测框数) 和 Recall (累积 TP / 总 GT 框数).\n画出 PR 图\n所有点插值法 (interpolation performed in all points), 从右向左画平行线获得多个长方体, 计算面积和就是 AP\n其实就是召回对精度的积分\n$$\r\\mathrm{AP}=\\int_0^1 p(r) d r\r$$ 实际代码中的计算可以先从上向下, 从左向右找峰值点 (最高的点), 到最后一个点停止. 之后计算 每个峰值点到前一个峰值点的距离 ($\\Delta R$) * 峰值点的高度 ($P$), 最后求和就是 $AP$. mAP是什么?\nAP的平均值(mAP, mean average presicion): 在信息检索中, AP指的是不同召回率上的正确率的平均值, 而现在的有些检索系统为了能够快速返回结果, 在计算AP时就不再考虑召回率. 假设数据库中有5条信息与查询信息相关, 并分别出现在查询结果中的第1, 3, 6, 9, 10位, 那么这次查询的AP就是: $AP=(1/1+2/3+3/6+4/9+5/10)/5=0.62$, 得到多条查询的AP值, 对其进行平均, 就得到了mAP.\n图像检测任务中, 简单来说就是获得每个类别的AP后求平均. 特点\n从 YOLO 中继承了将 Detection 转化为 Regression 的思路, 一次完成目标定位与分类. 基于 Faster RCNN 中的 Anchor, 提出了与之相似的 Prior box. SSD 按照如下规则生成 Prior box\n以特征图上每个点的中点为中心, 生成一些列同心的 Prior box 正方形 Prior box 的最小边长为: $\\text{min size}$, 最大边长为: $\\sqrt{\\text{min size}*\\text{max size}}$ 设置不同的纵横比 (aspect ratio) 可以分别生成 2 个长方形框: 长宽分别为: $\\text{min size}*\\sqrt{\\text{aspect ratio}}$ 和 $\\frac{\\text{min size}}{\\sqrt{\\text{aspect ratio}}}$ 每个特征图对应的 Prior box 的 min size 和 max size 由以下公式决定, m 是使用特征图的数量 (eg: SSD 300 中的 m 为 6)\n$$\rs_k=s_{\\min }+\\frac{s_{\\max }-s_{\\min }}{m-1}(k-1), \\quad k \\in[1, m]\r$$ SSD 加入基于特征金字塔的检测方式，即在不同感受野 (即尺度, 尺寸) 的 Feature map 上预测目标. 具体来讲, SSD 的突出贡献是: 使用低层 Feature map 检测小目标，使用高层 Feature map 检测大目标.\n训练时的样本标记, 正负样本比例为 1:3 (经验值)\n正样本: 与 GT 重合度高的 boxes, 其输出对应分类设为对应物体; 物体 GT 框与 Anchor 的 IOU 大于 0.5 负样本: 其他所有样本 SSD 模型图和精度效率图\nSSD 输入尺寸 $300*300$\nSSD 输出的矩阵结构是 4 个偏移 (shape offsets) + 21 个类别置信度 (20 个类别+ 1 个背景类别)\nSSD 的损失函数\n位置回归 default box: Softmax Loss (Faster R-CNN 是 log loss) 目标类别分类 score 置信度: Smooth L1 loss (同 Faster R-CNN) 优点\n性能媲美 YOLO 检测精度媲美 Faster RCNN 缺点\n需要手动设置 prior box 的 min_size, max_size 和 aspect_ratio 值. 网络中 prior box 的基础大小和形状不能直接通过学习获得, 而是需要手工设置. 而网络中每一层 feature 使用的 prior box 大小和形状恰好都不一样, 导致调试过程非常依赖经验 虽然采用了特征金字塔 (Pyramdial feature hierarchy) 的思路, 但是对小目标的 Recall 依然一般, 并没有达到碾压 Faster RCNN 的级别. 作者认为, 这是由于 SSD 使用 conv4_3 低级 feature 去检测小目标, 而低级特征卷积层数少, 存在特征提取不充分的问题 3.2. 特征金字塔网络 Feature Pyramid Network (FPN) 2017 【目标检测】FPN(Feature Pyramid Network)\nFPN 增强的是语义的特征. 之后 YOLOv4 的 PAN 结构更近一步, 在 FPN 后加了金字塔结构, 即增强语义特征又增强位置特征.\nFPN 是一种自顶向下路径和横向连接将低分辨率, 语义强的特性与高分辨率, 语义弱的特性结合起来的体系结构.\nFPN 借鉴了 ResNet 的跳接操作, 用于结合底层特征和高层特征. 借鉴了 SSD 的检测策略, 在不同分辨率的特征图上分别作预测. FPN可以分三部分:\n自底向上 每向上一级用 step=2 做降采样 (Down sampling) (输出 size 相同的网络部分被称为一级) FPN 用 2 到 5 级参与预测 ( 1 级语义信息太低被抛弃) 自顶向下 每向下一级做上采样 (Up sampling)\n上采样的方法简单的有最近邻插值, 也可以使用其他的线性插值方法\n加上自底向上的低分辨率高语义特征跳接用于预测\n连接两部分的跳接 跳接时前后维度不一致的问题?\n使用 1*1 的卷积层进行升降维 通过跳接融合之后, 还要通过一个 3*3 的卷积层.\n用于减轻最近邻插值带来的影响. (因为周围的数字都比较接近, 会出现重叠效应 (Aliasing effect), 灰度不连续, 在灰度变化的地方可能出现明显的锯齿) 简单理解: 漏斗, 底部 → 高分辨率 (特征信息少, 但是能精准定位物体); 顶部 → 低分辨率 (特征信息多, 但是不能定位物体).\n如下图, 上面的图是其他的跳接特征融合, 下面是 FPN. FPN 结合了图像金字塔结构 + SSD 的优点, 能够检测到多尺度的物体. FPN 跳接融合低语义信息高分辨率特征图和高语义信息低分辨率特征图, 最后融合全部特征去预测结果.\n这部分的几级被称为 $\\left\\{P_2, P_3, P_4, P_5, P_6\\right\\}$. 其中 $2 \\sim 5$ 分别对应 $C$ 的 $2 \\sim 5$, $P_6$ 是 $P_5$ 降采样得到的. 这用于检测的五个特征图的分辨率分别为: $\\left\\{32^2, 64^2, 128^2, 256^2, 512^2\\right\\}$.\n下面的图是 Faster R-CNN 中的 RPN 网络结构, 特征融合结构可以放在前面, 用于更好的输出 Feature map.\n图像金字塔结构能够预测各尺度特征图, 能获得不同尺度的信息, 但性能消耗大.\nSSD 结构是传统 CNN 结构, 但是各尺度特征图都进行了预测. 但是由于 SSD 没有做高低分辨率特征图跳接, 所以没有使用底层特征做预测, 所以小目标检测困难.\nMASK R-CNN 使用了 FPN 结构.\n4. 感受野 (Receptive field) 如何计算感受野(Receptive Field)——原理\n定义: 感受野就是输入图像对这一层输出的神经元的影响有多大. 反过来说就是特征图上的某点能看到原始图像多大的区域.\n如果堆叠 3 个 33 的卷积核, 步长为1. 那么它的感受野就是 77. 这和 7*7 卷积核的结果是一样的, 那么为什么要堆叠 3 个小卷积呢?\n为了增加性能. 3 个小卷积核的参数量更小. 卷积过程越多, 特征提取更细致, 能加入的非线性变换 (如 RELU) 和 归一化层 (Batch normalization) 也越多. 这就是为什么 VGG 网络都是用了小的卷积核.\n5. 常见的目标检测算法 基于深度学的目标检测方法一之基本思想概念_hh_2018的博客-CSDN博客\n基于深度学的目标检测方法二之基于候选框的方法_hh_2018的博客-CSDN博客\n基于深度学的目标检测方法三之基于回归的方法_基于回归的目标检测_hh_2018的博客-CSDN博客\n一口气学完所有【目标检测算法RCNN/SSD/YOLO/SPPNet\u0026hellip;】是什么体验？浙大计算机博士手把手带你学！—人工智能/计算机视觉/深度学习_哔哩哔哩_bilibili\nMXNet/Gluon 深度学习笔记 (六) —— 物体检测总结\n5.1. R-CNN 首次使用深度学习进行目标检测. 使用 selective search 的方法, 找到候选框.\n原理\n对每张输入图片使用一个基于规则的选择性搜索 (Selective search), 生成 2000 个候选区域 (Region proposals)\n使用过分割手段, 将图像分割成许多小区域 查看现有的小区域, 合并 可能性最高 的两个区域, 重复直到整张图像合并成一个区域位置 合并规则: 合并颜色 (颜色直方图), 纹理 (梯度直方图)相似的区域\n合并后总面积减小 (为了防止一个大区域覆盖多个小区域)\n合并后目标总面积在边界框 (Bounding box) 中占比大 (为了保证合并后形状规则)\n对每个候选区域使用CNN进行特征提取\n将网络提取的特征送入每一类的 SVM 分类器 进行判别\n分类并获得置信度之后, 对所有框进行 非极大值抑制\n使用 回归器 (Regressor) 精细修正候选框位置\n使用线性脊回归器在损失函数上添加一个 $l_2$ 范数作为惩罚项, 这个参数造成了预测框额外的缩放和平移. 使结果更接近于 GT.\n回归器的损失函数有几种? 区别是什么呢?\n回归损失函数1：L1 loss, L2 loss以及Smooth L1 Loss的对比 - Brook_icv - 博客园\n均方误差 (MSE, $l_2$ loss):\n优点: 光滑连续方便收敛.\n缺点: 受到离群点影响较大.\n平均绝对误差 (MAE, $l_1$ loss):\n优点: 不容易梯度爆炸, 受离群点影响不大.\n缺点: 不光滑, 大部分情况梯度相等, 不利于收敛.\nSmooth L1\n$$\r\\text { Smooth } L_1(x)=\\left\\{\\begin{array}{cc}0.5 x^2 \u0026 \\text { if }|x|\u003c1 \\\\|x|-0.5 \u0026 \\text { otherwise }\\end{array}\\right.\r$$\n介于 L1 和 L2 之间, 解决了 L1 不光滑的问题, 同时减少了受离群点的影响.\n缺点\nSelective search 需要在 CPU 上进行操作, 并且 2000 个候选框都要做特征提取, 所以速度较慢. 使用支持向量机 (SVM) 在 CPU 上进行分类. 特征提取使用 CNN, 所以输入网络的候选框全都要 resize 到 227x227 的尺寸. 算法结构分散 (非端到端). 也可以使用 EdgeBoxes 来寻找候选框, 精度相同但速度很快\n5.1.1. 如何去除冗余的检测框? 使用非极大值抑制 (NMS)\n步骤如下:\n建立两个表, 一个保留表, 一个候选表. 将所有框放入候选表. 从候选表中排序找到置信度最大的框 $\\alpha$ 放入保留表. 用 $\\alpha$ 与候选表中的所有框做 IoU 计算, 大于阈值 (如 0.5) 的从候选表中丢弃. 重复 3 和 4, 直到候选表为空. IoU计算\n5.2. SPP-Net (空间金字塔池化) 2014 RCNN 在之后的改进之中, 借鉴了很多 SPP-Net 的思想.\n目标检测（3）-SPPNet\n优点\n输入的时候不需要缩放\n基于空间金字塔池化层, 每幅图片只需要提取一次特征 (R-CNN 一张图片需要提取 2k 次特征)\n如何做到的呢?\n原始图片中的ROI如何映射到到feature map?\n一张图片只经过一次卷积, 获得多个尺度的特征图. Selective search 获得原图上所有的边界框. 通过坐标映射 (Coordinate Mapping) 来算出需要预测的边界框对应各尺度的特征图上的位置. 从而获得大小不同的特征矩阵. 如何映射?\n$S$ 是 CNN 网络中所有层的步长的乘积. 对于图片大小有影响的只有全连接层. 因为全连接层的节点数是必须固定的, 所以必须使全连接层前面的特征图的尺寸满足全连接层的尺寸. 如何做到呢?\n使用空间金字塔池化层 (Spatial pyramid pooling). 使用卷积块 (CNN block, 其中包括卷积层, 池化层, 激活函数) 提取特征之后, 使用 3 个不同尺度的池化特征图, 每个池化特征图取最大值 (作 Max pooling), 作为 FC 层的 21 个神经元.\neg:\n假设原图输入尺寸 224x224, 并且卷积层有 256 个过滤器, 输出的特征矩阵尺寸是 13x13x256. 从这个特征矩阵中可以获得多个候选区域的映射矩阵. 每个映射矩阵都作 Max pooling, 于是矩阵的尺寸就变为 4x4, 2x2, 1x1. 将矩阵摊平. 就是 21x1 的向量, 输入全连接层. ← 这样的向量有 256 个. 缺点\nSPP-Net 还是多段的训练, 依旧使用了 Selective search 模块来生成候选区域, 分类使用 SVM, 所以效率还是很低.\n在输入 SPP 前, 所有候选框的特征图必须 resize 到正方形 (Max pooling 必须输入和输出尺寸为倍数关系), 这降低了效率.\n为什么论文用了 SVM 和 FC+softmax 两种方法作分类呢?\n因为 SVM 在少量样本的情况下, 不容易过拟合, mAP 精度高于 FC.\n5.3. Fast-RCNN 2015 优点\n优化了 SPP-Net 在 FC 之前做 Max pooling (SPP) 的操作. 使用 ROI pooling 的方法代替 SPP.\nROI (Region of Intereset) ROI pooling 可以看作是空间金字塔池化的简化版本, 它通过将区域候选框对应的卷积层特征池化为尺寸为 $K*M$ . (SPP 进行 3 次最大池化, 并且输入 ROI 不需要 resize). 如果池化尺寸对不上 FC 的输入怎么办? 直接使用 卷积特征尺寸 / 块的尺寸 就可以了.\n如: 特征尺寸 $5*7$, FC 输入尺寸为 $2*2$, 就动态调整特征尺寸变为 $5/2 * 7/2$.\n下图是 ROI Pooling 的过程, 对应特征池化为 $2*2$, 最终得到结果.\n卷积复用, 提升了速度\n分类器从 SVM 变为了 Softmax.\n接近端到端的结构, 可以从 Softmax 和 Regressor 反向传播到卷积.\n损失 Loss\n分类: $N+1$ 路的 Softmax, $N$ 是分类数量, $1$ 是背景, 使用交叉熵损失.\n回归: $4*N$ 路输出的 Regressor, $N$ 个类别每个都有一个单独的 Regressor, 使用平均绝对误差 (MAE) 损失 (即 L1 损失).\n$$\r\\mathrm{Regressor\\_Loss} = \\frac{1}{m} \\sum_{i=1}^m\\left|\\left(y_i-\\hat{y}_{k_i}\\right)\\right|\r$$ 缺点\n依旧使用 Selective search 做候选框 (有大量重叠), 还不是完全的端到端结构, 速度还是太慢.\n候选框 (Region proposal) 的坐标位置通常是小数, 输入 ROI 之前会将其整数化, 将整数化后的边界再次整数化获得池化结果, 这影响了检测的精度\n改进方案: ROI Align (Mask-RCNN中提出) R-CNN, SPP-Net, Fast R-CNN 性能精度对比\n5.4. Faster-RCNN 2015 使用 RPN (Reginal Proposal Network 区域检测网络) 代替 Selective search, 达成了整体网络端到端的结构.\n网络整体 backbone 用的还是卷积, neck 部分使用 RPN+ROI Pooling, head 部分 Regressor+Softmax.\n下面是举例, 可以看到特征图大小 $51*39*256 = 509184$, 另外每个特征图像素点还要各画 9 个 anchor box, 对于空间消耗还是很大的.\nRPN部分\n分两路走\n分类分支: 使用小卷积, 计算一个二分类任务判断候选框里有没有东西 回归分支: 如果有东西, 需要做一个定位框的微调 将原图的特征图经过一个 3*3 的卷积核, 每个滑动窗口的中心点为 anchor 的中心点, 在原图中框出多个不同尺度, 长宽比的 anchors (尺度: 128, 256, 512; 长宽比: 1:1, 1:2, 2:1).\nRPN的预处理\n优点:\n提出了RPN网络, 提升了性能, 并使得整体变为一个端到端的网络 缺点:\n训练参数过大 (候选区域过多) 对于真实训练使用来说还是性能不够 5.5. YOLO 膜拜！YOLO目标检测竟被讲的如此简单！（完整版）YOLOv1-v8，草履虫都能听懂！这么好的课程还没人看？我不更了！！！_哔哩哔哩_bilibili\nYOLO速度快, 可以用于实施检测任务; 但是相对的 mAP 会降低.\n5.5.1. YOLOv1 YOLO 的结构\nGoogleNet + CNN x 4 + FC x 2, 是端到端的结构\n训练时, 图片输入尺寸为 $224*224*3$; 推理时为 $448*448*3$\n为什么输入图片的尺寸是固定的?\n因为 YOLO 网络中卷积直接接上了全连接层, 不像 Faster-RCNN 那样有 ROI 池化. 全连接层的输入尺寸是固定的, 导致网络的输入尺寸也只能固定了.\nYOLO 训练流程\n将输入图片尺寸 resize 到 $448*448$, 经过卷积 ($7*7*1024$) + 全连接 ($1470*1$) 网络之后 reshape 为 $7*7*30$ 的特征图.\n每个 $7*7$ 的特征图, 有 $49$ 个像素点 每个像素点都对应原图的一个正方形区域 (类似于感受野, 这里被称作单元格 (Grid cell)). 每个单元格默认预测 $2$ 个 Bounding box (bbox) 的置信度. 所以一张特征图有 $7*7*2=98$ 个 bbox. 训练时, 只使用置信度高的那个 bbox; 推理时, 使用 NMS 过滤掉置信度低的 bbox, 再分类 或者 先用阈值过滤一批置信度低的 bbox, 再分类别地对置信度进行 NMS (YOLO 源码). 但由于不同类别的 bbox 重叠度不会太高, 所以两种方法效果不会差太多. URL 为什么特征图尺寸是奇数?\n因为一般情况下, 照片的中心会有一个物体作为主体, 所以中心有一个 Gird cell 能提高精度.\nbbox 的置信度\n如果判断单元格中没有物体, 置信度为 0 如果判断单元格中有物体, 则置信度等于预测的 box 与 gt 的 IOU 如何判断单元格中有没有物体? 如果 gt 框的中心点在该单元格内, 则这个单元格包含物体 反之则不包含物体 每个 bbox 的参数: 位置参数: $x,y,w,h$ ($x,y$ 为 bbox 中心相对于单元格中心的偏移量, $w,h$ 为 bbox 的宽高相对整张图片的占比)\n$$\rx=\\frac{x_c}{w_i} S-x_{c o l}, y=\\frac{y_c}{h_i} S-y_{\\text {row }} \\quad w=\\frac{w_b}{w_i}, h=\\frac{h_b}{h_i}\r$$ 置信度: $c$\n30 又代表什么? $30$ 代表参数: $2*(4+1)+20$ (2 个bbox, bbox 的参数有 $5$ 个, 加上 $20$ 个分类在这个单元格上的概率) 于是每个单元格输出一个置信度高的 bbox 位置, 并选择一个概率大的类别.\n训练时预测框对应的目标标记 (GT) 怎么生成? Loss 是什么?\n损失\n总损失 = bbox Loss + 置信度 Loss + 分类 Loss; 用的都是预测值和 GT 值差的平方.\n最后一个分类误差: GT 标签标注的物体概率为 1, 其他为 0; 预测出来的结果所有类别都是浮点数. 优点\n速度快 缺点\n准确率降低\n对于靠得很近的物体 (重点都在同一个单元格上), 和小目标检测效果都不好, 因为一个单元格只预测两个框.\n5.5.2. YOLOv2 YOLOv2 性能精度与其他模型的对比图, 这里的 YOLOv2 的输入使用了不同尺寸的图片 (正方形).\n大尺寸图片精度高速度慢; 小尺寸图片精度低速度快.\nYOLOv2 对 YOLOv1 的一些小细节做了改进如下图\nBatch Normalization\n神经网络基础部件-BN层详解 - 嵌入式视觉 - 博客园\n在卷积层后全都加上了 Batch Normalization 做归一化, 使得训练时收敛相对更容易. 并且去掉了 Dropout YOLOv1 并没有使用 BN BN 是什么? BN 就是将所有值都减去均值, 再除以标准差. 这样就可以将数据变为以 0 为中心, 1 为标准差的分布. 为什么这么做? 因为很多的激活函数如 Sigmoid 函数, tanh 函数都是以 0 附近为非饱和区的, 数值太大或太小都会进入饱和区, 容易导致梯度消失难以训练.\nBN 的好处\n加快模型收敛; 改善梯度(远离饱和区); 可以使用大的学习率; 对初始化不敏感; 有正则化的作用 (取代 Dropout) 结果: 使用 BN 层之后, 能够提升 2% mAP 更大分辨率 High Resolution Classifier\nv1 训练使用 $224*224*3$ 小分辨率图片, 推理使用 $416*416*3$ 大分辨率图片, 这样做可能导致模型水土不服 v2 使用小分辨率图片后, 额外进行了 10 次大分辨率图片进行微调 结果: mAP 又提升约 4% 新的卷积网络结构 DarkNet-19\n这个是分类模型结构图. 双横线以下的是分类模型独有的结构.\n检测模型结构图, 虚线内的是 DarkNet, 外面的是检测模型独有的结构.\nDarkNet 深度相对较浅, 所以速度较快, 同时精度较高\n去掉了全连接层 (因为 FC 层参数多, 影响性能)\n使用 5 次降采样, Max pooling 卷积尺寸 $2*2$, 步长 2, 所以总的步长为 $2^5=32$. 由于池化层的特性, 需要输入图片能被 32 整除, 所以 DarkNet 检测模型输入尺寸为 $416*416$. 这样最后池化得到的特征图尺寸为 $13*13$. (相比 YOLOv1 的 $7*7$ 特征图更大)\n$3*3$ 卷积之间使用了 $1*1$ 卷积\n$1*1$ 卷积是什么? 作用是什么? 如果 $1*1$ 卷积的卷积核个数小于上层卷积层的卷积核个数, 并且步长为 1 的时候. (可以将其视作一个全连接层, 经过 $1*1$ 卷积的每一个卷积核都可以视作一次对上层特征矩阵的加权求和)\n作用: 使用了 $1*1$ 卷积之后就可以在原先的基础上多加一层激活函数. 这样就可以在特征图的尺寸不变 (不损失分辨率) 的前提下, 增加网络的非线性表达能力.\n为什么卷积网络要加激活函数? 为什么要增加非线性?\n卷积神经网络中为什么要在卷积层后面添加激活函数? - 知乎\n因为如果多层卷积网络没有激活函数, 那么它的效果和单层卷积网络是一样, 只能拟合线性特征.\n增加激活函数之后, 多层卷积网络就可以拟合非线性的特征, 而实际情况图片的特征非常复杂, 并不是线性的.\n如果 $1*1$ 卷积的卷积核步长不为 1 的时候, 可以理解为是一种池化操作.\n$1*1$ 卷积的降维操作还可以减小网络的参数量.\nAnchor Box\nYOLOv2 参考了 Faster-RCNN 使用 Anchor 方法, 但是添加的不是手动设置尺寸的先验框, 而是用聚类提取尺寸的先验框.\nYOLOv1 推理时预测 98 个框/张图片, YOLOv2 推理时超过 1000 个框/张图片. 虽然 mAP 没有获得提升, 但是 Recall (查全率) 得到了大幅提升.\n聚类提取先验框 Dimension Clusters\nYOLOv2 使用了聚类的方法提取先验框. 以前的方法生成的框的比例都是固定的, 不一定能完全适合特定的数据集 YOLOv1 是将图均分 49 格每格生成 2 个框, 训练后对框进行偏移. Faster-RCNN 将特征图的每个像素作为 Anchor 生成 9 个候选框 (长宽比手动设定, 带有一定的主观性), 训练后对框进行偏移. YOLOv2 基于 COCO 数据集, 将数据集中的标注框进行了聚类 k-means 聚类需要设置 聚类数量 $k$ 和 距离指标 $d$. 聚类数量默认为 5, 超过 5 之后的 IOU 提升不大了.\n距离指标公式如下:\n$$\rd(box, centroid)=1-IOU(box, centroid)\r$$ 先验框的目的是使预测框与 GT 框的 IOU 更高, 所以这里使用 box 与 聚类中心的 box 之间的 IOU 作为距离指标. 直接位置预测 Direct location prediction\n候选框偏移量参数 $x,y,w,h$ 预测的时候, $x,y$ 为 bbox 中心相对于单元格中心的偏移量, 中心点 $(x,y)$ 很可能飘出单元格 (Grid cell) 外, 这样对导致训练收敛出现问题 ←YOLOv1的缺陷. YOLOv1 的偏移公式如下:\n$$\r\\begin{array}{c}\rx = (t_x*w_a)-x_a \\\\\ry = (t_y*h_a)-y_a\r\\end{array}\r$$YOLOv2 预测的 bbox 中心点是相对于对应单元格本身的偏移量, 预测 5 个参数: $t_x,t_y,t_w,t_h,t_o$. 公式如下:\n$$\r\\begin{aligned}b_x \u0026 =\\sigma\\left(t_x\\right)+c_x \\\\b_y \u0026 =\\sigma\\left(t_y\\right)+c_y \\\\b_w \u0026 =p_w e^{t_w} \\\\b_h \u0026 =p_h e^{t_h} \\\\\\operatorname{Pr}(\\text { object }) * \\operatorname{IOU}(b, \\text { object }) \u0026 =\\sigma\\left(t_o\\right)\\end{aligned}\r$$ $\\sigma\\left(t_x\\right),\\sigma\\left(t_y\\right)$ 是预测 bbox 中心点相对于单元格边缘的距离, 单元格边缘长度为 1. $\\sigma$ 是 Sigmoid 函数, 所以结果只能是 0 到 1 之间. Pass through (精细特征 Fine-Grained Features)\n使用不同尺寸的特征图来强化不同尺寸目标的检测能力, 过程中运用了一个小技巧 (Pass through). 分类模型没有用 Pass through layer.\n由于 YOLOv1 使用的是最后一层的特征, 所以感受野很大, 对小目标的识别就变得很差. 所以需要融合之前的特征 (要将高分辨率特征拆分并叠加后获得细粒度特征 (Pass through)).\nPass through 特征图 (这么做之后图片尺寸减小了, 但是保留了大部分的信息)\n选用了 $26*26*512$ 尺寸的特征图, 用 $1*1$ 卷积将这个特征图尺寸改为 $26*26*64$, 使用 Pass through 层再将尺寸变为 $13*13*256$. 将这个矩阵融合到卷积输出的 $13*13*1024$ 的特征图中.\n注意最后输入预测的尺寸 $125*1*1$, $125=(5+20)*5$ 是 $(x,y,w,h,c + classes)*(anchor\\_box)$.\n多尺度 Multi-Scale\nYOLOv2 可以检测尺寸在 $320*320 \\sim 608*608$ 之间的图片, 注意图片尺寸必须被 32 整除 (因为网络池化层的特性, 每次池化特征尺寸就要除 2).\n由于 DarkNet 网络中没有了全连接层, 取而代之的是 Global average pooling (GAP 全局均值池化) 层. 根据 DarkNet 网络, 将特征图输入 GAP 层之后, 输出还是特征图数量的特征图, 但是特征图的尺寸变为 $1*1$ (GAP 将每一个特征图都分别求了一个平均值), 之后使用 Softmax 来分类就行了.\n全局平均池化与全连接对比 - you-wh - 博客园\n全连接层的计算量大于 GAP\nLoss\n5.5.3. YOLOv3 深入浅出Yolo系列之Yolov3\u0026amp;Yolov4\u0026amp;Yolov5\u0026amp;Yolox核心基础知识完整讲解\n【精读AI论文】YOLO V3目标检测（附YOLOV3代码复现）_哔哩哔哩_bilibili\nYOLOv3 的推理速度提升, 并且对于小目标的检测能力增加了.\n下边左图是 IOU 在0.5到0.95之间的各阈值所获得的平均值结果, 右图是 IOU 为 0.5 作为阈值获得的结果.\n这次模型的输入为\n$416*416*3$ (用于预测的特征矩阵尺寸 $13,26,52$);\n$608*608*3$ (用于预测的特征矩阵尺寸 $19,38,76$).\n更大的 Backbone (DarkNet-53)\nDarkNet-53 网络结构图\n从 YOLOv2 的 19 层卷积网络增加到了 53 层.\nDarkNet-53 由 52 层卷积层 + 1 层 FC 层构成, 其中大部分卷积层都加了残差连接.\n由于 DarkNet 尾端有 3 次卷积缩小特征尺寸, 所以最小的输入图片必须大于 32x32, 并且尺寸是 32 的倍数.\nDarkNet-53 等精度接近 ResNet-101, 每秒可进行的浮点运算量和 FPS 高于 ResNet-152.\n更多的候选框\n这次每个单元格内生成一个中心点作为 Anchor, 根据 Anchor 生成 3 个候选框, 特征的尺寸为 $N*N*(3*(4+1+80))$. (这里的 $N$ 有三个不同的尺度 $52*52,26*26,13*13$)\n这三个不同尺度的特征图中如果有物体, 那么物体的中心肯定有一个 Anchor. 问题是应该选择哪个尺度和形状的候选框才能正好概括到物体?\n这次与 YOLOv1 不同, 不是看候选框的置信度, 而是与指定 GT 框做 IOU, IOU 最大的候选框作为正样本; 剩下的与指定 GT 框的 IOU 大于手动指定阈值(如 0.5), 则忽略; 其他候选框作为负样本. 分类预测置信度\n获取预测分类的置信度方法: 候选框的置信度 x 类别的置信度.\n损失 Loss\n遍历所有候选框, 当输入尺寸为 $416*416*3$ 时, $S^2=13^2+26^2+52^2$ ← 三个尺度; $B=3$ ← 每个单元格 3 个候选框 正样本 正样本候选框回归损失, $x,y,w,h$ 与 GT 的距离. 正样本分类损失, 逐类别计算二元交叉熵损失 + $-log(候选框粗选置信度)$. 负样本 负样本候选框粗选损失, $-log(1-候选框粗选置信度)$. 模型训练过程\n实际的 GT 数据也需要换算到相应的单元格, 找到对应的 $x,y,w,h$. 模型测试过程\n手动设置置信度阈值 多分类非极大值抑制 5.5.4. YOLOv4 深入浅出Yolo系列之Yolov3\u0026amp;Yolov4\u0026amp;Yolov5\u0026amp;Yolox核心基础知识完整讲解\n预处理 数据增强\nMosaic 数据增强\n对输入图片进行了随机缩放, 随机裁剪, 随机排布.\n用途:\n对于模型来说, 小目标的 AP 通常比普通目标低. 而COCO数据集包含大量的分布不均匀的小目标.\nBackbone 部分的更新\nCSPDarkNet-53 代替了 DarkNet-53;\n网络中的一些改动:\n在 Backbone 部分用 CBM 模块代替了 CBL 模块; 使用 Mish 激活函数代替 Leaky ReLU.\n优点: 增强卷积的学习能力, 在轻量化的同时保持准确性; 降低内存消耗. 理论上对负值的轻微允许可以获得更好的梯度流, 而不是像 ReLU 中那样的硬零边界, 而且平滑的激活函数允许更好的信息深入神经网络, 从而得到更好的准确性和泛化. CSP 模块代替了残差模块\n增强CNN学习能力的Backbone:CSPNet - pprp - 博客园\nDenseNet：比ResNet更优的CNN模型\nCSPNet 的作者认为推理计算量过高是因为网络优化中的梯度信息重复造成的.\nCSPDenseNet 在学习 DenseNet 重复使用各尺度特征的梯度信息的同时, 通过截断梯度流来防止过多的重复梯度信息.\nDenseNet 是 ResNet 后推出的网络, 更加的激进, 通过前后层的密集连接 (dense connection) 使每一层都接收到前面所有层的信息; 同时通过融合不同层的特征图, 来实现特征的重用 (feature reuse). 这两个优点增强了 DenseNet 的性能. 其中的 $H_l$ 函数表述非线性转化函数 (non-linear transformation), 其中可以包含 BN, ReLU, Pooling 和 Conv. DenseNet 的正向传播\n$$\r\\begin{aligned}\u0026 \\mathbf{x}_1=\\mathbf{w}_1{ }^* \\mathbf{x}_0 \\\\\u0026 \\mathbf{x}_2=\\mathbf{w}_2{ }^*\\left[\\mathbf{x}_0, \\mathbf{x}_1\\right] \\\\\u0026 \\vdots \\\\\u0026 \\mathbf{x}_{\\mathbf{k}}=\\mathbf{w}_{\\mathbf{k}}{ }^*\\left[\\mathbf{x}_{\\mathbf{0}}, \\mathbf{x}_1, \\ldots, \\mathbf{x}_{\\mathrm{k}-1}\\right]\\end{aligned}\r$$DenseNet 的反向传播\n可以发现大量的梯度信息被用来更新不同尺度层的权重. CSPDenseNet 的正向传播\n$$\r\\begin{aligned}\u0026 \\mathbf{x}_{\\mathrm{k}}=\\mathbf{w}_{\\mathrm{k}} *\\left[\\mathbf{x}_0,, \\mathbf{x}_1, \\ldots, \\mathbf{x}_{\\mathrm{k}-1}\\right] \\\\\u0026 \\mathbf{x}_{\\mathrm{T}}=\\mathbf{w}_{\\mathrm{T}}*\\left[\\mathbf{x}_0,, \\mathbf{x}_1, \\ldots, \\mathbf{x}_{\\mathrm{k}}\\right] \\\\\u0026 \\mathbf{x}_{\\mathrm{U}}=\\mathbf{w}_{\\mathrm{U}} *\\left[\\mathbf{x}_0, \\mathbf{x}_{\\mathrm{T}}\\right]\\end{aligned}\r$$CSPDenseNet 的反向传播\n可以看到密集层和部分过度层不包含另一方重复的梯度信息, 由此截断了梯度流, 防止了重复的梯度信息传递. CSPX 模块包含 $5+2*X$ 个卷积层, 模块中的第一个卷积层步长为 2, 其他卷积层的步长为 1, 导致内个 CSPX 都具有下采样 1/2 的能力.\nDropblock 等于是在做 Cutout 数据增强, 在图片上挖掉一块. 这样可以影响到卷积, 而 Dropout 那样的随机开孔对卷积的影响太小. 而对于 Cutout 来说, 只能在输入层用, Dropblock 则可以用在网络中每个特征图上.\nNeck 部分的更新\n使用 SPP 模块进行多尺度融合;\n与 YOLOv3 的 FPN 结构不同, YOLOv4 在 FPN 层后面还添加了一个自底向上的特征金字塔.\nPAN结构\n(b) 区域特征图 $N_i$ 从下至上与 $P_{i+1}$ 向融合, 计算出 $N_{i+1}$. 损失 Loss\nYOLOv4 添加了CIoU Loss\nCIoU Loss\nCIoU Loss 之前的 DIoU Loss\nCIoU Loss 同时考虑了重叠面积, 中心点距离, 预测框与 GT 框的长宽比. 公式如下\n$$ \\text{CIOU_Loss}=1-\\mathrm{CIOU}=1-\\left(\\mathrm{IOU}-\\frac{\\text{Distance_2}^2}{\\text{Distance_C}^2}-\\frac{v^2}{(1-\\mathrm{IOU})+v}\\right)\n$$\n$$\r\\nu=\\frac{4}{\\pi^2}\\left(\\arctan \\frac{w^{\\mathrm{gt}}}{\\mathrm{h}^{\\mathrm{gt}}}-\\arctan \\frac{\\mathrm{w}^{\\mathrm{p}}}{\\mathrm{h}^{\\mathrm{p}}}\\right)^2\r$$ DIoU nms\n将 NMS 中的 IoU 计算换成了 DIoU 计算, 因为考虑到了候选框的中心点位置信息, 所以在重叠物体较多的问题中, DIoU nms 效果由于传统 nms.\n同级别精度和效率 CenterNet2\n5.5.4. YOLOv5 深入浅出Yolo系列之Yolov5核心基础知识完整讲解\n数据增强\nMosaic 数据增强 RandomAffine 随机仿射变换 MixUp 随机混合两张图片, 改一改透明度 图像模糊等采用 Albu 库实现的变换 HSV 颜色空间增强 随机水平翻转 Auto Anchor 自适应锚框计算\n与 YOLOv3 类似使用数据集中的 GT 聚类获得, 不同是聚类的标准不再是 IoU, 而是宽高比.\nYOLOv5 在 COCO 数据集上的初始 Anchor 如下, 每一行对应一个尺度, 各有 3 各宽高比例.\n自适应图片缩放 (推理时使用)\n由于数据集中的图片长宽比例都不同, 需要按比例缩放并填充黑边, 但是如果黑边过多会造成信息冗余, 推理速度下降.\n使用图像自适应来添加最少的灰边, 这样推理速度上升了 37%.\nBackbone 部分使用了 Focus 结构\n就是 Pass through 特征图, 将图片尺寸减半. (Pass through 可以增强小目标识别, 但是用在这里似乎并不为了提升 mAP, 作者说是为了提速)\n可以看到 YOLOv5 相比 YOLOv3 相同为位置参数量明显减少. 卷积层参数: 卷积核尺寸 3x3, 步长为 1. 有 32 个卷积核. 每个卷积核对 12 层特征图进行卷积, 得到的结果相加, 所以最后有 32 层. Neck 部分使用了新的 CSP2 结构\n5.5.6. YOLOv8 如何看待YOLOv8，YOLOv5作者开源新作，它来了！? - 知乎\n特点:\n提供了一个全新的 SOTA 模型, 包括 P5 640 和 P6 1280 分辨率的目标检测网络和基于 YOLACT 的实例分割模型. 和 YOLOv5 一样, 基于缩放系数也提供了 N/S/M/L/X 尺度的不同大小模型, 用于满足不同场景需求 骨干网络和 Neck 部分可能参考了 YOLOv7 ELAN 设计思想, 将 YOLOv5 的 C3 结构换成了梯度流更丰富的 C2f 结构, 并对不同尺度模型调整了不同的通道数, 属于对模型结构精心微调, 不再是无脑一套参数应用所有模型, 大幅提升了模型性能. 不过这个 C2f 模块中存在 Split 等操作对特定硬件部署没有之前那么友好了 Head 部分相比 YOLOv5 改动较大, 换成了目前主流的解耦头结构, 将分类和检测头分离, 同时也从 Anchor-Based 换成了 Anchor-Free Loss 计算方面采用了 TaskAlignedAssigner 正样本分配策略, 并引入了 Distribution Focal Loss 训练的数据增强部分引入了 YOLOX 中的最后 10 epoch 关闭 Mosiac 增强的操作, 可以有效地提升精度 模型结构图\n精度和速度\n模型 YOLOv5 params(M) FLOPs@640 (B) YOLOv8 params(M) FLOPs@640 (B) n 28.0(300e) 1.9 4.5 37.3 (500e) 3.2 8.7 s 37.4 (300e) 7.2 16.5 44.9 (500e) 11.2 28.6 m 45.4 (300e) 21.2 49.0 50.2 (500e) 25.9 78.9 l 49.0 (300e) 46.5 109.1 52.9 (500e) 43.7 165.2 x 50.7 (300e) 86.7 205.7 53.9 (500e) 68.2 257.8 5.5.7. YOLOv9 中小模型相对于YOLOv5 效率降低精度提高. 5.6. SSD (Single Shot MultiBox Detector) 跳转到3.1\n5.7. Mask-RCNN 属于一个通用的可以实例分割的物体检测框架.\n【物体检测实战】Mask-Rcnn图像实例分割被同济大佬给讲透了，原理+论文详细解读，带你快速入门！附配套资料_人工智能/深度学习/物体检测/yolo_哔哩哔哩_bilibili\nmask-rcnn解读_maskrcnn模型的运行结果-CSDN博客\n语义分割算法Mask RCNN论文解读_maskrcnn源论文名称-CSDN博客\nMask R-CNN 算法浅谈 - 乞力马扎罗的雪顶 - 博客园\nMask-RCNN 流程图\nMask-RCNN 文字解释流程图\nMask-RCNN 与 Faster-RCNN 类似\n第一阶段都是 卷积提取特征+RPN 生成候选框 (region proposal)和初步分类. 第二阶段中, Mask-RCNN 除了和 Faster-RCNN 相同的 ROI 池化, 分类和回归分支之外, 还添加了一个全卷积网络 (FCN) 的分支, 对每个 ROI 预测了对应的二值掩膜 (Binary Mask). 其中目标所在的像素为 1, 其他位置像素为 0. Mask-RCNN 对 ROI 池化做了改进, 使用 ROI Align.\n优化了ROI 池化的整数化 → 用双线性插值替代最近邻插值.\n最后在每个大 bin 中对 4 个中心点进行 Max pooling.\nFCN 是什么?\n不含有 FC 层的卷积网络, 可以适合任意尺寸的输入. 增大特征尺寸的反卷积层 (deconv layer), 能够输出精细结果. 结果不同深度结果的跳级 (Skip) 结构, 能够同时确保鲁棒性和准确性. 优点 可以接受任意大小的输入图像 (因为没有全连接层). 更加高效, 避免了使用邻域带来的重复计算和空间浪费的问题. 缺点 得到的结果还不够精细. 没有充分考虑像素之间的关系, 缺乏空间一致性. 损失函数\n计算每个 ROI 上的损失\n$$\rL_{ROI}=L_{cls}+L_{bbox}+L_{mask}\r$$ 5.8. Vision Transformer 识别用 AN IMAGE IS WORTH 16X16 WORDS: TRANSFORMERS FOR IMAGE RECOGNITION AT SCALE\nViT论文逐段精读【论文精读】_哔哩哔哩_bilibili\nVIT (Vision Transformer) 模型论文+代码(源码)从零详细解读，看不懂来打我_哔哩哔哩_bilibili\nVision Transformer in Classification\n预处理\n对图片进行编码\n前人研究中, 由于将图片每一个像素作为最细粒度进行 Embedding 的计算复杂度太高, 所以会使用特征图的每一个像素, 孤立自注意力 (只使用局部的小窗口, 通过控制窗口大小来调整计算复杂度) 或轴向注意力 (Axial Attention 将 2d 图片拆分为高度和宽度分别作为轴应用自注意力, 如以行为轴, 就是计算每一行与其他行之间的互相作用)\nViT 将图片划分为局部, 将局部像素变为一维作为一个元素输入 FC 层, 就可以获得 Linear embedding, 就可以传入 Transformer. 就和 NLP 的 Transformer 一样, 但是 ViT 是有监督的.\n特性\nViT 在 ImageNet 这类中型数据库性能会低于 ResNet, 因为 transformer 对于卷积网络缺少了归纳偏置 (inductive biases), 这是获取先验信息的能力, 对卷积网络来说有两个归纳偏置:\n空间局部性 (Locality) 由于卷积核的滑动, 相邻的区域会学习到相邻的特征 (共享权重) 平移等变性 (Translation equivariance) $f(g(x))=g(f(x))$, 不论先做哪个函数, 都是一样的结果. 可以将 $f$ 函数理解为卷积, $g$ 函数理解为平移操作. (因为卷积核是在图片中滑动的) 为了验证这个问题是由于缺少先验信息导致的, 使用大规模数据集预训练 ViT 后, ViT 的性能就获得了很大的提升.\n在图片预处理之后, 直接使用标准的 Transformer 来做图片识别问题.\n模型\n模型结构图\nViT 将图片划分为局部的块, 将块变为序列输入线性投射层 (FC). 这里图片既存在图片自身的信息, 又存在图片的位置信息 (Position embedding) 的, 就是上图的深色椭圆形数字. 位置信息可以让模型学到一般的情况下, 物体之间的位置关系.\n假设输入图片尺寸为 $224\\times224\\times3$, patch_size=16 (切 $16\\times16$ 块), 那么就可以获得 196 个图像块. 经过线性投射层的维度是 $768\\times768$, 最终获得输出维度: $196\\times768*768\\times768=196\\times768$ (矩阵运算), 这是图像本身的 token, 另外还需要加一个 spiecal token:[class] (是整个图片的分类 token, 实际上作用不大, 之后会说), 维度为 $1\\times768$. 最终进入标准的 Transformer 的序列尺寸为: $197\\times768$.\n这时候还需要加入位置编码信息. 建立一个表, 表的每一行代表一个序号 (位置信息), 每一行是一个向量, 维度是 $768$. 这样表的尺寸就是 $197\\times768$. 将这个表与图像的 token + class 相加即可.\nTransformer encoder\n输入矩阵经过归一化层尺寸不变, 经过多头注意力层时, 假设有 12 个自注意力头, 每个头中的 $k,q,v$ 的维度都变为 $197\\times(768/12)$, 将 12 个头拼接, 获得维度还是 $197\\times768$ 的矩阵. 经过 MLP 层时, 维度会放大 $197\\times3072$, 再缩小回 $197\\times768.$ (MLP 是 Transformer 里的feed forward, 把 attention 抓取出来的序列信息映射成语义信息). 这里为了对应残差连接所以维度不变, 这样也可以叠更多个 Transformer Encoder.\n监督学习\n上面讲到 [class] token, 作者为了保持和原始的 transformer 保持一致, 所以也用了 [class] token, 在 NLP 是对句子做分类的时候用到的特征, 在 ViT [class] token 用于局部图像块的分类 (就是输出结果中提取 class token, 输入一个小型多层 MLP + tanh 激活函数做分类).\n一般的图像识别网络, Backbone 后面可以接 GAP (全局平均池化), 池化后 + 单层 FC + Softmax. 好好调参的话, 效果和 MLP 差不多.\n不同的位置编码\n作者使用了 1-D 位置编码, 2-D 位置编码, 相对位置编码, 但是效果差异不大.\n1-D 位置编码:\n$$\r1\\ 2\\ 3\\ \\cdots\\ 9\r$$ 2-D 位置编码:\n$$\r\\begin{matrix}\r11 \u0026 12 \u0026 13\\\\\r21 \u0026 22 \u0026 23\\\\\r31 \u0026 32 \u002633\r\\end{matrix}\r$$ 相对位置编码:\n同样是一维, 使用块之间的相对距离来编码, 而不是绝对位置.\n作者认为, 是因为分出来的块太少, 只有 16 块, 所以不管用那种方法位置信息都很明确, 所以性能没有差距.\n对于大尺寸图片的微调\n理论上来说, ViT 可以对应各种大小的图片, 保持 patch size 不变的情况下, token 的长度会边长, 只要显存够就能训练. 但是, 如果训练大尺寸图片, 那边原来的位置编码信息就没有用了, 因为token 长度对不上.\n这时候, 需要对微调图片进行 2d 插值缩放图片到训练时用的图片大小, 但是这么做会影响性能.\n可视化实验\n左图展示了 Linear projection layer 如何 embedding 图片的 RGB 值, 结果类似于特征图.\n中图展示了 Position embeddingm, 显示的是位置之间的相似性, 结果可以看到同行同列和特殊比例位置相似性会更高.\n右图展示了图片中远距离像素点之间的关系是否会被自注意力观察到.\n可以看到自注意力模块可以看到图像主体.\n5.9. DETR 2020 End-to-End Object Detection with Transformers\nhttps://github.com/facebookresearch/detr\n目标检测(DEtection TRansformer)—DETR\n过去的检测网络是从小到大, 从局部到全局 (FPN → PAN), 各个尺度集合到一起; DETR 是从大到小, 从全局到局部的方式.\n简单来讲, DETR 找目标就像在地图上找目标一样, 先全局粗略搜索, 再精细搜索, 所以对小目标检测效果不是很好. 网络结构\nDETR 先使用卷积网络提取特征, 后接上 Transformer 编解码, 并行预测最终的检测结果.\nLoss: 在训练过程中, 使用二分匹配将预测框与 GT 框进行匹配, 没有物体的框归为“无对象”分类. 预测框与 GT 框一对一匹配. 用的匹配算法是匈牙利算法.\n解码器解码之后, 将 embedding 出入共享前馈网络 (feed forward network FFN, 一般是 MLPs), 获得类和边界框结果.\n编码器\n不是必须的, 作用是特征加强.\n注意力可视化图中可以看出, Encoder 的注意力机制可以抠出目标, 即使遮挡严重\n解码器\nDecoder 的注意力集中在目标边缘, 说明 Decoder 学到了目标的边缘信息, 这有助于更加精确的定位目标.\n网络优点:\n简化了流程提升了效率, 消除了如 NMS, anchor. 提高了性能. 性能\nR101 是用了 RESNET-101 作为 Backbone. 没有写 R101 的用了 RESNET-50. 5.10. Co-DETR 2023 DETRs with Collaborative Hybrid Assignments Training\nCo-DETR:DETRs与协同混合分配训练论文学习笔记_co-detr 环境配置-CSDN博客\n网络结构图\n","permalink":"https://sqf.icu/article/3c44f067-d3bd-4bf6-aefc-e0bea032d6b5/","summary":"\u003ch1 id=\"1-原始cnn\"\u003e1. 原始CNN\u003c/h1\u003e\n\u003cp\u003e卷积结构的网络大致由 3 各网络层组成: 卷积层, 池化层和全连接层.\u003c/p\u003e\n\u003ch2 id=\"11-卷积层-convolution-layer\"\u003e1.1. 卷积层 Convolution layer\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e使用不同的卷积核依次进行卷积提取特征\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/aa00b231c5da0f0032e20eda.png\"\u003e\u003c/p\u003e\n\u003cp\u003e卷积操作涉及的参数如下:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003e滑动窗口步长: 步长不同会导致特征图尺寸不同\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e步长越小, 计算效率越低\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/ae2a4164e2a94543ab8a73ad.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e卷积核尺寸\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e边缘填充\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e有些卷积核按照特定步长会导致漏掉一些原图的像素, 所以需要再边界补 $0$.\u003c/li\u003e\n\u003cli\u003e$0$ 不会对卷积计算产生影响.\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e卷积核个数\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e卷积核的个数决定了特征图的厚度 (第三个维度)\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/92ec14616faaf8015fba534f.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e卷积的尺寸计算, 卷积有两种方式: VALID 和 SAME. VALID 不进行补 $0$, 会漏掉一些原图的参数, SAME 补 $0$, 多加一圈 $0$ 来补齐. 下面的公式是 SAME, 去掉 $2P$ 就是 VALID.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/310cb0a1eff53f9042e52447.png\"\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e长度:\u003c/p\u003e\n$$\r\n        H_2=\\frac{H_1-F_H+2 P}{S}+1\r\n        $$\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e宽度:\u003c/p\u003e\n$$\r\n        W_2=\\frac{W_1-F_W+2 P}{S}+1\r\n        $$\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e$W_1,H_1$ 表示 input 的宽度和长度\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e$W_2,H_2$ 表示输入特征图的宽度和长度\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e$F$ 表示卷积核长和宽的大小\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e$S$ 表示滑动窗口的步长\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e$P$ 表示边界填充 (padding) 厚度\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e卷积参数共享:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e如果图像是 $32*32*3$ 的图像, 卷积核有 $10$ 个, 尺寸都为 $5*5*3$ (就是对 RGB 三通道都做卷积). 这样的话, 每个卷积核需要 $5*5*3=75$  个参数, 加上每个卷积核都有一个对应的偏置参数 $b$, 总共需要 $(75+1)*10$ 个参数.\u003c/li\u003e\n\u003cli\u003e所以卷积网络参数远少于全连接神经网络参数.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e使用多个不同尺寸的卷积核之后全连接如何处理? (NLP 处理句子或 CV 处理图片时被使用到)\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/a4cb8ba8f639ceb75a756334.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://blog.csdn.net/The_lastest/article/details/81460424\"\u003e使用多个不同尺寸的卷积核卷积后的全连接处理_多个卷积核_空字符（公众号：月来客栈）的博客-CSDN博客\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"目标检测问题常用的模型"},{"content":"1. 激活函数 深度学习常见激活函数介绍及代码实现 - UCloud云社区\n1. ReLU 线性整流函数(Linear rectification function), 又称修正线性单元, 是一种人工神经网络中常用的激活函数(activation function), 通常指代以斜坡函数及其变种为代表的非线性函数.\n$$\rf(x)=max(0,x)\r$$2. Sigmoid 缺点\nsigmoid有一个梯度消失的问题, $|z|\u003e4$(变量值很大或很小)的时候, 梯度就快消失了(趋近于0).\n3. Tanh $$\rf(x)=\\tanh (x)=\\frac{\\left(e^{x}-e^{-x}\\right)}{\\left(e^{x}+e^{-x}\\right)}\r$$\n4. Logistic Regression (LR 逻辑回归) [ML] 逻辑回归与 Softmax 回归\nsigmoid函数\nLR 模型是用线性回归模型的结果逼近真实标记 ($Y=1$ ) 的对数几率 (log odds,logit). 所谓的几率表示事件发生的概率 $P(Y=1|x)$ 与事件不发生的概率 $P(Y=0|x)$ 之比\n$$\rodds=\\frac{P(Y=1|x)}{1-P(Y=1|x)}\r$$那么对数几率就是对几率取自然对数的结果\n$$\r\\text { logit(odds) }=\\ln \\frac{P(Y=1 \\mid x)}{1-P(Y=1 \\mid x)}=w^{T} x + b\r$$ 给定一组训练数据, 要求解上述的条件概率分布, 可以应用极大似然估计法 (Maximum Likelihood Estimation, MLE) 估计模型的参数. 极大似然估计, 即是对样本的似然函数 L 进行求参.\n$$\rL\\left(x_{1}, x_{2}, \\cdots, x_{n} ; \\hat{\\theta}\\right)=\\underset{\\theta \\in \\Theta}{max}L\\left(x_{1}, x_{2}, \\cdots, x_{n} ; \\theta\\right)\r$$令 $P(Y=1 \\mid x)=\\pi(x), P(Y=0 \\mid x)=1-\\pi(x)$, 似然函数为:\n$$\r\\prod_{i=1}^{n}\\left[\\pi\\left(x_{i}\\right)\\right]^{y_{i}}\\left[1-\\pi\\left(x_{i}\\right)\\right]^{1-y_{i}}\r$$对数似然函数(求最大化):\n$$\rL(w)=\\sum_{i=1}^{n}\\left[y_{i} \\log \\pi\\left(x_{i}\\right)+\\left(1-y_{i}\\right) \\log \\left(1-\\pi\\left(x_{i}\\right)\\right)\\right]\r$$ $\\pi(x)=\\frac{e^{w^{T} x}}{1+e^{w^{T} x}}$ $w=\\left(w^{(1)}, w^{(2)}, \\cdots, w^{(d)}, b\\right)^{T} \\in \\mathbb{R}^{d+1}$ $x=\\left(x^{(1)}, x^{(2)}, \\cdots, x^{(d)}, 1\\right)^{T} \\in \\mathbb{R}^{d+1}$ 最后的优化问题（转化为最小化）：\n$$\r\\underset{w}{min}-\\frac{1}{n} \\sum_{i=1}^{n}\\left[y_{i} \\log \\pi_{w}\\left(x_{i}\\right)+\\left(1-y_{i}\\right) \\log \\left(1-\\pi_{w}\\left(x_{i}\\right)\\right)\\right]\r$$针对上述最小化问题，采用 Newton method, quasi-Newton method (BFGS, L-BFGS), conjugate gradient 或者梯度下降法 (引入超参数 $\\alpha$ ) , SGD 等等求都可以.\n之后就是求解.\n关联知识: 机器学习模型介绍 - 1. Logistic Regression\n5. 多项逻辑回归模型(Multinomial Logistic Regression; softmax regression) Softmax Regression 与 logistic regression 的联系\nsoftmax逻辑回归就是多分类的逻辑回归\n详细推导\n[ML] 逻辑回归与 Softmax 回归\n2. 损失函数 损失函数的目的: 度量真实值和预测值之间的距离 2.1. 交叉熵(cross entropy) 2.1.1. cross entropy 公式推导过程\n你真的理解交叉熵损失函数了吗？_哔哩哔哩_bilibili\n$$\r\\begin{aligned}\\operatorname{argmax} \\log \\prod_{\\mathrm{n}} \\prod_{\\mathrm{i}} \\hat{Y}_{i}^{Y_{i}}\u0026=\\operatorname{argmax} \\sum_{n} \\sum_{i} Y_{i} \\log \\hat{Y}_{i}\\\\\u0026=\\operatorname{argmin}-\\sum_{n} \\sum_{i} Y_{i} \\log \\hat{Y}_{i}\\end{aligned}\r$$ $n$表示训练样本数; $i$表示分类数量. 因为只要找到最值就可以了, 所有这里是额外加一个$log$的. 利用$log$似然函数的特性, 把连乘提到$log$左边变成连加; 加上负号求最小值. categorial_crossentropy函数和sparse_categorial_crossentropy函数:\n相同之处在于它们的 $y$ 都在 $(0,1)$ 之间 不同在于$Y_i$: 如果 $Y_i$ 的结果是one-hot encoded, 就是用categorical_crossentropy. 例(三分类问题): $[1,0,0] , [0,1,0], [0,0,1]$. 如果 $Y_i$ 的结果是整型, 使用sparse_categorical_crossentropy. 例(三分类问题): $[1], [2], [3]$. 2.1.2. Binary cross entropy 二元交叉熵是二分类问题中常用的一个Loss损失函数, 是用来评判一个二分类模型预测结果的好坏程度. 公式如下:\n$$\rloss=-\\frac{1}{N} \\sum_{i=1}^{N} \\left[y_{i} \\cdot \\log \\left(p\\left(y_{i}\\right)\\right)+\\left(1-y_{i}\\right) \\cdot \\log \\left(1-p\\left(y_{i}\\right)\\right)\\right]\r$$ 其中, $y_i$ 是二元标签 0 或者 1, $p(y_i)$ 是模型的预测值为标签 $y_i$ 的概率 之所以加负号是因为概率在$(0,1)$, 取log之后是负的, 用负数表示信息不符合我们的认知逻辑，所以取负让结果为正. 就是说模型预测值越接近于gt值, loss越小; 越远离gt值, loss越大. 对于标签 $y$ 为 1 的情况, 如果预测值 $p(y)$ 趋近于 1, 那么损失函数的值应当趋近于 0. 反之, 如果此时预测值 $p(y)$ 趋近于 0, 那么损失函数的值为 $\\infty$. 如下图所示.\n对于标签 $y$ 为 0 的情况如下\n2.2. Softmax (归一化指数函数) $f_{i}(\\vec{x})=\\frac{e^{x_{i}}}{\\sum_{j=1}^{J} e^{x_{j}}} \\quad \\text { for } i=1, \\ldots, J$\n将原本的输出映射到区间$(0,1)$之间, 所有的值和为1\n算是一种概率\n好处:\n求导方便\n好结果和坏结果更显著\n梯度下降时更新梯度, 由于网络末尾需要softmax函数计算结果$a$.\n交叉熵函数的简单形式:\n$\\text { Loss }=-\\sum_{i} y_{i} \\ln a_{i}$\n正向和反向求导时就很方便\nSoftmax 函数的特点和作用是什么？\n损失函数推导过程\n逻辑回归（Logistic Regression）（二）\n3. 过拟合问题 当讨论到模型的过拟合问题时, 不妨对算法的期望泛化误差进行讨论。我们已经知道: 泛化误差可 以分解为 bias, variance, noise 之和。\n偏差 (bias) 衡量模型的期望预测与真实结果的偏离程度（模型的拟合能力）；方差 (variance) 衡量了同样大小的训练集的变动所导致的学习性能的变化, 即刻画了数据扰动 （数据变化对模型预测能力）所造成的影响（或者理解为在测试集上的表现）。噪声表达了在 当前任务上任何学习算法所能达到的期望泛化误差的下界，即刻画了学习问题本身的难度.\n过拟合: low bias, high variance 欠拟合: high bias, low varience 3.1. 一般处理方法 减少特征的数量: 人工篮选特征、嵌入式选择 正则化：保持所有特征当时减小或者增大特征参数 $w^{(i)}$, 使得所有变量对最终的预测只贡献一 点比例 这里一般采用L1或L2正则化：(损失函数推导见拓展部分)\n$$\r\\begin{gathered}\\min _{w, c}\\|w||_1 + C \\sum_{i=1}^n \\log \\left(\\exp \\left(-y_i\\left(x_i^T w+c\\right)\\right)+1\\right) \\\\\\min _{w, c} \\frac{1}{2} w^T w + C \\sum_{i=1}^n \\log \\left(\\exp \\left(-y_i\\left(x_i^T w+c\\right)\\right)+1\\right)\\end{gathered}\r$$ 4. Dropout 以一定的概率随机地“临时丢弃”一部分神经元节点. 优点, 解决过拟合的原因: 训练时: 减小网络的大小 减少神经元之间复杂的共适应关系(co-adaptations), 这样权值的更新不再依赖于有固定关系的隐含节点的共同作用，阻止了某些特征仅仅在某个特定特征下才有效果的情况. 人工神经网络的一个核心思想是分布式表征(Distributed Representation), 当我们表述一个概念的时候, 神经元和概念之间不是一对一对应映射(map)存储的，它们之间的关系是多对多。当一个节点发生故障的时候, 其他对应的节点能表达概念. 每次迭代所得到的不同结构的神经网络, 比只在单个健全网络上进行特征学习, 其泛化能力来得更加健壮. 测试时: 将参与学习的节点和那些被隐藏的节点以概率p加权求和，综合计算得到网络的输出。(算是一种集成学习(Ensemble Learning)) 训练阶段每个神经元以概率p被保留 测试阶段每个神经元都激活, 权重W要乘以p, 输出pW 因为输入将被dropout的神经元的值为$w$, 训练时dropout之后的期望是$E=pw+(1-p)*0$, 在预测阶段总是激活, 所以为了保持相同的输出期望, 所以$w \\to pw$. 5. 目标函数, 代价函数, 损失函数 代价函数: 代价函数=损失函数, loss function越小, 标识模型对数据的拟合越好 目标函数: 在代价函数的最优化经验风险的基础上加入优化结构风险策略(eg: L2正则化)的函数表达式. 不加结构风险策略时, 目标函数就与代价函数一致了. 6. 损失函数的使用场景 7. k-fold交叉验证 Method of Stacking (左半边) 训练时每个model都用k-fold cross validation训练得到k个模型，测试时每个model的k个模型预测测试集得到的结果取平均 (右半边) 训练时使用level2 model训练 验证集的合集和训练集，测试时使用level2 model来预测 ","permalink":"https://sqf.icu/article/509be69c-9b65-42dc-9872-dba6bf1aa5ee/","summary":"\u003ch1 id=\"1-激活函数\"\u003e1. 激活函数\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"https://www.ucloud.cn/yun/20462.html\"\u003e深度学习常见激活函数介绍及代码实现 - UCloud云社区\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"1-relu\"\u003e1. ReLU\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003e线性整流函数(\u003cstrong\u003eLinear rectification function), 又称\u003c/strong\u003e修正线性单元,\u003c/strong\u003e 是一种\u003ca href=\"https://baike.baidu.com/item/%E4%BA%BA%E5%B7%A5%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/382460?fromModule=lemma_inlink\"\u003e人工神经网络\u003c/a\u003e中常用的激活函数(activation function), 通常指代以\u003ca href=\"https://baike.baidu.com/item/%E6%96%9C%E5%9D%A1%E5%87%BD%E6%95%B0?fromModule=lemma_inlink\"\u003e斜坡函数\u003c/a\u003e及其变种为代表的\u003ca href=\"https://baike.baidu.com/item/%E9%9D%9E%E7%BA%BF%E6%80%A7%E5%87%BD%E6%95%B0/16029251?fromModule=lemma_inlink\"\u003e非线性函数\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/a50df74d5ca86628c7536585.png\"\u003e\u003c/p\u003e\n$$\r\nf(x)=max(0,x)\r\n$$\u003ch2 id=\"2-sigmoid\"\u003e2. Sigmoid\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e缺点\u003c/p\u003e\n\u003cp\u003esigmoid有一个梯度消失的问题, $|z|\u003e4$(变量值很大或很小)的时候, 梯度就快消失了(趋近于0).\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"深度学习训练用激活损失函数和技巧"},{"content":"1. 汉诺塔问题 问题: 将汉诺塔从A移动到C, 小圆盘必须在大圆盘上面.\n分析:\n可以将最底下的一块圆盘作为独立个体, 上面的所有圆盘作为另一个个体. 则整个汉诺塔的移动步骤如下.\n算法实现:\ndef hanoi(n, a, b, c): if n \u0026gt; 0: hanoi(n-1, a, c, b) print(f\u0026#34;move {a} to {c}\u0026#34;) hanoi(n-1, b, a, c) hanoi(3, \u0026#39;a\u0026#39;,\u0026#39;b\u0026#39;,\u0026#39;c\u0026#39;) 2. 查找 2.1. 顺序查找 def linear_search(li, val): \u0026#34;\u0026#34;\u0026#34;顺序查找 Args: li (_type_): _description_ val (_type_): _description_ Returns: _type_: _description_ \u0026#34;\u0026#34;\u0026#34; for index, value in enumerate(li): if val == value: return index return None 2.2. 二分查找 def binary_search(li, val): \u0026#34;\u0026#34;\u0026#34;二分查找, 必须是顺序排列的列表 Args: li (_type_): _description_ val (_type_): _description_ Returns: _type_: _description_ \u0026#34;\u0026#34;\u0026#34; left = 0 right = len(li) - 1 while right \u0026gt;= left and right \u0026lt; len(li): print(\u0026#34;right: \u0026#34;, right) print(\u0026#34;left: \u0026#34;, left) mid = (right + left) // 2 print(\u0026#34;mid: \u0026#34;, mid) if li[mid] == val: return mid elif li[mid] \u0026gt; val: right = mid - 1 else: left = mid + 1 return None 3. 排序算法 1.1. 简单 1.1.1. 冒泡排序 像气泡向上冒一样, 想象列表竖直. 第0轮: 从列表i=0位置开始. 如果最底部(i=0)的数字A比上一个数B大, 就互换位置. 再将A与上一个数C对比, 以此类推. 第1轮: 从列表i=1位置开始. 第len(list)-1轮: 从列表i=len(list)-1位置开始. def bubble_sort(random_list): \u0026#34;\u0026#34;\u0026#34;冒泡排序(升序排列). 遍历列表, 如果当前数字比它之后的数字大, 就对换位置. 时间复杂度: O(n^2) Args: random_list (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; for i in range(len(random_list)-1): # 选中一个数字(不包括最后一个数字) print(random_list) break_flag = True # 如果全程没有更新, 则排序已经完成, 终止循环 for j in range(len(random_list)-i-1): # 挨个遍历, 但是最后一个数不取到 if random_list[j] \u0026gt; random_list[j+1]: # 选中数大就对换位置 random_list[j], random_list[j+1] = random_list[j+1], random_list[j] break_flag = False if break_flag: break return random_list 1.1.2. 选择排序 遍历找最小 def select_sort_simple(random_list): \u0026#34;\u0026#34;\u0026#34;选择排序v1(升序排列). 只遍历一次, 将最小的数加入新的list 时间复杂度: O(n) 空间复杂度: O(n) Args: random_list (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; sort_list = [] while len(random_list) != 0: min_value = min(random_list) sort_list.append(min_value) random_list.remove(min_value) return sort_list def select_sort(random_list): \u0026#34;\u0026#34;\u0026#34;选择排序v2(升序排列). 每次遍历都将最小的数放到遍历区最左端 时间复杂度: O(n^2) 空间复杂度: O(1) Args: random_list (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; for i in range(len(random_list)-1): for j in range(i, len(random_list)): if random_list[i] \u0026gt; random_list[j]: random_list[i], random_list[j] = random_list[j], random_list[i] return random_list 1.1.3. 插入排序 从左边开始遍历, 像打牌时的理牌一样操作.\n提取遍历到的数, 将比它大的数各右移一格, 这个数插入空档中.\ndef insert_sort(random_list): \u0026#34;\u0026#34;\u0026#34; 插入排序 时间复杂度: O(n^2) 空间复杂度: O(1) Args: random_list (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; for i in range(1, len(random_list)): tmp = random_list[i] j = i - 1 while j \u0026gt;= 0 and tmp \u0026lt; random_list[j]: random_list[j+1] = random_list[j] j -= 1 random_list[j+1] = tmp return random_list 1.2. 困难 1.2.1. 快速排序 缺点: 递归的层数是有限制的, windows下限制为998. 修改限制后能到达3929层左右. 无法处理更长的列表\n时间复杂度推导\n每一层的partition各自的时间复杂度是O(n), 如第2层每个partition的时间复杂度都是O(8). 一共有logn层 得出总共的时间复杂度为O(nlogn) 代码\nclass QuickSort(): \u0026#34;\u0026#34;\u0026#34; 快速排序 1. 取元素p(列表第一个元素)使元素p归位 2. 列表分为两部分, p左边都比p小, 右边都比p大 3. 递归完成排序 时间复杂度: O(nlogn) 空间复杂度: O(1) Args: input_list (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; def __init__(self, input_list): self.input_list = input_list def partition(self, left, right): \u0026#34;\u0026#34;\u0026#34; 取index=left的数A(额外保存), 则list[left]留出空位 从index=right的数B开始向左 if B\u0026gt;=A: B不动, left指针不动, right指针开始向左移动 if B\u0026lt;A: B移动到li[left]位置, right指针暂停left指针开始向右移动 if left==right: return left (找到中间值) Args: left (_type_): _description_ right (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; keep_mid = self.input_list[left] while left \u0026lt; right: while left \u0026lt; right and self.input_list[right] \u0026gt;= keep_mid: right -= 1 self.input_list[left] = self.input_list[right] while left \u0026lt; right and self.input_list[left] \u0026lt;= keep_mid: left += 1 self.input_list[right] = self.input_list[left] self.input_list[left] = keep_mid return left def quick_sort(self, left, right): if left \u0026lt; right: mid = self.partition(left, right) # 算出下标的位置 self.quick_sort(left, mid-1) self.quick_sort(mid+1, right) return self.input_list 1.2.2. 堆排序 树与二叉树\n概念 根节点, 叶子节点 树的深度 树的度（同一深度最多的子节点个数） 孩子节点和父节点 子树 树是一种数据结构 树是由n个节点组成的集合 if n=0, 这是一颗空树 if n\u0026gt;0, 存在一个节点作为树的根节点, 其他节点可以分为m个集合, 每个集合本身又是一棵树 二叉树的顺序存储方式 二叉树的每层节点个数 $2^0\\ 2^1\\ 2^2\\ 2^3$ 父节点与左孩子节点的编号下标关系 $i\\rightarrow2i+1$ 父节点与右孩子节点的编号下标关系 $i\\rightarrow2i+2$ 从孩子节点推断父节点的编号下标 $j\\rightarrow(i-1)//2$ 大根堆满足: 完全二叉树 任一节点都比其孩子节点大 小根堆满足: 完全二叉树 任一节点都比其孩子节点小 堆的向下取数\n从父节点推算子节点\nchild_l = 2 * root + 1 child_r = 2 * root + 2 从最后一个非子节点开始(需要推断父节点位置)\nif len(list) = n last node = n-1 if child node = n-1 parent node = ((n-1)-1)//2 = n//2-1 堆排序\n建立堆\n从最后一个叶子节点开始向上调整\n得到对顶元素, 为最大元素\n去掉堆顶, 将堆最后一个元素放到堆顶, 此时可通过一次调整重新使堆有序(就是挨个出数)\n不使用额外空间: 去掉顶部元素9的时候, 将9移动到3的位置, 将堆的结尾指针移动到4. 堆顶元素为第二大元素\n重复步骤3, 直到堆变空\n实现堆排序代码\nclass HeapSort(): def __init__(self, input_list): self.input_list = input_list @staticmethod def sift(list_, low, high): \u0026#34;\u0026#34;\u0026#34; 向下调整 时间复杂度: O(logn) 空间复杂度: O(1) Args: low (_type_): 堆的根节点的位置 high (_type_): 堆的最后一个元素的位置 IS_MAX_HEAP (_type_): 是否是大根堆, 默认为True \u0026#34;\u0026#34;\u0026#34; i = low # i初始转态指向根节点 j = 2*i+1 # j初始状态是i的左孩子 tmp = list_[low] # 存放根节点 while j \u0026lt;= high: # 说明j的位置有数(在列表内) # 使j指向大的那个孩子节点 # j右边有数, 并且j右边的数大于j指向的数(大根堆) if j+1 \u0026lt;= high and list_[j+1] \u0026gt; list_[j]: j += 1 # j指向右孩子 # 如果当前j指向的位置的数大于根节点, 就替换掉根节点(大根堆) if list_[j] \u0026gt; tmp: list_[i] = list_[j] i = j # 根节点向下一层(孩子节点作为根节点) j = 2*i+1 else: # 如果j指向的数小于tmp, tmp放到某个根节点(tmp下面的子节点小于tmp但上面的根节点大于tmp) list_[i] = tmp break else: # 如果j走出了列表的范围(根节点此时指向最后一层, j指向最后一层的下一层), 循环终止, tmp放到i指向的位置 list_[i] = tmp def heap_sort(self): \u0026#34;\u0026#34;\u0026#34; 时间复杂度: O(nlogn) 空间复杂度: O(1) Returns: _type_: _description_ \u0026#34;\u0026#34;\u0026#34; len_list = len(self.input_list) # 构造堆 # 循环: 从最后一个父节点开始都过来遍历 # 最后一个孩子节点为n-1, n为列表长度, 则最后一个父节点为n//2-1 # i表示建立堆的时候, 调整的部分的根的下标 for i in range(len_list//2-1, -1, -1): self.sift(self.input_list, i, len_list-1) print(\u0026#34;create heap\\n\u0026#34;, self.input_list) # 开始排序 # i表示当前堆的最后一个元素位置 for i in range(len_list-1, -1, -1): self.input_list[0], self.input_list[i] = self.input_list[i], self.input_list[0] self.sift(self.input_list, 0, i-1) # i-1, 更新堆的最后一个元素位置 return self.input_list 使用python内置库, 进行堆排序\ndef heap_sort_py(random_list): \u0026#34;\u0026#34;\u0026#34;使用python内置库, 进行堆排序 Args: random_list (_type_): _description_ Returns: _type_: _description_ \u0026#34;\u0026#34;\u0026#34; heapq.heapify(random_list) # 建立堆 res_list = [] for _ in range(len(random_list)): res_list.append(heapq.heappop(random_list)) return random_list 堆排序topK问题\n原理:\n在列表中取k个元素, 用这些元素建立一个小根堆(堆顶是堆里最小的). 遍历剩下的列表, 元素小于堆顶的忽略, 大于堆顶的放在堆顶, 对堆进行调整. 性能\n时间复杂度: O(nlogk) 代码实现\nclass HeapSortTopK(): def __init__(self, input_list): self.input_list = input_list @staticmethod def sift(list_, low, high): \u0026#34;\u0026#34;\u0026#34; 向下调整 时间复杂度: O(logn) 空间复杂度: O(1) Args: low (_type_): 堆的根节点的位置 high (_type_): 堆的最后一个元素的位置 \u0026#34;\u0026#34;\u0026#34; i = low # i初始转态指向根节点 j = 2*i+1 # j初始状态是i的左孩子 tmp = list_[low] # 存放根节点 while j \u0026lt;= high: # 说明j的位置有数(在列表内) # 使j指向大的那个孩子节点 # j右边有数, 并且j右边的数大于j指向的数(大根堆) if j+1 \u0026lt;= high and list_[j+1] \u0026lt; list_[j]: j += 1 # j指向右孩子 # 如果当前j指向的位置的数小于根节点, 就替换掉根节点(大根堆) if list_[j] \u0026lt; tmp: list_[i] = list_[j] i = j # 根节点向下一层(孩子节点作为根节点) j = 2*i+1 else: break list_[i] = tmp def topk(self, k): \u0026#34;\u0026#34;\u0026#34; 只排序列表中前k个大的数(不重复). 原理: - 在列表中取k个元素, 用这些元素建立一个小根堆(堆顶是堆里最小的). - 遍历剩下的列表, 元素小于堆顶的忽略, 大于堆顶的放在堆顶, 对堆进行调整. - 因为是小根堆, 所以堆顶的元素最小 时间复杂度: O(nlogk) 空间复杂度: O(1) Args: k (_type_): _description_ Returns: _type_: _description_ \u0026#34;\u0026#34;\u0026#34; # 取k个元素建一个小根堆 heap = self.input_list[:k] for i in range(len(heap)//2-1, -1, -1): self.sift(heap, i, len(heap)-1) print(heap) # 遍历剩下的列表 for i in range(k, len(self.input_list)): # 剩下的元素大于堆顶的, 替换堆顶元素 if self.input_list[i] \u0026gt; heap[0]: # 注意, 这里用的是大于不是大于等于, 忽略了重复的数字 heap[0] = self.input_list[i] self.sift(heap, 0, k-1) # 进行一波堆整理 print(self.input_list[i]) print(heap) # 排序结束, 出数 for i in range(k-1, -1, -1): # 替换堆顶和最后一个父节点 heap[0], heap[i] = heap[i], heap[0] self.sift(heap, 0, i-1) # 进行一波堆整理 # print(heap) return heap 1.2.3. 归并排序 原理\n分解: 将列表不断一分为二, 直到只剩一个元素 合并: 将有序列表归并, 直到合成一个列表 代码\nclass MergeSort(): def __init__(self, input_list) -\u0026gt; None: self.input_list = input_list def merge(self, low, mid, high): \u0026#34;\u0026#34;\u0026#34; 合并列表 这个函数存在要求, 前一半和后一半必须都是有序的(都是从小到大排列) 从小到大排序 时间复杂度: O(nlogn) 空间复杂度: O(n) Args: low (_type_): 当前列表最左端 mid (_type_): 当前列表中间 high (_type_): 当前列表最右端 \u0026#34;\u0026#34;\u0026#34; i = low # 左半部分指针位置 j = mid + 1 # 右半部分指针位置 tmp_list = [] while i \u0026lt;= mid and j \u0026lt;= high: if self.input_list[i] \u0026lt; self.input_list[j]: tmp_list.append(self.input_list[i]) i += 1 else: tmp_list.append(self.input_list[j]) j += 1 # 循环结束之后, 剩下的一边必定是顺序且比tmp_list中最大的元素大 while i \u0026lt;= mid: # 如果i还剩下 tmp_list.append(self.input_list[i]) i += 1 while j \u0026lt;= high: tmp_list.append(self.input_list[j]) j += 1 self.input_list[low: high+1] = tmp_list def split(self, low, high): \u0026#34;\u0026#34;\u0026#34; 递归将列表分解, 直到只有两端列表各只有1个元素 这两个元素开始合并 Args: low (_type_): _description_ high (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; if low \u0026lt; high: # 至少需要两个元素 mid = (low + high) // 2 # 递归分解 self.split(0, mid) self.split(mid+1, high) # 两个有序列表合并 self.merge(low, mid, high) 4. 栈 原理:\n只能从一端进出 后进先出 操作:\n进栈: push 出栈: pop 取栈顶: gettop 栈的实现\nclass Stack(): def __init__(self) -\u0026gt; None: self.stack = [] def push(self, element): self.stack.append(element) def pop(self): return self.stack.pop() def get_top(self): if len(self.stack) \u0026gt; 0: return self.stack[-1] else: return None def is_empty(self): return len(self.stack) == 0 def show(self): return self.stack 括号匹配问题\ndef bracket_match(li): \u0026#34;\u0026#34;\u0026#34;匹配完整形式的括号列表 Args: li (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; # 建立字典 b_dict = {\u0026#39;[\u0026#39;: \u0026#39;]\u0026#39;, \u0026#39;(\u0026#39;: \u0026#39;)\u0026#39;, \u0026#39;{\u0026#39;: \u0026#39;}\u0026#39;} stack = Stack() for ele in li: if ele in b_dict: # 元素为左括号 stack.push(ele) else: # 元素为右括号 if stack.is_empty(): return False elif b_dict[stack.get_top()] == ele: stack.pop() else: return False print(stack.show()) # 全部遍历完之后, 如果是一个空列表, 则括号列表是符合规定的 return stack.is_empty() 5. 队列 原理\n从队尾(rear)进, 从队头(front)出 先进先出 环形队列\n代码\nclass Queue: def __init__(self, size=100) -\u0026gt; None: self.size = size self.queue = [x for x in range(size)] self.rear = 0 # rear指向队尾的位置 self.front = 0 # front指向队首的前一个位置 def push(self, element): if not self.is_filled(): self.rear = (self.rear + 1) % self.size self.queue[self.rear] = element else: raise IndexError(\u0026#39;queue is filled\u0026#39;) def pop(self): if not self.is_empty(): self.front = (self.front + 1) % self.size return self.queue[self.front] else: raise IndexError(\u0026#39;queue is empty\u0026#39;) def is_empty(self): return self.rear == self.front def is_filled(self): return (self.rear + 1) % self.size == self.front def main(): q = Queue(5) for i in range(4): q.push(i) for i in range(4): print(q.pop()) 双向队列\n队首队尾两端都支持双向队列 q = deque([1, 2, 3], 5) # 列表, 队列尺寸 q.append(4) q.append(5) q.append(6) print(q) for _ in range(5): print(q.popleft()) ########### deque([2, 3, 4, 5, 6], maxlen=5) 2 3 4 5 6 6. 栈和队列的应用 - 迷宫问题 栈 深度优先算法(DFS)\n使用回溯法 从一个节点开始, 任意找下一个能走的点, 当找不到能走的点时, 退回上一个点寻找是否有其他方向的点 使用栈存储当前路径 代码实现\ndef maze_path_dfs(maze, x1, y1, x2, y2): \u0026#34;\u0026#34;\u0026#34;使用深度优先算法走迷宫 Args: x1 (_type_): 起点的x坐标 y1 (_type_): 起点的y坐标 x2 (_type_): 终点的x坐标 y2 (_type_): 终点的y坐标 \u0026#34;\u0026#34;\u0026#34; # 在迷宫中行走时用的四个方向 dirs_path = [ lambda x, y: (x+1, y), lambda x, y: (x-1, y), lambda x, y: (x, y+1), lambda x, y: (x, y-1), ] stack = [] stack.append((x1, y1)) # 给栈添加起点 while len(stack) \u0026gt; 0: # 栈不为空的时候 cur_node = stack[-1] if cur_node == (x2, y2): print(f\u0026#34;Find route: {stack}\u0026#34;) return True for dir in dirs_path: next_node = dir(cur_node[0], cur_node[1]) if maze[next_node[0]][next_node[1]] == 0: # 说明下一步是通的 stack.append(next_node) maze[next_node[0]][next_node[1]] = 2 # 记录走过的坐标 break # 深度优先, 所以有路就直接跳出循环, 走下一步 else: # 这里的else在for循环结束为止没有break的情况下触发 # 发现当前位置没有路时 maze[cur_node[0]][cur_node[1]] = 2 # 当前位置堵上 stack.pop() # 回退一格 return False 队列 广度优先算法(BFS)\n从一个节点开始, 寻找所有接下来能继续走的点, 继续不断寻找, 直到找到出口 使用队列存储当前正在考虑的节点 代码实现\ndef maze_path_bfs(maze, dirs_path, x1, y1, x2, y2): \u0026#34;\u0026#34;\u0026#34;使用广度优先算法走迷宫 Args: maze (_type_): _description_ dirs_path (_type_): _description_ x1 (_type_): _description_ y1 (_type_): _description_ x2 (_type_): _description_ y2 (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; from collections import deque queue = deque() queue.append((x1, y1, -1)) # 向队列的尾部(rear)加入初始位置 save_path_list = [] while len(queue) \u0026gt; 0: # 如果队列长度为0, 说明起始位置周围都是墙壁 cur_node = queue.popleft() # 当前的位置是队列的头部(left) if cur_node[:2] == (x2, y2): print(save_path_list) print(route_print(save_path_list)) return True # 这个list在for循环外, 所以它的长度可以表示dfs的当前层数 save_path_list.append(cur_node) for dir in dirs_path: next_node = dir(cur_node[0], cur_node[1]) if maze[next_node[0]][next_node[1]] == 0: # 下一个位置是空的 queue.append( (next_node[0], next_node[1], len(save_path_list) - 1)) maze[next_node[0]][next_node[1]] = 2 else: return False 7. 链表 链表是由一系列节点组成的元素集合\n链表的优点\n链表在插入删除操作上快 链表的内存可以灵活分配, 没有栈和队列的容量限制 链表这种链式存储的数据结构对树和图的结构有很大的启发性 7.1. 创建单链表 头插法 头部插入新节点\n节点中, item保存元素, next保存下一个节点的内存地址 从1开始, head移动到下一个节点 尾插法 尾部插入新节点\n节点中, item保存元素, next保存下一个节点的内存地址 从1开始, head不动, tail移动到下一个节点 代码\nclass Node: def __init__(self, item) -\u0026gt; None: self.item = item self.next = None def create_link_list_head(li): \u0026#34;\u0026#34;\u0026#34;头插法创建链表 Args: li (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; head = Node(li[0]) for ele in li[1:]: node = Node(ele) node.next = head # 新节点next需要指向原始节点, 防止链表断裂 head = node # 然后让新节点代替原始节点, 开始下一轮循环 return head def create_link_list_tail(li): \u0026#34;\u0026#34;\u0026#34;尾插法创建链表 Args: li (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; tail = head = Node(li[0]) for ele in li[1:]: node = Node(ele) tail.next = node # 此时, tail是原始节点, node是新节点 -\u0026gt; tail.next指向新节点 tail = node # 需要把新节点作为对象赋值到tail上 return head def print_link(lk): while lk: print(lk.item, end=\u0026#39; \u0026#39;) lk = lk.next link_list = [1, 2, 3, 4, 5] lk = create_link_list_head(link_list) print_link(lk) lk = create_link_list_tail(link_list) print_link(lk) 7.2. 单链表插入 链表节点的插入. 将节点p插入链表的当前节点的下一个位置\n将节点p的next指向当前节点的next位置 将当前节点的next指向节点p 7.3. 单链表删除 删除链表中的节点p. 需要将该节点的前一个节点作为当前节点.\n将节点4赋值为p 当前节点的next指向下下个节点 删除节点p (回收内存) 7.4. 创建双向链表 单链表只能从头向尾操作, 但是双链表可以做双向操作\n7.5. 双向链表插入 7.6. 双向链表删除 8. 二叉树 8.1. 创建二叉树 代码\nclass BiTreeNode: def __init__(self, data) -\u0026gt; None: self.data = data self.lchild = None self.rchild = None def main(): a = BiTreeNode(\u0026#34;a\u0026#34;) b = BiTreeNode(\u0026#34;b\u0026#34;) c = BiTreeNode(\u0026#34;c\u0026#34;) d = BiTreeNode(\u0026#34;d\u0026#34;) e = BiTreeNode(\u0026#34;e\u0026#34;) f = BiTreeNode(\u0026#34;f\u0026#34;) g = BiTreeNode(\u0026#34;g\u0026#34;) e.lchild = a e.rchild = g a.rchild = c c.lchild = b c.rchild = d g.rchild = f root = e print(root.lchild.rchild.data) ################################# # 结果为: c 8.2. 二叉树的遍历 根和子节点的遍历顺序都是root → left →right\n前序遍历: 根写在左边\n中序遍历: 根写在中间\n后序遍历: 根写在右边\n层序遍历: 逐行扫描\n算法实现需要使用队列, 先进先出. eg: E入队 E出队AG入队 A出队C入队, G出队F入队 C出队BD入队, F出队 BD出队 4种二叉树遍历代码\nclass BiTreeNode: def __init__(self, data) -\u0026gt; None: self.data = data self.lchild = None self.rchild = None def pre_order(self, root): \u0026#34;\u0026#34;\u0026#34;前序遍历 Args: root (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; if root: print(root.data, end=\u0026#39; \u0026#39;) self.pre_order(root.lchild) self.pre_order(root.rchild) def in_order(self, root): \u0026#34;\u0026#34;\u0026#34;中序遍历 Args: root (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; if root: self.in_order(root.lchild) print(root.data, end=\u0026#39; \u0026#39;) self.in_order(root.rchild) def post_order(self, root): \u0026#34;\u0026#34;\u0026#34;后序遍历 Args: root (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; if root: self.post_order(root.lchild) self.post_order(root.rchild) print(root.data, end=\u0026#39; \u0026#39;) def level_order(self, root): \u0026#34;\u0026#34;\u0026#34;层序遍历 Args: root (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; queue = deque() queue.append(root) # 根节点入队 while len(queue) \u0026gt; 0: node = queue.popleft() # 根节点出队 print(node.data, end=\u0026#39; \u0026#39;) if node.lchild: queue.append(node.lchild) if node.rchild: queue.append(node.rchild) 8.3. 二叉搜索树 二叉搜索树是一颗二叉树且满足性质:\n设$x$是二叉树的一个节点.\n如果$y$是$x$左子树的一个节点, 那么$y.key \\le x.key$\n如果$y$是$x$右子树的一个节点, 那么$y.key \\ge x.key$\n各节点数值都不相等.\n插入操作\n对比当前节点, 如果当前节点比插入数值小, 就对比当前节点的左孩子, 反之右孩子\n如果没有孩子, 就插入\n代码\nfrom collections import deque class Node(): def __init__(self, data) -\u0026gt; None: self.data = data self.lchild = None self.rchild = None self.parent = None class BST(): def __init__(self, li, do_rec=False) -\u0026gt; None: self.root = None if do_rec: for val in li: self.root = self.insert(self.root, val) else: for val in li: self.insert_no_rec(val) def insert(self, node, val): \u0026#34;\u0026#34;\u0026#34;使用递归实现插入二叉搜索树 Args: node (_type_): 当前节点 val (_type_): 需要插入的数值 \u0026#34;\u0026#34;\u0026#34; if not node: node = Node(val) elif val \u0026lt; node.data: node.lchild = self.insert(node.lchild, val) node.lchild.parent = node elif val \u0026gt; node.data: node.rchild = self.insert(node.rchild, val) node.rchild.parent = node return node def insert_no_rec(self, val): p = self.root if not p: self.root = Node(val) return while True: if val \u0026lt; p.data: if p.lchild: p = p.lchild else: # 左孩子的位置有空时 p.lchild = Node(val) p.lchild.parent = p return elif val \u0026gt; p.data: if p.rchild: p = p.rchild else: # 右孩子的位置有空时 p.rchild = Node(val) p.rchild.parent = p return else: return def in_order(self, root): \u0026#34;\u0026#34;\u0026#34;中序遍历 Args: root (_type_): _description_ \u0026#34;\u0026#34;\u0026#34; if root: self.in_order(root.lchild) print(root.data, end=\u0026#39; \u0026#39;) self.in_order(root.rchild) list_ = [4, 6, 7, 9, 2, 1, 3, 5, 8] print(\u0026#39;\\nrec\u0026#39;) tree = BST(list_, True) tree.in_order(tree.root) print(\u0026#39;\\nno rec\u0026#39;) tree_rec = BST(list_, False) tree_rec.in_order(tree_rec.root) 查询操作\n代码\ndef query(self, node, val): if not node: # 如果节点为空, 说明没找到, 返回None return None if node.data \u0026lt; val: return self.query(node.rchild, val) elif node.data \u0026gt; val: return self.query(node.lchild, val) else: return node def query_no_rec(self, val): p = self.root if not p: return None while p: if p.data \u0026lt; val: p = p.rchild elif p.data \u0026gt; val: p = p.lchild else: return p return None target = 2 print(\u0026#39;query rec\u0026#39;) print(tree.query(tree.root, target).data) print(\u0026#39;query not rec\u0026#39;) print(tree.query_no_rec(target).data) 删除操作\n目标是叶子节点: 直接删除\n目标只有一个孩子: 将此节点的父亲与孩子相连, 删除目标\n目标有两个孩子: 将其右子树的最小节点n的值替换目标m的值，并删除n\n二叉树 层序遍历\n8.4. 深度优先搜索和广度优先搜索模板 BFS\nBFS使用队列，把每个还没有搜索到的点依次放入队列，然后再弹出队列的头部元素当做当前遍历点。 如果不需要确定当前遍历到了哪一层，BFS模板如下:\nwhile queue 不空： cur = queue.pop() for 节点 in cur的所有相邻节点： if 该节点有效且未访问过： queue.push(该节点) 如果要确定当前遍历到了哪一层，BFS模板如下。\nlevel表示当前遍历到二叉树中的哪一层了，也可以理解为在一个图中，现在已经走了多少步了。 size表示在当前遍历层有多少个元素，也就是队列中的元素数，我们把这些元素一次性遍历完，即把当前层的所有元素都向外走了一步。 level = 0 while queue 不空： size = queue.size() while (size --) { cur = queue.pop() for 节点 in cur的所有相邻节点： if 该节点有效且未被访问过： queue.push(该节点) } level ++; DFS\n递归 9. 动态规划 01背包问题\nclass Solution: def knapsack_01(self, w_list: List[int], v_list: List[int], c: int) -\u0026gt; int: \u0026#34;\u0026#34;\u0026#34; 建立价值和重量表 不放i-1: dp[i][j] = dp[i-1][w] 放i-1: dp[i][j] = dp[i-1][j-w[i]] + v[i] 在“上一个结果价值”和“把当前第i个物品装入背包里所得到价值”二者里选价值较大的 :param w: :param v: :param c: :return: \u0026#34;\u0026#34;\u0026#34; dp = [[0 for _ in range(c+1)] for _ in range(len(w_list))] for i in range(1, len(w_list)): # 跳过0 for j in range(1, c+1): if w_list[i] \u0026gt; j: # 外层循环i,如果第i个物品质量大于当前背包容量 dp[i][j] = dp[i - 1][j] else: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w_list[i]] + v_list[i]) return dp[-1][-1] \u0026#34;\u0026#34;\u0026#34; 优化, 去掉一维 \u0026#34;\u0026#34;\u0026#34; dp = [0 for _ in range(c+1)] for i in range(1, len(w_list)): for j in range(c, w_list[i]-1, -1): dp[j] = max(dp[j], dp[j-w_list[i]]+v_list[i]) return dp[-1] if __name__ == \u0026#39;__main__\u0026#39;: v = [0, 60, 100, 120] w = [0, 10, 20, 30] c = 50 # 最重不超过50 s = Solution() print(s.knapsack_01(w, v, c)) 完全背包问题\n多重背包问题\n混合背包问题\n二维费用背包问题\n分组背包问题\n背包问题求方案数\n求背包问题的方案\n有依赖的背包问题\n","permalink":"https://sqf.icu/article/0cc434c5-b9f7-40c2-b01b-b2220af19ae6/","summary":"\u003ch1 id=\"1-汉诺塔问题\"\u003e1. \u003ca href=\"https://www.bilibili.com/video/BV1uA411N7c5?p=6\u0026amp;vd_source=0847973121d4fdd8364284ef7353ef09\"\u003e汉诺塔问题\u003c/a\u003e\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e问题: 将汉诺塔从A移动到C, 小圆盘必须在大圆盘上面.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/549af7700cd9478a13ba37af.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e分析:\u003c/p\u003e\n\u003cp\u003e可以将最底下的一块圆盘作为独立个体, 上面的所有圆盘作为另一个个体. 则整个汉诺塔的移动步骤如下.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/6e90b2a31f1ab41dd52e8ce8.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"数据结构与算法"},{"content":"1. Logistic Regression 模型介绍\n逻辑回归 (Logistic regression) 是分类模型, 常用于二分类.\n逻辑回归的本质是: 假设数据服从分布, 然后使用极大似然估计做参数的估计\nLogistic 分布是一种连续概率分布\n分布函数: $$\rF(x)=P(X \\leq x)=\\frac{1}{1+e^{-(x-\\mu) / \\gamma}}\r$$ 密度函数:\n$$\rf(x)=F^{\\prime}(X \\leq x)=\\frac{e^{-(x-\\mu) / \\gamma}}{\\gamma\\left(1+e^{-(x-\\mu) / \\gamma}\\right)^{2}}\r$$ $\\mu$: 未知参数; $\\gamma$: 形状参数. logistic 分布的形状与正态分布的形状相似, 但是Logistic 分布的尾部更长, 所以我们可以使用Logistic 分布来建模比正态分布具有更长尾部和更高波峰的数据分布. Sigmoid 函数就是Logistic 的分布函数在$\\mu=0, \\gamma=1$的特殊形式. Logistic 回归\nLogistic 回归主要用于分类问题, 如二分类, 对于所给的数据假设存在一条直线可以将数据完成线性可分.\n先看决策边界 (decision boundary) 问题\n有线性决策边界(linear decision boundaries) 可以表示为 $w_1x_1+w_2x_2+b=0$, 假设某个样本点 $h_w(x)=w_1x_1+w_2x_2+b\u003e0$ 那么可以判断其类别为1, 这个过程就是感知机.\n非线性决策边界(non-linear decision boundaries)\nLogistic 回归还需要找到分类概率$P(Y=1)$与输入向量$x$ 的直接关系, 然后通过比较概率值来判断类别.\n考虑二分类问题, 给定数据集:\n$D=\\left(x_{1}, y_{1}\\right),\\left(x_{2}, y_{2}\\right), \\cdots,\\left(x_{N}, y_{N}\\right), x_{i} \\subseteq R^{n}, y_{i} \\in 0,1, i=1,2, \\cdots, N$\n由于多元线性回归模型(单调可导函数) $w^Tx+b$ 的取值是连续的, 所以不能拟合离散变量, 但可以用它来拟合条件概率$P(Y=1|x)$, 因为概率的取值也是连续的. 而概率的取值范围是[0, 1], 所以使用广义线性模型.\n最理想的模型是单位阶跃函数:\n$p(y_i=1 \\mid x_i)=\\left\\{\\begin{array}{ll}0, \u0026 z\u003c0 \\\\0.5, \u0026 z=0 \\\\1, \u0026 z\u003e0\\end{array}, \\quad z=w^{T} x_i+b\\right.$\n但是这个模型不单调, 所以不可导(不连续不平滑), 所以不是广义线性模型\n常用的函数是sigmoid函数, 将\n$f(x) = \\frac{1}{1+e^{-x}}\\in(0,1)$, $h(y_i) = w^Tx_i+b\\in(-\\infty, \\infty)$\n$y_i = f(x_i) = \\frac{1}{1+e^{-(w^Tx_i+b)}}$\n此时$y$是一个概率(0到1之间), 设y为x的正例概率, 1-y为x的反例概率, 两者的比值为几率 (odds).\n$ln(odds)=ln(\\frac{y}{1-y})=w^Tx+b$\n$w^Tx+b=ln\\frac{P(Y=1|x)}{1-P(Y=1|x)}$\n$P(y=1|x)=\\pi_w(x)=\\frac{1}{1-e^{-(w^Tx+b)}}$\n$P(y=-1|x)=1-\\pi_w(x)$\n这里$y\\in(-1,1)$\n所以输出$y=1$的对数几率是由输入$x$的线性函数表示的模型, 这就是逻辑回归模型.\n2. Support Vector Machine(SVM) 支持向量机（英语：support vector machine，常简称为SVM，又名支持向量网络）是在分类与回归分析中分析数据的监督式学习模型与相关的学习算法。给定一组训练实例，每个训练实例被标记为属于两个类别中的一个或另一个，SVM训练算法创建一个将新的实例分配给两个类别之一的模型，使其成为非概率二元线性分类器。SVM模型是将实例表示为空间中的点，这样映射就使得单独类别的实例被尽可能宽的明显的间隔分开。然后，将新的实例映射到同一空间，并基于它们落在间隔的哪一侧来预测所属类别。\nSVM有三种不同的模型:\n线性可分SVM\n当训练数据线性可分时, 通过硬间隔(hard margin)最大化可以学习得到一个线性分类器(硬间隔SVM)\n线性SVM\n当训练数据不线性可分但近似可分时, 通过软间隔(soft margin)最大化可以学习得到一个线性分类器(软间隔SVM: 允许少量样本不满足约束).\n非线性SVM\n当训练数据不可分时, 通过使用核技巧(kernel trick)和软间隔最大化可以学习到一个非线性SVM.\n支持向量 (Support vertor)\n在线性可分的情况下, 训练数据集的样本点中与分离超平面距离最近的数据点叫支持向量, 比如, 假设一个超平面是$X^TW+b=0$, 这个点在$X^TW+b=\\pm1$上.\n移动或删除非支持向量都不会对最优超平面产生影响, 即支持向量对模型起着决定性作用, 所以这个方法叫支持向量机.\n软间隔最大化\n软间隔允许少量样本不满足约束\n惩罚参数C\nC调节优化方向中两个指标(间隔大小, 分类准确度)偏好的权重.\n软间隔SVM相对于硬间隔SVM, 适当放宽了margin的大小, 容忍了一些分类错误(当做噪声处理)\n$C\\to\\infty$, 禁止分类误差样本存在, 就是硬间隔SVM.(过拟合) $C\\to0$, 不再关注分类是否正确, 只要求间隔越大越好, 训练无法收敛.(欠拟合) 核技巧 (kernel trick)\n核技巧原理:\n使用一个变换将原空间的数据映射到新空间(如更高维度甚至是无穷维度空间) 在新空间里用线性方法从训练数据中学习得到模型. 总结\n任何算法都有其优缺点，支持向量机也不例外。\n支持向量机的优点是:\n由于SVM是一个凸优化问题，所以求得的解一定是全局最优而不是局部最优。 不仅适用于线性线性问题还适用于非线性问题(用核技巧)。 拥有高维样本空间的数据也能用SVM，这是因为数据集的复杂度只取决于支持向量而不是数据集的维度，这在某种意义上避免了“维数灾难”。 理论基础比较完善(例如神经网络就更像一个黑盒子)。\n支持向量机的缺点是:\n二次规划问题求解将涉及m阶矩阵的计算(m为样本的个数), 因此SVM不适用于超大数据集。(SMO算法可以缓解这个问题) 只适用于二分类问题。(SVM的推广SVR也适用于回归问题；可以通过多个SVM的组合来解决多分类问题)\nReference\n看了这篇文章你还不懂SVM你就来打我\n3. TF-IDF算法 一文看懂 TF-IDF (概念图解+4大变种+发展历史)\n向量空间模型就是希望把查询关键字和文档都表达成向量，然后利用向量之间的运算来进一步表达向量间的关系 优点: 简单快速 缺点: 用词频来衡量文章中的词的重要性不够全面. 3.1. TF （Term Frequency）—— “单词频率” 某个关键字在文档中出现的次数 问题: TF不能完整的描述文档的相关度. eg. 停词 于是需要IDF 3.2. IDF（Inverse Document Frequency）—— “逆文档频率” 惩罚 (Penalize)那些出现在太多文档中的单词。 真正携带 “相关” 信息的单词仅仅出现在相对比较少，有时候可能是极少数的文档里. 所以使用DF的倒数来表示. 文档频率 (DF): 有多少文档涵盖了这个单词. 如果有太多文档都涵盖了某个单词, 这个单词也就越不重要, 或者说是这个单词就越没有信息量. 3.3. TF-IDF的4个变种 通过对数函数避免 TF 线性增长 由于TF值的增长没有上限, 某个单词在一个文档中的TF相对的来说表达了某种相关度. 超过了某个阈值之后这个TF就没什么区分度了.\n所以使用Log函数对TF进行变换, 使其不线性增长.\n$TF = 1+log({TF}_{old})$\neg: 假设 “Car” 出现一次，新的值是 1，出现 100 次，新的值是 5.6，而出现 200 次，新的值是 6.3。\n标准化解决长文档、短文档问题 根据文档的最大 TF 值进行的标准化(Normalization). eg: 一个文档 A 有 3,000 个单词，一个文档 B 有 250 个单词，很明显，即便 “Car” 在这两个文档中都同样出现过 20 次，也不能说这两个文档都同等相关。 对数函数处理 IDF Log函数对IDF进行变换. 相对于直接使用 IDF 来作为惩罚因素, 可以使用 N+1 然后除以 DF 作为一个新的 DF 的倒数, 并且再在这个基础上通过一个对数变化. 这里的 N 是所有文档的总数. 优点1: 使用了文档总数来做标准化, 类似于方法2. 优点2: 利用对数达到非线性增长的目的. 方法1. 查询词及文档向量标准化 使向量能够不受向量里有效元素多少的影响. 不同长度的文档, 标准化为单位向量. 此时点积运算, 就等于在原向量上进行余弦相似度运算. 3.4. 运算过程 eg:\n一个包含O个单词的文档中出现单词x P次.\n总共M个文档, 其中N个文档中存在单词x.\n$TF(x)=\\frac{P}{O}$\n$IDF(x) = log(\\frac{M}{N+1})$\n$W(x)=TF(x)*IDF(x)=\\frac{P}{O}log(\\frac{M}{N+1})$\n分母+1是为了避免分母为0的情况.\n4. K-means 基于欧式距离的聚类算法, 其认为两个目标的距离越近, 相似度越大。\n算法步骤 选择初始化的k个样本作为初始聚类中心: $a=a_1,a_2,a_3...a_k$\n针对数据集中每一个样本$x_i$, 计算它到每个聚类中心的距离, 将其分到距离最短的聚类中心所对应的类中\n$\\text { label }_{i}=\\underset{1","permalink":"https://sqf.icu/article/8e9dce96-deed-41bf-88c7-76b3f7be962c/","summary":"\u003ch1 id=\"1-logistic-regression\"\u003e1. Logistic Regression\u003c/h1\u003e\n\u003cp\u003e模型介绍\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e逻辑回归 (Logistic regression) 是分类模型, 常用于二分类.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e逻辑回归的本质是: 假设数据服从分布, 然后使用极大似然估计做参数的估计\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eLogistic 分布是一种连续概率分布\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e分布函数:\u003c/li\u003e\n\u003c/ul\u003e\n$$\r\n    F(x)=P(X \\leq x)=\\frac{1}{1+e^{-(x-\\mu) / \\gamma}}\r\n    $$\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e密度函数:\u003c/p\u003e\n$$\r\n        f(x)=F^{\\prime}(X \\leq x)=\\frac{e^{-(x-\\mu) / \\gamma}}{\\gamma\\left(1+e^{-(x-\\mu) / \\gamma}\\right)^{2}}\r\n        $$\u003cul\u003e\n\u003cli\u003e$\\mu$: 未知参数; $\\gamma$: 形状参数.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/media/e0be5b8ea2993dbd5a5f0aeb.png\"\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003elogistic 分布的形状与正态分布的形状相似, 但是Logistic 分布的尾部更长, 所以我们可以使用Logistic 分布来建模比正态分布具有更长尾部和更高波峰的数据分布.\u003c/li\u003e\n\u003cli\u003eSigmoid 函数就是Logistic 的分布函数在$\\mu=0, \\gamma=1$的特殊形式.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eLogistic 回归\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eLogistic 回归主要用于分类问题, 如二分类, 对于所给的数据假设存在一条直线可以将数据完成线性可分.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e先看决策边界 (decision boundary) 问题\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e有线性决策边界(linear decision boundaries) 可以表示为 $w_1x_1+w_2x_2+b=0$, 假设某个样本点 $h_w(x)=w_1x_1+w_2x_2+b\u003e0$ 那么可以判断其类别为1, 这个过程就是感知机.\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/media/bc1c677b06f99e3c51b05761.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e非线性决策边界(non-linear decision boundaries)\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/media/6c86cb6879ececf9312c2c84.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eLogistic 回归还需要找到分类概率$P(Y=1)$与输入向量$x$ 的直接关系, 然后通过比较概率值来判断类别.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e考虑二分类问题, 给定数据集:\u003c/p\u003e\n\u003cp\u003e$D=\\left(x_{1}, y_{1}\\right),\\left(x_{2}, y_{2}\\right), \\cdots,\\left(x_{N}, y_{N}\\right), x_{i} \\subseteq R^{n}, y_{i} \\in 0,1, i=1,2, \\cdots, N$\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e由于多元线性回归模型(单调可导函数) $w^Tx+b$ 的取值是连续的, 所以不能拟合离散变量, 但可以用它来拟合条件概率$P(Y=1|x)$, 因为概率的取值也是连续的. 而概率的取值范围是[0, 1], 所以使用广义线性模型.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e最理想的模型是单位阶跃函数:\u003c/p\u003e\n\u003cp\u003e$p(y_i=1 \\mid x_i)=\\left\\{\\begin{array}{ll}0, \u0026 z\u003c0 \\\\0.5, \u0026 z=0 \\\\1, \u0026 z\u003e0\\end{array}, \\quad z=w^{T} x_i+b\\right.$\u003c/p\u003e\n\u003cp\u003e但是这个模型不单调, 所以不可导(不连续不平滑), 所以不是广义线性模型\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e常用的函数是sigmoid函数, 将\u003c/p\u003e\n\u003cp\u003e$f(x) = \\frac{1}{1+e^{-x}}\\in(0,1)$, $h(y_i) = w^Tx_i+b\\in(-\\infty, \\infty)$\u003c/p\u003e\n\u003cp\u003e$y_i = f(x_i) = \\frac{1}{1+e^{-(w^Tx_i+b)}}$\u003c/p\u003e\n\u003cp\u003e此时$y$是一个概率(0到1之间), 设y为x的正例概率, 1-y为x的反例概率, 两者的比值为几率 (odds).\u003c/p\u003e\n\u003cp\u003e$ln(odds)=ln(\\frac{y}{1-y})=w^Tx+b$\u003c/p\u003e\n\u003cp\u003e$w^Tx+b=ln\\frac{P(Y=1|x)}{1-P(Y=1|x)}$\u003c/p\u003e\n\u003cp\u003e$P(y=1|x)=\\pi_w(x)=\\frac{1}{1-e^{-(w^Tx+b)}}$\u003c/p\u003e\n\u003cp\u003e$P(y=-1|x)=1-\\pi_w(x)$\u003c/p\u003e\n\u003cp\u003e这里$y\\in(-1,1)$\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e所以输出$y=1$的对数几率是由输入$x$的线性函数表示的模型, 这就是逻辑回归模型.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"机器学习模型介绍"},{"content":"1. CNN 卷积核介绍\nCNN中常用的四种卷积详解\n1.1. 一般卷积 一个卷积核在图像上滑动，并求取对应元素相乘求和的过程.\n使用参数:\n卷积核大小 (Kernel Size) 步长 (Stride) 填充 (Padding) 输入和输出通道数 (Input \u0026amp; Output Channels) 普通卷积公式:\n$$\r\\mathbf{y}\\left(\\mathbf{p}_0\\right)=\\sum_{\\mathbf{p}_n \\in \\mathcal{R}} \\mathbf{w}\\left(\\mathbf{p}_n\\right) \\cdot \\mathbf{x}\\left(\\mathbf{p}_0+\\mathbf{p}_n\\right)\r$$ $\\mathbf{x}\\left(\\mathbf{p}_0+\\mathbf{p}_n\\right)$: 表示相对位置坐标 $p_n$ 的像素值; $\\mathbf{w}\\left(\\mathbf{p}_n\\right)$: 表示这个像素的权重. 1.2. 扩张卷积 (空洞卷积, 膨胀卷积) 在标准的卷积核中注入空洞, 以此来增加模型的感受野 (reception field).\n增加的参数:\n扩张率 (dilation rate) 指的是卷积核的点的间隔数. 出现的原因: 在深度网络中为了增加感受野并降低计算量, 需要进行池化, 这样虽然可以增加感受野, 但空间分辨率降低了.\n扩张卷积的好处: 在不丢失特征分辨率的情况下扩大了感受野, 进而对检测大物体有比较好的效果.\n1.3. 转置卷积 (反卷积, 逆卷积 Transpose Convolution, Deconvolution) 有时候上采样 (使用各种插值算法) 的效果不好, 需要模型自己找到一种好的上采样方式.\n常用于以下 GAN 和图像分割场景:\n在 DCGAN 中, 生成器将会用随机值转变为一个全尺寸 (full-size) 的图片, 这个时候就需要用到转置卷积. 在语义分割模型中, 会使用卷积层在编码器中进行特征提取, 然后在解码层中进行恢复为原先的尺寸, 这样才可以对原来图像的每个像素都进行分类. 这个过程同样需要用到转置卷积. 经典方法如: FCN 和 Unet. CNN 的可视化: 通过转置卷积将 CNN 中得到的特征图还原到像素空间, 以观察特定的特征图对哪些模式的图像敏感. 对于转置卷积而言, 实际上是想建立一个与普通卷积相反的操作, 也就是建立一个一对多的关系. 比如我们想要建立的是输出卷积中的1个值与输入卷积中的9个值的关系.\n从信息论的角度, 卷积操作是不可逆的, 所以转置卷积并不是使用输出矩阵和卷积核计算原始的输入矩阵, 而是计算得到保持了相对位置关系的矩阵. 1.4. 空间分离卷积 (spatial separable convolutions) 在空间维度将标准卷积运算进行拆分, 将标准卷积核拆分成多个小卷积核, 如下图所示:\n优点: 这样做可以减小计算复杂度.\n应用例: 分离的sobel算子.\n1.5. 可变形卷积 可变形卷积公式\n$$\n\\mathbf{y}\\left(\\mathbf{p}0\\right)=\\sum{\\mathbf{p}_n \\in \\mathcal{R}} \\mathbf{w}\\left(\\mathbf{p}_n\\right) \\cdot \\mathbf{x}\\left(\\mathbf{p}_0+\\mathbf{p}_n+\\Delta \\mathbf{p}_n\\right)\n$$\n可变形卷积的输出:\n$$\routput\\_size = 2*kernel\\_size^2\r$$ $\\mathbf{p}$ 如何获得?\n$\\Delta \\mathbf{p}_n$ 是位置偏移量. 是训练时学习到的浮点型数值, 由图像经过普通卷积计算得到. 偏移后的亚像素点 $\\mathbf{p}$ 转换为像素值 $\\mathbf{v}_n$并 乘上各自的权重, 并且求和, 就获得了最终像素的值.\n亚像素点的值 $\\mathbf{v}_n$ 怎么获得? 找到亚像素点之后, 采样临近的4个像素点.\n使用双线性插值, 求得最终的值.\n插值算法介绍 - 1. 双线性插值\n在训练中, 通过计算损失, 反向传播和优化函数来更新 $\\Delta\\mathbf{p}_n$.\n2. RNN 深度学习（六）：LSTM模型与前向反向传播算法_lstm backpropagation_anshuai_aw1的博客-CSDN博客\n循环神经网络 (Recurrent Neural Network) 处理序列数据的神经网络.\n相比一般的神经网络来说能够处理序列变化的数据, 比如上下文问题 (单词的含义因为上下文而变化).\n$x$: 当前节点下的输入; $h$: 上个节点的输出$h$; $y$: 当前节点下的输出; $h'$: 传递到下一个节点的输出.\n2.1. LSTM 长短期记忆 (Long short-term memory, LSTM) 是一种特殊的 RNN, 主要是为了解决长序列训练过程中的梯度消失和梯度爆炸问题. 相比普通 RNN, LSTM 在更长的序列中表现更好.\nLSTM 与 RNN 不同之处: LSTM 比 RNN 多了一个传递状态$c^t$ (cell state) LSTM 与 RNN 相同之处: 都有一个$h^t$ (hidden state) $c^t$ 在传递中改变得很慢 (对于之前的 $c$ 不断累积, 长期记忆), $h^t$ 则改变的很快 (短期记忆)\n2.1.1. LSTM 详细结构 使用 LSTM 的当前输入 $x^t$ 和上一个状态传递下来的 $h^{t-1}$ 拼接训练得到四个状态.\n$z$ 将结果通过一个 $tanh$ 激活函数来转换为 $[-1,1]$ 的值 (这里使用 $tanh$ 是因为这里是将其做为输入数据, 而不是门控信号). $z^f, z^i, z^o$ 是有拼接向量乘以权重矩阵后, 再通过 $sigmoid$ 激活函数转换成 $0$ 到 $1$ 之间的数值, 在作为门控状态. $\\odot$: Hadamard Product (哈达玛积)\n两矩阵对应的元素各自相乘\n$\\oplus$: 矩阵加法\n2.1.2. LSTM 三阶段 忘记阶段: 对上一个节点传入的输入进行选择性遗忘 (忘记不重要的, 记住重要的). $z^f$: 控制上一个状态的 $c^{t-1}$ 进行选择性遗忘 (forget). 选择记忆阶段: 对输入的 $x^t$ 选择性记忆. $z$: 当前输入内容由z表示 $z^i$: information 一阶段和二阶段结果相加就是 $c^t$ 输出阶段: 这个阶段将决定哪些将会被当成当前状态的输出. 主要是通过 $z^o$ 来进行控制的。并且还对上一阶段得到的 $z^o$ 进行了放缩 (通过一个 $tanh$ 激活函数进行变化). 2.1.3. LSTM 前向传播算法 LSTM 模型有两个隐藏状态 $h^{(t)}, C^{(t)}$, 模型参数几乎是 RNN 的4倍, 因为现在多了 $W_f, U_f, b_f, W_a, U_a, b_a, W_i, U_i, b_i, W_o, U_o, b_o$ 这些参数.\n前向传播过程在每个序列索引位置的过程为:\n更新遗忘门输出:\n$$\rf^{(t)}=\\sigma\\left(W_f h^{(t-1)}+U_f x^{(t)}+b_f\\right) \\quad\\quad \\text{(1)}\r$$ 更新输入门两部分输出:\n$$\ri^{(t)}=\\sigma\\left(W_i h^{(t-1)}+U_i x^{(t)}+b_i\\right) \\quad\\quad \\text{(2)}\r$$$$\ra^{(t)}=\\tanh \\left(W_a h^{(t-1)}+U_a x^{(t)}+b_a\\right) \\quad\\quad \\text{(3)}\r$$ 更新细胞状态:\n$$\rC^{(t)}=C^{(t-1)} \\odot f^{(t)}+i^{(t)} \\odot a^{(t)} \\quad\\quad \\text{(4)}\r$$ 更新输出门输出:\n$$\ro^{(t)}=\\sigma\\left(W_o h^{(t-1)}+U_o x^{(t)}+b_o\\right) \\quad\\quad \\text{(5)}\r$$$$\rh^{(t)}=o^{(t)} \\odot \\tanh \\left(C^{(t)}\\right) \\quad\\quad \\text{(6)}\r$$ 更新当前序列索引预测输出:\n$$\r\\hat{y}^{(t)}=\\sigma\\left(V h^{(t)}+c\\right) \\quad\\quad \\text{(7)}\r$$ 整体的过程如下图所示\n在$t$时刻, $C^{(t)}$ 用于计算 $h^{(t)}$ 和 $C^{(t+1)}$ 2.1.4. LSTM 反向传播算法 有了 LSTM 前向传播算法, 推导反向传播算法就很容易了, 思路和RNN的反向传播算法思路一致, 也是通过梯度下降法迭代更新我们所有 的参数, 关键点在于计算所有参数基于损失函数的偏导数.\n在 RNN 中, 为了反向传播误差, 我们通过隐藏状态 $h^{(t)}$ 的梯度 $\\delta^{(t)}$ 一步步向前传播. 在LSTM这里也类似. 只不过我们这里有两个隐藏状态 $h^{(t)}$ 和 $C^{(t)}$. 这里我们定义两个 $\\delta$, 即:\n$$\r\\delta_h^{(t)}=\\frac{\\partial L}{\\partial h^{(t)}} \\quad\\quad \\text{(8)}\r$$$$\r\\delta_C^{(t)}=\\frac{\\partial L}{\\partial C^{(t)}} \\quad\\quad \\text{(9)}\r$$反向传播时只使用了 $\\delta_C^{(t)}$, 变量 $\\delta_h^{(t)}$ 仅为帮助我们在某一层计算用, 并没有参与反向传播. 如下图所示:\n输出层定义的损失函数为对数损失, 激活函数为 $softmax$ 激活函数. 因为与RNN的推导类似, 在最后的序列索引位置 $\\tau$ 的 $\\delta_h^{(\\tau)}$ 和 $\\delta_C^{(\\tau)}$ 为:\n$$\r\\delta_h^{(\\tau)}=\\frac{\\partial L}{\\partial O^{(\\tau)}} \\frac{\\partial O^{(\\tau)}}{\\partial h^{(\\tau)}}=V^T\\left(\\hat{y}^{(\\tau)}-y^{(\\tau)}\\right) \\quad\\quad \\text{(10)}\r$$$$\r\\delta_C^{(\\tau)}=\\frac{\\partial L}{\\partial h^{(\\tau)}} \\frac{\\partial h^{(\\tau)}}{\\partial C^{(\\tau)}}=\\delta_h^{(\\tau)} \\odot o^{(\\tau)} \\odot\\left(1-\\tanh ^2\\left(C^{(\\tau)}\\right)\\right) \\quad\\quad \\text{(11)}\r$$接着由 $\\delta_C^{(t+1)}$ 反向推导 $\\delta_C^{(t)}$, $\\delta_h^{(t)}$ 的梯度由本层的输出梯度误差决定, 与公式 (10) 类似, 即:\n$$\r\\delta_h^{(t)}=\\frac{\\partial L}{\\partial h^{(t)}}=V^T\\left(\\hat{y}^{(t)}-y^{(t)}\\right) \\quad\\quad \\text{(12)}\r$$而 $\\delta_C^{(t)}$ 的反向梯度误差由前一层 $\\delta_C^{(t+1)}$ 的梯度误差和本层的从 $h^{(t)}$ 传回来的梯度误差两部分组成, 即：\n$$\r\\delta_C^{(t)}=\\frac{\\partial L}{\\partial C^{(t+1)}} \\frac{\\partial C^{(t+1)}}{\\partial C^{(t)}}+\\frac{\\partial L}{\\partial h^{(t)}} \\frac{\\partial h^{(t)}}{\\partial C^{(t)}}=\\delta_C^{(t+1)} \\odot f^{(t+1)}+\\delta_h^{(t)} \\odot o^{(t)} \\odot\\left(1-\\tanh ^2\\left(C^{(t)}\\right)\\right) \\quad\\quad \\text{(13)}\r$$公式 (13) 的前半部分由公式 (4) 和公式 (9) 得到, 公式 (13) 的后半部分由公式 (6) 和公式 (8) 得到.\n有了 $\\delta_h^{(t)}$ 和 $\\delta_C^{(t)}$, 计算这一大堆参数的梯度就很容易了, 这里只给出 $W_f$ 的梯度计算过程, 其他的 $U_f, b_f, W_a, U_a, b_a, W_i, U_i, b_i, W_o, U_o, b_o, V, c$ 的梯度大家只要照搬就可以了。\n$$\r\\frac{\\partial L}{\\partial W_f}=\\sum_{t=1}^\\tau \\frac{\\partial L}{\\partial C^{(t)}} \\frac{\\partial C^{(t)}}{\\partial f^{(t)}} \\frac{\\partial f^{(t)}}{\\partial W_f}=\\sum_{t=1}^\\tau \\delta_C^{(t)} \\odot C^{(t-1)} \\odot f^{(t)} \\odot\\left(1-f^{(t)}\\right)\\left(h^{(t-1)}\\right)^T \\quad\\quad \\text{(14)}\r$$公式 (14) 的由公式 (1), 公式 (4) 和公式 (9) 得到.\n由上面可以得到, 只要我们清晰地搞清楚前向传播过程, 且只使用了$\\delta_C^{(t)}$ 进行反向传播的话, 反向传播的整个过程是比较清晰的. 更详细 的过程可以参看参考文献【2】 在这里有必要解释下为什么反向传播不使用 $\\delta_h^{(t)}$, 如果与《深度学习 (五) : 循环神经网络(RNN)模型与前向反向传播算法》里一样的话, 那么 $\\delta_h^{(t)}$ 的计算方式就不应该是 (12) 式了. 因为, $h^{(t)}$ 参与了 $L^{(t)}$ 和 $L^{(t+1)}$ 的计算, 所以在RNN文章里的求梯度方法, $\\frac{\\partial L}{\\partial h^{(t)}}$ 应该是\n$$\r\\delta_h^{(t)}=\\frac{\\partial L}{\\partial h^{(t)}}+\\frac{\\partial L}{\\partial h^{(t+1)}} \\frac{\\partial h^{(t+1)}}{\\partial h^{(t)}} \\quad\\quad \\text{(12*)}\r$$但是, 这里是一个比较复杂的时序模型, 如果使用 RNN 的思路, 将 $h^{(t+1)}$ 的部分也一起反向传播回来的话, 这里的反向梯度根本无法得到闭式解. 而只考虑一个的话, 也可以做反向梯度优化, 进度下降, 但是优化起来容易的多, 可以理解为这里做了一个近似.\n2.2. GRU 人人都能看懂的GRU\n门控相较于 LSTM 减少为两个.\n重置门控 (reset gate)\n更新门控 (update gate)\n首先使用重置门控来得到“重置”之后的数据 $h^{t-1^{\\prime}}=h^{t-1} \\odot r$, 再将 $h^{t-1^{\\prime}}$ 与输入 $x^t$ 进行拼接，再通过一个 $tanh$ 激活函数来将数据放缩到 $(-1, 1)$ 的范围内.\n”更新记忆“阶段\n更新表达式:\n$$\rh^{t}=(1-z) \\odot h^{t-1}+z \\odot h^{\\prime}\r$$ 门控信号（这里的 $z$ ）的范围为0~1. 门控信号越接近1, 代表”记忆“下来的数据越多, 而越接近0则代表”遗忘“的越多.\n有读者发现在 PyTorch 里面的 GRU [链接] 写法相比原版对 $h^{t-1}$ 多了一个映射, 相当于一个GRU变体, 猜测是多加多这个映射能让整体实验效果提升较大。如果有了解的同学欢迎评论指出。\nGRU聪明的一点就在于, 我们使用了同一个门控 $z$ 就同时可以进行遗忘和选择记忆 (LSTM则要使用多个门控). $(1-z) \\odot h^{t-1}$ : 表示对原本隐藏状态的选择性“遗忘\u0026quot;. 这里的 $1-z$ 可以想象成遗忘门 (forget gate), 忘记 $h^{t-1}$ 维度中一些不重要的信息. $z \\odot h^{\\prime}$ : 表示对包含当前节点信息的 $h^{\\prime}$ 进行选择性\u0026quot;记忆\u0026quot;. 与上面类似, 这里的 $(1-z)$ 同理 会忘记 $h^{\\prime}$ 维度中的一些不重要的信息. 或者, 这里我们更应当看做是对 $h^{\\prime}$ 维度中的某些信息 进行选择. $h^t=(1-z) \\odot h^{t-1}+z \\odot h^{\\prime}$ : 结合上述, 这一步的操作就是忘记传递下来的 $h^{t-1}$ 中的某些维 度信息, 并加入当前节点输入的某些维度信息. 可以看到, 这里的遗忘 $z$ 和选择 $(1-z)$ 是联动的. 也就是说, 对于传递进来的维度信息, 我 们会进行选择性遗忘, 则遗忘了多少权重 $(z)$, 我们就会使用包含当前输入的 $h^{\\prime}$ 中所对应 的权重进行弥补 $(1-z)$ 。以保持一种\u0026quot;恒定\u0026quot;状态. 2.3. BiLSTM BiLSTM介绍及代码实现\n前向的 $\\operatorname{LSTM}_L$ 依次输入“我\u0026quot;，“爱”，“中国\u0026quot;得到三个向量 $\\left\\{\\mathrm{h}_{L0}， \\mathrm{h}_{L1}，\\mathrm{h}_{L2}\\right\\}$. 后向的 $\\mathrm{LSTM}_R$ 依次输 入“中国”，“爱”，“我\u0026quot;得到三个向量 $\\left\\{\\mathrm{h}_{R0}， \\mathrm{h}_{R1}，\\mathrm{h}_{R2}\\right\\}$. 最后将前向和后向的隐向量进行拼接得到 $\\left\\{\\left[\\mathrm{h}_{L0}\\right.\\right., \\left.\\left.\\mathrm{h}_{R2}\\right],\\left[\\mathrm{h}_{L1},\\mathrm{h}_{R1}\\right],\\left[\\mathrm{h}_{L2}, \\mathrm{h}_{R0}\\right]\\right\\}$, 即$\\left\\{\\mathrm{h}_{0}， \\mathrm{h}_{1}，\\mathrm{h}_{2}\\right\\}$.\n对于情感分类任务来说, 我们采用的句子的表示往往是 $[h_{L2},h_{R2}]$. 因为其包含了前向与后向的所有信息, 如下图所示:\n3. Word2vec Word2Vec 是从大量文本语料中以无监督的方式学习语义知识的一种模型. 通过学习文本来用词向量来反映语义信息. Embedding 其实就是一个映射, 将单词从原先所属的空间映射到新的多维空间中, 也就是把原先词所在空间嵌入到一个新的空间中去. 隐层的激活函数其实是线性的，相当于没做任何处理 (这也是 Word2vec 简化之前语言模型的独到之处), 我们要训练这个神经网络，用反向传播算法，本质上是链式求导 (BP 算法). 当模型训练完后，最后得到的其实是神经网络的权重. eg: 输入一个单词 x 的 one-hot encoder, 激活隐含层里的权重, 从而得出向量 vx. 由于 x 的 one-hot encoder 各不相同, 所以vx可以用来唯一表示 x. gensim 和 google 的 word2vec 里面并没有用到 onehot encoder，而是初始化的时候直接为每个词随机生成一个N维的向量，并且把这个N维向量作为模型参数学习. 3.1. Skip-gram 模型 用一个词语作为输入, 来预测它周围的上下文 Skip-gram 的负采样\n对高频词采样\neg: window = 2\nstopwords 出现次数过高, 导致与之相关的训练样本都不会提供关于另一个单词的语义信息. Word2Vec 通过“抽样”模式来解决这种高频词问题. 训练原始文本中遇到的每一个单词都有一定概率被从文本中删掉, 而这个被删除的概率与单词的频率有关.\n抽样率\n$$\rZ(w_i)=1000/1e9=1e^-6\r$$ $w_i$: 一个单词; $Z(w_i)$是$w_i$这个单词在所有语料中出现的频次. 层次 $softmax$ 所使用的哈弗曼树使用这个词频作为权重. $$\rP\\left(w_{i}\\right)=\\left(\\sqrt{\\frac{Z\\left(w_{i}\\right)}{0.001}}+1\\right) \\times \\frac{0.001}{Z\\left(w_{i}\\right)}\r$$ $P(w_i)$ 表示保留某个单词的概率; $0.001$ 是默认参数, 值越大, 单词被删除的概率越大. 负采样每次让一个训练样本仅仅更新一小部分的权重, 这样就会降低梯度下降过程中的计算量. 单词抽样率越高, 被删除的概率越大\n当单词在语料中出现的频率小于 $0.0026$ 时, 它是 $100\\%$ 被保留的, 这意味着只有那些在语料中出现频率超过 $0.26\\%$ 的单词才会被采样. 当 $Z(w_i)=0.00746$ 时, $P(w_i)=0.5$, 意味着这一部分的单词有 $50\\%$ 的概率被保留. 当 $Z(w_i)=1.0$ 时, $P(w_i)=0.033$, 意味着这部分单词以 $3.3\\%$ 的概率被保留.\n3.2. CBOW 模型 continuous bag of words (连续词袋模型) 用一个词语的上下文作为输入, 来预测这个词语本身.\n3.3. Word2vec 的训练 trick 两个降低复杂度的近似方法 Hierarchical Softmax (层次softmax):\nHierarchical Softmax（层次Softmax）\n一种对输出层进行优化的策略, 输出层从原始模型的利用 softmax 计算概率值改为了利用Huffman 树 (最优二叉树) 计算概率值. 霍夫曼树优点: 比完全二叉树空间复杂度更小.\n本质是把 N 分类问题变成 $log(N)$ 次二分类. (二叉树时间复杂度 $O(log(N))$)\n哈夫曼树输出层不使用 one-hot 来表示, softmax 回归就不需要对那么多 0 进行拟合, 节省时间. 只需要拟合输出值到根的那条路径.\nNegative Sampling (简写 NEG, 负采样):\nNoise-Contrastive Estimation (简写 NCE, 噪声对比估计) 的简化版本: 把语料中的一个词串的中心词替换为别的词, 构造语料 D 中不存在的词串作为负样本. 因此在这种策略下, 优化目标变为了: 最大化正样本的概率，同时最小化负样本的概率. (每一个词都会被作为中心词) 本质是预测总体类别的一个子集. (NCE 是一种对观测数据的概率密度进行估计的方法, 通过构造一些分布已知的 noise data, 将概率密度的估计问题转化为一个 logistic regression 问题)\n4. Transformers 一些主流模型的区别\n4.1. Attention Model 4.1.1. Encoder-Decoder框架 前大多数注意力模型附着在 Encoder-Decoder 框架下\n$$\r\\text { Source }=\\left\\langle\\mathbf{x}_{1}, \\mathbf{x}_{2} \\ldots \\mathbf{x}_{\\mathbf{m}}\\right\\rangle\r$$$$\r\\text { Target }=\\left\\langle\\mathbf{y}_{1}, \\mathbf{y}_{2} \\ldots \\mathbf{y}_{\\mathbf{n}}\\right\\rangle\r$$ Encoder: 对 Source 进行编码，将输入句子通过非线性变换转化为中间语义表示 C.\n$$\r\\mathbf{C}=\\mathcal{F}\\left(\\mathbf{x}_{1}, \\mathbf{x}_{2} \\ldots \\mathbf{x}_{\\mathbf{m}}\\right)\r$$注意这里编码需要在在训练的时候建立一个表, 保存最细粒度字符与对应的向量, 表中的向量包括:\nInput embedding\n这就是 $d_{model}$\nPositional encoding\n将位置信息 + $d_{model}$, 变成 positional input embeddings\n位置编码使用频率不同的正弦和余弦函数, $$\r\\begin{aligned}P E_{(p o s, 2 i)} \u0026 =\\sin \\left(pos / 10000^{2 i / d_{\\mathrm{model}}}\\right) \\\\P E_{(p o s, 2 i+1)} \u0026 =\\cos \\left(p o s / 10000^{2 i / d_{\\mathrm{model}}}\\right)\\end{aligned}\r$$ $pos$ 是位置; $i$ 是维度. 公式是位置编码每个维度对应函数曲线, 曲线波长范围: $2\\pi \\sim 10000 \\cdot 2\\pi$ 的几何级数. 奇数维度用 $cos$; 偶数维度用 $sin$. 选择正余弦函数是因为它可以允许模型推断出比训练期间遇到的序列更长的序列. Decoder: 根据 C 和之前已经生成的历史信息Target(1~i-1)来生成i时刻要生成的单词:\n$$\r\\mathbf{y}_{\\mathbf{i}}=\\mathcal{G}\\left(\\mathrm{C}, \\mathrm{y}_{1}, \\mathrm{y}_{2} \\ldots \\mathrm{y}_{\\mathrm{i}-1}\\right)\r$$ 在计算 attention 的过程中, 使用一个 Q(uery), 计算它和每个 K(ey) 的相似度作为权重, 对所有的 V(alue) 进行加权求和.\n在 self-attention 中, QKV 有 embedding 的结果经过不同的线性变换得到, 维度都是 $h_{hidden}\\times l_{src}$\n4.1.2. Attention model Soft Attention model\n上图的 E-D 模型没有 attention, 因为 Target 中每个单词生成过程如下, $\\mathbf{f}$ 是 Decoder 的非线性变换函数, $\\mathrm{C}$ 没有变化(等于人眼中没有焦点).\n$$\r\\begin{array}{l}\\mathrm{y}_{1}=\\mathbf{f}(\\mathrm{C}) \\\\\\mathrm{y}_{2}=\\mathbf{f}\\left(\\mathrm{C}, \\mathrm{y}_{1}\\right) \\\\\\mathrm{y}_{3}=\\mathbf{f}\\left(\\mathrm{C}, \\mathrm{y}_{1}, \\mathrm{y}_{2}\\right)\\end{array}\r$$ 没有引入注意力的模型在输入句子比较短的时候问题不大，但是如果输入句子比较长，此时所有语义完全通过一个中间语义向量 $\\mathrm{C}$ 来表示，单词自身的信息已经消失，可想而知会丢失很多细节信息，这也是为何要引入注意力模型的重要原因.\n目标句子中的每个单词都应该学会其对应的源语句子中单词的注意力分配概率信息。这意味着在生成每个单词 $y_i$ 的时候，原先都是相同的中间语义表示 $\\mathrm{C}_i$ 会被替换成根据当前生成单词而不断变化的.\n则生成过程变为\n$$\r\\begin{array}{l}\\mathrm{y}_{1}=\\mathbf{f1} \\left(\\mathrm{C}_{1}\\right) \\\\\\mathrm{y}_{2}=\\mathbf{f1} \\left(\\mathrm{C}_{2}, \\mathrm{y}_{1}\\right) \\\\\\mathrm{y}_{3}=\\mathbf{f1} \\left(\\mathrm{C}_{3}, \\mathrm{y}_{1}, \\mathrm{y}_{2}\\right)\\end{array}\r$$ 汤姆追逐杰瑞 → Tom chase Jerry\n$$\r\\begin{aligned}C_{汤姆}\u0026=\\mathbf{g}(\\mathbf{0.6} * \\mathbf{f2}(\\text { \"Tom\" }), \\mathbf{0.2} * \\mathbf{f2} (\\text { Chase }), \\mathbf{0.2} * \\mathbf{f2} (\\text { \"Jerry\" }))\\\\C_{追逐}\u0026=\\mathbf{g}(\\mathbf{0.2} * \\mathbf{f2} (\\text { \"Tom\" }), \\mathbf{0} . \\mathbf{7} * \\mathbf{f2} (\\text { Chase }), \\mathbf{0.1} * \\mathbf{f2} (\\text { \"Jerry\" }))\\\\C_{杰瑞}\u0026=\\mathbf{g}(\\mathbf{0.3} * \\mathbf{f2} (\\text { \"Tom\" }), \\mathbf{0.2} * \\mathbf{f2}(\\text { Chase }), \\mathbf{0.5} * \\mathbf{f2}(\\text { \"Jerry\" }))\\end{aligned}\r$$ f2 函数代表 Encoder 对输入英文单词的某种变换函数。\n如 Encoder 是用 RNN model 的话\nf2 函数的结果某个输入 $x_i$ 后隐层节点的状态值\n$\\mathbf{g}$ 代表 Encoder 根据单词的中间表示合成整个句子中间语义表示的变换函数\n$\\mathbf{g}$ 函数对构成元素加权求和:\n$$\rC_{i}=\\sum_{j=1}^{L_{x}} a_{i j} h_{j}\r$$ $L_x$: Source的长度\n$a_{ij}$: 在 Target 输出第 i 个单词时, Source 中第 j 个单词的注意力分配系数\n$h_j$: Source 中第 j 个单词的语义编码\neg:\nif C_i的i指汤姆 L_x=3 h_1=f(\u0026#34;Tom\u0026#34;) h_2=f(\u0026#34;Chase\u0026#34;) h_3=f(\u0026#34;Jerry\u0026#34;) 对应注意力模型权值分别是0.6, 0.2, 0.2, 所以g函数本质上就是个加权求和函数, 如图\n如何知道Attention模型所需要的输入句子的单词注意力分配概率分布值呢?\n图 5 为非 Attention 模型的 Encoder-Decoder 框架, encoder 和 decoder 都使用 RNN 模型. 图 6 为添加注意力概率分布值的通用计算过程. 对于采用 RNN 的 decoder 来说, 在时刻 $i$, 如果要生成 $y_i$ 单词.\n目的: 计算得到 $y_i$ 时 source 的那三个单词对 $y_i$ 的注意力分配概率分布. 通过隐层节点 $i-1$ 时刻得到 $H_{i-1}$. 使用 $H_{i-1}$ 与 source 中每一个单词对应的 RNN 隐层节点状态(语义编码) $h_j$ 进行对比. (即 $F(h_j,H_{i-1})$)来获得目标单词 $y_i$ 和每个输入单词对应的对齐可能性. 这个 F 函数在不同论文里可能会采取不同的方法, 然后函数 F 的输出经过 Softmax 进行归一化就得到了符合概率分布取值区间的注意力分配概率分布数值. 4.1.3. Attention 机制的本质 如把 attention 机制从 E-D 框架剥离\n$$\rAttention(Query,Source) = \\sum_{i=1}^{L_x} Similarity(Query, Key_i)*Value_i\r$$$L_x$ 代表 Source 长度\n将 Source 中的构成元素想象成是由一系列的 $$ 数据对构成. 给定 Target 中某个元素 Query, 通过计算 Query 和各个 Key 的相似性/相关性, 得到每个 Key 对应 Value 的权重系数. (相似计算: 点积, cosine, MLP) 对 Value 加权求和, 从而得到 Attention 数值. https://blog.csdn.net/malefactor/article/details/78767781 待完善\n双竖线: 模长(向量长度)\nSelf Attention model\nAttention 机制: 发生在 Target 的元素 Query 和 Source 中的所有元素之间. Self Attention 机制: Source 内部元素之间或者 Target 内部元素之间发生的 Attention 机制. (算 source 就是把图 9 下面的公式中的 Query 变为 Source 中的元素; 算 target 同理) 4.2. Transformers 从RNN到\u0026quot;只要注意力\u0026quot;\u0026ndash;Transformer模型\n【NLP】Transformer模型原理详解\n超强动画，一步一步深入浅出解释Transformer原理！_哔哩哔哩_bilibili\n缩放点积注意力（Scaled Dot-Product Attention, SDPA）和多头注意力（Multi-Head Attention, MHA）\n在上述注意力机制的描述中涉及了三个集合: 查询集合 Q , 键集合 K 和值集合 V. 但是, 这些集合并非一定要各不相同, 常见情况分为三种:\n三个集合完全不同 QKV. 键和值集合是同一个集合 QVV. 即查询, 键和值三个集合实际是一回事. transformers 包括一个 encoder 栈和一个 decoder 栈\nencoder 栈中的每个 encoder 都包含 self-attention 模块加全连接层\ndecoder 栈中的每个 decoder 都包含 self-attention 模块 + encoder-decoder 的 self-attention + dense layer\n4.2.1. encoder self-attention 和 decoder self-attention encoder self-attention module\n编码器自注意力模块用来捕捉输入句子中词与词之间的关系\n$$\r\\text { attention }_{S D P A}(Q, K, V)=\\operatorname{softmax}\\left(\\frac{Q K^{T}}{\\sqrt{d_{k}}}\\right) V\r$$ decoder self-attention module\n不同的是添加了掩膜机制, 这是由于在解码器中, 自注意力模块只被允许处理当前项之前的那些项, 上述目标的实现方式非常简单, 只要在 softmax 注意力权重概率化之前, 用掩膜将当前处理项之后的所有项隐去即可.\n加掩膜机制是为了防止预测当前位置是不会接触到未来的信息.\n$$\r\\text { attention }_{S D P A}(Q, K, V)=\\operatorname{softmax}\\left(\\frac{Q K^{T} \\odot M}{\\sqrt{d_{k}}}\\right) V\r$$\nencoder-decoder self-attention module\nQVV 模式. Q 来自于上一个 decoder 的输出, V 来自于最后一个编码器的输出.\n该注意力模块能够使得解码器中的每个项都能够有重点的 “看一遍” 输入序列中的每一个词\n最后 linear + softmax\n4.3. BERT 一种深度双向的, 无监督的语言表示.\n整体预训练图\nMasked LM(masked language model)\n随机掩盖输入单词中的 $15\\%$, 不像 Word2Vec CBOW 一样把每个词都预测一遍.\n原因: 预测被掩盖的词, 就是一个单纯的分类问题. 根据这个位置的上下文在预测这个词, 而不是根据上一个词来预测这个词的概率(传统生成语言模型), 这种模型叫自编码语言模型 (Autoencoder LM). 正常的语言模型预测所有token, 所以masked LM相比正常的LM收敛的慢. Bert 和 Word2Vec (CBOW) 的区别 在预训练 (pre-training) 阶段, 模型使用 [MASK] 标签做分类任务训练, 这有点像词向量模型 CBOW, 只不过它使用更强的 Transformers 做语义特征提取器, 可以考虑到更长的上下文信息, 而不仅仅是直接取窗口长度单词之后使用浅层全连接模型做训练. CBOW 训练后得到的是每一个 token 的静态词向量, 而 Bert 是根据上下文信息学习出的词向量, 所以词义消歧 (WSD) 和词性标注 (POS) 表现更好. $15\\%$ 中 $80\\%$ 用 mask 标签替换, $10\\%$ 用随机单词替换, $10\\%$ 用原始单词.\n为什么这么做: 如果只扣掉 $15\\%$ 的单词, 在 fine-tuning 的时候模型不会使用 mask 标签, 并且可能会遇到没见过的单词.\n$10\\%$ 保留原始单词: 因为 fine-tuning 的时候的数据中所有的词都是已知的. 如果在 pre-training 的时候只用 [mask] 替换单词, 那么模型只知道根据其他词的信息来预测当前词, 而不会利用这个词本身的信息, 这样损失的信息可能不利于 fine-tuning.\n$10\\%$ 用的随机单词替换: 如果都使用原始单词, 模型会直接照抄当前保留的词. 使用 $10\\%$ 随机单词的话, 模型无法判断这个单词在这个位置是否正确, 预测 [mask] 时迫使模型依赖上下文去预测这个单词, 可以使模型具有一定的纠错能力.\nNext Sentence Prediction\n在一个文章中选两句话, 判断是不是连续的 ( $50\\%$ 概率).\n词嵌入 embedding\n符号[CLS][SEP]\ntoken embedding: 词向量 segment embedding: 句子的相对位置信息 (比如用 [SEP] 分割两个句子, 句子 2 都是 $E_A$ 句子 2 对应的单词都是 $E_B$) position embedding: 位置信息(单词位置, 就是 index) w2v 和 Bert 的区别\n训练方法不同, w2v 是单词与单词的位置关系进行训练, 计算词向量(skip-gram)\nBert 和 GPT 区别\n对比 OpenAI GPT (Generative pre-trained transformer), BERT是双向的 Transformer block 连接; 就像单向 RNN 和双向 RNN 的区别. GPT没有 encoder-decoder attention.\n由于 Bert 是双向的, 已经知道后面要预测的词了, 所以无法做生成任务.\n为什么 BERT 比 ELMo 效果好?\nLSTM 抽取特征的能力远弱于 Transformer BERT 的训练数据以及模型参数均多余 ELMo ELMo 和 BERT 的区别是什么?\nELMo 模型是通过语言模型任务得到句子中单词的 embedding 表示, 以此作为补充的新特征给下游任务使用, 因为 ELMO 给下游提供的是每个单词的特征形式, 所以这一类预训练的方法被称为 “Feature-based Pre-Training” BERT 模型是基于 Fine-tuning 模式, 这种做法和图像领域基于 Fine-tuning 的方式基本一致, 下游任务需要将模型改造成 BERT 模型 (接住 Bert 模型的输出), 才可利用 Bert 模型预训练好的参数. Bert 的缺点\npre-training 时, 被 mask 掉的单词之间的关系可能相互独立也可能相互存在联系. fine-tuning 的时候没有 mask 标签 $15\\%$ mask 训练慢. Bert 随机 mask wordpiece 分词可能会 mask 掉单词的一部分. word piece 分词\n一文读懂BERT中的WordPiece\n简单来说就是把单词再细分 (BPE (Byte-Pair Encoding) 双字节编码), 如: \u0026ldquo;loved\u0026rdquo;, \u0026ldquo;loving\u0026rdquo;, \u0026ldquo;loves\u0026rdquo; 可以变成 \u0026ldquo;lov\u0026rdquo;, \u0026ldquo;ed\u0026rdquo;, \u0026ldquo;ing\u0026rdquo;, \u0026ldquo;es\u0026rdquo;.\n原理:\n把一个一个字母按单词顺序放一起组合, 找出出现频率高的相邻序列, 把这个序列合并之后再组合, 循环.\n4.4. Roberta 更多训练数据, 更大的 batch size 训练更长时间 Dynamic Masking 训练同一条数据时, 会有不同 mask, 分别喂给不同 epoch 断句和起始符号不同 \u0026lt;s\u0026gt;\u0026lt;/s\u0026gt; 4.5. GPT-2 使用 40G 的高质量语料库训练, 比 Bert 更大 (16G) 使用 wordpiece model 解决 OOV 问题(和bert相同) 模型是单向 transformers 的, 所以可以语言生成任务. (bert是双向 transformers; ELMo 是双向LSTM 都不能做生成任务, 因为事先知道了答案) ","permalink":"https://sqf.icu/article/8d1565b9-cd7c-43db-81d4-7333e323d837/","summary":"\u003ch1 id=\"1-cnn\"\u003e1. CNN\u003c/h1\u003e\n\u003cp\u003e卷积核介绍\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://cloud.tencent.com/developer/article/1624813\"\u003eCNN中常用的四种卷积详解\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"11-一般卷积\"\u003e1.1. 一般卷积\u003c/h2\u003e\n\u003cp\u003e一个卷积核在图像上滑动，并求取对应元素相乘求和的过程.\u003c/p\u003e\n\u003cp\u003e使用参数:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e卷积核大小 (Kernel Size)\u003c/li\u003e\n\u003cli\u003e步长 (Stride)\u003c/li\u003e\n\u003cli\u003e填充 (Padding)\u003c/li\u003e\n\u003cli\u003e输入和输出通道数 (Input \u0026amp; Output Channels)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/media/4b8e425d7c2df76777c70ea9.png\"\u003e\u003c/p\u003e\n\u003cp\u003e普通卷积公式:\u003c/p\u003e","title":"一些 NLP 常见深度学习的网络结构介绍"},{"content":"1. 梯度问题 梯度\n梯度是一个向量, 表示某一函数在该点处的方向导数沿着该方向取得最大值.\n即函数在该点处沿着该方向(此梯度的方向)变化最快, 变化率最大(为该梯度的模).\n梯度下降\n目的: 减小真实值(gt)和预测值的距离 批量梯度下降法(Batch Gradient Descent) batch_size=样本总数 小批量梯度下降法(Mini-Batch Gradient Descent) batch_size=x(16, 32, 64 \u0026hellip;) 随机梯度下降(Stochastic Gradient Descent) batch_size=1 改进方法 Momentum (动量)\n$v_t=\\gamma v_{t-1}+\\eta g_t$\n$\\theta_{t+1}=\\theta_t-v_t$\n$\\gamma$: 阻力(衰减系数); $g_t$: 梯度; $v$: 前进步伐; $\\eta$: 学习速率\nAdam\n惯性保持: 记录梯度的一阶矩\n$m_t=\\beta_1m_{t-1}+(1-\\beta_1)g_t$\n环境感知: 记录梯度的二阶矩\n$v_t=\\beta_2v_{t-1}+(1-\\beta_2)g_t^2$\n更新函数\n$\\theta_{t+1}=\\theta_t-\\frac{\\eta\\cdot \\hat{m_t}}{\\sqrt{\\hat{v_t}+\\epsilon}}$\n$\\hat{m_t}=\\frac{m_t}{1-\\beta_1^t}$; $\\hat{v_t}=\\frac{v_t}{1-\\beta_2^t}$\nAdaDelta和RMSProp\n对AdaGrad的改进 AdaGrad使用所有历史梯度的平方和的平方根做分母, 所以分母随时间单调递增. 这两个采用指数衰退计算平均值的方法, 用历史梯度的均值代替求和. 2. 神经网络 正向传播和反向传播 正反向传播举例推导图\n3. 梯度爆炸和梯度消失问题 $f_{i+1}=f\\left(f_{i} * w_{i+1}+b_{i+1}\\right)$\nBP（反向传播算法）就是基于梯度下降策略，以目标的负梯度方向对参数进行调整，参数的更新为:\n$w=w+\\Delta w$,\n学习率$\\alpha$, 得出:\n$\\Delta w = -\\alpha\\frac{\\partial Loss}{w}$,\n如果更新第二层隐层的w的信息, 根据链式求导:\n$\\Delta w_{1}=\\frac{\\partial L o s s}{\\partial w_{2}}=\\frac{\\partial L o s s}{\\partial f_{4}} \\cdot \\frac{\\partial f_{4}}{\\partial f_{3}} \\cdot \\frac{\\partial f_{3}}{\\partial f_{2}} \\cdot \\frac{\\partial f_{2}}{\\partial w_{2}}$\n$\\frac{\\partial f_{4}}{\\partial f_{3}}$就是对激活函数进行求导\n如果此部分大于1，那么层数增多，最终的求出的梯度更新将以指数形式增加，即发生梯度爆炸\n如果此部分小于1，那么层数增多，梯度更新信息将会以指数形式衰减，即发生了梯度消失\n如何解决\n预训练加微调\n提出采取无监督逐层训练方法.\n每次训练一层隐节点，训练时将上一层隐节点的输出作为输入，而本层隐节点的输出作为下一层隐节点的输入，此过程是逐层“预训练”（pre-training）\n在预训练完成后，再对整个网络进行“微调”（fine-tunning）\n此思想相当于是先寻找局部最优，然后整合起来寻找全局最优，此方法有一定的好处，但是目前应用的不是很多了。\n梯度剪切, 正则化\n梯度剪切这个方案主要是针对梯度爆炸提出的\n其思想是设置一个梯度剪切阈值，然后更新梯度的时候，如果梯度超过这个阈值，那么就将其强制限制在这个范围之内。这可以防止梯度爆炸。梯度是$\\Delta W$.\n另外一种解决梯度爆炸的手段是采用权重正则化 (weithts regularization), 通过对网络权重做正则限制过拟合。\n$\\text { Loss }=\\left(y-W^{T} x\\right)^{2}+\\alpha\\|W\\|^{2}$\n$\\alpha$: 正则项系数. 如果梯度爆炸造成$||W||^2$很大, 用$\\alpha$来调节, 部分限制梯度爆炸的发生.\n比较常见的是l1正则，和l2正则.\n$l_{1}: \\Omega(w)=\\|w\\|_{1}=\\sum_{i}\\left|w_{i}\\right|$\n$l_{2}: \\Omega(w)=\\|w\\|_{2}^{2}=\\sum_{i} w_{i}^{2}$\nL2计算方便(求导直接就是2$w$, 而L1导数是一个常数), 对大数的惩罚更大, 防止过拟合\nTensorflow 搭建网络的时候已经设置了正则化参数，则调用以下代码可以直接计算出正则损失\nregularization_loss = tf.add_n(tf.losses.get_regularization_losses(scope=\u0026#39;my_resnet_50\u0026#39;)) 如果没有设置初始化参数，也可以使用以下代码计算$l_2$正则损失\nl2_loss = tf.add_n([tf.nn.l2_loss(var) for var in tf.trainable_variables() if \u0026#39;weights\u0026#39; in var.name]) Batch Normalization\nBatchnorm本质上是解决反向传播过程中的梯度问题\n因为深层神经网络在做非线性变换前的激活输入值（就是那个x=WU+B，U是输入）随着网络深度加深或者在训练过程中，其分布逐渐发生偏移或者变动，之所以训练收敛慢，一般是整体分布逐渐往非线性函数的取值区间的上下限两端靠近（对于Sigmoid函数来说，意味着激活输入值WU+B是大的负值或正值），所以这导致反向传播时低层神经网络的梯度消失，这是训练深层神经网络收敛越来越慢的本质原因，而BN就是通过一定的规范化手段，把每层神经网络任意神经元这个输入值的分布强行拉回到均值为0方差为1的标准正态分布，其实就是把越来越偏的分布强制拉回比较标准的分布，这样使得激活输入值落在非线性函数对输入比较敏感的区域，这样输入的小变化就会导致损失函数较大的变化，意思是这样让梯度变大，避免梯度消失问题产生，而且梯度变大意味着学习收敛速度快，能大大加快训练速度.\n批规范化，通过规范化操作将每一层的输出信号x规范化到均值为0，方差为1保证网络的稳定性.\n加速收敛\n控制过拟合，可以少用或不用Dropout和正则 降低网络对初始化权重敏感\n允许使用较大的学习率\n举个简单例子： 正向传播中 $f_{3}=f_{2}\\left(w^{T} * x+b\\right)$，那么反向传播中, $\\frac{\\partial f_{2}}{\\partial x}=\\frac{\\partial f_{2}}{\\partial f_{1}} w$ 中有w的存在，所以$w$的大小影响了梯度的消失和爆炸，batchnorm就是通过对每一层的输出做scale和shift的方法，通过一定的规范化手段，把每层神经网络任意神经元这个输入值的分布强行拉回到接近均值为0方差为1的标准正太分布，即严重偏离的分布强制拉回比较标准的分布，这样使得激活输入值落在非线性函数对输入比较敏感的区域，这样输入的小变化就会导致损失函数较大的变化，使得让梯度变大，避免梯度消失问题产生，而且梯度变大意味着学习收敛速度快，能大大加快训练速度。\n残差结构\n解决了梯度消失过快的问题. 因为残差的捷径(shortcut)部分的残差单元:\n深度残差网络 (Deep residual network, ResNet)\n你必须要知道CNN模型：ResNet\n深度网络的退化问题\n增加网络的深度可以使网络进行更加复杂的特征模式的提取, 可是加深网络层数会出现退化问题(Degradation problem).\n极端情况: 这些增加的层什么也不学习，仅仅复制浅层网络的特征，即这样新层是恒等映射 (Identity mapping)\n残差学习\n对于一个堆积层结构（几层堆积而成）当输入为 $x$ 时其学习到的特征记为 $H(x)$ ，现在我们希望其可以学习到残差 $F(x)=H(x)-x$，这样其实原始的学习特征是 $F(x)+x$ 。\n之所以这样是因为残差学习相比原始特征直接学习更容易。当残差为0时，此时堆积层仅仅做了恒等映射，至少网络性能不会下降，实际上残差不会为0，这也会使得堆积层在输入特征基础上学习到新的特征，从而拥有更好的性能。\n从数学的角度来分析, 残差单元可以表示为:\n$y_l=h(x_l)+F(x_l,W_l)$\n$x_{l+1}=f(y_l)$\n$x_l$ 和 $x_{l+1}$ 分别表示的是第 $l$ 个残差单元的输入和输出(每个残差单元一般包含多层结构如图6). $F$是残差函数, 表示学习到的残差. $h(x_l)=x_l$表示恒等映射. $f$表示ReLU激活函数. 正向传播, 学习特征为:\n$x_{L}=x_{l}+\\sum_{i=l}^{L-1} F\\left(x_{i}, W_{i}\\right)$\n反向过程的梯度:\n$\\frac{\\partial \\text { Loss }}{\\partial x_{l}}=\\frac{\\partial Loss}{\\partial x_{L}} \\cdot \\frac{\\partial x_{L}}{\\partial x_{l}}=\\frac{\\partial \\operatorname{Loss}}{\\partial x_{L}} \\cdot\\left(1+\\frac{\\partial}{\\partial x_{l}} \\sum_{i=l}^{L-1} F\\left(x_{i}, W_{i}\\right)\\right)$\n式子的第一个因子$\\frac{\\partial \\text { loss }}{\\partial x_{L}}$表示损失函数$Loss$到达$L$的梯度. 小括号中的1就是短路机制 (shortcut connection) 可以无损地传播梯度. 另外一项残差梯度则需要经过带有weights的层. 残差梯度不会那么巧全为-1, 而且有1所以不会梯度消失, 所以残差学习会更容易. 4. 梯度下降和梯度上升 都利用了BP算法 梯度下降 模型以参数化形式表示, 所以模型的更新等价于参数的更新 梯度上升 模型直接定义在函数空间中, 这就扩大了可以使用的模型种类 5. 神经网络参数初始化 为什么神经网络参数不能全部初始化为全0？\n第301页，深度学习，2016年（英文版）\n也许唯一已知完全确定的属性是初始参数需要在不同单元之间“打破对称性”。如果具有相同激活函数的两个隐藏单元连接到相同的输入，则这些单元必须具有不同的初始参数。如果它们具有相同的初始参数，那么应用于确定性成本和模型的确定性学习算法将以相同的方式不断更新这两个单元。\n6. 层数和神经元数量 如何确定神经网络的层数和隐藏层神经元数量?\n隐藏层的层数\n在神经网络中, 当且仅当数据非线性分离时才需要隐藏层.\n对于简单的数据集, 一两层隐藏层通常就够了 对于设计时间序列或计算机视觉的复杂数据集, 需要额外增加层数. 二分类问题(如两个类可以用一条直线分开(先行分离函数))只需要使用单层神经网络就行. 没有隐藏层：仅能够表示线性可分函数或决策\n隐藏层数=1：可以拟合任何“包含从一个有限空间到另一个有限空间的连续映射”的函数\n隐藏层数=2：搭配适当的激活函数可以表示任意精度的任意决策边界，并且可以拟合任何精度的任何平滑映射\n隐藏层数\u0026gt;2：多出来的隐藏层可以学习复杂的描述（某种自动特征工程）\n层数越深，理论上拟合函数的能力增强，效果按理说会更好，但是实际上更深的层数可能会带来过拟合的问题，同时也会增加训练难度，使模型难以收敛\n隐藏层中的神经元数量\n在隐藏层中使用太少的神经元将导致:\n欠拟合(underfitting) 隐藏层中的神经元过多(过多的信息处理能力)可能会导致:\n训练集中包含的有限信息量不足以训练隐藏层中的所有神经元 → 过拟合(overfitting) 即使训练数据包含的信息量足够，隐藏层中过多的神经元会增加训练时间. 对所有隐藏层使用相同数量的神经元就足够了.\n对于某些数据集，拥有较大的第一层并在其后跟随较小的层将导致更好的性能，因为第一层可以学习很多低阶的特征，这些较低层的特征可以馈入后续层中，提取出较高阶特征.\n与在每一层中添加更多的神经元相比，添加层层数将获得更大的性能提升. 因此，不要在一个隐藏层中加入过多的神经元.\n经验之谈:\n$N_{h}=\\frac{N_{s}}{\\left(\\alpha *\\left(N_{i}+N_{o}\\right)\\right)}$\n$N_i$ 是输入层神经元个数; $N_o$ 是输出层神经元个数; $N_s$ 是训练集的样本数; $\\alpha$ 是可以自取的任意值变量，通常范围可取 2-10. 经验之谈2:\n隐藏神经元的数量应在输入层的大小和输出层的大小之间. 隐藏神经元的数量应为输入层大小的2/3加上输出层大小的2/3. 隐藏神经元的数量应小于输入层大小的两倍. 如果过拟合的话，采用early-stopping, Batch Normalization, Dropout, 添加正则化项的方式。\n","permalink":"https://sqf.icu/article/b2ae0a7a-4b69-495b-9486-438655555358/","summary":"\u003ch1 id=\"1-梯度问题\"\u003e1. 梯度问题\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e梯度\u003c/p\u003e\n\u003cp\u003e梯度是一个向量, 表示某一函数在该点处的方向导数沿着该方向取得最大值.\u003c/p\u003e\n\u003cp\u003e即函数在该点处沿着该方向(此梯度的方向)变化最快, 变化率最大(为该梯度的模).\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e梯度下降\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e目的: 减小真实值(gt)和预测值的距离\u003c/li\u003e\n\u003cli\u003e批量梯度下降法(\u003cstrong\u003eBatch Gradient Descent\u003c/strong\u003e) batch_size=样本总数\u003c/li\u003e\n\u003cli\u003e小批量梯度下降法(\u003cstrong\u003eMini-Batch Gradient Descent\u003c/strong\u003e) batch_size=x(16, 32, 64 \u0026hellip;)\u003c/li\u003e\n\u003cli\u003e随机梯度下降(\u003cstrong\u003eStochastic Gradient Descent\u003c/strong\u003e) batch_size=1\u003c/li\u003e\n\u003cli\u003e改进方法\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eMomentum (动量)\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e$v_t=\\gamma v_{t-1}+\\eta g_t$\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e$\\theta_{t+1}=\\theta_t-v_t$\u003c/p\u003e\n\u003cp\u003e$\\gamma$: 阻力(衰减系数); $g_t$: 梯度; $v$: 前进步伐; $\\eta$: 学习速率\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eAdam\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e惯性保持: 记录梯度的一阶矩\u003c/p\u003e\n\u003cp\u003e$m_t=\\beta_1m_{t-1}+(1-\\beta_1)g_t$\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e环境感知: 记录梯度的二阶矩\u003c/p\u003e\n\u003cp\u003e$v_t=\\beta_2v_{t-1}+(1-\\beta_2)g_t^2$\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e更新函数\u003c/p\u003e\n\u003cp\u003e$\\theta_{t+1}=\\theta_t-\\frac{\\eta\\cdot \\hat{m_t}}{\\sqrt{\\hat{v_t}+\\epsilon}}$\u003c/p\u003e\n\u003cp\u003e$\\hat{m_t}=\\frac{m_t}{1-\\beta_1^t}$; $\\hat{v_t}=\\frac{v_t}{1-\\beta_2^t}$\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eAdaDelta和RMSProp\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e对AdaGrad的改进\u003c/li\u003e\n\u003cli\u003eAdaGrad使用所有历史梯度的平方和的平方根做分母, 所以分母随时间单调递增.\u003c/li\u003e\n\u003cli\u003e这两个\u003cdel\u003e采用指数衰退计算平均值的方法,\u003c/del\u003e 用历史梯度的均值代替求和.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"神经网络介绍"},{"content":"简介\n*args 和 **kwargs *是必要的, 后面的变量可以变换\n*args 是用来发送一个非键值对的可变数量的参数列表给一个函数.\ndef test_var_args(f_arg, *argv): print(\u0026#34;first normal arg:\u0026#34;, f_arg) for arg in argv: print(\u0026#34;another arg through *argv:\u0026#34;, arg) test_var_args(\u0026#39;yasoob\u0026#39;, \u0026#39;python\u0026#39;, \u0026#39;eggs\u0026#39;, \u0026#39;test\u0026#39;) **kwargs允许你将不定长度的键值对, 作为参数传递给一个函数.\ndef greet_me(**kwargs): for key, value in kwargs.items(): print(\u0026#34;{0} == {1}\u0026#34;.format(key, value)) \u0026gt;\u0026gt;\u0026gt; greet_me(name=\u0026#34;yasoob\u0026#34;) name == yasoob 如果你想在函数里同时使用所有这三种参数\nsome_func(fargs, *args, **kwargs) 生成器(Generators) yield\n生成器也是一种迭代器，但是你只能对其迭代一次。这是因为它们并没有把所有的值存在内存中，而是在运行时生成值。 你通过遍历来使用它们，要么用一个“for”循环，要么将它们传递给任意可以进行迭代的函数和结构。 def generator_function(): for i in range(10): yield i for item in generator_function(): print(item) # Output: 0 # 1 # 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9 许多Python 2里的标准库函数都会返回列表，而Python 3都修改成了返回生成器，因为生成器占用更少的资源。\nMap, Filter, Reduce Map: 会将一个函数映射到一个输入列表的所有元素上。\nmap(function_to_apply, list_of_inputs) items = [1, 2, 3, 4, 5] squared = list(map(lambda x: x**2, items)) Filter: 过滤列表中的元素，并且返回一个由所有符合要求的元素所构成的列表\nnumber_list = range(-5, 5) less_than_zero = filter(lambda x: x \u0026lt; 0, number_list) print(list(less_than_zero)) # 译者注：上面print时，加了list转换，是为了python2/3的兼容性 # 在python2中filter直接返回列表，但在python3中返回迭代器 # 因此为了兼容python3, 需要list转换一下 # Output: [-5, -4, -3, -2, -1] Reduce: 当需要对一个列表进行一些计算并返回结果时使用\nfrom functools import reduce product = reduce( (lambda x, y: x * y), [1, 2, 3, 4] ) # Output: 24 Set数据结构 set与列表(list)的行为类似，区别在于set不能包含重复的值.\n检查列表中是否包含重复的元素\n\u0026#34;\u0026#34;\u0026#34; For循环 \u0026#34;\u0026#34;\u0026#34; some_list = [\u0026#39;a\u0026#39;, \u0026#39;b\u0026#39;, \u0026#39;c\u0026#39;, \u0026#39;b\u0026#39;, \u0026#39;d\u0026#39;, \u0026#39;m\u0026#39;, \u0026#39;n\u0026#39;, \u0026#39;n\u0026#39;] duplicates = [] for value in some_list: if some_list.count(value) \u0026gt; 1: if value not in duplicates: duplicates.append(value) print(duplicates) ### 输出: [\u0026#39;b\u0026#39;, \u0026#39;n\u0026#39;] \u0026#34;\u0026#34;\u0026#34; set \u0026#34;\u0026#34;\u0026#34; some_list = [\u0026#39;a\u0026#39;, \u0026#39;b\u0026#39;, \u0026#39;c\u0026#39;, \u0026#39;b\u0026#39;, \u0026#39;d\u0026#39;, \u0026#39;m\u0026#39;, \u0026#39;n\u0026#39;, \u0026#39;n\u0026#39;] duplicates = set([x for x in some_list if some_list.count(x) \u0026gt; 1]) print(duplicates) ### 输出: set([\u0026#39;b\u0026#39;, \u0026#39;n\u0026#39;]) 交集(intersection): 你对比两个集合的交集（两个集合中都有的数据）\nvalid = set([\u0026#39;yellow\u0026#39;, \u0026#39;red\u0026#39;, \u0026#39;blue\u0026#39;, \u0026#39;green\u0026#39;, \u0026#39;black\u0026#39;]) input_set = set([\u0026#39;red\u0026#39;, \u0026#39;brown\u0026#39;]) print(input_set.**intersection**(valid)) ### 输出: set([\u0026#39;red\u0026#39;]) 差集(difference): 找出无效的数据，相当于用一个集合减去另一个集合的数据\nvalid = set([\u0026#39;yellow\u0026#39;, \u0026#39;red\u0026#39;, \u0026#39;blue\u0026#39;, \u0026#39;green\u0026#39;, \u0026#39;black\u0026#39;]) input_set = set([\u0026#39;red\u0026#39;, \u0026#39;brown\u0026#39;]) print(input_set.**difference**(valid)) ### 输出: set([\u0026#39;brown\u0026#39;]) 创建集合可以用{}, 不用set()\n三元运算符 is_fat = True state = \u0026#34;fat\u0026#34; if is_fat else \u0026#34;not fat\u0026#34; 装饰器 原始版本\ndef a_new_decorator(a_func): def wrapTheFunction(): print(\u0026#34;before a_func()\u0026#34;) a_func() print(\u0026#34;after a_func()\u0026#34;) return wrapTheFunction def a_function_requiring_decoration(): print(\u0026#34;smell\u0026#34;) a_function_requiring_decoration() #outputs: \u0026#34;smell\u0026#34; a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration) #now a_function_requiring_decoration is wrapped by wrapTheFunction() a_function_requiring_decoration() #outputs:before a_func() # smell # after a_func() 装饰器版本\n# from functools import wraps def a_new_decorator(a_func): # @wraps(a_func) def wrapTheFunction(): print(\u0026#34;before a_func()\u0026#34;) a_func() print(\u0026#34;after a_func()\u0026#34;) return wrapTheFunction @a_new_decorator def a_function_requiring_decoration(): print(\u0026#34;smell\u0026#34;) a_function_requiring_decoration() #outputs:before a_func() # smell # after a_func() 存在问题, 不显示原函数名\nprint(a_function_requiring_decoration.__name__) # Output: wrapTheFunction 添加 @wraps(a_func) (@wraps接受一个函数来进行装饰，并加入了复制函数名称、注释文档、参数列表等等的功能。)\nprint(a_function_requiring_decoration.__name__) # Output: a_function_requiring_decoration wrap 日志: 日志是装饰器运用的另一个亮点\nfrom functools import wraps def logit(func): @wraps(func) def with_logging(*args, **kwargs): print(func.__name__ + \u0026#34; was called\u0026#34;) return func(*args, **kwargs) return with_logging @logit def addition_func(x): \u0026#34;\u0026#34;\u0026#34;Do some math.\u0026#34;\u0026#34;\u0026#34; return x + x result = addition_func(4) # Output: addition_func was called 还有详细logit构建, 发邮件啥的 对象变动 Mutation 不可变(immutable)对象 int, string, float, tuple 可变(mutation)对象 dict, list, set slots 默认情况下Python用一个字典来保存一个对象的实例属性。这非常有用，因为它允许我们在运行时去设置任意的新属性。 然而，对于有着已知属性的小类来说，它可能是个瓶颈。这个字典浪费了很多内存。 使用__slots__来告诉Python不要使用字典，而且只给一个固定集合的属性分配空间。 class MyClass(object): __slots__ = [\u0026#39;name\u0026#39;, \u0026#39;identifier\u0026#39;] # 使用slots减少内存占用 def __init__(self, name, identifier): self.name = name self.identifier = identifier self.set_up() # ... 虚拟环境(virtualenv) pip install virtualenv virtualenv myproject source myproject/bin/activate 如果你想让你的virtualenv使用系统全局模块\nvirtualenv --system-site-packages mycoolproject 退出虚拟环境\ndeactivate 容器 Collections defaultdict 与dict不同, 你不需要检查key是否存在. 当你在一个字典中对一个键进行嵌套赋值时，如果这个键不存在，会触发keyError异常。 defaultdict允许我们用一个聪明的方式绕过这个问题。 counter Counter是一个计数器，它可以帮助我们针对某项数据进行计数。\nfrom collections import Counter colours = ( (\u0026#39;Yasoob\u0026#39;, \u0026#39;Yellow\u0026#39;), (\u0026#39;Ali\u0026#39;, \u0026#39;Blue\u0026#39;), (\u0026#39;Arham\u0026#39;, \u0026#39;Green\u0026#39;), (\u0026#39;Ali\u0026#39;, \u0026#39;Black\u0026#39;), (\u0026#39;Yasoob\u0026#39;, \u0026#39;Red\u0026#39;), (\u0026#39;Ahmed\u0026#39;, \u0026#39;Silver\u0026#39;), ) favs = Counter(name for name, colour in colours) print(favs) ## 输出: ## Counter({ ## \u0026#39;Yasoob\u0026#39;: 2, ## \u0026#39;Ali\u0026#39;: 2, ## \u0026#39;Arham\u0026#39;: 1, ## \u0026#39;Ahmed\u0026#39;: 1 ## }) 统计文件\nwith open(\u0026#39;filename\u0026#39;, \u0026#39;rb\u0026#39;) as f: line_count = Counter(f) print(line_count) deque\ndeque提供了一个双端队列，你可以从头/尾两端添加或删除元素.\n可以像list一样用\nfrom collections import deque d = deque() d.append(1) print(d[0]) d.popleft() # pop最左边 d.pop() # pop最右边 d = deque(maxlen=30) # 设置最大长度, deque塞满时, 最左的元素自动删除 你还可以从任一端扩展这个队列中的数据:\nd = deque([1,2,3,4,5]) d.extendleft([0]) # 左边添加 d.extend([6,7,8]) # 右边添加 print(d) ## 输出: deque([0, 1, 2, 3, 4, 5, 6, 7, 8]) 命名元组 (namedtuple)\nfrom collections import namedtuple Animal = namedtuple(\u0026#39;Animal\u0026#39;, \u0026#39;name age type\u0026#39;) perry = Animal(name=\u0026#34;perry\u0026#34;, age=31, type=\u0026#34;cat\u0026#34;) print(perry) ## 输出: Animal(name=\u0026#39;perry\u0026#39;, age=31, type=\u0026#39;cat\u0026#39;) print(perry.name) ## 输出: \u0026#39;perry\u0026#39; print(perry[0]) ## 输出: perry ############## perry.age = 42 # x ## 输出: ## Traceback (most recent call last): ## File \u0026#34;\u0026#34;, line 1, in ## AttributeError: can\u0026#39;t set attribute ############### print(perry._asdict()) # 将一个命名元组转换为字典 ## 输出: OrderedDict([(\u0026#39;name\u0026#39;, \u0026#39;Perry\u0026#39;), (\u0026#39;age\u0026#39;, 31), ... 枚举 Enumerate for counter, value in enumerate(some_list): print(counter, value) my_list = [\u0026#39;apple\u0026#39;, \u0026#39;banana\u0026#39;, \u0026#39;grapes\u0026#39;, \u0026#39;pear\u0026#39;] for c, value in enumerate(my_list, 1): # 这个可选参数允许我们定制从哪个数字开始枚举 print(c, value) # 输出: (1, \u0026#39;apple\u0026#39;) (2, \u0026#39;banana\u0026#39;) (3, \u0026#39;grapes\u0026#39;) (4, \u0026#39;pear\u0026#39;) 对象自省 dir: 返回一个列表，列出了一个对象所拥有的属性和方法。\nmy_list = [1, 2, 3] dir(my_list) # Output: [\u0026#39;__add__\u0026#39;, \u0026#39;__class__\u0026#39;, \u0026#39;__contains__\u0026#39;, \u0026#39;__delattr__\u0026#39;, \u0026#39;__delitem__\u0026#39;, # \u0026#39;__delslice__\u0026#39;, \u0026#39;__doc__\u0026#39;, \u0026#39;__eq__\u0026#39;, \u0026#39;__format__\u0026#39;, \u0026#39;__ge__\u0026#39;, \u0026#39;__getattribute__\u0026#39;, # \u0026#39;__getitem__\u0026#39;, \u0026#39;__getslice__\u0026#39;, \u0026#39;__gt__\u0026#39;, \u0026#39;__hash__\u0026#39;, \u0026#39;__iadd__\u0026#39;, \u0026#39;__imul__\u0026#39;, # \u0026#39;__init__\u0026#39;, \u0026#39;__iter__\u0026#39;, \u0026#39;__le__\u0026#39;, \u0026#39;__len__\u0026#39;, \u0026#39;__lt__\u0026#39;, \u0026#39;__mul__\u0026#39;, \u0026#39;__ne__\u0026#39;, # \u0026#39;__new__\u0026#39;, \u0026#39;__reduce__\u0026#39;, \u0026#39;__reduce_ex__\u0026#39;, \u0026#39;__repr__\u0026#39;, \u0026#39;__reversed__\u0026#39;, \u0026#39;__rmul__\u0026#39;, # \u0026#39;__setattr__\u0026#39;, \u0026#39;__setitem__\u0026#39;, \u0026#39;__setslice__\u0026#39;, \u0026#39;__sizeof__\u0026#39;, \u0026#39;__str__\u0026#39;, # \u0026#39;__subclasshook__\u0026#39;, \u0026#39;append\u0026#39;, \u0026#39;count\u0026#39;, \u0026#39;extend\u0026#39;, \u0026#39;index\u0026#39;, \u0026#39;insert\u0026#39;, \u0026#39;pop\u0026#39;, # \u0026#39;remove\u0026#39;, \u0026#39;reverse\u0026#39;, \u0026#39;sort\u0026#39;] type: 返回一个对象的类型\nid: 返回任意不同种类对象的唯一ID, 内存地址.\ninspect: 获取活跃对象的信息\nimport inspect print(inspect.getmembers(str)) # Output: [(\u0026#39;__add__\u0026#39;, \u0026lt;slot wrapper \u0026#39;__add__\u0026#39; of ... ... 列表推导式, 字典推导式, 集合推导式 list\nvariable = [out_exp for out_exp in input_list if out_exp == 2] squared = [x**2 for x in range(10)] dict\n# 把同一个字母但不同大小写的值合并起来 mcase = {\u0026#39;a\u0026#39;: 10, \u0026#39;b\u0026#39;: 34, \u0026#39;A\u0026#39;: 7, \u0026#39;Z\u0026#39;: 3} mcase_frequency = { k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys() } # mcase_frequency == {\u0026#39;a\u0026#39;: 17, \u0026#39;z\u0026#39;: 3, \u0026#39;b\u0026#39;: 34} # 快速对换一个字典的键和值 {v: k for k, v in some_dict.items()} squared\nsquared = {x**2 for x in [1, 1, 2]} print(squared) # Output: {1, 4} 异常 try except\ntry: file = open(\u0026#39;test.txt\u0026#39;, \u0026#39;rb\u0026#39;) except IOError as e: # 处理一个IOError的异常 print(\u0026#39;An IOError occurred. {}\u0026#39;.format(e.args[-1])) try: file = open(\u0026#39;test.txt\u0026#39;, \u0026#39;rb\u0026#39;) except EOFError as e: print(\u0026#34;An EOF error occurred.\u0026#34;) raise e except IOError as e: print(\u0026#34;An error occurred.\u0026#34;) raise e try: file = open(\u0026#39;test.txt\u0026#39;, \u0026#39;rb\u0026#39;) except Exception: # 捕获所有异常 # 打印一些异常日志，如果你想要的话 raise finally从句: 包裹到finally从句中的代码不管异常是否触发都将会被执行.\ntry: file = open(\u0026#39;test.txt\u0026#39;, \u0026#39;rb\u0026#39;) except IOError as e: print(\u0026#39;An IOError occurred. {}\u0026#39;.format(e.args[-1])) finally: print(\u0026#34;This would be printed whether or not an exception occurred!\u0026#34;) # Output: An IOError occurred. No such file or directory # This would be printed whether or not an exception occurred! try/else从句: 没有触发异常时运行\ntry: print(\u0026#39;I am sure no exception is going to occur!\u0026#39;) except Exception: print(\u0026#39;exception\u0026#39;) else: # 这里的代码只会在try语句里没有触发异常时运行, # 但是这里的异常将 *不会* 被捕获 print(\u0026#39;This would only run if no exception occurs. And an error here \u0026#39; \u0026#39;would NOT be caught.\u0026#39;) finally: print(\u0026#39;This would be printed in every case.\u0026#39;) # Output: I am sure no exception is going to occur! # This would only run if no exception occurs. # This would be printed in every case. lambda表达式 lambda 参数:操作(参数) add = lambda x, y: x + y print(add(3, 5)) # Output: 8 for-else else从句会在循环正常结束时执行 for item in container: if search_something(item): # Found it! process(item) break else: # Didn\u0026#39;t find anything.. not_found_in_container() 使用C扩展 CTypes\nfrom ctypes import * Open函数 with open(\u0026#39;photo.jpg\u0026#39;, \u0026#39;r+\u0026#39;) as f: jpgdata = f.read() 读取一个文件，检测它是否是JPG（提示：这些文件头部以字节FF D8开始） with open(\u0026#39;photo.jpg\u0026#39;, \u0026#39;rb\u0026#39;) as inf: jpgdata = inf.read() if jpgdata.startswith(b\u0026#39;\\xff\\xd8\u0026#39;): text = u\u0026#39;This is a JPEG file (%d bytes long)\\n\u0026#39; else: text = u\u0026#39;This is a random file (%d bytes long)\\n\u0026#39; 函数缓存 设置最多缓存最近多少个返回值 缓存多的话, 可重复调用的值, 节省运行时间 cache_info() 用于查看缓存信息 from functools import lru_cache @lru_cache(maxsize=32) # 最好设置为 2 的倍数，默认为 128。None 的话就相当于是 maxsize 为正无穷了 def fib(n): if n \u0026lt; 2: return n return fib(n-1) + fib(n-2) \u0026gt;\u0026gt;\u0026gt; print([fib(n) for n in range(10)]) # Output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] fib.cache_clear() # 对返回值清空缓存 上下文管理器 class File(object): def __init__(self, file_name, method): self.file_obj = open(file_name, method) def __enter__(self): return self.file_obj def __exit__(self, type, value, traceback): self.file_obj.close() with File(\u0026#39;demo.txt\u0026#39;, \u0026#39;w\u0026#39;) as opened_file: opened_file.write(\u0026#39;Hola!\u0026#39;) 当异常发生时，with语句会采取哪些步骤。 它把异常的type,value和traceback传递给__exit__方法 它让__exit__方法来处理异常 如果__exit__返回的是True，那么这个异常就被优雅地处理了。 如果__exit__返回的是True以外的任何东西，那么这个异常将被with语句抛出。 bisect 数组二分查找算法 这个模块对有序列表提供了支持，使得他们可以在插入新数据仍然保持有序。对于长列表，如果其包含元素的比较操作十分昂贵的话，这可以是对更常见方法的改进。\nbisect.**bisect_left**(a, x, lo=0, hi=len(a), ***, key=None)\n在 a 中找到 x 合适的插入点以维持有序。参数 lo 和 hi 可以被用于确定需要考虑的子集；默认情况下整个列表都会被使用。如果 x 已经在 a 里存在，那么插入点会在已存在元素之前（也就是左边）。如果 a 是列表（list）的话，返回值是可以被放在 list.insert() 的第一个参数的。 返回的插入点 i 将数组 a 分成两半，使得 all(val \u0026lt; x for val in a[lo : i]) 在左半边而 all(val \u0026gt;= x for val in a[i : hi]) 在右半边。 key 指定带有单个参数的 key function 用来从数组的每个元素中提取比较键。 为了支持搜索复杂记录，键函数不会被应用到 x 值。 如果 key 为 None，则将直接进行元素比较而不需要中间的函数调用。 在 3.10 版更改: 增加了 key 形参。\npython中的特殊方法 python中的特殊方法被python解释器调用, 我们一般不会亲自调用.\n我们可以使用内置函数来使用. eg: __len()__实现后, 使用len()即可.\n也有特殊方法的调用是隐式的. eg: for i in x, 使用的是内置函数iter(x).\n详细见:\nPython基础-特殊方法\n特殊（魔术）方法汇总一览表\n","permalink":"https://sqf.icu/article/bb85b582-8dcb-45db-95e6-166a23d74ef0/","summary":"\u003cp\u003e\u003ca href=\"https://eastlakeside.gitbook.io/interpy-zh/\"\u003e简介\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"args-和-kwargs\"\u003e*args 和 **kwargs\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e*是必要的, 后面的变量可以变换\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e*args 是用来发送一个非键值对的可变数量的参数列表给一个函数.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etest_var_args\u003c/span\u003e(f_arg, \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eargv):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    print(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;first normal arg:\u0026#34;\u003c/span\u003e, f_arg)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e arg \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e argv:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        print(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;another arg through *argv:\u0026#34;\u003c/span\u003e, arg)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etest_var_args(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;yasoob\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;python\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;eggs\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;test\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e**kwargs允许你将不定长度的键值对, 作为参数传递给一个函数.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egreet_me\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e**\u003c/span\u003ekwargs):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e key, value \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e kwargs\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eitems():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        print(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{0}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e == \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{1}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eformat(key, value))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u0026gt;\u003c/span\u003e greet_me(name\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;yasoob\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ename \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e yasoob\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e如果你想在函数里同时使用所有这三种参数\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esome_func(fargs, \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eargs, \u003cspan style=\"color:#f92672\"\u003e**\u003c/span\u003ekwargs)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":"Python的高级用法"},{"content":"1. 准备工作 精简固件可以不刷, 小米盒子一般只要卸载应用就可以去掉所有广告了, 直接调到第3章\n小米盒子4/4c\nusb双公头线(刷固件用)\npc\npc线刷使用软件, 驱动和固件\nYesStbTool_Secure_test20191027 # 无线连接+adb Amlogic USB Burning Tool_v2.1.6.8 # 烧录固件用 libusb0.dll # 可能需要的驱动, usb驱动 InstallDriver_Worldcup.exe # 可能需要的驱动 MiBOX4_YQZM2_root_aml_upgrade_package20200808.img # 使用的精简固件 2. 刷入固件 2.1. 设置盒子 下边有部分图片参考\n小米盒子4/4c带root刷机教程，及如何刷AndroidTV系统\n小米盒子内置应用如何卸载 小米盒子内置应用卸载教程_小米盒子论坛_ZNDS\n允许开发者选项\n开启adb调式\nadb调试的选项上有允许安装第三方app, 顺手允许\n连接wifi, 确认ip地址\nusb双头线连接pc和盒子\n2.2. 刷固件 安装并打开USB Burning Tool, 选择文件-导入烧录包 选择MiBOX4_YQZM2_root_aml_upgrade_package20200808.img 点击开始 (先放着) 打开YesStbTool_Secure_test20191027-YesStbToolvm.exe 输入设备ip地址, 点击连接 (注意盒子重启后有概率自动关闭adb调试, 这个时候连接会报错, 并提示一些乱码)\n连接成功后, 点击ADB shell输入命令(重启进入线刷模式)\nreboot update 稍等一下就可以听见usb接入的声音, USB Burning Tool应该开始烧录了.\n烧录成功之后, 拔掉usb线, 重新接电源启动盒子.\n3. 安装app 复制apk文件到u盘, 插上盒子安装app\n默认的桌面不好用, 先装上其他桌面app, 然后需要设置该桌面app开机启动.\n卸载系统应用,ADB shell输入命令\npm uninstall --user 0 com.yangqi.rom.launcher.free # 第三方固件可能自带的氧气桌面 # 小米原生系统需要删除的app pm uninstall --user 0 mitv.service pm uninstall --user 0 com.xiaomi.mitv.upgrade pm uninstall --user 0 com.mitv.tvhome pm uninstall --user 0 com.xiaomi.mitv.shop pm uninstall --user 0 com.xiaomi.mitv.payment pm uninstall --user 0 com.mipay.wallet.tv pm uninstall --user 0 com.xiaomi.mibox.gamecenter pm uninstall --user 0 com.miui.systemAdSolution pm uninstall --user 0 com.xiaomi.mitv.advertise pm uninstall --user 0 com.mitv.gallery pm uninstall --user 0 com.duokan.videodaily pm uninstall --user 0 com.xiaomi.statistic pm uninstall --user 0 com.android.location.fused pm uninstall --user 0 com.xiaomi.mitv.tvpush.tvpushservice pm uninstall --user 0 com.xiaomi.mitv.calendar pm uninstall --user 0 com.xiaomi.mitv.tvmanager pm uninstall --user 0 com.xiaomi.tv.gallery pm uninstall --user 0 com.mitv.codec.update pm uninstall --user 0 com.xiaomi.tv.appupgrade 重启盒子\n4. 小米4s精简 默认安装的程序\nshell@transformers:/ $ pm list packages package:com.mitv.screensaver package:com.duokan.airkan.tvbox package:com.android.providers.media package:com.xiaomi.account package:com.mitv.tvhome package:com.xiaomi.tv.gallery package:com.mitv.alarmcenter package:com.sohu.inputmethod.sogou.tv package:com.android.externalstorage package:com.xiaomi.gamecenter.sdk.service.mibox package:com.android.providers.downloads package:com.droidlogic package:com.dangbei.tvlauncher package:com.mitv.codec.update package:com.xiaomi.tweather package:com.mitv.shoplugin package:com.xm.webcontent package:com.xiaomi.mitv.appstore package:com.android.defcontainer package:com.android.pacprocessor package:com.miui.daemon package:com.android.certinstaller package:com.xiaomi.mitv.settings package:com.xiaomi.mitv.providers.settings package:android package:com.android.statementservice package:com.xiaomi.mitv.mediaexplorer package:com.xiaomi.mitv.systemui package:com.android.providers.settings package:com.xiaomi.smarthome.tv package:com.android.sharedstoragebackup package:com.xiaomi.mibox.lockscreen package:com.mitv.videoplayer package:com.starcor.mango package:com.bilibili.tv package:com.elinkway.tvlive2.beta package:com.xiaomi.screenrecorder package:com.xiaomi.mitv.smartshare package:com.xiaomi.voicecontrol package:com.xiaomi.tv.nameservice package:com.xiaomi.mimusic2 package:com.google.android.webview package:com.android.keychain package:com.xiaomi.mitv.pay package:com.xiaomi.mitv.advertise package:com.android.packageinstaller package:com.android.proxyhandler package:com.xiaomi.devicereport package:com.dianshijia.fasttv package:com.mitv.mivideoplayer package:com.mitv.gallery package:com.duokan.videodaily package:com.xiaomi.tv.appupgrade package:com.miui.tv.analytics package:com.xiaomi.statistic package:com.android.vpndialogs package:com.android.shell package:com.xiaomi.mitv.remotecontroller.service package:com.android.location.fused package:com.android.systemui package:com.xiaomi.mitv.tvpush.tvpushservice package:com.xiaomi.account.auth package:com.xiaomi.mitv.calendar package:com.android.bluetooth package:com.android.captiveportallogin package:com.miui.core package:com.xiaomi.mitv.tvmanager 按照第3章卸载应用即可\n5. 央视直播 https://github.com/mengzehe/TVBox\n目前可用app:\n电视仓(需要使用直播源)\n电视直播(IOS)\n央视频tv版(Android)\n目前可用源\nhttp://home.jundie.top:81/top98.json ","permalink":"https://sqf.icu/article/f275d975-3b2c-4d3d-800e-48a5b34f560b/","summary":"\u003ch1 id=\"1-准备工作\"\u003e1. 准备工作\u003c/h1\u003e\n\u003cp\u003e精简固件可以不刷, 小米盒子一般只要卸载应用就可以去掉所有广告了, 直接调到第3章\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e小米盒子4/4c\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eusb双公头线(刷固件用)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003epc\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003epc线刷使用软件, 驱动和固件\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eYesStbTool_Secure_test20191027  \u003cspan style=\"color:#75715e\"\u003e# 无线连接+adb\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAmlogic USB Burning Tool_v2.1.6.8  \u003cspan style=\"color:#75715e\"\u003e# 烧录固件用\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elibusb0.dll  \u003cspan style=\"color:#75715e\"\u003e# 可能需要的驱动, usb驱动\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eInstallDriver_Worldcup.exe  \u003cspan style=\"color:#75715e\"\u003e# 可能需要的驱动\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eMiBOX4_YQZM2_root_aml_upgrade_package20200808.img  \u003cspan style=\"color:#75715e\"\u003e# 使用的精简固件\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":"小米盒子 4c/4s 精简去广告"},{"content":"0. 微超主板登陆 超微主板使用配置 ipmi 功能流程介绍\n用户名和密码都是: ADMIN 可以在配置-用户中更改密码 设置时间\n显示画面\n在远程控制中找到iKVM/HTML5, 可以启动远程管理服务器, 在网页端直接看到开机时显示的bios等画面, 就不需要外接显示器了.\n1. 账号设置Local Users 在Credentials - Local Users中可以添加用户, 但是无法在系统盘下设定用户目录.\n这个用户用于管理员操作, 所以在设置账号的时候给这个用户的Auxiliary Groups添加builtin-administrator\n设定用户目录, 这样ssh登录时会自动到达这个路径\nsudo mkdir /mnt/[存储池的名称]/home/[user文件夹] cd /mnt/[存储池的名称]/home/ sudo chgrp [用户名] [user文件夹] sudo chown [用户名] [user文件夹] # 文件夹下的所有文件(如果存在)都需要改一下用户所属 安全起见. admin账号建议锁定. 锁定后这两个账号就不能用于网页和ssh登陆了.\n2. 调整时间 TrueNas的系统时间如果与Bios的时间不一致, 会导致Reporting数据无法显示.\nweb页面设置 System Settings - General\n修改 Localization - timezoom 为当地时间Asia/Shanghai\nssh登录相同user\n查看时间是否正确, Local time 为现在当地的时间, Universal time时UTC的时间, 应与当地时间有时差, 注意RTC time是主板设置的时间, 应与local time相同.\n$ timedatectl Local time: Wed 2023-04-19 21:32:13 CST Universal time: Wed 2023-04-19 13:32:13 UTC RTC time: Wed 2023-04-19 13:32:13 Time zone: Asia/Shanghai (CST, +0800) System clock synchronized: no NTP service: n/a RTC in local TZ: no 设定Local time (这个和Time zone应该是和True nas网页端设定的时间同步的)\n~~sudo date --set 2023-04-18 sudo date --set 19:15:38~~ BIOS设定时间\n需要进入bios中设置, 这和在ipmi网页端设定的时间不同步. 这个时间必须是UTC+0. 3. 修改各个服务的端口 网页http端口: System Settings - General - Gui, 修改Web Interface HTTP Port端口, 以后的网页登录时需要加端口: http://192.168.31.229:[端口]\nssh端口: System Settings - Services, 修改ssh端口(在添加密钥后将密码登录关闭)\nssh进一步设定可以在命令行进行\n~~sudo vi /etc/ssh/sshd_config # 在末尾添上 PasswordAuthentication no PermitRootLogin no AllowUsers sun X11Forwarding no~~ 先创建.ssh文件夹: sudo ssh-keygen\n在.ssh下创建authorized_keys文件, 里面添加需要ssh登录这个nas的其他设备的公钥id_rsa.pub内容.\n重启ssh服务\nsudo systemctl restart ssh webdev, smb: System Settings - Services, 修改端口.\n4. 设定磁盘定期扫描 磁盘的健康程度需要定时扫描, 但不需要过于频繁. Data Protection页面下需要设定以下任务:\nScrub Tasks: 设定定时打扫磁盘任务, At 09:00, on day 8 and 21 of the month (Threshold Days: 7) S.M.A.R.T. Tests: 设定扫描磁盘健康状态任务, At 09:00, on day 1, 15, and 28 of the month (All disk; Type: Long) 5. 共享文件夹和smb服务 How To Setup TrueNAS Scale Apps With Shares For Host Path Volumes\n这个有一点复杂, 需要建立dataset, 给user账号权限.\n尽量使不同的服务使用不同的datasets, 建立不同账号进行访问以保证安全.\n这里有个权限问题, 在smb datasets下是无法修改文件夹的权限的, 可能会导致无法进行zip等问题.\nOperation not permitted\n这时候需要把文件解压到smb共享的文件夹外面, 再进行其他操作.\n使用rsync可以在复制文件到smb文件夹内的时候不改变权限, 复制完再改用户和组\nrsync -avu --no-perms [source] [dest]\rsudo chown -R [user] [file]\rsudo chgrp -R [user] [file] rsync参数\nrsync 命令，Linux rsync 命令详解：远程数据同步工具 - Linux 命令搜索引擎\n-v, --verbose 详细模式输出。\r-q, --quiet 精简输出模式。\r-c, --checksum 打开校验开关，强制对文件传输进行校验。\r-a, --archive 归档模式，表示以递归方式传输文件，并保持所有文件属性，等于-rlptgoD。\r-r, --recursive 对子目录以递归模式处理。\r-R, --relative 使用相对路径信息。\r-b, --backup 创建备份，也就是对于目的已经存在有同样的文件名时，将老的文件重新命名为~filename。可以使用--suffix选项来指定不同的备份文件前缀。\r--backup-dir 将备份文件(如~filename)存放在在目录下。\r-suffix=SUFFIX 定义备份文件前缀。\r-u, --update 仅仅进行更新，也就是跳过所有已经存在于DST，并且文件时间晚于要备份的文件，不覆盖更新的文件。\r-l, --links 保留软链结。\r-L, --copy-links 想对待常规文件一样处理软链结。\r--copy-unsafe-links 仅仅拷贝指向SRC路径目录树以外的链结。\r--safe-links 忽略指向SRC路径目录树以外的链结。\r-H, --hard-links 保留硬链结。\r-p, --perms 保持文件权限。\r-o, --owner 保持文件属主信息。\r-g, --group 保持文件属组信息。\r-D, --devices 保持设备文件信息。\r-t, --times 保持文件时间信息。\r-S, --sparse 对稀疏文件进行特殊处理以节省DST的空间。\r-n, --dry-run现实哪些文件将被传输。\r-w, --whole-file 拷贝文件，不进行增量检测。\r-x, --one-file-system 不要跨越文件系统边界。\r-B, --block-size=SIZE 检验算法使用的块尺寸，默认是700字节。\r-e, --rsh=command 指定使用rsh、ssh方式进行数据同步。\r--rsync-path=PATH 指定远程服务器上的rsync命令所在路径信息。\r-C, --cvs-exclude 使用和CVS一样的方法自动忽略文件，用来排除那些不希望传输的文件。\r--existing 仅仅更新那些已经存在于DST的文件，而不备份那些新创建的文件。\r--delete 删除那些DST中SRC没有的文件。\r--delete-excluded 同样删除接收端那些被该选项指定排除的文件。\r--delete-after 传输结束以后再删除。\r--ignore-errors 及时出现IO错误也进行删除。\r--max-delete=NUM 最多删除NUM个文件。\r--partial 保留那些因故没有完全传输的文件，以是加快随后的再次传输。\r--force 强制删除目录，即使不为空。\r--numeric-ids 不将数字的用户和组id匹配为用户名和组名。\r--timeout=time ip超时时间，单位为秒。\r-I, --ignore-times 不跳过那些有同样的时间和长度的文件。\r--size-only 当决定是否要备份文件时，仅仅察看文件大小而不考虑文件时间。\r--modify-window=NUM 决定文件是否时间相同时使用的时间戳窗口，默认为0。\r-T --temp-dir=DIR 在DIR中创建临时文件。\r--compare-dest=DIR 同样比较DIR中的文件来决定是否需要备份。\r-P 等同于 --partial。\r--progress 显示备份过程。\r-z, --compress 对备份的文件在传输时进行压缩处理。\r--exclude=PATTERN 指定排除不需要传输的文件模式。\r--include=PATTERN 指定不排除而需要传输的文件模式。\r--exclude-from=FILE 排除FILE中指定模式的文件。\r--include-from=FILE 不排除FILE指定模式匹配的文件。\r--version 打印版本信息。\r--address 绑定到特定的地址。\r--config=FILE 指定其他的配置文件，不使用默认的rsyncd.conf文件。\r--port=PORT 指定其他的rsync服务端口。\r--blocking-io 对远程shell使用阻塞IO。\r-stats 给出某些文件的传输状态。\r--progress 在传输时显示传输过程。\r--log-format=formAT 指定日志文件格式。\r--password-file=FILE 从FILE中得到密码。\r--bwlimit=KBPS 限制I/O带宽，KBytes per second。\r-h, --help 显示帮助信息。 SMB服务连接的datasets会自动设置ACL权限, 导致datasets内chmod等操作全都被禁止, 禁用ACL后指定用户就可以随意修改chmod了.\n注意ACL可以给不同的用户不同的权限. 禁用ACL之后, 只能简单的设置单一用户权限. 修改位置 Truenas web ui - Datasets - Permissions 6. 外接磁盘挂载 查看移动硬盘的信息\nsudo fdisk -l ... Disk /dev/sdh: 7.28 TiB, 8001562869760 bytes, 15628052480 sectors Disk model: Game Drive Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 4096 bytes I/O size (minimum/optimal): 4096 bytes / 4096 bytes Disklabel type: gpt Disk identifier: 0D305159-052E-4FEE-8800-8B0D64CC501E Device Start End Sectors Size Type /dev/sdh1 2048 15628050431 15628048384 7.3T Microsoft basic data 挂载硬盘\nsudo mkdir /mnt/ex_device sudo mount /dev/sdh1 /mnt/ex_device 导入外界磁盘数据\n方法1: 直接在命令行cp\n方法2: 使用truenas网页端 Datasets - Import Data, 系统一次只能导一个外部磁盘.\nDocs Hub | Importing Data\n卸载硬盘\n如果使用完硬盘需要卸载硬盘:\nsudo umount /dev/sdh1 6.2. windows samba文件夹挂载到nas sudo mount -o username=[user],password=[passwd] //[ip addr]/[windows共享的盘符或文件夹] /mnt/ex_device 7. 内存缓存arc zfs 对 arc 的需求很大，在普通的 linux 系统上，zfs_arc_max 为 0, 代表最大 arc 占用是总内存的一半，比如 48G 的内存就会占用 24G 用作 arc, 剩下 24G 用作系统和应用服务.\n不过如果你没有那么多 docker 要跑的话，鉴于 arc 对 zfs 系统的巨大作用，我建议将 zfs_arc_max 设置为总内存的 75%. 比如总内存 48G,zfs_arc_max 就设为 35G, 也就是 $35*1024^3=37580963840$\n设置方法就是在 system setting - Advanced - Init/Shutdown Scripts - add\ntype: command\ncommand:\necho 37580963840 \u0026gt;\u0026gt; /sys/module/zfs/parameters/zfs_arc_max when: pre init\n8. 防火墙配置 注意配置文件中不可以有空格在每条命令之前, 比如空白行中有一个空格也会报语法错误.\n*filter # Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn\u0026#39;t use lo0 -A INPUT -i lo -j ACCEPT -A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT # Accepts all established inbound connections -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Allows all outbound traffic # You could modify this to only allow certain traffic -A OUTPUT -j ACCEPT # multiport setting -A INPUT -m multiport -p udp --dports [port1,port2] -j ACCEPT # single port setting -A INPUT -p tcp --dport [port] -j ACCEPT # Allows SSH connections for script kiddies # THE -dport NUMBER IS THE SAME ONE YOU SET UP IN THE SSHD_CONFIG FILE -A INPUT -p tcp -m state --state NEW --dport [ssh port] -j ACCEPT # Allow ping # -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT # log iptables denied calls (access via \u0026#39;dmesg\u0026#39; command) -A INPUT -m limit --limit 5/min -j LOG --log-prefix \u0026#34;iptables denied: \u0026#34; --log-level 7 # Reject all other inbound - default deny unless explicitly allowed policy: -A INPUT -j REJECT -A FORWARD -j REJECT COMMIT 载入设置\n# 清除老规则 sudo iptables -F # 设定和存放现有的规则 sudo mkdir -p /etc/iptables sudo vi /etc/iptables/iptable_rules sudo chmod +x /etc/iptables/iptable_rules sudo iptables-restore \u0026lt; iptable_rules # 查看现在的规则 sudo iptables -L -n 设置开机自启动 在 system setting - Advanced - Init/Shutdown Scripts - add\ntype: command\ncommand:\n/usr/sbin/iptables-restore \u0026lt; /etc/iptables/iptable_rules when: post init\n9. UPS设置 设置 System Settings - Services - UPS\n这篇文章详细介绍了ups和主从两台NAS的配置方法\n简略版, shell下查看没有问题的话, 拔掉UPS的总电源测试NAS是否能够顺利关机即可.\n10. frp客户端设置 wget https://github.com/fatedier/frp/releases/download/v0.43.0/frp_0.43.0_linux_amd64.tar.gz tar -xzvf frp_0.43.0_linux_amd64.tar.gz cd frp_0.43.0_linux_amd64 客户端设置\nvi frpc.ini [common] server_addr = xxxxxxxx server_port = xxx token = xxxxxxxxxxxxxxxxxxxxxxxxxx [ssh] type = tcp local_ip = 127.0.0.1 local_port = xxx remote_port = xxx 11. 开启apt使用权限 默认是无法使用apt安装软件的.\nsudo chmod +x /usr/bin/apt* 12. docker 据说docker将在23年10月从scale版本中移除. 可以以后的版本可以需要用apt-get安装一下docker\nUse docker-compose on TrueNAS SCALE 22.12 (Bluefin) without Kubernetes\n# 先看看默认有没有docker compose, 有的话开一下权限就好了. sudo chmod +x /usr/bin/docker-compose # 如果没有, 再安装 sudo apt-get update sudo apt-get install docker-compose-plugin # 如果需要proxy sudo apt-get -o Acquire::http::proxy=\u0026#34;http://xxx:xxx\u0026#34; install xxxx # 查看compose版本 sudo docker compose version Docker Compose version v2.10.2 使用docker compose一键安装 准备好docker-compose.yaml文件 运行命令sudo docker-compose up 后台启动服务并指定文件夹docker-compose -f docker-compose.yaml up -d 停止服务docker-compose -f docker-compose.yaml stop 停止并删除服务(!!!!!!!!危险!!!!!!!!!, 使用之后mysqldocker中的tables全部删除)docker-compose -f docker-compose.yaml down 14. 风扇调速 查看风扇的最大最小转速, 比如, 风扇的转速为 $400 \\sim 1700\\pm10\\%$ RPM\n一般在主板ipmi网页端Server health - sensor readings 可以看到目前通电风扇的各种参数.\nsudo ipmitool sensor thresh FAN1 lower 100 200 450 FAN1 是需要修改参数的风扇编号, 如 FANA, FAN1, FAN2 等等. 100 是不可恢复下限转速(Low NR). 200 是下紧急临界转速(Low CT). 450 是非紧急临界转速. 注意: 当主板的PWM风扇模式为Optimal时, 如果风扇Low CT设定太高, 主板会不停调动风扇满速→减速→满速循环, 声音很吵. 16. 有用的软件 nethogs 网络监视用, 查看什么进程在调用网络 17. Troubleshutting 17.1. 硬盘噪音问题 日常使用的过程中发现一个问题, 每隔5秒, 硬盘便会被访问一次, 发出一次噪音.\nMove System Dataset SCALE\n原因 The open txg is committed to the pool periodically (SPA sync) and zfs_txg_timeout represents the default target upper limit. zfs_txg_timeout 默认为5秒 由于这种访问会随着磁盘读写动态调整, 所以可以将这个阈值设置大一点, 在磁盘空闲的时候就能做到降低访问频率的效果. 解决方法: 将/sys/module/zfs/parameters/zfs_txg_timeout从默认的5改为120\n设置开机命令\necho 120 \u0026gt; /sys/module/zfs/parameters/zfs_txg_timeout 17.2. 重启时卡住的问题 解决方法, 每次重启都在引导处选择初始化安装, 这样boot的时候会继续下去.\n进入系统后, 发现服务器中的所有设置和pool都保留着. 可能相关的讨论:\nServer can only boot from \u0026ldquo;Initial-install\u0026rdquo;\n17.3. SSH: permission denied (publickey) 如果ssh突然登不上了, 可能是权限问题\n.ssh文件夹的权限: 700 authorized_keys权限: 600 用户文件夹权限: 700\n17.4. 更换硬盘 因为突然断电等情况, 出现阵列索引错误. 如果磁盘损坏需要更换的话也可以使用.\nTrueNAS存储池和磁盘降级（DEGRADED）个人处理经验\n","permalink":"https://sqf.icu/article/9ebf9e68-9665-40d3-904d-236706b14a8d/","summary":"\u003ch1 id=\"0-微超主板登陆\"\u003e0. 微超主板登陆\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"https://zhuanlan.zhihu.com/p/597490170\"\u003e超微主板使用配置 ipmi 功能流程介绍\u003c/a\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e用户名和密码都是: ADMIN\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e可以在配置-用户中更改密码\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e设置时间\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/cbc2cc9d0d179b915fc5b454.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e显示画面\u003c/p\u003e\n\u003cp\u003e在远程控制中找到\u003ccode\u003eiKVM/HTML5\u003c/code\u003e, 可以启动远程管理服务器, 在网页端直接看到开机时显示的bios等画面, 就不需要外接显示器了.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"TrueNas初期配置"},{"content":"ゼルダの伝説　ティアーズ オブ ザ キングダム : WORLD | Nintendo Switch | 任天堂\n","permalink":"https://sqf.icu/article/938eb94c-805a-46c1-8f4e-f9a2533c6336/","summary":"\u003cp\u003e\u003ca href=\"https://www.nintendo.co.jp/zelda/totk/world/index.html\"\u003eゼルダの伝説　ティアーズ オブ ザ キングダム : WORLD | Nintendo Switch | 任天堂\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/fd68012c2c5f32e1d5c7c92f.png\"\u003e\u003c/p\u003e","title":"ゼルダの伝説　ティアーズ オブ ザ キングダム"},{"content":"1. 安装Gitea镜像 qnap Container Station - 创建 - 创建应用程序(yaml文件, 与docker compose文件建立docker container完全相同)\nversion: \u0026#39;3.3\u0026#39; services: gitea_db: image: mysql:5.7 container_name: gitea_db restart: always environment: MYSQL_DATABASE: gitea MYSQL_ROOT_PASSWORD: [mysql root password] MYSQL_USER: gitea MYSQL_PASSWORD: [mysql root password] volumes: - db_data:/var/lib/mysql_gitea ports: - \u0026#34;[host sql port for sql container]:3306\u0026#34; networks: - gitea-network gitea_app: depends_on: - gitea_db image: gitea/gitea container_name: gitea_app restart: always ports: - \u0026#34;[host ssh port for gitea container]:22\u0026#34; - \u0026#34;[host http port for gitea container]:3000\u0026#34; volumes: - [gitea config and data path in nas]:/data networks: - gitea-network volumes: db_data: app_data: networks: gitea-network: driver: \u0026#34;bridge\u0026#34; 1.1. gitea install配置参考 如果sql服务器中没有保存以前的gitea配置, 首次打开gitea页面会显示安装配置\n数据库主机可以配置nas服务器的内网地址和sql docker出口端口, 数据库密码 1.2. gitea 配置样例 gitea/app.example.ini at main · go-gitea/gitea\n不要复制conf/app.ini到custom文件夹下, 直接修改conf/app.ini. 不然配置会无法生效.\nREPO_INDEXER_ENABLED 开启代码搜索, 但是会占用空间约6倍与源仓库需注意.\n挑选部分建议修改的配置\n[repository] ROOT = /data/git/repositories [service] DISABLE_REGISTRATION = true REQUIRE_SIGNIN_VIEW = true REGISTER_EMAIL_CONFIRM = false ENABLE_NOTIFY_MAIL = false ALLOW_ONLY_EXTERNAL_REGISTRATION = false ENABLE_CAPTCHA = false DEFAULT_KEEP_EMAIL_PRIVATE = false DEFAULT_ALLOW_CREATE_ORGANIZATION = false DEFAULT_ENABLE_TIMETRACKING = true NO_REPLY_ADDRESS = noreply.localhost ; close openid signin/signup [openid] ENABLE_OPENID_SIGNIN = false ENABLE_OPENID_SIGNUP = false 2. Github或其他平台代码迁移到Gitea gitlab代码迁移的同时, 保留之前的提交记录信息.\n在Gitea中新建一个项目的仓库，用来存放后面需要拷贝的代码信息\n将对应的镜像push到新的仓库地址\ngit push --mirror 新仓库地址 git push --mirror http://[ip address]:[http port]/xxx/xxx.git git push --mirror ssh://git@[ip address]:[ssh port]/xxx/xxx.git 将本地仓库的远程地址替换为当前的仓库地址.\ngit remote set-url origin 新仓库地址 //将本地远程仓库地址改为新地址 ","permalink":"https://sqf.icu/article/db00659c-c07e-4818-ba5b-e825018782c0/","summary":"\u003ch1 id=\"1-安装gitea镜像\"\u003e1. 安装Gitea镜像\u003c/h1\u003e\n\u003cp\u003eqnap Container Station - 创建 - 创建应用程序(yaml文件, 与docker compose文件建立docker container完全相同)\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eversion: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;3.3\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eservices: \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  gitea_db:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    image: mysql:\u003cspan style=\"color:#ae81ff\"\u003e5.7\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    container_name: gitea_db\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    restart: always\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    environment:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      MYSQL_DATABASE: gitea\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      MYSQL_ROOT_PASSWORD: [mysql root password]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      MYSQL_USER: gitea\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      MYSQL_PASSWORD: [mysql root password]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    volumes:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e db_data:\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003evar\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003elib\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003emysql_gitea\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ports:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;[host sql port for sql container]:3306\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    networks:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e gitea\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003enetwork\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  gitea_app:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    depends_on:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e gitea_db\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    image: gitea\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003egitea\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    container_name: gitea_app\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    restart: always\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ports:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;[host ssh port for gitea container]:22\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;[host http port for gitea container]:3000\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    volumes:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e [gitea config \u003cspan style=\"color:#f92672\"\u003eand\u003c/span\u003e data path \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e nas]:\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003edata\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    networks:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e gitea\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003enetwork\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003evolumes:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  db_data:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  app_data:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enetworks:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  gitea\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003enetwork:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    driver: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;bridge\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"11-gitea-install配置参考\"\u003e1.1. gitea install配置参考\u003c/h2\u003e\n\u003cp\u003e如果sql服务器中没有保存以前的gitea配置, 首次打开gitea页面会显示安装配置\u003c/p\u003e","title":"威联通QNAP Nas 搭建Gitea代码托管平台"},{"content":"打开火绒设置-安全设置-高级防护-自定义防护-添加规则, 添加保护对象, 阻止该路径下所有文件操作.\nC:\\Windows\\SoftwareDistribution\\Download\\* ","permalink":"https://sqf.icu/article/f053e253-29d0-465e-8188-25abdba5f2cc/","summary":"\u003cp\u003e打开火绒设置-安全设置-高级防护-自定义防护-添加规则, 添加保护对象, 阻止该路径下所有文件操作.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eC:\u003cspan style=\"color:#ae81ff\"\u003e\\W\u003c/span\u003eindows\u003cspan style=\"color:#ae81ff\"\u003e\\S\u003c/span\u003eoftwareDistribution\u003cspan style=\"color:#ae81ff\"\u003e\\D\u003c/span\u003eownload\u003cspan style=\"color:#ae81ff\"\u003e\\*\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/7e181ae586fb0b08de2bef88.png\"\u003e\u003c/p\u003e","title":"火绒阻止 windows 更新"},{"content":"什么是梯度下降法？ - 知乎\n[论文阅读] 综述梯度下降优化算法\n最小二乘问题的四种解法——牛顿法，梯度下降法，高斯牛顿法和列文伯格-马夸特法的区别和联系\n1. 梯度下降 梯度下降法用来计算函数的最小值.\n1.1. 二维函数梯度下降 比如需要计算函数 $f(x)=x^2$ 的最小值, 如果不从经验上获知其最小值, 如何通过迭代来计算呢?\n首先需要设置一个起点 $x_0$, 假设 $x_0=10$.\n此时函数的梯度如下\n$$\r\\nabla f(x_0)={f}'(x_0)=2x_0=20\r$$由于这个梯度是一个一维向量, 并且在 $x$ 轴的向量指向函数增长最快的方向, 求梯度下降的目的是找到函数增长最慢的方向, 也就是反方向 $-\\nabla f(x_0)$.\n另外 $\\nabla$ (Nabla算子) 是向量微分算子, 定义为 $\\nabla_r=\\frac{d}{dr}$.\n这时候将当前值 $x_0$, 将其看做向量, 与梯度的反方向相加, 就可以获得下一个值 $x_1$ 的位置.\n$$\rx_1=x_0-\\gamma\\nabla f(x_0)\r$$ 这里的 $\\gamma$ 表示为步长 (学习率), 用来控制采样点移动距离. 步长的设定是凭借经验的, 过小收敛较慢, 过大会无法收敛. 这里设定 $\\gamma = 0.2$. $$\rx_1=10-0.2*20=6\r$$此时的采样点来到了 $x=6$ 的位置.\n开始迭代\n迭代方法同上\n1.2. 三维函数梯度下降 找到函数 $f(x)=x_a^2+2x_b^2$ 的最小值, 函数三维图和等高线如下.\n设置初始点 $x_0=(-3.5,-3.5)$, 此时梯度为:\n$$\r\\nabla f(x_0)=\\left(\\frac{\\partial f\\left(\\boldsymbol{x}_0\\right)}{\\partial x_a}, \\frac{\\partial f\\left(\\boldsymbol{x}_0\\right)}{\\partial x_b}\\right)=(-7,-14)\r$$ 设置 $\\gamma=0.1$, 可以计算出下一点 $x_1$ 的向量\n$$\rx_1=x_0-\\gamma \\nabla f(x_0)=(-2.8,-2.1)\r$$ 开始迭代\n方法同上\n1.3. 深度学习中的梯度下降 模型训练过程中, 需要计算的是损失函数的最小值\n而在深度学习的优化算法中不同的梯度下降算法如下图所示\n拿随机梯度下降算法举例, $L$ 是每个样本的损失函数, $f(x;\\Theta)$ 表示一个输入为 $x$ 和 初始参数 $\\Theta$ 的函数, $y$ 表示 GT 值.\n其中的梯度计算是先计算样本数据的平均损失, 但是损失函数中有 $\\Theta$ 作为优化参数, 也就是说函数变为了以 $\\Theta$ 为未知数的函数, 对 $\\Theta$ 求偏导, 之后带入 $\\Theta_i$ 获得梯度参数 $g$.\n之后更新 $\\Theta_{i+1}=\\Theta_i-\\eta g$.\n","permalink":"https://sqf.icu/article/f6cb80f3-f00a-4328-8c7e-b95013554fee/","summary":"\u003cp\u003e\u003ca href=\"https://www.zhihu.com/question/305638940\"\u003e什么是梯度下降法？ - 知乎\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://zhuanlan.zhihu.com/p/110104333\"\u003e[论文阅读] 综述梯度下降优化算法\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://zhuanlan.zhihu.com/p/113946848\"\u003e最小二乘问题的四种解法——牛顿法，梯度下降法，高斯牛顿法和列文伯格-马夸特法的区别和联系\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"1-梯度下降\"\u003e1. 梯度下降\u003c/h1\u003e\n\u003cp\u003e梯度下降法用来计算函数的最小值.\u003c/p\u003e\n\u003ch2 id=\"11-二维函数梯度下降\"\u003e1.1. 二维函数梯度下降\u003c/h2\u003e\n\u003cp\u003e比如需要计算函数 $f(x)=x^2$ 的最小值, 如果不从经验上获知其最小值, 如何通过迭代来计算呢?\u003c/p\u003e","title":"梯度下降法介绍"},{"content":"ELDEN RING オフィシャルウェブサイト\n","permalink":"https://sqf.icu/article/67f38bdf-9256-4500-b62a-134589583694/","summary":"\u003cp\u003e\u003ca href=\"https://www.eldenring.jp/newsdetail/news_detail_230228_1.html\"\u003eELDEN RING オフィシャルウェブサイト\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/7cc05f17dc0e2347c8e1aea6.jpeg\"\u003e\u003c/p\u003e","title":"ELDEN RING DLC「Shadow of the Erdtree」"},{"content":"最小二乘法合函数的公式 使用最小二乘法拟合函数需要前置条件\n设定多项式的阶数 $n$ 存在大于多项式阶数的点坐标 $((x_1,y_1), (x_2,y_2), ..., (x_k,y_k))$ 最小二乘拟合公式\n$$\r\\begin{bmatrix} (\\varphi_0,\\varphi_0) \u0026 (\\varphi_0,\\varphi_1) \u0026 ... \u0026 (\\varphi_0,\\varphi_n)\\\\ (\\varphi_1,\\varphi_0) \u0026 (\\varphi_1,\\varphi_1) \u0026 ... \u0026 (\\varphi_1,\\varphi_n)\\\\ \u0026 \u0026... \\\\ (\\varphi_n,\\varphi_0) \u0026 (\\varphi_n,\\varphi_1) \u0026 ... \u0026 (\\varphi_n,\\varphi_n)\\end{bmatrix}\\begin{bmatrix}a_0 \\\\ a_1 \\\\ ... \\\\ a_n\\end{bmatrix}=\\begin{bmatrix}(f,\\varphi_0) \\\\(f,\\varphi_1) \\\\ ... \\\\(f,\\varphi_n) \\end{bmatrix}\r$$ 其中括号的含义是矩阵内元素逐个相乘之和;\n$\\varphi_n$ 是所有点坐标的 $x$ 坐标的 $n$ 次方;\n$a_n$ 是多项式每一阶前的参数, 从 0 开始增大;\n$f$ 表示所有点坐标的 $y$ 坐标;\n最终可以获得 $n$ 个包含 $a_n$ 的公式, 计算公式即可算出 $a_0,a_1,...,a_n$ 参数, 从而拟合多项式.\n时序多维点坐标预测 对于预测时序多维点坐标, 可以将时间 $t$ 作为横坐标, 每个维度作为纵坐标, 分开拟合每个维度的多项式. 预测出每个维度的坐标值后再合并成一个点.\ndef np_ployfit(point_np, degree=1): \u0026#34;\u0026#34;\u0026#34;numpy polyfit使用连续3帧3维点的坐标预测下一帧3维点的坐标, 拟合使用的多项式为2阶 Args: point_np (numpy): 点坐标矩阵 numpy([[frame1_point1],[frame1_point2],...], [[frame2_point1],...], [[frame3_point1],...]) degree (int): 自由度, 默认为2, 表示拟合2次函数 Returns: numpy: _description_ \u0026#34;\u0026#34;\u0026#34; predictions = [] for i in range(point_np.shape[1]): # 对每一个点进行拟合 params = np.polyfit(np.arange(3), point_np[:, i, 0], degree) # 对 x 坐标进行拟合 x_pred = np.polyval(params, 3) params = np.polyfit(np.arange(3), point_np[:, i, 1], degree) # 对 y 坐标进行拟合 y_pred = np.polyval(params, 3) params = np.polyfit(np.arange(3), point_np[:, i, 2], degree) # 对 z 坐标进行拟合 z_pred = np.polyval(params, 3) predictions.append([x_pred, y_pred, z_pred]) return np.array(predictions) 参考 【数值分析】【纯干货】速成最小二乘拟合法_哔哩哔哩_bilibili\n","permalink":"https://sqf.icu/article/55b99b61-d7ad-49a1-a475-5f52339222ca/","summary":"\u003ch1 id=\"最小二乘法合函数的公式\"\u003e最小二乘法合函数的公式\u003c/h1\u003e\n\u003cp\u003e使用最小二乘法拟合函数需要前置条件\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e设定多项式的阶数 $n$\u003c/li\u003e\n\u003cli\u003e存在大于多项式阶数的点坐标 $((x_1,y_1), (x_2,y_2), ..., (x_k,y_k))$\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e最小二乘拟合公式\u003c/p\u003e\n$$\r\n\\begin{bmatrix} (\\varphi_0,\\varphi_0) \u0026 (\\varphi_0,\\varphi_1) \u0026 ... \u0026 (\\varphi_0,\\varphi_n)\\\\ (\\varphi_1,\\varphi_0) \u0026 (\\varphi_1,\\varphi_1) \u0026 ... \u0026 (\\varphi_1,\\varphi_n)\\\\   \u0026 \u0026... \\\\ (\\varphi_n,\\varphi_0) \u0026 (\\varphi_n,\\varphi_1) \u0026 ... \u0026 (\\varphi_n,\\varphi_n)\\end{bmatrix}\\begin{bmatrix}a_0 \\\\ a_1 \\\\ ... \\\\ a_n\\end{bmatrix}=\\begin{bmatrix}(f,\\varphi_0) \\\\(f,\\varphi_1) \\\\ ... \\\\(f,\\varphi_n) \\end{bmatrix}\r\n$$\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e其中括号的含义是矩阵内元素逐个相乘之和;\u003c/p\u003e\n\u003cp\u003e$\\varphi_n$ 是所有点坐标的 $x$ 坐标的 $n$ 次方;\u003c/p\u003e\n\u003cp\u003e$a_n$ 是多项式每一阶前的参数, 从 0 开始增大;\u003c/p\u003e\n\u003cp\u003e$f$ 表示所有点坐标的 $y$ 坐标;\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e最终可以获得 $n$ 个包含 $a_n$ 的公式, 计算公式即可算出 $a_0,a_1,...,a_n$ 参数, 从而拟合多项式.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"最小二乘拟合函数"},{"content":"1. 共线原理 双相机立体重建时, 利用物体点-光心-像点三者共线的原理, 在找到左右匹配的像点并且完成去畸变之后, 就能够在三维空间中形成两条直线, 物体点就是这两个直线的交点.\n交点指最小二乘交点, 因为这两个直线由于偏差通常不会交于一点. 共线方程描述了物体点-光心-像点三者共线的含义, 也相当于三维点到二维点的投影过程, 该投影过程可表达为\n$$\r\\left[\\begin{array}{l}\\mathrm{x}_{\\mathrm{c}} \\\\\\mathrm{y}_{\\mathrm{c}} \\\\\\mathrm{z}_{\\mathrm{c}}\\end{array}\\right]=\\left[\\begin{array}{llll}\\mathrm{R}_{11} \u0026 \\mathrm{R}_{12} \u0026 \\mathrm{R}_{13} \u0026 \\mathrm{~T}_{\\mathrm{x}} \\\\\\mathrm{R}_{21} \u0026 \\mathrm{R}_{22} \u0026 \\mathrm{R}_{23} \u0026 \\mathrm{~T}_{\\mathrm{y}} \\\\\\mathrm{R}_{31} \u0026 \\mathrm{R}_{32} \u0026 \\mathrm{R}_{33} \u0026 \\mathrm{~T}_{\\mathrm{z}}\\end{array}\\right]\\left[\\begin{array}{c}\\mathrm{x}_{\\mathrm{w}} \\\\\\mathrm{y}_{\\mathrm{w}} \\\\\\mathrm{z}_{\\mathrm{w}} \\\\1\\end{array}\\right] \\quad\\quad \\text{(1)}\r$$ 2. 解超定线性方程组 将公式 $1$ 转换为非齐次方程组\n$$\r\\left\\{\\begin{array}{l}\\mathrm{x}_{\\mathrm{c}}=\\mathrm{R}_{11} \\mathrm{x}_{\\mathrm{w}}+\\mathrm{R}_{12} \\mathrm{y}_{\\mathrm{w}}+\\mathrm{R}_{13} \\mathrm{z}_{\\mathrm{w}}+\\mathrm{T}_{\\mathrm{x}} \\\\\\mathrm{y}_{\\mathrm{c}}=\\mathrm{R}_{21} \\mathrm{x}_{\\mathrm{w}}+\\mathrm{R}_{22} \\mathrm{y}_{\\mathrm{w}}+\\mathrm{R}_{23} \\mathrm{z}_{\\mathrm{w}}+\\mathrm{T}_{\\mathrm{y}} \\\\\\mathrm{z}_{\\mathrm{c}}=\\mathrm{R}_{31} \\mathrm{x}_{\\mathrm{w}}+\\mathrm{R}_{32} \\mathrm{y}_{\\mathrm{w}}+\\mathrm{R}_{33} \\mathrm{z}_{\\mathrm{w}}+\\mathrm{T}_{\\mathrm{z}}\\end{array}\\right.\r$$ 作归一化使 $z_c$ 为1\n$$\r\\left\\{\\begin{array}{l}\\hat{\\mathrm{x}_{\\mathrm{c}}}=\\mathrm{x}_{\\mathrm{c}} / \\mathrm{z}_{\\mathrm{c}}=\\frac{\\mathrm{R}_{11} \\mathrm{x}_{\\mathrm{w}}+\\mathrm{R}_{12} \\mathrm{y}_{\\mathrm{w}}+\\mathrm{R}_{13} \\mathrm{z}_{\\mathrm{w}}+\\mathrm{T}_{\\mathrm{x}}}{\\mathrm{R}_{31} \\mathrm{x}_{\\mathrm{w}}+\\mathrm{R}_{32} \\mathrm{y}_{\\mathrm{w}}+\\mathrm{R}_{33} \\mathrm{z}_{\\mathrm{w}}+\\mathrm{T}_{\\mathrm{z}}} \\\\\\hat{\\mathrm{y}_{\\mathrm{c}}}=\\mathrm{y}_{\\mathrm{c}} / \\mathrm{z}_{\\mathrm{c}}=\\frac{\\mathrm{R}_{21} \\mathrm{x}_{\\mathrm{w}}+\\mathrm{R}_{22} \\mathrm{y}_{\\mathrm{w}}+\\mathrm{R}_{23} \\mathrm{z}_{\\mathrm{w}}+\\mathrm{T}_{\\mathrm{y}}}{\\mathrm{R}_{31} \\mathrm{x}_{\\mathrm{w}}+\\mathrm{R}_{32} \\mathrm{y}_{\\mathrm{w}}+\\mathrm{R}_{33} \\mathrm{z}_{\\mathrm{w}}+\\mathrm{T}_{\\mathrm{z}}}\\end{array}\\right. \\quad\\quad \\text{(2)}\r$$ 将公式 $2$ 转换为1组线性方程式\n$$\r\\left\\{\\begin{array}{l}\\left(\\hat{\\mathrm{x}_{\\mathrm{c}}} \\mathrm{R}_{31}-\\mathrm{R}_{11}\\right) \\mathrm{x}_{\\mathrm{w}}+\\left(\\hat{\\mathrm{x}_{\\mathrm{c}}} \\mathrm{R}_{32}-\\mathrm{R}_{12}\\right) \\mathrm{y}_{\\mathrm{w}}+\\left(\\hat{\\mathrm{x}_{\\mathrm{c}}} \\mathrm{R}_{33}-\\mathrm{R}_{13}\\right) \\mathrm{z}_{\\mathrm{w}}+\\left(\\hat{\\mathrm{x}_{\\mathrm{c}}} \\mathrm{T}_{\\mathrm{z}}-\\mathrm{T}_{\\mathrm{x}}\\right)=0 \\\\\\left(\\hat{\\mathrm{y}_{\\mathrm{c}}} \\mathrm{R}_{31}-\\mathrm{R}_{21}\\right) \\mathrm{x}_{\\mathrm{w}}+\\left(\\hat{\\mathrm{y}_{\\mathrm{c}}} \\mathrm{R}_{32}-\\mathrm{R}_{22}\\right) \\mathrm{y}_{\\mathrm{w}}+\\left(\\hat{\\mathrm{y}_{\\mathrm{c}}} \\mathrm{R}_{33}-\\mathrm{R}_{23}\\right) \\mathrm{z}_{\\mathrm{w}}+\\left(\\hat{\\mathrm{y}_{\\mathrm{c}}} \\mathrm{T}_{\\mathrm{z}}-\\mathrm{T}_{\\mathrm{y}}\\right)=0\\end{array}\\right.\r$$ 三角测量使用两个二维点 $(\\hat{\\mathrm{x}_{c1}},\\hat{\\mathrm{y}_{c1}}),(\\hat{\\mathrm{x}_{c2}},\\hat{\\mathrm{y}_{c2}})$ 来确定一个三维点, 所以能够生成两组线性方程式, 转换为矩阵方程\n$$\r\\left[\\begin{array}{llll}\\hat{\\mathrm{x}_{\\mathrm{c1}}} \\mathrm{R}_{31_1}-\\mathrm{R}_{11_1} \u0026\\hat{\\mathrm{x}_{\\mathrm{c1}}} \\mathrm{R}_{32_1}-\\mathrm{R}_{12_1} \u0026\\hat{\\mathrm{x}_{\\mathrm{c1}}} \\mathrm{R}_{33_1}-\\mathrm{R}_{13_1} \u0026\\hat{\\mathrm{x}_{\\mathrm{c1}}} \\mathrm{T}_{\\mathrm{z_1}}-\\mathrm{T}_{\\mathrm{x_1}} \\\\ \\hat{\\mathrm{y}_{\\mathrm{c1}}} \\mathrm{R}_{31_1}-\\mathrm{R}_{21_1} \u0026\\hat{\\mathrm{y}_{\\mathrm{c1}}} \\mathrm{R}_{32_1}-\\mathrm{R}_{22_1} \u0026\\hat{\\mathrm{y}_{\\mathrm{c1}}} \\mathrm{R}_{33_1}-\\mathrm{R}_{23_1} \u0026\\hat{\\mathrm{y}_{\\mathrm{c1}}} \\mathrm{T}_{\\mathrm{z_1}}-\\mathrm{T}_{\\mathrm{y_1}} \\\\\\hat{\\mathrm{x}_{\\mathrm{c1}}} \\mathrm{R}_{31_2}-\\mathrm{R}_{11_2} \u0026\\hat{\\mathrm{x}_{\\mathrm{c1}}} \\mathrm{R}_{32_2}-\\mathrm{R}_{12_2} \u0026\\hat{\\mathrm{x}_{\\mathrm{c1}}} \\mathrm{R}_{33_2}-\\mathrm{R}_{13_2} \u0026\\hat{\\mathrm{x}_{\\mathrm{c1}}} \\mathrm{T}_{\\mathrm{z_2}}-\\mathrm{T}_{\\mathrm{x_2}} \\\\ \\hat{\\mathrm{y}_{\\mathrm{c1}}} \\mathrm{R}_{31_2}-\\mathrm{R}_{21_2} \u0026\\hat{\\mathrm{y}_{\\mathrm{c1}}} \\mathrm{R}_{32_2}-\\mathrm{R}_{22_2} \u0026\\hat{\\mathrm{y}_{\\mathrm{c1}}} \\mathrm{R}_{33_2}-\\mathrm{R}_{23_2} \u0026\\hat{\\mathrm{y}_{\\mathrm{c1}}} \\mathrm{T}_{\\mathrm{z_2}}-\\mathrm{T}_{\\mathrm{y_2}} \\end{array}\\right]\\left[\\begin{array}{l}\\mathrm{x}_\\mathrm{w} \\\\\\mathrm{y}_\\mathrm{w} \\\\\\mathrm{z}_\\mathrm{w} \\\\1 \\end{array}\\right]=\\left[\\begin{array}{l}0 \\\\0 \\\\0 \\\\0 \\end{array}\\right]\r$$ 需要求得系数矩阵就是左边的矩阵 $A$. 对该矩阵进行奇异值分解 $A=U D V^T$. $V$ 矩阵的最后一列就是方程解为 $[X, Y, Z, W]$, 归一化之后就是三维坐标系下的点坐标.\n参考资料 【精选】OpenCV三角测量重建triangulatePoints原理解析-CSDN博客\n","permalink":"https://sqf.icu/article/34023e2b-e8c2-489e-a988-9a9fd4ad9183/","summary":"\u003ch1 id=\"1-共线原理\"\u003e1. 共线原理\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e双相机立体重建时, 利用物体点-光心-像点三者共线的原理, 在找到左右匹配的像点并且完成去畸变之后, 就能够在三维空间中形成两条直线, 物体点就是这两个直线的\u003cstrong\u003e交点\u003c/strong\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e交点\u003c/strong\u003e指最小二乘交点, 因为这两个直线由于偏差通常不会交于一点. 共线方程描述了\u003cstrong\u003e物体点-光心-像点\u003c/strong\u003e三者共线的含义, 也相当于三维点到二维点的投影过程, 该投影过程可表达为\u003c/p\u003e\n$$\r\n    \\left[\\begin{array}{l}\\mathrm{x}_{\\mathrm{c}} \\\\\\mathrm{y}_{\\mathrm{c}} \\\\\\mathrm{z}_{\\mathrm{c}}\\end{array}\\right]=\\left[\\begin{array}{llll}\\mathrm{R}_{11} \u0026 \\mathrm{R}_{12} \u0026 \\mathrm{R}_{13} \u0026 \\mathrm{~T}_{\\mathrm{x}} \\\\\\mathrm{R}_{21} \u0026 \\mathrm{R}_{22} \u0026 \\mathrm{R}_{23} \u0026 \\mathrm{~T}_{\\mathrm{y}} \\\\\\mathrm{R}_{31} \u0026 \\mathrm{R}_{32} \u0026 \\mathrm{R}_{33} \u0026 \\mathrm{~T}_{\\mathrm{z}}\\end{array}\\right]\\left[\\begin{array}{c}\\mathrm{x}_{\\mathrm{w}} \\\\\\mathrm{y}_{\\mathrm{w}} \\\\\\mathrm{z}_{\\mathrm{w}} \\\\1\\end{array}\\right] \\quad\\quad \\text{(1)}\r\n    $$\u003c/li\u003e\n\u003c/ul\u003e","title":"OpenCV三角测量原理公式"},{"content":"用途 计算表格中开始日期和结束日期, 显示经过了几天, 还有几天结束, 经过天数和总天数的百分比 计算Done和Total列的数值(任务完成的值和总值), 计算任务完成度, 显示任务完成了多少 代码 使用时, 删除缩进和换行. 使代码变为1行复制到表格Formula列. 注意替换列名 vscode里删除缩进和换行→按ctrl+shift+h替换→正则模式\\n| 替换为空. \u0026#34;进度: \u0026#34; + format(slice(\u0026#34;::::::::::::::::::::::::::::::::::::::::\u0026#34;, 0, ceil(prop(\u0026#34;Done\u0026#34;) / prop(\u0026#34;Total\u0026#34;) * 40))) + format(slice(\u0026#34;........................................\u0026#34;, 0, 40 - ceil(prop(\u0026#34;Done\u0026#34;) / prop(\u0026#34;Total\u0026#34;) * 40))) + \u0026#34; \u0026#34; + format(round(prop(\u0026#34;Done\u0026#34;) / prop(\u0026#34;Total\u0026#34;) * 100)) + \u0026#34;%\u0026#34; + \u0026#34;\\n日期: \u0026#34; + if( empty(start(prop(\u0026#34;Date\u0026#34;))), \u0026#34;........................................ 经过-天 还有-天结束 -%\u0026#34;, if( start(prop(\u0026#34;Date\u0026#34;)) == end(prop(\u0026#34;Date\u0026#34;)), \u0026#34;........................................ 经过\u0026#34; + format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;)) + \u0026#34;天 还有-天结束 -%\u0026#34;, if( start(prop(\u0026#34;Date\u0026#34;)) \u0026gt; now(), \u0026#34;........................................ 还有\u0026#34; + format(dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;)) + \u0026#34;天开始 还有\u0026#34; + format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;)) + \u0026#34;天结束 -%\u0026#34;, if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) \u0026lt; dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;), format(slice(\u0026#34;::::::::::::::::::::::::::::::::::::::::\u0026#34;, 0, floor(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) / dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) * 40))) + format(slice(\u0026#34;........................................\u0026#34;, 0, 40 - floor(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) / dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) * 40))) + \u0026#34; 经过\u0026#34; + format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;)) + \u0026#34;天\u0026#34; + \u0026#34; 还有\u0026#34; + format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;)) + \u0026#34;天结束\u0026#34; + \u0026#34; \u0026#34; + format(round(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) / dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) * 100)) + \u0026#34;%\u0026#34;, \u0026#34;::::::::::::::::::::::::::::::::::::::::\u0026#34; + \u0026#34; 用\u0026#34; + format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;)) + \u0026#34;天 还有0天结束 100%\u0026#34; ) ) ) ) 一些常用函数\nformat: 转换为字符串 format(随便啥的) slice: 字符串切片 slice(str, 开始index, 结束index(取不到)) ceil: 小数取大于这个数的整数 ceil(1.1)=2 floor: 小数取小于这个数的整数 ceil(1.1)=1 round: 小数四舍五入 round(4.4) == 4 round(4.5) == 5 prop: 取某一列元素 prop(\u0026#34;Date\u0026#34;) 取日期那一列 end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)): 日期格式开始日期和结束日期(如果没有结束日期时, 默认结束日期等于开始日期) now(): 当前日期 dateBetween: 计算两个日期间的天数或月数 dateBetween(结束日期, 开始日期, [\u0026#34;days\u0026#34;, \u0026#34;months\u0026#34;, \u0026#34;years\u0026#34;]) if: if判断 if(判断条件, 如果为true运行代码, 如果为false运行代码) empty: 空返回true, 非空返回false 也可以将天数转换为年月日\n需要修改下面代码\nformat(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;)) 改为\nif( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;) \u0026gt; 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;)) + \u0026#34;年\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) \u0026gt; 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) - dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;) * 12) + \u0026#34;月\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) \u0026gt; 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) - floor(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) * 30.44)) + \u0026#34;天\u0026#34;, \u0026#34;0天\u0026#34; ) 合并后 版本2\n\u0026#34;进度: \u0026#34; + format(slice(\u0026#34;::::::::::::::::::::::::::::::::::::::::\u0026#34;, 0, ceil(prop(\u0026#34;Done\u0026#34;) / prop(\u0026#34;Total\u0026#34;) * 40))) + format(slice(\u0026#34;........................................\u0026#34;, 0, 40 - ceil(prop(\u0026#34;Done\u0026#34;) / prop(\u0026#34;Total\u0026#34;) * 40))) + \u0026#34; \u0026#34; + format(round(prop(\u0026#34;Done\u0026#34;) / prop(\u0026#34;Total\u0026#34;) * 100)) + \u0026#34;%\u0026#34; + \u0026#34;\\n日期: \u0026#34; + if( empty(start(prop(\u0026#34;Date\u0026#34;))), \u0026#34;........................................ 经过-天 还有-天结束 -%\u0026#34;, if( start(prop(\u0026#34;Date\u0026#34;)) == end(prop(\u0026#34;Date\u0026#34;)), \u0026#34;........................................ 经过\u0026#34; + if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;) \u0026gt; 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;)) + \u0026#34;年\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) \u0026gt; 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) - dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;) * 12) + \u0026#34;月\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) \u0026gt; 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) - floor(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) * 30.44)) + \u0026#34;天\u0026#34;, \u0026#34;0天\u0026#34; ) + \u0026#34; 还有-天结束 -%\u0026#34;, if( start(prop(\u0026#34;Date\u0026#34;)) \u0026gt; now(), \u0026#34;........................................ 还有\u0026#34; + if( dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;) \u0026gt; 0, format(dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;)) + \u0026#34;年\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) \u0026gt; 0, format(dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) - dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;) * 12) + \u0026#34;月\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;) \u0026gt; 0, format(dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;) - floor(dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) * 30.44)) + \u0026#34;天\u0026#34;, \u0026#34;0天\u0026#34; ) + \u0026#34;开始 还有\u0026#34; + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;)) + \u0026#34;年\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) - dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;) * 12) + \u0026#34;月\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;) - floor(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) * 30.44)) + \u0026#34;天\u0026#34;, \u0026#34;0天\u0026#34; ) + \u0026#34;结束 -%\u0026#34;, if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) \u0026lt; dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;), format(slice(\u0026#34;::::::::::::::::::::::::::::::::::::::::\u0026#34;, 0, floor(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) / dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) * 40))) + format(slice(\u0026#34;........................................\u0026#34;, 0, 40 - floor(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) / dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) * 40))) + \u0026#34; 经过\u0026#34; + if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;) \u0026gt; 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;)) + \u0026#34;年\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) \u0026gt; 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) - dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;) * 12) + \u0026#34;月\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) \u0026gt; 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) - floor(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) * 30.44)) + \u0026#34;天\u0026#34;, \u0026#34;0天\u0026#34; ) + \u0026#34; 还有\u0026#34; + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;)) + \u0026#34;年\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) - dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;) * 12) + \u0026#34;月\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;) - floor(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) * 30.44)) + \u0026#34;天\u0026#34;, \u0026#34;0天\u0026#34; ) + \u0026#34;结束\u0026#34; + \u0026#34; \u0026#34; + format(round(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) / dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) * 100)) + \u0026#34;%\u0026#34;, \u0026#34;::::::::::::::::::::::::::::::::::::::::\u0026#34; + \u0026#34; 经过\u0026#34; + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;)) + \u0026#34;年\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) - dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;) * 12) + \u0026#34;月\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) - floor(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) * 30.44)) + \u0026#34;天\u0026#34;, \u0026#34;0天\u0026#34; ) + \u0026#34; 还有0天结束 100%\u0026#34; ) ) ) ) 效果 版本1\n版本2\n也可以使用官方的进度条, 不过限制还是很多的,不如自定义.\nps: notion formula能自定义函数就好了…\npps:\n优化一下经过和剩余日期的计算公式, 替换了一下进度条符号(▦ ▢)\n\u0026#34;进度: \u0026#34; + format(slice(\u0026#34;▦▦▦▦▦▦▦▦▦▦\u0026#34;, 0, ceil(prop(\u0026#34;Done\u0026#34;) / prop(\u0026#34;Total\u0026#34;) * 10))) + format(slice(\u0026#34;▢▢▢▢▢▢▢▢▢▢\u0026#34;, 0, 10 - ceil(prop(\u0026#34;Done\u0026#34;) / prop(\u0026#34;Total\u0026#34;) * 10))) + \u0026#34; \u0026#34; + format(round(prop(\u0026#34;Done\u0026#34;) / prop(\u0026#34;Total\u0026#34;) * 100)) + \u0026#34;%\u0026#34; + \u0026#34;\\n日期: \u0026#34; + if( empty(start(prop(\u0026#34;Date\u0026#34;))), \u0026#34;▢▢▢▢▢▢▢▢▢▢ 经过-天 还有-天结束 -%\u0026#34;, if( start(prop(\u0026#34;Date\u0026#34;)) == end(prop(\u0026#34;Date\u0026#34;)), \u0026#34;▢▢▢▢▢▢▢▢▢▢ 经过\u0026#34; + if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;) \u0026gt; 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;)) + \u0026#34;年\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) \u0026gt; 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) - dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;) * 12) + \u0026#34;月\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) \u0026gt;= 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) - floor(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) * 30.44)) + \u0026#34;天\u0026#34;, \u0026#34;0天\u0026#34; ) + \u0026#34; 还有-天结束 -%\u0026#34;, if( start(prop(\u0026#34;Date\u0026#34;)) \u0026gt; now(), \u0026#34;▢▢▢▢▢▢▢▢▢▢ 还有\u0026#34; + if( dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;) \u0026gt; 0, format(dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;)) + \u0026#34;年\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) \u0026gt; 0, format(dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) - dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;) * 12) + \u0026#34;月\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;) \u0026gt;= 0, format(dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;) - floor(dateBetween(start(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) * 30.44) + 1) + \u0026#34;天\u0026#34;, \u0026#34;0天\u0026#34; ) + \u0026#34;开始 还有\u0026#34; + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;)) + \u0026#34;年\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) - dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;) * 12) + \u0026#34;月\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;) \u0026gt;= 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;) - floor(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) * 30.44) + 1) + \u0026#34;天\u0026#34;, \u0026#34;0天\u0026#34; ) + \u0026#34;结束 -%\u0026#34;, if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) \u0026lt; dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;), format(slice(\u0026#34;▦▦▦▦▦▦▦▦▦▦\u0026#34;, 0, floor(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) / dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) * 10))) + format(slice(\u0026#34;▢▢▢▢▢▢▢▢▢▢\u0026#34;, 0, 10 - floor(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) / dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) * 10))) + \u0026#34; 经过\u0026#34; + if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;) \u0026gt; 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;)) + \u0026#34;年\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) \u0026gt; 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) - dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;) * 12) + \u0026#34;月\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) \u0026gt;= 0, format(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) - floor(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) * 30.44)) + \u0026#34;天\u0026#34;, \u0026#34;0天\u0026#34; ) + \u0026#34; 还有\u0026#34; + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;)) + \u0026#34;年\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) - dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;years\u0026#34;) * 12) + \u0026#34;月\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;) \u0026gt;= 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;days\u0026#34;) - floor(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), now(), \u0026#34;months\u0026#34;) * 30.44) + 1) + \u0026#34;天\u0026#34;, \u0026#34;0天\u0026#34; ) + \u0026#34;结束\u0026#34; + \u0026#34; \u0026#34; + format(round(dateBetween(now(), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) / dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) * 100)) + \u0026#34;%\u0026#34;, \u0026#34;▦▦▦▦▦▦▦▦▦▦\u0026#34; + \u0026#34; 经过\u0026#34; + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;)) + \u0026#34;年\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) \u0026gt; 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) - dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;years\u0026#34;) * 12) + \u0026#34;月\u0026#34;, \u0026#34;\u0026#34; ) + if( dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) \u0026gt;= 0, format(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;days\u0026#34;) - floor(dateBetween(end(prop(\u0026#34;Date\u0026#34;)), start(prop(\u0026#34;Date\u0026#34;)), \u0026#34;months\u0026#34;) * 30.44)) + \u0026#34;天\u0026#34;, \u0026#34;0天\u0026#34; ) + \u0026#34; 还有0天结束 100%\u0026#34; ) ) ) ) 方形符號 - ▩\n","permalink":"https://sqf.icu/article/ebeae06c-3412-465c-bac9-a5fc095a323b/","summary":"\u003ch1 id=\"用途\"\u003e用途\u003c/h1\u003e\n\u003col\u003e\n\u003cli\u003e计算表格中开始日期和结束日期, 显示经过了几天, 还有几天结束, 经过天数和总天数的百分比\u003c/li\u003e\n\u003cli\u003e计算Done和Total列的数值(任务完成的值和总值), 计算任务完成度, 显示任务完成了多少\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch1 id=\"代码\"\u003e代码\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e使用时, 删除缩进和换行. 使代码变为1行复制到表格Formula列.\u003c/li\u003e\n\u003cli\u003e注意替换列名\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003evscode\u003c/code\u003e里删除缩进和换行→按\u003ccode\u003ectrl+shift+h\u003c/code\u003e替换→正则模式\u003ccode\u003e\\n|\u003c/code\u003e     替换为空.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;进度: \u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eformat\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eslice\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;::::::::::::::::::::::::::::::::::::::::\u0026#34;\u003c/span\u003e, 0, ceil\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Done\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e / prop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Total\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 40\u003cspan style=\"color:#f92672\"\u003e)))\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eformat\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eslice\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;........................................\u0026#34;\u003c/span\u003e, 0, \u003cspan style=\"color:#ae81ff\"\u003e40\u003c/span\u003e - ceil\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Done\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e / prop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Total\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 40\u003cspan style=\"color:#f92672\"\u003e)))\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34; \u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eformat\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eround\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Done\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e / prop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Total\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 100\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%\u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\\n日期: \u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    empty\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003estart\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)))\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;........................................ 经过-天 还有-天结束 -%\u0026#34;\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e end\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;........................................ 经过\u0026#34;\u003c/span\u003e + format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;天 还有-天结束 -%\u0026#34;\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e \u0026gt; now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;........................................ 还有\u0026#34;\u003c/span\u003e + format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003estart\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;天开始 还有\u0026#34;\u003c/span\u003e + format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;天结束 -%\u0026#34;\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026lt; dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eslice\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;::::::::::::::::::::::::::::::::::::::::\u0026#34;\u003c/span\u003e, 0, floor\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e / dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 40\u003cspan style=\"color:#f92672\"\u003e)))\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eslice\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;........................................\u0026#34;\u003c/span\u003e, 0, \u003cspan style=\"color:#ae81ff\"\u003e40\u003c/span\u003e - floor\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e / dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 40\u003cspan style=\"color:#f92672\"\u003e)))\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34; 经过\u0026#34;\u003c/span\u003e + format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;天\u0026#34;\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34; 还有\u0026#34;\u003c/span\u003e + format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;天结束\u0026#34;\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34; \u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eround\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e / dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 100\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%\u0026#34;\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;::::::::::::::::::::::::::::::::::::::::\u0026#34;\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34; 用\u0026#34;\u003c/span\u003e + format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;天 还有0天结束 100%\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e一些常用函数\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eformat: 转换为字符串 format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e随便啥的\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eslice: 字符串切片 slice\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003estr, 开始index, 结束index\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e取不到\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eceil: 小数取大于这个数的整数 ceil\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e1.1\u003cspan style=\"color:#f92672\"\u003e)=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efloor: 小数取小于这个数的整数 ceil\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e1.1\u003cspan style=\"color:#f92672\"\u003e)=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eround: 小数四舍五入 round\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e4.4\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e round\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e4.5\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eprop: 取某一列元素 prop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e 取日期那一列\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e: 日期格式开始日期和结束日期\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e如果没有结束日期时, 默认结束日期等于开始日期\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e: 当前日期\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edateBetween: 计算两个日期间的天数或月数 dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e结束日期, 开始日期, \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e])\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e: if判断 \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e判断条件, 如果为true运行代码, 如果为false运行代码\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eempty: 空返回true, 非空返回false\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e也可以将天数转换为年月日\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e需要修改下面代码\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eformat\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e改为\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;年\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e - dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 12\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;月\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e - floor\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 30.44\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;天\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;0天\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e合并后 版本2\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;进度: \u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eformat\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eslice\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;::::::::::::::::::::::::::::::::::::::::\u0026#34;\u003c/span\u003e, 0, ceil\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Done\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e / prop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Total\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 40\u003cspan style=\"color:#f92672\"\u003e)))\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eformat\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eslice\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;........................................\u0026#34;\u003c/span\u003e, 0, \u003cspan style=\"color:#ae81ff\"\u003e40\u003c/span\u003e - ceil\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Done\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e / prop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Total\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 40\u003cspan style=\"color:#f92672\"\u003e)))\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34; \u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eformat\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eround\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Done\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e / prop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Total\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 100\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%\u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\\n日期: \u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    empty\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003estart\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)))\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;........................................ 经过-天 还有-天结束 -%\u0026#34;\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e end\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;........................................ 经过\u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;年\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e - dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 12\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;月\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e - floor\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 30.44\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;天\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;0天\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34; 还有-天结束 -%\u0026#34;\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e \u0026gt; now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;........................................ 还有\u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003estart\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003estart\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;年\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003estart\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003estart\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e - dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003estart\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 12\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;月\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003estart\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003estart\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e - floor\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003estart\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 30.44\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;天\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;0天\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;开始 还有\u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;年\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e - dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 12\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;月\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e - floor\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 30.44\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;天\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;0天\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;结束 -%\u0026#34;\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026lt; dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eslice\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;::::::::::::::::::::::::::::::::::::::::\u0026#34;\u003c/span\u003e, 0, floor\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e / dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 40\u003cspan style=\"color:#f92672\"\u003e)))\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eslice\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;........................................\u0026#34;\u003c/span\u003e, 0, \u003cspan style=\"color:#ae81ff\"\u003e40\u003c/span\u003e - floor\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e / dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 40\u003cspan style=\"color:#f92672\"\u003e)))\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34; 经过\u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;年\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e - dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 12\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;月\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e - floor\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 30.44\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;天\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;0天\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34; 还有\u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;年\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e - dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 12\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;月\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e - floor\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, now\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 30.44\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;天\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;0天\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;结束\u0026#34;\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34; \u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eround\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003enow\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e / dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 100\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%\u0026#34;\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;::::::::::::::::::::::::::::::::::::::::\u0026#34;\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34; 经过\u0026#34;\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;年\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e - dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;years\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 12\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;月\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    dateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u0026gt; 0,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    format\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;days\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e - floor\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edateBetween\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eend\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, start\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eprop\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Date\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;months\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e * 30.44\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;天\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;0天\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e + \u003cspan style=\"color:#e6db74\"\u003e\u0026#34; 还有0天结束 100%\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"Notion formula 表格中自动计算日期完成度的进度条和任务完成的进度条"},{"content":"Nas静音 威联通Nas买来之后每天3点都会自动开始一些计划任务, 关闭后晚上安静不少\n关于计划任务的说明和操作在这里\nAdd items to crontab\n# ┌───────────── minute (0 - 59) # │ ┌───────────── hour (0 - 23) # │ │ ┌───────────── day of the month (1 - 31) # │ │ │ ┌───────────── month (1 - 12) # │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday; # │ │ │ │ │ 7 is also Sunday on some systems) # │ │ │ │ │ # │ │ │ │ │ # * * * * * \u0026lt;command to execute\u0026gt; 问题是执行sudo crontab /etc/config/crontab \u0026amp;\u0026amp; sudo /etc/init.d/crond.sh restart 命令之后, 一些任务又会自动重置\n0 3 * * * /sbin/vs_refresh 4 3 * * 3 /etc/init.d/backup_conf.sh 解决方法:\n问题出在/etc/init.d/crond.sh 上, 修改之\n############# # 46行 echo \u0026#34;0 3 * * * /sbin/vs_refresh\u0026#34; \u0026gt;\u0026gt; /etc/config/crontab # 或者新版 46行 local time=$(/sbin/getcfg vs_refresh schedule -d \u0026#39;13:0\u0026#39;) ############ # 88-97行 1) #once a day echo \u0026#34;4 13 * * * /etc/init.d/backup_conf.sh\u0026#34; \u0026gt;\u0026gt; /etc/config/crontab ;; 30) #once a month echo \u0026#34;4 13 3 * * /etc/init.d/backup_conf.sh\u0026#34; \u0026gt;\u0026gt; /etc/config/crontab ;; 7) #once a week echo \u0026#34;4 13 * * 3 /etc/init.d/backup_conf.sh\u0026#34; \u0026gt;\u0026gt; /etc/config/crontab ;; *) #for testing echo \u0026#34;*/3 * * * * /etc/init.d/backup_conf.sh\u0026#34; \u0026gt;\u0026gt; /etc/config/crontab ;; 重启nas可能会重置设置 需注意.\n分别压缩每个文件夹到单个压缩包(linux方面) 到存放需要分别压缩的文件夹的根目录下\nfind * -type d -maxdepth 1 | xargs -i zip -r -m {}.zip {} find参数 需要使用*来避免匹配到当前目录./ -type: 匹配的类型. d: 文件夹; f: 文件 -maxdepth: 最大的寻找文件夹深度 xargs -i: 匹配linux zip -r: 遍历文件夹下的文件 -m: 压缩后删除源文件 威联通一些系统设置 开机自动启动\nAll HAL-based Intel and AMD NAS use ... mount $(/sbin/hal_app --get_boot_pd port_id=0)6 /tmp/config touch /tmp/config/autorun.sh chmod +x /tmp/config/autorun.sh $EDITOR /tmp/config/autorun.sh umount /tmp/config autorun.sh启动脚本样例\n/share/CACHEDEV1_DATA/homes/xxx/frp/frpc -c /share/CACHEDEV1_DATA/xxx/frp/frpc.ini \u0026gt;\u0026gt; /share/CACHEDEV1_DATA/homes/xxx/frp/frp.log \u0026amp; # \u0026amp; 表示后台运行这个程序 ln -s /share/CACHEDEV1_DATA/homes /share/homes # ssh登陆时, 用户能找到默认路径. /share/CACHEDEV1_DATA为系统安装盘挂载的位置. iptbales防火墙\n防火墙的最后一行需要drop掉所有端口服务, 在上面插入需要放行的端口 iptables -L # 查看防火墙配置 iptables -L -n --line-number # 查看规则行数 sudo iptables -D [INPUT/QUFIREWALL/FORWARD/OUTPUT] [规则行数] # 删除特定规则 sudo iptables -I [INPUT/QUFIREWALL/FORWARD/OUTPUT] -m multiport -p tcp --dports [要放行的端口] -j ACCEPT # -I 插入第一行. -A 插入最后一行 威联通单盘休眠设置 不推荐, 每次访问硬盘的时候, 磁盘电机启动声很大.\n1. 查看被系统设置为raid1的磁盘 辨认各个分区对应的物理磁盘\nsudo parted /dev/sda print sudo parted /dev/sdb print 查看系统raid1所挂载的分区\nsudo mdadm -D /dev/md9 Number Major Minor RaidDevice State 0 8 33 0 active sync /dev/sdc1 1 8 49 1 active sync /dev/sdd1 2 8 65 2 active sync /dev/sde1 3 8 17 3 active sync /dev/sdb1 128 8 1 4 active sync /dev/sda1 sudo mdadm -D /dev/m13 Number Major Minor RaidDevice State 0 8 36 0 active sync /dev/sdc4 1 8 52 1 active sync /dev/sdd4 2 8 68 2 active sync /dev/sde4 3 8 20 3 active sync /dev/sdb4 128 8 4 4 active sync /dev/sda4 2. 建立脚本 文件存放地址: /share/CACHEDEV1_DATA/homes/sun/internal_raid_setting\n建立三个脚本\n# 将机械硬盘断开系统raid1 vim disconnect_internal_raid.sh* #!/bin/sh mdadm /dev/md9 --fail /dev/sda1 mdadm /dev/md9 --fail /dev/sdc1 mdadm /dev/md9 --fail /dev/sdd1 mdadm /dev/md9 --fail /dev/sde1 mdadm /dev/md13 --fail /dev/sda4 mdadm /dev/md13 --fail /dev/sdc4 mdadm /dev/md13 --fail /dev/sdd4 mdadm /dev/md13 --fail /dev/sde4 # 将机械硬盘连接系统raid1 vim rebuild_internal_raid.sh* #!/bin/sh mdadm /dev/md9 --re-add /dev/sda1 mdadm /dev/md9 --re-add /dev/sdc1 mdadm /dev/md9 --re-add /dev/sdd1 mdadm /dev/md9 --re-add /dev/sde1 mdadm /dev/md13 --re-add /dev/sda4 mdadm /dev/md13 --re-add /dev/sdc4 mdadm /dev/md13 --re-add /dev/sdd4 mdadm /dev/md13 --re-add /dev/sde4 # 设置磁盘状态监视脚本 vim raid1_monitor.sh* #!/bin/sh echo `date` `hdparm -C /dev/sda | grep state` \u0026gt;\u0026gt; /share/CACHEDEV1_DATA/homes/sun/internal_raid_setting/raid1_monitor.log 2\u0026gt;\u0026amp;1 echo `date` `hdparm -C /dev/sdb | grep state` \u0026gt;\u0026gt; /share/CACHEDEV1_DATA/homes/sun/internal_raid_setting/raid1_monitor.log 2\u0026gt;\u0026amp;1 echo `date` `hdparm -C /dev/sdc | grep state` \u0026gt;\u0026gt; /share/CACHEDEV1_DATA/homes/sun/internal_raid_setting/raid1_monitor.log 2\u0026gt;\u0026amp;1 echo `date` `hdparm -C /dev/sdd | grep state` \u0026gt;\u0026gt; /share/CACHEDEV1_DATA/homes/sun/internal_raid_setting/raid1_monitor.log 2\u0026gt;\u0026amp;1 echo `date` `hdparm -C /dev/sde | grep state` \u0026gt;\u0026gt; /share/CACHEDEV1_DATA/homes/sun/internal_raid_setting/raid1_monitor.log 2\u0026gt;\u0026amp;1 设置系统任务计划\n# 每天 0 点恢复系统 RAID1 $ echo \u0026#34;0 0 * * * /bin/bash /share/CACHEDEV1_DATA/my_cron/readd_raid1.sh\u0026#34; \u0026gt;\u0026gt; /etc/config/crontab # 每天 0 点 15 分恢复系统 RAID1 $ echo \u0026#34;15 0 * * * /bin/bash /share/CACHEDEV1_DATA/my_cron/fail_raid1.sh\u0026#34; \u0026gt;\u0026gt; /etc/config/crontab # 每 10 分钟检测 HDD 是否休眠，结果保存在 raid1_monitor.log 中 $ echo \u0026#34;*/10 * * * * /bin/bash /share/CACHEDEV1_DATA/my_cron/raid1_monitor.sh\u0026#34; \u0026gt;\u0026gt; /etc/config/crontab # 重启 crontab $ sudo crontab /etc/config/crontab \u0026amp;\u0026amp; sudo /etc/init.d/crond.sh restart Reference https://github.com/Bpazy/blog/issues/150\n安装python3 在App center安装python3\n命令行启用python3\nsource /etc/profile.d/python3.bash ","permalink":"https://sqf.icu/article/968feb30-37f3-4fc8-a08a-36ab750a2e1d/","summary":"\u003ch1 id=\"nas静音\"\u003eNas静音\u003c/h1\u003e\n\u003cp\u003e威联通Nas买来之后每天3点都会自动开始一些计划任务, 关闭后晚上安静不少\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e关于计划任务的说明和操作在这里\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://wiki.qnap.com/wiki?title=Add_items_to_crontab\u0026amp;setlang=ja\"\u003eAdd items to crontab\u003c/a\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ┌───────────── minute (0 - 59)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │ ┌───────────── hour (0 - 23)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │ │ ┌───────────── day of the month (1 - 31)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │ │ │ ┌───────────── month (1 - 12)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │ │ │ │ │                                   7 is also Sunday on some systems)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │ │ │ │ │\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │ │ │ │ │\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# * * * * * \u0026lt;command to execute\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e问题是执行\u003ccode\u003esudo crontab /etc/config/crontab \u0026amp;\u0026amp; sudo /etc/init.d/crond.sh restart\u003c/code\u003e 命令之后, 一些任务又会自动重置\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e * * * /sbin/vs_refresh\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e * * \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e /etc/init.d/backup_conf.sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e解决方法:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e问题出在\u003ccode\u003e/etc/init.d/crond.sh\u003c/code\u003e 上, 修改之\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#############\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 46行\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;0 3 * * * /sbin/vs_refresh\u0026#34;\u003c/span\u003e \u0026gt;\u0026gt; /etc/config/crontab\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 或者新版 46行\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elocal time\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003e/sbin/getcfg vs_refresh schedule -d \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;13:0\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e############\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 88-97行\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e1\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e      \u003cspan style=\"color:#75715e\"\u003e#once a day\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;4 13 * * * /etc/init.d/backup_conf.sh\u0026#34;\u003c/span\u003e \u0026gt;\u0026gt; /etc/config/crontab\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e;;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e30\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e     \u003cspan style=\"color:#75715e\"\u003e#once a month\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;4 13 3 * * /etc/init.d/backup_conf.sh\u0026#34;\u003c/span\u003e \u0026gt;\u0026gt; /etc/config/crontab\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e;;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e7\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e      \u003cspan style=\"color:#75715e\"\u003e#once a week\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;4 13 * * 3 /etc/init.d/backup_conf.sh\u0026#34;\u003c/span\u003e \u0026gt;\u0026gt; /etc/config/crontab\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e;;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e*\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e      \u003cspan style=\"color:#75715e\"\u003e#for testing\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;*/3 * * * * /etc/init.d/backup_conf.sh\u0026#34;\u003c/span\u003e \u0026gt;\u0026gt; /etc/config/crontab\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e;;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e重启nas可能会重置设置 需注意.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"威联通QNAP Nas 相关问题"},{"content":" 目前好用的DNS # 较稳定\r223.5.5.5 # 有时可以满速\r168.126.63.1\r168.126.63.2\r# 可以尝试\r34.80.2.188 PS5 如何修改DNS\n另外, psn图片上传功能无法在挂代理的时候使用(可能是代理设定的dns的原因), 需要断开代理, 挂dns. ","permalink":"https://sqf.icu/article/17251a3a-059a-4972-bbb1-e0bf3420653d/","summary":"\u003cul\u003e\n\u003cli\u003e目前好用的DNS\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# 较稳定\r\n223.5.5.5  # 有时可以满速\r\n168.126.63.1\r\n168.126.63.2\r\n\r\n# 可以尝试\r\n34.80.2.188\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e\u003ca href=\"https://zhuanlan.zhihu.com/p/345649053\"\u003ePS5 如何修改DNS\u003c/a\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e另外, psn图片上传功能无法在挂代理的时候使用(可能是代理设定的dns的原因), 需要断开代理, 挂dns.\u003c/li\u003e\n\u003c/ul\u003e","title":"PS5/Switch DNS"},{"content":"以下是开发过程中遇到的C++的一些特性记录. tags: C/C++, Decode, GPU, Python category: Documents\n当前目的开发c++硬解码并使用python调用其动态库实现一次抽一次帧.\n以下是开发过程中遇到的C++的一些特性记录.\n1. 二级指针初始化与释放 二级指针需要初始化两次, 分别是二级指针和一级指针\nint **a; a = (int *)malloc(num * sizeof(int)); for (int32_t i = 0; i \u0026lt; num; i++) { a[i] = (int)malloc(num_2 * sizeof(int)); } // or int **a; a = new int*[num]; for (int32_t i = 0; i \u0026lt; num; i++) { a[i] = new int[num_2]; } 释放指针, 需要先释放一级指针再释放二级指针, 如果先释放二级指针, 一级指针的地址会丢失, 导致内存泄漏.\nfor(i = 0; i \u0026lt; 100; i++) { delete []temp[i]; } delete []temp; 2. C++结构体与python传值 c++定义结构体对象\nstruct VideoPreprocessInf { int64_t frame_index = 0; int32_t ori_w = 0; int32_t ori_h = 0; int32_t resize_w = 0; int32_t resize_h = 0; int32_t img_w = 0; int32_t img_h = 0; int32_t pad_w = 0; int32_t pad_h = 0; int32_t roi_start_w = 0; int32_t roi_start_h = 0; int32_t roi_w = 0; int32_t roi_h = 0; int32_t channel = 3; int32_t output_size = 0; bool do_crop_middle = false; bool do_padding = false; float scale = 1.f; double mean[3] = {0.0f, 0.0f, 0.0f}; double standard[3] = {1.f, 1.f, 1.f}; } video_preprocess_inf; python定义同结构体对象\nclass VideoPreprocessInf(Structure): _fields_ = ( (\u0026#39;frame_index\u0026#39;, c_longlong), (\u0026#39;ori_w \u0026#39;, c_int), (\u0026#39;ori_h \u0026#39;, c_int), (\u0026#39;resize_w \u0026#39;, c_int), (\u0026#39;resize_h \u0026#39;, c_int), (\u0026#39;img_w \u0026#39;, c_int), (\u0026#39;img_h \u0026#39;, c_int), (\u0026#39;pad_w \u0026#39;, c_int), (\u0026#39;pad_h \u0026#39;, c_int), (\u0026#39;roi_start_w \u0026#39;, c_int), (\u0026#39;roi_start_h \u0026#39;, c_int), (\u0026#39;roi_w \u0026#39;, c_int), (\u0026#39;roi_h \u0026#39;, c_int), (\u0026#39;channel\u0026#39;, c_int), (\u0026#39;output_size\u0026#39;, c_int), (\u0026#39;do_crop_middle\u0026#39;, c_bool), (\u0026#39;do_padding\u0026#39;, c_bool), (\u0026#39;scale\u0026#39;, c_float), (\u0026#39;mean\u0026#39;, c_double * 3), (\u0026#39;standard\u0026#39;, c_double * 3), ) python端初始化结构体示例\n之后就可以输入C++动态库函数\ninf_list = [0, 0, 0, resize_w, resize_h, 0, 0, 0, 0, 0, 0, 0, 0, channel, 0, do_crop_middle, do_padding, 1.0, mean, standard] video_preprocess_inf = VideoPreprocessInf(*inf_list) C++端初始化结构体\n全局结构体只需要在结构体结尾加上变量, 其他地方只要使用变量即可\nstruct VideoPreprocessInf { int64_t frame_index = 0; ... } video_preprocess_inf; 需要当成调用多次的时候初始化:\nstruct VideoPreprocessInf { int64_t frame_index = 0; ... }; //初始化 VideoPreprocessInf vpi = { .frame_index = 1, ... }; // 或者 VideoPreprocessInf vpi = { frame_index:1, ... }; // 或者给需要修改的元素各自赋值 VideoPreprocessInf vpi; vpi.frame_index = 1; ... 3. C++头文件使用C风格的函数 extern \u0026#34;C\u0026#34; { int xxxx(); } 4. struct和typedef struct的区别 struct和typedef struct彻底明白了\nDifference between \u0026lsquo;struct\u0026rsquo; and \u0026rsquo;typedef struct\u0026rsquo; in C++?\n5. 实现python调用c++单步抽帧 使用全局指针, 函数中全局指针指向new class demuxer 和 decoder\nDemuxer *demuxer_p = nullptr; DlDecoder *decoder_p = nullptr; VideoInitInf init_demuxer_decoder(char *inputFilename, int gpu_id) { // 初始化数据流提取器和解码器, 使用全局指针指向它们 demuxer_p = new Demuxer(inputFilename); decoder_p = new DlDecoder(gpu_id, 0xf, 0xf, true, demuxer_p-\u0026gt;GetVideoCodec()); ... } float *video_decoder(VideoPreprocessInf video_preprocess_inf, bool do_extract) { // 单步抽帧 demuxer_p-\u0026gt;Demux(\u0026amp;pVideo, \u0026amp;nVideoBytes); decoder_p-\u0026gt;Decode(pVideo, nVideoBytes, \u0026amp;output_frames, \u0026amp;output_frame_count, 0); ... } void release_demuxer_decoder() { // 如果指针指向内存地址, 则清除缓存, 重置指针 if (demuxer_p) { delete demuxer_p; demuxer_p = nullptr; } if (decoder_p) { delete decoder_p; decoder_p = nullptr; } ... } 6. C++ 11 Lambda表达式 遇到符号[=]\nC++ 11 Lambda表达式\n7. CUDA C编程 如何在 CUDA C/C++ 中实现数据传输的重叠\ncudaMemcpyAsync等知识\n7.1. python c++ 混合编程 华为开发者论坛\n环境\nhttps://github.com/pybind/pybind11\npip install pybind11 pip install pytest 直接使用pybind11文件夹, 直接放在项目文件夹根目录下, 和CMakeLists.txt还有cu.cc文件放一起.\ngit clone https://github.com/pybind/pybind11.git 7.1.1. cmakelists编译的过程中不停循环不终止问题 cmakelists循环执行_阿伟跑呀的博客-CSDN博客\n7.2. C++ 传承python方法2 7.3. python 使用ctype与C++通信 C++编译 Cmakelists.txt\nSET (LIBHELLO_SRC ${SRCS})\rADD_LIBRARY (AppDec SHARED ${LIBHELLO_SRC})\r# 输出动态库\rinstall(TARGETS AppDec\rLIBRARY DESTINATION ${CMAKE_BINARY_DIR}/bin\r) ","permalink":"https://sqf.icu/article/415935a0-a0fe-4156-8de1-be51d0072ac8/","summary":"\u003cp\u003e以下是开发过程中遇到的C++的一些特性记录.\ntags: C/C++, Decode, GPU, Python\ncategory: Documents\u003c/p\u003e\n\u003cp\u003e当前目的开发c++硬解码并使用python调用其动态库实现一次抽一次帧.\u003c/p\u003e\n\u003cp\u003e以下是开发过程中遇到的C++的一些特性记录.\u003c/p\u003e","title":"硬解码开发过程中遇到的一些c++和python混合编程问题"},{"content":" 参考三维重建公开课前两节课\n2022B站最好最全的【三维重建】课程！！！北邮教授竟然把三维重建讲的如此通俗易懂，学不会UPZHIJIE 退网下架！！！-人工智能/计算机视觉/三维重建_哔哩哔哩_bilibili\n1. 摄像机几何 1.1. 针孔模型\u0026amp;透镜 1.1.1. 针孔相机 早期相机: 小孔成像(添加屏障→减少模糊)\n需要研究的是虚拟像平面\n虚拟像平面到针孔的距离等于焦距 虚拟像平面的成像大小等于像平面的成像大小, 方向与原物体相同, 研究方便 缩小光圈可以使成像更清晰, 但是通过的光更少(成像更暗)\n为了使成像更亮, 可以增加一个透镜\n小孔成像系统建立数学模型\n摄像机坐标系下, 三维点到平面的关系\n$$\rP=\\left[\\begin{array}{l}x \\\\y \\\\z\\end{array}\\right] \\rightarrow P^{\\prime}=\\left[\\begin{array}{l}x^{\\prime} \\\\y^{\\prime}\\end{array}\\right] \\quad\\left\\{\\begin{array}{l}x^{\\prime}=f \\frac{x}{z} \\\\y^{\\prime}=f \\frac{y}{z}\\end{array}\\right.\r$$ 1.1.2. 透镜 这里的f是透镜到焦点的距离\n近轴折射模型\n根据折射定律:\n$$\rf=\\frac{R}{2(n-1)}\r$$ $R$为透镜球面半在, $n$为透镜折射系数 $$\rz^{\\prime}=f+z_0\r$$$$\r\\begin{cases}x^{\\prime}=z^{\\prime} \\frac{x}{z} \\\\ y^{\\prime}=z^{\\prime} \\frac{y}{z}\\end{cases}\r$$ 近轴折射模型依旧满足小孔成像的数学模型 透镜缺点 失焦\n畸变\n1.2. 摄像机几何 1.2.1. 将像平面转换像素平面的过程 真实情况下, 成像获得的是离散的像素, 而不是连续的像平面图形\n→ 需要修改小孔成像模型\n偏置: 需要偏移坐标点的位置(像平面中的原点$C'$转换到像素图坐标上时位置是$[C_x, C_y]$)\n单位转换: 将单位 $m$ 转换为像素, 转换常数 $k$ ($x$方向) 和 $l$ ($y$方向) 以相机成像元器件参数为准.\n$$\r(x, y, z) \\rightarrow \\left( \\underbrace{f \\red{k}}_\\alpha\\frac{x}{z} +c_x, \\underbrace{f \\red{l}}_\\beta\\frac{y}{z} +c_y\\right)\r$$ 单位: $k,l:pixel/m; f:m$ 非方形像素: $\\alpha\\beta$: $pixel$ 合并一下相机成像元器件的参数\n$$\rP=(x, y, z) \\rightarrow P^{\\prime}=\\left(\\alpha \\frac{x}{z}+c_x, \\beta \\frac{y}{z}+c_y\\right)\r$$ 存在一个问题: $P$(三维空间坐标系的点坐标)$\\to P'$(像素平面坐标系的点坐标)的变换不是线性变换, 因为$x$的改变会使$z$也改变(如果将$\\frac{\\alpha}{z}$理解为直线的斜率的话)\n1.2.2. 将像平面转换像素平面的过程变为线性变换(齐次坐标系) 欧式坐标变为齐次坐标: 将原本是n维的坐标向量用n+1维表示(一一对应)\n齐次坐标还原欧式坐标: 将最后一维的值除以前面的每一维的值\n不一一对应, 下面这两个齐次坐标还原后相同\n$$\r\\begin{bmatrix} 1\\\\ 1\\\\ 1\\end{bmatrix}\\begin{bmatrix} 2\\\\ 2\\\\ 2\\end{bmatrix}\r$$ 欧式转齐次公式\n1.2.3. 解决相机偏斜问题 相机工艺问题造成偏斜, $\\theta$角夹角\n带偏斜补正的转换公式\nK有5个自由度(5个可变参数) $$\rP'=MP=K\\begin{bmatrix}I\u0026 0\\end{bmatrix}P\r$$$$\rI = \\begin{bmatrix} 1\u00260\u00260\\\\ 0\u00261\u00260\\\\ 0\u00260\u00261\\end{bmatrix}\r$$\n1.2.4. 规范化相机 规范化相机在现实世界不存在, 三维点坐标等于齐次坐标的前3维\n$$\rP^{\\prime}=\\left[\\begin{array}{l}x \\\\y \\\\z\\end{array}\\right]=\\underbrace{\\left[\\begin{array}{llll}1 \u0026 0 \u0026 0 \u0026 0 \\\\0 \u0026 1 \u0026 0 \u0026 0 \\\\0 \u0026 0 \u0026 1 \u0026 0\\end{array}\\right]}_M\\left[\\begin{array}{l}x \\\\y \\\\z \\\\1\\end{array}\\right]\r$$ $P^{\\prime}$的欧式坐标为\n$$\r\\left[\\begin{array}{l}\r\\frac{x}{z} \\\\\r\\frac{y}{z}\r\\end{array}\\right]\r$$ 1.2.5. 世界坐标系与投影矩阵 世界坐标系用于方便的描述三维物体的空间信息\n$R$: 旋转矩阵 (3, 3); $T$: 平移矩阵 (3, 1)\n$\\begin{bmatrix} R\u0026T\\\\ 0\u00261\\end{bmatrix}$: 转换参数 (4, 4)\n最终获得$P_w$: 世界坐标系坐标 (4, 1)\n整理公式获得完整的相机模型\n$P'$: 像素平面, $P$: 摄像机坐标下点的坐标, $P_w$: 世界坐标系下$P$点的位置.\n投影矩阵有11个自由度(内参5个, 外参 $R$ ( $xyz$ 3个), $T$ ( $xyz$ 3个))\n计算像素平面坐标 $P'$\n$$\rP^{\\prime}=M P_w=\\left[\\begin{array}{l}m_1 \\\\m_2 \\\\m_3\\end{array}\\right] P_w=\\left[\\begin{array}{l}m_1 P_w \\\\m_2 P_w \\\\m_3 P_w\\end{array}\\right] \\rightarrow\\left(\\frac{m_1 P_w}{m_3 P_w}, \\frac{m_2 P_w}{m_3 P_w}\\right)\r$$$$\rM=\\left[\\begin{array}{l}m_1 \\\\m_2 \\\\m_3\\end{array}\\right]\r$$ 定理 (Faugeras, 1993)\n$$\rM=K[R T]=\\left[\\begin{array}{ll}K R \u0026 K T\\end{array}\\right]=\\left[\\begin{array}{ll}A \u0026 b\\end{array}\\right] \\quad A=\\left[\\begin{array}{c}a_1^T \\\\a_2^T \\\\a_3^T\\end{array}\\right]\r$$ 令 $M=(A \\ b)$ 为 $3\\times 4$ 的矩阵, $a_i^T(i=1,2,3)$ 表示为矩阵 $A$ 的行 M是透视投影矩阵的充分必要条件 $Det(A)\\not=0$ (A是满秩矩阵) 关于秩 秩的概念: 在线性代数中，一个矩阵A的列秩是A的线性独立的纵列的极大数目。类似地，行秩是A的线性无关的横行的极大数目。\n计算秩的例子:\n根据这个定理，我们得到利用初等变换求矩阵的秩的方法: 用初等行变换把矩阵变成行阶梯形矩阵, 行阶梯形矩阵中非零行的行数就是该矩阵的秩.\neg: 求矩阵 $A$ 的秩.\n$$\rA=\\left(\\begin{array}{rrrr}1 \u0026 0 \u0026 0 \u0026 1 \\\\ 1 \u0026 2 \u0026 0 \u0026 -1 \\\\ 3 \u0026 -1 \u0026 0 \u0026 4 \\\\ 1 \u0026 4 \u0026 5 \u0026 1\\end{array}\\right)\r$$\n所以 $\\mathrm{r}(\\boldsymbol{A})=3$\n满秩和失秩$m\\times n$矩阵的秩最大为: m和n中的较小者, 表示为 $min(m,n)$. 有尽可能大的秩的矩阵被称为有满秩; 否则矩阵是**秩不足(**或称为“欠秩”)的.\nM是零倾斜透视投影矩阵的充分必要条件 $Det(A)\\not=0$ $(a_1\\times a_3)\\cdot(a_2\\times a_3)=0$ ($\\theta=90^{\\circ}$ ) 关于矩阵乘法 叉乘的概念: $a\\times b = c$, 则$c$垂直于$ab$向量的平面 点乘的概念: 如果$a\\cdot b=0$, 则$a$垂直于$b$ M是零倾斜且宽高比为1透视投影矩阵的充分必要条件 $Det(A)\\not=0$ $(a_1\\times a_3)\\cdot(a_2\\times a_3)=0$ $(a_1\\times a_3)\\cdot(a_1\\times a_3)=(a_2\\times a_3)\\cdot(a_2\\times a_3)$ 1.2.6. 投影变换 1.3. 其他摄像机模型 各种相机的作用\n1.3.1. 弱透视投影相机 $\\pi$的场景点全都认为在同一个平面(用于处理距离较远的点)\n放大率$m$\n$$\r\\left\\{\\begin{array} { l } { x ^ { \\prime } = \\frac { f ^ { \\prime } } { z } x } \\\\{ y ^ { \\prime } = \\frac { f ^ { \\prime } } { z } y }\\end{array} \\rightarrow \\left\\{\\begin{array}{l}x^{\\prime}=\\frac{f^{\\prime}}{z_0} x \\\\y^{\\prime}=\\frac{f^{\\prime}}{z_0} y\\end{array}\\right.\\right.\r$$ 上: 原本的透视关系; 下: 弱透视投影相机的透视关系\n透视(世界坐标系下$P_w$点是齐次坐标, 要转换为非齐次)\n$$\r\\begin{aligned}P^{\\prime}= \u0026 M P_w=\\left[\\begin{array}{l}m_1 \\\\m_2 \\\\m_3\\end{array}\\right] P_w=\\left[\\begin{array}{l}m_1 P_w \\\\m_2 P_w \\\\m_3 P_w\\end{array}\\right] \\quad M=\\left[\\begin{array}{ll}A \u0026 b \\\\v \u0026 1\\end{array}\\right]=\\left[\\begin{array}{l}m_1 \\\\m_2 \\\\m_3\\end{array}\\right] \\\\\u0026 \\stackrel{\\mathbf{E}}{\\rightarrow}\\left(\\frac{m_1 P_w}{m_3 P_w}, \\frac{m_2 P_w}{m_3 P_w}\\right)\\end{aligned}\r$$ $m_i$: 1x4矩阵; $P_w$: 4x1矩阵\n投影矩阵\n$$\rM=K[R T]=\\left[\\begin{array}{l}m_1 \\\\m_2 \\\\m_3\\end{array}\\right]\r$$ $K$: 3x3; $R$: 3x3; $T$: 3x1→$[R\\ T]$: 3x4 弱透视\n$$\r\\begin{aligned} P^{\\prime}\u0026=M P_w=\\left[\\begin{array}{l}m_1 \\\\m_2 \\\\m_3\\end{array}\\right] P_w=\\left[\\begin{array}{c}m_1 P_w \\\\m_2 P_w \\\\1\\end{array}\\right] \u0026 M=\\left[\\begin{array}{ll}A \u0026 b \\\\0 \u0026 1\\end{array}\\right] = \\left[\\begin{array}{l}m_1 \\\\m_2 \\\\m_3\\end{array}\\right] \\\\\u0026 \\stackrel{\\mathbf{E}}{\\rightarrow}\\underbrace{\\left(m_1 P_w, m_2 P_w\\right)}_{m_1m_2是放大率} \\\\ \u0026\u0026=\\left[\\begin{array}{cccc} m_1 \\\\ m_2 \\\\ 0 \\quad 0 \\quad 0 \\quad 1\\end{array}\\right]\\end{aligned}\r$$ $m_1m_2m_3$都是(1, 4), 所以使用弱透视投影模型可以少4个参数, 于是可以加快计算\n1.3.2. 正交投影相机 相机中心到像平面无限远的时候\n$$\r\\left\\{\\begin{array} { l } { \\mathrm { x } ^ { \\prime } = \\frac { f ^ { \\prime } } { z } x } \\\\{ y ^ { \\prime } = \\frac { f ^ { \\prime } } { z } y }\\end{array} \\rightarrow \\left\\{\\begin{array}{l}x^{\\prime}=x \\\\y^{\\prime}=y\\end{array}\\right.\\right.\r$$ 1.4. 线性方程组的最小二乘解 1.4.1. 线性方程组的最小二乘解 线性方程组的解\n当方程组无解 $(p\u003eq)$ 的时候, 需要找最小二乘解\n$$\rE(x) \\stackrel{\\text { def }}{=} \\sum_{i=1}^p\\left(a_{i 1} x_1+a_{i 2} x_2+\\cdots a_{i q} x_q-y_i\\right)^2=\\|\\boldsymbol{A} \\boldsymbol{x}-\\boldsymbol{y}\\|^2\r$$ 线性方程组的最小二乘解\n$$\r\\boldsymbol{x}^*=\\underset{\\boldsymbol{x}}{\\operatorname{argmin}}\\|\\boldsymbol{A} \\boldsymbol{x}-\\boldsymbol{y}\\|^2\r$$\n1.4.2. 齐次线性方程组求最小二乘解 齐次线性方程组特点: y=0\n求解方法: 矩阵 $A$ 进行奇异值分解 $A=U D V^T$ $x^*$ 为 $V$ 矩阵的最后一列 (最小奇异值对应的右奇异向量) 1.4.3. 非线性方程组求最小二乘解 2. 相机标定 2.1. 透镜相机标定问题 2.1.1. 概念 相机标定: 求解相机内外参数矩阵\n用途: 通过这些参数描述三维世界到二维像素的映射关系\n公式:\n2.1.2. 求解相机内外参矩阵$M$ 相机的内外参构成了投影矩阵. 而投影矩阵有11个未知量组成.\n由1.3.1透视公式推导得出像素点公式\n$$\rp_i=\\left[\\begin{array}{l}u_i \\\\v_i\\end{array}\\right]=\\left[\\begin{array}{l}\\frac{m_1 P_i}{m_3 P_i} \\\\\\frac{m_2 P_i}{m_3 P_i}\\end{array}\\right]\r$$$$\r\\begin{aligned}\u0026 u_i=\\frac{m_1 P_i}{m_3 P_i} \\quad \\rightarrow \\quad u_i\\left(m_3 P_i\\right)=m_1 P_i \\quad \\rightarrow \\quad m_1 P_i-u_i\\left(m_3 P_i\\right)=0 \\\\\u0026 v_i=\\frac{m_2 P_i}{m_3 P_i} \\quad \\rightarrow \\quad v_i\\left(m_3 P_i\\right)=m_2 P_i \\quad \\rightarrow \\quad m_2 P_i-v_i\\left(m_3 P_i\\right)=0\\end{aligned}\r$$ 由于一个点可以获得两个方程, 所以做内参外参标定的时候有11个未知量, 需要至少6个点. 当获取了超过6个点的像素坐标信息之后, 就可以应用超定齐次线性方程组(p\u0026gt;q → 方程组的数量大于线性方程的未知参数的数量)求最小二乘解\n所有方程组合可得:\n$$\r\\left\\{\\begin{array}{c}-u_1\\left(m_3 P_1\\right)+m_1 P_1=0 \\\\-v_1\\left(m_3 P_1\\right)+m_2 P_1=0 \\\\\\vdots \\\\-u_n\\left(m_3 P_n\\right)+m_1 P_n=0 \\\\-v_n\\left(m_3 P_n\\right)+m_2 P_n=0\\end{array}\\right.\r$$简化得\n$$\rPm=0\r$$详细拆分, 由于最终$Pm$矩阵相乘之后是一个实数, 实数转置等于本身, 所以可以加转置符号.\n另外, $P$ 中的$P_n$是三维坐标, $u_n,v_n$ 是二维坐标, 都是已知的, 所以 $P$ 是线性变换.\n$$\rP \\stackrel{\\text { def }}{=}\\left(\\begin{array}{ccc}P_1^T \u0026 0^T \u0026 -u_1 P_1^T \\\\0^T \u0026 P_1^T \u0026 -v_1 P_1^T \\\\\u0026 \\vdots \u0026 \\\\P_n^T \u0026 0^T \u0026 -u_n P_n^T \\\\0^T \u0026 P_n^T \u0026 -v_n P_n^T\\end{array}\\right)_{2 n \\times 12}\r$$ 这里有12列是因为: $P_n^T$的尺寸是1x4. $$\rm \\stackrel{\\text { def }}{=}\\left(\\begin{array}{c}\\mathrm{m}_1^T \\\\\\mathrm{~m}_2^T \\\\\\mathrm{~m}_3^T\\end{array}\\right)_{12 \\times 1}\r$$ 这里有12行是因为: $m_i^T$的尺寸是4x1. 求 $Pm=0$ 的最小二乘解, 最终要获得的11个未知参数都在矩阵 $m$ 里面\n$$\r\\begin{aligned}\u0026 \\min _{\\boldsymbol{m}}\\|\\boldsymbol{P} \\boldsymbol{m}\\| \\\\\u0026 \\text { s.t. }\\|\\boldsymbol{m}\\|=1\\end{aligned}\r$$ $s.t.$表示限制条件\n求解方法:\n矩阵 $P$ 进行奇异值分解 $P=U D V^T$ $x^*$ 为 $V$ 矩阵的最后一列 (最小奇异值对应的右奇异向量) 于是 $P \\rightarrow U_{2 n \\times 12} D_{12 \\times 12} V_{12 \\times 12}^T$\n结论: $m$ 为 $P$ 矩阵最小奇异值的右奇异向量, 且 $\\|m\\|=1$\n$$\r\\boldsymbol{m} \\stackrel{\\text { def }}{=}\\left(\\begin{array}{l}m_1^T \\\\m_2^T \\\\m_3^T\\end{array}\\right) \\Longrightarrow M=\\left[\\begin{array}{l}m_1 \\\\m_2 \\\\m_3\\end{array}\\right]=\\left[\\begin{array}{ll}A \u0026 b\\end{array}\\right]\r$$ 由于 $m$ 的尺寸: 12x1, 变换成矩阵 $M$ (3x4), 就获得了相机的内外参矩阵$M$. 另外, 还需要求一个矩阵系数$\\rho$\n先看矩阵投影公式\n$$\r\\boldsymbol{p}^{\\prime}=M P=K[R T] P $$ 内参矩阵\n$$\r\\begin{aligned}\r\u0026 K=\\left[\\begin{array}{ccc}\r\\alpha \u0026 -\\alpha \\cot \\theta \u0026 u_0 \\\\\r0 \u0026 \\frac{\\beta}{\\sin \\theta} \u0026 v_0 \\\\\r0 \u0026 0 \u0026 1\r\\end{array}\\right] \\\\\r\u0026\r\\end{aligned}\r$$ 外参矩阵\n$$\rR=\\left[\\begin{array}{l}r_1^T \\\\r_2^T \\\\r_3^T\\end{array}\\right] T=\\left[\\begin{array}{l}t_x \\\\t_y \\\\t_z\\end{array}\\right]\r$$ 其中, $r_i^T$ 是单位向量, 表示旋转角度, 其中两两点乘为0, 两两叉乘得到第三个向量. 因为这3个向量互相垂直. 合并获得$\\rho M$的公式\n$$\r\\rho \\mathrm{M}=\\left(\\begin{array}{cc}\\alpha r_1^T-\\alpha \\cot \\theta r_2^T+u_0 r_3^T \u0026 \\alpha t_x-\\alpha \\cot \\theta t_y+u_0 t_z \\\\\\frac{\\beta}{\\sin \\theta} r_2^T+v_0 r_3^T \u0026 \\frac{\\beta}{\\sin \\theta} t_y+v_0 t_z \\\\r_3^T \u0026 t_z\\end{array}\\right)\r$$ $\\rho$ 为一个比例系数, 表示 $M$ 与真实相机之间的关系.\n2.1.3. 获得相机内参 $\\rho,u_0,v_0$ 可以将$M$先分解\n$$\r\\rho[A\\quad b]=K[R\\quad T]\r$$ $A$ 是 $M$ 的前3个元素(旋转矩阵), $b$ 是 $M$ 的最后一列(平移矩阵) $$\rA=\\left[\\begin{array}{l}a_1{ }^T \\\\a_2{ }^T \\\\a_3{ }^T\\end{array}\\right] \\quad \\mathbf{b}=\\left[\\begin{array}{l}b_1 \\\\b_2 \\\\b_3\\end{array}\\right]\r$$ 去掉 $b$\n$$\r\\rho A=\\rho\\left(\\begin{array}{c}a_1^T \\\\a_2^T \\\\a_3^T\\end{array}\\right)=\\left(\\begin{array}{c}\\alpha r_1^T-\\alpha \\cot \\theta r_2^T+u_0 r_3^T \\\\\\frac{\\beta}{\\sin \\theta} r_2^T+v_0 r_3^T \\\\r_3^T\\end{array}\\right)=K R \\quad\\quad \\text{(213a)}\r$$ 看第3行, $\\rho a_3^T=r_3^T$, 两边都取模. 由于旋转向量模为1. 由于$\\rho$ 是系数, 脱离模之后无法知道正负, 所以\n$$\r\\rho=\\frac{ \\pm 1}{\\left|a_3\\right|} \\quad\\quad \\text{(213b)}\r$$ 由于旋转向量的原理, 各旋转向量互相垂直, 所以 $r_1\\cdot r_3=0$; $r_2\\cdot r_3=0$; $r_3\\cdot r_3=1$. 由公式 $213a$ 的第1行点乘第3行可得\n$$\r\\rho a_1^T \\cdot \\rho a_3^T=(\\alpha r_1^T-\\alpha \\cot \\theta r_2^T+u_0 r_3^T) \\cdot r_3^T=u_0\r$$$$\ru_0=\\rho^2 (a_1\\cdot a_3) \\quad\\quad \\text{(213c)}\r$$ 同理\n$$\rv_0=\\rho^2(a_2\\cdot a_3) \\quad\\quad \\text{(213d)}\r$$ 由于这里的 $a_1,a_2,a_3$ 都是已知的(因为 $M$ 已知), 所以由公式 $213b, 213c, 213d$ 可以获得相机的内参 $\\rho,u_0,v_0$.\n2.1.4. 获得相机内参 $\\theta$ 对于公式 $213a$ 使用叉乘 各旋转向量互相垂直, 所以 $r_1\\times r_3=r_2$; $r_2\\times r_3=r_1$; $r_3\\times r_3=0$ $$\r\\left\\{\\begin{array}{c}\\rho^2\\left(a_1 \\times a_3\\right)\u0026=\u0026\\alpha r_2-\\alpha \\cot \\theta r_1 \\\\ \\rho^2\\left(a_2 \\times a_3\\right)\u0026=\u0026\\frac{\\beta}{\\sin \\theta} r_1\\end{array}\\right. \\quad\\quad \\text{(214e)}\r$$ 两边取模, 旋转向量都模都为1\n$$\r\\left\\{\\begin{array}{l}\\rho^2\\left|a_1 \\times a_3\\right|=\\frac{|\\alpha|}{\\sin \\theta} \\\\\\rho^2\\left|a_2 \\times a_3\\right|=\\frac{|\\beta|}{\\sin \\theta}\\end{array}\\right. \\quad\\quad \\text{(214f)}\r$$ $\\alpha r_{2}-\\alpha \\cot \\theta r_{1}$ 的模怎么求?\n由向量模的公式 $$\r|\\vec{a} |=\\sqrt{\\vec{a}^T\\cdot \\vec{a}} $$ 可以获得 $\\alpha r_{2}-\\alpha \\cot \\theta r_{1}$ 的模\n$$\r\\begin{array}{l}\\left(\\alpha r_{2}-\\alpha \\cot \\theta r_{1}\\right)^{T} \\cdot\\left(\\alpha r_{2}-\\alpha \\cot \\theta r_{1}\\right)=\\alpha^{2}+(\\alpha \\cot \\theta)^{2} \\\\=\\alpha^{2}\\left(1+\\left(\\frac{\\cos \\theta}{\\sin \\theta}\\right)^{2}\\right)=\\left(\\frac{\\alpha}{\\sin \\theta}\\right)^{2}\\end{array}\r$$ 公式 $214e$ 相互点乘可得\n$$\r\\begin{aligned}\r\\rho^2\\left(a_1 \\times a_3\\right) \\cdot \\rho^2\\left(a_2 \\times a_3\\right)=\u0026\\alpha r_2 \\cdot \\frac{\\beta}{\\sin \\theta} r_1-\\alpha \\cot \\theta r_1 \\cdot \\frac{\\beta}{\\sin \\theta} r_1 \\\\\r=\u00260-\\frac{\\alpha \\beta \\cdot \\cos \\theta}{\\sin ^2 \\theta}\\end{aligned} \\quad\\quad \\text{(214g)}\r$$ 公式 $214f$ 相互点乘可得\n$$\r\\rho^2\\left|a_1 \\times a_3\\right| \\cdot \\rho^2\\left|a_2 \\times a_3\\right|=\\frac{\\alpha \\beta}{\\sin ^2 \\theta} \\quad\\quad \\text{(214h)}\r$$ 公式 $214g,214h$相除可得\n$$\r\\cos \\theta=-\\frac{\\left(a_1 \\times a_3\\right) \\cdot\\left(a_2 \\times a_3\\right)}{\\left|a_1 \\times a_3\\right|\\left|a_2 \\times a_3\\right|} $$ 这里可以反向推导出一个结论:\nM是零倾斜透视投影矩阵的充分必要条件\n$$\r(a_1\\times a_3)\\cdot(a_2\\times a_3)=0\r$$也就是 $\\theta=90^{\\circ}$ , 表示像素是垂直的, 零倾斜\n2.1.5. 获得相机内参 $\\alpha,\\beta$ 由公式 $214f$ 可得\n$$\r\\begin{aligned}\\alpha \u0026 =\\rho^{2}\\left|a_{1} \\times a_{3}\\right| \\sin \\theta \\\\\\beta \u0026 =\\rho^{2}\\left|a_{2} \\times a_{3}\\right| \\sin \\theta\\end{aligned}\r$$ 如果 $\\alpha=\\beta$, 那么\n$$\r|a_1\\times a_3|=|a_2\\times a_3|\r$$ 由向量性质: 向量模的平方等于向量的平方.\n$$\rb^2=b\\cdot b=|b|\\cdot |b|\\cos0^{\\circ}=|b|²\r$$可得:\n$$\r(a_1\\times a_3)\\cdot(a_1\\times a_3)=(a_2\\times a_3)\\cdot(a_2\\times a_3)\r$$ 2.1.6. 获得相机外参 $r_1,r_2,r_3(R)$ $r_1$ 可以由公式 $214e, 214f$ 的第2行相除获得\n$$\rr_1=\\frac{(a_2\\times a_3)}{|a_2 \\times a_3|}\r$$ $r_3$ 可以由公式 $214a$ 的第3行和 $214b$ 获得\n$$\rr_3=\\rho a_3=\\pm \\frac{a_3}{|a_3|}\r$$ $r_2$\n$$\rr_2=r_1\\times r_3\r$$ 2.1.7. 获得相机外参 $T$ 还是先分解 $M$矩阵\n$$\r\\rho[A\\quad b]=K[R\\quad T]\r$$ 这次去掉旋转矩阵\n$$\r\\rho b=KT\r$$ 两边同乘$K^{-1}$\n$$\rT=\\rho K^{-1}b\r$$ 由于 $b$ 可以直接从 $M$ 中获得; $K$ 是内参矩阵已知; $\\rho$ 也已知. 平移矩阵就算出来了.\n2.1.8. 总结 2.2. 径向畸变相机标定 径向畸变: 图像像素点以畸变中心为中心点, 沿着径向产生的位置偏差, 从而导致图像中所成的像发生形变.\n2.2.1. 畸变相机模型 $$\r\\overbrace{\\red{\\left[\\begin{array}{ccc}\\frac{1}{\\lambda} \u0026 0 \u0026 0 \\\\\\bar{\\lambda} \u0026 \\frac{1}{\\lambda} \u0026 0 \\\\0 \u0026 0 \u0026 1\\end{array}\\right]}}^{S_\\lambda(失真系数)} M P_i \\rightarrow\\left[\\begin{array}{l}u_i \\\\v_i\\end{array}\\right]=p_i \\quad\\quad \\text{(22a)}\r$$ $\\lambda$ 是畸变模型 $$\r\\lambda=\\underbrace{1 \\pm \\sum_{p=1}^3 \\red{k_p} d^{2 p}}_{\\text {多项式函数 }}\r$$ $k_p$是畸变因子\n正号表示桶形畸变; 负号表示枕型畸变.\n图像放大率随光轴距离的增加而减小\n建模径向特性\n$$\rd^2=u^2+v^2\r$$ 2.2.2. 求解失真系数 $$\r\\red{\\overbrace{\\left[\\begin{array}{ccc}\\frac{1}{\\lambda} \u0026 0 \u0026 0 \\\\\\bar{\\lambda} \u0026 \\frac{1}{\\lambda} \u0026 0 \\\\0 \u0026 0 \u0026 1\\end{array}\\right]}^{Q} M} P_i \\rightarrow\\left[\\begin{array}{l}u_i \\\\v_i\\end{array}\\right]=p_i\r$$$$\rQ=\\left[\\begin{array}{l}q_1 \\\\q_2 \\\\q_3\\end{array}\\right]\r$$$$\rp_i=\\left[\\begin{array}{l}u_i \\\\v_i\\end{array}\\right]=\\left[\\begin{array}{l}\\frac{q_1 p_i}{q_3 p_i} \\\\\\frac{q_2 p_i}{q_3 p_i}\\end{array}\\right] \\quad\\quad \\text{(222a)}\r$$ 获得方程组, 但这不是线性方程组. 因为 $q$ 包含了 $\\lambda$, $\\lambda$ 随着坐标变化在变化.\n$$\r\\left\\{\\begin{array}{l}u_i q_3 P_i=q_1 P_i \\\\v_i q_3 P_i=q_2 P_i\\end{array}\\right.\r$$$$\r\\left\\{\\begin{array}{l}u_i q_3 P_i-q_1 P_i=0 \\\\v_i q_3 P_i-q_2 P_i=0\\end{array}\\right.\r$$$$\r\\left\\{\\begin{array}{l}f_1(k_1, k_2, k_3, \\boldsymbol{m}_1, \\boldsymbol{m}_{\\mathbf{2}}, \\boldsymbol{m}_{\\mathbf{3}})=0 \\\\f_2(\\underbrace{k_1, k_2, k_3}_{畸变因子} , \\underbrace{\\boldsymbol{m}_1, \\boldsymbol{m}_{\\mathbf{2}}, \\boldsymbol{m}_3}_{投影矩阵})=0\\end{array}\\right.\r$$ 增加采样点\n$$\r\\left\\{\\begin{array}{c}f_1\\left(k_1, k_2, k_3, \\boldsymbol{m}_1, \\boldsymbol{m}_2, \\boldsymbol{m}_{\\mathbf{3}}\\right)=0 \\\\f_2\\left(k_1, k_2, k_3, \\boldsymbol{m}_1, \\boldsymbol{m}_{\\mathbf{2}}, \\boldsymbol{m}_{\\mathbf{3}}\\right)=0 \\\\\\vdots \\\\f_{2 n}\\left(k_1, k_2, k_3, \\boldsymbol{m}_1, \\boldsymbol{m}_2, \\boldsymbol{m}_{\\mathbf{3}}\\right)=0\\end{array}\\right.\r$$ 最小二乘解\n$$\r\\begin{aligned}\u0026 \\text { 令 } \\boldsymbol{x}^{\\boldsymbol{T}}=\\left(k_1, k_2, k_3, \\boldsymbol{m}_1, \\boldsymbol{m}_2, \\boldsymbol{m}_{\\mathbf{3}}\\right) \\\\\u0026 \\boldsymbol{x}^*=\\arg \\min _{\\boldsymbol{x}}\\|\\boldsymbol{f}(\\boldsymbol{x})\\|^2\\end{aligned}\r$$ 牛顿法与列文伯格-马夸尔特法 (L-M方法)\n从初始解开始迭代，若初始解与实际相距较远，可能会很慢 估计解可能是初始解的函数 (由于局部最小值) 牛顿法需要计算一阶导矩阵J (雅可比矩阵) ,二阶导矩阵 H (海塞矩阵) L-M算法不用计算H 2.2.3. 求解线性部分 由公式 $222a$ 可得\n$$\rp_i=\\left[\\begin{array}{l}u_i \\\\v_i\\end{array}\\right]=\\frac{1}{\\lambda}\\left[\\begin{array}{l}\\frac{m_1p_i}{m_3p_i} \\\\ \\frac{m_2p_i}{m_3p_i}\\end{array}\\right]=\\left[\\begin{array}{l}\\frac{1}{\\lambda}\\frac{m_1p_i}{m_3p_i} \\\\ \\frac{1}{\\lambda}\\frac{m_2p_i}{m_3p_i}\\end{array}\\right]\r$$$$\r\\frac{u_{i}}{v_{i}}=\\frac{\\frac{1}{\\lambda} \\frac{\\left(m_{1} P_{i}\\right)}{\\left(m_{3} p_{i}\\right)}}{\\frac{1}{\\lambda} \\frac{\\left(m_{2} p_{i}\\right)}{\\left(m_{3} p_{i}\\right)}}=\\frac{m_{1} p_{i}}{m_{2} p_{i}}\r$$$$\r\\left\\{\\begin{array}{c}v_{1}\\left(m_{1} P_{1}\\right)-u_{1}\\left(m_{2} P_{1}\\right)=0 \\\\v_{i}\\left(m_{1} P_{i}\\right)-u_{i}\\left(m_{2} P_{i}\\right)=0 \\\\\\vdots \\\\v_{n}\\left(m_{1} P_{n}\\right)-u_{n}\\left(m_{2} P_{n}\\right)=0\\end{array}\\right.\r$$ 简化可得\n$$\rLn=0\r$$$$\rL \\stackrel{\\text { def }}{=}\\left(\\begin{array}{cc}v_1 P_1^T \u0026 -u_1 P_1^T \\\\v_2 P_2^T \u0026 -u_2 P_2^T \\\\\\vdots \u0026 \\vdots \\\\v_n P_n^T \u0026 -u_n P_n^T\\end{array}\\right)\r$$ 就可以使用多个点通过奇异值分解(SVD)求得$m_1,m_2$\n$$\rn=\\left[\\begin{array}{l}m_1^T\\\\m_2^T\\end{array}\\right]\r$$ 之后再计算公式 $222a$ 就少了两个未知参数, 使用牛顿法与列文伯格-马夸尔特法收敛会更快.\n","permalink":"https://sqf.icu/article/b5e48d43-432e-41ef-8b76-ce810588372f/","summary":"\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e参考三维重建公开课前两节课\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://www.bilibili.com/video/BV1DP41157dB/?spm_id_from=333.337.search-card.all.click\u0026amp;vd_source=0847973121d4fdd8364284ef7353ef09\"\u003e2022B站最好最全的【三维重建】课程！！！北邮教授竟然把三维重建讲的如此通俗易懂，学不会UPZHIJIE 退网下架！！！-人工智能/计算机视觉/三维重建_哔哩哔哩_bilibili\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"1-摄像机几何\"\u003e1. 摄像机几何\u003c/h1\u003e\n\u003ch2 id=\"11-针孔模型透镜\"\u003e1.1. 针孔模型\u0026amp;透镜\u003c/h2\u003e\n\u003ch3 id=\"111-针孔相机\"\u003e1.1.1. 针孔相机\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e早期相机: 小孔成像(添加屏障→减少模糊)\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/b2f46b7e4ef4618e7047654d.png\"\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e需要研究的是虚拟像平面\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e虚拟像平面到针孔的距离等于焦距\u003c/li\u003e\n\u003cli\u003e虚拟像平面的成像大小等于像平面的成像大小, 方向与原物体相同, 研究方便\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e缩小光圈可以使成像更清晰, 但是通过的光更少(成像更暗)\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/e77834d2569be6c881eac78a.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e为了使成像更亮, 可以增加一个透镜\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/85ae57041fb11f718e4b81ee.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e小孔成像系统建立数学模型\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/9a0c9f3c190f7ab5b9e50dfc.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e摄像机坐标系下, 三维点到平面的关系\u003c/p\u003e\n$$\r\n    P=\\left[\\begin{array}{l}x \\\\y \\\\z\\end{array}\\right] \\rightarrow P^{\\prime}=\\left[\\begin{array}{l}x^{\\prime} \\\\y^{\\prime}\\end{array}\\right] \\quad\\left\\{\\begin{array}{l}x^{\\prime}=f \\frac{x}{z} \\\\y^{\\prime}=f \\frac{y}{z}\\end{array}\\right.\r\n    $$\u003c/li\u003e\n\u003c/ul\u003e","title":"三维计算机视觉相机标定笔记"},{"content":"Deep Learning With PyTorch - Full Course\n1. Installation PyTorch\n2. Tensor Basics import torch torch.zeros() torch.ones() torch.rand() # 正数随机(0, 1) torch.randn() # 带负数的随机(-1, 1) torch.tensor([[1, 1], [2, 3]]) torch.add(a, b) torch.mul(a, b) # 哈德马积 torch.mm(a, b) # 矩阵相乘 a.t() # 转置 a.add_(1) # 矩阵内数值全部+1 # 也可以直接 a+=1, 在numpy中也可以用 a = torch.rand(2, 4) a.view(-1, 2) #使矩阵从(2, 4)-\u0026gt;(4, 2), -1是缺省值自动计算 torch.xxxx(xxxxx ,dtype=float (int32)) # 可以定义数据类型 import numpy as np a = np.ones() b = torch.from_numpy(a) # np.ndarray -\u0026gt; tensor c = b.numpy() # tensor -\u0026gt; np.ndarray # 书中的一些其他基础函数 a = torch.arange(12) # 新定义1-12个元素张量 # tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) x.shape # 显示张量的形状 # torch.Size([12]) x.numel() # 只显示张量的元素数量 # 12 tensor格式是专门为cuda准备的 tensor和np.ndarray 相互转换时, 变量的内存共享, eg: 使用add_, 都会变. if torch.cuda.is_available(): device = torch.device(\u0026#34;cuda\u0026#34;) x = torch.ones(5, device=device) # 写入显存 y = torch.ones(5) y = y.to(device) # 写入显存2 z = x + y print(z) # z = z.to(\u0026#34;cpu\u0026#34;) # 只有参数放回内存之后才可以改为numpy格式 z.numpy() # 报错, 显存中的tensor参数不能变成numpy格式 numpy格式无法放入显存\n选定显卡\nimport os os.environ[\u0026#34;CUDA_VISIBLE_DEVICES\u0026#34;] = \u0026#34;0\u0026#34; # or # when loading model model.load_state_dict(torch.load(PATH, map_location=\u0026#34;cuda:0\u0026#34;)) model.to(device) # or when initing the model model_load = NeuralNetMultiClass(input_size, hidden_size, num_classes).to(device) 3. Autograd Pytorch autograd,backward详解\n注意, loss必须是标量, 才能进行反向传播. 所以如果loss是向量, 需要用sum或mean将loss转换为标量. x = torch.randn(3, requires_grad=True) # requires_grad 使矩阵支持求导 print(x) y = x + 2 # grad_fn=\u0026lt;AddBackward0\u0026gt; print(y) z = y * y * 2 # grad_fn=\u0026lt;MulBackward0\u0026gt; z = z.mean() # grad_fn=\u0026lt;MeanBackward0\u0026gt; print(z) # v = torch.tensor([0.1, 0.1, 0.1], dtype=torch.float32) # z.backward(v) # z.backward() # dz/dx, 只会对标量输出来计算梯度, 向量的话用mean, sum函数转换为标量. # 或者直接 v = torch.tensor([1, 0]) 只计算向量中第一项. # 或者v = torch.tensor([0.1, 0.1, 0.1], dtype=torch.float32), torch.ones_like(z) # 使v和输出一致. print(x.grad) #小技巧 1. x.requires_grad_(False) # 可以把requires_grad项改为False, x变 2. y = x.detach() # requires_grad -\u0026gt; False, x不变 3. with torch.no_grad(): y = x + 1 # requires_grad -\u0026gt; False, x不变, 但是y不能直接等于x 直接y = x + 1 # y就带上了gradien function, grad_fn=\u0026lt;AddBackward0\u0026gt; 每个epoch训练之后都要使w的grad清零: weights = torch.ones(4, requires_grad=True) for epoch in range(3): model_output = (weights*3).sum() model_output.backward() print(weights.grad) **weights.grad.zero_()** 4. Backpropagation 5. Gradient Descent With Autograd and Backpropagation Training Pipeline: Model, Loss, and Optimizer\n# -*- coding:utf-8 -*- import numpy as np import torch from torch import nn # f = w*x # f = 2*x x = torch.tensor([[1], [2], [3], [4]], dtype=torch.float32) y = torch.tensor([[2], [4], [6], [8]], dtype=torch.float32) x_test = torch.tensor([5], dtype=torch.float32) # w = torch.tensor(0, dtype=torch.float32, requires_grad=True) n_samples, n_features = x.shape print(n_samples, n_features) input_size = n_features output_size = n_features # model = nn.Linear(input_size, output_size) class LinearRegression(nn.Module): def __init__(self, input_dim, output_dim): super(LinearRegression, self).__init__() self.lin = nn.Linear(input_dim, output_dim) def forward(self, x): return self.lin(x) model = LinearRegression(input_size, output_size) # def forward(x): # return w * x print(f\u0026#34;prediction before training: f(5) = {model(x_test).item():.3f}\u0026#34;) # training learning_rate = 0.01 n_iters = 100 loss = nn.MSELoss() optimizer = torch.optim.SGD((model.parameters()), lr=learning_rate) if torch.cuda.is_available(): device = torch.device(\u0026#39;cpu\u0026#39;) x.to(device) y.to(device) # w.to(device) for epoch in range(n_iters): y_pred = model(x) l = loss(y, y_pred) # 反向传播 l.backward() # with torch.no_grad(): # w -= learning_rate * w.grad # 大部分的优化器都内置了step函数, 用于在反向传播之后更新内部的参数 optimizer.step() # 重置梯度 optimizer.zero_grad() if epoch % 10 == 0: [w, b] = model.parameters() print(f\u0026#39;epoch {epoch + 1}: w = {w[0][0]: .3f}, b = {b[0]: .3f} loss = {l:.8f}\u0026#39;) print(f\u0026#34;prediction after training: f(5) = {model(x_test).item():.3f}\u0026#34;) 4 1 prediction before training: f(5) = 1.611 epoch 1: w = 0.468, b = 0.562 loss = 19.56327057 epoch 11: w = 1.486, b = 0.876 loss = 0.65111023 epoch 21: w = 1.658, b = 0.903 loss = 0.15336990 epoch 31: w = 1.693, b = 0.885 loss = 0.13254575 epoch 41: w = 1.706, b = 0.861 loss = 0.12452319 epoch 51: w = 1.716, b = 0.835 loss = 0.11726725 epoch 61: w = 1.724, b = 0.811 loss = 0.11044146 epoch 71: w = 1.732, b = 0.787 loss = 0.10401321 epoch 81: w = 1.740, b = 0.764 loss = 0.09795904 epoch 91: w = 1.748, b = 0.741 loss = 0.09225740 prediction after training: f(5) = 9.495 类里的super是干嘛的? 可以调用基类里的方法, 如果调用C类的话, 会再super处自动调用A类\nclass A(): def __init__(self): print(\u0026#39;Call class A\u0026#39;) print(\u0026#39;Leave class A\u0026#39;) class C(A): def __init__(self): print(\u0026#39;Call class C\u0026#39;) super(C, self).__init__() print(\u0026#39;Leave class C\u0026#39;) ################# Call class C Call class A Leave class A Leave class C 6. Linear Regression # -*- coding:utf-8 -*- \u0026#34;\u0026#34;\u0026#34; 1. Design model (input, output size, forward pass) 2. construct loss and optimizer 3. Training loop - forward pass: compute prediction and loss - backward pass: gradients - update weights \u0026#34;\u0026#34;\u0026#34; import matplotlib.pyplot as plt import numpy as np import torch import torch.nn as nn from sklearn import datasets if torch.cuda.is_available(): device = torch.device(\u0026#34;cuda\u0026#34;) else: device = torch.device(\u0026#34;cpu\u0026#34;) X_np, y_np = datasets.make_regression(n_samples=100, n_features=1, noise=20, random_state=1) X = torch.from_numpy(X_np.astype(np.float32)) y = torch.from_numpy(y_np.astype(np.float32)) y = y.view(y.shape[0], 1) X = X.to(device) y = y.to(device) # print(X.shape) # print(y.shape) n_samples, n_features = X.shape # model input_size = n_features output_size = 1 model = nn.Linear(input_size, output_size) model.to(device) # loss and optimizer learning_rate = 0.01 loss = nn.MSELoss() optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) # training loop epochs = 1000 for epoch in range(epochs): # forward pass and loss y_pre = model(X) loss_ = loss(y_pre, y) # backward pass loss_.backward() # update optimizer.step() optimizer.zero_grad() if (epoch + 1) % 10 == 0: print(f\u0026#34;epoch: {epoch + 1}, loss: {loss_:.4f}\u0026#34;) # 这里使用了分离函数detach使predict没有require_grad, # 有require_grad或在显存中都无法转换为numpy的类型 # 如果不使用detach(), 可以使用with torch.no_grad(): predict = model(X).cpu().detach().numpy() plt.plot(X_np, y_np, \u0026#39;ro\u0026#39;) plt.plot(X_np, predict, \u0026#39;b\u0026#39;) plt.savefig(\u0026#39;linear_regression_result.png\u0026#39;) epoch: 10, loss: 4351.0640 epoch: 20, loss: 3248.5317 epoch: 30, loss: 2450.2957 epoch: 40, loss: 1871.7806 epoch: 50, loss: 1452.1096 epoch: 60, loss: 1147.4028 epoch: 70, loss: 925.9892 epoch: 80, loss: 764.9808 epoch: 90, loss: 647.8183 epoch: 100, loss: 562.5082 Process finished with exit code 0 7. Logistic Regression # -*- coding:utf-8 -*- \u0026#34;\u0026#34;\u0026#34; 1. Design model (input, output size, forward pass) 2. construct loss and optimizer 3. Training loop - forward pass: compute prediction and loss - backward pass: gradients - update weights \u0026#34;\u0026#34;\u0026#34; import numpy as np import torch import torch.nn as nn from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler # 0. prepare data bc = datasets.load_breast_cancer() X, y = bc.data, bc.target n_samples, n_features = X.shape X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=1) # 建立一个实施标准化的实例 sc = StandardScaler() # fit_transform用于获得训练集各个特征的均值和方差. X_train = sc.fit_transform(X_train) # 测试集用上面获得的均值和方差对各个特征的数据进行转换, 这样模型推理测试集的时候结果更会准确 X_test = sc.transform(X_test) X_train = torch.from_numpy(X_train.astype(np.float32)) X_test = torch.from_numpy(X_test.astype(np.float32)) y_train = torch.from_numpy(y_train.astype(np.float32)) y_test = torch.from_numpy(y_test.astype(np.float32)) # 矩阵转置 view(矩阵第一维(行数), 矩阵第二维(列数)) y_train = y_train.view(y_train.shape[0], 1) y_test = y_test.view(y_test.shape[0], 1) class LogisticRegression(nn.Module): def __init__(self, input): super(LogisticRegression, self).__init__() self.linear = nn.Linear(input, 1) def forward(self, x): y_p = torch.sigmoid(self.linear(x)) return y_p model = LogisticRegression(n_features) # loss and optimizer lr = 0.01 loss = nn.BCELoss() opt = torch.optim.SGD(model.parameters(), lr=lr) # training epochs = 6000 for epoch in range(epochs): y_p = model(X_train) loss_ = loss(y_p, y_train) loss_.backward() opt.step() opt.zero_grad() if epoch % 10 == 0: print(f\u0026#34;epoch {epoch}, loss {loss_.item():.4f}\u0026#34;) with torch.no_grad(): y_p = model(X_test) y_p_cls = y_p.round() # tensor round函数可以将浮点数四舍五入到最近的整数 acc = y_p_cls.eq(y_test).sum() / float(y_test.shape[0]) print(f\u0026#34;acc {acc:.4f}\u0026#34;) epoch 5920, loss 0.0665 epoch 5930, loss 0.0665 epoch 5940, loss 0.0664 epoch 5950, loss 0.0664 epoch 5960, loss 0.0664 epoch 5970, loss 0.0664 epoch 5980, loss 0.0663 epoch 5990, loss 0.0663 acc 0.9737 8. Dataset 8.1. DataLoader 使用torch.utils.data.DataLoader()调用数据 DataLoader方法结合了数据集和取样器, 可以自动对数据进行shuffle, mini_batch, 多线程, 自定义预处理方法等功能, 非常方便. # -*- coding:utf-8 -*- import math import numpy as np import torch from torch.utils.data import DataLoader class WineDataset(): def __init__(self): xy = np.loadtxt(\u0026#39;./pytorchTutorial/data/wine/wine.csv\u0026#39;, delimiter=\u0026#39;,\u0026#39;, dtype=np.float32, skiprows=1) self.x = torch.from_numpy(xy[:, 1:]) self.y = torch.from_numpy(xy[:, [0]]) self.n_samples = xy.shape[0] def __getitem__(self, item): # 特殊函数__getitem__可以使这个类实例像调用列表一样, # 调用类的属性变量 return self.x[item], self.y[item] def __len__(self): return self.n_samples dataset = WineDataset() # first_data = dataset[0] # features, labels = first_data # print(features) # print(labels) dataloader = DataLoader(dataset=dataset, batch_size=4, shuffle=True, num_workers=2) # dataiter = iter(dataloader) # data = dataiter.next() # features, labels = data # print(features) # print(labels) # training loop num_epochs = 2 total_sample = len(dataset) n_iterations = math.ceil(total_sample / 4) print(total_sample, n_iterations) for epoch in range(num_epochs): for i, (inputs, labels) in enumerate(dataloader): # forward backward, update if (i + 1) % 5 == 0: print(f\u0026#34;epoch: {epoch + 1}/{num_epochs}, step {i + 1}/{n_iterations}, inputs {inputs.shape}\u0026#34;) 178 45 epoch: 1/2, step 5/45, inputs torch.Size([4, 13]) epoch: 1/2, step 10/45, inputs torch.Size([4, 13]) epoch: 1/2, step 15/45, inputs torch.Size([4, 13]) epoch: 1/2, step 20/45, inputs torch.Size([4, 13]) epoch: 1/2, step 25/45, inputs torch.Size([4, 13]) epoch: 1/2, step 30/45, inputs torch.Size([4, 13]) epoch: 1/2, step 35/45, inputs torch.Size([4, 13]) epoch: 1/2, step 40/45, inputs torch.Size([4, 13]) epoch: 1/2, step 45/45, inputs torch.Size([2, 13]) epoch: 2/2, step 5/45, inputs torch.Size([4, 13]) epoch: 2/2, step 10/45, inputs torch.Size([4, 13]) epoch: 2/2, step 15/45, inputs torch.Size([4, 13]) epoch: 2/2, step 20/45, inputs torch.Size([4, 13]) epoch: 2/2, step 25/45, inputs torch.Size([4, 13]) epoch: 2/2, step 30/45, inputs torch.Size([4, 13]) epoch: 2/2, step 35/45, inputs torch.Size([4, 13]) epoch: 2/2, step 40/45, inputs torch.Size([4, 13]) epoch: 2/2, step 45/45, inputs torch.Size([2, 13]) Process finished with exit code 0 8.2. Dataset Transforms 对数据进行预处理的时候该怎么做? # -*- coding:utf-8 -*- import math import numpy as np import torch, torchvision from torch.utils.data import DataLoader, Dataset class WineDataset(Dataset): def __init__(self, transform=None): xy = np.loadtxt(\u0026#39;./pytorchTutorial/data/wine/wine.csv\u0026#39;, delimiter=\u0026#39;,\u0026#39;, dtype=np.float32, skiprows=1) self.x = xy[:, 1:] self.y = xy[:, [0]] self.n_samples = xy.shape[0] self.transform = transform def __getitem__(self, item): sample = self.x[item], self.y[item] if self.transform: sample = self.transform(sample) return sample def __len__(self): return self.n_samples class ToTensor: def __call__(self, sample): inputs, labels = sample return torch.from_numpy(inputs), torch.from_numpy(labels) class MulTransform: def __init__(self, factor): self.factor = factor def __call__(self, sample): inputs, labels = sample inputs += self.factor return inputs, labels # dataset = WineDataset(transform=ToTensor()) dataset = WineDataset(transform=None) first_data = dataset[0] features, labels = first_data print(features) print(labels) # torchvision.transforms.Compose集合所有指定的预处理类 composed = torchvision.transforms.Compose([ToTensor(), MulTransform(4)]) dataset = WineDataset(transform=composed) first_data = dataset[0] features, labels = first_data print(features) print(labels) # dataloader = DataLoader(dataset=dataset, batch_size=4, shuffle=True, num_workers=2) # # # dataiter = iter(dataloader) # # data = dataiter.next() # # features, labels = data # # print(features) # # print(labels) # # # training loop # num_epochs = 2 # total_sample = len(dataset) # n_iterations = math.ceil(total_sample / 4) # print(total_sample, n_iterations) # # for epoch in range(num_epochs): # for i, (inputs, labels) in enumerate(dataloader): # # forward backward, update # if (i + 1) % 5 == 0: # print(f\u0026#34;epoch: {epoch + 1}/{num_epochs}, step {i + 1}/{n_iterations}, inputs {inputs.shape}\u0026#34;) 特殊函数 call__和__init 类似, 不同之处:\n在创建实例的时候__init__会被调用, __call__不会. 对实例进行输入的时候, __call__才会被调用. class A(): def __init__(self): print(\u0026#39;init函数\u0026#39;) def __call__(self, param): print(\u0026#39;call 函数\u0026#39;, param) a = A() # print: init函数 a(1) # print: call 函数 9. 激活函数 9.1. Sigmoid 二分类问题可以用sigmoid函数(又称Logistic函数). 可以将$(-\\infty , +\\infty)$范围的数值映射到$(0,1)$之间. 所以可以表示为概率. 公示如下:\n$$\rg(z)=\\frac{1}{1+e^{-z}} $$9.2. Softmax 多分类问题可以使用Softmax, 公示如下:\n$$\rS(y_i)=\\frac{e^{y_i}}{\\sum e^{y_j}}\r$$import torch import torch.nn as nn import numpy as np def softmax(x): return np.exp(x) / np.sum(np.exp(x), axis=0) x = np.array([2.0, 1.0, 0.1]) outputs = softmax(x) print(\u0026#39;softmax numpy:\u0026#39;, outputs) x = torch.tensor([2.0, 1.0, 0.1]) outputs = torch.softmax(x, dim=0) print(\u0026#39;softmax numpy:\u0026#39;, outputs) softmax numpy: [0.65900114 0.24243297 0.09856589] softmax numpy: tensor([0.6590, 0.2424, 0.0986]) Process finished with exit code 0 9.4. Activation Functions 深度学习训练用激活损失函数和技巧\n常见的激活函数\nstep function sigmoid tanh ReLU Leaky ReLU softmax 10. Loss 损失函数 10.1. Cross Entropy 通常分类问题使用Softmax或Sigmoid函数获得每一个分类的可能的概率.\n$$\rD(\\hat{Y}, Y)=-\\frac{1}{N} \\cdot \\sum Y_{i} \\cdot \\log \\left(\\hat{Y}_{i}\\right)\r$$\n公式推导过程\n你真的理解交叉熵损失函数了吗？_哔哩哔哩_bilibili\n$$\r\\begin{aligned}\\operatorname{argmax} \\log \\prod_{\\mathrm{n}} \\prod_{\\mathrm{i}} \\hat{Y}_{i}^{Y_{i}}\u0026=\\operatorname{argmax} \\sum_{n} \\sum_{i} Y_{i} \\log \\hat{Y}_{i}\\\\\u0026=\\operatorname{argmin}-\\sum_{n} \\sum_{i} Y_{i} \\log \\hat{Y}_{i}\\end{aligned}\r$$ $n$表示训练样本数; $i$表示分类数量. 因为只要找到最值就可以了, 所有这里是额外加一个$log$的. 利用$log$似然函数的特性, 把连乘提到$log$左边变成连加; 加上负号求最小值. # -*- coding:utf-8 -*- import numpy as np import torch import torch.nn as nn def cross_entropy(actual, predicted): loss = -np.sum(actual * np.log(predicted)) return loss Y = np.array([1, 0, 0]) y_pred_good = np.array([0.7, 0.2, 0.1]) y_pred_bad = np.array([0.1, 0.3, 0.6]) l1 = cross_entropy(Y, y_pred_good) l2 = cross_entropy(Y, y_pred_bad) print(f\u0026#39;Loss1 numpy: {l1:.4f}\u0026#39;) print(f\u0026#39;Loss2 numpy: {l2:.4f}\u0026#39;) \u0026#34;\u0026#34;\u0026#34; xxxxxxxxxxxxxxxxxxxxxx \u0026#34;\u0026#34;\u0026#34; loss = nn.CrossEntropyLoss() Y = torch.tensor([2, 0, 1]) Y_pred_good = torch.tensor([[0.1, 1.0, 2.1], [2.0, 1.0, 0.1], [0.1, 3.0, 0.1]]) Y_pred_bad = torch.tensor([[2.1, 1.0, 0.1], [0.1, 1.0, 2.1], [0.1, 3.0, 0.1]]) l1 = loss(Y_pred_good, Y) l2 = loss(Y_pred_bad, Y) print(l1.item()) print(l2.item()) _, predictions1 = torch.max(Y_pred_good, 1) _, predictions2 = torch.max(Y_pred_bad, 1) print(predictions1) print(predictions2) Loss1 numpy: 0.3567 Loss2 numpy: 2.3026 xxxxxxxxxxxxxxxxxxxxxxxxx 0.3018244206905365 1.6241613626480103 tensor([2, 0, 1]) tensor([0, 2, 1]) 如果使用nn.CrossEntropyLoss()就不要再网络最后加Softmax层, 但是如果使用nn.BCELoss(),网络最后要加上Sigmoid层.\n如果网络是多分类问题, 就是用nn.CrossEntropyLoss()\nclass NeuralNetMultiClass(nn.Module): def __init__(self, input_size, hidden_size, num_classes): super(NeuralNetMultiClass, self).__init__() self.linear1 = nn.Linear(input_size, hidden_size) # nn.Linear(in_features, out_features) self.relu = nn.ReLU() self.linear2 = nn.Linear(hidden_size, num_classes) def forward(self, x): out = self.linear1(x) out = self.relu(out) out = self.linear2(out) return out model = NeuralNetMultiClass(input_size=28*28, hidden_size=5, num_classes=3) criterion = nn.CrossEntropyLoss() 如果网络是二分类问题, 就是用nn.BCELoss(), 网络最后需要使用sigmoid函数.\nclass NeuralNetSingleClass(nn.Module): def __init__(self, input_size, hidden_size): super(NeuralNetSingleClass, self).__init__() self.linear1 = nn.Linear(input_size, hidden_size) # nn.Linear(in_features, out_features) self.relu = nn.ReLU() self.linear2 = nn.Linear(hidden_size, 1) def forward(self, x): out = self.linear1(x) out = self.relu(out) out = self.linear2(out) y_pred = torch.sigmoid(out) return y_pred model = NeuralNetSingleClass(input_size=28*28, hidden_size=5) criterion = nn.BCELoss() 11. Feed-Forward Neural Net # -*- coding:utf-8 -*- import matplotlib.pyplot as plt import torch import torch.nn as nn import torchvision import torchvision.transforms as transforms device = torch.device(\u0026#39;cuda\u0026#39; if torch.cuda.is_available() else \u0026#39;cpu\u0026#39;) print(f\u0026#39;Training on the {device}...\u0026#39;) input_size = 784 hidden_size = 100 num_classes = 10 num_epochs = 15 batch_size = 128 lr = 0.001 train_dataset = torchvision.datasets.MNIST(root=\u0026#39;./pytorchTutorial/data/\u0026#39;, train=True, transform=transforms.ToTensor(), download=True) test_dataset = torchvision.datasets.MNIST(root=\u0026#39;./pytorchTutorial/data/\u0026#39;, train=False, transform=transforms.ToTensor()) train_len = int(train_dataset.data.shape[0] * 0.9) val_len = train_dataset.data.shape[0] - train_len torch.manual_seed(0) train_set, val_set = torch.utils.data.random_split(dataset=train_dataset, lengths=[train_len, val_len]) train_loader = torch.utils.data.DataLoader(dataset=train_set, batch_size=batch_size, shuffle=True) val_loader = torch.utils.data.DataLoader(dataset=val_set, batch_size=batch_size, shuffle=True) test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False) examples = iter(train_loader) samples, labels = examples.next() print(samples.shape, labels.shape) # for i in range(6): # plt.subplot(2, 3, i+1) # plt.imshow(samples[i][0], cmap=\u0026#39;gray\u0026#39;) # plt.savefig(\u0026#39;feed_forward.png\u0026#39;) class NeuralNetMultiClass(nn.Module): def __init__(self, input_size, hidden_size, num_classes): super(NeuralNetMultiClass, self).__init__() self.l1 = nn.Linear(input_size, hidden_size) self.relu = nn.ReLU() self.l2 = nn.Linear(hidden_size, num_classes) def forward(self, x): out = self.l1(x) out = self.relu(out) out = self.l2(out) return out def validation_test(loaders, val_or_test, model_cur): \u0026#34;\u0026#34;\u0026#34; :param loaders: :param val_or_test: validation: 0; test: 1 :return: \u0026#34;\u0026#34;\u0026#34; with torch.no_grad(): n_correct = 0 n_samples = 0 for images, labels in loaders: images = images.reshape(-1, 28 * 28).to(device) labels = labels.to(device) outputs = model_cur(images) # value, index _, predictions = torch.max(outputs, 1) n_samples += labels.shape[0] if val_or_test == 0: n_correct += (predictions != labels).sum().item() else: n_correct += (predictions == labels).sum().item() # print(f\u0026#39;predictions: {predictions}; labels: {labels}\u0026#39;) res = 100.0 * n_correct / n_samples # print(f\u0026#39;n_correct: {n_correct}; n_samples: {n_samples}\u0026#39;) return res model = NeuralNetMultiClass(input_size, hidden_size, num_classes).to(device) # loss and optimizer criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=lr) # training loop n_total_steps = len(train_loader) loss_list = [] val_loss_list = [] epoch_list = [] tmp_min_val_loss = 999 for epoch in range(num_epochs): for i, (images, labels) in enumerate(train_loader): # 100, 1, 28, 28 # 100, 784 images = images.reshape(-1, 28 * 28).to(device) labels = labels.to(device) # forward outputs = model(images) loss = criterion(outputs, labels) # backwards optimizer.zero_grad() loss.backward() optimizer.step() if (i + 1) % 100 == 0: val_loss = validation_test(val_loader, 0, model) # print(f\u0026#39;epoch {epoch + 1}/{num_epochs}, step {i + 1}/{n_total_steps}, loss {loss.item():.4f}\u0026#39;) loss_list.append(loss.item()) val_loss_list.append(val_loss) if tmp_min_val_loss \u0026gt; val_loss: tmp_min_val_loss = val_loss torch.save(model.state_dict(), \u0026#39;feed_forward_model_weights.pt\u0026#39;) print( f\u0026#39;epoch {epoch + 1}/{num_epochs}, step {i + 1}/{n_total_steps}, loss {loss.item():.4f}, val_loss {val_loss:.4f}\u0026#39;) for i in range(int(num_epochs * (n_total_steps // 100))): epoch_list.append(i + 1) del model plt.plot(epoch_list, loss_list, \u0026#39;ro\u0026#39;, label=\u0026#39;loss\u0026#39;) plt.plot(epoch_list, val_loss_list, \u0026#39;b-\u0026#39;, label=\u0026#39;val_loss\u0026#39;) plt.legend() plt.savefig(\u0026#39;feed_forward_loss_val.png\u0026#39;) # test model_load = NeuralNetMultiClass(input_size, hidden_size, num_classes).to(device) model_load.load_state_dict(torch.load(\u0026#39;feed_forward_model_weights.pt\u0026#39;)) acc = validation_test(test_loader, 1, model_load) print(f\u0026#39;accuracy: {acc:.4f}\u0026#39;) Training on the cuda... torch.Size([128, 1, 28, 28]) torch.Size([128]) epoch 1/15, step 100/422, loss 0.4841, val_loss 11.4833 epoch 1/15, step 200/422, loss 0.2547, val_loss 9.1667 epoch 1/15, step 300/422, loss 0.4167, val_loss 8.6167 epoch 1/15, step 400/422, loss 0.2693, val_loss 7.5500 epoch 2/15, step 100/422, loss 0.4004, val_loss 6.7167 ... epoch 10/15, step 300/422, loss 0.0457, val_loss 2.5667 epoch 11/15, step 200/422, loss 0.0541, val_loss 2.3667 epoch 14/15, step 100/422, loss 0.0326, val_loss 2.3167 accuracy: 97.7200 Process finished with exit code 0 12. Convolutional Neural Net (CNN) # -*- coding:utf-8 -*- import torch import torch.nn as nn import torch.nn.functional as F import torchvision import torchvision.transforms as transforms import matplotlib.pyplot as plt import numpy as np # Device configuration device = torch.device(\u0026#39;cuda\u0026#39; if torch.cuda.is_available() else \u0026#39;cpu\u0026#39;) # Hyper-parameters num_epochs = 5 batch_size = 4 learning_rate = 0.001 # dataset has PILImage images of range [0, 1]. # We transform them to Tensors of normalized range [-1, 1] transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) # CIFAR10: 60000 32x32 color images in 10 classes, with 6000 images per class train_dataset = torchvision.datasets.CIFAR10(root=\u0026#39;./data\u0026#39;, train=True, download=True, transform=transform) test_dataset = torchvision.datasets.CIFAR10(root=\u0026#39;./data\u0026#39;, train=False, download=True, transform=transform) train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True) test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False) classes = (\u0026#39;plane\u0026#39;, \u0026#39;car\u0026#39;, \u0026#39;bird\u0026#39;, \u0026#39;cat\u0026#39;, \u0026#39;deer\u0026#39;, \u0026#39;dog\u0026#39;, \u0026#39;frog\u0026#39;, \u0026#39;horse\u0026#39;, \u0026#39;ship\u0026#39;, \u0026#39;truck\u0026#39;) # def imshow(img): # img = img / 2 + 0.5 # unnormalize # npimg = img.numpy() # plt.imshow(np.transpose(npimg, (1, 2, 0))) # plt.show() # # # # get some random training images # dataiter = iter(train_loader) # images, labels = dataiter.next() # # # show images # imshow(torchvision.utils.make_grid(images)) class ConvNet(nn.Module): def __init__(self): super(ConvNet, self).__init__() self.conv1 = nn.Conv2d(3, 6, 5) self.pool = nn.MaxPool2d(2, 2) self.conv2 = nn.Conv2d(6, 16, 5) self.fc1 = nn.Linear(16 * 5 * 5, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10) def forward(self, x): # -\u0026gt; n, 3, 32, 32 x = self.pool(F.relu(self.conv1(x))) # -\u0026gt; n, 6, 14, 14 x = self.pool(F.relu(self.conv2(x))) # -\u0026gt; n, 16, 5, 5 x = x.view(-1, 16 * 5 * 5) # -\u0026gt; n, 400 x = F.relu(self.fc1(x)) # -\u0026gt; n, 120 x = F.relu(self.fc2(x)) # -\u0026gt; n, 84 x = self.fc3(x) # -\u0026gt; n, 10 return x model = ConvNet().to(device) criterion = nn.CrossEntropyLoss() optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) n_total_steps = len(train_loader) for epoch in range(num_epochs): for i, (images, labels) in enumerate(train_loader): # origin shape: [4, 3, 32, 32] = 4, 3, 1024 # input_layer: 3 input channels, 6 output channels, 5 kernel size images = images.to(device) labels = labels.to(device) # Forward pass outputs = model(images) loss = criterion(outputs, labels) # Backward and optimize optimizer.zero_grad() loss.backward() optimizer.step() if (i + 1) % 2000 == 0: print(f\u0026#39;Epoch [{epoch + 1}/{num_epochs}], Step [{i + 1}/{n_total_steps}], Loss: {loss.item():.4f}\u0026#39;) print(\u0026#39;Finished Training\u0026#39;) PATH = \u0026#39;./cnn.pth\u0026#39; torch.save(model.state_dict(), PATH) with torch.no_grad(): n_correct = 0 n_samples = 0 n_class_correct = [0 for i in range(10)] n_class_samples = [0 for i in range(10)] for images, labels in test_loader: images = images.to(device) labels = labels.to(device) outputs = model(images) # max returns (value ,index) _, predicted = torch.max(outputs, 1) n_samples += labels.size(0) n_correct += (predicted == labels).sum().item() for i in range(batch_size): label = labels[i] pred = predicted[i] if (label == pred): n_class_correct[label] += 1 n_class_samples[label] += 1 acc = 100.0 * n_correct / n_samples print(f\u0026#39;Accuracy of the network: {acc} %\u0026#39;) for i in range(10): acc = 100.0 * n_class_correct[i] / n_class_samples[i] print(f\u0026#39;Accuracy of {classes[i]}: {acc} %\u0026#39;) 13. Transfer Learning # -*- coding:utf-8 -*- import torch import torch.nn as nn import torch.optim as optim from torch.optim import lr_scheduler import numpy as np import torchvision from torchvision import datasets, models, transforms import matplotlib.pyplot as plt import time import os import copy mean = np.array([0.5, 0.5, 0.5]) std = np.array([0.25, 0.25, 0.25]) data_transforms = { \u0026#39;train\u0026#39;: transforms.Compose([ transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize(mean, std) ]), \u0026#39;val\u0026#39;: transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean, std) ]), } data_dir = \u0026#39;data/hymenoptera_data\u0026#39; image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x]) for x in [\u0026#39;train\u0026#39;, \u0026#39;val\u0026#39;]} dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=4, shuffle=True, num_workers=0) for x in [\u0026#39;train\u0026#39;, \u0026#39;val\u0026#39;]} dataset_sizes = {x: len(image_datasets[x]) for x in [\u0026#39;train\u0026#39;, \u0026#39;val\u0026#39;]} class_names = image_datasets[\u0026#39;train\u0026#39;].classes device = torch.device(\u0026#34;cuda:0\u0026#34; if torch.cuda.is_available() else \u0026#34;cpu\u0026#34;) print(class_names) def imshow(inp, title): \u0026#34;\u0026#34;\u0026#34;Imshow for Tensor.\u0026#34;\u0026#34;\u0026#34; inp = inp.numpy().transpose((1, 2, 0)) inp = std * inp + mean inp = np.clip(inp, 0, 1) plt.imshow(inp) plt.title(title) plt.show() # Get a batch of training data inputs, classes = next(iter(dataloaders[\u0026#39;train\u0026#39;])) # Make a grid from batch out = torchvision.utils.make_grid(inputs) imshow(out, title=[class_names[x] for x in classes]) def train_model(model, criterion, optimizer, scheduler, num_epochs=25): since = time.time() best_model_wts = copy.deepcopy(model.state_dict()) best_acc = 0.0 for epoch in range(num_epochs): print(\u0026#39;Epoch {}/{}\u0026#39;.format(epoch, num_epochs - 1)) print(\u0026#39;-\u0026#39; * 10) # Each epoch has a training and validation phase for phase in [\u0026#39;train\u0026#39;, \u0026#39;val\u0026#39;]: if phase == \u0026#39;train\u0026#39;: model.train() # Set model to training mode else: model.eval() # Set model to evaluate mode running_loss = 0.0 running_corrects = 0 # Iterate over data. for inputs, labels in dataloaders[phase]: inputs = inputs.to(device) labels = labels.to(device) # forward # track history if only in train with torch.set_grad_enabled(phase == \u0026#39;train\u0026#39;): outputs = model(inputs) _, preds = torch.max(outputs, 1) loss = criterion(outputs, labels) # backward + optimize only if in training phase if phase == \u0026#39;train\u0026#39;: optimizer.zero_grad() loss.backward() optimizer.step() # statistics running_loss += loss.item() * inputs.size(0) running_corrects += torch.sum(preds == labels.data) if phase == \u0026#39;train\u0026#39;: scheduler.step() epoch_loss = running_loss / dataset_sizes[phase] epoch_acc = running_corrects.double() / dataset_sizes[phase] print(\u0026#39;{} Loss: {:.4f} Acc: {:.4f}\u0026#39;.format( phase, epoch_loss, epoch_acc)) # deep copy the model if phase == \u0026#39;val\u0026#39; and epoch_acc \u0026gt; best_acc: best_acc = epoch_acc best_model_wts = copy.deepcopy(model.state_dict()) print() time_elapsed = time.time() - since print(\u0026#39;Training complete in {:.0f}m {:.0f}s\u0026#39;.format( time_elapsed // 60, time_elapsed % 60)) print(\u0026#39;Best val Acc: {:4f}\u0026#39;.format(best_acc)) # load best model weights model.load_state_dict(best_model_wts) return model #### Finetuning the convnet #### # Load a pretrained model and reset final fully connected layer. model = models.resnet18(pretrained=True) num_ftrs = model.fc.in_features # Here the size of each output sample is set to 2. # Alternatively, it can be generalized to nn.Linear(num_ftrs, len(class_names)). model.fc = nn.Linear(num_ftrs, 2) model = model.to(device) criterion = nn.CrossEntropyLoss() # Observe that all parameters are being optimized optimizer = optim.SGD(model.parameters(), lr=0.001) # StepLR Decays the learning rate of each parameter group by gamma every step_size epochs # Decay LR by a factor of 0.1 every 7 epochs # Learning rate scheduling should be applied after optimizer’s update # e.g., you should write your code this way: # for epoch in range(100): # train(...) # validate(...) # scheduler.step() step_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=7, gamma=0.1) model = train_model(model, criterion, optimizer, step_lr_scheduler, num_epochs=25) #### ConvNet as fixed feature extractor #### # Here, we need to freeze all the network except the final layer. # We need to set requires_grad == False to freeze the parameters so that the gradients are not computed in backward() model_conv = torchvision.models.resnet18(pretrained=True) for param in model_conv.parameters(): param.requires_grad = False # Parameters of newly constructed modules have requires_grad=True by default num_ftrs = model_conv.fc.in_features model_conv.fc = nn.Linear(num_ftrs, 2) model_conv = model_conv.to(device) criterion = nn.CrossEntropyLoss() # Observe that only parameters of final layer are being optimized as # opposed to before. optimizer_conv = optim.SGD(model_conv.fc.parameters(), lr=0.001, momentum=0.9) # Decay LR by a factor of 0.1 every 7 epochs exp_lr_scheduler = lr_scheduler.StepLR(optimizer_conv, step_size=7, gamma=0.1) model_conv = train_model(model_conv, criterion, optimizer_conv, exp_lr_scheduler, num_epochs=25) 14. Tensorboard 启动tensorboard\nMAC终端连接ssh，将服务器的6006端口（或者其他没有被占用的端口都行，比如6007…）重定向到自己机器上来，在本地终端，输入以下命令：\nssh -L 16006:127.0.0.1:6006 username@remote_server_ip 说明：16006:127.0.0.1代表自己机器上的16006号端口(这个端口号应该也是自己改的，只要是本地没有被占用的就可以)，6006（或者其他服务器上没有被占用）是服务器上tensorboard使用的端口。username指的是服务器的用户名；remote_server_ip指的是服务器的IP。\n在服务器终端输入以下命令： 需要在工程文件夹下执行\ntensorboard --logdir=runs --port=6006 --load_fast=false 在本地浏览器输入以下地址便可访问： 127.0.0.1:16006/\ncode\nshow image\nfrom torch.utils.tensorboard import SummaryWriter writer = SummaryWriter(\u0026#39;runs/mnist\u0026#39;) ... examples = iter(train_loader) samples, labels = examples.next() print(samples.shape, labels.shape) for i in range(6): plt.subplot(2, 3, i+1) plt.imshow(samples[i][0], cmap=\u0026#39;gray\u0026#39;) # plt.savefig(\u0026#39;feed_forward.png\u0026#39;) img_grid = torchvision.utils.make_grid(samples) writer.add_image(\u0026#34;mnist_images\u0026#34;, img_grid) writer.close() sys.exit() ... show model graph\nmodel = NeuralNetMultiClass(input_size, hidden_size, num_classes).to(device) # loss and optimizer criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=lr) **writer.add_graph(model, samples.reshape(-1, 28*28).to(device))** writer.close() show loss\nrunning_loss = 0.0 running_correct = 0 for epoch in range(num_epochs): for i, (images, labels) in enumerate(train_loader): # 100, 1, 28, 28 # 100, 784 images = images.reshape(-1, 28 * 28).to(device) labels = labels.to(device) # forward outputs = model(images) loss = criterion(outputs, labels) # backwards optimizer.zero_grad() loss.backward() optimizer.step() # tensorboard show loss running_loss += loss.item() _, predicted = torch.max(outputs.data, 1) running_correct += (predicted == labels).sum().item() if (i + 1) % 100 == 0: val_loss = validation_test(val_loader, 0, model) # print(f\u0026#39;epoch {epoch + 1}/{num_epochs}, step {i + 1}/{n_total_steps}, loss {loss.item():.4f}\u0026#39;) loss_list.append(loss.item()) val_loss_list.append(val_loss) if tmp_min_val_loss \u0026gt; val_loss: tmp_min_val_loss = val_loss torch.save(model.state_dict(), \u0026#39;feed_forward_model_weights.pt\u0026#39;) print( f\u0026#39;epoch {epoch + 1}/{num_epochs}, step {i + 1}/{n_total_steps}, loss {loss.item():.4f}, val_loss {val_loss:.4f}\u0026#39;) writer.add_scalar(\u0026#39;training loss\u0026#39;, running_loss/100, epoch*n_total_steps+i) writer.add_scalar(\u0026#39;acc\u0026#39;, running_correct / 100, epoch * n_total_steps + i) running_loss = 0.0 running_correct = 0 15. Save and Load Models # save torch.save(model.state_dict(), \u0026#39;model.pt\u0026#39;) # del model ... #load model_load = NeuralNetMultiClass(input_size, hidden_size, num_classes).to(device) model_load.load_state_dict(torch.load(\u0026#39;model.pt\u0026#39;)) model_load.eval() # test acc = validation_test(test_loader, 1, model_load) print(f\u0026#39;accuracy: {acc:.4f}\u0026#39;) model.eval()的作用\n有些model中存在dropout layers或BatchNorm layers, 这些layers在evaluation的时候是不使用的, eval()函数可以关闭这些layers.\neval()在validation和test时都不会进行梯度下降.(无需使用torch.no_grad())\n如果之后还需要训练, 使用train()函数.\n# training step ... model.train() ... 查看model权重\n# model = torch.save(FILE) # model = torch.load(FILE) 使用state_dict() load_state_dict()显示更详细 # model.eval() for param in model_load.parameters(): print(param) ","permalink":"https://sqf.icu/article/8da37f6b-dcd7-4302-bd13-a8e8467aa8c2/","summary":"\u003cp\u003e\u003ca href=\"https://www.youtube.com/watch?v=c36lUUr864M\"\u003eDeep Learning With PyTorch - Full Course\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"1-installation\"\u003e1. Installation\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"https://pytorch.org/\"\u003ePyTorch\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"2-tensor-basics\"\u003e2. Tensor Basics\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e torch\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etorch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ezeros()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etorch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eones()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etorch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003erand() \u003cspan style=\"color:#75715e\"\u003e# 正数随机(0, 1)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etorch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003erandn() \u003cspan style=\"color:#75715e\"\u003e# 带负数的随机(-1, 1)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etorch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etensor([[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e], [\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e]])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etorch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eadd(a, b)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etorch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003emul(a, b) \u003cspan style=\"color:#75715e\"\u003e# 哈德马积\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etorch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003emm(a, b) \u003cspan style=\"color:#75715e\"\u003e# 矩阵相乘\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ea\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003et() \u003cspan style=\"color:#75715e\"\u003e# 转置\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ea\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eadd_(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) \u003cspan style=\"color:#75715e\"\u003e# 矩阵内数值全部+1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 也可以直接 a+=1, 在numpy中也可以用\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ea \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e torch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003erand(\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ea\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eview(\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#75715e\"\u003e#使矩阵从(2, 4)-\u0026gt;(4, 2), -1是缺省值自动计算\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etorch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003exxxx(xxxxx ,dtype\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003efloat (int32)) \u003cspan style=\"color:#75715e\"\u003e# 可以定义数据类型\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e numpy \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e np\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ea \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e np\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eones()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eb \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e torch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003efrom_numpy(a) \u003cspan style=\"color:#75715e\"\u003e# np.ndarray -\u0026gt; tensor\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ec \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e b\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003enumpy() \u003cspan style=\"color:#75715e\"\u003e# tensor -\u0026gt; np.ndarray\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 书中的一些其他基础函数\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ea \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e torch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003earange(\u003cspan style=\"color:#ae81ff\"\u003e12\u003c/span\u003e) \u003cspan style=\"color:#75715e\"\u003e# 新定义1-12个元素张量\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ex\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eshape \u003cspan style=\"color:#75715e\"\u003e# 显示张量的形状\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# torch.Size([12])\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ex\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003enumel() \u003cspan style=\"color:#75715e\"\u003e# 只显示张量的元素数量\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 12\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003etensor格式是专门为cuda准备的\u003c/li\u003e\n\u003cli\u003etensor和np.ndarray 相互转换时, 变量的内存共享, eg: 使用add_, 都会变.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e torch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ecuda\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eis_available():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    device \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e torch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003edevice(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;cuda\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e torch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eones(\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e, device\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003edevice) \u003cspan style=\"color:#75715e\"\u003e# 写入显存\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e torch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eones(\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e) \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e y\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eto(device) \u003cspan style=\"color:#75715e\"\u003e# 写入显存2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    z \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e y\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    print(z)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#75715e\"\u003e# z = z.to(\u0026#34;cpu\u0026#34;) # 只有参数放回内存之后才可以改为numpy格式\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    z\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003enumpy() \u003cspan style=\"color:#75715e\"\u003e# 报错, 显存中的tensor参数不能变成numpy格式\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003enumpy格式无法放入显存\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e选定显卡\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e os\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eos\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eenviron[\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;CUDA_VISIBLE_DEVICES\u0026#34;\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;0\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# or\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# when loading model\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emodel\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eload_state_dict(torch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eload(PATH, map_location\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;cuda:0\u0026#34;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emodel\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eto(device)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# or when initing the model\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emodel_load \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e NeuralNetMultiClass(input_size, hidden_size, num_classes)\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eto(device)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":"PyTorch深度学习入门"},{"content":"第1节课 transfer learning\nInductive Transfer Learning 归纳式迁移学习\nTransductive Transfer Learning 直推式迁移学习\nDomain Adaptation 领域的自适应 任务一致，数据不一致 Unsupervised Transfer Learning 无监督式迁移学习\nDA\none-step Xs=Xt,P(Xs)≠P(Xt) 数据空间一致，数据分布不一致 Xs≠Xt 数据空间不一致 multi-step 多步 （如同时含有文字和图片） 特征的自适应\n半监督 DA问题\n加号左边是标记好的样本，右边是没有标记好的样本。\n第2节课 对长文本支持弱，根据句号截断\n用GPT文本生成来文本增强\ntest data预测之后与训练集合并，在训练集上切出一块验证集，训练。（扩大数据量？）\n第3节课 残差？\n左边是一个门控结构\n2不同的特征工程相同model也可以融合\n3半监督\n4bert系列5个模型，和不同fine-tuning方式\n文章的开头和结尾往往会有重要信息。\nWWM对中文更有效 词级别的mask\n在sentiment analyze中更有效\nSVD /PCN 矩阵分解\nensemble模型融合\n起始字符的语义信息\n最大池化\n最后的一个字符的语义信息\n2不用transformer时，常用word2vec之类的\n4不太用\n第4节课 面试相关问题 融合\n加权融合 先不同模型提交结果 分数差的权重高 eg. 0.7model1+0.3model2 stacking 作业\n","permalink":"https://sqf.icu/article/390d7e5a-d21e-448f-b096-0310b27cd073/","summary":"\u003ch1 id=\"第1节课\"\u003e第1节课\u003c/h1\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/media/22ed3d624ebd4bdc9d0980e5.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/media/3dd31d84753762be5fdaceed.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/media/5f526d940005132439575adb.png\"\u003e\u003c/p\u003e\n\u003cp\u003etransfer learning\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003eInductive Transfer Learning 归纳式迁移学习\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eTransductive Transfer Learning 直推式迁移学习\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eDomain Adaptation 领域的自适应\n\u003cul\u003e\n\u003cli\u003e任务一致，数据不一致\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUnsupervised Transfer Learning 无监督式迁移学习\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/media/4449b4cca31b311f0b984f5f.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/media/30133b2d72dd560c72724b02.png\"\u003e\u003c/p\u003e\n\u003cp\u003eDA\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eone-step\n\u003col\u003e\n\u003cli\u003eXs=Xt,P(Xs)≠P(Xt) 数据空间一致，数据分布不一致\u003c/li\u003e\n\u003cli\u003eXs≠Xt 数据空间不一致\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/li\u003e\n\u003cli\u003emulti-step\n\u003col\u003e\n\u003cli\u003e多步 （如同时含有文字和图片）\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/media/fa731eb1ef2ad69146c6cf7e.png\"\u003e\u003c/p\u003e","title":"深度之眼 迁移学习公开课"},{"content":"网格修复 1. 网格介绍 网格指的是三维多边形网格模型，以下简称为“网格”。简单来说，可以给网格下一个简单定义：由多边形集合定义的，用以表示三维模型表面轮廓的拓扑和空间结构称为“网格”，英文称作“polygon mesh”或“mesh”。\n其中，尤以三角网格应用最为广泛（表示最为简单且稳定），因此本文一般讨论的网格是三角网格，但即便是由四边形及以上的多边形构成的网格也可以通过三角剖分（Triangulation）算法来获得三角网格。\n2. 网格修复介绍 在3D打印，CAD研发，多目重建，三维扫描重建，数字文物建模以及其他三维图形处理领域，多半会遇到网格表面的质量不够好的情况。\n四种典型的网格质量问题\n总结来说， 网格的问题可以归结为六种：\n法向错误（反向？）\n三角形的顶点次序与三角形面片的法向量不满足规则。这主要是由于生成STL文件时顶点顺序的混乱导致外法向量计算错误。这种错误不会造成以后的切片和零件制作的失败，但是为了保持三维模型的完整性，我们必须加以修复。\n孔洞\n这主要是由于三角面片的丢失引起的。当CAD模型的表面有较大曲率的曲面相交时，在曲面相交部分会出现丢失三角面片而造成孔洞。孔洞修复通过添加新的面片以填补缺失的区域。\n缝隙\n通常由于顶点不重合引起的。缝隙和孔洞都可以看作是三角面片缺失产生的。但对于裂缝，修复通常是移动点将其合并在一起。\n多壳体\n壳体的定义是一组相互正确连接的三角形的有限集合。一个正确的STL模型通常只有一个壳。存在多个壳体通常是由于零件块造型时没有进行布尔运算，结构与结构之间存在分割面引起的。\nSTL文件可能存在由非常少的面片组成、表面积和体积为零的干扰壳体。这些壳体没有几何意义，可以直接删除。\n重叠或相交\n重叠面错误主要是由三角形顶点计算时舍入误差造成的，由于三角形的顶点在3D空间中以浮点数表示的，如果圆整误差范围较大，就会导致面片的重叠或者分离。\n错误边界\n在STL格式中，每一个三角面片与周围的三角面片都应该保持良好的连接。如果某个连接处出了问题，这个边界称为错误边界，并用黄线标示， 一组错误边界构成错误轮廓。面片法向错误、缝隙、孔洞、重叠都会引发错误的边界，对不同位置的错误确定坏边原因，找到合适的修复方法。\n注意：大多数的网格处理算法都是基于表面封闭且符合2-manifold特性的网格来设计的（可以暂时理解成网格表面封闭且光滑），甚至有些算法还需要多边形在网格上分布均匀。\n3. 现有算法介绍 目前网格修复算法分类：\n基于点云或基于网格： 体数据修复（Volume-based methods）：先构建体数据（例如LDI，Octree，Uniform grid等），在体数据上修复完成后重建网格。 表面数据修复（Surface-based methods，网格修复）：直接在网格表面进行修补孔洞和其他缺陷。 神经网络/模式学习： 学习某些区域的特征来修复 利用同类或相似三维模型的局部相近区域进行拷贝修整 3.1. 基于点云 基于点云的方法是最先被研究的，其中确实有一些有价值的理论，可能对未来的研究者来说，对孔洞填充的研究有所启发。随着计算机图形学的快速发展，基于网格的方法得到了越来越多的关注，并在曲面重建中发挥了基础作用。尽管存在不同种类的网格，只有三角网格是最流行的重建表面的方法。所以2018年的综述只讨论了基于网格的方法。 3.2. 基于网格 体数据修复\nThe biggest difference between this method and others is that it guarantees the full preservation of the input mesh, Fig.10 confirms this point. The main strength of volume-based hole filling methods in meshes is that they are robust to resolve geometric defects and produce a manifold output mesh surface without self-intersections. The major weakness is that in the diffusion phase, geometric details are lost inevitably, even in the remainder areas far from the hole.\nVolFill2002[20]\nDavis, J., Marschner, S. R., Garr, M., Levoy, M.: filling holes in complex surfaces using volumetric diffusion. In 3D Data Processing Visualization and Transmission. Proceedings. IEEE. First International Symposium on pp. 428-441.(2002) 介绍了一种典型的修复技术，采用体积扩散程序来完成孔的表面。它的目的是针对那些详细的孔在几何上和拓扑上过于复杂而无法用一般的surface-based methods解决的情况。 JuTao2004[21]\nJu T. Robust repair of polygonal models[J]. ACM Transactions on Graphics (TOG), 2004, 23(3): 888-895.\nIt partitions the space into disjoint internal and external volume using an octree grid to repair polygonal model surface by contouring. Though it guarantees a closed output model, it alters the input mesh which may lose sharp features and fine details of the models, as can be seen from the results in Fig.4, this approach alters the organization of the original input mesh obviously.\n**PolyMender：**windows+非开源？需要登录wustl大学账号\nGuo2006[22]\nGuo T Q, Li J J, Weng J G, et al. Filling holes in complex surfaces using oriented voxel diffusion[C]//2006 International Conference on Machine Learning and Cybernetics. IEEE, 2006: 4370-4375. It introduces an oriented voxel global diffusion method to fill holes in complex surfaces. In particular, the diffusion direction of the oriented distance field is controlled accurately inward the hole to restore the sharp features of the incomplete input. While this algorithm is able to fix the incomplete surface smoothly and handle complex holes which contain islands, it consumes large quantity of memory to store these oriented volumetric units such that it lacks the ability to tackle large size input models. Ramesh2015[23]\nCentin M, Pezzotti N, Signoroni A. Poisson-driven seamless completion of triangular meshes[J]. Computer Aided Geometric Design, 2015, 35: 42-55. It employs a Poisson Reconstruction step to obtain an implicit function and then deploys an interpolation method to reconstruct missing parts of the input mesh. A fast and continuous surface-oracle computation exploited to efficiently guide the restricted Delaunay triangulation is one of the crucial elements to perform hole filling works. windows系统，闭源：https://drive.google.com/file/d/1bbnwyYe550L3Un69ix-SdzCZvk-FfNDy/view 表面数据修复\nLiepa2003[24] Liepa P. Filling holes in meshes[C]//Proceedings of the 2003 Eurographics/ACM SIGGRAPH symposium on Geometry processing. 2003: 200-205. It proposes a surface oriented method to smoothly fill holes such that the vertex densities around the holes are interpolated. python（非官方？）：https://github.com/russelmann/hole-filling-liepa Jun2005[17] Jun Y. A piecewise hole filling algorithm in reverse engineering[J]. Computer-aided design, 2005, 37(2): 263-270. It splits a complex hole into several simple holes and fills each divided simple hole with planar triangulation method consecutively until the entire complex hole is closed. ReMESH2006 Attene M, Falcidieno B. Remesh: An interactive environment to edit and repair triangle meshes[C]//IEEE International Conference on Shape Modeling and Applications 2006 (SMI'06). IEEE, 2006: 41-41. C++：https://github.com/huxingyi/autoremesher MeshFix2010[25] M. Attene. A lightweight approach to repairing digitized polygon meshes. The Visual Computer, 2010. (c) Springer. DOI: 10.1007/s00371-010-0416-3\npython源码：https://github.com/pyvista/pymeshfix\nC++源码：https://github.com/MarcoAttene/MeshFix-V2.1\nIt concentrates on converting a low-quality digitized polygon mesh to a single manifold and watertight triangle mesh without degenerating or intersecting elements. It assumes that the resulting mesh should be a single connected manifold bounding a polyhedron and the sampling density should not vary significantly from one part of the mesh to another. Its inherited characteristics don’t guarantee that the filled surface will converge eventually, which is the main drawbacks of this method.\n主要模块：\nhttps://zhuanlan.zhihu.com/p/53269870\n拓扑重建（Topology reconstruction）：删除离群点，冗余小连通块，修补孔洞 等。 几何校正（Geommtry correction）：包括矫正退化元素（比如夹角近乎0或180度，长度近乎0的线段等等，但暂时都可以统一为近乎空面积或夹角过小的三角形），自交多边形，甚至是超过阈值的某个三角边长等。 Qiang2010[18] Qiang H, Shusheng Z, Xiaoliang B, et al. Hole filling based on local surface approximation[C]//2010 International Conference on Computer Application and System Modeling (ICCASM 2010). IEEE, 2010, 3: V3-242-V3-245. It creates new triangles by the constraint Delaunay triangulation method to fill holes. Wei2010[26] Wei M, Wu J, Pang M. An integrated approach to filling holes in meshes[C]//2010 International Conference on Artificial Intelligence and Computational Intelligence. IEEE, 2010, 3: 306-310. It generates a minimal triangulation to the hole. In order to assort with the density of neighbor meshes, the new triangles are subdivided according to their edge length. The defect of the method is obvious for the filling results dependent heavily on the geometry of the hole neighbors. Harary2014[27] Harary G, Tal A, Grinspun E. Context-based coherent surface completion[J]. ACM Transactions on Graphics (TOG), 2014, 33(1): 1-12. It introduces a hole filling algorithm for a given triangle mesh to synthesize missing geometry by learning the knowledge of the similar geometry in the remainder mesh. Different from other context-based approaches, it completes the hole field coherently to the local neighborhood while maintaining a proper triangulation of the mesh surface. [28]和[29] has been used widely to deal with large scattered data sets. Without the requisite of prior knowledge of the object topology, the methods construct the implicit signed distance function constrained by the exterior points near the hole to approximate the surface and interpolate new points into hole regions Branch2006[28] Branch J, Prieto F, Boulanger P. Automatic hole-filling of triangular meshes using local radial basis function[C]//Third International Symposium on 3D Data Processing, Visualization, and Transmission (3DPVT'06). IEEE, 2006: 727-734. An implicit surface representation based on Radial Basis Functions(RBF). Tekumalla2014[29] Tekumalla L S, Cohen E. Reverse engineering point clouds to fit tensor product B-spline surfaces by blending local fits[J]. arXiv preprint arXiv:1411.5993, 2014. An implicit surface representation based on Moving Least Squares. Functions(RBF) Dellepiane2009[30] Dellepiane M, Venturi A, Scopigno R. Image guided reconstruction of un-sampled data: a coherent filling for uncomplete Cultural Heritage models[C]//2009 IEEE 12th International Conference on Computer Vision Workshops, ICCV Workshops. IEEE, 2009: 939-946. An image facilitates the hole filling process efficiently and precisely. Quinsat2015[31] Quinsat Y. Filling holes in digitized point cloud using a morphing-based approach to preserve volume characteristics[J]. The International Journal of Advanced Manufacturing Technology, 2015, 81(1): 411-421. It requires a priori knowledge of the input model and it mainly focuses on the hole filling problem of the CAD model, so this algorithm cannot be applied to other common inputs. 这个需要通用性不强。 其他4个软件类工具\nMesh Repairing Software on the Web：http://www.meshrepair.org/ MeshLab：https://github.com/cnr-isti-vclab/meshlab 新的一些算法\n关键词：\nsite:thecvf.com mesh holes patching site:thecvf.com mesh filling holes Shi2021 Shi Y, Ni B, Liu J, et al. Geometric Granularity Aware Pixel-To-Mesh[C]//Proceedings of the IEEE/CVF International Conference on Computer Vision. 2021: 13097-13106.\n已知算法对比试验结果\n3.3. 神经网络 Jeon J, Lee S. Reconstruction-based pairwise depth dataset for depth image enhancement using CNN[C]//Proceedings of the European Conference on Computer Vision (ECCV). 2018: 422-438. 需要a RGB-D camera。 参考资料 浅谈三维网格修复\nMesh Repairing Software on the Web\n综述：Guo X, Xiao J, Wang Y. A survey on algorithms of hole filling in 3D surface reconstruction[J]. The Visual Computer, 2018, 34(1): 93-103. 浅谈三维网格修复：https://zhuanlan.zhihu.com/p/53269870 Mesh Repairing Software on the Web：http://www.meshrepair.org/ **Eurographics 2012 Tutorial** ←基于the survey Polygon Mesh Repairing: An Application Perspective by Marco Attene（2013） ","permalink":"https://sqf.icu/article/5cf9e354-ba89-45bf-a17c-5fe67beaadf2/","summary":"\u003ch1 id=\"网格修复\"\u003e网格修复\u003c/h1\u003e\n\u003ch2 id=\"1-网格介绍\"\u003e1. 网格介绍\u003c/h2\u003e\n\u003cp\u003e网格指的是\u003cstrong\u003e三维多边形网格模型\u003c/strong\u003e，以下简称为“网格”。简单来说，可以给网格下一个简单定义：\u003cstrong\u003e由多边形集合定义的，用以表示三维模型表面轮廓的拓扑和空间结构称为“网格”，\u003cstrong\u003e英文称作\u003c/strong\u003e“polygon mesh”或“mesh”\u003c/strong\u003e。\u003c/p\u003e","title":"三维网格修复论文调研"},{"content":"https://github.com/TheFrenchLeaf/Bundler\n安装cmake\n安装bundler\nmkdir build cd build cmake .. make apt-get install imagemagick Linux =\u0026gt; use makefile in program/main or Cmake. =\u0026gt; Note the fact that the compilation will use the following resident libraries : - jpeg - lapack blas gfortran (included in most lapack distibution) - sometimes atlas. =\u0026gt; CMAKE USAGE : Go to the extracted archive path. $ mkdir Output $ cd Output $ cmake -G \u0026#34;CodeBlocks - Unix Makefiles\u0026#34; .. $ make =\u0026gt; Your binaries will be in Output/src ! apt-get install -y libjpeg-dev liblapack-dev libblas-dev gfortran libatlas-base-dev 问题1：//usr/lib/x86_64-linux-gnu/libblas.so.3: error adding symbols: DSO missing from command line\n[ 49%] Building CXX object src/CMakeFiles/RadialUndistort.dir/RadialUndistort.cpp.o [ 50%] Building CXX object src/CMakeFiles/RadialUndistort.dir/LoadJPEG.cpp.o [ 51%] Linking CXX executable RadialUndistort /usr/bin/c++ -fopenmp -rdynamic CMakeFiles/RadialUndistort.dir/RadialUndistort.cpp.o CMakeFiles/RadialUndistort.dir/LoadJPEG.cpp.o -o RadialUndistort ../lib/imagelib/libimagelib.a ../lib/matrix/libmatrix.a -ljpeg -llapack ../lib/cblas/libcblas.a ../lib/cminpack/libcminpack.a -lgfortran /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/liblapack.so: undefined reference to symbol \u0026#39;dgemm_\u0026#39; //usr/lib/x86_64-linux-gnu/libblas.so.3: error adding symbols: DSO missing from command line collect2: error: ld returned 1 exit status src/CMakeFiles/RadialUndistort.dir/build.make:126: recipe for target \u0026#39;src/RadialUndistort\u0026#39; failed make[2]: *** [src/RadialUndistort] Error 1 CMakeFiles/Makefile2:352: recipe for target \u0026#39;src/CMakeFiles/RadialUndistort.dir/all\u0026#39; failed make[1]: *** [src/CMakeFiles/RadialUndistort.dir/all] Error 2 Makefile:103: recipe for target \u0026#39;all\u0026#39; failed make: *** [all] Error 2 解决： Resolved by adding -lblas to the end of: src/CMakeFiles/Bundle2PMVS.dir/link.txt src/CMakeFiles/Bundler.dir/link.txt src/CMakeFiles/RadialUndistort.dir/link.txt 修改\n~~MATCHKEYS=$BASE_PATH/Output/src/KeyMatchFull BUNDLER=$BASE_PATH/Output/src/Bundler~~ MATCHKEYS=$BASE_PATH/build/src/KeyMatchFull BUNDLER=$BASE_PATH/build/src/Bundler chmod -R a+x bin/*\nbin/sift无法运行\nlinux内核版本问题？搁置。。。\n../bin/sift bash: ../bin/sift: No such file or directory ","permalink":"https://sqf.icu/article/d1b7e048-63eb-428e-a56c-dd2431b51cda/","summary":"\u003cp\u003e\u003ca href=\"https://github.com/TheFrenchLeaf/Bundler\"\u003ehttps://github.com/TheFrenchLeaf/Bundler\u003c/a\u003e\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003e安装cmake\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e安装bundler\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir build\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd build\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecmake ..\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt-get install imagemagick\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eLinux \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u0026gt; use makefile in program/main or Cmake.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u0026gt; Note the fact that the compilation will use the following resident libraries :\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         - jpeg\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         - lapack blas gfortran \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eincluded in most lapack distibution\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         - sometimes atlas.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u0026gt; CMAKE USAGE :\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eGo to the extracted archive path. \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ mkdir Output\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ cd Output\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ cmake -G \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;CodeBlocks - Unix Makefiles\u0026#34;\u003c/span\u003e ..\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ make\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u0026gt; Your binaries will be in Output/src !\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt-get install -y libjpeg-dev liblapack-dev libblas-dev gfortran libatlas-base-dev\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e问题1：//usr/lib/x86_64-linux-gnu/libblas.so.3: error adding symbols: DSO missing from command line\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e 49%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Building CXX object src/CMakeFiles/RadialUndistort.dir/RadialUndistort.cpp.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e 50%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Building CXX object src/CMakeFiles/RadialUndistort.dir/LoadJPEG.cpp.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e 51%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Linking CXX executable RadialUndistort\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/usr/bin/c++   -fopenmp  -rdynamic CMakeFiles/RadialUndistort.dir/RadialUndistort.cpp.o CMakeFiles/RadialUndistort.dir/LoadJPEG.cpp.o  -o RadialUndistort  ../lib/imagelib/libimagelib.a ../lib/matrix/libmatrix.a -ljpeg -llapack ../lib/cblas/libcblas.a ../lib/cminpack/libcminpack.a -lgfortran \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/liblapack.so: undefined reference to symbol \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dgemm_\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e//usr/lib/x86_64-linux-gnu/libblas.so.3: error adding symbols: DSO missing from command line\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecollect2: error: ld returned \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e exit status\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esrc/CMakeFiles/RadialUndistort.dir/build.make:126: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;src/RadialUndistort\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003esrc/RadialUndistort\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCMakeFiles/Makefile2:352: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;src/CMakeFiles/RadialUndistort.dir/all\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e1\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003esrc/CMakeFiles/RadialUndistort.dir/all\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eMakefile:103: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;all\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eall\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e解决：\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eResolved by adding -lblas to the end of:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esrc/CMakeFiles/Bundle2PMVS.dir/link.txt\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esrc/CMakeFiles/Bundler.dir/link.txt\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esrc/CMakeFiles/RadialUndistort.dir/link.txt\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e修改\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~~MATCHKEYS\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e$BASE_PATH/Output/src/KeyMatchFull\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eBUNDLER\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e$BASE_PATH/Output/src/Bundler~~\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eMATCHKEYS\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e$BASE_PATH/build/src/KeyMatchFull\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eBUNDLER\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e$BASE_PATH/build/src/Bundler\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003echmod -R a+x bin/*\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ebin/sift无法运行\u003c/p\u003e\n\u003cp\u003elinux内核版本问题？搁置。。。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e../bin/sift \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebash: ../bin/sift: No such file or directory\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ol\u003e","title":"bundler安装（无法使用内置sift）"},{"content":"1. 安装 下载项目\ngit clone --recursive https://github.com/nvlabs/instant-ngp cd instant-ngp 安装环境\npip install -r requirements.txt cmake -S . -B build 问题1\nCMake Error: The source directory \u0026#34;/home/xxx/graphics_primitives/instant-ngp/build\u0026#34; does not appear to contain CMakeLists.txt. Specify --help for usage, or press the help button on the CMake GUI. # 老版本cmake会读取build下的配置文件, 新版本不用, 所以升级cmake版本 或 CMake Error at CMakeLists.txt:9 (cmake_minimum_required): CMake 3.19 or higher is required. You are running version 3.10.2 -- Configuring incomplete, errors occurred! 解决: 升级CMake 非root安装cmake wget https://github.com/Kitware/CMake/releases/download/v3.23.0/cmake-3.23.0.tar.gz tar zxvf cmake-3.23.0.tar.gz \u0026amp;\u0026amp; cd cmake-3.23.0 ~~./bootstrap~~ ./bootstrap -- -DCMAKE_USE_OPENSSL=OFF # 非root下可以选择关闭openssl防止报错 ./configure --prefix=/.../cmake # 设置在自己目录下 make make install vim ~/.bashrc export PATH=/home/xxx/cmake/bin:$PATH source ~/.bashrc 问题: ./bootstrap时报错\nCMake Error at Utilities/cmcurl/CMakeLists.txt:586 (message): Could not find OpenSSL. Install an OpenSSL development package or configure CMake with -DCMAKE_USE_OPENSSL=OFF to build without OpenSSL. 解决: 没有开发版OpenSSL, 不使用openssl\n# apt-get install libssl-dev # 非root ./bootstrap -- -DCMAKE_USE_OPENSSL=OFF 问题: ./configure \u0026ndash;prefix=/\u0026hellip;/cmake 地址写错或没有权限\n-- No release type specified. Setting to \u0026#39;Release\u0026#39;. CMake Error at CMakeLists.txt:38 (message): Some instant-ngp dependencies are missing. If you forgot the \u0026#34;--recursive\u0026#34; flag when cloning this project, this can be fixed by calling \u0026#34;git submodule update --init --recursive\u0026#34;. CMAKE_CUDA_ARCHITECTURES must be valid if set.\n解决: 删除build文件夹 cmake --build build --config RelWithDebInfo -j 16 问题1: nvcc fatal : Unsupported gpu architecture \u0026lsquo;compute_80+PTX\u0026rsquo;\n[ 1%] Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/cpp_api.cu.o [ 3%] Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/cutlass_mlp.cu.o [ 5%] Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/loss.cu.o [ 7%] Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/common.cu.o [ 10%] Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/encoding.cu.o [ 10%] Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/common_device.cu.o [ 12%] Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/network.cu.o [ 14%] Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/optimizer.cu.o [ 18%] Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/object.cu.o [ 18%] Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/reduce_sum.cu.o [ 20%] Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/fully_fused_mlp.cu.o nvcc fatal : Unsupported gpu architecture \u0026#39;compute_80+PTX\u0026#39; nvcc fatal : Unsupported gpu architecture \u0026#39;compute_80+PTX\u0026#39; dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:103: recipe for target \u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/cpp_api.cu.o\u0026#39; failed make[2]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/cpp_api.cu.o] Error 1 make[2]: *** Waiting for unfinished jobs.... nvcc fatal : Unsupported gpu architecture \u0026#39;compute_80+PTX\u0026#39; nvcc fatal : Unsupported gpu architecture \u0026#39;compute_80+PTX\u0026#39; dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:145: recipe for target \u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/loss.cu.o\u0026#39; failed make[2]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/loss.cu.o] Error 1 nvcc fatal : Unsupported gpu architecture \u0026#39;compute_80+PTX\u0026#39; dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:75: recipe for target \u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/common.cu.o\u0026#39; failed make[2]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/common.cu.o] Error 1 dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:117: recipe for target \u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/cutlass_mlp.cu.o\u0026#39; failed make[2]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/cutlass_mlp.cu.o] Error 1 nvcc fatal : Unsupported gpu architecture \u0026#39;compute_80+PTX\u0026#39; nvcc fatal : Unsupported gpu architecture \u0026#39;compute_80+PTX\u0026#39; dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:89: recipe for target \u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/common_device.cu.o\u0026#39; failed make[2]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/common_device.cu.o] Error 1 nvcc fatal : Unsupported gpu architecture \u0026#39;compute_80+PTX\u0026#39; dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:159: recipe for target \u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/network.cu.o\u0026#39; failed make[2]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/network.cu.o] Error 1 nvcc fatal : Unsupported gpu architecture \u0026#39;compute_80+PTX\u0026#39; dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:131: recipe for target \u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/encoding.cu.o\u0026#39; failed make[2]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/encoding.cu.o] Error 1 dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:187: recipe for target \u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/optimizer.cu.o\u0026#39; failed make[2]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/optimizer.cu.o] Error 1 nvcc fatal : Unsupported gpu architecture \u0026#39;compute_80+PTX\u0026#39; nvcc fatal : Unsupported gpu architecture \u0026#39;compute_80+PTX\u0026#39; dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:173: recipe for target \u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/object.cu.o\u0026#39; failed make[2]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/object.cu.o] Error 1 dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:215: recipe for target \u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/fully_fused_mlp.cu.o\u0026#39; failed make[2]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/fully_fused_mlp.cu.o] Error 1 dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:201: recipe for target \u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/reduce_sum.cu.o\u0026#39; failed make[2]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/reduce_sum.cu.o] Error 1 CMakeFiles/Makefile2:305: recipe for target \u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/all\u0026#39; failed make[1]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/all] Error 2 make[1]: *** Waiting for unfinished jobs.... [ 49%] Built target glfw_objects Makefile:90: recipe for target \u0026#39;all\u0026#39; failed make: *** [all] Error 2 解决: 在instant-ngp/CMakeLists.txt顶部添加:\n后面的数字是显卡的算力, 以nccl中设定的算力为准\nset( ENV{TCNN_CUDA_ARCHITECTURES} 75 ) 问题2: make[1]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/all] Error 2\nConsolidate compiler generated dependencies of target tiny-cuda-nn [ 29%] Built target glfw_objects [ 30%] Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/optimizer.cu.o /home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/include/tiny-cuda-nn/optimizers/shampoo.h(753): error: identifier \u0026#34;cublasSetWorkspace\u0026#34; is undefined detected during: instantiation of \u0026#34;tcnn::ShampooOptimizer\u0026lt;T\u0026gt;::ShampooOptimizer(const tcnn::json \u0026amp;) [with T=float]\u0026#34; /home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/src/optimizer.cu(71): here instantiation of \u0026#34;tcnn::Optimizer\u0026lt;T\u0026gt; *tcnn::create_optimizer\u0026lt;T\u0026gt;(const tcnn::json \u0026amp;) [with T=float]\u0026#34; /home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/include/tiny-cuda-nn/optimizers/average.h(65): here /home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/include/tiny-cuda-nn/optimizers/shampoo.h(771): error: identifier \u0026#34;cublasSetWorkspace\u0026#34; is undefined detected during: instantiation of \u0026#34;tcnn::ShampooOptimizer\u0026lt;T\u0026gt;::ShampooOptimizer(const tcnn::json \u0026amp;) [with T=float]\u0026#34; /home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/src/optimizer.cu(71): here instantiation of \u0026#34;tcnn::Optimizer\u0026lt;T\u0026gt; *tcnn::create_optimizer\u0026lt;T\u0026gt;(const tcnn::json \u0026amp;) [with T=float]\u0026#34; /home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/include/tiny-cuda-nn/optimizers/average.h(65): here /home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/include/tiny-cuda-nn/optimizers/shampoo.h(794): error: identifier \u0026#34;cublasSetWorkspace\u0026#34; is undefined detected during: instantiation of \u0026#34;tcnn::ShampooOptimizer\u0026lt;T\u0026gt;::ShampooOptimizer(const tcnn::json \u0026amp;) [with T=float]\u0026#34; /home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/src/optimizer.cu(71): here instantiation of \u0026#34;tcnn::Optimizer\u0026lt;T\u0026gt; *tcnn::create_optimizer\u0026lt;T\u0026gt;(const tcnn::json \u0026amp;) [with T=float]\u0026#34; /home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/include/tiny-cuda-nn/optimizers/average.h(65): here 3 errors detected in the compilation of \u0026#34;/home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/src/optimizer.cu\u0026#34;. dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:187: recipe for target \u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/optimizer.cu.o\u0026#39; failed make[2]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/optimizer.cu.o] Error 1 CMakeFiles/Makefile2:305: recipe for target \u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/all\u0026#39; failed make[1]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/all] Error 2 Makefile:90: recipe for target \u0026#39;all\u0026#39; failed make: *** [all] Error 2 原因: nccl对应cuda版本是11.0, 不是11.4.\n解决: 重装cuda或nccl\ncmake查错: 后面加-v, 能显示报错的行.\n只需要python虚拟环境的服务器中的配置 pip install -r requirements.txt export TCNN_CUDA_ARCHITECTURES=86 下载并安装 OptiX，并设置 OptiX_INSTALL_DIR 环境变量\n[https://developer.download.nvidia.cn/designworks/optix/secure/7.4.0/NVIDIA-OptiX-SDK-7.4.0-linux64-x86_64.sh?Y1wWl64XXNqxb7ETeQnMC1FDmN-fg1gq7yFZP75uvqo80VkyJjPEU3cEJtIRP3v6wmsgw55EbgwyzswJ4A0GXWe5B-UAyQ5Xb5u7L5Sn7Ty8RTcxARIb_EABVVHU-MCH_g75f9_YxdflsT30csKrIWTrIdMjRbKKwOb4lXPIGyZcCQo_3zg\u0026amp;t=eyJscyI6ImdzZW8iLCJsc2QiOiJodHRwczpcL1wvd3d3Lmdvb2dsZS5jb21cLyJ91](https://developer.download.nvidia.cn/designworks/optix/secure/7.4.0/NVIDIA-OptiX-SDK-7.4.0-linux64-x86_64.sh?Y1wWl64XXNqxb7ETeQnMC1FDmN-fg1gq7yFZP75uvqo80VkyJjPEU3cEJtIRP3v6wmsgw55EbgwyzswJ4A0GXWe5B-UAyQ5Xb5u7L5Sn7Ty8RTcxARIb_EABVVHU-MCH_g75f9_YxdflsT30csKrIWTrIdMjRbKKwOb4lXPIGyZcCQo_3zg\u0026amp;t=eyJscyI6ImdzZW8iLCJsc2QiOiJodHRwczpcL1wvd3d3Lmdvb2dsZS5jb21cLyJ91112#) 需要将 CUDA 升级至 11.4，可以多版本 CUDA 并存，但是将环境变量链接至\nexport OptiX_INSTALL_DIR=/home/xxx/Install/NVIDIA-OptiX-SDK-7.4.0-linux64-x86_64 2. 测试 使用现有图片进行测试\n./build/testbed --scene data/nerf/fox # or python scripts/run.py --scene ./data/my_data/lego_car/ --mode nerf --save_mesh ./output/lego_car.ply --gui 问题\n./build/testbed: relocation error: ./build/testbed: symbol cublasSetWorkspace_v2 version libcublas.so.11 not defined in file libcublas.so.11 with link time reference 使用python scripts/run.py查看错误\nTraceback (most recent call last): File \u0026#34;scripts/run.py\u0026#34;, line 25, in \u0026lt;module\u0026gt; import pyngp as ngp # noqa ImportError: /home/xxx/graphics_primitives/instant-ngp/build/pyngp.cpython-37m-x86_64-linux-gnu.so: symbol cublasSetWorkspace_v2 version libcublas.so.11 not defined in file libcublas.so.11 with link time reference 原因, 环境配置错误 图片transform\npython scripts/colmap2nerf.py --run_colmap --colmap_matcher exhaustive --images ./data/image_samples/crocodile/image --aabb_scale 16 --out ./data/image_samples/crocodile/transforms.json 3. docker docker build - \u0026lt; Dockerfile docker run --runtime=nvidia --name [name] --gpus all -it -p 10022:22 [Container ID] docker start [Container ID] docker exec -i -t [Container ID] bash # 使用Dockerfile配置文件 docker install X11 apt-get install -y xserver-xorg-core apt-get install x11-xserver-utils export DISPLAY=[client ip addr]:0.0 xhost + python scripts/run.py 4. colmap install ceres-solver\ngit clone https://github.com/ceres-solver/ceres-solver cd ./ceres-solver git checkout 2.0.0 mkdir ./build cd build cmake ../ -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF -DCMAKE_INSTALL_PREFIX:PATH=/home/xxx/Install make -j make install set ceres enviroment\n# cuda export CUDA_HOME=/home/xxx/Install/cuda-11.4.2 export PATH=/home/xxx/Install/cuda-11.4.2/bin:$PATH export LD_LIBRARY_PATH=/home/xxx/Install/cuda-11.4.2/lib64:$LD_LIBRARY_PATH # cmake export PATH=/home/xxx/Install/cmake/bin:$PATH # ceres export CERES_LIBRARIES=/home/xxx/Install/lib:$CERES_LIBRARIES export CERES_INCLUDE_DIRS=/home/xxx/Install/inculde:$CERES_INCLUDE_DIRS # $HOME all export LD_LIBRARY_PATH=/home/xxx/Install/lib:$LD_LIBRARY_PATH export PATH=/home/xxx/Install/bin:$PATH # OptiX export OptiX_INSTALL_DIR=/home/xxx/Install/NVIDIA-OptiX-SDK-7.4.0-linux64-x86_64 install colmap\ngit clone https://github.com/colmap/colmap cd ./colmap mkdir ./build cd build cmake .. # -DCMAKE_INSTALL_PREFIX:PATH=/home/xxx/Install make -j make install colmap -h 问题METIS_INCLUDE_DIRS-NOTFOUND 解决方法安装libmetis-dev ","permalink":"https://sqf.icu/article/1963e335-2096-4b49-91a2-f7b52ac8c181/","summary":"\u003ch1 id=\"1-安装\"\u003e1. 安装\u003c/h1\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003e下载项目\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone --recursive https://github.com/nvlabs/instant-ngp\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd instant-ngp\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e安装环境\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip install -r requirements.txt\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecmake -S . -B build \n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e问题1\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCMake Error: The source directory \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/home/xxx/graphics_primitives/instant-ngp/build\u0026#34;\u003c/span\u003e does \u003cspan style=\"color:#f92672\"\u003enot\u003c/span\u003e appear to contain CMakeLists\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etxt\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSpecify \u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003ehelp \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e usage, \u003cspan style=\"color:#f92672\"\u003eor\u003c/span\u003e press the help button on the CMake GUI\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 老版本cmake会读取build下的配置文件, 新版本不用, 所以升级cmake版本\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e或\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCMake Error at CMakeLists\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etxt:\u003cspan style=\"color:#ae81ff\"\u003e9\u003c/span\u003e (cmake_minimum_required):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  CMake \u003cspan style=\"color:#ae81ff\"\u003e3.19\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003eor\u003c/span\u003e higher \u003cspan style=\"color:#f92672\"\u003eis\u003c/span\u003e required\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e  You are running version \u003cspan style=\"color:#ae81ff\"\u003e3.10.2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003e Configuring incomplete, errors occurred\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e!\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e解决: 升级CMake\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e非root安装cmake\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ewget https:\u003cspan style=\"color:#f92672\"\u003e//\u003c/span\u003egithub\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ecom\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eKitware\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eCMake\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003ereleases\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003edownload\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003ev3\u003cspan style=\"color:#ae81ff\"\u003e.23.0\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003ecmake\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3.23.0\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etar\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003egz\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etar zxvf cmake\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3.23.0\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etar\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003egz \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e cd cmake\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3.23.0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e~~./\u003c/span\u003ebootstrap\u003cspan style=\"color:#f92672\"\u003e~~\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e./\u003c/span\u003ebootstrap \u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eDCMAKE_USE_OPENSSL\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eOFF \u003cspan style=\"color:#75715e\"\u003e# 非root下可以选择关闭openssl防止报错\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e./\u003c/span\u003econfigure \u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003eprefix\u003cspan style=\"color:#f92672\"\u003e=/.../\u003c/span\u003ecmake \u003cspan style=\"color:#75715e\"\u003e# 设置在自己目录下\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake install\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003evim \u003cspan style=\"color:#f92672\"\u003e~/.\u003c/span\u003ebashrc\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport PATH\u003cspan style=\"color:#f92672\"\u003e=/\u003c/span\u003ehome\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003exxx\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003ecmake\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003ebin:\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e$\u003c/span\u003ePATH\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esource \u003cspan style=\"color:#f92672\"\u003e~/.\u003c/span\u003ebashrc\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e问题: ./bootstrap时报错\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e CMake Error at Utilities\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003ecmcurl\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eCMakeLists\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etxt:\u003cspan style=\"color:#ae81ff\"\u003e586\u003c/span\u003e (message):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  Could \u003cspan style=\"color:#f92672\"\u003enot\u003c/span\u003e find OpenSSL\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e  Install an OpenSSL development package \u003cspan style=\"color:#f92672\"\u003eor\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  configure CMake \u003cspan style=\"color:#66d9ef\"\u003ewith\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eDCMAKE_USE_OPENSSL\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eOFF to build without OpenSSL\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e解决: 没有开发版OpenSSL, 不使用openssl\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# apt-get install libssl-dev\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 非root\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e./\u003c/span\u003ebootstrap \u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eDCMAKE_USE_OPENSSL\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eOFF\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e问题: ./configure \u0026ndash;prefix=/\u0026hellip;/cmake 地址写错或没有权限\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-- No release type specified. Setting to \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Release\u0026#39;\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCMake Error at CMakeLists.txt:38 \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003emessage\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  Some instant-ngp dependencies are missing.  If you forgot the \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;--recursive\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  flag when cloning this project, this can be fixed by calling \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;git submodule\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e  update --init --recursive\u0026#34;\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCMAKE_CUDA_ARCHITECTURES must be valid if set.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e解决: 删除build文件夹\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecmake --build build --config RelWithDebInfo -j \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e问题1: nvcc fatal   : Unsupported gpu architecture \u0026lsquo;compute_80+PTX\u0026rsquo;\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e  1%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/cpp_api.cu.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e  3%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/cutlass_mlp.cu.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e  5%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/loss.cu.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e  7%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/common.cu.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e 10%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/encoding.cu.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e 10%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/common_device.cu.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e 12%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/network.cu.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e 14%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/optimizer.cu.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e 18%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/object.cu.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e 18%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/reduce_sum.cu.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e 20%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/fully_fused_mlp.cu.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003envcc fatal   : Unsupported gpu architecture \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;compute_80+PTX\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003envcc fatal   : Unsupported gpu architecture \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;compute_80+PTX\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:103: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/cpp_api.cu.o\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/cpp_api.cu.o\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** Waiting \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e unfinished jobs....\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003envcc fatal   : Unsupported gpu architecture \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;compute_80+PTX\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003envcc fatal   : Unsupported gpu architecture \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;compute_80+PTX\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:145: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/loss.cu.o\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/loss.cu.o\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003envcc fatal   : Unsupported gpu architecture \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;compute_80+PTX\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:75: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/common.cu.o\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/common.cu.o\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:117: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/cutlass_mlp.cu.o\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/cutlass_mlp.cu.o\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003envcc fatal   : Unsupported gpu architecture \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;compute_80+PTX\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003envcc fatal   : Unsupported gpu architecture \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;compute_80+PTX\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:89: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/common_device.cu.o\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/common_device.cu.o\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003envcc fatal   : Unsupported gpu architecture \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;compute_80+PTX\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:159: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/network.cu.o\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/network.cu.o\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003envcc fatal   : Unsupported gpu architecture \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;compute_80+PTX\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:131: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/encoding.cu.o\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/encoding.cu.o\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:187: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/optimizer.cu.o\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/optimizer.cu.o\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003envcc fatal   : Unsupported gpu architecture \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;compute_80+PTX\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003envcc fatal   : Unsupported gpu architecture \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;compute_80+PTX\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:173: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/object.cu.o\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/object.cu.o\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:215: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/fully_fused_mlp.cu.o\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/fully_fused_mlp.cu.o\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:201: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/reduce_sum.cu.o\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/reduce_sum.cu.o\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCMakeFiles/Makefile2:305: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/all\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e1\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/all\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e1\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** Waiting \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e unfinished jobs....\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e 49%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Built target glfw_objects\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eMakefile:90: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;all\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eall\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e解决: 在instant-ngp/CMakeLists.txt顶部添加:\u003c/p\u003e\n\u003cp\u003e后面的数字是显卡的算力, 以nccl中设定的算力为准\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eset\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e ENV\u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003eTCNN_CUDA_ARCHITECTURES\u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e75\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e问题2: make[1]: *** [dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/all] Error 2\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eConsolidate compiler generated dependencies of target tiny-cuda-nn\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e 29%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Built target glfw_objects\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e 30%\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Building CUDA object dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/optimizer.cu.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/include/tiny-cuda-nn/optimizers/shampoo.h\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e753\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: error: identifier \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;cublasSetWorkspace\u0026#34;\u003c/span\u003e is undefined\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          detected during:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            instantiation of \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;tcnn::ShampooOptimizer\u0026lt;T\u0026gt;::ShampooOptimizer(const tcnn::json \u0026amp;) [with T=float]\u0026#34;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/src/optimizer.cu\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e71\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: here\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            instantiation of \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;tcnn::Optimizer\u0026lt;T\u0026gt; *tcnn::create_optimizer\u0026lt;T\u0026gt;(const tcnn::json \u0026amp;) [with T=float]\u0026#34;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/include/tiny-cuda-nn/optimizers/average.h\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e65\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: here\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/include/tiny-cuda-nn/optimizers/shampoo.h\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e771\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: error: identifier \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;cublasSetWorkspace\u0026#34;\u003c/span\u003e is undefined\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          detected during:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            instantiation of \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;tcnn::ShampooOptimizer\u0026lt;T\u0026gt;::ShampooOptimizer(const tcnn::json \u0026amp;) [with T=float]\u0026#34;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/src/optimizer.cu\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e71\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: here\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            instantiation of \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;tcnn::Optimizer\u0026lt;T\u0026gt; *tcnn::create_optimizer\u0026lt;T\u0026gt;(const tcnn::json \u0026amp;) [with T=float]\u0026#34;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/include/tiny-cuda-nn/optimizers/average.h\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e65\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: here\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/include/tiny-cuda-nn/optimizers/shampoo.h\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e794\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: error: identifier \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;cublasSetWorkspace\u0026#34;\u003c/span\u003e is undefined\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          detected during:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            instantiation of \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;tcnn::ShampooOptimizer\u0026lt;T\u0026gt;::ShampooOptimizer(const tcnn::json \u0026amp;) [with T=float]\u0026#34;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/src/optimizer.cu\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e71\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: here\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            instantiation of \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;tcnn::Optimizer\u0026lt;T\u0026gt; *tcnn::create_optimizer\u0026lt;T\u0026gt;(const tcnn::json \u0026amp;) [with T=float]\u0026#34;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/include/tiny-cuda-nn/optimizers/average.h\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e65\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: here\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e errors detected in the compilation of \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/home/xxx/graphics_primitives/instant-ngp/dependencies/tiny-cuda-nn/src/optimizer.cu\u0026#34;\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/build.make:187: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/optimizer.cu.o\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/optimizer.cu.o\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCMakeFiles/Makefile2:305: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/all\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e1\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edependencies/tiny-cuda-nn/src/CMakeFiles/tiny-cuda-nn.dir/all\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eMakefile:90: recipe \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;all\u0026#39;\u003c/span\u003e failed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake: *** \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eall\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Error \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e原因: nccl对应cuda版本是11.0, 不是11.4.\u003c/p\u003e\n\u003cp\u003e解决: 重装cuda或nccl\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ecmake查错: 后面加\u003ccode\u003e-v\u003c/code\u003e, 能显示报错的行.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"只需要python虚拟环境的服务器中的配置\"\u003e只需要python虚拟环境的服务器中的配置\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip install -r requirements.txt\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport TCNN_CUDA_ARCHITECTURES\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e86\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e下载并安装 OptiX，并设置 OptiX_INSTALL_DIR 环境变量\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ehttps://developer.download.nvidia.cn/designworks/optix/secure/7.4.0/NVIDIA-OptiX-SDK-7.4.0-linux64-x86_64.sh?Y1wWl64XXNqxb7ETeQnMC1FDmN-fg1gq7yFZP75uvqo80VkyJjPEU3cEJtIRP3v6wmsgw55EbgwyzswJ4A0GXWe5B-UAyQ5Xb5u7L5Sn7Ty8RTcxARIb_EABVVHU-MCH_g75f9_YxdflsT30csKrIWTrIdMjRbKKwOb4lXPIGyZcCQo_3zg\u0026amp;t\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eeyJscyI6ImdzZW8iLCJsc2QiOiJodHRwczpcL1wvd3d3Lmdvb2dsZS5jb21cLyJ91\u003cspan style=\"color:#f92672\"\u003e](\u003c/span\u003ehttps://developer.download.nvidia.cn/designworks/optix/secure/7.4.0/NVIDIA-OptiX-SDK-7.4.0-linux64-x86_64.sh?Y1wWl64XXNqxb7ETeQnMC1FDmN-fg1gq7yFZP75uvqo80VkyJjPEU3cEJtIRP3v6wmsgw55EbgwyzswJ4A0GXWe5B-UAyQ5Xb5u7L5Sn7Ty8RTcxARIb_EABVVHU-MCH_g75f9_YxdflsT30csKrIWTrIdMjRbKKwOb4lXPIGyZcCQo_3zg\u0026amp;t\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eeyJscyI6ImdzZW8iLCJsc2QiOiJodHRwczpcL1wvd3d3Lmdvb2dsZS5jb21cLyJ91112#\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e需要将 CUDA 升级至 11.4，可以多版本 CUDA 并存，但是将环境变量链接至\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport OptiX_INSTALL_DIR\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e/home/xxx/Install/NVIDIA-OptiX-SDK-7.4.0-linux64-x86_64\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ol\u003e","title":"instant-ngp项目实装"},{"content":"目录\n默认Pipline中的组件算法 参考AliceVision和meshroom程序自带说明文档\nAliceVision | Photogrammetric Computer Vision Framework\n下图是Meshroom默认pipline，其中实线连接的参数是初始设定的值；虚线连接的参数是实现设定的值。 1.1. Camera Init Input Setting Output Description Viewpoints Input viewpoints (1 Element for each loaded image) - ID - Pose ID - Image Path - Intrinsic: Internal Camera Parameters (Intrinsic ID) - Rig (-1 - 200) - Rig Sub-Pose: Rig Sub-Pose Parameters (-1 - 200) - Image Metadata: (list of metadata elements) 输入图片路径， 获得图片文件的信息 Intrinsic Camera Intrinsics (1 Element for each loaded image) - ID - Initial Focal Length: Initial Guess on the Focal Length - Focal Length: Known/Calibrated Focal Length - Camera Type: pinhole’, ‘radial1’, ‘radial3’, ‘brown’, ‘fisheye4’ - #Make: Camera Make (not included in this build, commented out) - #Model: Camera Model - #Sensor Width: Camera Sensor Width - Width: Image - Width (0-10000) - Height: Image Height (0-10000) - Serial Number: Device Serial Number (camera and lens combined) - Principal Point: X (0-10000) Y(0-10000)- DistortionParams: Distortion Parameters - Locked(True/False): If the camera has been calibrated, the internal camera parameters (intrinsics) can be locked. It should improve robustness and speedup the reconstruction. 相机内置默认参数 Sensor Database Camera sensor width database path 相机型号及其参数数据库 Default Field Of View Empirical value for the field of view in degree 45° (0°-180°) 相机视野 Verbose Level verbosity level (fatal, error, warning, info, debug, trace) 日志详细程度 SfMData File …/cameraInit.sfm 输出SfM数据文件路径 导入图片。\n1.2. Feature Extraction 特征提取 Input Setting Output Description SfMData SfMData SfMData file. 输入SfM数据文件路径 Describer Types Describer types used to describe an image. ‘sift’, ‘siftfloat’, ‘siftupright’, ‘akaze’, ‘akazeliop’, ‘akazemldb’, ‘cctag3’, ‘cctag4’, ‘siftocv’, ‘akazeocv’ 设置特征检测算法 Describer Preset Control the ImageDescriber configuration (low, medium, normal, high, ultra). Configuration “ultra” can take long time ! 设置特征精度？ Force CPU Extraction Use only CPU feature extraction. 强制使用CPU检测特征 Max Nb Threads Specifies the maximum number of threads to run simultaneously (0 for automatic mode). (0-24) 0 verbosity level (fatal, error, warning, info, debug, trace). Features Folder Output path for the features and descriptors files (*.feat, *.desc). 特征文件路径 这一步的目的是提取独特的像素组，这些像素组在某种程度上不受图像采集过程中相机视角变化的影响。因此，场景中的一个特征在所有图像中都应该有类似的特征描述。\n常见特征检测方法大致三种（SIFT, AKAZE, CCTAG）\n论文：常用特征检测方法调研。A survey of recent advances in visual feature detection, Yali Li, Shengjin Wang, Qi Tian, Xiaoqing Ding, 2015\nSIFT（Scale-invariant feature transform ****尺度不变特征转换）的最初目标是在第一幅图像中提取可辨识的斑块（discriminative patches），这些斑块可以与第二幅图像的可辨识斑块进行比较，而不考虑旋转、平移和比例。由于相关的细节只存在于某一比例，所以提取的斑块是以稳定的兴趣点为中心。在某种程度上，可以利用SIFT的不变性来处理图像采集过程中视点变化时发生的图像变动。\nSIFT 特征\n论文：Distinctive image features from scale-invariant keypoints, David G. Lowe, 2004 SIFT详细解释：Anatomy of the SIFT Method, Ives Rey Otero, Mauricio Delbracio, 2014 AKAZE（Accelerated-KAZE）可以成为在挑战性条件（如皮肤）的提取特征上表现良好\n论文：AKAZE Fast explicit diffusion for accelerated features in nonlinear scale spaces, P.F. Alcantarilla, J. Nuevo, A. Bartoli, 2013 优点：能够比SIFT匹配更广的角度。 缺点：可能会提取很多特征，重新划分也不一定好。 CCTag 是一种具有3或4个冠的标记类型。可以在拍摄过程中把标记放在场景中，以自动重新定位，并将场景的比例调整到已知的大小。它对运动模糊、景深、遮挡的影响很强。要注意在CCTags周围有足够的白边。\n需要背景标记辅助\nCCTag Library - CCTag documentation\n论文：https://cctag.readthedocs.io/en/latest/bibliography.html#id2 由于纹理复杂度的变化（从一幅图像到另一幅图像或图像的不同部分），提取的特征数量可能会有很大的变化，因此使用了一个后过滤步骤，将提取的特征数量控制在合理的范围内（例如每幅图像在1到1万之间）。我们使用网格过滤（Grid Filtering）来确保图像中的良好分区。\n1.3. Image Matching 图像匹配 Input Setting Output Description SfMData SfMData SfMData file Features Folders Features Folders Folder(s) containing the extracted features and descriptors 特征文件路径 Method 选择产生图像描述符的算法（VocabularyTree; Sequential; SequentialAndVocabularyTree; Exhaustive; Frustum; FrustumOrVocabularyTree） Voc Tree: Tree Input name for the vocabulary tree file ALICEVISION_VOCTREE 选择词汇树时，输入词汇树文件路径 Voc Tree: Weights Input name for the weight file, if not provided the weights will be computed on the database built with the provided set 选择词汇树时，输入词汇树权重路径，没有的话自动计算 Minimal Number of Images Minimal number of images to use the vocabulary tree. If we have less features than this threshold, we will compute all matching combinations 设定词汇树用到的最小图片数 Max Descriptors Limit the number of descriptors you load per image. Zero means no limit 设定一张图片中最大的描述符数量 Nb Matches The number of matches to retrieve for each image (If 0 it will retrieve all the matches) 50 (0-1000) 设定每张图片的匹配数量? Verbose Level verbosity level (fatal, error, warning, info, debug, trace) Image Pairs Filepath to the output file with the list of selected image pairs 输出图片对列表文件路径 找到与场景中相同区域的图像。将图像简化为一个紧凑的图像描述符来计算所有图像描述符之间的距离。通过比较这些图像描述符来查看不同的图像是否具有相同的内容。\n产生这种图像描述符的常用方法：\n词汇树（Vocabulary Tree）使用图像检索技术来寻找共享某些内容的图像，而不需要付出解决所有特征匹配细节的代价。每张图像都用一个紧凑的图像描述符表示，这样可以非常有效地计算所有图像描述符之间的距离。\n基于词汇树的图像检索（一）：词汇树_Mewparadise的博客-CSDN博客_词汇树怎么做\n论文：Scalable Recognition with a Vocabulary Tree, David Nister and Henrik Stewenius, CVPR 2006 序列（Sequential） 如果输入是一个视频序列，可以使用这个选项在它们之间随着时间的推移连接图像。\n序列+词汇树（SequentialAndVocabularyTree）可以实现不同时间的关键帧之间的连接。\nExhaustive 输出所有图像对。\nFrustum 如果图像有已知的姿势，则计算摄像机之间的交点frustum，以创建图像对的列表\nFrustumOrVocabularyTree 如果图像有已知的姿势，使用frustum交集，否则使用VocabularuTree。\n1.4. Feature Matching 特征匹配 Input Setting Output Description SfMData SfMData SfMData file Features Folders Features Folders Folder(s) containing the extracted features and descriptors Image Pairs Path to a file which contains the list of image pairs to match Describer Types Describer Types Describer types used to describe an image **sift**'/ 'sift_float'/ 'sift_upright'/ 'akaze'/ 'akaze_liop'/ 'akaze_mldb'/ 'cctag3'/ 'cctag4'/ 'sift_ocv'/ 'akaze_ocv Photometric Matching Method For Scalar based regions descriptor ' * BRUTE_FORCE_L2: L2 BruteForce matching' ' * ANN_L2: L2 Approximate Nearest Neighbor matching ' * CASCADE_HASHING_L2: L2 Cascade Hashing matching ' * FAST_CASCADE_HASHING_L2: L2 Cascade Hashing with precomputed hashed regions (faster than CASCADE_HASHING_L2 but use more memory) 'For Binary based descriptor ' * BRUTE_FORCE_HAMMING: BruteForce Hamming matching' Geometric Estimator Geometric estimator: (acransac: A-Contrario Ransac // loransac: LO-Ransac (only available for fundamental_matrix model) Geometric Filter Type Geometric validation method to filter features matches: **fundamental_matrix** // essential_matrix // homography_matrix /// homography_growing // no_filtering' Distance Ratio Distance ratio to discard non meaningful matches 0.8 (0.0 - 1) Max Iteration Maximum number of iterations allowed in ransac step 2048 (1 - 20000) Max Matches Maximum number of matches to keep (0 - 10000) Save Putative Matches putative matches (True/False) 保存推定结果 Guided Matching the found model to improve the pairwise correspondences (True/False) Export Debug Files debug files (svg/ dot) (True/False) 是否输出调试文件 Verbose Level verbosity level (fatal, error, warning, info, debug, trace) Matches Folder Path to a folder in which computed matches will be stored 匹配文件的保存路径 这一步的目的是在候选图像对之间匹配所有特征。分两步进行：\n测光匹配（Photometric Matches） 它在两幅输入图像的特征描述符集之间进行测光匹配。对于第一幅图像上的每个特征描述符，它在第二幅图像中寻找最接近的两个描述符，并在它们之间使用一个相对阈值。这个假设去除了重复结构的特征，但已被证明是一个稳健的标准。[Lowe2004]\n在第二幅图像中为每个特征找到两个最接近的描述符，使用蛮力的方法计算密集，但存在许多优化的算法。最常见的是近似最近邻（Approximate Nearest Neighbor，ANN）算法，也有级联哈希算法（Cascading Hashing）。 Fast Approximate Nearest Neighbors with Automatic Algorithm Configuration. Muja, Marius, and David G. Lowe. VISAPP (1). 2009 几何过滤（Geometric Filtering） 它对光度匹配的候选人进行几何过滤。在离群检测框架RANSAC（RANdom SAmple Consensus）中，通过使用极点几何来进行几何过滤。它随机选择一小部分特征对应关系并计算fundamental or essential matrix，然后检查验证该模型的特征数量并通过RANSAC框架进行迭代。\n1.5. Structure From Motion 运动推断结构（稀疏重建） Input Setting Output SfMData file Features Folder Folder(s) containing the extracted features and descriptors. Matches Folders Folder(s) in which computed matches are stored. Describer Types Describer types used to describe an image. ‘sift’, ‘siftfloat’, ‘siftupright’, ‘akaze’, ‘akazeliop’, ‘akazemldb’, ‘cctag3’, ‘cctag4’, **’siftocv’, ‘akazeocv’ Localizer Estimator Estimator type used to localize cameras (acransac, ransac, lsmeds, loransac, maxconsensus). Observation Constraint Observation contraint mode used in the optimization: Basic: Use standard reprojection error in pixel coordinates, Scale: Use reprojection error in pixel coordinates but relative to the feature scale Localizer Max Ransac Iterations Maximum number of iterations allowed in ransac step. (1-20000) 4096 Localizer Max Ransac Error Maximum error (in pixels) allowed for camera localization (resectioning). If set to 0, it will select a threshold according to the localizer estimator used (if ACRansac, it will analyze the input data to select the optimal value). (0.0-100-0) 0.0 Lock Scene Previously Reconstructed This option is useful for SfM augmentation. Lock previously reconstructed poses and intrinsics. Local Bundle Adjustment It reduces the reconstruction time, especially for large datasets (500+ images) by avoiding computation of the Bundle Adjustment on areas that are not changing. LocalBA Graph Distance Graph-distance limit to define the Active region in the Local Bundle Adjustment strategy. (2-10) 1 Maximum Number of Matches Maximum number of matches per image pair (and per feature type). This can be useful to have a quick reconstruction overview. 0 means no limit. (0-50000) 1 Minimum Number of Matches Minimum number of matches per image pair (and per feature type). This can be useful to have a meaningful reconstruction with accurate keypoints. 0 means no limit. (0-50000) 1 Min Input Track Length Minimum track length in input of SfM (2-10) Min Observation For Triangulation Minimum number of observations to triangulate a point. Set it to 3 (or more) reduces drastically the noise in the point cloud, but the number of final poses is a little bit reduced (from 1.5% to 11% on the tested datasets). (2-10) Min Angle For Triangulation Minimum angle for triangulation. (0.1-10) 3.0 Min Angle For Landmark Minimum angle for landmark. (0.1-10) 2.0 Max Reprojection Error Maximum reprojection error. (0.1-10) 4.0 Min Angle Initial Pair Minimum angle for the initial pair. (0.1-10) 5.0 Max Angle Initial Pair Maximum angle for the initial pair. (0.1-60) 40.0 Use Only Matches From Input Folder Use only matches from the input matchesFolder parameter. Matches folders previously added to the SfMData file will be ignored. Use Rig Constraint Enable/Disable rig constraint. Force Lock of All Intrinsic Camera Parameters. Force to keep constant all the intrinsics parameters of the cameras (focal length, principal point, distortion if any) during the reconstruction. This may be helpful if the input cameras are already fully calibrated. Filter Track Forks Enable/Disable the track forks removal. A track contains a fork when incoherent matches lead to multiple features in the same image for a single track. Initial Pair A Filename of the first image (without path). Initial Pair B Filename of the second image (without path). Inter File Extension Extension of the intermediate file export. (‘.abc’, ‘.ply’) Verbose Level Verbosity level (fatal, error, warning, info, debug, trace). Output SfMData File (SfMData ) Path to the output sfmdata file (sfm.abc) Output SfMData File (Views and Poses) Path to the output sfmdata file with cameras (views and poses). (cameras.sfm) Output Folder Folder for intermediate reconstruction files and additional reconstruction information files. 保存运动推断结构所有文件的文件夹路径 将分析的特征进行匹配，以了解所有二维观测（2D observations）数据背后的几何关系，并通过所有摄像机的位姿（pose 位置和方向）和内部校准推断出刚性场景结构（三维点 3D points）。\n论文：Fast and Accurate Image Matching with Cascade Hashing for 3D Reconstruction Jian Cheng, Cong Leng, Jiaxiang Wu, Hainan Cui, Hanqing Lu. CVPR 2014 该管道是一个不断增长的重建过程（增量SfM，incremental SfM）\n它首先计算一个初始的双视图重建（two-view reconstruction），通过添加新的视图来迭代扩展。\nFuse 2-View Matches into Tracks 将双视角匹配的图像融合到轨迹中 将图像对之间的所有特征匹配融合为轨迹。每条轨迹代表空间中的一个候选点，从多个相机中可见。然而，在管道的这一步，它仍然包含许多离群值。 Initial Image Pair 初始图像对 选择最佳的初始图像对。这一选择对于最终重建的质量至关重要。所以这个 图像对 应该最大限度地增加匹配的数量和每个图像中相应特征的再分配。（this image pair should maximize the number of matches and the repartition of the corresponding features in each image.）但同时，相机之间的角度也应该足够大，以提供可靠的几何信息。 Initial 2-View Geometry 初始的双视角几何学 计算所选2幅图像之间的基本矩阵（fundamental matrix），并认为第一幅图像是坐标系的原点。 Triangulate 三角测量 用两个第一台相机的位姿，将相应的2D特征三角化为3D点。 Next Best View Selection 下一个最佳视图选择 选择所有与已经三维重建的特征有足够关联的图像。 Estimate New Cameras 估计新相机 基于这些2D-3D关联，它对这些新相机中的每一个进行切除。切除 是 RANSAC框架 下的透视-点算法（Perspective-n-Point algorithm，PnP），用来找到验证大多数特征关联的相机位姿。在每个摄像机上，都要进行非线性最小化（non-linear minimization）来完善姿势。 论文：A Novel Parametrization of the P3P-Problem for a Direct Computation of Absolute Camera Position and Orientation. Kneip, L.; Scaramuzza, D. ; Siegwart, R. CVPR 2011 论文：EPnP: An Accurate O(n) Solution to the PnP Problem. V. Lepetit and F. Moreno-Noguer and P. Fua, IJCV 2009 Triangulate 三角测量 从这些新的相机姿态中，一些轨迹会被2个或更多被切除的相机所看到，并对它们进行三角测量。 Optimize 优化 执行捆绑调整以完善一切：所有摄像机的外在参数和内在参数，以及所有三维点的位置。通过删除所有具有高重投影误差（high reprojection error）或观测值之间角度不足的观测值来过滤捆绑的调整。 Loop from 5 to 9 步骤5到9循环 由于我们对新的点进行了三角测量，就得到了更多的候选图像用于下一个最佳视图的选择，之后从步骤5到9反复进行迭代。增加摄像机，将新的二维特征三角化为三维点，并删除变得无效的三维点，直到无法定位新的视图。 位置估计器：\nacransac：Adaptive structure from motion with a contrario model estimation. Pierre Moulon, Pascal Monasse, and Renaud Marlet. ACCV 2012 ransac：Automatic homographic registration of a pair of images, with a contrario elimination of outliers. Moisan, Lionel, Pierre Moulon, and Pascal Monasse. IPOL 2012 无序图片匹配加速：Unordered feature tracking made fast and easy, Pierre Moulon and Pascal Monasse, CVMP 2012 Efficient Structure from Motion by Graph Optimization. M. Havlena, A. Torii, and T. Pajdla. ECCV 2010 Hierarchical structure-and-motion recovery from uncalibrated images. R. Toldo, R. Gherardi, M. Farenzena and A. Fusiello. CVIU 2015 sfm重建：\nMultistage SFM: Revisiting Incremental Structure from Motion, Rajvi Shah, Aditya Deshpande, P J Narayanan, 2014 1.6. Prepare Dense Scene 稠密场景 Input Setting Output Description SfMData SfMData SfMData file ImagesFolders Use images from specific folder(s). Filename should be the same or the image uid. Output File Type Output file type for the undistorted images. (jpg, png, tif, exr) 输出不失真图片的格式 Save Metadata Save projections and intrinsics information in images metadata (only for .exr images). 设定是否保存 Save Matrices Text Files Save projections and intrinsics information in text files. 设定是否保存 Correct images exposure Apply a correction on images Exposure Value 设定是否保存 Verbose Level [‘fatal’, ‘error’, ‘warning’, ‘info’, ‘debug’, ‘trace’] Undistorted images List of undistorted images. 保存不失真的图片的路径 Images Folder MVS Configuration file (desc.Node.internalFolder + ‘mvs.ini) 这个节点导出未变形的图像，这样深度图和纹理就可以在针孔图像（Pinhole images）上计算并且不会变形。\n1.7. Depth Map 深度估计 Input Setting Output Description SfMData SfMData SfMData file. Images Folder Images Folder Use images from a specific folder instead of those specify in the SfMData file. Filename should be the image uid. (Prepare Dense Scene输出的exr格式图片) Downscale Image downscale factor (1, 2, 4, 8, 16) Min View Angle Minimum angle between two views.(0.0 - 10.0) Max View Angle Maximum angle between two views. (10.0 - 120.0) SGM: Nb Neighbour Cameras Semi Global Matching: Number of neighbour cameras (1 - 100) SGM: WSH: Semi Global Matching Half-size of the patch used to compute the similarity (1 - 20) SGM: GammaC Semi Global Matching: GammaC Threshold (0 - 30) SGM: GammaP Semi Global Matching: GammaP Threshold (0 - 30) Refine: Number of samples (1 - 500) Refine: Number of Depths (1 - 100) Refine: Number of Iterations (1 - 500) Refine: Nb Neighbour Cameras Refine: Number of neighbour cameras. (1 - 20) Refine: WSH Refine: Half-size of the patch used to compute the similarity. (1 - 20) Refine: Sigma Refine: Sigma Threshold (0 - 30) Refine: GammaC Refine: GammaC Threshold. (0 - 30) Refine: GammaP Refine: GammaP threshold. (0 - 30) Refine: Tc or Rc pixel size Use minimum pixel size of neighbour cameras (Tc) or current camera pixel size (Rc) Verbose Level verbosity level (fatal, error, warning, info, debug, trace) Output Output folder for generated depth maps 对所有被SfM解析过的相机，检索每个像素的深度值。\nBlock Matching Semi-Global Matching (SGM) ：Accurate and efficient stereo processing by semi-global matching and mutual information, H. Hirschmüller. CVPR 2005 ←Meshroom使用的方法 Stereo processing by semiglobal matching and mutual information, H. Hirschmüller, 2008 ADCensus：On building an accurate stereo matching system on graphics hardware. Xing, M., Xun, S., Mingcai Z., Shaohui J., Haitao, W., Xiaopeng Z., 2011 1.8. Depth Map Filter 深度图过滤 Input Setting Output Description SfMData SfMData SfMData file Depth Map Folder Input depth map folder Min View Angle Minimum angle between two views Max View Angle Maximum angle between two views Number of Nearest Cameras Number of nearest cameras used for filtering 10 (0 - 20) Min Consistent Cameras Min Number of Consistent Cameras 3 (0 - 10) Min Consistent Cameras Bad Similarity Min Number of Consistent Cameras for pixels with weak similarity value 4 (0 - 10) Filtering Size in Pixels Filtering size in Pixels (0 - 10) Filtering Size in Pixels Bad Similarity Filtering size in pixels (0 - 10) Verbose Level verbosity level (fatal, error, warning, info, debug, trace) Filtered DepthMaps Folder Output folder for generated depth maps 过滤多个深度图中不连贯的深度图值。这就可以在开始融合Meshing节点中的所有深度图之前，过滤掉不稳定的点。确保多个相机之间的一致性。根据相似度值和相干摄像机的数量选择一个折衷方案，以保持弱支持的表面而不增加伪影。\n1.9. Meshing 网格重建 Input Setting Output Description SfMData SfMData file. Depth Maps Folder Input depth maps folder Filtered Depth Maps Folder Input filtered depth maps folder Estimate Space From SfM Estimate the 3d space from the SfM Min Observations For SfM Space Estimation Minimum number of observations for SfM space estimation. (0-100) 3 Min Observations Angle For SfM Space Estimation Minimum angle between two observations for SfM space estimation. (0-120) 10 Max Input Points Max input points loaded from depth map images (500000 - 500000000) Max Points Max points at the end of the depth maps fusion (100000 - 10000000) Max Points Per Voxel (500000 – 30000000) Min Step The step used to load depth values from depth maps is computed from maxInputPts. Here we define the minimal value for this step, so on small datasets we will not spend too much time at the beginning loading all depth values (1- 20) 2 Partitioning (singleBlock, auto) Repartition (multiResolution, regularGrid) angleFactor (0.0-200.0) 15.0 simFactor (0.0-200.0) 1.0 pixSizeMarginInitCoef (0.0-10.0) 2.0 pixSizeMarginFinalCoef (0.0-10.0) 4.0 voteMarginFactor (0.1-10.0) 4.0 contributeMarginFactor (0.0-10.0) 2.0 simGaussianSizeInit (0.0-50) 10.0 simGaussianSize (0.0-50) 0.1 minAngleThreshold (0.0-10.0) 0.01 Refine Fuse Refine depth map fusion with the new pixels size defined by angle and similarity scores. Add Landmarks To The Dense Point Cloud Add SfM Landmarks to the dense point cloud. Colorize Output Whether to colorize output dense point cloud and mesh. Save Raw Dense Point Cloud Save dense point cloud before cut and filtering. Verbose Level verbosity level (fatal, error, warning, info, debug, trace). Output Mesh Output mesh (OBJ file format). mesh.obj Output Dense Point Cloud Output dense point cloud with visibilities (SfMData file format). densePointCloud.abc 创建一个密集的场景的几何表面表示。\n3D Delaunay tetrahedralization之后，compute weights on cells and weights on facets connecting the cells。\n论文：Multi-view reconstruction preserving weakly-supported surfaces, Michal Jancosek, Tomas Pajdla, CVPR 2011 论文：Exploiting Visibility Information in Surface Reconstruction to Preserve Weakly Supported Surfaces, Michal Jancosek, Tomas Pajdla 1.10. Mesh Filtering 网格修复 Input Setting Output Description Mesh Input Mesh (OBJ file format) Keep Only the Largest Mesh Keep only the largest connected triangles group (True/False) 只保留最大的模型，默认不使用（“Keep Only The Largest Mesh”. This is disabled by default in the 2019.1.0 release to avoid that the environment is being meshed, but not the object of interest. The largest Mesh is in some cases the reconstructed background. When the object of interest is not connected to the large background mesh it will be removed. You should place your object of interest on a well structured non transparent or reflecting surface (e.g. a newspaper).） Smoothing Subset (all; surface_boundaries; surface_inner_part) Smoothing Boundaries Neighbours Neighbours of the boundaries to consider 0 (0 - 20) Smoothing Iterations 5 (0 - 50) Smoothing Lambda 1 (0 - 10) Filtering Subset (all; surface_boundaries; surface_inner_part) 筛选子集？ Filtering Iterations 1 (0 - 20) Filter Large Triangles Factor Remove all large triangles. We consider a triangle as large if one edge is bigger than N times the average edge length. Put zero to disable it. 60 (1 - 100) Filter Triangles Ratio Remove all triangles by ratio(largest edge/smallest edge). Put zero to disable it. 0 (0 - 50) Verbose Level [‘fatal’, ‘error’, ‘warning’, ‘info’, ‘debug’, ‘trace’] Output mesh Output mesh (OBJ file format) internalFolder + ‘mesh.obj 图形切割（Graph Cut）Max-Flow：优化切割体积\n论文：An Experimental Comparison of Min-Cut/Max-Flow Algorithms for Energy Minimization in Computer Vision, Yuri Boykov and Vladimir Kolmogorov. 2004 This cut represents the extracted mesh surface. 过滤表面上的不良单元。最后，对网格进行拉普拉斯滤波，以消除局部伪影。\n1.11. Texturing 纹理重建 Input Setting Output Description Images Folder Use images from a specific folder instead of those specify in the SfMData file. Filename should be the image uid. Other Input Mesh (Mesh) Optional input mesh to texture. By default, it will texture the result of the reconstruction. MVS Configuration file …/mvs.ini Input Dense Reconstruction Path to the dense reconstruction result (mesh with per vertex visibility) Texture Side Output texture size 1024, 2048, 4096, 8192, 16384 Texture Downscale Texture downscale factor1, 2, 4, 8 Texture File Type Texture File Type ‘jpg’, ‘png’, ‘tiff’, ‘exr’ Unwrap Method Method to unwrap input mesh if it does not have UV coordinates Basic (\u0026gt; 600k faces) fast and simple. Can generate multiple atlases LSCM (\u0026lt;= 600k faces): optimize space. Generates one atlas ABF (\u0026lt;= 300k faces): optimize space and stretch. Generates one atlas Use UDIM Use UDIM UV mapping. True/False. Fill Holes Fill Texture holes with plausible values True/False Padding Texture edge padding size in pixel 5 (0-100) multiBandDownscale Width of frequency bands for multiband blending 4 (0 - 8) multiBandNbContrib (MultiBand contributions) Number of contributions per frequency band for multiband blending(each frequency band also contributes to lower bands) useScroe Use triangles scores (ie. reprojection area) for multiband blending. True/False Max Nb of Images For Fusion Max number of images to combine to create the final texture (0-10) Best Score Threshold 0.0 to disable filtering based on threshold to relative best score 0.1 (0.0 - 1.0) Angle Hard Threshold 0.0 to disable angle hard threshold filtering 90 (0.0 - 180.0) Process Colorspace (sRGB; LAB; XYZ)Colorspace for the texturing internal computation (does not impact the output file colorspace) Correct Exposure Uniformize images exposeure values True/False Force Visible By All Vertices Triangle visibility is based on the union of vertices visiblity. True/False Flip Normals Option to flip face normals. It can be needed as it depends on the vertices order in triangles and the convention change from one software to another. True/False Visibility Remapping Method Method to remap visibilities from the reconstruction to the input mesh (Pull, Push, PullPush). Subdivision Target Ratio Percentage of the density of the reconstruction as the target for the subdivision(0: disable subdivision, 0.5: half density of the reconstruction; 1: full density of the reconstruction) 0.8 (0.0 - 1.0) Verbose Level verbosity level (fatal, error, warning, info, debug, trace). Output Folder Folder for output mesh: OBJ, material and texture files. Output Mesh Folder for output mesh: OBJ, material and texture files. internalFolder + ‘texturedMesh.obj Output Material Folder for output mesh: OBJ, material and texture files. internalFolder + ‘texturedMesh.mtl Output Textures Folder for output mesh: OBJ, material and texture files. internalFolder + ‘texture_*.png 如果网格没有相关的UV，它会计算出自动的UV贴图。AliceVision实现了一个基本的UV映射方法来最小化纹理空间（a basic UV mapping approach to minimize the texture space）。标准的UV映射方法是由[Levy2002]提供的。\n论文：Least Squares Conformal Maps for Automatic Texture Atlas Generation, Bruno Lévy, Sylvain Petitjean, Nicolas Ray, Jérome Maillot, Siggraph 2002 对于每个三角形，使用与每个顶点相关的可见性信息来检索纹理候选。\n过滤掉与表面没有良好角度的相机，以支持正面平行的相机，最后对像素值进行平均。\n由于使用[Burt1983]中描述的多波段混合法的一般化（a generalization of the multi-band blending described），所以在低频视野（views）中的平均比在高频中的平均要多。这种方法与[Baumberg2002]和[Allene2008]的精神是一致的。\n","permalink":"https://sqf.icu/article/c977f91a-33b5-485d-ae62-b7b077b096b6/","summary":"\u003cp\u003e目录\u003c/p\u003e\n\u003ch1 id=\"默认pipline中的组件算法\"\u003e默认Pipline中的组件算法\u003c/h1\u003e\n\u003cp\u003e参考AliceVision和meshroom程序自带说明文档\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://alicevision.org/#photogrammetry/natural_feature_extraction\"\u003eAliceVision | Photogrammetric Computer Vision Framework\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://meshroom-manual.readthedocs.io/en/latest/\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e下图是Meshroom默认pipline，其中实线连接的参数是初始设定的值；虚线连接的参数是实现设定的值。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/caf1f52a342662ab552b1998.png\"\u003e\u003c/p\u003e","title":"Meshroom各模块算法调查"},{"content":"NeRF入门介绍视频\nNeRF系列公开课01 | 基于NeRF的三维内容生成_哔哩哔哩_bilibili\nNeRF简介_哔哩哔哩_bilibili\n1. NeRF相比于三维重建的区别 一些场景的内容特别复杂, 使用三维重建效果较差, 但是NeRF渲染三维场景可以达到类似于相机拍摄的效果 没有像传统常见方式一样使用hard shape的表征方式, 而是使用soft shape. hard shape需要object segmentation mask(抠图, 把物体的背景都去掉) hard shape有boundary discontinuity(边界不连续)的问题需要解决 只使用相机和物体表面之间的ray上的很多samples做计算, 性能消耗少很多 NeRF缺点是, 目前没有很好的工具去编辑物体的颜色形状等 2. NeRF的工作原理 NeRF的工作原理简单介绍：\n体素表示: NeRF将三维空间分割成许多小的体素(小立方体). 每个体素内都采样辐射度值来表示该体素内部的颜色和透明度. 这些体素构成了场景的三维表示.\n光线采样: 为了生成图像, NeRF会从相机位置沿着每个像素位置的光线进行采样, 以便在这些位置上估计辐射度.\n辐射度估计：对于每个光线上的采样点，NeRF使用神经场模型MLP来估计该点的辐射度。它将光线上的坐标和摄像机参数作为输入，并输出辐射度值，表示了在该点的颜色和透明度。\n输入的是5维, 一个点在空间中的位置$(x,y,z)$和相机的观测方向$(\\theta,\\varphi)$←这是弧度单位(radians)中的极角(polar angle)和方位角(azimuthal angle), 由于相机的观测方向是一个单位向量, 向量大小$r=1$被省略了. 经过MLP网络, 输出是4维, 该点的RGB值和体积密度(volume occupancy density)(或者说是透明度) ← 就是辐照度(randiance). 通过将一条光线上所有采样点的辐照度(4维向量)做累加, 获得这条光线在输出图像上的像素值. 图像生成：一旦辐射度值被估计出来，NeRF可以使用这些值来合成图像。这是通过在光线上的各个采样点上插值和组合辐射度值来完成的。最终的图像是由这些采样点生成的。\n训练过程通过最小化实际观察到的图像和由NeRF预测生成的图像之间的差异来进行. 这通常使用像素级的损失函数来完成.\n2.1. NeRF和体渲染的关系 神经辐射场是将2D的输入表征成3D场景的过程\n体渲染是将真实3D场景中的很多点位投射到2D画面的过程\nNeRF使用了体渲染的方式进行训练\n光线的向量公式:\n$$\rr(t)=o+td\r$$o表示光线的起点, t表示光线到点的距离, d表示光线的方向.\n光线上取的点, 位置不是均匀分布的. 原因查看光线颜色值公式的离散采样部分. 坐标系间需要互相转换 世界坐标系(场景中物体的位置)和相机位姿(相机位置)属于外参 像素坐标系, 是投影到相机画面上的坐标 2.2. 光线的颜色 光线的颜色值公式\n$$\rC(\\mathbf{r})=\\int_{t_n}^{t_f} T(t) \\sigma(\\mathbf{r}(t)) \\mathbf{c}(\\mathbf{r}(t), \\mathbf{d}) d t, \\text { where } T(t)=\\exp \\left(-\\int_{t_n}^t \\sigma(\\mathbf{r}(s)) d s\\right)\r$$ 下面的文章解释了这个公式.\nOptical models for direct volume rendering(1995)这篇论文提出了体渲染的三种光线模型:\n下面的公式只保留了重要的过程, 详细推导过程看下面的文章.\n【论文精读】NeRF中的数学公式推导_nerf数学推导_YuhsiHu的博客-CSDN博客\n光线吸收模型 物体的粒子本身不发光, 也不反光(简单来说就是吸收它们拦截的所有光, 却不散射或发射任何光). 假设粒子是相同的球体，半径为 $\\mathrm{r}$ ,投影面积 $\\mathrm{A}=\\pi \\mathrm{r}^2$ , 设 $\\rho$ 为每单位体积的粒子数. 这个模型的传递方程是\n$$\r\\frac{\\mathrm{dI}}{\\mathrm{ds}}=-\\rho(\\mathrm{s}) \\mathrm{AI}(\\mathrm{s})=-\\tau(\\mathrm{s}) \\mathrm{I}(\\mathrm{s})\r$$ $\\mathrm{s}$ 是沿光流方向的光线的长度, $\\mathrm{I}(\\mathrm{s})$是距离 $\\mathrm{s}$ 处的光强度, $\\rho$ 是光点密度. $\\tau(\\mathrm{s})=\\rho(\\mathrm{s}) \\mathrm{A}$ 称为消光系数(在NeRF公式中表示为$\\sigma$), 反映了光被遮挡的速率. 整理并且等式两边同时积分, 最终获得这个微分方程的解(光消减的公式)\n$$\r\\mathrm{I}(\\mathrm{s})=\\mathrm{I}_0 \\exp \\left(-\\int_0^{\\mathrm{s}} \\tau(\\mathrm{t}) \\mathrm{dt}\\right)\r$$ $\\mathrm{I}_0$ 是在 $\\mathrm{s}=0$ 处的光强度, 而 $\\mathrm{T}(\\mathrm{s})=\\exp \\left(-\\int_0^{\\mathrm{s}} \\tau(\\mathrm{t}) \\mathrm{dt}\\right)$是介于 0 和 $\\mathrm{s}$ 之间的介质的透明度($\\tau(\\mathrm{t})$ 在NeRF公式中表示为$\\sigma$). 在体渲染中, 消光系数 $\\tau$ 通常称为不透明度. 光线发射模型 物体的粒子本身会发出光, 并且不吸收光(介质还可以通过外部照明的发射或反射来增加光线). 如果粒子是透明的, 但以每单位投影面积的强度 $\\mathrm{C}$ 发光. 其中的$\\tau(\\mathrm{s})$ 在NeRF公式中表示为$\\sigma$ 这个 $\\mathrm{I}(\\mathrm{s})$ 的微分方程:\n$$\r\\frac{\\mathrm{dI}}{\\mathrm{ds}}=\\mathrm{C}(\\mathrm{s}) \\rho(\\mathrm{s}) \\mathrm{A}=\\mathrm{C}(\\mathrm{s}) \\tau(\\mathrm{s})=\\mathrm{g}(\\mathrm{s})\r$$这个方程的解如下 (光发射的公式)\n$$\r\\mathrm{I}(\\mathrm{s})=\\mathrm{I}_0+\\int_0^{\\mathrm{s}} \\mathrm{g}(\\mathrm{t}) \\mathrm{dt}\r$$ $\\mathrm{I}_0$ 是 $\\mathrm{s}=0$ 处的光强度. 吸收发射模型 实际上, 空间中的粒子会遮挡入射光, 并添加自己的光. 因此, 一个现实的微分方程应该包括源项 $\\mathrm{g}(\\mathrm{s})$ 和衰减项 $\\mathrm{I}(\\mathrm{s})$ . 我们只需要将前两种模型进行简单的数值加和, 就可以得到这个模型的传递方程:\n$$\r\\frac{\\mathrm{dI}}{\\mathrm{ds}}=\\mathrm{g}(\\mathrm{s})-\\tau(\\mathrm{s}) \\mathrm{I}(\\mathrm{s})\r$$从volume边缘的 $s=0$ 积分到眼睛的 $\\mathrm{s}=\\mathrm{D}$ :\n$$\r\\mathrm{I}(\\mathrm{D}) \\exp \\left(\\int_0^{\\mathrm{D}} \\tau(\\mathrm{t}) \\mathrm{dt}\\right)-\\mathrm{I}_0=\\int_0^{\\mathrm{D}}\\left(\\mathrm{g}(\\mathrm{s}) \\exp \\left(\\int_0^{\\mathrm{s}} \\tau(\\mathrm{t}) \\mathrm{dt}\\right)\\right) \\mathrm{ds}\r$$整理得到:\n$$\r\\mathrm{I}(\\mathrm{D})=\\mathrm{I}_0 \\exp \\left(-\\int_0^{\\mathrm{D}} \\tau(\\mathrm{t}) \\mathrm{dt}\\right)+\\int_0^{\\mathrm{D}}\\left(\\mathrm{g}(\\mathrm{s}) \\exp \\left(-\\int_{\\mathrm{s}}^{\\mathrm{D}} \\tau(\\mathrm{t}) \\mathrm{dt}\\right)\\right) \\mathrm{ds}\r$$第一项表示来自背景的光, 乘以空间的透明度. 第二项是源项 $\\mathrm{g}(\\mathrm{s})$ 在每个位置 $\\mathrm{s}$ 贡献的积分, 乘以位置 $\\mathrm{s}$ 到眼睛的透明度 $\\mathrm{T}^{\\prime}(\\mathrm{s})=\\exp \\left(-\\int_{\\mathrm{s}}^{\\mathrm{D}}\\tau(\\mathrm{x})\\mathrm{dx}\\right)$ , 那么:\n$$\r\\mathrm{I}(\\mathrm{D})=\\mathrm{I}_0 \\mathrm{~T}(\\mathrm{D})+\\int_0^{\\mathrm{D}} \\mathrm{g}(\\mathrm{s}) \\mathrm{T}^{\\prime}(\\mathrm{s}) \\mathrm{ds}\r$$等式右侧第一项代表着从坐标 0 点出发经过 0 到 $\\mathrm{D}$ 的介质入射到相机的光强, 称之为背景光, 在NeRF中, 这一项考虑为 0 . 所以在NeRF 中, 这个式子化简为:\n$$\r\\mathrm{I}(\\mathrm{D})=\\int_0^{\\mathrm{D}} \\mathrm{g}(\\mathrm{s}) \\mathrm{T}^{\\prime}(\\mathrm{s}) \\mathrm{ds}=\\int_0^{\\mathrm{D}} \\mathrm{T}^{\\prime}(\\mathrm{t}) \\tau(\\mathrm{t}) \\mathrm{c}(\\mathrm{t}) \\mathrm{dt}\r$$其中 $\\mathrm{T}^{\\prime}(\\mathrm{t})=\\exp \\left(-\\int_{\\mathrm{t}}^{\\mathrm{D}} \\tau(\\mathrm{x}) \\mathrm{dx}\\right)$.\n转变为NeRF中的公式 光线的吸收发射模型和NeRF公式的坐标不同, Max的文章中相机坐标为D, 无穷远点为0, 而NeRF公式中相反. 并且, 0到无穷之间的距离中, 不是所有位置上都有介质. 所以, 可以定义近平面$t_n$和远平面$t_f$\n$$\r\\mathrm{I}(0)=\\int_{\\mathrm{t}_{\\mathrm{n}}}^{\\mathrm{t}_{\\mathrm{f}}} \\mathrm{T}^{\\prime}\\left(\\mathrm{t}_{\\mathrm{n}}, \\mathrm{t}\\right) \\tau(\\mathrm{t}) \\mathrm{c}(\\mathrm{t}) \\mathrm{dt}\r$$NeRF中把消光系数(也就是不透明度) $\\tau(\\mathrm{t})$ 叫做体积密度 $\\sigma(\\mathrm{t})$ , 那么上式可以整理为:\n$$\rI(0)=\\int_{t_n}^{t_f} T^{\\prime}\\left(t_n, t\\right) \\sigma(t) c(t) d t\r$$如果记 $\\mathrm{T}(\\mathrm{t})=\\exp \\left(\\int_{\\mathrm{t}{\\mathrm{n}}}^{\\mathrm{t}}-\\sigma(\\mathrm{t}) \\mathrm{dt}\\right)$ , 那么上式可以变成:\n$$\r\\mathrm{I}(0)=\\int_{\\mathrm{t_n}}^{\\mathrm{t_f}} \\mathrm{T}(\\mathrm{t}) \\sigma(\\mathrm{t}) \\mathrm{c}(\\mathrm{t}) \\mathrm{dt}\r$$而这一切讨论都是在固定射线的情况下, 如果这个射线是动态的, 我们还需要用 $r(t)=0+t d$ 来表示的话, 那么 $\\tau(r(t))$ 其实可以表示 在 $\\mathrm{r}$ 这条射线上, $\\mathrm{t}$ 位置的体积密度, $\\mathrm{c}(\\mathrm{r}(\\mathrm{t}), \\mathrm{d})$ 就可以表示在 $\\mathrm{r}$ 这条射线上, $\\mathrm{t}$ 位置对 $\\mathrm{d}$ 方向的光强. 那么上式可以进一步变为:\n$$\r\\mathrm{I}(0)=\\int_{\\mathrm{t_n}}^{\\mathrm{t_f}} \\mathrm{T}(\\mathrm{t}) \\sigma(\\mathrm{r}(\\mathrm{t})) \\mathrm{c}(\\mathrm{r}(\\mathrm{t}), \\mathrm{d}) \\mathrm{dt}, \\text { where } \\mathrm{T}(\\mathrm{t})=\\exp \\left(-\\int_{\\mathrm{t}{\\mathrm{n}}}^{\\mathrm{t}} \\sigma(\\mathrm{r}(\\mathrm{s})) \\mathrm{ds}\\right)\r$$因为我们研究的是 $\\mathrm{r}$ 这条射线上的光, 眼睛位置固定不变, 所以可以隐去相机位置 0 , 而添加参数 $\\mathrm{r}$ 来强调射线也是个变量, 再用 $\\mathrm{C}$ 替换掉光强 $\\mathrm{I}$ , 所以最终式子变为:\n$$\r\\mathrm{C}(\\mathrm{r})=\\int_{\\mathrm{t_n}}^{\\mathrm{t_f}} \\mathrm{T}(\\mathrm{t}) \\sigma(\\mathrm{r}(\\mathrm{t})) \\mathrm{c}(\\mathrm{r}(\\mathrm{t}), \\mathrm{d}) \\mathrm{dt}, \\text { where } \\mathrm{T}(\\mathrm{t})=\\exp \\left(-\\int_{\\mathrm{t_n}}^{\\mathrm{t}} \\sigma(\\mathrm{r}(\\mathrm{s})) \\mathrm{ds}\\right)\r$$这就是NeRF中的光线颜色值公式, 将MLP的预测值$(\\sigma,c)$带入公式. $T(t)$是光线累积量(到t点之前, 光线都没被阻碍的概率), $\\sigma(r(t))$是体素密度(光线被阻碍的概率)), $c(r(t),d)$表示在t点处粒子发出的颜色.\n而在实际训练中, 只有数百张图片, 所以连续积分需要变为离散采样. 将近远平面区间等分为 $\\mathrm{N}$ 份, 在每个小区间内取样. 把积分符号变为求和, $T(t)$ 变为 $T_i$ , $c(r(t), d)$ 变为 $c_i$ , $\\sigma(r(t)) d t$ 变为 $\\sigma_i \\delta_i$ ($\\delta_i$ 是相邻样本之间的距离), 则得到最终的离散化公式:\n$$\r\\begin{aligned}\u0026\\hat{C}(\\mathbf{r})=\\sum_{i=1}^N T_i\\left(1-\\exp \\left(-\\sigma_i \\delta_i\\right)\\right) \\mathbf{c}_i, \\text { where } T_i=\\exp \\left(-\\sum_{j=1}^{i-1} \\sigma_j \\delta_j\\right)\\\\\u0026t_i \\sim \\mathcal{U}\\left[t_n+\\frac{i-1}{N}\\left(t_f-t_n\\right), t_n+\\frac{i}{N}\\left(t_f-t_n\\right)\\right]\\end{aligned}\r$$ $t_i$ 这里是在进行分层采样(将$t_n$到$t_f$之间的距离等分为$\\mathrm{N}$块, 每一块里面随机选取一个采样点), $\\mathrm{N}$ 为采样值(设定为64或128…). 注意这里的公式是由上面的积分公式转变而来, 使用的是求积规则 (We use these samples to estimate $C(r)$ with the quadrature rule discussed in the volume rendering review by Max [Optical Models for Direct Volume Rendering]) 下面的文章公式推导更详细\nNeRF入门之体渲染 (Volume Rendering)\n3. 优化神经辐射场的方法 3.1. 高频位置编码 Positional encoding 如果直接将 $(x,y,z,θ,φ)$ 5维信息输入网络 $F_θ$ 会导致渲染在表示颜色和几何形状的高频变化方面表现不佳(细节缺失). (神经网络有个特点就是倾向于学习低频函数, 如果网络中缺少高频信息, 那么这个现象会更加明显)\n举例来说, 左图是低频函数, 右图是高频函数. 左边x轴靠得近的点, y的值也相近; 但是相同的x轴距离, 可能在高频函数上, y的值差得很远.\n解决方法:\n在5维信息输入网络之前, 使用高频函数将输入映射到高频空间, 可以帮助网络更好的拟合含有高频变化的数据. 具体做法:\n将5维数据的每一项都转换为含有高频信号的向量.\n对于每个点的$(x,y,z)$各自被映射为10个$sin$和$cos$的组合, 也就是从3个分量变成了60个分量(维度).\n$$\r\\left(x, y, z, \\ldots,\\sin \\left(2^{n-1} x\\right), \\sin \\left(2^{n-1} y\\right), \\sin \\left(2^{n-1} z\\right), \\cos \\left(2^{n-1} x\\right), \\cos \\left(2^{n-1} y\\right), \\cos \\left(2^{n-1} z\\right) )\\right.\r$$ 注意, 代码中作者在前面加上了 $(z,y,z)$ 的原值, n 取值从 1 到 10. 最终变为 63 个分量. 对于每个点上相机的观测方向 $(\\theta,\\varphi)$ (单位向量, 默认r=1)可以转变为向量 $(x,y,z)$, 并各自被映射为 4 个$sin$和$cos$的组合, 也就是从 3 个分量变成了 24 个分量. 同样的, 代码中作者加上了相机观测方向的原值, 最终变为27个分量.\n3.2. 分层采样 Hierarchical sampling 分层采样在这里说过了.\n分层采样的问题:\n直接使用公式中的体渲染积分, 需要控制采样起始点. 如果直接对全局采样, 所需要的计算消耗过大, 且采样区间的点较为稀疏. 假设使用均匀分布采样, 则直接采样效率低. 选择恰当的起始, 终止点在这里是非常重要的. 解决方法:\nNeRF使用两个网络同时进行训练 (后称 coarse 和 fine 网络 (eg: 粗网络取64个点和精细网络取128+64个点)), coarse 网络输入的点是通过对光线均匀采样得到的, 根据 coarse 网络预测的体密度值, 对光线的分布进行估计, 然后根据估计出的分布进行第二次重要性采样, 然后再把所有的采样点一起输入到 fine 网络进行预测. 具体过程请见下图.\n$$\r\\hat{C}_{c}(\\mathbf{r})=\\sum_{i=1}^{N_{c}} w_{i} c_{i} \\\\ w_{i}=T_{i}\\left(1-\\exp \\left(-\\sigma_{i} \\delta_{i}\\right)\\right) \\\\ \\hat{w}_{i}=w_{i} / \\sum_{j=1}^{N_{c}} w_{j}\r$$ $\\hat{w}_{i}$权重可以看成沿着射线的分段常数概率密度函数(Piecewise-constant PDF) 3.3. Loss NeRF使用MSE(均方误差)作为loss. 对图片上的每一个像素的颜色都进行loss计算.\n$$\r\\mathcal{L}=\\sum_{\\mathbf{r} \\in \\mathcal{R}}\\left[\\left\\|\\hat{C}_{c}(\\mathbf{r})-C(\\mathbf{r})\\right\\|_{2}^{2}+\\left\\|\\hat{C}_{f}(\\mathbf{r})-C(\\mathbf{r})\\right\\|_{2}^{2}\\right]\r$$ $\\hat{C}_{c}$是粗网络的颜色, $\\hat{C}_{f}$是精细网络的颜色. 4. 网络结构 5. 评价指标 PSNR: Peak Signal to Noise Ratio 峰值信噪比\n$$\r\\mathrm{PSNR}=10 \\times \\lg \\left(\\frac{\\text { MaxValue }^{2}}{\\mathrm{MSE}}\\right)\r$$ MSE: 渲染图和原图每个像素的每个通道都做均方误差. 值越大越好, MaxValue 为像素值的最大取值, 为255. SSIM: structural similarity 图片结构相似性算法.\n$$\r\\begin{array}{l}\\operatorname{SSIM}(\\mathbf{x}, \\mathbf{y})=[l(\\mathbf{x}, \\mathbf{y})]^{\\alpha} \\cdot[c(\\mathbf{x}, \\mathbf{y})]^{\\beta} \\cdot[s(\\mathbf{x}, \\mathbf{y})]^{\\gamma} \\\\\\\\l(\\mathbf{x}, \\mathbf{y})=\\frac{2 \\mu_{x} \\mu_{y}+C_{1}}{\\mu_{x}^{2}+\\mu_{y}^{2}+C_{1}} \\longrightarrow \\text { 亮度 } \\\\\\\\c(\\mathbf{x}, \\mathbf{y})=\\frac{2 \\sigma_{x} \\sigma_{y}+C_{2}}{\\sigma_{x}^{2}+\\sigma_{y}^{2}+C_{2}} \\longrightarrow \\text { 对比度 } \\\\\\\\s(\\mathbf{x}, \\mathbf{y})=\\frac{\\sigma_{x y}+C_{3}}{\\sigma_{x} \\sigma_{y}+C_{3}} \\longrightarrow \\text { 结构 } \\\\\\\\\\operatorname{SSIM}(\\mathbf{x}, \\mathbf{y})=\\frac{\\left(2 \\mu_{x} \\mu_{y}+C_{1}\\right)\\left(2 \\sigma_{x y}+C_{2}\\right)}{\\left(\\mu_{x}^{2}+\\mu_{y}^{2}+C_{1}\\right)\\left(\\sigma_{x}^{2}+\\sigma_{y}^{2}+C_{2}\\right)}\\end{array}\r$$ 值越大越好, NeRF中$\\alpha \\beta \\gamma$系数都为1; $\\mu_x$为图片的均值; $\\sigma_x$为图片的方差; $\\sigma_{xy}$为两张图片的协方差; C1、C2、C3为常数, 避免分母接近于0时造成的不稳定性. 在实际应用中, 可以利用滑动窗口将图像分块, 考虑到窗口形状对分块的影响, 可以采用高斯 加权计算每一窗口的均值、方差以及协方差, 然后计算对应块的结构相似度SSIM, 最后将平均值作为两图像的结构相似性度量, 即平均结构相似性SSIM. LPIPS\n$$\rd\\left(x, x_{0}\\right)=\\sum_{l} \\frac{1}{H_{l} W_{l}} \\sum_{h, w}\\left\\|w_{l} \\odot\\left(\\hat{y}_{h w}^{l}-\\hat{y}_{0 h w}^{l}\\right)\\right\\|_{2}^{2}\r$$ 学习感知图像相似度, 数值越小表示图像的相似性越高. ","permalink":"https://sqf.icu/article/f4f45fdf-1826-48da-b1e9-641c5570e326/","summary":"\u003cp\u003eNeRF入门介绍视频\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://www.bilibili.com/video/BV1d34y1n7fn\"\u003eNeRF系列公开课01 | 基于NeRF的三维内容生成_哔哩哔哩_bilibili\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://www.bilibili.com/video/BV1Qd4y1r7ZX/?spm_id_from=333.337.search-card.all.click\u0026amp;vd_source=0847973121d4fdd8364284ef7353ef09\"\u003eNeRF简介_哔哩哔哩_bilibili\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"1-nerf相比于三维重建的区别\"\u003e1. NeRF相比于三维重建的区别\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e一些场景的内容特别复杂, 使用三维重建效果较差, 但是NeRF渲染三维场景可以达到类似于相机拍摄的效果\u003c/li\u003e\n\u003cli\u003e没有像传统常见方式一样使用hard shape的表征方式, 而是使用soft shape.\n\u003cul\u003e\n\u003cli\u003ehard shape需要object segmentation mask(抠图, 把物体的背景都去掉)\u003c/li\u003e\n\u003cli\u003ehard shape有boundary discontinuity(边界不连续)的问题需要解决\u003c/li\u003e\n\u003cli\u003e只使用相机和物体表面之间的ray上的很多samples做计算, 性能消耗少很多\u003c/li\u003e\n\u003cli\u003eNeRF缺点是, 目前没有很好的工具去编辑物体的颜色形状等\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"2-nerf的工作原理\"\u003e2. NeRF的工作原理\u003c/h1\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/04cbb56c2fb8f4c35e5369b6.png\"\u003e\u003c/p\u003e","title":"NeRF原理介绍"},{"content":"1. 安装meshroom git clone --recursive git://github.com/alicevision/meshroom cd meshroom git checkout v2021.1.0 # \u0026lt;- 版本必须和Alicevision的版本相同 pip install -r requirements.txt 2. 不编译AliceVision使用meshroom 下载一个合适的 release 版本 Checkout corresponding Meshroom (ui) version/tag to avoid versions incompatibilities LD_LIBRARY_PATH=~/foo/Meshroom-2021.1.0/aliceVision/lib/ PATH=$PATH:~/foo/Meshroom-2021.1.0/aliceVision/bin/ PYTHONPATH=$PWD python3 meshroom/ui #meshroom alicevision export LD_LIBRARY_PATH=/algorithm/xxx/meshroom_save/Meshroom-2021.1.0-av2.4.0-centos7-cuda10.2/aliceVision/lib:$LD_LIBRARY_PATH export PATH=/algorithm/xxx/meshroom_save/Meshroom-2021.1.0-av2.4.0-centos7-cuda10.2/aliceVision/bin:$PATH 安装cx_Freeze (不打包项目，不用setup.py就不装)\n~~pip3 install --upgrade pip pip install -i https://marcelotduarte.github.io/packages/ cx_Freeze python -m pip install cx_Freeze --upgrade~~ conda install -c conda-forge cx_freeze 3. 命令行运行Meshroom 各模块的数据保存在参数cache对应的文件夹下 export PYTHONPATH=$PWD python bin/meshroom_batch --input /algorithm/xxx/graphics_primitives/ex_dataset_5/BuOu/images --cache /algorithm/xxx/meshroom_save/MeshroomCache_BuOu_command_test_1 /algorithm/xxx/graphics_primitives/ex_dataset_5/SaiChe/images_png 问题，运行报错：\n[2022-06-02 16:01:56,160][WARNING] == The following \u0026#34;submitters\u0026#34; plugins could not be loaded == * simpleFarmSubmitter: No module named \u0026#39;simpleFarm\u0026#39; ... 解决方法，可以无视\nhttps://github.com/alicevision/meshroom/issues/1510\n在 ./meshroom/meshroom/submitters/simpleFarmSubmitter.py 注释import simpleFarm\n问题，运行报错：\n(meshroom) xxx@3090_a:meshroom$ python bin/meshroom_batch --input /algorithm/xxx/graphics_primitives/ex_dataset_5/BuOu/images --output /algorithm/xxx/meshroom_save/Meshroom_BuOu_command_test_1 --cache /algorithm/xxx/meshroom_save/MeshroomCache_BuOu_command_test_1 Program called with the following parameters: * allowSingleView = 1 * allowedCameraModels = \u0026#34;pinhole,radial1,radial3,brown,fisheye4,fisheye1,3deanamorphic4,3deradial4,3declassicld\u0026#34; * defaultCameraModel = \u0026#34;\u0026#34; (default) * defaultFieldOfView = 45 * defaultFocalLengthPix = -1 (default) * defaultIntrinsic = \u0026#34;\u0026#34; (default) * groupCameraFallback = Unknown Type \u0026#34;20EGroupCameraFallback\u0026#34; * imageFolder = \u0026#34;\u0026#34; (default) * input = \u0026#34;/tmp/tmp8xqjy59g/CameraInit/f9436e97e444fa71a05aa5cf7639b206df8ba282/viewpoints.sfm\u0026#34; * output = \u0026#34;/tmp/tmp8xqjy59g/CameraInit/f9436e97e444fa71a05aa5cf7639b206df8ba282/cameraInit.sfm\u0026#34; * sensorDatabase = \u0026#34;\u0026#34; * useInternalWhiteBalance = 1 * verboseLevel = \u0026#34;info\u0026#34; * viewIdMethod = Unknown Type \u0026#34;N11aliceVision9sfmDataIO13EViewIdMethodE\u0026#34; * viewIdRegex = \u0026#34;.*?(\\d+)\u0026#34; (default) [16:23:28.919566][fatal] 3deanamorphic4 Traceback (most recent call last): File \u0026#34;bin/meshroom_batch\u0026#34;, line 165, in \u0026lt;module\u0026gt; views, intrinsics = cameraInit.nodeDesc.buildIntrinsics(cameraInit, filesByType.images) File \u0026#34;/algorithm/xxx/meshroom_save/meshroom/meshroom/nodes/aliceVision/CameraInit.py\u0026#34;, line 311, in buildIntrinsics raise RuntimeError(\u0026#39;CameraInit failed with error code {}.\\nCommand was: \u0026#34;{}\u0026#34;.\\n\u0026#39;.format( RuntimeError: CameraInit failed with error code 1. Command was: \u0026#34;aliceVision_cameraInit --sensorDatabase \u0026#34;\u0026#34; --defaultFieldOfView 45.0 --groupCameraFallback folder --allowedCameraModels pinhole,radial1,radial3,brown,fisheye4,fisheye1,3deanamorphic4,3deradial4,3declassicld --useInternalWhiteBalance True --viewIdMethod metadata --verboseLevel info --output \u0026#34;/tmp/tmp8xqjy59g/CameraInit/f9436e97e444fa71a05aa5cf7639b206df8ba282/cameraInit.sfm\u0026#34; --allowSingleView 1 --input \u0026#34;/tmp/tmp8xqjy59g/CameraInit/f9436e97e444fa71a05aa5cf7639b206df8ba282/viewpoints.sfm\u0026#34;\u0026#34;. 解释：The alicevision version and meshroom version do not match. Try installing the latest alicevision from the develop branch 解决：使用相同版本的alicevision和meshroom 下载发行版meshroom v2021.1.0 使用其中的Alicevision\ngit clone --recursive git://github.com/alicevision/meshroom git checkout v2021.1.0 4. 自定义pipline 在GUI界面修改pipline，保存project（.mg文件） 命令行调用的时候增加参数-p /your/path/to/project.mg 5. 需要输出的结果 需要的结果\nStructureFromMotion\n./StructureFromMotion/*/sfm.abc\nDepthMapFilter 计算深度图估计\n./DepthMapFilter//_depthMap.exr\n./DepthMapFilter//_depthMap.png\nMeshing 网格模型\n网格模型 ./Meshing/*/mesh.obj\n点云 ./Meshing/*/densePointCloud.abc\nMeshFiltering 网格修复后的模型\n网格模型 ./MeshFiltering/*/mesh.obj\nTexturing 纹理映射\n./Texturing/*/texturedMesh.obj\n./Texturing/*/texturedMesh.mtl\n./Texturing//.png\n06_06 meshroom cache\ntankandtemples\nBigBIRD_20samples\ncustom_data\nMeshroomCache_custom_data_ZhouXiaoHei_fps\ndtu_images\nMeshroomCache_dtu_images_scan\n使用的图片数据\n/algorithm/chenshundong/mvs_reconstruction_dataset\nBigbird rgb_higher 3m_high_tack_spray_adhesive sift特征提取算法重建模失败， 使用akaze, akaze也不行 tankandtemp train dta_images images custom_data 稠密重建文件结构和格式\n/algorithm/chenshundong/mvs_reconstruction_outputs/ colmap/ # COLMAP 稀疏重建的结果 dataset/smaple/ colmap_sparse # COLMAP 格式的SfM结果 colmap_text # txt 格式的SfM结果 openmvg/ # OpenMVG 稀疏重建的结果 dataset/smaple/ reconstruction_sequential/sfm_data.bin # OpenMVG 原始的SfM结果 openmvs_format/ # 转为 OpenMVS 格式的结果 colmap_format_text/ # 转为 COLMAP 格式的结果 限制cpu参与计算的核心\ntaskset -c [core number start]-[core number end] python xxx.py 6. 单独运行各node 看运行的log文件可以找到每个node的命令\n","permalink":"https://sqf.icu/article/94a376b3-4670-4883-a26f-d0466fc57e0e/","summary":"\u003ch1 id=\"1-安装meshroom\"\u003e1. 安装meshroom\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone --recursive git://github.com/alicevision/meshroom\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd meshroom\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit checkout v2021.1.0 \u003cspan style=\"color:#75715e\"\u003e# \u0026lt;- 版本必须和Alicevision的版本相同\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip install -r requirements.txt\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"2-不编译alicevision使用meshroom\"\u003e2. 不编译AliceVision使用meshroom\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e下载一个合适的 \u003ca href=\"https://github.com/alicevision/meshroom/releases\"\u003erelease\u003c/a\u003e 版本\u003c/li\u003e\n\u003cli\u003eCheckout corresponding Meshroom (ui) version/tag to avoid versions incompatibilities\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eLD_LIBRARY_PATH=~/foo/Meshroom-2021.1.0/aliceVision/lib/ PATH=$PATH:~/foo/Meshroom-2021.1.0/aliceVision/bin/ PYTHONPATH=$PWD python3 meshroom/ui\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#meshroom alicevision\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport LD_LIBRARY_PATH\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e/algorithm/xxx/meshroom_save/Meshroom-2021.1.0-av2.4.0-centos7-cuda10.2/aliceVision/lib:$LD_LIBRARY_PATH\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport PATH\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e/algorithm/xxx/meshroom_save/Meshroom-2021.1.0-av2.4.0-centos7-cuda10.2/aliceVision/bin:$PATH\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e安装cx_Freeze (不打包项目，不用setup.py就不装)\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~~pip3 install --upgrade pip\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip install -i https://marcelotduarte.github.io/packages/ cx_Freeze\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython -m pip install cx_Freeze --upgrade~~\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econda install -c conda-forge cx_freeze\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":"命令行使用meshroom"},{"content":"纹理映射 纹理映射 (Texture Mapping) 是一种将物体空间坐标点转化为纹理坐标，进而从纹理上获取对应点的值，以增强着色细节的方法。\n左：网格模型；右：纹理映射后的模型\n纹理映射有以下四个步骤，但并不是每个都要使用，只是体现纹理映射可以被灵活操控，以获得我们想要的效果。\n1. 投影映射(Projector And Mapping) 投影映射是将三维的空间坐标点转化为二维的纹理坐标点，方法有两种：\nProjector\nProjector有4种投影方式Plane、Cubic、Cylindrical和Spherical\nUV Mapping\nProjector 只适用于简单情况，对于更复杂的几何体贴图，往往需要用到 UV Mapping：用于将 3 维模型中的每个顶点与 2 维纹理坐标一一对应。\n2. 变换函数(Corresponder Function) 2.1. 坐标范围处理 此时得到的有可能是 [0.25,0.3] 这种在 [0,1] 范围内的值，但也有可能超出了 [0,1] 范围，那么需要对范围外的值进行处理，一般有以下几种方法：Repeat、Mirror、Clamp 和 Border。\n2.2. 坐标自由变换 除了对这些超出范围的 uv 值处理，还可以对其施加“变换”，比如旋转，平移，缩放，比如想让纹理随着时间运动起来，那么就可以逐帧变换 uv 值\n但要注意的是：对 uv 坐标施加的变换矩阵，往往是实际想要变换的逆矩阵\n如：若想让纹理向右偏移 0.5 单位，那么则应该是 u – 0.5 而不是 u + 0.5。就好比是一个窗口去看这张纹理，uv 就是窗口，窗口向左移动，看起来就是纹理向右移动\n2.3. 转到纹理空间 在对 uv 进行合理变换之后，其范围都落到了 [0,1]，再分别乘以纹理实际的宽高，可得到纹理坐标。比如 uv 坐标为 [0.25,0.3]，纹理的宽高为 [256,256]，那么相乘可得到 [64,76.8]，出现了小数。\n3. 纹理采样(Texture Sampling) 屏幕或者画布上的一个单元：pixel。 纹理上的一个单元：texel。 设想一种特殊情况，我们要渲染的物体正面对着我们，刚好画布尺寸与纹理尺寸一致，比如都是 512*512，那么在获取每个 pixel 对应 texel 值时，刚好就能得到整数的纹理坐标，只需要每个 texel 逐个读取即可，不用考虑什么采样与重建。\n而实际中，我们会面临纹理过大或者过小两种情况。分两种情况来讨论：\n采样原理 纹理分辨率过小，需要放大 (Magnification)\n上采样涉及到重建和采样，重建时需要选择滤波器 (filter)：\n最邻近采样 (nearest neighbor)：类似 box 滤波器 双线性采样 (bilinear)：类似 tent 滤波器 三次卷积采样 (cubic convolution)：类似 sinc 滤波器的截断近似，因为 sinc 本身是最理想的滤波器，但是宽度是无限，无法实际使用 利用 GPU 的双线性插值特性，实现不同的上采样纹理插值:\nhttps://zhuanlan.zhihu.com/p/369977849\n纹理分辨率过大，需要缩小 (Minification)\n将高分辨率的纹理贴到低分辨率的画布，即一个 pixel 覆盖了多个 texel。\n纹理采样抗锯齿 在放大的情况进行混合时，只考虑了周围四个 texel 的值进行混合，而在缩小的情况中，一个 pixel 覆盖的 texel，个数往往不只 4 个，所以容易出现锯齿。 需要对纹理进行预处理，建立一种数据结构，在采样时尽可能对 pixel 覆盖的 texel 区域的平均值进行估计。 三种抗锯齿的方法 Mipmapping Summed-Area Table（SAT） 各向异性过滤 (Anisotropic Filtering) Texture Representation 纹理表现形式\n有一些方法可以优化处理纹理时的性能\n纹理合图(texture atlas) 一般使用这个。 一般程序读取模型的时候，使用的是白模（.obj文件）和纹理合图（.png文件） 纹理数组(texture array) 无绑定纹理(bindless texture) 4. 纹理转换 在通过纹理采样获取纹理值后，并不一定直接将纹理值作为颜色使用，还有其他用途，如在 Normal Mapping 中当作法向量使用，在 Bump Mapping 中当作高度偏移使用，所以还需要对纹理值进行相应的转换。\n5. 最新论文进展 meshroom使用的方法 Lévy B, Petitjean S, Ray N, et al. Least squares conformal maps for automatic texture atlas generation[J]. ACM transactions on graphics (TOG), 2002, 21(3): 362-371. UVAtlas - isochart texture atlasing(微软 2004持续更新) Zhou K, Synder J, Guo B, et al. Iso-charts: stretch-driven mesh parameterization using spectral analysis[C]//Proceedings of the 2004 Eurographics/ACM SIGGRAPH symposium on Geometry processing. 2004: 45-54. https://github.com/Microsoft/UVAtlas AtlasNet CVPR2018 ADOBE Groueix T, Fisher M, Kim V G, et al. A papier-mâché approach to learning 3d surface generation[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2018: 216-224.\n开源python：https://github.com/ThibaultGROUEIX/AtlasNet\nTexture Fields CVPR2019 Oechsle M, Mescheder L, Niemeyer M, et al. Texture fields: Learning texture representations in function space[C]//Proceedings of the IEEE/CVF International Conference on Computer Vision. 2019: 4531-4540.\n开源python：https://github.com/syb7573330/im2avatar\nXiang CVPR2021 Xiang F, Xu Z, Hasan M, et al. Neutex: Neural texture mapping for volumetric neural rendering[C]//Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2021: 7119-7128.\n开源python：https://github.com/fbxiang/NeuTex\nWei ICCV2021 Wei X, Chen Z, Fu Y, et al. Deep Hybrid Self-Prior for Full 3D Mesh Generation[C]//Proceedings of the IEEE/CVF International Conference on Computer Vision. 2021: 5805-5814.\n开源python：https://github.com/weixk2015/DHSP3D\n参考资料 SLAM texture\n图形学基础 - 纹理 - 纹理映射流程\n图形学基础 - 纹理 - 纹理映射盘点\n更详细：\n六.纹理（Texturing）\n","permalink":"https://sqf.icu/article/3c219494-a951-4b97-b550-04cfd5fef307/","summary":"\u003ch1 id=\"纹理映射\"\u003e纹理映射\u003c/h1\u003e\n\u003cp\u003e纹理映射 (Texture Mapping) 是一种将物体空间坐标点转化为纹理坐标，进而从纹理上获取对应点的值，以增强着色细节的方法。\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"左：网格模型；右：纹理映射后的模型\" loading=\"lazy\" src=\"/media/020c3fb762aaf54101d91ef98f4b102abefb07456447298921ded598835040d4.jpg\"\u003e\u003c/p\u003e\n\u003cp\u003e左：网格模型；右：纹理映射后的模型\u003c/p\u003e\n\u003cp\u003e纹理映射有以下四个步骤，但并不是每个都要使用，只是体现纹理映射可以被灵活操控，以获得我们想要的效果。\u003c/p\u003e","title":"三维重建纹理映射调研"},{"content":"0. 需求 修改meshroom未修改稠密点云的输出格式，需要在alicevision项目编译前修改代码 AliceVision/src/software/pipeline# vim main_meshing.cpp\nif(saveRawDensePointCloud) { ALICEVISION_LOG_INFO(\u0026#34;Save dense point cloud before cut and filtering.\u0026#34;); StaticVector\u0026lt;StaticVector\u0026lt;int\u0026gt;\u0026gt; ptsCams; delaunayGC.createPtsCams(ptsCams); sfmData::SfMData densePointCloud; createDenseSfMData(sfmData, mp, delaunayGC._verticesCoords, ptsCams, densePointCloud); removeLandmarksWithoutObservations(densePointCloud); if(colorizeOutput) sfmData::colorizeTracks(densePointCloud); sfmDataIO::Save(densePointCloud, (outDirectory/\u0026#34;densePointCloud_raw.abc\u0026#34;).string(), sfmDataIO::ESfMData::ALL_DENSE); } // 修改 densePointCloud_raw.abc -\u0026gt; densePointCloud_raw.ply 1. Nvidia docker安装AliceVision host克隆alicevision项目 git clone --recursive https://github.com/alicevision/AliceVision.git cd AliceVision/ \u0026amp;\u0026amp; git checkout v2.4.0 mkdir build \u0026amp;\u0026amp; cd build cmake -DCMAKE_BUILD_TYPE=Release -DALICEVISION_USE_ALEMBIC=ON .. 装组件 参考AliceVision/CMakeLists.txt获得各组件的版本 下载编译或apt-get安装 -- Boost 1_76 found. 编译 -- OpenEXR found. (Version 2.5.8) 编译 可选： libjpeg-turbo-2.1.1 编译 -- OpenImageIO found. apt-get install libopenimageio-dev -- eigen3 3.4.0 编译（可选） -- git clone ceres-solver 编译 apt-get install libgoogle-glog-dev libgflags-dev libatlas-base-dev libeigen3-dev libsuitesparse-dev apt-get install libmetis-dev liblapack-dev libcxsparse3 libgflags-dev libgtest-dev -- geogram-1.7.6 编译 apt-get install libxinerama-dev libxcursor-dev apt-get install libglfw3 libglfw3-dev xlibmesa-glu-dev # https://stackoverflow.com/questions/8321628/compiling-error-cannot-find-lglu-and-lgl-in-kubuntu-linux -- alembic 编译 apt-get install zlib1g-dev make 编译 出现error,修改问题部分 make install 2. AliceVision docker安装AliceVision 下载docker image\ndocker pull alicevision/alicevision-deps:cuda10.2-ubuntu18.04 克隆项目\ngit clone --recursive https://github.com/alicevision/AliceVision.git cd AliceVision/ \u0026amp;\u0026amp; git checkout v2.4.0 mkdir build \u0026amp;\u0026amp; cd build 安装依赖, 参考AliceVision/CMakeLists.txt获得各组件的版本\n-- zlib 1.2.11 编译 编译项目\nexport AV_DEV=/opt/AliceVision_git \u0026amp;\u0026amp; \\ export AV_INSTALL=/opt/AliceVision_install \u0026amp;\u0026amp; \\ cmake -DCMAKE_BUILD_TYPE=Release -DALICEVISION_USE_ALEMBIC=ON \\ -DOPENIMAGEIO_LIBRARY_DIR_HINTS:PATH=/opt/AliceVision_install/lib/ \\ -DOPENIMAGEIO_INCLUDE_DIR:PATH=/opt/AliceVision_install/include/ \\ -DOPENEXR_HOME:PATH=/opt/AliceVision_install/include/OpenEXR \\ -DGEOGRAM_INSTALL_PREFIX:PATH=/opt/AliceVision_install/lib \\ -DGEOGRAM_INCLUDE_DIR:PATH=/opt/AliceVision_install/include/geogram1 \\ .. make 编译\n出现error,修改问题部分 make install\n3. 结果 用meshroom的cache测试结果，获得raw dense point cloud.ply文件。\naliceVision_meshing --input /dataset/algorithm/xxx/meshroom_save/06_03_meshroom_cache_result/MeshroomCache_dtu_images_scan12_sift/StructureFromMotion/ab427438bb1653cf7294c95b53293706552114b5/sfm.abc \\ --depthMapsFolder /dataset/algorithm/xxx/meshroom_save/06_03_meshroom_cache_result/MeshroomCache_dtu_images_scan12_sift/DepthMapFilter/3cf9ff40f09181afd9e7f29a2b0d2f0b876571c8/ \\ --estimateSpaceFromSfM True --estimateSpaceMinObservations 3 --estimateSpaceMinObservationAngle 10 --maxInputPoints 50000000 --maxPoints 5000000 --maxPointsPerVoxel 1000000 --minStep 2 \\ --partitioning singleBlock --repartition multiResolution --angleFactor 15.0 --simFactor 15.0 --pixSizeMarginInitCoef 2.0 --pixSizeMarginFinalCoef 4.0 --voteMarginFactor 4.0 \\ --contributeMarginFactor 2.0 --simGaussianSizeInit 10.0 --simGaussianSize 10.0 --minAngleThreshold 1.0 --refineFuse True --helperPointsGridSize 10 --nPixelSizeBehind 4.0 --fullWeight 1.0 \\ --voteFilteringForWeaklySupportedSurfaces True --addLandmarksToTheDensePointCloud False --invertTetrahedronBasedOnNeighborsNbIterations 10 --minSolidAngleRatio 0.2 \\ --nbSolidAngleFilteringIterations 2 --colorizeOutput False --maxNbConnectedHelperPoints 50 --saveRawDensePointCloud True --exportDebugTetrahedralization False --seed 0 --verboseLevel info \\ --outputMesh /root/output/MeshroomCache_dtu_images_scan12_sift/mesh.obj --output /root/output/MeshroomCache_dtu_images_scan12_sift/densePointCloud.ply 上面两种方式都可以在--colorizeOutput False 的时候生成未过滤的稠密点云，但是数量小于10w（其他项目生成的稠密点云在100w以上），使用--colorizeOutput True 会报错：\n报错\n方法1报错： Compute scene structure color 0% 10 20 30 40 50 60 70 80 90 100% |----|----|----|----|----|----|----|----|----|----| Abnormal program termination: function terminate() was called aliceVision_meshing: /build/openimageio-l3oG0b/openimageio-2.1.12.0~dfsg0/src/include/OpenImageIO/unordered_map_concurrent.h:434: OpenImageIO_v2_1::unordered_map_concurrent\u0026lt;KEY, VALUE, HASH, PRED, BINS, BINMAP\u0026gt;::Bin::~Bin() [with KEY = OpenImageIO_v2_1::ustring; VALUE = OpenImageIO_v2_1::intrusive_ptr\u0026lt;OpenImageIO_v2_1::pvt::ImageCacheFile\u0026gt;; HASH = OpenImageIO_v2_1::ustringHash; PRED = std::equal_to\u0026lt;OpenImageIO_v2_1::ustring\u0026gt;; long unsigned int BINS = 64; BINMAP = tsl::robin_map\u0026lt;OpenImageIO_v2_1::ustring, OpenImageIO_v2_1::intrusive_ptr\u0026lt;OpenImageIO_v2_1::pvt::ImageCacheFile\u0026gt;, OpenImageIO_v2_1::ustringHash\u0026gt;]: Assertion `m_nlocks == 0\u0026#39; failed. ./run.sh: line 1: 27 Aborted (core dumped) aliceVision_meshing --input /dataset/algorithm/xxx/meshroom_save/06_03_meshroom_cache_result/MeshroomCache_dtu_images_scan12_sift/StructureFromMotion/ab427438bb1653cf7294c95b53293706552114b5/sfm.abc --depthMapsFolder /dataset/algorithm/xxx/meshroom_save/06_03_meshroom_cache_result/MeshroomCache_dtu_images_scan12_sift/DepthMapFilter/3cf9ff40f09181afd9e7f29a2b0d2f0b876571c8/ --estimateSpaceFromSfM True --estimateSpaceMinObservations 3 --estimateSpaceMinObservationAngle 10 --maxInputPoints 50000000 --maxPoints 5000000 --maxPointsPerVoxel 1000000 --minStep 2 --partitioning singleBlock --repartition multiResolution --angleFactor 15.0 --simFactor 15.0 --pixSizeMarginInitCoef 2.0 --pixSizeMarginFinalCoef 4.0 --voteMarginFactor 4.0 --contributeMarginFactor 2.0 --simGaussianSizeInit 10.0 --simGaussianSize 10.0 --minAngleThreshold 1.0 --refineFuse True --helperPointsGridSize 10 --nPixelSizeBehind 4.0 --fullWeight 1.0 --voteFilteringForWeaklySupportedSurfaces True --addLandmarksToTheDensePointCloud False --invertTetrahedronBasedOnNeighborsNbIterations 10 --minSolidAngleRatio 0.2 --nbSolidAngleFilteringIterations 2 --colorizeOutput True --maxNbConnectedHelperPoints 50 --saveRawDensePointCloud True --exportDebugTetrahedralization False --seed 0 --verboseLevel info --outputMesh /root/output/MeshroomCache_dtu_images_scan12_sift/mesh.obj --output /root/output/MeshroomCache_dtu_images_scan12_sift/densePointCloud.ply 方法2报错： Compute scene structure color 0% 10 20 30 40 50 60 70 80 90 100% |----|----|----|----|----|----|----|----|----|----| Abnormal program termination: function terminate() was called Abnormal program termination: received signal 11 (Segmentation fault) ","permalink":"https://sqf.icu/article/08147f25-5e09-4422-8089-084ef2dd020f/","summary":"\u003ch1 id=\"0-需求\"\u003e0. 需求\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e修改meshroom未修改稠密点云的输出格式，需要在alicevision项目编译前修改代码\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eAliceVision/src/software/pipeline# vim main_meshing.cpp\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-cpp\" data-lang=\"cpp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(saveRawDensePointCloud)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ALICEVISION_LOG_INFO(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Save dense point cloud before cut and filtering.\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  StaticVector\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eStaticVector\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e ptsCams;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  delaunayGC.createPtsCams(ptsCams);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  sfmData\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eSfMData densePointCloud;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  createDenseSfMData(sfmData, mp, delaunayGC._verticesCoords, ptsCams, densePointCloud);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  removeLandmarksWithoutObservations(densePointCloud);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(colorizeOutput)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    sfmData\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003ecolorizeTracks(densePointCloud);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  sfmDataIO\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eSave(densePointCloud, (outDirectory\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;densePointCloud_raw.abc\u0026#34;\u003c/span\u003e).string(), sfmDataIO\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eESfMData\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eALL_DENSE);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 修改 densePointCloud_raw.abc -\u0026gt; densePointCloud_raw.ply\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"1-nvidia-docker安装alicevision\"\u003e1. Nvidia docker安装AliceVision\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003ehost克隆alicevision项目\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone --recursive https://github.com/alicevision/AliceVision.git\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd AliceVision/ \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e git checkout v2.4.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir build \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e cd build\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecmake -DCMAKE_BUILD_TYPE\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eRelease -DALICEVISION_USE_ALEMBIC\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eON ..\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e装组件\u003c/li\u003e\n\u003c/ul\u003e\n\u003col\u003e\n\u003cli\u003e参考\u003ccode\u003eAliceVision/CMakeLists.txt\u003c/code\u003e获得各组件的版本\u003c/li\u003e\n\u003cli\u003e下载编译或apt-get安装\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-- Boost 1_76 found. 编译\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-- OpenEXR found. \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eVersion 2.5.8\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e 编译\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t可选： libjpeg-turbo-2.1.1 编译\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-- OpenImageIO found. \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\tapt-get install libopenimageio-dev\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-- eigen3 3.4.0 编译（可选）\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-- git clone ceres-solver 编译\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\tapt-get install libgoogle-glog-dev libgflags-dev libatlas-base-dev libeigen3-dev libsuitesparse-dev\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\tapt-get install libmetis-dev liblapack-dev libcxsparse3 libgflags-dev libgtest-dev\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-- geogram-1.7.6 编译\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\tapt-get install libxinerama-dev libxcursor-dev\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\tapt-get install libglfw3 libglfw3-dev xlibmesa-glu-dev\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e# https://stackoverflow.com/questions/8321628/compiling-error-cannot-find-lglu-and-lgl-in-kubuntu-linux\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-- alembic 编译\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\tapt-get install zlib1g-dev\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003emake 编译\n\u003cul\u003e\n\u003cli\u003e出现error,修改问题部分\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003emake install\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"2-alicevision-docker安装alicevision\"\u003e2. AliceVision docker安装AliceVision\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e下载docker image\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edocker pull alicevision/alicevision-deps:cuda10.2-ubuntu18.04\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e克隆项目\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone --recursive https://github.com/alicevision/AliceVision.git\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd AliceVision/ \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e git checkout v2.4.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir build \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e cd build\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e安装依赖, 参考\u003ccode\u003eAliceVision/CMakeLists.txt\u003c/code\u003e获得各组件的版本\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-- zlib 1.2.11 编译\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e编译项目\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport AV_DEV\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e/opt/AliceVision_git \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport AV_INSTALL\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e/opt/AliceVision_install \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecmake -DCMAKE_BUILD_TYPE\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eRelease -DALICEVISION_USE_ALEMBIC\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eON \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e -DOPENIMAGEIO_LIBRARY_DIR_HINTS:PATH\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e/opt/AliceVision_install/lib/ \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e -DOPENIMAGEIO_INCLUDE_DIR:PATH\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e/opt/AliceVision_install/include/ \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e -DOPENEXR_HOME:PATH\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e/opt/AliceVision_install/include/OpenEXR \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e -DGEOGRAM_INSTALL_PREFIX:PATH\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e/opt/AliceVision_install/lib \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e -DGEOGRAM_INCLUDE_DIR:PATH\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e/opt/AliceVision_install/include/geogram1 \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e ..\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003emake 编译\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e出现error,修改问题部分\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003emake install\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"ubuntu编译安装AliceVision"},{"content":" 服务器ssh服务\n在服务器上查看ssh服务, 或直接用本账号直接登陆服务器.\n查看服务器网络服务, 打印路由表\nifconfig 或 ip addr ip route show route ping\n查看是否ping通或有没有被跳转到其他ip地址\n其他设备 ping 服务器 服务器 ping 其他设备 其他设备 ping 网关 服务器 ping 网关 查看防火墙设置\niptables -L 查看系统日志\n需要事先启动服务\nUbuntu系统配置日志/var/log/message\n简单说明这次遇到的问题: 远程无法连接服务器, 重启服务器无效\n无法ping通服务器\nsshd 没问题\n其他设备ping 服务器 time out\n服务器能正常上网, 并且ping通其他设备\n服务器ping网关192.168.50.1会被跳转到另一个网段192.168.100.1\n而traceroute连百度通过的网关是_gateway (192.168.50.1)\u0026hellip;\u0026hellip;.\nping 192.168.100.1 可以ping通.\n路由表中只有docker0的虚拟网卡的桥接地址是192.168.100.1→修改下docker0虚拟网卡地址\nHow to Configure Docker Default Bridge docker0\n/etc/docker/daemon.json 加上bip. 改为默认地址. 172.17.0.1.\n修改服务器路由表\nlinux 路由表设置 之 route 指令详解_梦想专栏-CSDN博客_linux 路由配置\n(修改路由表的时候没有看br-xxxxxxxxx的虚拟网卡(在其他服务器中存在这个虚拟网卡), 似乎也是docker的虚拟网卡, 不过不影响使用)\n现在就可以直接ping通192.168.50.1了.\n原因: 由于之前没开系统日志, 无法知道具体原因, 推测是各网卡设置的ip地址所在的网段冲突造成的问题.\n","permalink":"https://sqf.icu/article/1ad824fd-b1f6-4225-8f7d-386f26cf3607/","summary":"\u003col\u003e\n\u003cli\u003e\n\u003cp\u003e服务器ssh服务\u003c/p\u003e\n\u003cp\u003e在服务器上查看ssh服务, 或直接用本账号直接登陆服务器.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e查看服务器网络服务, 打印路由表\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eifconfig 或 ip addr\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eip route show\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eroute\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eping\u003c/p\u003e\n\u003cp\u003e查看是否ping通或有没有被跳转到其他ip地址\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e其他设备 ping 服务器\u003c/li\u003e\n\u003cli\u003e服务器 ping 其他设备\u003c/li\u003e\n\u003cli\u003e其他设备 ping 网关\u003c/li\u003e\n\u003cli\u003e服务器 ping 网关\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e查看防火墙设置\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eiptables \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eL\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e查看系统日志\u003c/p\u003e\n\u003cp\u003e需要事先启动服务\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://codeantenna.com/a/8eaq0ykCrc\"\u003eUbuntu系统配置日志/var/log/message\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e","title":"无法远程连接Linux服务器故障排查记录"},{"content":"遇到问题 使用PaddleOCR进行多卡训练的时候, 显示错误\nserver not ready, wait 3 sec to retry... not ready endpoints:[\u0026#39;127.0.0.1:49741\u0026#39;] W0213 13:56:36.361328 41053 dynamic_loader.cc:258] You may need to install \u0026#39;nccl2\u0026#39; from NVIDIA official website: https://developer.nvidia.com/nccl/nccl-downloadbefore install PaddlePaddle. Traceback (most recent call last): File \u0026#34;tools/train.py\u0026#34;, line 145, in \u0026lt;module\u0026gt; main(config, device, logger, vdl_writer) File \u0026#34;tools/train.py\u0026#34;, line 44, in main dist.init_parallel_env() File \u0026#34;/home/xxx/.conda/envs/paddle/lib/python3.8/site-packages/paddle/distributed/parallel.py\u0026#34;, line 225, in init_parallel_env parallel_helper._init_parallel_ctx() File \u0026#34;/home/xxx/.conda/envs/paddle/lib/python3.8/site-packages/paddle/fluid/dygraph/parallel_helper.py\u0026#34;, line 42, in _init_parallel_ctx __parallel_ctx__clz__.init() RuntimeError: (PreconditionNotMet) The third-party dynamic library (libnccl.so) that Paddle depends on is not configured correctly. (error code is libnccl.so: cannot open shared object file: No such file or directory) Suggestions: 1. Check if the third-party dynamic library (e.g. CUDA, CUDNN) is installed correctly and its version is matched with paddlepaddle you installed. 2. Configure third-party dynamic library environment variables as follows: - Linux: set LD_LIBRARY_PATH by `export LD_LIBRARY_PATH=...` - Windows: set PATH by `set PATH=XXX; (at /paddle/paddle/fluid/platform/dynload/dynamic_loader.cc:285) INFO 2022-02-13 13:56:37,879 launch_utils.py:320] terminate process group gid:41058 INFO 2022-02-13 13:56:41,884 launch_utils.py:341] terminate all the procs ERROR 2022-02-13 13:56:41,884 launch_utils.py:602] ABORT!!! Out of all 2 trainers, the trainer process with rank=[0] was aborted. Please check its log. INFO 2022-02-13 13:56:45,888 launch_utils.py:341] terminate all the procs INFO 2022-02-13 13:56:45,888 launch.py:311] Local processes completed. 推测错误是系统缺少nccl2导致的.\n解决方法 下载与CUDA版本和linux系统版本符合的NCCL, URL(需要登录NVIDIA账号)\n查看cuda版本: nvidia-smi 查看系统版本: lsb_release -a 使用cuda 11.4, Ubuntu 18.04.6 LTS对应的 Local installer for Ubuntu 18.04\n下载nccl的git项目\ngit clone https://github.com/NVIDIA/nccl.git 安装设置\nchmod 777 -R nccl\rcd nccl\rvim src/collectives/device/gen_rules.sh\r:set ff=unix # gen_rules.sh文件是dos格式文件(windows默认格式), 需要转换成unix格式\rmake -j48 src.build BUILDDIR=/home/xxx/Install/nccl/build CUDA_HOME=/usr/local/cuda NVCC_GENCODE=\u0026#34;-gencode=arch=compute_80,code=sm_80\u0026#34; j12表示使用12个核心，使用nproc查看总核心数，根据具体情况进行调整； BUILDDIR表示编译后，一些文件的存储路径；默认是nccl/build；当然如果是root用户可以指定到/usr/local/ncc/； CUDA_HOME表示CUDA的目录，默认就是/usr/local/cuda，但是我这边不加这个，会报错，很奇怪； NVCC_GENCODE，如果不添加该字段，默认会编译支持所有架构；为了加速编译以及降低二进制文件大小，添加该字段，具体见：CUDA GPUs, **Matching CUDA arch and CUDA gencode for various NVIDIA architectures** (注意似乎目前nccl还不支持算力8.6, 使用8.0. NVCC_GENCODE=\u0026quot;-gencode=arch=compute_80,code=sm_80\u0026quot;) 最后呢，编译完成的文件都在指定的**BUILDDIR**字段路径下，需要将其添加到环境变量；\nvim ~/.bashrc 在打开的文件中，添加：\nexport LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/xxx/Install/nccl/build/lib\rexport PATH=$PATH:/home/xxx/Install/nccl/build/include 保存后，执行：\nsource ~/.bashrc 之后就能开始跑多卡训练了.\n","permalink":"https://sqf.icu/article/b871ea61-2001-4c93-9f53-f25378fa4794/","summary":"\u003ch1 id=\"遇到问题\"\u003e遇到问题\u003c/h1\u003e\n\u003cp\u003e使用PaddleOCR进行多卡训练的时候, 显示错误\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eserver not ready, wait \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e sec to retry...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enot ready endpoints:\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;127.0.0.1:49741\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eW0213 13:56:36.361328 \u003cspan style=\"color:#ae81ff\"\u003e41053\u003c/span\u003e dynamic_loader.cc:258\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e You may need to install \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;nccl2\u0026#39;\u003c/span\u003e from NVIDIA official website: https://developer.nvidia.com/nccl/nccl-downloadbefore install PaddlePaddle.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTraceback \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003emost recent call last\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  File \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;tools/train.py\u0026#34;\u003c/span\u003e, line 145, in \u0026lt;module\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    main\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003econfig, device, logger, vdl_writer\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  File \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;tools/train.py\u0026#34;\u003c/span\u003e, line 44, in main\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    dist.init_parallel_env\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  File \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/home/xxx/.conda/envs/paddle/lib/python3.8/site-packages/paddle/distributed/parallel.py\u0026#34;\u003c/span\u003e, line 225, in init_parallel_env\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    parallel_helper._init_parallel_ctx\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  File \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/home/xxx/.conda/envs/paddle/lib/python3.8/site-packages/paddle/fluid/dygraph/parallel_helper.py\u0026#34;\u003c/span\u003e, line 42, in _init_parallel_ctx\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    __parallel_ctx__clz__.init\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eRuntimeError: \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003ePreconditionNotMet\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e The third-party dynamic library \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003elibnccl.so\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e that Paddle depends on is not configured correctly. \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eerror code is libnccl.so: cannot open shared object file: No such file or directory\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  Suggestions:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  1. Check \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e the third-party dynamic library \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003ee.g. CUDA, CUDNN\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e is installed correctly and its version is matched with paddlepaddle you installed.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  2. Configure third-party dynamic library environment variables as follows:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - Linux: set LD_LIBRARY_PATH by \u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003eexport LD_LIBRARY_PATH\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e...\u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - Windows: set PATH by \u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003eset PATH\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eXXX; \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eat /paddle/paddle/fluid/platform/dynload/dynamic_loader.cc:285\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eINFO 2022-02-13 13:56:37,879 launch_utils.py:320\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e terminate process group gid:41058\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eINFO 2022-02-13 13:56:41,884 launch_utils.py:341\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e terminate all the procs\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eERROR 2022-02-13 13:56:41,884 launch_utils.py:602\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e ABORT!!! Out of all \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e trainers, the trainer process with rank\u003cspan style=\"color:#f92672\"\u003e=[\u003c/span\u003e0\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e was aborted. Please check its log.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eINFO 2022-02-13 13:56:45,888 launch_utils.py:341\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e terminate all the procs\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eINFO 2022-02-13 13:56:45,888 launch.py:311\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Local processes completed.\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e推测错误是系统缺少nccl2导致的.\u003c/p\u003e","title":"Linux下无root权限编译安装nccl2(30系列显卡)"},{"content":"0. 背景 最近想整一个个人主页玩玩, 可是平时时间紧张, 所以需要一个建立之后, 可以快速编写博文或直接从我的笔记转换为博文, 并且需要能够快速简单的上传方式.\n目前, 本人使用的笔记工具正是Notion, 并且有personal pro可以无限制上传文件. 于是使用Notion建站的话, 图床之类的问题也一并解决了(Github Pages显示1G的存贮, 长期写博文的话需要图床的支持). 另外, Notion的建站有两种方式, 本次介绍的方式和需要购买独立域名并且配合Cloudflare DNS重定位服务的方式. 后者需要购买独立域名(可能还需要备案), 并且部分域名可能需要修改DNS才能被Cloudflare识别, 试了两天还是放弃了. 本次介绍的方式无需考虑费用问题且建站调试也更快一些.\n本文面向对计算机和前端有一定知识同学. 不过其实只用Notion建站也够了, 就是样式简陋点, 但是好歹没有bug. 🤣 1. 涉及到的服务和项目 Notion: 笔记与写作工具. 由于是基于web开发, 所以在各平台都可以无缝切换. 购买Personal Pro 或使用学生邮箱可以不受限制的上传文件, 不过免费版也够用.\nNotion入门一些时间成本, 另外需要一些Markdown知识. Vercel: 免费的网站托管服务. 网页更新速度比 Github Pages 更快.\nnextjs-notion-starter-kit: 使用Vercel和Next.js服务建站的项目.\n缺点: 建站和调试需要一些前端知识. 优点: 建站和调试结束之后, 就可以使用Notion直接更新文章. 与Github Pages相比更加方便, 不过相对的, 能使用的模板也更少一些. Node.js: 使用和调试上述项目的基础工具.\n2. 大致流程 2.1. 事前准备 下载\n下载nextjs-notion-starter-kit项目的压缩包.\n原作者制作的主页: https://transitivebullsh.it/. 如果需要本站的样式, 可以使用这个连接下载这个压缩包. 下载 Node.js.\n注册\n注册 Notion, Vercel, Github.\n2.2. 开始建站 在本地安装Node.js, 一路默认设置点确定即可. 解压nextjs-notion-starter-kit项目的压缩包. 打开终端. 进入项目的根目录. 配置项目. # 安装npm, 如果报错的话使用: npm i --legacy-peer-deps npm install # 安装vercel服务 npm i -g vercel # 上传一次项目, 初次上传时需要选择进行一些配置, # 中途需要将vercel和github连接一次, 其他情况一路回车就行. npm run deploy 2.3. 开始调试 首先打开Notion, 新建一篇笔记作为自己的站点首页, 在右上角点击Share 将这一页设为公开. 按自己的需求可以允许被他人吐槽, 被搜索引擎发现或被人复制网站所有内容等功能. 查看当前页面的URL(不是Share里的URL, 是浏览器里的URL) # URL例子: https://www.notion.so/travis-fischer/TransitiveBullsh-it-78fc5a4b88d74b0e824e29407e9f1ec1 # 则需要记下后面的编号, 这个编号是之后需要的rootNotionPageId 78fc5a4b88d74b0e824e29407e9f1ec1 回到本地, 打开项目中的site.config.js. // 修改为自己的rootNotionPageId rootNotionPageId: \u0026#39;78fc5a4b88d74b0e824e29407e9f1ec1\u0026#39; // 以下按需修改############################################################ // basic site info (required) name: \u0026#39;Homepage\u0026#39;, domain: \u0026#39;sun\u0026#39;, author: \u0026#39;sun\u0026#39;, // open graph metadata (optional) description: \u0026#39;Example site description\u0026#39;, socialImageTitle: \u0026#39;sun\u0026#39;, socialImageSubtitle: \u0026#39;Hello World!\u0026#39;, // 以上按需修改############################################################ // social usernames (optional) 只填自己需要的, 填用户名. // 这几个不留空的话, 会以图标的形式显示在页面的右侧. twitter: \u0026#39;\u0026#39;, github: \u0026#39;\u0026#39;, linkedin: \u0026#39;\u0026#39;, 启动网页本地调试模式\n终端进入项目文件夹路径, 使用命令npm run dev进入调试, 打开网址 http://localhost:3000, 显示调试页面.\n处理网页右上角的Github项目标志\n目前点击这个图标会进入, 项目原作者的Github项目.\n各种网站的图标可以在public文件夹中替换修改.\n进阶: 调式主页的页面样式\n在项目中打开styles/notion.css, 可以进行各种参数设置.\n一般样式都在styles和components这两个文件夹里.\n3. 新建和发布博文 建立一个表格, 将Name, Description, Public, Published, Tags建立好 (或者直接复制原项目作者的Notion主页里的表格).\n在表格中新建一行, 然后在Name列点击Open打开新的一页, 开始写文章.\n点击Public即可公布想要公布的文章.\n4. 连接私有域名 Vercel进入设置界面, 在Domains添加私有域名.\n编辑下方之前自动生成的域名, 选择刚添加的私有域名即可.\n5. 可能出现的报错 调试的时候出现以下警告: (node:5656) [DEP0128] DeprecationWarning: Invalid \u0026#39;main\u0026#39; field in \u0026#39;D:\\code_project\\nextjs-notion-starter-kit\\node_modules\\react-icons\\package.json\u0026#39; of \u0026#39;lib\u0026#39;. Please either fix that or report it to the module author (Use `node --trace-deprecation ...` to show where the warning was created) 解决方法: 打开node_modules/react-icons/lib/package.json. 删除并替换代码. (原代码不能注释, 一定要删除.)\n// 原本的代码 \u0026#34;main\u0026#34;: \u0026#34;lib\u0026#34;, // 替换为 \u0026#34;main\u0026#34;: \u0026#34;./lib/cjs/index.js\u0026#34;, \u0026#34;module\u0026#34;: \u0026#34;./lib/esm/index.js\u0026#34;, \u0026#34;exports\u0026#34;: { \u0026#34;.\u0026#34;: { \u0026#34;require\u0026#34;: \u0026#34;./lib/cjs/index.js\u0026#34;, \u0026#34;default\u0026#34;: \u0026#34;./lib/esm/index.js\u0026#34; } }, 使用网页搜索功能时卡住不出结果\n原因: 没有修改site.config.js中的domain参数\n解决方法: 需要将domain参数改为自己的网站网址.\n调试项目的时候出现报错: 'next' 不是内部或外部命令，也不是可运行的程序\n解决方法: npm install cross-env\n","permalink":"https://sqf.icu/article/40bc66d8-3f2a-4629-99c0-a9e985b35394/","summary":"\u003ch1 id=\"0-背景\"\u003e0. 背景\u003c/h1\u003e\n\u003cp\u003e最近想整一个个人主页玩玩, 可是平时时间紧张, 所以需要一个建立之后, 可以快速编写博文或直接从我的笔记转换为博文, 并且需要能够快速简单的上传方式.\u003c/p\u003e","title":"Notion + Next.js 搭建个人博客"},{"content":"1. 体育赛事相关服务内容目 目前找到的，与媒体或体育赛事播放相关的人工智能内容生产服务大致有以下三种：\n比赛视频内容标记和自动剪辑 WSC Sports 阿里云 百度云 VidPress 赛事自动拍摄 AIGC Veo Sports Camera 思锐科技 赛事之窗 比赛语音智能转化及生成 百度 Amazon SageMaker 其他 2. 比赛视频内容标记和自动剪辑 自动对于比赛直播的内容进行多模态识别，切片和标记，并在赛后实现的人工或自动快速剪辑。\n2.1. WSC Sports 服务内容\nWSC的ClipPro平台会在一场比赛中产生大量带有标签的视频片段，根据这些标签来制作集锦。 核心技术\nClipPro平台的输入是各种比赛的直播或录播的视频数据和音频数据，以及统计数据和社交媒体内容，然后使用人工智能来标记带有详细信息和评级的剪辑。 比赛项目\n合作方（面向掌握体育赛事播放权的广播公司和流媒体）\nWSC Sports 专有的 AI 技术平台可为全球 200 多个联赛和转播合作伙伴自动创建和分发精彩片段，其中包括 NBA、NHL、ESPN、YouTubeTV、德甲、FIBA 和腾讯体育。 YouTube、Amazon等平台提供大规模短视频自动化生产与分发服务。 软硬件\nClipPro（基于云的编辑和检测工具，直播切片和内容标记）\nClipPro是一个在线平台，使数字制作团队能够实时编辑来自直播的视频，并立即发布到 Brightcove 的在线视频平台，社交媒体或将其无缝推送到任何其他在线视频平台，应用程序或网站。 该技术自动识别体育比赛中的事件，并使用元数据对其进行分类。 AVGen (自动视频生成器)\n集锦生成 (可以选择特定的人, 动作, 时间等)。 Graphics 360 商业包装\n自动生成特定人或团队的介绍, 视频, 缩略图。对球员, 团队进行商业包装。 Google web story ****(非主要服务)\nWSC Sports 以故事格式创建实时精彩片段，这些精彩片段将出现在 Google 搜索的现场比赛中，并且会随着比赛的进行不断更新。 Google web story 是在谷歌搜索中出现的模块。表现形式是以图片或10s内的视频作为背景, 写上介绍文字的动态卡片。 应用形式\n腾讯 （ClipPro 和 AVGen）\n使用WSC平台工具生成大量球星个人集锦, 产球队个人集锦，各类得分集锦，各类比赛核心事件集锦,，并栏目化。\n使用WSC的数据生成网页对单场比赛内容做汇总（WSC只了负责集锦部分，且集锦视频名称推测为人工生成）。\n记者和编辑（ClipPro）\nClipPro 会自动生成并向推荐最相关的定制视频, 他们可以将这些视频嵌入任何文, 报告, 统计表或故事情节中. 例如, 如果文章谈论科比·布莱恩特的三分球, 该工具会立即生成科比在上一场比赛/上个月/有史以来所有三分球的视频滚动, 编辑器可以立即将其嵌入文章中. Okko Sport（ClipPro + Google web story）\n生成体育赛事集锦, 并制作成google web story形式. 2.2. 阿里云 https://blog.csdn.net/yunqiinsight/article/details/81015954\n服务内容\n在2018年俄罗斯世界杯期间，对比赛直播进行剪辑自动生成集锦。 核心技术\n对帧图景深、位置、事件、红黄牌、不同角色行为、禁区危险画面及球星人脸的标注，也包含对音频中关键词、音频事件等的人工标注。 在视频的图像识别中，通过识别视频中已注册的球星并进行人物追踪，同时做了一定程度的容错处理和补偿优化，并针对不同位置的球星微调追踪模型，最终对球星在视频中出现的时间线、幅面坐标及置信度进行综合的动态分析。 在解说词识别中， 则使用了世界杯场景的语音识别模型，该模型对球员名称、足球术语、解说员的语速/语气/语调等进行了额外的训练和优化，尤其是在声学模型上针对足球场景下的球场及观众噪声进行了适应性训练，使得其最终对世界杯解说词的识别准确率提升了超过10个百分点。 球星集锦的实现通过对世界杯场景进行深入理解和分析，从比赛视频、解说词音频、球星库及人物场记等各个维度进行识别与分析，并利用多模态融合技术，从而实现复杂场景下的集锦效果。 阿里云赛事自动剪辑处理流程\n比赛项目\n足球 合作方\n央视体育频道 软硬件\n未显示 应用形式\n生成特定球员于本场比赛的集锦，在比赛后的1到2天内，发布优酷上。（人气不佳）\n2.3. 百度云 VidPress https://ai.baidu.com/support/news?action=detail\u0026amp;id=2504\nhttp://research.baidu.com/Blog/index-view?id=134\nhttps://www.sohu.com/a/444746657_100230216\nhttps://tiyu.baidu.com/matchlist\n服务内容\n视频切片和标注 使用VidPress平台，自动生成剪辑视频。 核心技术\n视频切片和标注 数据集：包括500场来自2014到2017年三个赛季的欧洲足球五大联赛和欧洲冠军联赛的视频，视频总时长达到764小时，人工标注达30万个。\n在 SoccerNetv2 数据上微调了五种预训练的特征提取器模型：TPN、GTA、VTN、irCSN 和 I3D-Slow。\nVidPress Sports团队的模型能够处理事件定位和回放溯源（不同角度回放精彩片段）这两个方面的任务，并采用了 Transformer 结构。\nSoccerNet-v2 足球视频理解竞赛两项任务的冠军。\n论文：https://arxiv.org/pdf/2106.14447v1.pdf\n比赛项目\n足球 合作方\n未知 软硬件\n在线 VidPress 平台（可以通过表格文字等生成、剪辑视频）\n应用形式\n不过，无法从百度体育的集锦视频等途径中推测出是否使用了自动切片标注和自动剪辑。最近的篮球比赛，精彩片段的集锦也不多。\n在智能创作平台https://ai.baidu.com/creativity/index中没有找到自动视频标注和剪辑的功能。\nSoccerNet-v2比赛举办与2021年中旬，可能自动标注与剪辑功能还在测试中。\n3. 赛事自动拍摄 模仿摄影师的推拉摇移等专业拍摄手法，自动选取有效的画面进行视频输出。\n3.1. AIGC（央视网人工智能编辑部） https://aigc.cctv.com/products/znps/index.shtml?spm=0.Pu2AdJB8T3nL.ETBeE6wfqmwp.12\n服务内容 智能拍摄，依托AI技术模仿摄影师的专业拍摄手法，进行自动拍摄。 核心技术 图像识别，自动拍摄。 借助多目高清全景镜头拍摄，可以对拍摄画面实时拼接处理，实时形成全景画面。 合作方 未显示 软硬件 未显示 应用形式 节目自动录制 现场直播 3.2. Veo Sports Camera https://new.qq.com/omn/20200726/20200726A0JTTF00.html\nhttps://event.veo.co/\n服务内容 智能拍摄，数据分析 核心技术 两个4K摄像头以一定角度放置在一个盒子里，抬高到距球场23英尺的高度，使摄像机能够以180度的全景拍摄整个球场。 使用针对比赛开发的人工智能技术，放大和跟踪行动开始。 使用65000场足球赛的数据来训练模型，使用模型来分析比赛数据。 比赛项目 足球、篮球、橄榄球。 合作方 Veo与至少10家美国职业足球大联盟(MLS)以及一些世界上最大的足球联赛(如意甲、英超、法甲、德甲和西甲)的俱乐部都有合作协议 软硬件 Veo Cam 2 相机（两个4K视频传感器180度视角、Nvidia芯片等硬件）\nLive-streaming 直播观看app\nVeo Editor 编辑器\n借助 Veo Analytics可以查看比赛进攻次数的可视化、二维地图、球员平均位置和动作统计、比赛事件概览和各种数据统计。 相机加年费服务，1,887欧元起。\n应用形式 运动员 Nathan Wade 利用Veo的技术改进自己的技术，并将数据发给俱乐部用来获得签约机会。 团队 分析比赛和分享比赛片段。 3.3. 思锐科技 https://www.ruisport.cn/\nhttps://space.bilibili.com/85537402?spm_id_from=333.905.b_7570496e666f.2\n服务内容 智能拍摄，数据分析 核心技术 使用多人姿态捕捉技术，根据球衣颜色区分主队客队，可生成2D图 比赛项目 足球、篮球 合作方 短视频和视频平台。 软硬件 AI摄像机一台、服务器一台、交换机一台及配件。 价格：25000元/套，无年费。 应用形式 官网和bilibili上有一些比赛视频 3.4. 赛事之窗 https://www.zerosportsai.com/\nhttps://www.qunfengshe.com/products/UHJvZHVjdDoxMDE=\n服务内容 足球场景分析，视频剪辑分享功能。 核心技术 使用独创ZAP运动视觉感知算法聚合引擎。 人脸识别 肢体重建 三维场景重建 事件概率算法 实时趋势预测 搭载自研高性能AI智能摄像头。 搭载海豚AI健康检测系统，基于3D视觉技术全自动检测青少年的体型体态，并给出分析报告。 比赛项目 足球 合作方 投资：商汤科技、深圳市政府基金 1100+行业顶级客户（具体未显示） 主要针对职业青训、校园足球以及大众足球 软硬件 多目4K摄像头拼接、180°全景拍摄。 app拥有对视频片段自动标记和剪辑功能。 价格未知。 应用形式 实时跟踪拍摄赛场的各项数据，传入终端供教练裁判使用。 比赛时：标注高亮球员，传球示意，区域标注。 比赛后：对比赛视频进行深度分析（使用目标检测追踪，事件检测和三维重建） 4. 自动比赛解说生成 代替或辅助真人解说员，对体育比赛进行解说。\n4.1. 百度 https://www.sohu.com/a/110574437_161062\nhttps://tech.qq.com/a/20160818/050938.htm\n服务内容\n通过跟踪、抓取、整合多个平台的资讯、技术数据、图片、视频、评论，并且基于篮球领域专业知识，使用自然流畅的人类语言和表情包进行书面讲解。 核心技术\n使用NBA和伦敦奥运会篮球赛事的相关比赛文字解说作为训练集 比赛项目\n篮球 合作方\n央视 软硬件\n前端为app\n应用形式\n2016年里约奥运会自动生成篮球比赛进行解说，不过存在延迟，无法实时解说。 4.2. Amazon SageMaker https://aws.amazon.com/cn/blogs/machine-learning/enhance-sports-narratives-with-natural-language-generation-using-amazon-sagemaker/\n服务内容 比赛解说 核心技术 数据集：使用不同的统计数据、特征值、球队和球员姓名生成了包括 8 个特征的 57,000 多个样本。 使用自然语言生成 (NLG) 设计和实现端到端 ML 系统, 使用预训练模型, 对少数数据进行微调之后, 就可以产生比模板更自然的比赛解说. 比赛项目 橄榄球、篮球 合作方 Fox Sports 软硬件 未显示 应用形式 通常篮球等比赛的节奏很快，而解说员会依靠模板生成的叙述来实时谈论游戏中的统计数据，但这些基于模板产生的句子有时听起来很僵硬且难以理解。为了改善广播体验，Fox Sports 求助于 AWS 及其人工智能技术，将比赛实时数据转换为易于理解的叙述形式。 使解说员可以快速地在球队和球员之间解说，以改善观众的体验。 4.3. 其他 https://cloud.tencent.com/developer/news/249659\nhttps://openaccess.thecvf.com/content_cvpr_2018/papers/Yu_Fine-Grained_Video_Captioning_CVPR_2018_paper.pdf\n服务内容\nAI体育解说 上海交通大学CVPR论文 核心技术\n时空实体定位与角色挖掘子网络：确定运动员的位置和角色。 细粒度的动作建模子网络：描述快速运动的骨骼和变换的位置。 一组关系建模子网络：对运动员之间的关系建模。 比赛项目\n篮球 应用形式\n数据集：在 YouTube 上收集了 50 个高清的 NBA 比赛视频，从中选择出 2000 个包含多样的细致动作的片段，并根据篮球解说的方式进行了标注6520 个句子。平均每个视频片段 3.16 个句子，29.7 个描述性词语。 实验结果 ","permalink":"https://sqf.icu/article/6be4ef49-8d76-49df-93d9-8dfbac209380/","summary":"\u003ch1 id=\"1-体育赛事相关服务内容目\"\u003e1. 体育赛事相关服务内容目\u003c/h1\u003e\n\u003cp\u003e目前找到的，与媒体或体育赛事播放相关的人工智能内容生产服务大致有以下三种：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e比赛视频内容标记和自动剪辑\n\u003cul\u003e\n\u003cli\u003eWSC Sports\u003c/li\u003e\n\u003cli\u003e阿里云\u003c/li\u003e\n\u003cli\u003e百度云 VidPress\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e赛事自动拍摄\n\u003cul\u003e\n\u003cli\u003eAIGC\u003c/li\u003e\n\u003cli\u003eVeo Sports Camera\u003c/li\u003e\n\u003cli\u003e思锐科技\u003c/li\u003e\n\u003cli\u003e赛事之窗\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e比赛语音智能转化及生成\n\u003cul\u003e\n\u003cli\u003e百度\u003c/li\u003e\n\u003cli\u003eAmazon SageMaker\u003c/li\u003e\n\u003cli\u003e其他\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"2-比赛视频内容标记和自动剪辑\"\u003e2. 比赛视频内容标记和自动剪辑\u003c/h1\u003e\n\u003cp\u003e自动对于比赛直播的内容进行多模态识别，切片和标记，并在赛后实现的人工或自动快速剪辑。\u003c/p\u003e","title":"智能体育内容生产服务相关调研"},{"content":"可行性分析 根据需求和调研，目前最佳的的方案的研究方向为：使用多个单目相机拍摄的照片实时获取3D人体姿态估计结果（multi-view 3D HPE）。不过，多视角的3D HPE可能无法达到50fps的效果。\n可使用的数据集\n多人多视角\n可使用的模型\n模型论文和源码\n模型精度和选用的数据集\n其他可行的方案是单一单目相机拍摄的照片进行多人3D HPE（single-view 3D MHPE），并使用bottom-up方法（预测耗时更少）或top-down方法（精度更高），相对于前者，可能遇到人体遮挡问题，但是对于数据的要求更低、消耗的计算资源更低。\n可使用的数据集，所有数据集整理在：https://github.com/zczcwh/DL-HPE\n多人单一视角\n可使用的模型\n模型论文和源码\n模型精度和选用的数据集\n人体姿态估计研究调研 人体模型（Human Body Modaling） 人体模型被用来表现从图片或视频中抽出的关键点（keypoints）和特征（features）。\n主要的人体模型有3种：\n运动学模型（Kinematic model；用于2D/3D HPE） 用一组关节位置和四肢方向来表示人体结构 用于捕捉不同身体部位之间的关系 缺点是无法表现人体材质和形状 平面模型（Planar model；用于2D HPE） 用于近似表示人体的外观和形状 无法表现材质 体积模型（Volumetric model；用于3D HPE） 存在多种流行的 3D 人体模型 可表现人体材质和形状 人体姿态估计（Human Pose Estimation） 看完这篇AI算法和笔记，跟面试官扯皮没问题了 | 基于深度学习和传统算法的人体姿态估计-CSDN博客\n目前的人体姿态估计（HPE）研究分为两种：\n2D HPE：从RGB图像估计每个关节的2D Pose（x，y）坐标。\n优点： 精确度相对于3D HPE更高 更容易实现并且不需要特殊设备 缺点：只能表现人体在一个平面上的姿势，没有前后的位置信息 难点： 数据量不足 深度模糊性问题 人体被遮挡问题 研究分支： 单人姿态估计，有两种基于深度学习的方法\nregession methods：通过使用基于深度学习的回归器直接构建从输入图像到身体关节坐标的映射。 body part detection methods：分两步 为身体部位定位生成关键点（即关节）的热图（heat map） 将这些检测到的关键点组装成人体姿态或骨架 多人姿态估计，也有两种基于深度学习的方法\ntop-down methods:\n检测人体，将多人图片分成单人图片\n为每个人使用单人姿态估计预测每个人的关键点（keypoints）\n精度比bottom-up methods更高\n被遮挡的人体无法被检测\nbottom-up methods:\n检测所有人体的关键点 将关键点组成每一个人体的姿势 速度比top-down methods更快, 检测时间不会随着人数的增加而增加 8-PAF标签设计方法.mp4_哔哩哔哩_bilibili\n网络结构\n对于一张输入图像，深度神经网络同时预测出每个骨点的热力图S=(S1，S2，…，SJ)和骨点之间的亲和区域L=(L1，L2，…，LC) 。\n热力图的峰值为骨点的位置，骨点相互连接构成二分图，亲和区域对图的连接进行稀疏，最后对二分图进行最优化实现多人姿态估计。\nMMPose\nhrnet识别\n这种架构相对于其他架构的一个优点是, 神经网络在估计姿势时保持高分辨率表示. 用一个并行卷积流的方法, 从第一阶段开始逐步逐个添加高分辨率到低分辨率的流.\n后一个阶段的并行流的分辨率由前一个阶段的分辨率和更低分辨率组成\n最后将所有的特征图上采样到对应64*48的尺寸, 相加融合\n网络的输出尺寸是 $64*48*n_{keypoint}$\n获得热力图, 因为gt点只有一个像素, 但是网络输出尺寸是64*48, 原图上的人的检测框缩小, 热力图表示关键点的位置\n以gt点为中心做高斯分布, 和预测点相比较\n损失计算\nOKS 相关性 人的检测框面积 预测点到gt的距离 数据增强\nfastrcnn检测人体\n3D HPE：从RGBD图像中估计每个关节的3D Pose（x，y，z）坐标。\n优点：能够捕捉到人体在一个空间中的位置和姿势。 缺点： 需要如单目相机、惯性测量单元（IMUs）、射频装置等特殊设备，成本较高。 2D HPE遇到的难点问题在3D HPE中依旧需要解决。 研究分支： 使用单目相机拍摄的RGBD图片或视频 目前主流研究\n单一视角3D存在2D HPE所存在的问题，并且多人HPE比单人HPE更复杂。\nsingle-view 3D HPE single-person 3D HPE\nmodel-free methods\n不采用人体模型\ndirect estimation approaches：直接预测3D HPE。 2D to 3D lifting approaches：先预测2D HPE，再使用2D HPE预测3D HPE。 model-based methods：预测人体关节点，再预测形体。\nmultiple-person 3D HPE\n采用与2D HPE相同的方法\ntop-down methods bottom-up methods multi-view 3D HPE 主要用于multiple-person HPE 优点：能解决单一视角时的人体遮挡问题\n缺点：\n需要大量数据含3D标注 使用encoder-decoder框架可使用不含标注数据，不过需要多视角图片和背景分割 强化学习，可使用更少的视点 以上方案的计算耗时会随相机数量的增加线性增加, 并且消耗大量内存。\n存在加速方案 (remelli et al.)\n存在更高效的相机添加方案 (Xie et al.)\n使用其他传感器，比如惯性测量单元 非主流研究 数据集 2D HPE 数据集\n2D HPE论文精度\n3D HPE 数据集\n3D HPE论文精度\nextra 3D data指的是在3D HPE之前，先使用有标注的额外数据集训练出一个2D HPE模型。 References Zheng C, Wu W, Yang T, et al. Deep learning-based human pose estimation: A survey[J]. arXiv preprint arXiv:2012.13392, 2020. Chen Y, Tian Y, He M. Monocular human pose estimation: A survey of deep learning-based methods[J]. Computer Vision and Image Understanding, 2020, 192: 102897. 深度学习和目标检测系列教程 22-300：关于人体姿态常见的估计方法. https://bbs.huaweicloud.com/blogs/297702, Oct, 2021. ","permalink":"https://sqf.icu/article/38ffa129-f64c-4cf8-a6c3-54387fb9ff2e/","summary":"\u003ch1 id=\"可行性分析\"\u003e可行性分析\u003c/h1\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003e根据需求和调研，目前最佳的的方案的研究方向为：使用多个单目相机拍摄的照片实时获取3D人体姿态估计结果（multi-view 3D HPE）。不过，多视角的3D HPE可能无法达到50fps的效果。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e可使用的数据集\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"/media/e7ffe453280088e13872fb67.csv\"\u003e多人多视角\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e可使用的模型\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"/media/47c9ff415cbea10013dd4ea3.csv\"\u003e模型论文和源码\u003c/a\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e模型精度和选用的数据集\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/96c62090cca3c7ea8f99f80d.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e其他可行的方案是单一单目相机拍摄的照片进行多人3D HPE（single-view 3D MHPE），并使用bottom-up方法（预测耗时更少）或top-down方法（精度更高），相对于前者，可能遇到人体遮挡问题，但是对于数据的要求更低、消耗的计算资源更低。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e可使用的数据集，所有数据集整理在：\u003ca href=\"https://github.com/zczcwh/DL-HPE\"\u003ehttps://github.com/zczcwh/DL-HPE\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"/media/650519d5b5e7aa49ef0de0e0.csv\"\u003e多人单一视角\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e可使用的模型\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"/media/cf17055f32caf8f2d156b755.csv\"\u003e模型论文和源码\u003c/a\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e模型精度和选用的数据集\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/2b87c39714f26641e1bf88c4.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/6d354e279f1ff43aec0b3f10.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e","title":"人体姿态估计研究调研"},{"content":"1. 导入点云数据文件 文件-导入-仅导入 导入需要的点云模型, 可以全选.\n2. 处理点云数据 点云的选择方式有多种, 处于模型正上方快捷栏. 可以使用套索模式对点云不需要的点, 使用del键进行删减. (右键按住可以转动模型; ctrl+右键可以移动模型)\n2.2. 多次扫描模型对齐 如果需要将多个扫描结果对齐, 点击菜单 对齐-扫描数据对齐. 对齐有2种方式\n自动对齐: 根据模型表面特征自动对齐, 通常效果不佳. 手动对齐: 选择 参照, 选中一个扫描结果. 再点击移动, 再选择一个其他的结果\n将两个模型位置摆正, 在相似度位置点上标记点. 并在不同的表面都这么标点.\n效果:\n对好一个,点击方法旁边的√进行应用, 之后下一个需要对齐的模型, 再点击移动.\n所有个体都对齐完成后, 点击 整体, 选中所有模型, 放入 移动. 再次应用.\n最后点击 扫描数据对齐的√ 进行应用.\n2.3. 合并所有个体 对齐完成后, 各个扫描的模型个体还是分开的, 需要进行合并.\n点击菜单 点-合并 全选选中所有个体, 点击 构造面片 (选择 高清面片构建 可以构成更高面片数的模型).\n下图为高清面片构建结果, 右图为构造面片结果:\n在构成高清面片时可以调整降噪级别, 数值越高, 物体表面越平滑. 此时就可以获得合并加上三角面片化的模型结果了, 高清面片模型需要先消减面片数量, 方法在3.1章.\n3. 处理三角面片模型 如果需要面片数较低但是维持在较精确的形状的话, 循环使用3.1~3.3章的方法, 直到取得需要的面片数.\n3.1. 平滑 可以使用 多边形-平滑 多次, 将模型变平滑. 平滑后模型变回点云模型, 需要使用整体再面片化将模型转回三角面片模型. 单次平滑和数次平滑后的效果对比如下:\n3.2. 减少面片的数量 点击菜单 多边形-消减, 设置参数来减少面片数.\n之后需要再将模型变会点云形式再重新封装, 点击 整体再面片化 即可. 但是, 如果存在过大坡面的时候使用整体再面片化, 会删除厚度较细的部分. 所以, 各部位厚度变化较大的模型需要避免使用(高模除外).\n3.3. 使用修补精灵 高清面片模型生成后会出现非流形几何形状. 使填孔功能无法使用, 所以需要选择 多边形-修补精灵 进行修补.\n修补完成后可能还会残留无法修补的部分. 再次修补即可. 中途可能会出现报错, 不过最后非流形的边会全部消失.\n3.4. 处理模型上的孔洞 此时获得的模型上可能会存在孔洞需要填补.\n点击菜单栏 多边形-填孔, 如果显示警告可以无视. 如果需要填很多孔, 可以点击锁定按钮来锁定当前方法.\n选择 境界, 点击孔洞的边选中孔洞, 点击填孔旁的√就可以进行补孔. 也可以拉框选中整个模型, 点击填孔进行自动填孔.\n但如果是过大的破面则无法填补.\n3.5. 精确曲面 对于需要获面片数量更少的模型时, 可以使用精确曲面功能, 用于根据模型表面的弧度拟合为可以用函数表达的曲线. 精确曲面可以进一步简化面数(多数情况对于细节很少或者人工构建的模型使用).\n点击菜单栏 精确曲面-自动曲面创建\n参数栏中可以选择机械(对于有几何规律的物体)和有机(对于基本没什么几何规律的物体).\n拟合选项: 公差可以加到0.05减小失败几率. 但是由此生成的实体可能并不是想要得模型主体, 可能是部分模型碎片, 无法使用.\n目前9313个面的椅子模型无法使用精确曲面, 生成的结果是一些小碎片.\n4. 领域 领域功能可以把一个模型分为不同的部分.\n4.1. 分割 点击菜单栏 领域-自动分割. 设置敏感度, 敏感度越高, 领域的分块越细. 常用的数值为5, 10, 30, 60, 70 (数值越大, 分块越多).\n使用分割功能, 选中一个块, 拉线将线围成一圈即可分离.\n4.2. 合并 点击菜单栏 领域-合并, 合并之前自动或手动分割的部分.\n具体操作: 如有两块区域A和B需要合并. 则点击区域A, 按住shift同时点击区域B. 再点击合并即可.\n4.3. 重分块 点击菜单栏 领域-重分块, 可以对单一领域进行重新分块. 点击重分块后, 修改敏感度. 重置对象, 选中需要分块的领域.\n重复第4章的操作, 最终获得的效果:\n5. 导出模型 右键点击左下角 面片或实体, 选择输出, 就可以选择想要的输出格式.\n","permalink":"https://sqf.icu/article/d79b86e3-b8e6-4cb7-8f43-bf4a8a669bb5/","summary":"\u003ch2 id=\"1-导入点云数据文件\"\u003e1. 导入点云数据文件\u003c/h2\u003e\n\u003cp\u003e文件-导入-仅导入 导入需要的点云模型, 可以全选.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/c26961d82cac830f3741dbf2.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"2-处理点云数据\"\u003e2. 处理点云数据\u003c/h2\u003e\n\u003cp\u003e点云的选择方式有多种, 处于模型正上方快捷栏. 可以使用套索模式对点云不需要的点, 使用del键进行删减. (右键按住可以转动模型; ctrl+右键可以移动模型)\u003c/p\u003e","title":"逆向建模软件 Geomagic Design X 点云数据处理和导出面片模型的方法"},{"content":"1. 背景 将人物从一张照片或视频中扣出, 并放入其他光照环境下的照片或视频中时会产生违和感, 那是因为背景中的光和照在人物身上的光的方向和亮度等信息并不相同. 为了使照在人物身上的光与背景光源的信息保持一致, 需要使用人像重照明 (portrait relighting) 技术. 而进行人像重照明任务的深度学习模型需要在不同光照环境下的人像照片数据, 所以需要搭建数据采集设备.\n2. 数据采集设备的常用组件 这里整合了从2000年到2021年间人像重照明数据采集设备论文中提到的常用组件. 2.1. 框体 由于人像重照明任务训练所需的数据为不同角度的光线照射到人像时的照片, 可能需要光线的方向的数据 (特别是每次拍摄只有一个光源的情况 (One-light-at-a-time(OLAT) data), 所以在拍摄的时候固定光源是更好的选择. 固定光源另一个好处在于可以在极短时间完成同一个人像的所有光线角度的拍摄, 甚至可以通过高速摄像机来进行实时录像, 而像Light Stage 1[1]和Light Stage 2[2]这类需要旋转的光源就无法做到. 构成框体的材料多为金属材料(铝合金), 但也存在木材. 木材的好处在于方便切割, 轻便, 但是易燃, LED发热量大可能引起火灾, 并且木材强度不一定足够. 2.1.1. 移动光源的框体 Debevec, Paul, et al. [1] 使用两根管子来规定光源的移动轨迹, 外部的管子使光源水平移动, 内部的管子使光源竖直移动. 光源固定在内部的管子中央, 从而使光源始终对准人脸, 并围绕着人脸运动.\n优点: 造价低. 缺点: 拍摄时间长, 完整旋转光源拍摄一个人像需要数分钟, 在此期间人和表情不能变动. 光源只有一个. Hawkins, et al. [2] 使用一个可以水平转动的半圆结构转动360度的过程中设定64个方向进行拍摄，结构内壁排列27个光源, 通过转动这个半圆结构来移动光源.\n优点: 光源增加到了27个. 缺点: 拍摄一个人像耗时10秒, 速度依旧不够快. 造价更高. 2.1.2. 固定光源的框体 细分正二十面体: Debevec, Paul, et al. [3] 从2002年的Light Stage 3开始使用固定光源进行拍摄. 框体为一个细分的正二十面体 (Subdivided icosahedron / Pentakis icosidodecahedron), 共有42个顶点, 80个面和120条棱, 直径为2米.\n在每个顶点和每条棱的中点上固定光源, 共162个. 为实验对象进出, 拆掉底部5条棱和一个顶点, 因此实际156个光源.\n底部被垫起80cm，使得装置的赤道与人脸的高度相同.\n类球体框架加上大量光源的优点在于, 可以制造不同强弱的亮度. 并且在光源足够多的时候, 可以使光线模拟连续的反光. 这就可以用来模拟周围环境反射光照到人身上的情景, 从而使不同场景的光照模拟更加真实. Light Stage 6 [5] 使用了更多的光源, 使这个特点更明显.\n同样是细分正二十面体作为框体的还有Light Stage 5 [4] , Light Stage 6[5], ESPER公司Light Stage, Kampouris, et al. [7], Liang, Bin, et al.[9] 和 Pandey, Rohit, et al. [10]. 直径从2.5米到8米不等. 光源还是设置在多边形的棱和顶点上.\n弧形框架: Wang, Zhibo, et al. [8] 和 便携式Light Stage X [11]使用弧形框架, 在人面前固定120度环绕的光源.\nPandey, Rohit, et al. [10] 表示同样使用bidirectional reflectance distribution function (BRDF)的情况下, Wang, Zhibo, et al. [8] 所产生的重照明结果不如他们的结果真实. (原因可能在于照明拍摄设备或框体的差别)\n缺点: 120度环绕的框体无法完全包裹被拍摄对象, 所以在模拟光照的时候比起类球形框体存在劣势.\n优点: 便携式Light Stage X [11]搬动较为方便, 占用的空间更小.\n另外, 便携式Light Stage X [11] 主要用于人物肖像3D建模. 通过不同角度的光照在人像的照片来使3D建模的结果更好.\n2.2. 灯光 LED灯的使用为主流, 购买更方便价格便宜, 体积很小. 相对的氙气频闪灯无法找到购买途径. 另外, 氙气灯的色温不可调节, 不适合做重照明的光源.\nLED反应灵敏, 通直流电时频闪的幅度也比一般的其他光源低很多.[12]\n2.2.1 白色光源 Light Stage 5 [4] 的每个光源都由3个Luxeon V白色LEDs组成, 色温4000K-6500K, 光通量360lm(流明), 产生 420 lux(照度).\n作用: 用白色光源配合通过时间复用照明和高速摄像机来拍摄动态人物. Wang, Zhibo, et al. 2020 [8], 27 white area lights型号未知.\nKampouris, et al. 2018 [7] 使用 iW MR gen3 lamps for white illumination: 色温2700K – 5700K\n作用: 结合RGB和白光LED可以用来控制入射光的光谱.\n白色 LED的相关链接\nhttps://www.mouser.tw/c/optoelectronics/led-lighting/led-emitters/high-power-leds-white/?m=Lumileds\u0026amp;series=LUXEON V\nhttps://item.taobao.com/item.htm?spm=a230r.1.14.4.e76f3c4c8w3UtI\u0026amp;id=557841165570\u0026amp;ns=1\u0026amp;abbucket=6#detail\nhttps://www.lightmoves.com.au/downloads/Documentation/Philips ColorKinetics/iW_MR_gen3_ProductGuide.pdf\n2.2.2 RGB光源 Kampouris, et al. 2018 [7] 和 Light Stage 3 [3] 使用 Color Kinetics 的 iColor MR 光源，细分的正二十面体的顶点安装RGB灯, 含18个红绿蓝LED灯珠; 边安装红外线灯(2.2.3描述)\nLight Stage 6 [5] 使用的是LumiLEDs Luxeon V LEDs灯组. Lumileds Luxeon V 4000K CRI70 LED 的色温 3780-4000, 光通量106-2019 **€2.50=**18元/颗\nLiang, Bin, et al. 2020 [9] 使用深圳红方光电HF-D507W LED灯, 淘宝没有售卖, 但是有类似的替代品, 功率1.5w 单买红绿蓝白每个颜色的灯珠3.5元. 色温范围1200K-6000K\nPandey, Rohit, et al. [10] 使用环形LED加中间的小LED灯组, 品牌型号不明.\nRGB LED的优点: 能更好的模拟周围环境反射光照到人身上的情景.\nRGB LED相关链接\nhttps://led4power.com/product/luxeon-v-4000k-70cri-led-20mm-4040-mosdtp-copper-dtp-mcpcb/\nhttps://budgetlightforum.com/node/60202\nhttps://item.taobao.com/item.htm?spm=a1z0d.6639537.1997196601.4.54e97484g147uv\u0026amp;id=636391510763\n2.2.3 红外线灯 Light Stage 3 [3] 在细分的正二十面体边的中间安装了红外线灯用来照背景, 红外线对人眼和color camera(因为加了可以透过红外线的滤光器(Hoya IR-pass filter))不可见, 可是单色相机(Uniq Vision UP-610 monochrome camera)可以感知. 之后就可以把背景扣掉留下人像.\n2.2.4 偏振片 作用: 通过水平偏振片和垂直偏振片对拍摄到的物体进行抠图. [13] Light Stage 1 [1] 将垂直偏振片放在光源前, 将水平偏振片放在相机前, 用来区分不同角度的光照的反射分量. Light Stage 3 [3] 选择用红外线照亮背景之后过滤而不是使用偏振片. ESPER [6] 和 Liang, Bin, et al. 2020 [9] 在灯前安装偏振片, 都是1组光源中有3个LED灯, 其中1个安装水平偏振片, 1个安装垂直偏振片, 最后一个不加偏振片. 如果1组灯里只有2个LED, 则一个装水平偏振片, 一个装垂直偏振片. 再在相机镜头前装上垂直偏振片. 使用了偏振片可以代替红外线灯加单色相机的组合, 降低成本. Pandey, Rohit, et al. [10]用了加强型的alpha mattes, 所以没有使用偏振片. 2.3 相机 拍摄设备的选用方案分两种, 一种是使用40个左右单反摄像机或60个左右RGB相机, 另一种则是使用一个高速摄像机和一个单色相机. 根据需要的数据不同, 可以二选一. 选用多个单反相机用以在极短时间内各个角度不同光源拍摄人像, 全部收集完之后再集中处理. 选用高速相机则是用来在一个固定视角实时捕捉人物的动作. 而单色相机则是用来配合红外线方便实时抠图. 3. 预计需要的设备 成熟的产品:\n直径2.5米, 光源数量可以定制.\nESPER公司Light Stage 在欧洲, 询问价格目前没有回应.\n框体: 细分的正二十面体. 共有42个顶点, 80个面和120条棱.\n12个五边形接口, 10个六边形接口. (可能需要定制) 直径3米: 边长约为0.82米. 使用木条2cmx2cm 120x7.6 → 912元 不锈钢条15x15mm 0.7mm厚 120cm长 120 → 950元 直径2.5米: 边长约为0.683米. 2.5米的直径用来采集头部到全身. 直径2米: 边长约为0.5465米. (目前空间限制可能2米比较合适) 多用来采集头部到半身像, 要进行全身肖像采集可能需要坐着. 灯光:\n光源的光通量尽可能的大, 否则亮度可能无法模拟真实光照. (不过可以在照相机中调整参数来改善)\nKampouris, et al. 2018 [7] 的方案较便宜, 分别使用白灯和RGB灯的组合来调整色温, 这种7个灯珠的LED灯组可以在淘宝定制, 预计936 (3x156x2) 元. 直径4cm. 但是不能控制每个灯珠. 光通量未知, 功率1.5w.\nLight Stage 6 [5] 使用的 LumiLEDs Luxeon V LEDs 灯组光通量最大可以达到2000LM, 但是需要自己开发, 6边形结构, RGB LED各7个, 白色LED 21个. (2m大小的框体可能用不到这个)\nLumiLEDs Luxeon 15w的每个灯珠淘宝上功率15w的15元左右, 有蓝色和白色. (替代) CREE XML2 RGBW色都有, 光通量 480-1000LM. 15元左右一个灯珠. 42x156x15=98280元 Pandey, Rohit, et al. [10] 方案, 红色灯珠8个, WGB各6个, 型号不明, 用CREE XML2灯珠的话 26x156x15=60840元 (2米的框体的话可以减少灯珠的数量和灯组的大小)\n偏振片 15cmx15cm 156 / 3 * 29 = 1508元\n如果matting能够直接抠图的话, 可以不使用偏振片. 相机\n只拍摄人像的话, 目前看到类球状框体最少需要40个单反相机(直径都在2.5米以上). 直径2米的框体可能需要的相机更少. 使用高速摄像机的话, 并没有找到卖一手Sony DXC-9000 和 单色相机 Uniq Vision UP-610的店. 卖Machine vision camera的店如Phantom Cameras有销售高速相机. Reference [1] Debevec, Paul, et al. \u0026ldquo;Acquiring the reflectance field of a human face.\u0026rdquo; Proceedings of the 27th annual conference on Computer graphics and interactive techniques. 2000.\n[2] Hawkins, Tim, Jonathan Cohen, and Paul Debevec. \u0026ldquo;A photometric approach to digitizing cultural artifacts.\u0026rdquo; Proceedings of the 2001 conference on Virtual reality, archeology, and cultural heritage. 2001.\n[3] Debevec, Paul, et al. \u0026ldquo;A lighting reproduction approach to live-action compositing.\u0026rdquo; ACM Transactions on Graphics (TOG) 21.3 (2002): 547-556.\n[4] Wenger, Andreas, et al. \u0026ldquo;Performance relighting and reflectance transformation with time-multiplexed illumination.\u0026rdquo; ACM Transactions on Graphics (TOG) 24.3 (2005): 756-764.\n[5] Debevec, Paul. \u0026ldquo;The light stages and their applications to photoreal digital actors.\u0026rdquo; SIGGRAPH Asia 2.4 (2012): 1-6.\n[6] ESPER, LightCage \u0026ldquo;https://www.esperhq.com/product/lightcage-scanning-rig/\u0026rdquo;\n[7] Kampouris, Christos, and Abhijeet Ghosh. \u0026ldquo;ICL multispectral light stage: building a versatile LED sphere with off-the-shelf components.\u0026rdquo; Proceedings of the Eurographics 2018 Workshop on Material Appearance Modeling. 2018.\n[8] Wang, Zhibo, et al. \u0026ldquo;Single image portrait relighting via explicit multiple reflectance channel modeling.\u0026rdquo; ACM Transactions on Graphics (TOG) 39.6 (2020): 1-13.\n[9] Liang, Bin, et al. \u0026ldquo;Research on face specular removal and intrinsic decomposition based on polarization characteristics.\u0026rdquo; Optics Express 29.20 (2021): 32256-32270.\n[10] Pandey, Rohit, et al. \u0026ldquo;Total relighting: learning to relight portraits for background replacement.\u0026rdquo; ACM Transactions on Graphics (TOG) 40.4 (2021): 1-21.\n[11] \u0026ldquo;USC Institute for Creative Technologies Helped Create 3D Portraits of President Obama Now on Display at the Smithsonian.\u0026rdquo; https://ict.usc.edu/news/press-releases/usc-institute-for-creative-technologies-helped-create-3d-portraits-of-president-obama-now-on-display-at-the-smithsonian/ 2014.\n[12] \u0026ldquo;LEDs: Fighting Flicker\u0026rdquo; https://www.architectmagazine.com/technology/lighting/leds-fighting-flicker_o 2014.\n[13] Ben-Ezra, Moshe. \u0026ldquo;Segmentation with invisible keying signal.\u0026rdquo; Proceedings IEEE Conference on Computer Vision and Pattern Recognition. CVPR 2000 (Cat. No. PR00662). Vol. 1. IEEE, 2000.\n[14] Sun, Tiancheng, et al. \u0026ldquo;Single Image Portrait Relighting.\u0026rdquo; arXiv e-prints (2019): arXiv-1905.\n部分设备的价格图 LED灯\n其他LED灯\n木条\n偏振片\n重照明设备组件 论文 框架 灯光 相机 背景 其他 Light Stage 1 木制外框架高3米，长宽2米；1.5m铁管x6 照明灯 x1 数码相机 x2 黑色幕布 2mx2m Light Stage 2 可以水平转动的半圆结构，结构内壁排列可以嵌入照明设备 氙气频闪灯 x27 编程控制亮度；频闪次数 Uniq Vision UC-610 x1 拍摄环境不能有其他光源 Sony DXC-9000 x1 Light Stage 3 细分的正二十面体，直径2m；铁管x(120 - 5) Color Kinetics的iColor MR光源，顶点安装RGB灯, 含18个红绿蓝LED灯珠; 而边安装红外线灯 x156 Sony DXC-9000 three-CCD color camera (night shot 摄像功能 + Hoya IR-pass 可以透过红外线的滤光器) x1 环境用哑光的幕布防止反射 三角支架 x1；玻璃分光器 x1 Uniq Vision UP-610 monochrome camera 单色相机 x1 Light Stage 5 同上 每个光源由3个Luxeon V白色LEDs组成，使用偏振片 x156 Vision Research Phantom v7.1 high-speed digital camera. (800x600 分辨率 4800fps) 同上 DLP高速投影仪; 灯光控制器：A Z-World Rabbit 2000 microcontroller drives the lights in arbitrary pattern sequences and triggers the camera’s shutter in sync with each pattern. Canon 1D Mark III x5 Sun, Tiancheng, et al 2019 同上 同上 Machine vision camera x7 Light Stage 6 直径8m，类球形 6,666 LumiLEDs Luxeon V LEDs; To avoid suspending the actor in the air, only the upper 2/3rds of the dome was built and the floor was populated with its own set of Lambertian-distribution light sources. three high-speed cameras ESPER 细分的正二十面体; 直径2.5m 定制光源，每一个光源都由3个LEDs组成，并且三个LED前分别不装偏振片，加装水平偏振片和加装竖直偏振片。 x156 Kampouris, et al. 2018 细分的正二十面体；直径2.5m 两种灯并排：168 iColor MR gen3 lamps for RGB illumination：定制灯可以单独控制三色通道 Canon 800D 全黑背景 168 iW MR gen3 lamps for white illumination: 色温2700K – 5700K PointGrey Grasshopper 3 Wang, Zhibo, et al. 2020 相机放灯左前，3排9列，弧形环绕正对着拍摄对象。 white area lights x27 Sony A5000 cameras x30 Liang, Bin, et al. 2020 细分的正二十面体；直径3m 单灯：深圳红方光电HF-D507W x156 双灯：深圳红方光电HF-D507W，每个光源包含7个LED灯珠；每组光源含两个光源，分别在光源前加装水平偏振片和竖直偏振片 x156组 Canon EOS-1D new: 每个灯中3个LED灯珠；其中一个LED前加装水平偏振片和一个加装竖直偏振片，另一个不装。 DSLR cameras x36 Canon EOS-1D X Mark II x4 Pandey, Rohit, et al. 2021 类球形(猜测4米直径) 可编程 LED 灯(每组26颗LED灯珠分别有 RGBW 4种颜色) x331组 RGB相机 x58 ","permalink":"https://sqf.icu/article/139d3e8d-1bfb-429f-aad0-609a3a82e592/","summary":"\u003ch1 id=\"1-背景\"\u003e1. 背景\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e将人物从一张照片或视频中扣出, 并放入其他光照环境下的照片或视频中时会产生违和感, 那是因为背景中的光和照在人物身上的光的方向和亮度等信息并不相同. 为了使照在人物身上的光与背景光源的信息保持一致, 需要使用人像重照明 (portrait relighting) 技术. 而进行人像重照明任务的深度学习模型需要在不同光照环境下的人像照片数据, 所以需要搭建数据采集设备.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/09353a215d72e08628d6eec3.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"人像重照明数据采集设备调研"},{"content":"1. 将自己的博客加入谷歌的search-console 打开 search-console\nGoogle Search Console\n添加自己的网站域名, 自建博客的话可以选择网址前缀\n确认后, 谷歌会生成一个googlexxxxxxxxxxxxx.html 文件, 将这个文件加入自己博客的public文件夹, 更新博客之后, 就可以完成认证.\n进入自己网站的 search-console 之后, 在顶端的搜索栏搜索自己的网站域名, 会显示网址尚未被收录到 Google, 点击提交请求, 等待1-2分钟, 如果你的网站可以被爬取, 那么会显示网址已收录到 Google.\n一般等待1天就可以在谷歌搜索中查到自己的网站内容.\n可以谷歌搜索: site:[自己网站的域名]\n2. 添加站点地图 在search-console的站点地图中添加sitemap的网址.\n可能会显示无法读取此站点地图, 这时候需要查看自己的网站中 sitemap 地址是不是正确; 域名前缀有没有www. 使用url提交站点地图, 直接用浏览器访问\nhttps://www.google.com/ping?sitemap=https://www.[域名]/sitemap.xml 可能得原因是提交的域名前缀没有www. 如果网站被托管到 vercel 上, 需要再 domain 里将自己的域名前缀加上www, 这时候可能会显示DNS配置错误, 需要vercel自己的dns解析服务. 找到自己买的域名的网站, 对于解析记录中将www记录的值换为 vercel 的 dns 域名.\n也有可能仅仅是谷歌那边的bug, 需要等待.\n谷歌站长工具sitemap站点地图提交状态为[无法获取]的四种解决办法_外贸SEO-小米技术社区\n","permalink":"https://sqf.icu/article/b5875672-2c10-4e10-8b0e-81ea65f6b917/","summary":"\u003ch1 id=\"1-将自己的博客加入谷歌的search-console\"\u003e1. 将自己的博客加入谷歌的search-console\u003c/h1\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003e打开 search-console\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://search.google.com/search-console\"\u003eGoogle Search Console\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e添加自己的网站域名, 自建博客的话可以选择\u003cstrong\u003e网址前缀\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/eaef66605ea8ca84a7edd7bf.png\"\u003e\u003c/p\u003e\n\u003cp\u003e确认后, 谷歌会生成一个\u003ccode\u003egooglexxxxxxxxxxxxx.html\u003c/code\u003e 文件, 将这个文件加入自己博客的\u003ccode\u003epublic\u003c/code\u003e文件夹, 更新博客之后, 就可以完成认证.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e进入自己网站的 search-console 之后, 在顶端的搜索栏搜索自己的网站域名, 会显示网址尚未被收录到 Google, 点击提交请求, 等待1-2分钟, 如果你的网站可以被爬取, 那么会显示网址已收录到 Google.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/c57bc657413552bd92315559.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/dd59bd8b23448afe515498e4.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e一般等待1天就可以在谷歌搜索中查到自己的网站内容.\u003c/p\u003e\n\u003cp\u003e可以谷歌搜索: \u003ccode\u003esite:[自己网站的域名]\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e","title":"谷歌上搜不到我的博客?!"},{"content":"Linux Ubuntu 20.04 系统安装流程\nNVIDIA-SMI has failed because it couldn’t communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.\n$ sudo add-apt-repository ppa:graphics-drivers/ppa $ ubuntu-drivers devices $ sudo apt install nvidia-driver-460 # edit GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub. 可以不用 GRUB_CMDLINE_LINUX_DEFAULT=\u0026#34;quiet splash pci=realloc\u0026#34; or GRUB_CMDLINE_LINUX_DEFAULT=\u0026#34;quiet splash\u0026#34; $ sudo update-grub $ sudo reboot 移动文件夹下所有文件, 包括子文件夹下的内容\nOpen a terminal and execute this command:\nmv -v ~/Downloads/* ~/Videos/ It will move all the files and folders from Downloads folder to Videos folder.\nTo move all files, but not folders:\nIf you are interested in moving all files (but not folders) from Downloads folder to Videos folder, use this command\nfind ~/Downloads/ -type f -print0 | xargs -0 mv -t ~/Videos To move only files from the Download folders, but not from sub-folders:\nIf you want to move all files from the Downloads folder, but not any files within folders in the Download folder, use this command:\nfind ~/Downloads/ -maxdepth 1 -type f -print0 | xargs -0 mv -t ~/Videos here, -maxdepth option specifies how deep find should try, 1 means, only the directory specified in the find command. You can try using 2, 3 also to test.\n文件大小查看命令\n查看某一个文件夹的大小 du -sh [文件夹] 查看当前文件夹下的文件大小总和 ls | wc -l 文件查找命令\n查找遍历文件夹下所有文件后缀为jpg的文件并复制 find [查找文件夹] -name \u0026#34;*.jpg\u0026#34; | xargs -i cp {} [输出文件夹] 批量执行命令 awk\n查找文件后批量处理\nls | grep zip | awk -F . \u0026#39;{system(\u0026#34;echo \u0026#34; $1)}\u0026#39; \u0026#34;ffmpeg -i \u0026#34; $1 \u0026#34;.wav -ar 36000 ../Wave_2/\u0026#34; $1 \u0026#34;.wav\u0026#34; for %a in (\u0026#34;*.wav\u0026#34;) do ffmpeg -i \u0026#34;%a\u0026#34; -ar 36000 \u0026#34;\\%~na.wav\u0026#34; script 输入参数: 直接写 $1 就是第一个参数\n获得当前文件夹名\necho $(basename $(pwd)) DNS服务器地址修改\n找到/etc/resolv.conf\nnameserver 就是DNS服务器地址\n图形界面添加自动启动项\ngnome-session-properties 文本界面设置子启动服务\n写服务文件，如nginx.service、redis.service、supervisord.service\n[Unit]:服务的说明 Description:描述服务 After:描述服务类别 [Service]服务运行参数的设置 Type=forking 是后台运行的形式 ExecStart 为服务的具体运行命令 ExecReload 为服务的重启命令 ExecStop 为服务的停止命令 PrivateTmp=True 表示给服务分配独立的临时空间 注意：启动、重启、停止命令全部要求使用绝对路径 [Install] 服务安装的相关设置，可设置为多用户 WantedBy=multi-user.target 文件保存在目录下：以754的权限。目录路径：/usr/lib/systemd/system/\n设置开机自启动\r[root@localhost ~]# systemctl enable nginx.service\r[root@localhost ~]# systemctl enable supervisord\r停止开机自启动\r[root@localhost ~]# systemctl disable nginx.service\r[root@localhost ~]# systemctl disable supervisord\r验证一下是否为开机启动\r[root@localhost ~]# systemctl is-enabled nginx\r[root@localhost ~]# systemctl is-enabled supervisord 开机自动启动脚本\n写脚本放入/etc/profile.d/\nUbuntu引导损坏 引导修复\n双系统Ubuntu 引导修复（Boot Repair）_碧海凌云的博客-CSDN博客_ubuntu引导修复\nlinux 使用rar\nhttps://www.rarlab.com/download.htm找到对应linux的压缩包\nwget https://www.rarlab.com/rar/rarlinux-x64-6.0.2.tar.gz tar -xvf rarlinux-x64-6.0.2.tar.gz cd rar sudo make # 解压 unrar x xxx.rar # 压缩 ubuntu tar 多线程压缩\n安装pigz\napt-get install -y pigz 压缩文件夹(默认占用所有cpu核心, 占用率50%-80%)\ntar --use-compress-program=pigz -h -cvpf [tar file name] [dir] 解压文件夹\ntar --use-compress-program=pigz -xvpf [tar file name] -C [dir] 需要限制cpu占用的话\ntaskset -c [core number start]-[core number end] [command] 向压缩包里追加文件\ntar -rvf [tar file name] [file you need to add] 格式化新的磁盘\nInstalling A New Hard Drive\nInstallingANewHardDrive\nStart parted as follows: sudo parted /dev/sdb Create a new GPT disklabel (aka partition table): (parted) mklabel gpt Set the default unit to TB: (parted) unit TB Create one partition occupying all the space on the drive. For a 4TB drive: (parted) mkpart\rPartition name? []? primary\rFile system type? [ext2]? ext4\rStart? 0\rEnd? 4 Check that the results are correct: (parted) print There should be one partition occupying the entire drive.\nSave and quit \u0026ldquo;parted\u0026rdquo;: (parted) quit Command Line Formatting To format the new partition as ext4 file system (best for use under Ubuntu):\nsudo mkfs -t ext4 /dev/sdb1 To format the new partition as fat32 file system (best for use under Ubuntu \u0026amp; Windows):\nsudo mkfs -t fat32 /dev/sdb1 As always, substitute \u0026ldquo;/dev/sdb1\u0026rdquo; with your own partition\u0026rsquo;s path.\n匹配k380键盘\n可能成功\nPairing LOGITECH K380 in Ubuntu 20.04\nArch Linux\n开发常用组件安装，遇到gcc之类的基础组件缺失时使用\napt-get install build-essential 向日葵 远程登录失败问题\n需要轻量化桌面\nsudo apt install lightdm 查看某个文件夹下文件或文件夹的数量(递归)\n# 查看文件数量 ls -lR | grep \u0026#34;^-\u0026#34; | wc -l # 查看文件夹数量 ls -lR | grep \u0026#34;^d\u0026#34; | wc -l 非root用户cuda安装\n安装CUDA和cuDNN到指定目录_kxqt233的博客-CSDN博客_cudnn安装位置\n磁盘空间清理\nrm -rf ~/.cache/pip conda clean -a htop设置\n使用htop命令查看进程的时候可以关闭重复线程方便查看 F2 (Setup) -Display options --Hide userland threads F10 (Done) Ubuntu 隐藏上方状态栏、左边任务栏及菜单按钮移到下方居中及隐藏（详细）\nUbuntu 隐藏上方状态栏、左边任务栏及菜单按钮移到下方居中及隐藏（详细）_锵锵锵锵~蒋的博客-CSDN博客_ubuntu隐藏任务栏\nubuntu 20.04 vps 开机自启动\ncd /etc/profile.d/ vim xxx.sh chmod a+x xxx.sh zip相关指令\n1.1. 查看压缩包内容和统计 zip -sf images.zip | grep -v *.jpg | wc -l zip -sf: 查看zip压缩包内容 grep -v: 去除不需要的行, 筛选需要的文件名 wc -l: 按行统计 1.2. 解压压缩包内部分文件 zip -sf images.zip | head -n 10 # 查看压缩包前10行内容 unzip images.zip \u0026#34;images/00001/000003.jpg\u0026#34; -d . # 解压单个文件到当前文件夹 1.3. 批量压缩文件夹并删除原文件夹 find . -maxdepth 1 -type d ! -name \u0026#34;.\u0026#34; -exec sh -c \u0026#39;zip -r -6 \u0026#34;{}.zip\u0026#34; \u0026#34;{}\u0026#34; \u0026amp;\u0026amp; rm -r \u0026#34;{}\u0026#34;\u0026#39; \\; Docker 问题整理 Docker 开发环境配置 1 (1)\n常用命令\ndocker pull ubuntu # get newest ubuntu image docker image ls # check all docker images docker ps -a # show all docker containers docker run -i -t -d [Image ID] bash # create a docker container in the background docker run --runtime=nvidia --name tts --gpus all -it -p 10022:22 [Image ID] docker exec -i -t [Container ID] bash # enter the container docker stop [Container ID] # stop the container docker start [Container ID] # start the container docker build -f Dockerfile . # docker 使用Dockerfile建立镜像 docker network inspect bridge -f \u0026#39;{{json .Containers}}\u0026#39; # host下查看docker的ip地址 换源\n# 打开配置文件 sudo vim /etc/docker/daemon.json # 添加阿里源 { \u0026#34;registry-mirrors\u0026#34;: [\u0026#34;https://md4nbj2f.mirror.aliyuncs.com\u0026#34;] } #重载配置文件 sudo systemctl daemon-reload # 重启docker sudo systemctl restart docker docker中安装使用openvpn\n3分钟快速在 Ubuntu 上安装 OpenVPN\n需要注意的是docker容器需要有host的权限!\ndocker run --privileged xxxxxxxx docker显卡插件\n$curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - $curl -s -L https://nvidia.github.io/nvidia-docker/ubuntu18.04/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list $sudo apt-get update $sudo apt-get install nvidia-docker2 $sudo pkill -SIGHUP dockerd $docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi 删除docker none镜像\n有效的 none 镜像Docker文件系统的组成，docker镜像是由很多 layers组成的，每个 layer之间有父子关系，所有的docker文件系统层默认都存储在/var/lib/docker/graph目录下，docker称之为图层数据库。\n最后做一个总结\u0026lt; none\u0026gt;:\u0026lt; none\u0026gt; 镜像是一种中间镜像，我们可以使用docker images -a来看到，他们不会造成硬盘空间占用的问题（因为这是镜像的父层，必须存在的），但是会给我们的判断带来迷惑。\n无效的 none 镜像\n另一种类型的 \u0026lt; none\u0026gt;:\u0026lt; none\u0026gt; 镜像是dangling images ，这种类型会造成磁盘空间占用问题。\n像Java和Golang这种编程语言都有一个内存区，这个内存区不会关联任何的代码。这些语言的垃圾回收系统优先回收这块区域的空间，将他返回给堆内存，所以这块内存区对于之后的内存分配是有用的\ndocker的悬挂(dangling)文件系统与上面的原理类似，他是没有被使用到的并且不会关联任何镜像，因此我们需要一种机制去清理这些悬空镜像。\n我们在上文已经提到了有效的\u0026lt; none\u0026gt;镜像，他们是一种中间层，那无效的\u0026lt; none\u0026gt;镜像又是怎么出现的？这些 dangling镜像主要是我们触发 docker build 和 docker pull命令产生的。\n使用下面的命令可以清理\nsudo docker rmi $(sudo docker images -f “dangling=true” -q)\ndocker没有自动垃圾回收处理机制，未来可能会有这方面的改进，但是目前我们只能这样手动清理（写个脚本就好）。\nDocker Dockerfile 换源\nRUN sed -i s/deb.debian.org/mirrors.aliyun.com/g /etc/apt/sources.list RUN apt-get clean RUN pip install -U pip RUN pip config set global.index-url http://mirrors.aliyun.com/pypi/simple RUN pip config set install.trusted-host mirrors.aliyun.com 或者直接用-i命令接在install后面 pip install xxx -i https://pypi.douban.com/simple/ 当dockerfile安装失败的时候, 想进入容器debug\n如果在构建Docker镜像时遇到失败，你可以使用**--no-cache**选项强制重新构建，以便解决某些缓存相关的问题。此外，你还可以将失败的构建层作为一个新的容器运行，以便进入容器并手动调试问题。\n要进入失败的Docker构建，首先找到最后一个构建层的ID。在构建过程中，你会看到类似以下内容的输出：\nsqlCopy code\rStep 3/6 : RUN apt-get update \u0026amp;\u0026amp; apt-get install -y software-properties-common \u0026amp;\u0026amp; add-apt-repository ppa:deadsnakes/ppa \u0026amp;\u0026amp; apt-get update \u0026amp;\u0026amp; apt-get install -y python3.6 python3.6-dev python3.6-venv python3-pip\r---\u0026gt; Running in 54f176c9b38d 在这里，**54f176c9b38d**是构建层的ID。构建失败后，使用以下命令创建一个新的容器并运行：\narduinoCopy code\rdocker run -it --rm 54f176c9b38d bash 现在你应该已经进入了容器。你可以手动运行命令来尝试找出导致构建失败的原因。在解决问题后，使用**exit**命令离开容器，并尝试重新构建Docker镜像。\nDocker使用ubuntu初始配置 更新apt-get apt-get update 更换apt-get源\napt-get 换源\n安装cmake\nHow to Install CMake on Ubuntu 20.04 LTS\n挂载宿主机硬盘\n# 使用-v 挂载多个文件夹 docker run --runtime=nvidia --name sqf_mvg -v \u0026#34;/algorithm/:/algorithm/\u0026#34; -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY --gpus all -it --net host sqf_workspace:lastest /bin/bash docker run -it -v \u0026#34;[host dir]:/[docker target dir]\u0026#34; [image id] /bin/bash https://blog.csdn.net/qq_41830712/article/details/90721395 --net 设置网络模式 bridge 模式，使用–net=bridge指定，默认设置。 none 模式，使用–net=none指定。 host 模式，使用–net=host指定。 container 模式，使用–net=container:容器名称或ID指定 对修改的container进行保存\ndocker commit -m=\u0026#34;[new image name]\u0026#34; 7cd5094bf22f [container name]:lastest docker 导入导出容器\n1. 查看容器id docker container ls -a 2. 导出容器 docker export [container id] \u0026gt; xxx.tar 3. 在其他机器导入容器 docker import - [repository name] \u0026lt; xxx.tar docker import之后docker run报错\n**docker: Error response from daemon: No command specified.** 解决方法:\n在docker run命令最后加上command, 一般是/bin/bash\ndocker error 一些服务器在安装用到nvidia服务的Dockerfile的时候可能会报错 Error response from daemon: could not select device driver \u0026#34;\u0026#34; with capabilities: [[gpu]] 原因: host没有安装nvidia适配docker的驱动 # 给apt加上nvidia的安装包的目录 distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list # 更新apt, 安装驱动, 重启dokcer服务 sudo apt-get update sudo apt-get install nvidia-container-runtime sudo service docker restart apt-get update 有时候docker使用apt-get update的时候可能会有下面的报错 Reading package lists... Done W: GPG error: https://developer.download.nvidia.cn/compute/cuda/repos/ubuntu1804/x86_64 InRelease: The following signatures couldn\u0026#39;t be verified because the public key is not available: NO_PUBKEY A4B469963BF863CC\rE: The repository \u0026#39;https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 InRelease\u0026#39; is not signed.\rN: Updating from such a repository can\u0026#39;t be done securely, and is therefore disabled by default.\rN: See apt-secure(8) manpage for repository creation and user configuration details.\r# 解决\rapt-key adv --keyserver keyserver.ubuntu.com --recv-keys A4B469963BF863CC\r# 如果上面一条报错\rgpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-key A4B469963BF863CC \u0026amp;\u0026amp; gpg --export --armor A4B469963BF863CC | apt-key add - 遇到库缺失问题，安装apt-file查找库 apt-get install apt-file apt-file search liblapack apt-file search libblas libatlas-base-dev: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so libatlas3-base: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3 libatlas3-base: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3.10.3 liblapack-dev: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so liblapack3: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3 liblapack3: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1 libopenblas-base: /usr/lib/x86_64-linux-gnu/openblas/liblapack.so.3 libopenblas-dev: /usr/lib/x86_64-linux-gnu/openblas/liblapack.so revolution-mkl: /usr/lib/R/lib/liblapack.so revolution-mkl: /usr/lib/R/lib/liblapack.so.3gf ############### libatlas3-base: /usr/lib/x86_64-linux-gnu/atlas/libblas.so.3 libatlas3-base: /usr/lib/x86_64-linux-gnu/atlas/libblas.so.3.10.3 libblas3: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3 libblas3: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1 libopenblas-base: /usr/lib/x86_64-linux-gnu/openblas/libblas.so.3 revolution-mkl: /usr/lib/R/lib/libblas.so.3gf Proxy和换源 wget 使用代理\nFor all users of the system via the /etc/wgetrcor for the user only with the ~/.wgetrcfile: use_proxy=yes http_proxy=127.0.0.1:8080 https_proxy=127.0.0.1:8080 apt-get 换源\n清华源生成源的路径点下面的链接, 修改**/etc/apt/sources.list**\nubuntu | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror\nsudo apt-get update # 更新源 其他版本\nubuntu镜像-ubuntu下载地址-ubuntu安装教程-阿里巴巴开源镜像站\nalpine修改镜像源\n使用阿里镜像 https://mirrors.aliyun.com\nsed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories\n使用科大镜像 http://mirrors.ustc.edu.cn\nsed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories\nanaconda 安装后替换源\nanaconda换源 pip 换源\npip换源 cmake 使用代理\n需要在CMakeLists.txt文件中添加代理地址\nset(ENV{http_proxy} \u0026#34;http://[url]:[port]\u0026#34;) set(ENV{https_proxy} \u0026#34;https://[url]:[port]\u0026#34;) ","permalink":"https://sqf.icu/article/280d7a1b-5f4e-477e-945c-7e8ecd27d667/","summary":"\u003ch1 id=\"linux\"\u003eLinux\u003c/h1\u003e\n\u003cp\u003eUbuntu 20.04 系统安装流程\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eNVIDIA-SMI has failed because it couldn’t communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e$\u003c/span\u003e sudo add\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eapt\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003erepository ppa:graphics\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003edrivers\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eppa\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e$\u003c/span\u003e ubuntu\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003edrivers devices\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e$\u003c/span\u003e sudo apt install nvidia\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003edriver\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e460\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# edit GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub. 可以不用\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eGRUB_CMDLINE_LINUX_DEFAULT\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;quiet splash pci=realloc\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eor\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eGRUB_CMDLINE_LINUX_DEFAULT\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;quiet splash\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e$\u003c/span\u003e sudo update\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003egrub\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e$\u003c/span\u003e sudo reboot\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e移动文件夹下所有文件, 包括子文件夹下的内容\u003c/p\u003e\n\u003cp\u003eOpen a terminal and execute this command:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003emv  -v ~/Downloads/* ~/Videos/\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eIt will move all the files and folders from Downloads folder to Videos folder.\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003e\u003cstrong\u003eTo move all files, but not folders:\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eIf you are interested in moving all files (but not folders) from Downloads folder to Videos folder, use this command\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003efind ~/Downloads/ -type f -print0 | xargs -0 mv -t ~/Videos\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e\u003cstrong\u003eTo move only files from the Download folders, but not from sub-folders:\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eIf you want to move all files from the Downloads folder, but not any files within folders in the Download folder, use this command:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003efind ~/Downloads/ -maxdepth 1 -type f -print0 | xargs -0 mv -t ~/Videos\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003ehere, \u003ccode\u003e-maxdepth\u003c/code\u003e option specifies how deep find should try, \u003ccode\u003e1\u003c/code\u003e means, only the directory specified in the find command. You can try using \u003ccode\u003e2\u003c/code\u003e, \u003ccode\u003e3\u003c/code\u003e also to test.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e文件大小查看命令\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e查看某一个文件夹的大小\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edu -sh [文件夹]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e查看当前文件夹下的文件大小总和\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003els | wc -l\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e文件查找命令\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e查找遍历文件夹下所有文件后缀为jpg的文件并复制\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efind [查找文件夹] -name \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;*.jpg\u0026#34;\u003c/span\u003e | xargs -i cp {} [输出文件夹]\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e批量执行命令 awk\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e查找文件后批量处理\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003els | grep zip | awk -F . \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;{system(\u0026#34;echo \u0026#34; $1)}\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ffmpeg -i \u0026#34;\u003c/span\u003e $1 \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;.wav -ar 36000 ../Wave_2/\u0026#34;\u003c/span\u003e $1 \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;.wav\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e %a in \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;*.wav\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edo\u003c/span\u003e ffmpeg -i \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%a\u0026#34;\u003c/span\u003e -ar \u003cspan style=\"color:#ae81ff\"\u003e36000\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\\%~na.wav\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003escript 输入参数:\n直接写 $1 就是第一个参数\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e获得当前文件夹名\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003ebasename \u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003epwd\u003cspan style=\"color:#66d9ef\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eDNS服务器地址修改\u003c/p\u003e\n\u003cp\u003e找到/etc/resolv.conf\u003c/p\u003e\n\u003cp\u003enameserver 就是DNS服务器地址\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e图形界面添加自动启动项\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egnome-session-properties\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e文本界面设置子启动服务\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e写服务文件，如nginx.service、redis.service、supervisord.service\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eUnit\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e:服务的说明\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDescription:描述服务\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAfter:描述服务类别\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eService\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e服务运行参数的设置\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eType\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eforking            是后台运行的形式\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStart               为服务的具体运行命令\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecReload              为服务的重启命令\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStop                为服务的停止命令\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePrivateTmp\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eTrue         表示给服务分配独立的临时空间\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e注意：启动、重启、停止命令全部要求使用绝对路径\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eInstall\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e               服务安装的相关设置，可设置为多用户\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWantedBy\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003emulti-user.target\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e文件保存在目录下：以754的权限。目录路径：/usr/lib/systemd/system/\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e设置开机自启动\r\n[root@localhost ~]# systemctl enable nginx.service\r\n[root@localhost ~]# systemctl enable supervisord\r\n\n停止开机自启动\r\n[root@localhost ~]# systemctl disable nginx.service\r\n[root@localhost ~]# systemctl disable supervisord\r\n\n验证一下是否为开机启动\r\n[root@localhost ~]# systemctl is-enabled nginx\r\n[root@localhost ~]# systemctl is-enabled supervisord\n\u003c/code\u003e\u003c/pre\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e开机自动启动脚本\u003c/p\u003e\n\u003cp\u003e写脚本放入/etc/profile.d/\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUbuntu引导损坏 引导修复\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://blog.csdn.net/u012260238/article/details/52713724\"\u003e双系统Ubuntu 引导修复（Boot Repair）_碧海凌云的博客-CSDN博客_ubuntu引导修复\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003elinux 使用rar\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://www.rarlab.com/download.htm\"\u003ehttps://www.rarlab.com/download.htm\u003c/a\u003e找到对应linux的压缩包\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ewget https://www.rarlab.com/rar/rarlinux-x64-6.0.2.tar.gz\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etar -xvf rarlinux-x64-6.0.2.tar.gz\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd rar \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo make \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 解压\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eunrar x xxx.rar\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 压缩\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eubuntu tar 多线程压缩\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e安装\u003cstrong\u003epigz\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt-get install -y pigz\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e压缩文件夹(默认占用所有cpu核心, 占用率50%-80%)\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etar --use-compress-program\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003epigz -h -cvpf \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003etar file name\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edir\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e解压文件夹\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etar --use-compress-program\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003epigz -xvpf \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003etar file name\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e -C \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edir\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e需要限制cpu占用的话\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etaskset -c \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ecore number start\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e-\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ecore number end\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ecommand\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e向压缩包里追加文件\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etar -rvf \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003etar file name\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003efile you need to add\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e格式化新的磁盘\u003c/p\u003e\n\u003cp\u003eInstalling A New Hard Drive\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://help.ubuntu.com/community/InstallingANewHardDrive\"\u003eInstallingANewHardDrive\u003c/a\u003e\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eStart parted as follows:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003esudo parted /dev/sdb\n\u003c/code\u003e\u003c/pre\u003e\u003col start=\"2\"\u003e\n\u003cli\u003eCreate a new GPT disklabel (aka partition table):\u003c/li\u003e\n\u003c/ol\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e(parted) mklabel gpt\n\u003c/code\u003e\u003c/pre\u003e\u003col start=\"3\"\u003e\n\u003cli\u003eSet the default unit to TB:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e(parted) unit TB\n\u003c/code\u003e\u003c/pre\u003e\u003col start=\"4\"\u003e\n\u003cli\u003eCreate one partition occupying all the space on the drive. For a 4TB drive:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e(parted) mkpart\r\nPartition name?  []? primary\r\nFile system type?  [ext2]? ext4\r\nStart? 0\r\nEnd? 4\n\u003c/code\u003e\u003c/pre\u003e\u003col start=\"5\"\u003e\n\u003cli\u003eCheck that the results are correct:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e(parted) print\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThere should be one partition occupying the entire drive.\u003c/p\u003e\n\u003col start=\"6\"\u003e\n\u003cli\u003eSave and quit \u0026ldquo;parted\u0026rdquo;:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e(parted) quit\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"command-line-formatting\"\u003eCommand Line Formatting\u003c/h3\u003e\n\u003cp\u003eTo format the new partition as ext4 file system (best for use under Ubuntu):\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003esudo mkfs -t ext4 /dev/sdb1\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eTo format the new partition as fat32 file system (best for use under Ubuntu \u0026amp; Windows):\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003esudo mkfs -t fat32 /dev/sdb1\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eAs always, substitute \u0026ldquo;/dev/sdb1\u0026rdquo; with your own partition\u0026rsquo;s path.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e匹配k380键盘\u003c/p\u003e\n\u003cp\u003e可能成功\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://unix.stackexchange.com/questions/590221/pairing-logitech-k380-in-ubuntu-20-04\"\u003ePairing LOGITECH K380 in Ubuntu 20.04\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://bbs.archlinux.org/viewtopic.php?id=195886\u0026amp;p=2\"\u003eArch Linux\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e开发常用组件安装，遇到gcc之类的基础组件缺失时使用\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eget install build\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eessential\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e向日葵 远程登录失败问题\u003c/p\u003e\n\u003cp\u003e需要轻量化桌面\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt install lightdm\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e查看某个文件夹下文件或文件夹的数量(递归)\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 查看文件数量\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003els -lR | grep \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;^-\u0026#34;\u003c/span\u003e | wc -l\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 查看文件夹数量\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003els -lR | grep \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;^d\u0026#34;\u003c/span\u003e | wc -l\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e非root用户cuda安装\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://blog.csdn.net/kxqt233/article/details/113825524\"\u003e安装CUDA和cuDNN到指定目录_kxqt233的博客-CSDN博客_cudnn安装位置\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e磁盘空间清理\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erm \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003erf \u003cspan style=\"color:#f92672\"\u003e~/.\u003c/span\u003ecache\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003epip\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econda clean \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ea\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ehtop设置\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e使用htop命令查看进程的时候可以关闭重复线程方便查看\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eF2 \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eSetup\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-Display options\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e--Hide userland threads\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eF10 \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eDone\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUbuntu 隐藏上方状态栏、左边任务栏及菜单按钮移到下方居中及隐藏（详细）\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://blog.csdn.net/weixin_43629813/article/details/100525856\"\u003eUbuntu 隐藏上方状态栏、左边任务栏及菜单按钮移到下方居中及隐藏（详细）_锵锵锵锵~蒋的博客-CSDN博客_ubuntu隐藏任务栏\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eubuntu 20.04 vps 开机自启动\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd /etc/profile.d/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003evim xxx.sh\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003echmod a+x xxx.sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ezip相关指令\u003c/p\u003e\n\u003ch2 id=\"11-查看压缩包内容和统计\"\u003e1.1. 查看压缩包内容和统计\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ezip -sf images.zip | grep -v *.jpg | wc -l\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003ezip -sf: 查看zip压缩包内容\u003c/li\u003e\n\u003cli\u003egrep -v: 去除不需要的行, 筛选需要的文件名\u003c/li\u003e\n\u003cli\u003ewc -l: 按行统计\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"12-解压压缩包内部分文件\"\u003e1.2. 解压压缩包内部分文件\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ezip -sf images.zip | head -n \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e# 查看压缩包前10行内容\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eunzip images.zip \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;images/00001/000003.jpg\u0026#34;\u003c/span\u003e -d .  \u003cspan style=\"color:#75715e\"\u003e# 解压单个文件到当前文件夹\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"13-批量压缩文件夹并删除原文件夹\"\u003e1.3. 批量压缩文件夹并删除原文件夹\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-jsx\" data-lang=\"jsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003efind\u003c/span\u003e . \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003emaxdepth\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;.\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eexec\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esh\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ec\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;zip -r -6 \u0026#34;{}.zip\u0026#34; \u0026#34;{}\u0026#34; \u0026amp;\u0026amp; rm -r \u0026#34;{}\u0026#34;\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\\\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":"Linux 问题整理"},{"content":"PIP spacepy安装失败\npip install git+https://github.com/spacepy/spacepy.git pip换源\n修改 ~/.pip/pip.conf (没有就创建一个)\n[global] timeout = 6000 index-url = https://pypi.tuna.tsinghua.edu.cn/simple trusted-host = pypi.tuna.tsinghua.edu.cn 使用默认源\npip install 模块名 -i https://pypi.org/simple 快速使用指定源\npip install 模块名 -i https://pypi.tuna.tsinghua.edu.cn/simple pip install 模块名 -i https://pypi.douban.com/simple/ 使用proxy下载, 开着vpn就无法使用第三方源, 这时需要使用—-proxy\n--proxy http://127.0.0.1:xxxx conda直接输入\nwindows terminal 调用虚拟环境\n# 管理员打开powershell set-executionpolicy remotesigned Anaconda python 3.8 使用pip报错.\nurllib3版本过高, 降低urllib3版本 使用国内服务器 pip install requests==2.20 或者使用下面的命令降低版本： pip install urllib3==1.25.8 pip install urllib3==1.25.11 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com python virtualenv 下配置 pip\n查找pip调用配置的路径\npip config -v list 当前项目文档下的venv文件夹中打开pip.ini, 配置\n如: pip使用阿里pip源\n[global] index-url = http://mirrors.aliyun.com/pypi/simple [install] trusted-host=mirrors.aliyun.com 系统环境\ncd %appdata% mkdir pip cd pip vim pip.ini [global] timeout = 6000 index-url = https://pypi.tuna.tsinghua.edu.cn/simple trusted-host = pypi.tuna.tsinghua.edu.cn Python-获取图片的大小\npip install pillow # 安装pillow import os from PIL import Image path = os.path.join(os.getcwd(),\u0026#34;23.png\u0026#34;) img = Image.open(path) print img.format # PNG print img.size # (3500, 3500) anaconda换源\nanaconda | 镜像站使用帮助 | 北京外国语大学开源软件镜像站 | BFSU Open Source Mirror\nvim ~/.condarc\nchannels: - defaults show_channel_urls: true default_channels: - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2 custom_channels: conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud pytorch-lts: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud 运行 conda clean -i 清除索引缓存，保证用的是镜像站提供的索引。\nanaconda 虚拟环境 export 环境\nManaging environments - conda 4.10.3.post41+bc22d85c documentation\nAnaconda export Environment file\nconda create -n myenv python=3.8.8 # 创建 conda remove --name myenv --all # 删除 # 导出环境 conda env export | grep -v \u0026#34;^prefix: \u0026#34; \u0026gt; environment.yml # 创建环境, 并导入包 conda env create -f environment.yml wsl conda 无法联网\n可能原因：未知\n解决：重启wsl\nwsl —shutdown 与宿主机无法连通？\nhttps://www.notion.so/Windows-7f41180ff12e4bdf898333cae5f49b9f#3e925add567d432d90849684676c2716 keras tensorflow 版本问题\n版本问题\u0026mdash;keras和tensorflow的版本对应关系\ntorch 多卡训练环境配置\n# 环境 conda update -n base conda conda install pytorch torchvision torchaudio cudatoolkit=11.1 -c pytorch -c nvidia # 删除yolov5/requirements.txt中以下三个包 - opencv-python[version=\u0026#39;\u0026gt;=4.1.2\u0026#39;] - torch[version=\u0026#39;\u0026gt;=1.7.0\u0026#39;] - thop conda install --yes --file requirements.txt pip 安装上面三个包 Jupyter notebook windows 使用jupyter notebook，远程使用jupyter notebook\n服务器端安装anaconda\n打开Anaconda Prompt，输入jupyter notebook \u0026ndash;generate-config生成配置文件，并记录路径。\n继续在Anaconda Prompt中输入ipython，然后输入from notebook.auth import passwd，最后输入passwd()，设置密码，然后复制输出生成的密钥文件。\n从第一步记录的路径找到配置文件，使用记事本打开配置文件。\n在配置文件中添加以下命令，并设置访问端口和拷贝生成的密钥。\nc.NotebookApp.ip = \u0026#39;*\u0026#39; # 设置远程所有ip可访问 c.NotebookApp.open_browser = False # 关闭浏览器 c.NotebookApp.password=u\u0026#39;密钥\u0026#39; # 输入上面生成的密钥 c.NotebookApp.port = 8888 # 设置SSH访问的端口 c.NotebookApp.allow_remote_access = True # 允许远程连接 花生壳内网映射http，访问限制不开。\n生成后，Anaconda Prompt输入\njupyter notebook # 保持开启状态 浏览器打开获得的网址就行。（网址不需要写端口）\njupyter notebook 使用虚拟环境\n虚拟环境下安装jupyter notebook\nconda install nb_conda jupyter notebook kernel切换（切换虚拟环境）\n需要在这个虚拟环境中安装ipykernel\npython -m ipykernel install --user --name py27 # py27是目标虚拟环境名 jupyter notebook 配置自动代码补全和Markdown文件的目录\n进入base环境\npip install jupyter_contrib_nbextensions # 没有设置源的话： -i https://pypi.mirrors.ustc.edu.cn/simple jupyter contrib nbextension install --user pip install jupyter_nbextensions_configurator jupyter nbextensions_configurator enable --user 安装成功后，关掉Jupyter notebook重新打开，观察是否安装成功，即多了一个nbextensions。\njupyter里ipynb和py文件的相互转换\n在name.ipynb所在目录下打开终，输入以下命令\njupyter nbconvert --to script name.ipynb # name.ipynb是要转换文件的名字，转换后在name.ipynb所在目录下出现name.py文件 jupyter notebook 快捷键\nJupyter Notebook 有两种键盘输入模式。 编辑模式，允许你往单元中键入代码或文本；这时的单元框线是绿色的。 命令模式，键盘输入运行程序命令；这时的单元框线是灰色。 命令模式 (按键 Esc 开启)快捷键： Enter : 转入编辑模式 Shift-Enter : 运行本单元，选中下个单元 Ctrl-Enter : 运行本单元 Alt-Enter : 运行本单元，在其下插入新单元 Y : 单元转入代码状态 M :单元转入markdown状态 R : 单元转入raw状态 设定 1 级标题 设定 2 级标题 设定 3 级标题 设定 4 级标题 设定 5 级标题 设定 6 级标题 Up : 选中上方单元 K : 选中上方单元 Down : 选中下方单元 J : 选中下方单元 Shift-K : 扩大选中上方单元 Shift-J : 扩大选中下方单元 A : 在上方插入新单元 B : 在下方插入新单元 X : 剪切选中的单元 C : 复制选中的单元 Shift-V : 粘贴到上方单元 V : 粘贴到下方单元 Z : 恢复删除的最后一个单元 D,D : 删除选中的单元 Shift-M : 合并选中的单元 Ctrl-S : 文件存盘 S : 文件存盘 L : 转换行号 O : 转换输出 Shift-O : 转换输出滚动 Esc : 关闭页面 Q : 关闭页面 H : 显示快捷键帮助 I,I : 中断Notebook内核 0,0 : 重启Notebook内核 Shift : 忽略 Shift-Space : 向上滚动 Space : 向下滚动 编辑模式 ( Enter 键启动)下快捷键 Tab : 代码补全或缩进 Shift-Tab : 提示 Ctrl-] : 缩进 Ctrl-[ : 解除缩进 Ctrl-A : 全选 Ctrl-Z : 复原 Ctrl-Shift-Z : 再做 Ctrl-Y : 再做 Ctrl-Home : 跳到单元开头 Ctrl-Up : 跳到单元开头 Ctrl-End : 跳到单元末尾 Ctrl-Down : 跳到单元末尾 Ctrl-Left : 跳到左边一个字首 Ctrl-Right : 跳到右边一个字首 Ctrl-Backspace : 删除前面一个字 Ctrl-Delete : 删除后面一个字 Esc : 进入命令模式 Ctrl-M : 进入命令模式 Shift-Enter : 运行本单元，选中下一单元 Ctrl-Enter : 运行本单元 Alt-Enter : 运行本单元，在下面插入一单元 Ctrl-Shift-- : 分割单元 Ctrl-Shift-Subtract : 分割单元 Ctrl-S : 文件存盘 Shift : 忽略 Up : 光标上移或转入上一单元 Down :光标下移或转入下一单元 Pycharm 服务器show图片失败, 远程无法显示图片\n# 服务器没装图形化界面 apt-get install xorg openbox # 只需要安装qt pip install pyqt5 使用MobaXterm_Personal_22.0远程登陆server或直接ssh远程登陆server(X11协议开启) 需要保持登陆的状态 echo $DISPLAY #查看显示设备 localhost:14.0 # 显示结果 export DISPLAY=localhost:14.0 之后就能显示imshow图片了 方法2\nFile-\u0026gt;Settings-\u0026gt;Plugins OpenCV Image Viewer Packages tqdm\n迭代器 tqdm(iterator) 可以将任意For循环显示成进度条形式\n使用方式\n# original for ele in list: ... # tqdm for ele in tqdm(list): ... # change tqdm log l = tqdm(list) for ele in l: l.set_description(f\u0026#34;xxx: {ele}\u0026#34;) ... # tqdm interval log l = tqdm(list) for ele in l: l.update(10) # 间隔10个循环更新一次信息 ... l.close() # 关闭tqdm 多线程\nfrom multiprocessing import Pool def apply(): \u0026#34;\u0026#34;\u0026#34; 多线程所调用apply方法 :return: list_crop: 处理完成的列表片段 \u0026#34;\u0026#34;\u0026#34; return list_crop def init_process(g_var1, g_var2, g_var3): \u0026#34;\u0026#34;\u0026#34; 全局函数, 初始化线程 :param global_vars: 全局的参数 g_var1 g_var2 g_var3 :return: \u0026#34;\u0026#34;\u0026#34; global input_path, output_path, first_use input_path, output_path, first_use = g_var1, g_var2, g_var3 list_crop # 待处理列表的切片(切成线程的分数) with Pool(processes=8, initializer=init_process, initargs=(input_path, output_path, first_use,)) as pool: list_crop_done = apply(list_crop) # 一个线程处理一个切片 res_list += list_crop_done # 处理完后叠加到结果list librosa\n使用python对音频进行降采样\ny_48k, sr = librosa.load(wav_filename, 48000) # 读取原音频 y_16k = librosa.resample(y=y_48k, orig_sr=48000, targe_sr=16000) # 降采样 nohup无法打印python的print函数\n是print的缓存问题 nohup python -u test.py \u0026gt;\u0026gt; nohup.out 2\u0026gt;\u0026amp;1 \u0026amp; python运行脚本时打印信息同时保存信息\npython xxx.py 2\u0026gt;\u0026amp;1 | tee [log file] Vscode 问题 vsode python format 格式化失效\n打开设置，搜索python.formatting.provider，选择autopep8\npip install pep8 pip install --upgrade autopep8 2023年python.formatting.provider 可能已经找不到了, 会出现以下问题 formatter server 启动失败 报错 You have deprecated linting or formatting settings for Python [duplicate] The setting \u0026quot;editor.defaultFormatter\u0026quot; for Python is set to \u0026quot;ms-python.python\u0026quot; which is deprecated. 解决方法 vscode 配置文件, 就是那个json文件中, 注释掉灰色的代码 (目前不适用的代码) \u0026quot;[python]\u0026quot;: editor.defaultFormatter 如果是ms-python.python, 改成autopep8. vscode 无法远程连接问题\n如果遇到没log但是无法远程连接的问题, 直接kill服务器所有关于vscode的进程 还有问题就删除服务器中.vscode-server文件夹. 关闭账号设置同步 降低vscode版本 vscode python debug 路径问题\n只需要在debug的文件开头调整路径就行\nimport os import sys os.chdir(sys.path[0]) ","permalink":"https://sqf.icu/article/ec997159-93c7-4572-b0d4-61b5f5284f94/","summary":"\u003ch1 id=\"pip\"\u003ePIP\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003espacepy安装失败\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip install git+https://github.com/spacepy/spacepy.git\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003epip换源\u003c/p\u003e\n\u003cp\u003e修改 ~/.pip/pip.conf (没有就创建一个)\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[\u003cspan style=\"color:#66d9ef\"\u003eglobal\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etimeout \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e6000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eindex\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eurl \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e https:\u003cspan style=\"color:#f92672\"\u003e//\u003c/span\u003epypi\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etuna\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etsinghua\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eedu\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ecn\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003esimple\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etrusted\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ehost \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e pypi\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etuna\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etsinghua\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eedu\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ecn\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e使用默认源\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003epip install 模块名 -i https://pypi.org/simple\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e快速使用指定源\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip install 模块名 -i https://pypi.tuna.tsinghua.edu.cn/simple\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip install 模块名 -i https://pypi.douban.com/simple/\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e使用proxy下载, 开着vpn就无法使用第三方源, 这时需要使用\u003ccode\u003e—-proxy\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e--proxy http://127.0.0.1:xxxx\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003ca href=\"https://so.csdn.net/so/search?q=conda\u0026amp;spm=1001.2101.3001.7020\"\u003econda\u003c/a\u003e直接输入\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ewindows terminal 调用虚拟环境\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 管理员打开powershell\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eset-executionpolicy remotesigned\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":"Python 问题整理"},{"content":"Windows 10 win10下使用vim\nwin10-PowerShell下使用vim_秋雨、、的博客-CSDN博客_powershell vim\nwindows启动时隐藏cmd窗口\n隐藏system窗口你也行（就是那个cmd窗口，好多方法）_冷月醉雪的博客-CSDN博客\n删除Windows10侧边栏项目\n如果您需要删除【资源管理器】左边面板的OneDrive图标，您可以尝试：\n前往C:\\Users\u0026lt;用户名\u0026gt;，看看有没有不需要的文件夹\n如果有关OneDrive图标依然存在，您可以登陆管理者账号，然后参考下方方法：\n注册表为系统的主要档案，任何修改可能会导致系统档案损毁。\n请您在修改注册表前衡量风险。\n有关备份注册表的方法，请参考微软官方资讯：\nhttp://support.microsoft.com/kb/322756\n同时按【win键+R】，输入regedit，打开【注册表】\n前往【hkey_current_user\\software\\microsoft\\windows\\currentversion\\explorer\\desktop\\NameSpace】\n左边面板，【NameSpace】文件夹下，点击不同的文件\n右边面板，留意【数据】栏部分，找到与您不需要的OneDrive账户的相关文件夹\n左边面板，对有关文件夹，右键删除\n重启电脑，看看效果\nwsl虚拟机无法ping host\n改防火墙规则\nWSL2 unable to ping host machine · Issue #4171 · microsoft/WSL\nssh 端口映射\nssh -L [收听接口:]收听端口:目标主机:目标端口 username@hostname # 多端口 ssh remote-host -L 8822:REMOTE_IP_1:22 -L 9922:REMOTE_IP_2:22 vscode正则表达式批量替换\n查找：\u0026#34;static/(.*).css 替换：\u0026#34;static/css/$1.css # $1是group1匹配到内容之后需要保留的变量. ([A-Za-z-0-9\\.\u0026#39; ,?\\\\:\\/!;%$@\u0026amp;()—£={}\u0026lt;\u0026gt;á`ñ’´\\[\\]*\\^]+)\t([A-Za-z-0-9\\.\u0026#39; ,?\\\\:\\/!;%$@\u0026amp;()—£={}\u0026lt;\u0026gt;á`ñ’´\\[\\]*\\^]+) windows openssh 安装\nwindows 会出现openssh安装失败的情况\n常规安装方法\n其他方法\n基于PowerShell的OpenSSH下载最新软件：\nhttps://github.com/PowerShell/Win32-OpenSSH/releases 到openssh安装文件夹下, 运行命令\npowershell.exe -ExecutionPolicy Bypass -File \u0026#34;D:\\Download\\OpenSSH-Win64\\install-sshd.ps1\u0026#34; # 启动ssh net start sshd # 设定自启动, 也可以直接在服务中启用自动 sc.exe config sshd start= auto 如果自启动失败(windows10 [SC] OpenSCManager 失败 5)\n此问题是因为用户没有在控制账号下登录，所以安装出问题（新装的系统，没有设置登录密码）。 运行\u0026ndash;\u0026gt;输入regedit\u0026ndash;\u0026gt;依次找到HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\ 将EnableLUA的值改为0，最后重启电脑，再次操作，即可。 进服务, 设定两项openssh服务为自动\n启动服务后可以通过 netstat 命令查看 SSH Server 服务是不是已经开始监听默认的 22 号端口了：\n打开C:\\ProgramData\\ssh\\sshd_config 修改端口\nPort 65001 PubkeyAuthentication yes 客户端创建公钥\nkeygen -R # 服务器将公钥放入administrators_authorized_keys文件中 cd C:\\ProgramData\\ssh mv id_rsa.pub administrators_authorized_keys ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC01uhrVXfP83HroGkgFvJauDUa86RG9JkhDShIVFVt6wBZfy+CHmZkl2HrZL064njETE8eNwtBJwSATRuPb5TsQv7i2+7RGOusRNpx3+/hoUW4fypBUn8qyPzw+OimjAQKvNF3kp1WZ8YZ7aeogZzTOeCejAPJ4Y26Rth5r3g4e0sk5J+lI/tTyw7bpB2qkxRa2SSbfBsuVcnyejAkYK5rQzG6Du4ckVl2d5d9mdZ24lzI8KF3s2m1/EcZI1w5VVy9dwmfp3CEIZxVqNQySIbvk18ZyJhanAjnjtmmlwX4V4ULdUyQ32dGc7+HMBBY1ec4ThOjPP0m58fYvn6sBIkL45Kh2SNpF1tHrmdj3AHkJ1/oac7ZqxjJsWTObG4TQ8puoCQVPNt+SzQI2c7d0dNWxfjlYTw8QduYH5kFZSng+KqaLbnldg9vrRy3+cYXyEtt2oM2tYjxvQUmCg5QEQIoZDjFDYcGwmwx0FgBkjBmoqxywj0pYJLzeFsJGZxZ1Mk= sun@DESKTOP-L98U77R 解决VM 与 Device/Credential Guard 不兼容。在禁用 Device/Credential Guard 后，可以运行 VM 的方法\n步骤一：禁用Device Guard或Credential Guard：\n禁用用于启用Credential Guard的组策略设置。 在主机操作系统上，右键单击“开始” \u0026gt; “运行”，键入gpedit.msc，然后单击“ 确定”。本地组策略编辑器打开。 转至本地计算机策略 \u0026gt; 计算机配置 \u0026gt; 管理模板\u0026gt;系统 \u0026gt;Device Guard（或者是： 设备防护） \u0026gt; 启用基于虚拟化的安全性。 选择已禁用。\n转到“ 控制面板” \u0026gt;“ 卸载程序” \u0026gt;“ 打开或关闭Windows功能”以关闭Hyper-V。 选择不重启。\n步骤二：通过命令关闭Hyper-V（控制面板关闭Hyper-V起不到决定性作用，要彻底关闭Hyper-V）\n以管理员身份运行Windows Powershell (管理员)（Windows键+X）\nbcdedit /set hypervisorlaunchtype off 重启.\n$‘\\r‘: command not found的解决方法\n去除Shell脚本的\\r字符： sed -i \u0026#39;s/\\r//\u0026#39; one-more.sh faststone 注册码\nname：bluman\rserial/序列号/注册码：VPISCJULXUFGDDXYAUYF windows下读取ext4格式磁盘\n官方下载地址：\nhttps://china.paragon-software.com/home-windows/extfs-for-windows/download.html\nParagon ExtFS for Windows 4.2.651\n下载安装\n然后下载补丁 V1.2 by TSRh\nparagon.extfs.fixed.winall.read.nfo.keygen-tsrh\n把keygen和另外两个文件放到ExtFS的安装目录下\n我的安装目录是 \u0026ldquo;C:\\Program Files (x86)\\Paragon Software\\ExtFS for Windows\u0026quot;\n打开keygen，先点击Patch RSA 2048，选择安装目录下的\nParagon ExtFS for Windows.exe\n再次点击 Patch RSA 2048，选择安装目录下的\nextservice.exe\n点击Generate让生成License，keygen会重启ExtFS的服务。\n之后打开 ExtFS 就发现已经破解完成。\n双系统罗技k380配对\n系统及蓝牙键盘信息：\nWindows版本：Windows 7 Ubuntu版本：Ubuntu 12.04(64位) 蓝牙键盘：罗技K480\n首先在Ubuntu下进行配对。使用ubuntu自带的蓝牙菜单进行配对，提示的配对密码是错误的。需要使用hcidump工具查找出真正的密码。详细步骤如下：\n打开终端，输入如下命令安装bluez-hcidump sudo apt-get install bluez-hcidump 使用hcidump工具开始抓取蓝牙配对密码 sudo hcidump -at | grep pass 在Ubuntu蓝牙菜单中，按照提示添加设备。 Ubuntu搜索到蓝牙键盘后，点击连接。此时hcidump会抓到正确的密码，如下所示，在蓝牙键盘上输入此密码并按回车即可配对成功。（切记不要输入配对菜单提示的错误密码） bdaddr 00:1F:20:F0:EF:75 passkey 224095 (注意记录下此处蓝牙键盘的物理地址 00:1F:20:F0:EF:75）\n进入windows进行重新配对，配对成功后，上述ubuntu的配对则会失效。因为配对的key信息已经修改。我们要做的是取出当前蓝牙键盘与windows配对使用的key，将其复制到Ubuntu下的linkkeys文件即可。 下载PsExec: http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx 解压后，找到PsExec.exe. 右键点击，在其属性-\u0026gt;兼容性中勾选“以管理员身份运行此程序” 运行cmd, 进入命令行，切换到PsExec.exe所在的目录，执行如下命令打开注册表编辑器：PsExec.exe -s -i regedit.exe 找到HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet002\\services\\BTHPORT\\Parameters\\Keys\\aa1111111111\\00:1F:20:F0:EF:75中的数据项（如f33a8cadac63b019e8533590b2821357)，记录下来。（自己敲键盘记住吧，无法直接复制）\n计算机\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\BTHPORT\\Parameters\\Keys\\f8e4e3e5ae56 将windows下配对产生的key复制到Ubuntu配对文件中。 重启进入Ubuntu 将在windows中记录的key信息，找到文件/var/lib/bluetooth/AA:11:11:11:11:11/linkkeys的对应00:1F:20:F0:EF:75的配对信息，替换掉。 重启ubuntu（必须重启，否则使用的还是原来的key信息） 系统无故自动重启\n【Kernel-Power】系统已在未先正常关机的情况下重新启动。如果系统停止响应、发生崩溃或意外断电，则可能会导致此错误。\n系统代理，网盘和网页 移除google,baidu搜索引擎广告\n使用关键字屏蔽uBlacklist，不需要网址屏蔽了\nGitHub - cobaltdisco/Google-Chinese-Results-Blocklist: 我终于能用谷歌搜中文了\u0026hellip;\u0026hellip;\n网址屏蔽\nGoogle 搜索在采集站的攻势下已经残废了，必须得配上『Google Hit Hider by Domain』才能使用 - V2EX\n长期维护网址：\nhttps://raw.githubusercontent.com/cobaltdisco/Google-Chinese-Results-Blocklist/master/GHHbD_perma_ban_list.txt https://pastebin.com/pMmmMM3G https://github.com/ron159/trash_sites Windows microsoft store 打不开问题，windows terminal安装打不开\n终极解决方案\nClash使用期间无法使用Outlook和OneNote · Issue #123 · Fndroid/clash_for_windows_pkg\n本质还是clash开启了系统代理的问题，不过Clash有选项可以改部分软件的代理使用方式\n打开General-UWP Lookback\n勾选 你的账户 - microsoft账户 Microsoft 便签 Microsoft Store Office OneNote for Windows 10 之后点Save Changes 旧方案\n解决应用商店打不开 代码: 0x80131500\n解决\n关闭系统代理\nclash把系统代理临时关了就行。\n或\n关闭自动更新\n没有设置按钮？似乎没大用。\n需要等待连接，连接失败也会出现设置按钮。 还没有：开始-设置搜索store-修复应用商店 修复结果可能是没有开用户权限，修复完就能点设置按钮了。 OneDrive 同步任意文件夹\n想要通过onedrive同步备份一个工作文件夹。依次打开OneDrive：设置-备份-管理备份，发现默认只能备份特定的文件夹，而我只想备份文档中的一个子文件夹。 以管理员身份打开cmd命令行, 建立软连接\nmklink /d \u0026#34;C:\\Users\\XXX\\OneDrive\\doc\u0026#34; \u0026#34;C:\\Users\\XXX\\Documents\\doc\u0026#34; 不需要提前在OneDrive中新建doc文件夹，输入该命令后，会自动创建该文件夹。\nOneDrive 不走 Clash proxy 代理\n修改setting中的parser. 注意在设定后parsers会写入yaml文件. parsers: # array - url: xxxx yaml: prepend-rules: - DOMAIN-SUFFIX,onedrive.com,China-Websites - DOMAIN-KEYWORD,onedrive,China-Websites - DOMAIN-SUFFIX,onedrive.live.com,China-Websites - DOMAIN-SUFFIX,khaitanpublicschool-my.sharepoint.com,China-Websites - DOMAIN-KEYWORD,steam,🇭🇰 香港 06 - DOMAIN-SUFFIX,steampowered.com,🇭🇰 香港 06 - DOMAIN-SUFFIX,steam-chat.com,🇭🇰 香港 06 - DOMAIN-SUFFIX,steamgames.com,🇭🇰 香港 06 - DOMAIN-SUFFIX,steamusercontent.com,🇭🇰 香港 06 - DOMAIN-SUFFIX,steamcontent.com,🇭🇰 香港 06 - DOMAIN-SUFFIX,steamstatic.com,🇭🇰 香港 06 - DOMAIN-SUFFIX,steamcdn-a.akamaihd.net,🇭🇰 香港 06 - DOMAIN-SUFFIX,store.st.dl.pinyuncloud.com,🇭🇰 香港 06 - DOMAIN-SUFFIX,media.st.dl.pinyuncloud.com,🇭🇰 香港 06 - DOMAIN-SUFFIX,cdn.akamai.steamstatic.com,🇭🇰 香港 06 Clash使用Parser添加自定义规则并防止更新覆盖\nwindows下映射阿里云\nCloudDrive可以解决所有问题, 一步到位.\nrclone更好\nWindows平台下使用 Rclone 挂载 OneDrive 为本地硬盘\nRcloneBroswer\nWindows平台下使用 Rclone 挂载 OneDrive 为本地硬盘\n安装docker\n需要wsl, 安装完docker for windows desktop客户端之后, 打开url\nWin10上Docker无法正常启动 出现install WSL2 kernel update的情况_LeungSr的博客-CSDN博客\n安装RaiDrive\nRaiDrive | Cloud Storage like a USB drive\n获取阿里云token\n阿里云盘\n管理员打开powershell\ndocker run -d --name=aliyunpan-webdav --restart=always -p 1180:8080 -v /etc/localtime:/etc/localtime -v /volume1/docker/aliyunpan_webdav:/etc/aliyun-driver/ -e TZ=\u0026#34;Asia/Shanghai\u0026#34; -e ALIYUNDRIVE_REFRESH_TOKEN=\u0026#34;阿里云盘的token\u0026#34; -e ALIYUNDRIVE_AUTH_PASSWORD=\u0026#34;访问密码\u0026#34; zx5253/webdav-aliyundriver 加上token后, port 51001 docker run -d --name=aliyunpan-webdav --restart=always -p 51001:8080 -v /etc/localtime:/etc/localtime -v /volume1/docker/aliyunpan_webdav:/etc/aliyun-driver/ -e TZ=\u0026#34;Asia/Shanghai\u0026#34; -e ALIYUNDRIVE_REFRESH_TOKEN=\u0026#34;24052a4af3fa46c4af9d92dcf31ac41b\u0026#34; -e ALIYUNDRIVE_AUTH_PASSWORD=\u0026#34;1GE9mAvev\u0026#34; zx5253/webdav-aliyundriver 浏览器打开127.0.0.1:51001\nuser: admin; pw: 刚输入的密码 使用RaiDrive\n群晖同步阿里云盘及Win电脑加载阿里云盘映射本地磁盘（网络磁盘）\ngithub代理\ngit config --global http.proxy \u0026#34;192.168.99.1:65003\u0026#34; git config --global https.proxy \u0026#34;192.168.99.1:65003\u0026#34; go 模块 proxy 代理\ngo moudle模块加载被墙解决方法_leiax00-CSDN博客\n始终无法连接？\n可能是系统时间不正确： 无法安装其他语言的输入法\nDownload Windows 10 1909 ISO 19H2 Language Pack [October 2019]\nLanguage Packs for Windows 11/10/8.1/7\n软件 下载道客巴巴,百度,之类的文档\n冰点文库和小叶文库下载器挂了后如何下载百度文库/豆丁/道客巴巴文档\nwindows md5 校验工具\nCertUtil -hashfile \u0026lt;path to file\u0026gt; MD5 Windows安装miniconda\n下载软件安装即可\n需要添加环境变量\nC:\\Users\\sunqi\\miniconda3 C:\\Users\\sunqi\\miniconda3\\Scripts C:\\Users\\sunqi\\miniconda3\\Library\\bin Windows安装git\n下载软件安装即可\n需要添加环境变量\nC:\\Program Files\\Git\\bin ","permalink":"https://sqf.icu/article/be49755c-60cd-4625-a930-94e00a43ef08/","summary":"\u003ch1 id=\"windows-10\"\u003eWindows 10\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003ewin10下使用vim\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://blog.csdn.net/qq_37933114/article/details/82932840\"\u003ewin10-PowerShell下使用vim_秋雨、、的博客-CSDN博客_powershell vim\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ewindows启动时隐藏cmd窗口\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://blog.csdn.net/lengyuezuixue/article/details/81209925\"\u003e隐藏system窗口你也行（就是那个cmd窗口，好多方法）_冷月醉雪的博客-CSDN博客\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e删除Windows10侧边栏项目\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/1df0d1a65123cff2bd75eeaa.png\"\u003e\u003c/p\u003e\n\u003cp\u003e如果您需要删除【资源管理器】左边面板的OneDrive图标，您可以尝试：\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003e前往C:\\Users\u0026lt;用户名\u0026gt;，看看有没有不需要的文件夹\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e如果有关OneDrive图标依然存在，您可以登陆管理者账号，然后参考下方方法：\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003chr\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e注册表为系统的主要档案，任何修改可能会导致系统档案损毁。\u003c/p\u003e\n\u003cp\u003e请您在修改注册表前衡量风险。\u003c/p\u003e\n\u003cp\u003e有关备份注册表的方法，请参考微软官方资讯：\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://support.microsoft.com/kb/322756\"\u003ehttp://support.microsoft.com/kb/322756\u003c/a\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003chr\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003col start=\"3\"\u003e\n\u003cli\u003e\n\u003cp\u003e同时按【win键+R】，输入regedit，打开【注册表】\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e前往【hkey_current_user\\software\\microsoft\\windows\\currentversion\\explorer\\desktop\\NameSpace】\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e左边面板，【NameSpace】文件夹下，点击不同的文件\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e右边面板，留意【数据】栏部分，找到与您不需要的OneDrive账户的相关文件夹\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e左边面板，对有关文件夹，右键删除\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e重启电脑，看看效果\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ewsl虚拟机无法ping host\u003c/p\u003e\n\u003cp\u003e改防火墙规则\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/microsoft/WSL/issues/4171\"\u003eWSL2 unable to ping host machine · Issue #4171 · microsoft/WSL\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003essh 端口映射\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003essh -L \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e收听接口:\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e收听端口:目标主机:目标端口 username@hostname\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 多端口\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003essh remote-host -L 8822:REMOTE_IP_1:22 -L 9922:REMOTE_IP_2:22\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003evscode正则表达式批量替换\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e查找\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e：\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;static/(.*).css\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e替换\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e：\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;static/css/$1.css  # $1是group1匹配到内容之后需要保留的变量.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e([A\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eZa\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ez\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e9\u003c/span\u003e\\\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; ,?\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\\\\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e:\\/!;%$@\u0026amp;()—£=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026lt;\u0026gt;á`ñ’´\\[\\]*\\^]+)\t([A-Za-z-0-9\\.\u0026#39;\u003c/span\u003e ,\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e?\u003c/span\u003e\\\\:\\\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e!\u003c/span\u003e;\u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e$\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e@\u0026amp;\u003c/span\u003e()\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e—£\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{}\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003eá\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e`\u003c/span\u003eñ\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e’´\u003c/span\u003e\\[\\]\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\\\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ewindows openssh 安装\u003c/p\u003e\n\u003cp\u003ewindows 会出现openssh安装失败的情况\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e常规安装方法\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/eb628e89054eb04f59558ab9.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/1efa2bb48b661e315d38dbd0.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e其他方法\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e基于PowerShell的OpenSSH下载最新软件：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/PowerShell/Win32-OpenSSH/releases\"\u003ehttps://github.com/PowerShell/Win32-OpenSSH/releases\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e到openssh安装文件夹下, 运行命令\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epowershell.exe -ExecutionPolicy Bypass -File \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;D:\\Download\\OpenSSH-Win64\\install-sshd.ps1\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 启动ssh\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enet start sshd\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 设定自启动, 也可以直接在服务中启用自动\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esc.exe config sshd start\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e auto\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e如果自启动失败(windows10 [SC] OpenSCManager 失败 5)\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e此问题是因为用户没有在控制账号下登录，所以安装出问题（新装的系统，没有设置登录密码）。\u003c/li\u003e\n\u003cli\u003e运行\u0026ndash;\u0026gt;输入regedit\u0026ndash;\u0026gt;依次找到HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\\u003c/li\u003e\n\u003cli\u003e将EnableLUA的值改为0，最后重启电脑，再次操作，即可。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e进服务, 设定两项openssh服务为自动\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/99b841c2712b4180dc7f9aac.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e启动服务后可以通过 netstat 命令查看 SSH Server 服务是不是已经开始监听默认的 22 号端口了：\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/0f52d5f0cf5a4a1451dc8410.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e打开C:\\ProgramData\\ssh\\sshd_config 修改端口\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePort \u003cspan style=\"color:#ae81ff\"\u003e65001\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePubkeyAuthentication yes\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e客户端创建公钥\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ekeygen -R \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 服务器将公钥放入administrators_authorized_keys文件中\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd C:\u003cspan style=\"color:#ae81ff\"\u003e\\P\u003c/span\u003erogramData\u003cspan style=\"color:#ae81ff\"\u003e\\s\u003c/span\u003esh mv id_rsa.pub administrators_authorized_keys\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003essh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC01uhrVXfP83HroGkgFvJauDUa86RG9JkhDShIVFVt6wBZfy+CHmZkl2HrZL064njETE8eNwtBJwSATRuPb5TsQv7i2+7RGOusRNpx3+/hoUW4fypBUn8qyPzw+OimjAQKvNF3kp1WZ8YZ7aeogZzTOeCejAPJ4Y26Rth5r3g4e0sk5J+lI/tTyw7bpB2qkxRa2SSbfBsuVcnyejAkYK5rQzG6Du4ckVl2d5d9mdZ24lzI8KF3s2m1/EcZI1w5VVy9dwmfp3CEIZxVqNQySIbvk18ZyJhanAjnjtmmlwX4V4ULdUyQ32dGc7+HMBBY1ec4ThOjPP0m58fYvn6sBIkL45Kh2SNpF1tHrmdj3AHkJ1/oac7ZqxjJsWTObG4TQ8puoCQVPNt+SzQI2c7d0dNWxfjlYTw8QduYH5kFZSng+KqaLbnldg9vrRy3+cYXyEtt2oM2tYjxvQUmCg5QEQIoZDjFDYcGwmwx0FgBkjBmoqxywj0pYJLzeFsJGZxZ1Mk\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e sun@DESKTOP-L98U77R\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e解决VM 与 Device/Credential Guard 不兼容。在禁用 Device/Credential Guard 后，可以运行 VM 的方法\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e步骤一：禁用Device Guard或Credential Guard：\u003c/p\u003e\n\u003cp\u003e禁用用于启用Credential Guard的组策略设置。\n在主机操作系统上，右键单击“开始” \u0026gt; “运行”，键入gpedit.msc，然后单击“ 确定”。本地组策略编辑器打开。\n转至本地计算机策略 \u0026gt; 计算机配置 \u0026gt; 管理模板\u0026gt;系统 \u0026gt;Device Guard（或者是： 设备防护） \u0026gt; 启用基于虚拟化的安全性。\n选择已禁用。\u003c/p\u003e\n\u003cp\u003e转到“ 控制面板” \u0026gt;“ 卸载程序” \u0026gt;“ 打开或关闭Windows功能”以关闭Hyper-V。\n选择不重启。\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e步骤二：通过命令关闭Hyper-V（控制面板关闭Hyper-V起不到决定性作用，要彻底关闭Hyper-V）\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e以管理员身份运行Windows Powershell (管理员)（Windows键+X）\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebcdedit /set hypervisorlaunchtype off\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e重启.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e$‘\\r‘: command not found的解决方法\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e去除Shell脚本的\u003cspan style=\"color:#ae81ff\"\u003e\\r\u003c/span\u003e字符：\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esed -i \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;s/\\r//\u0026#39;\u003c/span\u003e one-more.sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003efaststone 注册码\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ename：bluman\r\nserial/序列号/注册码：VPISCJULXUFGDDXYAUYF\n\u003c/code\u003e\u003c/pre\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ewindows下读取ext4格式磁盘\u003c/p\u003e\n\u003cp\u003e官方下载地址：\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://china.paragon-software.com/home-windows/extfs-for-windows/download.html\"\u003ehttps://china.paragon-software.com/home-windows/extfs-for-windows/download.html\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eParagon ExtFS for Windows 4.2.651\u003c/p\u003e\n\u003cp\u003e下载安装\u003c/p\u003e\n\u003cp\u003e然后下载补丁 V1.2 by TSRh\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://www.hopolcn.com/wp-content/uploads/2019/01/paragon.extfs_.fixed_.winall.read_.nfo_.keygen-tsrh.zip\"\u003eparagon.extfs.fixed.winall.read.nfo.keygen-tsrh\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e把keygen和另外两个文件放到ExtFS的安装目录下\u003c/p\u003e\n\u003cp\u003e我的安装目录是 \u0026ldquo;C:\\Program Files (x86)\\Paragon Software\\ExtFS for Windows\u0026quot;\u003c/p\u003e\n\u003cp\u003e打开keygen，先点击Patch RSA 2048，选择安装目录下的\u003c/p\u003e\n\u003cp\u003eParagon ExtFS for Windows.exe\u003c/p\u003e\n\u003cp\u003e再次点击 Patch RSA 2048，选择安装目录下的\u003c/p\u003e\n\u003cp\u003eextservice.exe\u003c/p\u003e\n\u003cp\u003e点击Generate让生成License，keygen会重启ExtFS的服务。\u003c/p\u003e\n\u003cp\u003e之后打开 ExtFS 就发现已经破解完成。\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e双系统罗技k380配对\u003c/p\u003e\n\u003cp\u003e系统及蓝牙键盘信息：\u003c/p\u003e\n\u003cp\u003eWindows版本：Windows 7\nUbuntu版本：Ubuntu 12.04(64位)\n蓝牙键盘：罗技K480\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003e首先在Ubuntu下进行配对。使用ubuntu自带的蓝牙菜单进行配对，提示的配对密码是错误的。需要使用hcidump工具查找出真正的密码。详细步骤如下：\u003c/p\u003e\n\u003cp\u003e打开终端，输入如下命令安装bluez-hcidump\nsudo apt-get install bluez-hcidump\n使用hcidump工具开始抓取蓝牙配对密码\nsudo hcidump -at | grep pass\n在Ubuntu蓝牙菜单中，按照提示添加设备。\nUbuntu搜索到蓝牙键盘后，点击连接。此时hcidump会抓到正确的密码，如下所示，在蓝牙键盘上输入此密码并按回车即可配对成功。（切记不要输入配对菜单提示的错误密码）\nbdaddr 00:1F:20:F0:EF:75 passkey 224095  (注意记录下此处蓝牙键盘的物理地址 00:1F:20:F0:EF:75）\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e进入windows进行重新配对，配对成功后，上述ubuntu的配对则会失效。因为配对的key信息已经修改。我们要做的是取出当前蓝牙键盘与windows配对使用的key，将其复制到Ubuntu下的linkkeys文件即可。\n下载PsExec: \u003ca href=\"http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx\"\u003ehttp://technet.microsoft.com/en-us/sysinternals/bb897553.aspx\u003c/a\u003e\n解压后，找到PsExec.exe. 右键点击，在其属性-\u0026gt;兼容性中勾选“以管理员身份运行此程序”\n运行cmd, 进入命令行，切换到PsExec.exe所在的目录，执行如下命令打开注册表编辑器：PsExec.exe -s -i regedit.exe\n找到HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet002\\services\\BTHPORT\\Parameters\\Keys\\aa1111111111\\00:1F:20:F0:EF:75中的数据项（如f33a8cadac63b019e8533590b2821357)，记录下来。（自己敲键盘记住吧，无法直接复制）\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Untitled\" loading=\"lazy\" src=\"/media/08eb082bf0b168102023220e.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e计算机\u003cspan style=\"color:#ae81ff\"\u003e\\H\u003c/span\u003eKEY_LOCAL_MACHINE\u003cspan style=\"color:#ae81ff\"\u003e\\S\u003c/span\u003eYSTEM\u003cspan style=\"color:#ae81ff\"\u003e\\C\u003c/span\u003eurrentControlSet\u003cspan style=\"color:#ae81ff\"\u003e\\S\u003c/span\u003eervices\u003cspan style=\"color:#ae81ff\"\u003e\\B\u003c/span\u003eTHPORT\u003cspan style=\"color:#ae81ff\"\u003e\\P\u003c/span\u003earameters\u003cspan style=\"color:#ae81ff\"\u003e\\K\u003c/span\u003eeys\u003cspan style=\"color:#ae81ff\"\u003e\\f\u003c/span\u003e8e4e3e5ae56\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col\u003e\n\u003cli\u003e将windows下配对产生的key复制到Ubuntu配对文件中。\n重启进入Ubuntu\n将在windows中记录的key信息，找到文件/var/lib/bluetooth/AA:11:11:11:11:11/linkkeys的对应00:1F:20:F0:EF:75的配对信息，替换掉。\n重启ubuntu（必须重启，否则使用的还是原来的key信息）\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e系统无故自动重启\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://answers.microsoft.com/zh-hans/windows/forum/all/kernel/157196ea-3b24-4f2e-a249-0ce502d33680\"\u003e【Kernel-Power】系统已在未先正常关机的情况下重新启动。如果系统停止响应、发生崩溃或意外断电，则可能会导致此错误。\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"Windows 问题整理"},{"content":"Hugging face hugging face的预训练模型下载慢的问题（使用BertModel.from_pretrained()等下载慢）_#苦行僧的博客-CSDN博客 (1)\n[国内HuggingFace，预训练模型镜像使用_A_zhangpengjie的博客-CSDN博客 (1)](%E5%9B%BD%E5%86%85HuggingFace%EF%BC%8C%E9%A2%84%E8%AE%AD%E7%BB%83%E6%A8%A1%E5%9E%8B%E9%95%9C%E5%83%8F%E4%BD%BF%E7%94%A8_A_zhangpengjie%E7%9A%84%E5%8D%9A%E5%AE%A2-CSDN%E5%8D%9A%E5%AE%A2%20%28.md\nGithub问题 git错误 You are not currently on a branch的解决办法\n今天使用 git pull和git push 命令，分别报错：\nYou are not currently on a branch, so I cannot use any\r\u0026#39;branch.\u0026lt;branchname\u0026gt;.merge\u0026#39; in your configuration file.\rPlease specify which remote branch you want to use on the command\rline and try again (e.g. \u0026#39;git pull \u0026lt;repository\u0026gt; \u0026lt;refspec\u0026gt;\u0026#39;).\rSee git-pull(1) for details. fatal: You are not currently on a branch.\rTo push the history leading to the current (detached HEAD)\rstate now, use\rgit push origin HEAD:\u0026lt;name-of-remote-branch\u0026gt; 这是什么意思呢？ 说我当前不是在分支上，因此不能 pull 或者 push\n然后利用git branch查看一下，发现：\ngit branch\r* (HEAD detached from bdcfe3d8)\r* master\r* issue68 我当前所处的位置是在HEAD detached from bdcfe3d8上\n所以进行如下操作\ngit branch temp bdcfe3d8\rgit checkout master\rgit merge temp 这三行命令的意思是：\n依据快照bdcfe3d8 创建 temp 分支 切换到 master 分支 将 temp 分支合并到 master分支 再看一下所有的分支\ngit branch\r* master\r* issue68\r* temp 这时候就可以进行 git pull 和 git push 了 记得删除 temp 分支哦\ngit branch -d temp git 加tag\ngit tag # 查看所有tag git log # 获取当前版本的编号 git tag -a v1.0 9fceb02 # 加上tag git show v1.0 # 查看指定tag git push origin v1.0 # 上传tag # 下载指定的tag 版本 git clone --branch \u0026lt;tag\u0026gt; \u0026lt;url\u0026gt; 删除某个已经push的commit\n先将本地的项目指向错误的commit之前的一个commit (这个操作会删除该commit之后的所有代码更改, 记得备份现有代码) git reset –-hard \u0026lt;commit hash\u0026gt; 更安全地进行强制推送, --force-with-lease 可以不使用本地分支的提交强行覆盖远端推送分支. git push --force-with-lease git push to branch\ngit show # 找到HEAD git push origin \u0026lt;HEAD\u0026gt;:\u0026lt;branch\u0026gt; git branch\nGit 版本控制系統(2) 開 branch 分支和操作遠端 repo.\nGit如何忽略已经上传的文件或文件夹？\n背景：使用IDEA新建项目，有时候会不小心将.idea文件夹上传上去，由于缓存的存在，之后再在.gitignore中添加这个文件夹就无效了，需要清除掉缓存.gitignore才会生效\ngit rm --cached \u0026lt;file\u0026gt;\n这个命令会直接从暂存区删除文件，工作区则不做出改变。\ngit rm --cached命令比git reset head更好，前者是删除掉，后者是替换掉。\n加上-r参数可以进行递归删除 eg: git rm -r --cached .idea/ 执行这个指令之后，需要重新提交代码，这个时候相当于提交了一个删除远程指定文件的请求，但是本地文件不会删除，而且.gitignore可以生效了\nnpm安装 npm install 报错 npm install error from the terminal\nnpm i --legacy-peer-deps ","permalink":"https://sqf.icu/article/c2ba6510-5ed9-4a8b-9397-6e9cefcfa73e/","summary":"\u003ch1 id=\"hugging-face\"\u003eHugging face\u003c/h1\u003e\n\u003cp\u003ehugging face的预训练模型下载慢的问题（使用BertModel.from_pretrained()等下载慢）_#苦行僧的博客-CSDN博客 (1)\u003c/p\u003e","title":"其他问题整理"}]