Add files via upload
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
### 介绍下 SVM
|
||||
|
||||
**SVM 的核心思想:寻找最佳分隔超平面**
|
||||
|
||||
想象一下,你有一堆红色的球和蓝色的球,你想用一根线把它们分开。你可以画出无数条线,但哪条线是最好的呢?
|
||||
|
||||
SVM 的答案是:那条离**最近**的红色球和蓝色的球都最远的线
|
||||
|
||||
在二维空间中,这个“线”就是一个**分隔平面**(Separating Plane)。在三维空间中,它是一个平面。在更高维度的空间中,我们称它为**超平面**(Hyperplane)
|
||||
|
||||
- **支持向量(Support Vectors)**:这些“最近”的数据点就是**支持向量**。它们是距离超平面最近的那些训练样本点,它们决定了超平面的位置。如果移除或移动这些支持向量,超平面的位置可能会发生变化。但如果移动那些离超平面很远的数据点,超平面则保持不变
|
||||
- **最大间隔(Maximal Margin)**:超平面到最近支持向量的距离被称为**间隔**(Margin)。SVM 的目标就是找到一个超平面,使得这个间隔最大化。这个最大间隔的超平面就是最优超平面
|
||||
|
||||
**线性可分与非线性可分**
|
||||
|
||||
**1. 线性可分(Linear SVM)**
|
||||
|
||||
当数据可以被一条直线(或一个超平面)完美分开时,我们称其为**线性可分**。在这种情况下,我们可以直接使用上面提到的最大间隔方法来找到最优超平面。
|
||||
|
||||
**2. 非线性可分(Kernel SVM)**
|
||||
|
||||
大多数情况下,数据点并非线性可分。例如,红色球和蓝色球可能混合在一起,你无法用一条直线将它们完全分开
|
||||
|
||||
这就是 SVM 强大之处的体现:**核技巧**(Kernel Trick)
|
||||
|
||||
核技巧的核心思想是,将原始的低维数据**映射**到一个更高维度的空间,在这个高维空间中,数据变得**线性可分**了
|
||||
|
||||
举个例子:一个二维的圆环,内圈是蓝色,外圈是红色。在二维平面上,你无法用一条直线将它们分开。但是,如果我们将这些点映射到三维空间,它们可能就会在一个平面上呈“碗状”分布,这时我们就可以用一个平面将它们分开了
|
||||
|
||||
常用的核函数有:
|
||||
|
||||
- **线性核(Linear Kernel)**:当数据本身线性可分时使用
|
||||
- **多项式核(Polynomial Kernel)**:可以将低维数据映射到高维
|
||||
- **径向基函数核(RBF Kernel)**:也叫高斯核,这是最常用、最强大的核函数之一,它能够将样本映射到无穷维度的空间,从而处理非常复杂的数据集
|
||||
|
||||
**软间隔与惩罚参数 C**
|
||||
|
||||
在现实世界中,完美的分隔几乎不存在,数据集中往往会有一些“异常值”或“噪声”点,它们会混入另一个类别。如果我们坚持找到一个完美的超平面,模型可能会**过拟合**
|
||||
|
||||
为了解决这个问题,SVM 引入了**软间隔(Soft Margin)**的概念。它允许一些数据点“越界”,即它们可以出现在间隔内部,甚至位于错误的一侧
|
||||
|
||||
- **惩罚参数 C(Penalty Parameter C)**:这个参数用来控制**容忍度**
|
||||
- **C 值很小**:模型容忍度高,允许更多数据点越界。这会使间隔更大,但可能会导致一些误分类,因此更不容易过拟合
|
||||
- **C 值很大**:模型容忍度低,对错误分类的惩罚很高。这会使间隔变小,模型试图精确地分离所有训练数据,因此更容易过拟合
|
||||
|
||||
选择合适的 C 值是一个重要的调优步骤
|
||||
@@ -0,0 +1,45 @@
|
||||
### 如何降低模型的误报率
|
||||
|
||||
**1. 调整决策阈值**
|
||||
|
||||
这是最直接、最常用的方法
|
||||
|
||||
- **原理**:分类模型通常会输出一个概率值,例如,预测一个邮件是垃圾邮件的概率为0.8。我们设定一个**决策阈值**(比如0.5),如果概率高于这个阈值,就预测为“垃圾邮件”
|
||||
- **如何操作**:为了降低误报率,我们可以**提高这个决策阈值**。如果我们将阈值从0.5提高到0.7,模型只有在对一个邮件有更高的信心时,才会将其标记为垃圾邮件。这样做会减少误报,但代价是可能会增加漏报(False Negative),即遗漏掉一些真正的垃圾邮件
|
||||
- **适用场景**:当你更看重准确性(Precision)而不是召回率(Recall)时,例如在金融诈骗检测中,宁可漏掉一些诈骗,也不想错误地阻止用户的正常交易
|
||||
|
||||
**2. 收集更多高质量的负样本**
|
||||
|
||||
**负样本**(Negative Samples)指的是不属于你所关注的类别的样本
|
||||
|
||||
- **原理**:模型之所以误报,是因为它可能没有见过足够多的负样本,或者负样本的种类太少,导致它对“负类别”的理解不够全面。当一个负样本的特征与正样本(你关注的类别)相似时,模型就很容易误判
|
||||
- **如何操作**:
|
||||
- **增加负样本数量**:尽可能收集更多不属于目标类别的数据,让模型有更多机会去学习真正的“负类”是什么样的
|
||||
- **增加负样本多样性**:特别关注那些容易被误报的**“困难负样本”**(Hard Negative Samples),并将它们加入训练集。这能强制模型学习更细粒度的边界,从而更好地区分正负样本
|
||||
- **适用场景**:当你的数据集存在严重的类别不平衡问题时
|
||||
|
||||
**3. 重新设计特征**
|
||||
|
||||
模型的性能很大程度上取决于你给它什么样的数据
|
||||
|
||||
- **原理**:如果模型总是误报某个特定类型的样本,很可能是因为当前的特征无法很好地区分这个样本和目标类别。
|
||||
- **如何操作**:
|
||||
- **添加新特征**:思考并提取一些能更好地区分正负样本的新特征。例如,在垃圾邮件识别中,除了关键词,还可以加入发件人信誉度、邮件格式异常等特征
|
||||
- **特征选择**:移除那些与目标无关或有误导性的特征,这可以帮助模型更专注于重要的信息
|
||||
- **适用场景**:当你发现模型的误报不是随机的,而是集中在某一类特定数据上时
|
||||
|
||||
**4. 调整损失函数或使用惩罚项**
|
||||
|
||||
- **原理**:标准的交叉熵损失函数对正负样本的错误预测给予相同的惩罚。为了降低误报,我们可以对误报(FP)给予更大的惩罚
|
||||
- **如何操作**:
|
||||
- **自定义损失函数**:设计一个**加权的损失函数**,给误报(将负样本预测为正样本)赋予更高的权重,让模型在训练过程中更努力地避免这种错误
|
||||
- **Focal Loss**:这是一种专门用于处理类别不平衡问题的损失函数,它能降低对那些易于分类的样本的权重,而更关注那些难以分类的样本,从而迫使模型去学习区分那些“困难”的负样本
|
||||
- **适用场景**:在类别极度不平衡,且误报代价极高的场景
|
||||
|
||||
**5. 集成学习**
|
||||
|
||||
- **原理**:集成学习通过结合多个模型的预测结果来提高整体性能。这可以减少单个模型因过拟合或对数据敏感而产生的误报
|
||||
- **如何操作**:
|
||||
- **投票法**:训练多个不同的模型,让它们对同一个样本进行预测,最终由多数模型投票决定结果。这可以有效减少单个模型出错带来的影响
|
||||
- **提升法(Boosting)**:如 **LightGBM** 或 **XGBoost**。这些算法会顺序地训练一系列弱分类器,每个后续分类器都会重点关注前一个分类器错误分类的样本,尤其是那些容易被误报的样本
|
||||
- **适用场景**:当你拥有足够的数据和计算资源来训练多个模型时
|
||||
@@ -0,0 +1,40 @@
|
||||
### 如何找攻击样本
|
||||
|
||||
**1. 基于梯度的攻击**
|
||||
|
||||
这是最常见、最基础的一类攻击方法,利用模型的梯度信息来生成扰动
|
||||
|
||||
- **原理**:利用反向传播,计算损失函数相对于输入图像的梯度。这个梯度表示了如果对图像的像素进行微小改变,会如何影响模型的预测结果。通过沿着这个梯度方向对图像进行调整,可以最大化模型的损失,从而导致模型分类错误
|
||||
- **代表算法**:
|
||||
- **快速梯度符号法(FGSM, Fast Gradient Sign Method)**:一种非常高效的单步攻击。它计算损失函数对输入图像的梯度,然后沿着梯度的正负号方向给图像加上一个微小的扰动
|
||||
- **基本迭代方法(BIM, Basic Iterative Method)/FGSM 迭代版**:FGSM 的多次迭代版本。它在每一步迭代中都计算梯度并进行小幅调整,以更精确地将图像推向模型的决策边界之外
|
||||
- **优点**:计算效率高,生成速度快
|
||||
- **缺点**:生成的对抗样本可能不够隐蔽,有时会留下人眼可见的痕迹
|
||||
|
||||
**2. 基于优化的攻击**
|
||||
|
||||
这类方法将寻找对抗样本看作一个优化问题,旨在找到最小的扰动,同时确保模型分类失败
|
||||
|
||||
- **原理**:设定一个优化目标,比如最小化扰动的大小(通常用L2或L∞范数来衡量),同时满足模型对新样本的预测结果是错误的
|
||||
- **代表算法**:
|
||||
- **Carlini & Wagner(C&W)攻击**:这是最强大的白盒攻击之一。它通过一个精心设计的损失函数,可以生成非常小且难以被防御方法检测到的对抗样本。这种攻击的成功率非常高,但计算成本也相对较高
|
||||
- **优点**:生成的对抗样本扰动非常小,视觉效果极佳,难以被发现
|
||||
- **缺点**:计算复杂,生成速度慢
|
||||
|
||||
**3. 基于生成模型的攻击**
|
||||
|
||||
这类方法利用生成对抗网络(GAN)来生成对抗样本,而非直接基于梯度或优化
|
||||
|
||||
- **原理**:训练一个生成器网络,它可以将随机噪声或正常样本作为输入,直接生成对抗性扰动。这个生成器被训练来欺骗一个分类器(判别器)
|
||||
- **优点**:一旦生成器训练好,生成对抗样本的速度非常快,几乎可以实时生成
|
||||
- **缺点**:生成器的训练过程复杂且不稳定,可能需要大量数据和计算资源
|
||||
|
||||
**4. 黑盒攻击**
|
||||
|
||||
以上方法都是**白盒攻击**,即需要知道模型的内部结构和参数。而**黑盒攻击**则更具挑战性,它不需要知道模型的内部信息,只能通过输入和输出来寻找攻击样本
|
||||
|
||||
- **原理**:
|
||||
- **基于迁移性(Transferability)**:在白盒模型(通常是公开的、结构相似的模型)上生成对抗样本,然后将这些样本用于攻击目标黑盒模型。研究表明,对抗样本在不同模型之间具有一定的**迁移性**
|
||||
- **基于查询(Query-based)**:通过向目标模型发送大量查询,观察其输出,并利用这些信息来估计模型的决策边界,从而生成攻击样本。这种方法通常需要大量的查询次数,但效果也更精确
|
||||
- **优点**:适用于无法获取模型参数的实际应用场景
|
||||
- **缺点**:通常比白盒攻击效率低,成功率也不如白盒攻击高
|
||||
@@ -0,0 +1,36 @@
|
||||
### 介绍下 KNN
|
||||
|
||||
**KNN 的核心思想:近朱者赤,近墨者黑**
|
||||
|
||||
KNN 算法的原理非常直观,可以比喻成“物以类聚,人以群分”
|
||||
|
||||
想象一下,你有一张地图,上面标注了各种餐馆的类型(中餐、西餐、日料)。现在,你想在地图上给一个新的、未标注的餐馆进行分类
|
||||
|
||||
KNN 的做法是:
|
||||
|
||||
1. **找到距离最近的邻居**:首先,找到离这个新餐馆最近的 K 个已知的餐馆
|
||||
2. **统计邻居的类别**:然后,统计这 K 个最近邻居中,哪种餐馆类型出现的次数最多
|
||||
3. **做出预测**:将出现次数最多的那个类别,作为新餐馆的预测类别
|
||||
|
||||
在这个例子中,**K** 就是你选择的“邻居”数量。如果 K=3,你就会考察离新餐馆最近的 3 个餐馆的类型;如果 K=5,你就会考察 5 个
|
||||
|
||||
**KNN 算法的步骤**
|
||||
|
||||
1. **确定 K 值**:选择一个合适的整数 K。这个 K 值是算法中唯一也是最重要的参数
|
||||
2. **计算距离**:对于每一个待分类的样本,计算它与所有训练集中样本的距离。常见的距离度量有:
|
||||
- **欧氏距离(Euclidean Distance)**:两点之间直线距离,最常用
|
||||
- **曼哈顿距离(Manhattan Distance)**:两点在坐标轴上移动的距离之和
|
||||
3. **排序**:将计算出的所有距离进行升序排序
|
||||
4. **选择 K 个最近邻**:选取距离最小的前 K 个样本
|
||||
5. **投票或取均值**:
|
||||
- **分类任务**:统计这 K 个样本所属类别中出现频率最高的那个类别,作为最终的预测类别
|
||||
- **回归任务**:计算这 K 个样本的标签值的平均值,作为最终的预测值
|
||||
|
||||
**如何选择 K 值?**
|
||||
|
||||
K 值的选择对 KNN 算法的性能影响很大:
|
||||
|
||||
- **K 值太小**:模型会变得非常复杂,对噪声数据和异常点非常敏感,容易导致**过拟合**
|
||||
- **K 值太大**:模型会变得过于简单,忽略了局部数据的特点,可能导致**欠拟合**
|
||||
|
||||
通常情况下,K 的值会根据数据的具体情况进行选择,常用的方法是通过交叉验证(Cross-validation)来寻找最优的 K 值
|
||||
@@ -0,0 +1,60 @@
|
||||
### 卷积神经网络介绍
|
||||
|
||||
**CNN 是什么?**
|
||||
|
||||
**卷积神经网络**是一种专门用于处理具有类似网格结构数据(如图像)的**深度学习**模型。它的灵感来源于人脑的**视觉皮层**,该皮层中的神经元只对视野中的特定区域敏感
|
||||
|
||||
简单来说,CNN 的核心思想是:**与其让模型去一次性地看一张完整的图片,不如让它通过一个“小窗口”去扫描图片,逐块地提取特征,然后再把这些局部特征组合起来,形成对整个图像的理解。** 这种“局部到整体”的处理方式,使得 CNN 在图像识别、目标检测等领域取得了巨大成功
|
||||
|
||||
**CNN 的核心构成**
|
||||
|
||||
一个典型的 CNN 主要由以下几个核心层组成:
|
||||
|
||||
**1. 卷积层**
|
||||
|
||||
这是 CNN 最核心的部分。它通过一个被称为**卷积核**(Kernel)或**滤波器**(Filter)的小窗口,在输入图像上进行滑动扫描
|
||||
|
||||
- **卷积核**:这个小窗口是一个矩阵,里面装着一系列权重
|
||||
- **滑动**:卷积核从图像的左上角开始,以一定的步长(Stride)向右和向下移动
|
||||
- **计算**:在每一次滑动到新位置时,卷积核会与它覆盖的图像区域进行**点乘**(Element-wise Multiplication),然后将结果相加,得到一个新的数值。这个新的数值代表了该区域的特征
|
||||
- **特征图**(Feature Map):卷积核在整个图像上滑动完成后,会生成一个由这些新数值组成的矩阵,我们称之为**特征图**。这个特征图捕捉了图像中某种特定的局部特征,比如边缘、纹理或颜色
|
||||
|
||||
通过使用多个不同的卷积核,我们可以提取出图像中多种多样的特征
|
||||
|
||||
**2. 激活层**
|
||||
|
||||
在卷积层计算出结果后,通常会紧跟一个**激活函数**,例如 **ReLU**(Rectified Linear Unit)
|
||||
|
||||
- **作用**:激活函数引入了**非线性**。如果没有激活函数,神经网络无论有多少层,最终都只会是线性的,无法学习和表达复杂的模式
|
||||
- **ReLU**:它的工作原理非常简单:`ReLU(x) = max(0, x)`。如果输入值大于0,它就保持不变;如果小于等于0,它就变为0。这使得模型能够更好地学习复杂的、非线性的特征
|
||||
|
||||
**3. 池化层**
|
||||
|
||||
池化层的作用是**压缩特征图**,减少数据维度,从而:
|
||||
|
||||
- **减少参数数量**:降低计算量,防止**过拟合**
|
||||
- **增强特征的鲁棒性**:使得模型对图像中的小幅平移、旋转或缩放变化不那么敏感
|
||||
|
||||
最常用的池化方法是**最大池化**(Max Pooling):在一个小区域内(比如2x2),只保留最大的那个值,而舍弃其他值
|
||||
|
||||
**4. 全连接层**
|
||||
|
||||
在经过多层卷积和池化之后,图像的特征被抽象和压缩。这时,我们通常会使用一个或多个**全连接层**
|
||||
|
||||
- **作用**:全连接层将前面所有提取到的局部特征**整合**起来,进行更高层次的抽象
|
||||
- **工作方式**:全连接层中的每个神经元都与前一层的所有神经元相连,就像传统的神经网络一样。
|
||||
|
||||
**5. 输出层**
|
||||
|
||||
全连接层的最后一层通常是**输出层**,它负责给出最终的预测结果
|
||||
|
||||
- **分类问题**:如果是一个图像分类任务,输出层会使用 **Softmax** 激活函数来输出每个类别的概率
|
||||
|
||||
**CNN 的工作流程概览**
|
||||
|
||||
1. **输入**:一张原始图像
|
||||
2. **多层卷积和激活**:通过多层**卷积层**和**激活层**,从图像中逐步提取出越来越抽象的特征,比如从边缘、纹理到物体的局部、再到完整的物体
|
||||
3. **多层池化**:在卷积层之间插入**池化层**,对特征图进行下采样,减少计算量,并增强模型对图像变化的鲁棒性
|
||||
4. **展平(Flatten)**:将最终的特征图**展平**成一个一维的向量
|
||||
5. **全连接层**:将这个向量输入到**全连接层**中,进行分类或回归
|
||||
6. **输出**:输出最终的预测结果
|
||||
@@ -0,0 +1,48 @@
|
||||
### 莱文斯坦距离
|
||||
|
||||
**莱文斯坦距离是什么?**
|
||||
|
||||
莱文斯坦距离,又被称为**编辑距离**,是衡量两个字符串之间相似度的一种度量方法。它定义了将一个字符串**A**转换成另一个字符串**B**所需的最少**单字符编辑操作**的次数
|
||||
|
||||
这些允许的单字符编辑操作有三种:
|
||||
|
||||
1. **插入(Insertion)**:在字符串中插入一个字符
|
||||
2. **删除(Deletion)**:从字符串中删除一个字符
|
||||
3. **替换(Substitution)**:将字符串中的一个字符替换成另一个字符
|
||||
|
||||
莱文斯坦距离越小,说明两个字符串越相似。反之,距离越大,相似度越低
|
||||
|
||||
**一个简单的例子**
|
||||
|
||||
让我们用一个例子来直观地理解它
|
||||
|
||||
计算字符串 **"kitten"** 和 **"sitting"** 的莱文斯坦距离
|
||||
|
||||
1. **"kitten"** -> **"sitten"**(将 'k' **替换**为 's')
|
||||
2. **"sitten"** -> **"sittin"**(将 'e' **替换**为 'i')
|
||||
3. **"sittin"** -> **"sitting"**(在末尾**插入** 'g')
|
||||
|
||||
总共需要 **3** 次编辑操作,所以 "kitten" 和 "sitting" 的莱文斯坦距离是 **3**
|
||||
|
||||
**如何计算?**
|
||||
|
||||
莱文斯坦距离通常使用**动态规划**(Dynamic Programming)算法来计算。这个方法的核心思想是构建一个二维矩阵,其中 `dp[i][j]` 存储的是字符串 A 的前 `i` 个字符与字符串 B 的前 `j` 个字符之间的编辑距离
|
||||
|
||||
矩阵的填充规则如下:
|
||||
|
||||
- **初始化**:
|
||||
|
||||
- `dp[i][0]` 等于 `i`(将 A 的前 `i` 个字符全部删除)
|
||||
- `dp[0][j]` 等于 `j`(将 B 的前 `j` 个字符全部插入)
|
||||
|
||||
- **递推关系**:对于矩阵中的每一个 `(i, j)`,我们比较 A 的第 `i` 个字符和 B 的第 `j` 个字符:
|
||||
|
||||
- 如果 `A[i-1]` 等于 `B[j-1]`,说明这两个字符相同,不需要编辑。此时 `dp[i][j] = dp[i-1][j-1]`
|
||||
- 如果 `A[i-1]` 不等于 `B[j-1]`,我们需要考虑三种操作的最小代价:
|
||||
- **插入**:`dp[i][j-1] + 1`
|
||||
- **删除**:`dp[i-1][j] + 1`
|
||||
- **替换**:`dp[i-1][j-1] + 1`
|
||||
|
||||
最终,`dp[i][j]` 取这三个值的最小值:`dp[i][j] = min(dp[i][j-1] + 1, dp[i-1][j] + 1, dp[i-1][j-1] + 1)`
|
||||
|
||||
最终,矩阵右下角的 `dp[len(A)][len(B)]` 就是两个字符串的莱文斯坦距离
|
||||
@@ -0,0 +1,72 @@
|
||||
### 倒排索引
|
||||
|
||||
**倒排索引是什么?**
|
||||
|
||||
倒排索引是一种非常重要且应用广泛的数据结构,它是现代**搜索引擎**的核心技术之一
|
||||
|
||||
它的基本思想是:**将文档中的每个词语与包含该词语的文档列表关联起来**
|
||||
|
||||
你可以把它想象成一本书后面的**索引**。在这本书的索引里,你不会看到“第10页有...,第11页有...”,而是会看到“**人工智能**:第10页、第11页、第25页...”
|
||||
|
||||
倒排索引就是这样一种结构,它将词语(或术语)作为**键**(Key),将包含该词语的文档列表作为**值**(Value)。这种“词语到文档”的映射关系与传统的“文档到词语”的映射(即正向索引)正好相反,因此得名“倒排”
|
||||
|
||||
**倒排索引的核心构成**
|
||||
|
||||
一个典型的倒排索引通常包含两个部分:
|
||||
|
||||
**1. 词典**
|
||||
|
||||
- **作用**:存储所有文档中出现过的所有**不重复**的词语
|
||||
- **结构**:通常是一个经过排序的列表或哈希表。它能让你快速定位到某个词语在倒排列表中的位置。
|
||||
|
||||
**2. 倒排列表**
|
||||
|
||||
- **作用**:存储每个词语出现的**文档ID**列表,以及该词语在文档中的**位置**、**频率**等信息
|
||||
- **结构**:与词典中的每个词语相对应,包含以下信息:
|
||||
- **文档ID(Document ID)**:包含该词语的文档的唯一标识符
|
||||
- **词频(Term Frequency)**:该词语在特定文档中出现的次数
|
||||
- **位置(Position)**:该词语在文档中出现的位置(如第几个词)。这对于处理短语查询(比如"人工智能")非常重要
|
||||
|
||||
**倒排索引的工作原理**
|
||||
|
||||
让我们通过一个简单的例子来理解它的工作流程:
|
||||
|
||||
假设我们有三个文档:
|
||||
|
||||
- **文档1**:`人工智能是未来。`
|
||||
- **文档2**:`学习人工智能。`
|
||||
- **文档3**:`未来是美好的。`
|
||||
|
||||
**1. 分词(Tokenization)**
|
||||
|
||||
首先,对每个文档进行分词,得到词语列表
|
||||
|
||||
- **文档1**:`[“人工智能”, “是”, “未来”]`
|
||||
- **文档2**:`[“学习”, “人工智能”]`
|
||||
- **文档3**:`[“未来”, “是”, “美好”]`
|
||||
|
||||
**2. 构建倒排索引**
|
||||
|
||||
然后,我们构建倒排索引,将每个词语与包含它的文档关联起来
|
||||
|
||||
| 词语 | 倒排列表(文档ID,词频,位置) |
|
||||
| -------- | ---------------------------------------------- |
|
||||
| 人工智能 | [ (文档1, tf:1, pos:0), (文档2, tf:1, pos:1) ] |
|
||||
| 是 | [ (文档1, tf:1, pos:1), (文档3, tf:1, pos:1) ] |
|
||||
| 未来 | [ (文档1, tf:1, pos:2), (文档3, tf:1, pos:0) ] |
|
||||
| 学习 | [ (文档2, tf:1, pos:0) ] |
|
||||
| 美好 | [ (文档3, tf:1, pos:2) ] |
|
||||
|
||||
**3. 查询过程**
|
||||
|
||||
现在,如果你搜索关键词“**人工智能**”,搜索引擎会怎么做呢?
|
||||
|
||||
1. **查询词典**:它会直接在倒排词典中找到“人工智能”这个词
|
||||
2. **获取倒排列表**:获取与“人工智能”对应的倒排列表,即 `[ (文档1, ...), (文档2, ...) ]`
|
||||
3. **返回结果**:根据这个列表,搜索引擎可以立即知道文档1和文档2包含了“人工智能”这个词,并迅速将它们作为搜索结果返回
|
||||
|
||||
如果你搜索“**人工智能 未来**”,搜索引擎会:
|
||||
|
||||
1. 分别找到“人工智能”和“未来”的倒排列表
|
||||
2. 对这两个列表进行**求交集**(Intersection),找到同时包含这两个词的文档ID
|
||||
3. 最终得到结果是**文档1**
|
||||
@@ -0,0 +1,47 @@
|
||||
### 搜索引擎的算法有哪些
|
||||
|
||||
**1. 爬虫与数据抓取**
|
||||
|
||||
这是整个搜索引擎系统的起点。爬虫是一个自动化程序,它会模拟人浏览网页的行为,从一个起始页面开始,沿着页面中的链接不断地爬取新的网页,并将它们存储到搜索引擎的数据库中
|
||||
|
||||
- **工作原理**:爬虫会周期性地访问网站,检查是否有新的内容或更新。为了提高效率,它会遵循一些规则,比如不爬取某些禁止访问的页面(通过 `robots.txt` 文件指定),或者优先抓取热门网站和经常更新的页面
|
||||
|
||||
**2. 索引**
|
||||
|
||||
抓取到的网页原始数据是无法直接用于搜索的。索引过程就是将这些网页数据进行**预处理**和**结构化**,使其能够被快速检索
|
||||
|
||||
- **分词(Tokenization)**:将网页内容分解成一个个独立的词语(或称为“词项”)。例如,将句子“深度学习算法”分解为“深度”、“学习”、“算法”
|
||||
- **倒排索引(Inverted Index)**:这是索引的核心。它将词语与包含该词语的文档列表进行关联。这种结构使得搜索引擎可以迅速找到包含特定关键词的所有文档,而不是遍历所有文档
|
||||
|
||||
**3. 排名算法**
|
||||
|
||||
这是搜索引擎算法中最核心、最复杂的部分,它决定了哪些搜索结果会排在前面。排名算法的目标是根据用户查询,评估每个网页的**相关性(Relevance)\**和\**重要性(Importance)**,并进行排序
|
||||
|
||||
**a. 文本相关性算法**
|
||||
|
||||
这些算法主要评估查询词和网页内容之间的匹配程度
|
||||
|
||||
- **TF-IDF(词频-逆文档频率)**:这是一种经典的相关性算法
|
||||
- **TF(Term Frequency)**:一个词在文档中出现的频率。如果一个词出现得越多,说明该文档与这个词越相关
|
||||
- **IDF(Inverse Document Frequency)**:一个词在所有文档中出现的频率。如果一个词在越少文档中出现,说明它越能区分文档,其权重越高
|
||||
- TF-IDF 的核心思想是:一个词在一个文档中出现频率高,但在所有文档中出现频率低,那么这个词对该文档的代表性就越强。
|
||||
|
||||
**b. 网页重要性算法**
|
||||
|
||||
这些算法旨在评估网页的整体权威性
|
||||
|
||||
- **PageRank**:这是 Google 早期最著名的排名算法。它的核心思想是:如果一个网页被越多重要的网页链接,那么它本身也越重要。可以把链接看作是一种“投票”。PageRank 会递归地计算每个网页的“重要性得分”,并将其作为排名的一个重要指标。
|
||||
|
||||
**c. 用户行为算法**
|
||||
|
||||
现代搜索引擎还会考虑用户的行为数据来优化排名
|
||||
|
||||
- **点击率(CTR)**:如果一个网页在搜索结果中的点击率很高,说明用户认为它很相关,这会提升它的排名
|
||||
- **停留时间**:用户在点击某个搜索结果后,在该页面停留的时间长短。如果用户很快就返回搜索结果页,可能说明这个页面不是他们想要的,这会降低它的排名
|
||||
|
||||
**4. 知识图谱与语义理解**
|
||||
|
||||
现代搜索引擎已经超越了简单的关键词匹配。它们能够理解查询背后的**意图**和**实体**
|
||||
|
||||
- **知识图谱(Knowledge Graph)**:它将实体(如“巴黎”、“埃菲尔铁塔”)及其相互关系组织成一个巨大的网络。当用户搜索“埃菲尔铁塔高度”时,搜索引擎可以直接从知识图谱中返回答案,而无需跳转到网页
|
||||
- **自然语言处理(NLP)**:搜索引擎利用 NLP 技术来理解查询的语义。例如,它能理解“苹果”这个词在“苹果公司”和“苹果手机”中的不同含义,从而给出更精准的结果
|
||||
@@ -0,0 +1,68 @@
|
||||
### 了解 TF-IDF 文档匹配算法吗
|
||||
|
||||
**TF-IDF 的核心思想**
|
||||
|
||||
TF-IDF 的核心思想可以用一句话概括:**一个词语在一个文档中出现得越多,并且在所有文档中出现得越少,那么它对于该文档的区分度就越高,也就越重要**
|
||||
|
||||
这个算法将一个词语的重要性分为两个部分来计算:
|
||||
|
||||
**1. 词频**
|
||||
|
||||
**TF** 表示一个词语在一个文档中出现的频率。计算公式通常是:
|
||||
|
||||
TF(t,d)=文档 d 中所有词语的总数词语 t 在文档 d 中出现的次数
|
||||
|
||||
- **作用**:衡量一个词语在**当前文档**中的重要性。一个词在文档中出现得越多,TF 值就越大,表明该词与该文档的相关性可能更高。
|
||||
|
||||
**2. 逆文档频率(IDF, Inverse Document Frequency)**
|
||||
|
||||
**IDF** 表示一个词语在整个文档集中出现的稀有程度。计算公式通常是:
|
||||
|
||||
IDF(t,D)=log(包含词语 t 的文档数+1文档总数 N)
|
||||
|
||||
这里的 +1 是为了防止分母为零,以避免对未出现的词语产生错误计算。
|
||||
|
||||
- **作用**:衡量一个词语在**所有文档**中的重要性。
|
||||
- 如果一个词语在很多文档中都出现,说明它是一个**通用词**(如“的”、“是”、“了”),它的 IDF 值就会很低,接近于0。
|
||||
- 如果一个词语只在很少的文档中出现,说明它是一个**稀有词**,它的 IDF 值就会很高。
|
||||
|
||||
**TF-IDF 的计算**
|
||||
|
||||
最终,一个词语在一个文档中的 **TF-IDF 值**是 **TF** 和 **IDF** 的乘积:
|
||||
|
||||
TF−IDF(t,d,D)=TF(t,d)×IDF(t,D)
|
||||
|
||||
**举个例子**
|
||||
|
||||
假设我们有一个包含3个文档的文档集:
|
||||
|
||||
- **文档1**:`“我 喜欢 吃 苹果。苹果 很甜。”`
|
||||
- **文档2**:`“我 喜欢 吃 香蕉。”`
|
||||
- **文档3**:`“我 喜欢 玩 电脑。”`
|
||||
|
||||
现在,我们来计算“**苹果**”这个词在**文档1**中的 TF-IDF 值
|
||||
|
||||
1. **计算 TF (苹果, 文档1)**
|
||||
- “苹果”在文档1中出现了2次
|
||||
- 文档1中总共有7个词语
|
||||
- TF=72≈0.286
|
||||
2. **计算 IDF (苹果, 所有文档)**
|
||||
- 文档总数 N=3
|
||||
- “苹果”只出现在文档1中,所以包含“苹果”的文档数是1
|
||||
- IDF=log(1+13)=log(1.5)≈0.176
|
||||
3. **计算 TF-IDF (苹果, 文档1)**
|
||||
- TF−IDF=0.286×0.176≈0.0503
|
||||
|
||||
如果再计算“**我**”这个词在**文档1**中的 TF-IDF 值:
|
||||
|
||||
1. **计算 TF (我, 文档1)**
|
||||
- “我”出现了1次
|
||||
- TF=71≈0.143
|
||||
2. **计算 IDF (我, 所有文档)**
|
||||
- 文档总数 N=3
|
||||
- “我”出现在了所有3个文档中
|
||||
- IDF=log(3+13)=log(0.75)≈−0.125
|
||||
3. **计算 TF-IDF (我, 文档1)**
|
||||
- TF−IDF=0.143×(−0.125)≈−0.0178
|
||||
|
||||
这个负值表明“我”这个词的通用性太高,几乎不具备区分度。而“苹果”这个词的 TF-IDF 值更高,因为它在文档1中频繁出现,但在整个文档集中又相对稀有,因此更能代表文档 1 的主题
|
||||
@@ -0,0 +1,58 @@
|
||||
### SGD 和 Adam 的区别
|
||||
|
||||
**什么是优化算法?**
|
||||
|
||||
在深入了解这两种算法之前,我们先明确一下什么是**优化算法**
|
||||
|
||||
在训练神经网络时,我们的目标是最小化**损失函数**(Loss Function)。损失函数衡量了模型预测结果与真实值之间的差距。优化算法就是一种方法,它告诉我们**如何调整模型的参数**(即权重和偏置),以使损失函数的值越来越小,从而让模型变得越来越准确
|
||||
|
||||
可以把优化算法想象成在下山时,如何选择每一步的方向和步长,才能最快地到达山谷(即损失函数的最小值)
|
||||
|
||||
**1. 随机梯度下降(SGD, Stochastic Gradient Descent)**
|
||||
|
||||
**基本原理**
|
||||
|
||||
**SGD** 是最基础、最原始的优化算法。它的“随机”体现在:在每一次迭代中,它**随机选择一个样本**(或一小批样本,即 **Mini-Batch SGD**),然后计算这一个(或一小批)样本的损失,并根据这个损失来更新模型的参数
|
||||
|
||||
这与传统的**批量梯度下降**(Batch Gradient Descent)不同,后者会计算所有训练样本的损失来更新一次参数。
|
||||
|
||||
**优点**
|
||||
|
||||
- **计算效率高**:由于每次只处理一小批样本,计算量大大减少,尤其是在面对海量数据时
|
||||
- **跳出局部最优**:SGD 的“随机性”使得它有机会跳出一些浅的局部最优解,找到更好的全局最优解。
|
||||
|
||||
**缺点**
|
||||
|
||||
- **收敛速度慢且不稳定**:由于每次的梯度只代表了一小部分数据,更新方向可能会非常“抖动”和不稳定,导致损失函数在下降时像锯齿一样波动
|
||||
- **需要手动设置学习率**:如果学习率(步长)太大,可能无法收敛;如果太小,收敛速度会非常慢。而且,整个训练过程都使用同一个固定的学习率,无法根据参数的重要性进行调整
|
||||
|
||||
**2. Adam(Adaptive Moment Estimation)**
|
||||
|
||||
**基本原理**
|
||||
|
||||
**Adam** 是一种**自适应学习率**的优化算法。它结合了**RMSprop** 和 **Adagrad** 的优点,是目前最常用、效果最好的优化器之一。它的核心思想是:**为每个参数都动态地调整学习率**
|
||||
|
||||
Adam 主要通过计算梯度的**一阶矩**(均值)和**二阶矩**(方差)的指数移动平均值来调整学习率
|
||||
|
||||
- **一阶矩(mt)**:可以看作是梯度的加权平均,它决定了更新方向
|
||||
- **二阶矩(vt)**:可以看作是梯度平方的加权平均,它决定了更新的步长大小
|
||||
|
||||
Adam 会根据这些动态计算的矩,为不同的参数提供不同的学习率。对于梯度大的参数,它会减小学习率;对于梯度小的参数,它会增加学习率
|
||||
|
||||
**优点**
|
||||
|
||||
- **收敛速度快**:由于它能够自适应地调整学习率,Adam 在多数情况下比 SGD 收敛得更快
|
||||
- **无需手动调优学习率**:大多数情况下,使用 Adam 的默认参数就能取得很好的效果,大大简化了调参过程
|
||||
- **能处理稀疏梯度**:对于有稀疏梯度的任务(如自然语言处理),Adam 表现出色
|
||||
|
||||
**缺点**
|
||||
|
||||
- **可能会收敛到局部最优**:一些研究表明,Adam 在某些特定场景下可能会收敛到比 SGD 差的局部最优解,这是因为它自适应的学习率可能导致它在训练后期学习率过低,无法跳出局部最优
|
||||
|
||||
| 特性 | SGD | Adam |
|
||||
| -------- | ------------------------------------------------ | ---------------------------------------------- |
|
||||
| 学习率 | 固定,需要手动设置 | 自适应,为每个参数动态调整 |
|
||||
| 更新方式 | 根据单个样本或 mini-batch 的梯度直接更新 | 结合一阶矩和二阶矩,动态调整更新方向和步长 |
|
||||
| 收敛性 | 波动较大,可能收敛到全局最优 | 平稳且快速收敛,但可能陷入较差的局部最优 |
|
||||
| 适用性 | 在大型模型或特定任务上需要精细调参,效果可能更好 | 绝大多数场景下都能快速获得不错的效果,易于使用 |
|
||||
| 调参难度 | 高,需要仔细调整学习率 | 低,默认参数通常表现良好 |
|
||||
@@ -0,0 +1,45 @@
|
||||
### 如何缩减模型的检测时延
|
||||
|
||||
**1. 模型量化**
|
||||
|
||||
**模型量化**是减少模型大小和计算量最直接有效的方法。它将模型参数从浮点数(如32位浮点数)转换为低精度的数据类型(如8位整数)
|
||||
|
||||
- **原理**:浮点运算比整数运算耗时更多。通过将权重和激活值量化为整数,可以利用专门的整数计算单元,从而大幅提高推理速度
|
||||
- **优点**:
|
||||
- 显著减少模型大小,便于部署在移动设备和边缘设备上
|
||||
- 大幅降低计算时延,尤其是对于 CPU 和 DSP 等处理器
|
||||
- **缺点**:可能会损失一定的模型精度。不过,在许多应用中,这种精度损失是可以接受的。
|
||||
|
||||
**2. 模型剪枝**
|
||||
|
||||
**模型剪枝**是移除模型中不重要或冗余的连接和神经元,以减小模型体积和计算量
|
||||
|
||||
- **原理**:在训练好的模型中,很多权重值可能接近于零,对模型的贡献很小。剪枝就是识别并移除这些不重要的权重或神经元
|
||||
- **方法**:
|
||||
- **非结构化剪枝**:移除单个权重,但会使得模型变得稀疏,需要特殊的硬件或库才能加速
|
||||
- **结构化剪枝**:移除整个神经元、通道或层,生成的模型结构更紧凑,可以直接在现有硬件上加速
|
||||
- **优点**:减少模型大小和计算量,提高推理速度,同时可以保持较高的精度
|
||||
|
||||
**3. 知识蒸馏**
|
||||
|
||||
**知识蒸馏**是一种训练技巧,它利用一个已经训练好的大型模型(**教师模型**)来指导一个较小的模型(**学生模型**)的学习过程
|
||||
|
||||
- **原理**:学生模型不仅学习真实标签,还学习教师模型的软目标(Soft Labels,即教师模型输出的概率分布)。这种方法让学生模型在学习过程中获得额外的“知识”,从而在模型大小显著减小的情况下,也能达到接近教师模型的性能
|
||||
- **优点**:能够在保持较高精度的前提下,将一个复杂模型的知识转移到一个更小、推理更快的新模型上
|
||||
|
||||
**4. 优化推理框架**
|
||||
|
||||
使用高效的推理框架可以最大化硬件性能,从而缩短时延
|
||||
|
||||
- **TensorRT**:NVIDIA 推出的高性能深度学习推理引擎。它可以对模型进行一系列的优化,如量化、层融合(Layer Fusion)等,并为 GPU 生成高度优化的代码,从而大幅提升推理速度
|
||||
- **ONNX Runtime**:一个跨平台的推理引擎,支持多种硬件和框架。它能够优化模型图,并选择最佳的执行路径,以提高推理性能
|
||||
- **OpenVINO**:英特尔推出的工具套件,专门用于在英特尔硬件(如 CPU、集成显卡、VPU)上进行高效的推理部署
|
||||
|
||||
**5. 硬件加速**
|
||||
|
||||
选择合适的硬件平台是缩减时延的根本
|
||||
|
||||
- **GPU(图形处理器)**:对于大规模并行计算有天然优势。深度学习模型中的矩阵乘法和卷积操作都可以高效地在 GPU 上执行
|
||||
- **TPU(张量处理器)**:谷歌专门为机器学习工作负载设计的专用集成电路(ASIC),在执行矩阵运算方面比 GPU 更高效
|
||||
- **FPGA(现场可编程门阵列)**:可以根据模型结构进行定制化硬件设计,从而达到极高的性能和能效比
|
||||
- **移动端 AI 芯片**:许多移动设备都集成了专门的神经处理单元(NPU),如苹果的 Neural Engine、高通的 Hexagon DSP,这些芯片专门为神经网络推理设计,具有低功耗和高效率的特点
|
||||
Reference in New Issue
Block a user