机器学习基础
机器学习基础
线性回归与逻辑回归
监督学习与非监督学习
监督学习(Supervised Learning):
数据:监督学习使用带有标签的数据进行训练。每个训练样本都由输入特征和对应的标签组成。输入特征是模型的输入,标签是对应的目标输出。
目标:监督学习的目标是通过对输入特征和标签之间的关系进行学习,构建一个能够准确预测新样本标签的模型。模型通过最小化预测值与真实标签之间的差异,例如使用损失函数计算预测误差并通过反向传播算法优化模型参数。
非监督学习(Unsupervised Learning):
数据:非监督学习使用未标记的数据进行训练,即没有对应的标签。数据只包含输入特征,没有与之对应的目标输出。
目标:非监督学习的目标是从数据中发现隐藏的结构、模式或特征。这种学习方式更加依赖于数据本身的统计特性和信息。常见的非监督学习任务包括聚类(将相似样本分组)。
损失函数
1.均方误差损失函数:
对于
目的是求
损失函数
2.交叉熵损失函数:
对于
当然激活函数可以是别的,目标是一个概率,其中表示这个逻辑回归的决策边界,它可以是各种形状,比如圆形或者是高维的。则下面是它的损失函数:
可以看出当预期概率为1时,在0到1之间时下降的,想让损失函数时,这个时候只能取1。另一种情况同样如此。而最终简化后的公式则是这样的:
特征缩放

防止特征尺度不平衡带来的影响: 当特征的尺度差异较大时,某些特征的值范围可能会远远超过其他特征。这可能导致模型在处理具有较大尺度的特征时过于关注这些特征,而忽略了其他特征的影响。通过进行特征缩放,可以将特征调整到相似的尺度,使得模型能够更加平衡地考虑各个特征的影响。(比如二维数据变成一维数据)
加快模型收敛速度: 在某些优化算法中,如梯度下降,特征的尺度差异可能导致算法收敛速度较慢。尺度较大的特征可能会导致梯度更新幅度过大,从而导致算法在这些特征上过度调整。通过特征缩放,可以使得不同特征的梯度变化范围相对一致,有助于加快算法的收敛速度。(像自适应学习率方法中的Adagrad算法,将学习率除以一个历史梯度Hadamard积的二范数,实现梯度数值归一化,避免了梯度更新幅度过大的问题,求稀疏矩阵更加平滑)
避免数值计算问题: 在某些情况下,特征的尺度差异可能导致数值计算问题。例如,某些优化算法可能在特征的尺度较大时产生数值溢出或不稳定的情况。通过将特征缩放到合适的范围,可以减少这些数值计算问题的发生。(各种误差)
常见的特征缩放方法包括标准化和归一化。标准化通过减去特征的均值并除以标准差,将特征调整为均值为0、标准差为1的分布。归一化将特征缩放到特定的范围,如[0, 1]或[-1, 1]。
梯度下降
其中为学习率,学习率的设置不应过大或过小。一般可以采用学习率衰减策略或自适应学习率方法。自适应学习率引入动量这个概念加速了梯度收敛,后又有了AdaGrad,RMSprop,Adam算法。下面为Adam算法。
其中第三行用的是指数加权移动平均法,由 其中而来,其中后面括号里V表示的是之前的之和,这其实就是动量法的思想,有种物理上惯性的感觉,而指数加权移动平均法目的是增大上一个的权值(一般设置为0.9),其主要针对的是梯度。
而第四行这个公式表示对Hadamard积使用指数移动平均法的进行更新。不同于第三行梯度下降方式进行优化,其目的是针对学习率进行优化,v的计算是通过将上一时刻的指数移动平均乘以梯度平方衰减参数(β2)并加上当前Hadamard积的一部分来实现。(其实就是RMSprop算法,相较于AdaGrad下降更快一点,避免了因历史部分缓慢,而导致下降缓慢)
第四五行中"bias-corrected"是指对估计值进行修正,以纠正由于算法初始条件或计算过程引入的偏差。这是因为在算法的初始阶段,这些估计值可能会受到初始化条件的影响,导致偏差较大。
补充adagrad法: 学习率除以一个历史梯度Hadamard积之和的二范数,adagrad本质是解决各方向导数数值量级的不一致而将梯度数值归一化,梯度太大的把它搞小一点。如下图,其中紫色为动量法,灰色为对动量进行归一化的。
过拟合
过拟合(overfitting)是指机器学习模型在训练数据上表现良好,但在新数据上的表现较差的现象。当一个模型过度适应训练数据的细节和噪音时,就会发生过拟合。 是高方差的一种表现形式。
为了解决过拟合问题,可以采取以下方法:
1.数据集扩充:增加更多的训练数据,可以减少模型对训练数据的过度拟合程度。
2.特征选择:选择对目标变量具有较高相关性的特征,排除对模型预测能力影响较小的特征。
3.正则化(Regularization):通过添加正则化项来限制模型参数的大小,例如L1正则化(L1 regularization)和L2正则化(L2 regularization)。正则化可以减小模型的复杂度,防止模型过度拟合训练数据。
4.交叉验证(Cross-validation):使用交叉验证来评估模型的性能。通过将数据集分成训练集和验证集,在训练过程中周期性地使用验证集来评估模型的泛化能力,以便及时发现并解决过拟合问题。
5.提前停止训练(Early stopping):在训练过程中监控模型在验证集上的性能,当性能开始下降时停止训练,防止模型过度拟合。
6.集成方法(Ensemble methods):使用多个模型的组合来减少过拟合的风险。例如,随机森林(Random Forest)和梯度提升树(Gradient Boosting)等集成方法可以通过结合多个弱模型来构建更强大的模型。
正则化
L1正则化:
L2正则化:
需要注意的是,正则化系数λ的选择对正则化的效果具有重要影响。较大的λ值会更强烈地惩罚模型的复杂性,可能导致模型欠拟合。较小的λ值则可能无法有效控制模型的复杂度,导致模型仍然容易过拟合。因此,在使用正则化时,需要根据具体问题和数据集的特点进行调优选择合适的正则化系数。
而因为都是凸优化问题,L1正则化倾向于产生稀疏解,即通过将一些特征的权重变为零来选择重要的特征,可以用于特征选择。相比之下,L2正则化倾向于将权重平均分配给所有特征,不会将特征的权重变为零,不具备明确的特征选择能力。
误差和偏差
上图为解决偏差和方差的一些方法,其中高方差意味着过拟合,即在一个数据集表现很好而在另一个数据集表现很差,那么最简单的方法则为添加数据。高偏差意味着学习效果很差,这点从历史模型的发展可以看出,随着模型发展的越来越深,偏差越来越小。
CNN
卷积层
卷积:
传统的卷积定义中,是要是要和转置的卷积核进行相乘,但在CNN中直接算的是内积。下面给出卷积前后尺寸公式。
池化层
池化目的是对卷积出来的结果进行特征压缩,提取主要特征,增大卷积核的感受野等。池化前后的尺寸计算同样可以用上面的公式。常见的池化操作有最大池化(Max Pooling)和平均池化(Average Pooling)两种。
全连接层
全连接层的作用是与下一层的单个神经元前一层神经元依次连接进行线性变换,并通过激活函数进行非线性映射,并连接到下一层。需要将数据先进行展平操作。
利用pytorch构建模型
在PyTorch中构建卷积神经网络(CNN)需要使用torch.nn模块提供的类和函数。创建模型有 2 个要素:构建子模块和拼接子模块。如 LeNet 里包含很多卷积层、池化层、全连接层,当我们构建好所有的子模块之后,按照一定的顺序拼接起来。
self.weight = nn.Parameter(torch.Tensor(5, 3)) # 定义一个可学习的权重参数
init.xavier_uniform_(self.weight) # 使用nn.init对权重参数进行初始化
针对于Parameter和init类,该代码代表着对有三个输入特征和5个输出特征,并使用Xavier方法对其进行权重初始化。而nn.Module类在PyTorch中集成了参数(nn.Parameter)的管理、初始化(nn.init)和函数(nn.functional)等功能。
给出一个类似Lenet代码:
class LeNet5(nn.Module):
def __init__(self):
super(LeNet5, self).__init__()
self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, stride=1)
self.pool1 = nn.AvgPool2d(kernel_size=2, stride=2)
self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5, stride=1)
self.pool2 = nn.AvgPool2d(kernel_size=2, stride=2)
self.fc1 = nn.Linear(in_features=16 * 5 * 5, out_features=120)
self.fc2 = nn.Linear(in_features=120, out_features=84)
self.fc3 = nn.Linear(in_features=84, out_features=10)
def forward(self, x):
x = self.pool1(torch.relu(self.conv1(x)))
x = self.pool2(torch.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
x = self.fc3(x)
return x
如果模型很复杂的话,pytorch提供了nn.Sequetial这个模型容器,可以用来包装特征提取和分类器两部分。
class LeNet5(nn.Module):
def __init__(self):
super(LeNet5, self).__init__()
self.features = nn.Sequential(
nn.conv1 = nn.Conv2d(1, 6, 5),
nn.Relu(),
nn.AvgPool2d(2, 2),
nn.conv1 = nn.Conv2d(6, 16, 5),
nn.Relu(),
nn.AvgPool2d(2, 2),
)
self.classifier = nn.Sequential(
nn.Linear(16*5*5, 120),
nn.ReLU(),
nn.Linear(120, 84),
nn.ReLU(),
nn.Linear(84, classes)
)
def forward(self, x):
x = self.features(x)
x = x.view(16 * 5 * 5,-1)
x = self.classifier(x)
return x
epoch概念
如果总数据N,batchsize是n的话,一个epoch进行N/n次迭代, 每次都喂入一个batchsize。