概率论是深度学习(Deep Learning, DL)和深度强化学习(Deep Reinforcement Learning, DRL)的核心数学基础之一,尤其在建模不确定性、优化模型和决策过程中扮演关键角色。本文将从概率论的基础概念出发,结合图解和动态车间调度(Job Shop Scheduling, JSS)的DRL场景,详细解析概率在深度学习中的应用,涵盖概率分布、期望、贝叶斯定理、蒙特卡洛方法等核心概念,并提供基于TensorFlow.NET的C#代码示例,展示如何在DRL中利用概率方法优化调度决策。代码将包含清晰的中文注释,并优化为更简洁易读的结构。


1. 概率论基础概念与图解

1.1 概率与随机变量

  • 定义:

    • 概率:事件发生的可能性,范围为 ([0, 1])。

    • 随机变量:描述随机事件结果的变量,分为离散型(如动作选择)和连续型(如状态值)。

    • 数学表示:

      • 离散随机变量 ( X ),概率质量函数(PMF):

        P(X=x)P(X = x)P(X = x)

      • 连续随机变量 ( X ),概率密度函数(PDF):

        fX(x)f_X(x)f_X(x)

        ,概率为

        P(a≤X≤b)=∫abfX(x) dxP(a \leq X \leq b) = \int_a^b f_X(x) \, dxP(a \leq X \leq b) = \int_a^b f_X(x) \, dx

        .
  • 图解:

    离散:P(X = 1) = 0.4, P(X = 2) = 0.6
    [图:柱状图,X=1 和 X=2 的概率]
    连续:f(x) = N(0, 1)(标准正态分布)
    [图:正态分布曲线,x轴为值,y轴为密度]
  • 深度学习中的作用:

    • 建模数据分布(如图像像素值)。

    • DRL中,状态转移概率 ( P(s'|s, a) ) 描述环境动态。

  • 车间调度示例:

    • 动作选择:离散随机变量 ( A ),表示选择某个工序的概率。

    • 状态:连续随机变量 ( S ),如机器可用时间。

1.2 概率分布

  • 常见分布:

    • 伯努利分布:二元事件(如选择/不选择某工序),

      P(X=1)=pP(X=1) = pP(X=1) = p

      P(X=0)=1−pP(X=0) = 1-pP(X=0) = 1-p

    • 多项式分布:多类别事件(如选择多个工序),

      P(X1,…,Xk)=n!x1!…xk!p1x1…pkxkP(X_1, \dots, X_k) = \frac{n!}{x_1!\dots x_k!} p_1^{x_1} \dots p_k^{x_k}P(X_1, \dots, X_k) = \frac{n!}{x_1!\dots x_k!} p_1^{x_1} \dots p_k^{x_k}

      .
    • 正态分布:连续变量,

      f(x)=12πσ2e−(x−μ)22σ2f(x) = \frac{1}{\sqrt{2\pi\sigma^2}} e^{-\frac{(x-\mu)^2}{2\sigma^2}}f(x) = \frac{1}{\sqrt{2\pi\sigma^2}} e^{-\frac{(x-\mu)^2}{2\sigma^2}}

      .
  • 深度学习中的作用:

    • 分类任务:Softmax输出概率分布(如动作选择概率)。

    • 噪声建模:正态分布用于权重初始化或数据增强。

  • 车间调度示例:

    • 动作选择概率:Softmax输出

      P(ai∣s)=eQ(s,ai)∑jeQ(s,aj)P(a_i|s) = \frac{e^{Q(s, a_i)}}{\sum_j e^{Q(s, a_j)}}P(a_i|s) = \frac{e^{Q(s, a_i)}}{\sum_j e^{Q(s, a_j)}}

      .
    • 图解:

      Q(s, a) = [2.1, 1.5, 0.8]
      Softmax:P(a|s) = [0.58, 0.32, 0.10]
      [图:Softmax概率分布柱状图]

1.3 期望(Expectation)

  • 定义:

    • 期望是随机变量的加权平均,衡量其“平均”结果。

    • 数学表示:

      • 离散:

        E[X]=∑xxP(X=x)E[X] = \sum_x x P(X=x)E[X] = \sum_x x P(X=x)

        .
      • 连续:

        E[X]=∫xfX(x) dxE[X] = \int x f_X(x) \, dxE[X] = \int x f_X(x) \, dx

        .
  • 深度学习中的作用:

    • 损失函数:期望损失

      E[L(θ)]E[L(\theta)]E[L(\theta)]

      用于优化模型。
    • DRL:Q值

      Q(s,a)=E[Rt+γmax⁡a′Q(s′,a′)]Q(s, a) = E[R_t + \gamma \max_{a'} Q(s', a')]Q(s, a) = E[R_t + \gamma \max_{a'} Q(s', a')]

      ,表示期望累积奖励。
  • 车间调度示例:

    • 期望Makespan:

      E喧嚣E[Makespan]=∑P(state)⋅Makespan(state)E喧嚣 E[\text{Makespan}] = \sum P(\text{state}) \cdot \text{Makespan(state)}E喧嚣 E[\text{Makespan}] = \sum P(\text{state}) \cdot \text{Makespan(state)}

      .
    • 图解:

      状态 s1, s2, s3
      Makespan = [10, 12, 15]
      P(s) = [0.5, 0.3, 0.2]
      E[Makespan] = 10*0.5 + 12*0.3 + 15*0.2 = 11.6
      [图:期望值计算]

1.4 贝叶斯定理

  • 定义:

    • 描述条件概率:

      P(A∣B)=P(B∣A)P(A)P(B)P(A|B) = \frac{P(B|A)P(A)}{P(B)}P(A|B) = \frac{P(B|A)P(A)}{P(B)}

      .
  • 深度学习中的作用:

    • 贝叶斯网络:建模参数的不确定性。

    • 变分自编码器(VAE):推断潜在变量分布 ( P(z|x) ).

  • 车间调度示例:

    • 推断机器故障概率:

      P(故障∣状态)=P(状态∣故障)P(故障)P(状态)P(\text{故障}|\text{状态}) = \frac{P(\text{状态}|\text{故障})P(\text{故障})}{P(\text{状态})}P(\text{故障}|\text{状态}) = \frac{P(\text{状态}|\text{故障})P(\text{故障})}{P(\text{状态})}

      .
    • 图解:

      P(故障|高温) = P(高温|故障) * P(故障) / P(高温)
      [图:贝叶斯公式条件概率]

1.5 蒙特卡洛方法

  • 定义:

    • 通过随机抽样估计期望或积分。

    • 数学表示:

      E[f(X)]≈1N∑i=1Nf(xi)E[f(X)] \approx \frac{1}{N} \sum_{i=1}^N f(x_i)E[f(X)] \approx \frac{1}{N} \sum_{i=1}^N f(x_i)

      ,其中

      xi∼P(X)x_i \sim P(X)x_i \sim P(X)

      .
  • 深度学习中的作用:

    • 经验回放:DRL中通过采样经验估计Q值。

    • 蒙特卡洛 dropout:通过多次前向传播估计模型不确定性。

  • 车间调度示例:

    • 估计平均Makespan:通过多次模拟调度策略,计算

      Avg Makespan=1N∑Makespani\text{Avg Makespan} = \frac{1}{N} \sum \text{Makespan}_i\text{Avg Makespan} = \frac{1}{N} \sum \text{Makespan}_i

      .
    • 图解:

      模拟 N 次调度
      Makespan = [11, 12, 10, 13, ...]
      E[Makespan] ≈ 平均值
      [图:蒙特卡洛采样]

2. 概率在深度学习与DRL中的应用

2.1 概率分布与Softmax

  • Softmax函数:

    • 将Q值转换为概率分布:

      P(ai∣s)=eQ(s,ai)∑jeQ(s,aj)P(a_i|s) = \frac{e^{Q(s, a_i)}}{\sum_j e^{Q(s, a_j)}}P(a_i|s) = \frac{e^{Q(s, a_i)}}{\sum_j e^{Q(s, a_j)}}

    • 用于动作选择(如ε-贪婪策略中的概率采样)。

  • 车间调度示例:

    • Q值

      Q(s,a)=[2.1,1.5,0.8]Q(s, a) = [2.1, 1.5, 0.8]Q(s, a) = [2.1, 1.5, 0.8]

      ,Softmax输出动作概率:

      P(a∣s)=[0.58,0.32,0.10]P(a|s) = [0.58, 0.32, 0.10]P(a|s) = [0.58, 0.32, 0.10]

    • 图解:

      Q值 -> Softmax -> 概率分布
      [图:Q值到概率的转换]

2.2 期望与Q值

  • Q值:

    • Q值是累积奖励的期望:

      Q(s,a)=E[Rt+γRt+1+γ2Rt+2+…∣s,a]Q(s, a) = E[R_t + \gamma R_{t+1} + \gamma^2 R_{t+2} + \dots | s, a]Q(s, a) = E[R_t + \gamma R_{t+1} + \gamma^2 R_{t+2} + \dots | s, a]

    • DQN通过神经网络近似

      Q(s,a;θ)Q(s, a; \theta)Q(s, a; \theta)

      .
  • 车间调度示例:

    • 期望奖励:

      E[R]=∑P(s′,r∣s,a)⋅rE[R] = \sum P(s', r|s, a) \cdot rE[R] = \sum P(s', r|s, a) \cdot r

      ,奖励为负的Makespan增量。
    • 图解:

      s -> a -> (s', r)
      Q(s, a) = E[R + γ max Q(s', a')]
      [图:期望奖励计算]

2.3 蒙特卡洛与经验,回放

  • 经验回放:

    • 存储经验 ( (s, a, r, s') ),随机抽样估计Q值。

    • 蒙特卡洛方法:通过多次采样逼近期望Q值。

  • 车间调度示例:

    • 抽样32条经验,计算目标Q值:

      target=r+γmax⁡a′Q(s′,a′;θ′)\text{target} = r + \gamma \max_{a'} Q(s', a'; \theta')\text{target} = r + \gamma \max_{a'} Q(s', a'; \theta')

    • 图解:

      经验池:[(s1, a1, r1, s1'), (s2, a2, r2, s2'), ...]
      随机抽样 -> 目标Q值
      [图:经验回放采样]

2.4 贝叶斯方法

  • 变分推断:

    • 近似后验分布

      P(θ∣D)≈q(θ)P(\theta|D) \approx q(\theta)P(\theta|D) \approx q(\theta)

      ,优化模型参数。
  • 车间调度示例:

    • 推断机器状态的概率分布:

      P(可用∣历史数据)P(\text{可用}|\text{历史数据})P(\text{可用}|\text{历史数据})

      .
    • 图解:

      P(可用|数据) = P(数据|可用) * P(可用) / P(数据)
      [图:贝叶斯推断]

3. C#代码示例:基于TensorFlow.NET的DQN与概率方法

以下代码实现DQN优化动态车间调度问题,使用Softmax概率分布进行动作选择,结合经验回放和目标网络,利用蒙特卡洛方法估计Q值。代码包含清晰的中文注释,结构简洁。

3.1 代码

csharp

using System;
using System.Collections.Generic;
using System.Linq;
using Tensorflow;
using NumSharp;
using static Tensorflow.Binding;

namespace DynamicDQNScheduler
{
    /// <summary>
    /// 动态车间调度器,使用DQN优化调度,目标是最小化Makespan。
    /// 概率方法:Softmax动作选择,蒙特卡洛经验回放,目标网络稳定训练。
    /// </summary>
    class DynamicDQNScheduler
    {
        /// <summary>
        /// 工序类,表示作业的一个工序。
        /// </summary>
        public class Operation
        {
            public int JobId { get; set; } // 作业ID
            public int MachineId { get; set; } // 机器ID
            public int Duration { get; set; } // 加工时间
        }

        /// <summary>
        /// 作业类,表示一个作业。
        /// </summary>
        public class Job
        {
            public int Id { get; set; } // 作业ID
            public List<Operation> Operations { get; set; } = new List<Operation>(); // 工序列表
            public int ArrivalTime { get; set; } // 到达时间
        }

        /// <summary>
        /// 经验类,用于经验回放。
        /// </summary>
        public class Experience
        {
            public float[] State { get; set; } // 当前状态
            public int Action { get; set; } // 动作索引
            public float Reward { get; set; } // 奖励
            public float[] NextState { get; set; } // 下一状态
            public bool Done { get; set; } // 是否完成
        }

        // 成员变量
        private readonly List<Job> jobs; // 作业列表
        private readonly int machineCount; // 机器数量
        private List<int> machineAvailableTime; // 机器可用时间
        private List<int> jobNextOperation; // 作业当前工序索引
        private List<int> jobLastEndTime; // 作业最后完工时间
        private readonly Random rand = new Random(); // 随机数生成器
        private readonly List<Experience> replayBuffer = new List<Experience>(); // 经验回放缓冲区
        private float epsilon = 0.5f; // ε-贪婪探索率
        private readonly float epsilonDecay = 0.995f; // ε衰减率
        private readonly float gamma = 0.9f; // 折扣因子
        private readonly Graph graph = new Graph().as_default(); // TensorFlow计算图
        private readonly Session session; // TensorFlow会话
        private Operation trainOp; // 训练操作
        private Tensor stateInput; // 状态输入
        private Tensor qValues; // 主网络Q值
        private Tensor targetQ; // 目标Q值
        private Tensor targetQValues; // 目标网络Q值
        private readonly int maxActions = 10; // 最大动作数量
        private readonly int targetUpdateFreq = 10; // 目标网络更新频率

        /// <summary>
        /// 构造函数,初始化调度器和神经网络。
        /// </summary>
        /// <param name="jobs">作业列表</param>
        /// <param name="machineCount">机器数量</param>
        public DynamicDQNScheduler(List<Job> jobs, int machineCount)
        {
            this.jobs = jobs;
            this.machineCount = machineCount;
            this.machineAvailableTime = new List<int>(new int[machineCount]);
            this.jobNextOperation = new List<int>(new int[jobs.Count]);
            this.jobLastEndTime = new List<int>(new int[jobs.Count]);
            InitializeNeuralNetwork();
            session = tf.Session();
            session.run(tf.global_variables_initializer());
        }

        /// <summary>
        /// 初始化主网络和目标网络。
        /// 数学背景:
        /// - 主网络:Q(s, a; θ) = W2 * ReLU(W1 * s + b1) + b2
        /// - 目标网络:Q(s', a'; θ') = tw2 * ReLU(tw1 * s' + tb1) + tb2
        /// - 损失:L(θ) = E[(r + γ max Q(s', a'; θ') - Q(s, a; θ))²]
        /// - Softmax:P(a|s) = exp(Q(s, a)) / Σ exp(Q(s, a'))
        /// </summary>
        private void InitializeNeuralNetwork()
        {
            tf_with(graph, g =>
            {
                int stateSize = 1 + machineCount + jobs.Count; // 状态维度
                stateInput = tf.placeholder(tf.float32, shape: new Shape(-1, stateSize), name: "state");

                // 主网络
                var w1 = tf.get_variable("w1", shape: new Shape(stateSize, 64), initializer: tf.random_normal_initializer());
                var b1 = tf.get_variable("b1", shape: new Shape(64), initializer: tf.zeros_initializer());
                var h1 = tf.nn.relu(tf.matmul(stateInput, w1) + b1);
                var w2 = tf.get_variable("w2", shape: new Shape(64, maxActions), initializer: tf.random_normal_initializer());
                var b2 = tf.get_variable("b2", shape: new Shape(maxActions), initializer: tf.zeros_initializer());
                qValues = tf.matmul(h1, w2) + b2;

                // 目标网络
                var tw1 = tf.get_variable("tw1", shape: new Shape(stateSize, 64), initializer: tf.random_normal_initializer());
                var tb1 = tf.get_variable("tb1", shape: new Shape(64), initializer: tf.zeros_initializer());
                var th1 = tf.nn.relu(tf.matmul(stateInput, tw1) + tb1);
                var tw2 = tf.get_variable("tw2", shape: new Shape(64, maxActions), initializer: tf.random_normal_initializer());
                var tb2 = tf.get_variable("tb2", shape: new Shape(maxActions), initializer: tf.zeros_initializer());
                targetQValues = tf.matmul(th1, tw2) + tb2;

                // 损失函数
                targetQ = tf.placeholder(tf.float32, shape: new Shape(-1, maxActions), name: "targetQ");
                var loss = tf.reduce_mean(tf.square(targetQ - qValues));
                trainOp = tf.train.AdamOptimizer(0.001f).minimize(loss);
            });
        }

        /// <summary>
        /// 更新目标网络参数:θ' ← θ。
        /// </summary>
        private void UpdateTargetNetwork()
        {
            session.run(new[] {
                tf.get_variable("tw1").assign(tf.get_variable("w1")),
                tf.get_variable("tb1").assign(tf.get_variable("b1")),
                tf.get_variable("tw2").assign(tf.get_variable("w2")),
                tf.get_variable("tb2").assign(tf.get_variable("b2"))
            });
        }

        /// <summary>
        /// 添加新作业,动态扩展状态空间。
        /// </summary>
        /// <param name="newJob">新作业</param>
        public void AddJob(Job newJob)
        {
            jobs.Add(newJob);
            jobNextOperation.Add(0);
            jobLastEndTime.Add(0);
            Console.WriteLine($"时间 {newJob.ArrivalTime}:新作业 J{newJob.Id} 到达");
        }

        /// <summary>
        /// 获取状态向量:s = [时间, 机器可用时间, 作业进度]。
        /// </summary>
        /// <param name="currentTime">当前时间</param>
        /// <returns>状态向量</returns>
        private float[] GetState(int currentTime)
        {
            var state = new float[1 + machineCount + jobs.Count];
            state[0] = currentTime;
            for (int i = 0; i < machineCount; i++) state[i + 1] = machineAvailableTime[i];
            for (int i = 0; i < jobs.Count; i++) state[i + 1 + machineCount] = jobNextOperation[i];
            return state;
        }

        /// <summary>
        /// 获取可用动作(可调度的工序)。
        /// </summary>
        /// <param name="currentTime">当前时间</param>
        /// <returns>动作列表(作业、工序、索引)</returns>
        private List<(Job, Operation, int)> GetAvailableActions(int currentTime)
        {
            var actions = new List<(Job, Operation, int)>();
            int actionIndex = 0;
            for (int i = 0; i < jobs.Count; i++)
            {
                if (jobs[i].ArrivalTime <= currentTime && jobNextOperation[i] < jobs[i].Operations.Count)
                {
                    actions.Add((jobs[i], jobs[i].Operations[jobNextOperation[i]], actionIndex++));
                }
            }
            return actions;
        }

        /// <summary>
        /// 使用ε-贪婪策略选择动作,基于Softmax概率分布。
        /// 数学背景:P(a|s) = exp(Q(s, a)) / Σ exp(Q(s, a'))
        /// </summary>
        /// <param name="state">当前状态</param>
        /// <param name="actions">可用动作</param>
        /// <returns>动作索引</returns>
        private int SelectAction(float[] state, List<(Job, Operation, int)> actions)
        {
            if (rand.NextDouble() < epsilon) // 探索:随机选择
                return actions.Count > 0 ? actions[rand.Next(actions.Count)].actionIndex : -1;

            var stateTensor = np.array(state).reshape(1, -1);
            var qVals = session.run(qValues, new FeedItem(stateInput, stateTensor));
            var probs = Softmax(qVals[0]); // Softmax概率分布
            float maxProb = float.MinValue;
            int bestAction = -1;

            for (int i = 0; i < actions.Count; i++)
            {
                if (probs[actions[i].actionIndex] > maxProb)
                {
                    maxProb = probs[actions[i].actionIndex];
                    bestAction = actions[i].actionIndex;
                }
            }

            return bestAction;
        }

        /// <summary>
        /// 计算Softmax概率分布。
        /// 数学公式:P(a_i|s) = exp(Q_i) / Σ exp(Q_j)
        /// </summary>
        /// <param name="qValues">Q值数组</param>
        /// <returns>概率分布</returns>
        private float[] Softmax(float[] qValues)
        {
            var expQ = qValues.Select(x => (float)Math.Exp(x)).ToArray();
            var sumExpQ = expQ.Sum();
            return expQ.Select(x => x / sumExpQ).ToArray();
        }

        /// <summary>
        /// 训练网络,使用蒙特卡洛经验回放。
        /// 数学背景:
        /// - 目标Q值:target = r + γ max Q(s', a'; θ')
        /// - 蒙特卡洛:通过采样估计E[L(θ)]
        /// </summary>
        private void TrainNetwork()
        {
            if (replayBuffer.Count < 32) return;

            var batch = replayBuffer.OrderBy(x => rand.Next()).Take(32).ToList();
            var states = batch.Select(e => e.State).ToArray();
            var targets = new float[batch.Count, maxActions];

            for (int i = 0; i < batch.Count; i++)
            {
                var experience = batch[i];
                var nextStateTensor = np.array(experience.NextState).reshape(1, -1);
                var nextQ = session.run(targetQValues, new FeedItem(stateInput, nextStateTensor));
                float maxNextQ = nextQ[0].Max();
                targets[i, experience.Action] = experience.Reward + (experience.Done ? 0 : gamma * maxNextQ);
            }

            var stateBatch = np.array(states);
            session.run(trainOp, new FeedItem(stateInput, stateBatch), new FeedItem(targetQ, targets));
        }

        /// <summary>
        /// 运行DQN调度,优化Makespan。
        /// </summary>
        /// <param name="maxSimulationTime">最大模拟时间</param>
        /// <returns>最佳Makespan</returns>
        public int Run(int maxSimulationTime)
        {
            int episodeCount = 0;
            int bestMakespan = int.MaxValue;

            while (episodeCount < 50)
            {
                machineAvailableTime = new List<int>(new int[machineCount]);
                jobNextOperation = new List<int>(new int[jobs.Count]);
                jobLastEndTime = new List<int>(new int[jobs.Count]);
                int currentTime = 0;
                int stepCount = 0;

                while (currentTime < maxSimulationTime || jobs.Any((j, i) => jobNextOperation[i] < j.Operations.Count))
                {
                    if (currentTime == 5 && episodeCount == 0)
                    {
                        var newJob = new Job
                        {
                            Id = jobs.Count,
                            ArrivalTime = currentTime,
                            Operations = new List<Operation>
                            {
                                new Operation { JobId = jobs.Count, MachineId = 0, Duration = 2 },
                                new Operation { JobId = jobs.Count, MachineId = 1, Duration = 3 },
                                new Operation { JobId = jobs.Count, MachineId = 2, Duration = 1 }
                            }
                        };
                        AddJob(newJob);
                    }

                    var state = GetState(currentTime);
                    var actions = GetAvailableActions(currentTime);
                    if (actions.Count == 0)
                    {
                        currentTime++;
                        continue;
                    }

                    int actionIndex = SelectAction(state, actions);
                    if (actionIndex == -1) continue;

                    var (job, operation, _) = actions.Find(a => a.actionIndex == actionIndex);
                    int jobIndex = jobs.IndexOf(job);
                    int machineId = operation.MachineId;
                    int duration = operation.Duration;

                    int oldMakespan = machineAvailableTime.Max();
                    int startTime = Math.Max(machineAvailableTime[machineId], jobLastEndTime[jobIndex]);
                    startTime = Math.Max(startTime, currentTime);
                    int endTime = startTime + duration;

                    machineAvailableTime[machineId] = endTime;
                    jobLastEndTime[jobIndex] = endTime;
                    jobNextOperation[jobIndex]++;
                    currentTime = startTime;

                    int newMakespan = machineAvailableTime.Max();
                    float reward = -(newMakespan - oldMakespan);
                    var nextState = GetState(currentTime);
                    bool done = !jobs.Any((j, i) => jobNextOperation[i] < j.Operations.Count);

                    replayBuffer.Add(new Experience
                    {
                        State = state,
                        Action = actionIndex,
                        Reward = reward,
                        NextState = nextState,
                        Done = done
                    });

                    TrainNetwork();
                    if (stepCount % targetUpdateFreq == 0) UpdateTargetNetwork();

                    Console.WriteLine($"时间 {startTime}:调度 J{job.Id}-工序{jobNextOperation[jobIndex]} 到 M{machineId},加工时间:{duration},完成时间:{endTime}");

                    epsilon = Math.Max(0.1f, epsilon * epsilonDecay);
                    stepCount++;
                }

                int makespan = machineAvailableTime.Max();
                bestMakespan = Math.Min(bestMakespan, makespan);
                episodeCount++;
                Console.WriteLine($"第 {episodeCount} 次训练,Makespan:{makespan}");
            }

            return bestMakespan;
        }

        /// <summary>
        /// 测试程序。
        /// </summary>
        public static void Main()
        {
            var jobs = new List<Job>
            {
                new Job { Id = 0, ArrivalTime = 0, Operations = new List<Operation>
                    {
                        new Operation { JobId = 0, MachineId = 0, Duration = 3 },
                        new Operation { JobId = 0, MachineId = 1, Duration = 2 },
                        new Operation { JobId = 0, MachineId = 2, Duration = 5 }
                    }
                },
                new Job { Id = 1, ArrivalTime = 0, Operations = new List<Operation>
                    {
                        new Operation { JobId = 1, MachineId = 1, Duration = 4 },
                        new Operation { JobId = 1, MachineId = 2, Duration = 1 },
                        new Operation { JobId = 1, MachineId = 0, Duration = 2 }
                    }
                },
                new Job { Id = 2, ArrivalTime = 0, Operations = new List<Operation>
                    {
                        new Operation { JobId = 2, MachineId = 2, Duration = 2 },
                        new Operation { JobId = 2, MachineId = 0, Duration = 4 },
                        new Operation { JobId = 2, MachineId = 1, Duration = 3 }
                    }
                }
            };

            var scheduler = new DynamicDQNScheduler(jobs, 3);
            int makespan = scheduler.Run(20);
            Console.WriteLine($"最终Makespan:{makespan}");
        }
    }
}

3.2 代码说明

  • 概率方法:

    • Softmax:SelectAction中使用Softmax将Q值转换为动作选择概率。

    • 蒙特卡洛:TrainNetwork通过随机抽样32条经验估计期望损失。

  • 目标网络:

    • 每10步更新目标网络参数,稳定Q值目标。

  • 状态与动作:

    • 状态:

      s=[t,m1,m2,m3,p1,p2,p3,… ]\mathbf{s} = [t, m_1, m_2, m_3, p_1, p_2, p_3, \dots]\mathbf{s} = [t, m_1, m_2, m_3, p_1, p_2, p_3, \dots]

      .
    • 动作:选择工序,基于Softmax概率分布。

  • 奖励:

    r=−ΔMakespanr = -\Delta \text{Makespan}r = -\Delta \text{Makespan}

    .
  • 图解:

    状态:s = [5, 3, 4, 2, 1, 2, 0]
    Q值:q = [2.1, 1.5, 0.8]
    Softmax:P(a|s) = [0.58, 0.32, 0.10]
    经验回放:[(s1, a1, r1, s1'), ...]

4. 总结

  • 概率核心概念:

    • 概率分布(Softmax)、期望(Q值)、贝叶斯定理(推断)、蒙特卡洛方法(经验回放)。

    • 图解直观展示概率分布和期望计算。

  • 深度学习应用:

    • Softmax用于动作选择,蒙特卡洛估计Q值,贝叶斯方法建模不确定性。

  • 车间调度:

    • DRL通过概率方法优化动态调度,适应新作业到达。

    • 代码使用Softmax和经验回放实现动作选择和Q值优化。

  • 代码特点:

    • 清晰的注释,结构化说明功能和数学背景。

    • 集成目标网络和Softmax,提升训练稳定性和动作选择。

如果您需要更深入的概率推导(如贝叶斯变分推断)、更复杂的图解(如概率分布3D可视化)或进一步代码优化(如优先级经验回放),请告诉我,我可以提供更详细的内容!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐