本节为吴恩达教授机器学习课程笔记第三部分,广义线性模型(2)构建广义线性模型,包括最小均方算法、逻辑回归,着重介绍softmax的推导,并给出softmax的核心代码以及pytorch实现。
2. 构建GLMS广义线性模型
考虑一个分类或者回归问题,我们希望得到一个x的函数,来计算随机变量y的值。为了推导出一个广义线性模型,我们给出这样三个假设:
- 给定x和,我们假定y的分布服从参数为的某个指数族分布
- 给定x,目标是预测的期望值,在绝大多数例子中,,因此,我们想要预测的值使得
- 自然参数和x是线性相关的,即,对于向量来说,即
2.1 典型的最小均方算法
,于是有下面的式子:
2.2 逻辑回归
对于二分类问题,有:
2.3 Softmax回归
考虑一个多分类问题,即模型有多个可能的输出对应多个不同的类别,我们可以用多项式分布来对该问题进行建模。
首先,我们可以将多项式分布表达为指数族的形式。定义:
即:
这里,是一个维向量,用表示向量的第i个分量。
此外引入一种特殊的定义,即1{},如果它接受的参数为True,则输出1,参数为False,输出0。这样我们可将把y和新的的关系写为:
更进一步地,有:
接下来证明多项式分布确实属于指数族分布,我们有:
对应地:
于是有:
这表明:
从而得到:
这个将映射为的函数成为softmax函数,根据之前给出的假设3,有:
这个多分类模型即softmax回归,是逻辑回归的推广,所以会输出:
换句话说,将输出属于每一类的概率。
最后我们来探讨参数拟合的问题,给出如下对数似然函数:
之后我们就可以用牛顿法或者梯度下降来最大化对数似然函数已得到参数值了。
softmax回归的核心代码
# softmax函数,将线性回归值转化为概率的激活函数。输入s要是行向量
def softmax(s):
return np.exp(s) / np.sum(np.exp(s), axis=1)
# 逻辑回归中使用梯度下降法求回归系数。逻辑回归和线性回归中原理相同,只不过逻辑回归使用sigmoid作为迭代进化函数。因为逻辑回归是为了分类而生。线性回归为了预测而生
def gradAscent(dataMat, labelPMat):
alpha = 0.2 #移动步长,也就是学习速率,控制更新的幅度。
maxCycles = 1000 #最大迭代次数
weights = np.ones((dataMat.shape[1],labelPMat.shape[1])) #初始化权回归系数矩阵 系数矩阵的行数为特征矩阵的列数,系数矩阵的列数为分类数目
for k in range(maxCycles):
h = softmax(dataMat*weights) #梯度上升矢量化公式,计算预测值(行向量)。每一个样本产生一个概率行向量
error = h-labelPMat #计算每一个样本预测值误差
weights = weights - alpha * dataMat.T * error # 根据所有的样本产生的误差调整回归系数
return weights # 将矩阵转换为数组,返回回归系数数组
pytorch实现
EPOCH = 5000
BATCH_SIZE = 100
LR = 0.01
train_set = Data.TensorDataset(x_train,y_train)
train_loader = Data.DataLoader(
dataset=train_set,
batch_size=BATCH_SIZE,
shuffle=True
)
net = nn.Sequential(
nn.Linear(8,50),
nn.ReLU(),
nn.Linear(50,4)
)
LOSS_FUNC = nn.CrossEntropyLoss() # 损失函数torch.nn.CrossEntropyLoss()中已经包含了Softmax函数
OPTIMIZER = torch.optim.SGD(net.parameters(), lr=LR)
for epoch in range(1,EPOCH+1):
loss_sum = 0.0
for step,(x,y) in enumerate(train_loader):
y_pred = net(x)
y = y.squeeze() #修正标签格式
loss = LOSS_FUNC(y_pred,y)
loss_sum += loss
OPTIMIZER.zero_grad()
loss.backward()
OPTIMIZER.step()
print("epoch: %d, loss: %f" %(epoch,loss_sum/BATCH_SIZE))