二分类的意图判定
题意
给定 条训练样本和
条测试样本。每个样本是一个由大写字母 A-G 组成的字符串,训练样本带有标签 0 或 1。要求用单层逻辑回归模型训练后,对测试样本进行预测。
模型的具体规格:
- 特征编码:7 维 one-hot 存在编码,字母 A-G 分别对应一个维度,存在为 1,不存在为 0
- 初始权重和偏置均为 0
- 激活函数:sigmoid
- 损失函数:二元交叉熵
- 优化方式:梯度下降,学习率 0.1,训练 20 个 epoch,batch size 为 1(即 SGD)
- 预测阈值:大于 0.5 输出 1,否则输出 0
思路
这道题没有什么算法设计的空间,就是老老实实把逻辑回归的训练和推理过程模拟出来。关键是把梯度计算搞对。
特征编码怎么做? 字符串里每个字符映射到维度 ,对应位置设为 1。比如 "ABC" 编码成
。
前向传播: 计算 ,再过 sigmoid 得到预测值
。sigmoid 实现要注意数值稳定性——
为负数时用
避免溢出。
梯度更新: 二元交叉熵对 的梯度推导很简洁,最终结果就是
。所以权重更新为:
$$
$$
其中 是学习率。
训练流程: 外层循环 20 个 epoch,内层按顺序遍历每条训练样本,逐条做前向 + 更新。这就是 batch size 为 1 的 SGD。
预测: 训练完后,对每条测试样本做一次前向传播, 输出 1,否则输出 0。
复杂度
- 时间:
,其中
是特征维度
- 空间:
,只需要存权重向量
代码
import math
def solve():
n, m = map(int, input().split())
train_data = []
for _ in range(n):
parts = input().split()
s = parts[0]
label = int(parts[1])
features = [0] * 7
for ch in s:
features[ord(ch) - ord('A')] = 1
train_data.append((features, label))
test_data = []
for _ in range(m):
s = input().strip()
features = [0] * 7
for ch in s:
features[ord(ch) - ord('A')] = 1
test_data.append(features)
w = [0.0] * 7
b = 0.0
lr = 0.1
for epoch in range(20):
for features, label in train_data:
z = sum(w[i] * features[i] for i in range(7)) + b
if z >= 0:
pred = 1.0 / (1.0 + math.exp(-z))
else:
ez = math.exp(z)
pred = ez / (1.0 + ez)
error = pred - label
for i in range(7):
w[i] -= lr * error * features[i]
b -= lr * error
for features in test_data:
z = sum(w[i] * features[i] for i in range(7)) + b
if z >= 0:
pred = 1.0 / (1.0 + math.exp(-z))
else:
ez = math.exp(z)
pred = ez / (1.0 + ez)
print(1 if pred > 0.5 else 0)
solve()

京公网安备 11010502036488号