第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()

    

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐