#P3389. 第2题-高斯朴素贝叶斯
-
1000ms
Tried: 37
Accepted: 14
Difficulty: 5
所属公司 :
美团
时间 :2025年8月16日-算法岗
-
算法标签>机器学习算法
第2题-高斯朴素贝叶斯
思路与题解
-
数据读取与划分
- 从标准输入读取一行 JSON,并解析出 train 与 test。
- train 的维度为 n×(m+1),前 m 列为特征,最后一列为标签 y∈{0,1};test 为 t×m。
-
参数估计
- 类别先验:对每个类别 c,计算 πc=NNc。
- 条件独立下的高斯参数:对每个类别 c、每个特征 j,计算均值 μcj 与总体方差 σcj2(使用 ddof=0)。
- 数值稳定:若 σcj2=0,将其置为 1e-9,避免除以 0 及 log0。
-
输出
- 将 t 个预测标签按输入顺序输出为单行 JSON 数组。
-
复杂度
- 训练阶段主要为均值/方差统计,时间复杂度约为 O(nm);
- 预测阶段对每个样本与类别进行计算,约为 O(tmC),其中 C 为类别数(本题中 C=2)。
import sys
import json
import numpy as np
EPS = 1e-9
def fit_gnb(X, y):
classes, counts = np.unique(y, return_counts=True)
n_classes, n_features = classes.shape[0], X.shape[1]
means = np.zeros((n_classes, n_features), dtype=float)
vars_ = np.zeros((n_classes, n_features), dtype=float)
log_priors = np.log(counts / y.shape[0])
for i, c in enumerate(classes):
Xc = X[y == c]
means[i] = Xc.mean(axis=0)
v = Xc.var(axis=0, ddof=0)
v[v == 0] = EPS
vars_[i] = v
return classes, log_priors, means, vars_
def predict_gnb(X_test, classes, log_priors, means, vars_):
const_terms = -0.5 * np.sum(np.log(2 * np.pi * vars_), axis=1)
log_posts = []
for k in range(classes.shape[0]):
diff = X_test - means[k]
ll = -0.5 * np.sum((diff ** 2) / vars_[k], axis=1)
log_posts.append(log_priors[k] + const_terms[k] + ll)
log_posts = np.vstack(log_posts).T
return classes[np.argmax(log_posts, axis=1)]
def main():
data = sys.stdin.read().strip()
if not data:
print("[]")
return
try:
obj = json.loads(data)
except json.JSONDecodeError as e:
# 常见原因:缺少 ']', 多了逗号,或键之间缺少逗号
print("[]")
return
if "train" not in obj or "test" not in obj:
print("[]")
return
train = np.array(obj["train"], dtype=float)
if train.ndim != 2 or train.shape[1] < 2:
print("[]")
return
X = train[:, :-1]
y = train[:, -1].astype(int)
test = np.array(obj["test"], dtype=float)
if test.ndim != 2 or test.shape[1] != X.shape[1]:
print("[]")
return
classes, log_priors, means, vars_ = fit_gnb(X, y)
preds = predict_gnb(test, classes, log_priors, means, vars_)
print(json.dumps([int(v) for v in preds.tolist()], ensure_ascii=False))
if __name__ == "__main__":
main()
题目内容
请你在仅使用 numpy/pandas 的前提下,手写实现高斯朴素贝叶斯(Gaussian Naive Bayes,GNB),并对给定测试样本输出类别预测。具体流程:
1.读取数据
-
train 字段:二维列表,每行最后一列为类别标签 y∈ {0,1},其余为数值特征
-
test 字段:二维列表,仅包含与训练集同维度的特征
2.参数估计
-
对每个类别 c 计算先验 πc=NNc
-
对每个特征计算类条件独立假设下的 均值 μcj 与方差 σcj2 (总体方差 ddof=0;若方差为 0 ,令 σcj2=1e−9)
3.预测
- 使用对数后验: log P(c∣x)=log πc +∑j[−21log(2πσcj2)-2σcj2(xj−μcj)2]
- 取 arg maxc log P(c∣x) 作为预测标签
4.结果输出
- 预测值保留整数 0/1,以 JSON 数组形式一次性输出,顺序与输入 test 保持一致
输入描述
标准输入为 一行 JSON。
-
n 行训练样本,m 维特征,最后一列为标签
-
所有值均为浮点数/整数,无额外空行
输出描述
标准输出仅含一行:即测试集中每个样本的预测标签(整数),使用单行 JSON数组表示。
补充说明
1.流程无需随机数;若实现中使用随机过程,必须固定为 np.random.seed(42)。
2.为确保通过全部测试用例,请使用仅 Numpy 与 Pandas 库实现本题。
3.计算方差使用总体力差 (np,var( ...doof=0))。
4.方差为 0 的特征设为 1e−9 防止除零。
样例1
输入
{"train": [[1,1,0],[1,1,0],[4,4,1],[4,2,1]], "test": [[1,1],[4,4]]}
输出
[0,1]