首页 > 试题广场 >

小红的云服务器带宽预测模型

[编程题]小红的云服务器带宽预测模型
  • 热度指数:524 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
小红目前是某云服务平台的 AI 工程师。为了更精准地分配机房带宽资源,她打算训练一个简单的线性神经元模型,用于实时预测每台服务器的出口带宽需求。 该模型接受两个输入特征:当前活跃连接数 x_1 和历史平均延迟指标 x_2。模型的预测输出 y_{pred} 的计算方式如下: y_{pred} = w_1 x_1 + w_2 x_2 + b 其中 w_1, w_2 为特征权重,b 为偏置项。 为了让模型能够处理大规模的实时数据流,小红决定采用 AdamW 优化器进行参数更新。具体算法流程如下: 1. 初始化:初始参数 w_1 = 0, w_2 = 0, b = 0。对应的动量估计(一阶矩)m 和平方梯度估计(二阶矩)v 也均初始化为 0。 2. 梯度计算:对于每个样本,给定真实带宽值 y_{true},各参数的梯度定义为: - g_{w_1} = 2(y_{pred} - y_{true})x_1 - g_{w_2} = 2(y_{pred} - y_{true})x_2 - g_b = 2(y_{pred} - y_{true}) 3. 参数迭代:设当前正在处理第 t 个样本(t 从 1 开始),对于每一个参数 \\theta \\in \\{w_1, w_2, b\\},执行以下更新: - m_t = \\beta_1 m_{t-1} + (1 - \\beta_1) g_t - v_t = \\beta_2 v_{t-1} + (1 - \\beta_2) g_t^2 - \\hat{m}_t = m_t / (1 - \\beta_1^t) - \\hat{v}_t = v_t / (1 - \\beta_2^t) - \\theta_t = \\theta_{t-1} - \\alpha (\\frac{\\hat{m}_t}{\\sqrt{\\hat{v}_t} + \\epsilon} + \\lambda \\theta_{t-1}) 4. 超参数设置: 小红使用了以下固定的实验参数: \\beta_1 = 0.9, \\beta_2 = 0.999, \\lambda = 0.01, \\alpha = 0.001, \\epsilon = 10^{-8} 请根据给定的 N 个样本,计算最终的模型参数。 提示: - 银行家舍入法(Round half to even):舍入到最接近的数值;若与两个数值的距离相等(即需要舍弃的部分恰好为 0.5),则舍入到最近的偶数。

输入描述:
第一行包含一个整数 N(1 ≤ N ≤ 10^5),代表样本总数。
接下来的 N 行,每行包含三个浮点数 x_1, x_2, y_{true}(-1000.0 ≤ x_1, x_2, y_{true} ≤ 1000.0),含义见题目描述。


输出描述:
输出一行三个浮点数,分别表示经过 N 次更新后的 w_1, w_2, b。
结果必须精确到 6 位小数,且使用银行家舍入法(四舍六入五成双)。数值之间用一个空格分隔,末尾不要有多余空格。
示例1

输入

2
2.0 0.0 4.0
0.0 2.0 -2.0

输出

0.001670 -0.000744 0.001266

说明

在样例中,处理第一个样本后,w_1 约更新为 0.001,w_2 保持为 0,b 约更新为 0.001。接着在此基础上处理第二个样本。
示例2

输入

3
1.0 1.0 2.0
2.0 2.0 4.0
3.0 3.0 6.0

输出

0.002750 0.002750 0.002923

说明

For sample 1 (latex): latex. The parameters are updated from 0 to latex.
For sample 2 (latex): latex. The parameters are updated to latex.
For sample 3 (latex): latex. The parameters are updated to the final values.
import sys
import math

def main():
    n = int(input())

    samples = []
    for _ in range(n):
        a1, a2, a3 = map(float, input().split())
        samples.append([a1, a2, a3])

    w1 = 0.0
    w2 = 0.0
    b = 0.0

    beta1 = 0.9
    beta2 = 0.999
    lamda = 0.01
    alpha = 0.001
    episilo = 1e-8

    # 一阶矩
    mw1 = 0.0
    mw2 = 0.0
    mb = 0.0

    # 二阶矩
    vw1 = 0.0
    vw2 = 0.0
    vb = 0.0

    for i in range(n):
        t = i + 1

        cur_x1 = samples[i][0]
        cur_x2 = samples[i][1]
        y_true = samples[i][2]

        # 预测值
        y_pre = w1 * cur_x1 + w2 * cur_x2 + b

        # 误差
        diff = y_pre - y_true

        # 梯度
        gw1 = 2 * diff * cur_x1
        gw2 = 2 * diff * cur_x2
        gb = 2 * diff

        # 保存旧参数
        old_w1 = w1
        old_w2 = w2
        old_b = b

        # 更新 w1
        mw1 = beta1 * mw1 + (1 - beta1) * gw1
        vw1 = beta2 * vw1 + (1 - beta2) * gw1 * gw1

        mw1_hat = mw1 / (1 - beta1 ** t)
        vw1_hat = vw1 / (1 - beta2 ** t)

        w1 = old_w1 - alpha * (
            mw1_hat / (math.sqrt(vw1_hat) + episilo) + lamda * old_w1
        )

        # 更新 w2
        mw2 = beta1 * mw2 + (1 - beta1) * gw2
        vw2 = beta2 * vw2 + (1 - beta2) * gw2 * gw2

        mw2_hat = mw2 / (1 - beta1 ** t)
        vw2_hat = vw2 / (1 - beta2 ** t)

        w2 = old_w2 - alpha * (
            mw2_hat / (math.sqrt(vw2_hat) + episilo) + lamda * old_w2
        )

        # 更新 b
        mb = beta1 * mb + (1 - beta1) * gb
        vb = beta2 * vb + (1 - beta2) * gb * gb

        mb_hat = mb / (1 - beta1 ** t)
        vb_hat = vb / (1 - beta2 ** t)

        b = old_b - alpha * (
            mb_hat / (math.sqrt(vb_hat) + episilo) + lamda * old_b
        )

    print(f"{w1:.6f} {w2:.6f} {b:.6f}")

if __name__ == "__main__":
    main()
发表于 2026-05-19 22:50:26 回复(0)