[PyTorch]手动实现logistic回归(只借助Tensor和Numpy相关的库)

文章目录

  • 实验要求
  • 一、生成训练集
  • 二、数据加载器
  • 三、手动构建模型
    • 3.1 logistic回归模型
    • 3.2 损失函数和优化算法
    • 3.3 模型训练
  • 四、训练结果

实验要求

  1. 人工构造训练数据集
  2. 手动实现logistic回归(只借助Tensor和Numpy相关的库)
  3. 从loss以及训练集上的准确率等多个角度对结果进行分析(可借助nn.BCELoss或nn.BCEWithLogitsLoss作为损失函数,从零实现二元交叉熵为选作)

一、生成训练集

# 1、生成训练集...h_k(x)=1/(1+e^(-k^*x)),k为参数,这里设置为[1.3,-1.0]
num_inputs = 2  # 特征数
num_examples = 1000  # 训练数据集样本数
true_k = [1.3, -1.0]
features = tensor(np.random.normal(0, 1, (num_examples, num_inputs)), dtype=torch.float)
labels = 1 / (1 + torch.exp(-1 * (true_k[0] * features[:, 0] + true_k[1] * features[:, 1])))
# 加入噪声
labels += torch.tensor(np.random.normal(0, 0.01, size=labels.size()), dtype=torch.float)
num0 = 0
num1 = 0
for i in range(num_examples):
    if labels[i] < 0.5:
        labels[i] = 0
        num0 += 1
    else:
        labels[i] = 1
        num1 += 1
# print(labels)
labels = labels.view(num_examples, 1)
print(num0, num1)

二、数据加载器

# 2、读取数据
def train_data_loader(batch_size, features, labels):
    num_exp = len(features)
    indices = list(range(num_exp))
    random.shuffle(indices)  # 打乱样本顺序
    for i in range(0, num_exp, batch_size):
        j = torch.LongTensor(indices[i:min(i + batch_size, num_exp)])  # 最后一次可能不足batch
        yield features.index_select(0, j), labels.index_select(0, j)  # 维度,索引
        # yield关键字:带yield的函数是一个生成器,只有调用函数时函数才会执行
        # next(函数):每次执行到yield处会return,下一次调用next时从上一次停止的地方继续执行至yield处
        # 函数.send(num)会将num值送入上一次停止的地方,再执行next

三、手动构建模型

3.1 logistic回归模型

k = torch.normal(0, 1.0, (num_inputs, 1), dtype=torch.float32)  # 训练参数随机初始化
# k = tensor([[0.5], [-0.5]], dtype=torch.float32)
k.requires_grad_(True)

def logistic_regression(x, k):
    return 1 / (1 + torch.exp(-1 * torch.mm(x, k)))

3.2 损失函数和优化算法

这里没有从零开始实现二元交叉熵损失函数,使用了torch.nn.BCELoss函数

# 3.2 损失函数和优化算法
# def bce_loss(y_hat, y):
# return -1 * (y * torch.log10(y_hat) + (1 - y) * torch.log10(1 - y_hat)) 单个样本的损失


def sgd(params, lr, batch_size):
    for param in params:
        param.data -= lr * param.grad / batch_size  # 这里更改param时用的param.data

3.3 模型训练

# 3.3 模型训练
lr = 0.03
num_epochs = 20
batch_size = 10
net = logistic_regression
loss = torch.nn.BCELoss()

for epoch in range(num_epochs):  # 一共进行num_epoch个迭代周期
    # 每个epoch会遍历使用一遍所有的训练集样本
    for x, y in train_data_loader(batch_size, features, labels):
        # x,y是一个batch的样本特征和标签
        y_hat = net(x, k)
        l = loss(y_hat, y)
        l.backward()  # 求梯度
        sgd([k], lr, batch_size)
        k.grad.data.zero_()  # 梯度清零
    train_l = loss(net(features, k), labels)  # 计算训练样本的损失
    print('epoch %d, loss %f' % (epoch + 1, train_l.item()))
    print('k', k)

四、训练结果

[PyTorch]手动实现logistic回归(只借助Tensor和Numpy相关的库)_第1张图片

你可能感兴趣的:(深度学习,python,深度学习)