#P4344.第3题-商品购买预测
·
第3题-商品购买预测 - problem_ide - CodeFun2000
import sys
import numpy as np
import math
def stable_sigmoid(z_list):
"""
数值稳定版 sigmoid
对 z >= 0 和 z < 0 分段计算,避免 exp 上下溢
"""
results = []
for z in z_list:
if z>=0:
val = 1/(1+math.exp(-z))
else:
val = math.exp(z)/(1+math.exp(z))
results.append(val)
return np.array(results,dtype=np.float64)
def compute_loss(X,y,w,b,lam,eps=1e-15):
"""
J(w,b) = 平均交叉熵 + (lam / (2n)) * ||w||_2^2
"""
n = X.shape[0]
z = X @ w + b
p = stable_sigmoid(z)
# 防止 log(0)
p = np.clip(p, eps, 1.0 - eps) # 强行把概率卡在 [1e-15, 1 - 1e-15] 之间,防止后面算对数时炸掉
ce = -np.mean(y * np.log(p) + (1.0 - y) * np.log(1.0 - p))
reg = (lam / (2.0 * n)) * np.sum(w * w)
return ce + reg
def train_logistic_regression(X, y, max_iter, alpha, lam, tol):
"""
按题解进行批量梯度下降训练
初始化: w=0, b=0
终止条件:
1) 达到 max_iter
2) 参数更新后重新计算损失,若相邻两次损失差 < tol,则停止
"""
n, d = X.shape
w = np.zeros(d, dtype=np.float64)
b = 0.0
prev_loss = compute_loss(X, y, w, b, lam)
for _ in range(max_iter):
z = X @ w + b
p = stable_sigmoid(z) # shape: (n,)
# 梯度(严格对应题解)
dw = (X.T @ (p - y)) / n + (lam / n) * w
db = np.sum(p - y) / n
# 参数更新
w -= alpha * dw
b -= alpha * db
# 更新后重新计算损失,再判断是否收敛
curr_loss = compute_loss(X, y, w, b, lam)
if abs(curr_loss - prev_loss) < tol:
break
prev_loss = curr_loss
return w, b
def predict(X, w, b):
"""
概率 >= 0.5 预测为 1,否则为 0
"""
probs = stable_sigmoid(X @ w + b)
preds = (probs >= 0.5).astype(int)
return preds, probs
def main():
data = sys.stdin.read().split()
if not data:
return
n = int(data[0])
max_iter = int(data[1])
alpha = float(data[2])
lam = float(data[3])
tol= float(data[4])
idx = 5
x_train = []
y_train = []
for _ in range(n):
age = float(data[idx])
income = float(data[idx+1])
browse = float(data[idx+2])
label = float(data[idx+3])
idx = idx+4
x_train.append([age,income,browse])
y_train.append(label)
x_train= np.array(x_train,dtype=np.float64)
y_train= np.array(y_train,dtype=np.float64)
m = int(data[idx])
idx += 1
x_test =[]
for _ in range(m):
age = float(data[idx])
income = float(data[idx+1])
browse = float(data[idx+2])
idx = idx+3
x_test.append([age,income,browse])
x_test = np.array(x_test,dtype=np.float64)
# 训练
w, b = train_logistic_regression(x_train, y_train, max_iter, alpha, lam, tol)
# 预测
preds, probs = predict(x_test, w, b)
# 输出
out = []
for pred, prob in zip(preds, probs):
out.append(f"{pred} {prob:.4f}")
sys.stdout.write("\n".join(out))
if __name__ == "__main__":
main()
更多推荐


所有评论(0)