《TF2.x强化学习手册》P59-P65-SARSA-Q-learning

文章目录

    • 实现SARSA算法和对应的强化学习智能体
      • 前期准备
      • 实现步骤
      • 工作原理
        • 初始化
        • 算法流程
    • 构建基于Q学习的智能体
      • 前期准备
      • 实现步骤
      • 工作原理
      • SARSA 算法的收敛性:
      • SARSA 适合在线学习和真实系统:
      • Q 学习算法的适用性:

实现SARSA算法和对应的强化学习智能体

  • SARSA(State-Action-Reward-State-Action)是一种强化学习算法,主要用于估计给定策略下的最优状态-动作价值函数(QQ 函数)。它是一种在轨策略(on-policy)算法,意味着它使用当前策略来选择动作。

如何实现SARSA算法(状态-行动-奖励-状态-行动)

以及如何使用SARSA开发和训练智能体

SARSA可以应用与无模型种子问题,并对未知马尔科夫决策过程MDP的价值函数进行优化。

前期准备

import numpy as np
import random

实现步骤

使用一个函数实现SARSA学习算法的更新

并使用 ϵ \epsilon ϵ-greedy的探索策略。

两者结合就可以得到一个在给定的强化学习环境中工作的完整智能体。

  1. 定义一个实现SARSA算法的函数,并用0初始化状态-动作价值

    def sarsa(env, max_episodes):grid_action_values = np.zeros((len(env.distinct_states), env.action_space.n))
    
  2. 根据环境的配置更新目标状态和炸弹状态的价值

    grid_action_values[env.goal_state] = 1
    grid_action_values[env.bomb_state] = -1
    
  3. 定义折扣因子gamma和学习率超参数 α \alpha α 。同样创建一个别名q表示grid_action_values

    gamma = 0.99  # discounting factor
    alpha = 0.01  # learning rate
    # q: state-action-value function
    q = grid_action_values
    
  4. 实现外部循环

    for episode in range(max_episodes):step_num = 1done = Falsestate = env.reset()action = greedy_policy(q[state], 1)
    
  5. 实现内循环,其中包括SARSA学习的更新步骤

    while not done:next_state, reward, done = env.step(action)step_num += 1decayed_epsilon = gamma ** step_num  # Doesn't have to be gammanext_action = greedy_policy(q[next_state], decayed_epsilon)q[state][action] += alpha * (reward + gamma * q[next_state][next_action] - q[state][action])state = next_stateaction = next_action
    
    1. 初始化:选择一个初始状态 S S S 和在该状态下执行的动作 A A A
    2. 循环直到结束
      • 执行动作 A A A,观察奖励 R R R 和下一个状态 S ′ S' S
      • 使用策略选择在状态 S ′ S' S 下要执行的动作 A ′ A' A
        在数学语言中,这些步骤可以表示为:
        S ′ , R , done = env.step ( A ) step_num + = 1 ϵ = γ step_num A ′ = greedy_policy ( Q ( S ′ ) , ϵ ) S', R, \text{done} = \text{env.step}(A) \\ \text{step\_num} += 1 \\ \epsilon = \gamma^{\text{step\_num}} \\ A' = \text{greedy\_policy}(Q(S'), \epsilon) S,R,done=env.step(A)step_num+=1ϵ=γstep_numA=greedy_policy(Q(S),ϵ)
    3. 更新 Q 值
      • 更新 Q 值 Q ( S , A ) Q(S, A) Q(S,A) 使用以下公式:
        Q ( S , A ) ← Q ( S , A ) + α [ R + γ Q ( S ′ , A ′ ) − Q ( S , A ) ] Q(S, A) \leftarrow Q(S, A) + \alpha \left[ R + \gamma Q(S', A') - Q(S, A) \right] Q(S,A)Q(S,A)+α[R+γQ(S,A)Q(S,A)]
        其中:
      • α \alpha α 是学习率。
      • γ \gamma γ 是折扣因子。
      • Q ( S ′ , A ′ ) Q(S', A') Q(S,A) 是在状态 S ′ S' S 下执行动作 A ′ A' A 的 Q 值。
    4. 转移到下一个状态和动作
      • 将当前状态 S S S 更新为下一个状态 S ′ S' S
      • 将当前动作 A A A 更新为下一个动作 A ′ A' A
        在数学语言中,这些步骤可以表示为:
        S = S ′ A = A ′ S = S' \\ A = A' S=SA=A
    5. 重复步骤 2-4,直到达到终止状态(done 为 True)。
  6. 在SARSA的最后一步,可视化状态-动作价值函数

    visualize_grid_action_values(grid_action_values)
    
  7. 实现智能体要使用的 ϵ \epsilon ϵ-greedy策略 greedy_policy()

    def greedy_policy(q_values, epsilon):"""Epsilon-greedy policy """if random.random() >= epsilon:return np.argmax(q_values)else:return random.randint(0, 3)
    
    • if random.random() >= epsilon::这里,random.random() 生成一个0到1之间的随机浮点数。如果这个随机数大于或等于 epsilon,那么执行 if 分支中的代码。
      • return np.argmax(q_values):如果条件为真,函数返回 q_values 数组中最大值的索引。这个索引代表了具有最高Q值的动作,也就是我们基于当前知识认为的最佳动作。
    • else::如果 random.random() 生成的随机数小于 epsilon,则执行 else 分支中的代码。
      • return random.randint(0, 3):在这种情况下,函数返回一个从0到3(包含0和3)的随机整数,代表随机选择的动作。这表明在 epsilon-greedy 策略中,有一定概率(由 epsilon 决定)我们会选择一个随机动作而不是最佳动作,以鼓励探索环境。
  8. 实现__main__函数并运行SARSA算法

    if __name__ == "__main__":max_episodes = 4000env = GridworldV2Env(step_cost=-0.1, max_ep_length=30)sarsa(env, max_episodes)
    

    在这里插入图片描述

工作原理

SARSA是一种基于时序差分学习的在轨策略(on-policy)控制算法。

本节使用SARSA算法估计最优状态-动作价值。SARSA算法与Q学习非常相似。

在每次迭代中,SARSA算法都会根据当前的状态和动作来更新价值表,目标是找到每个状态下的最优策略。通过这种方式,算法可以学习如何在给定的环境中取得最佳的行动策略。

总结一下,SARSA 算法的核心在于它在更新 Q 值时考虑了下一个状态 S ′ S' S 和下一个动作 A ′ A' A,而不是像 Q-Learning 那样考虑在下一个状态 S ′ S' S 下所有可能动作的最大 Q 值。这使得 SARSA 是一种同策略(on-policy)方法,因为它使用当前策略来选择下一个动作 A ′ A' A

Initialize Q ( s , a ) , ∀ s ∈ S , a ∈ A ( s ) Q(s,a),\forall s\in\mathcal{S},a\in\mathcal{A}(s) Q(s,a),sS,aA(s), arbitrarily, and Q ( t e r m i n a l − s t a t e , ⋅ ) = 0 Q(terminal-state,\cdot)=0 Q(terminalstate,)=0
Repeat (for each episode):
Initialize ⁡ S \operatorname{Initialize}S InitializeS
Choose A A A from S S S using policy derived from Q Q Q (e.g., ϵ \epsilon ϵ-greedy)
Repeat (for each step of episode):
T a k e a c t i o n A , o b s e r v e R , S ′ {\mathrm{Take~action~}A,{\mathrm{~observe~}}R,S^{\prime}} Take action A, observe R,S
Choose A ′ A^\prime A from S ′ S^\prime S using policy derived from Q Q Q (e.g., ϵ \epsilon ϵ-greedy)
Q ( S , A ) ← Q ( S , A ) + α [ R + γ Q ( S ′ , A ′ ) − Q ( S , A ) ] Q(S,A)\leftarrow Q(S,A)+\alpha\left[R+\gamma Q(S^{\prime},A^{\prime})-Q(S,A)\right] Q(S,A)Q(S,A)+α[R+γQ(S,A)Q(S,A)]
S ˙ ← S ′ ; \dot{S} \leftarrow S^{\prime }; S˙S; A ← A ′ ; A\leftarrow A^{\prime }; AA; until S S S is terminal

初始化
  • Q ( s , a ) Q(s,a) Q(s,a) 初始化:对于所有状态 s s s 和在状态 s s s 下可采取的动作 a a a Q Q Q 函数被任意初始化。 Q Q Q 函数表示在特定状态 s s s 下采取动作 a a a 的期望回报。
  • 终端状态 Q Q Q:对于终端状态,所有动作的 Q Q Q 值设为0,因为终端状态之后没有进一步的奖励。
算法流程
  1. 重复(每个剧集)

    • 对于每个剧集(episode),算法会进行以下步骤。
    • 初始化状态 S S S:选择一个初始状态 S S S
  2. 选择动作 A A A

    • 根据当前的 Q Q Q 函数(例如使用 ϵ \epsilon ϵ-贪婪策略)从状态 S S S 中选择一个动作 A A A
  3. 重复(每个剧集的每一步)

    • 采取动作并观察:执行动作 A A A,观察获得的奖励 R R R 和下一个状态 S ′ S' S
    • 选择下一个动作 A ′ A' A:在新的状态 S ′ S' S 下,使用基于 Q Q Q 函数的策略(如 ϵ \epsilon ϵ-贪婪)选择下一个动作 A ′ A' A
  4. 更新 Q Q Q 函数

    • 使用以下公式更新 Q Q Q 函数:
      Q ( S , A ) ← Q ( S , A ) + α [ R + γ Q ( S ′ , A ′ ) − Q ( S , A ) ] Q(S,A) \leftarrow Q(S,A) + \alpha \left[ R + \gamma Q(S',A') - Q(S,A) \right] Q(S,A)Q(S,A)+α[R+γQ(S,A)Q(S,A)]

    • 其中, α \alpha α 是学习率, γ \gamma γ 是折扣因子。

  5. 更新状态和动作

    • S ′ S' S 更新为新的当前状态 S S S
    • A ′ A' A 更新为新的当前动作 A A A
    • 这个过程一直重复,直到 S S S 成为终端状态。

构建基于Q学习的智能体

Q 学习可以应用于无模型的强化学习问题。它支持离轨(off-policy)学习,为使用其他策略或其他智能体收集经验的问题提供了实用的解决方案。

本节将构造一个可工作的强化学习智能体,使用Q学习算法生成状态-价值函数

前期准备

impoet numpy as np
import random

实现步骤

用一个函数实现Q学习算法,并使用 ϵ \epsilon ϵ-greedy的探索策略。

  1. 定义一个实现Q学习算法的函数,并用0初始化状态-动作价值

    def q_learning(env, max_episodes):grid_action_values = np.zeros((len(env.distinct_states), env.action_space.n))
    
  2. 根据环境的配置更新目标状态和炸弹状态的值

    grid_action_values[env.goal_state] = 1
    grid_action_values[env.bomb_state] = -1
    
  3. 定义折扣因子gamma 和学习率超参数 alpha 。同样创建一个别名q表示grid_action_values

    gamma = 0.99  # discounting factor
    alpha = 0.01  # learning rate
    # q: state-action-value function
    q = grid_action_values
    
  4. 实现外部循环

    for episode in range(max_episodes):step_num = 1done = Falsestate = env.reset()
    
  5. 实现内循环,其中包括Q学习的更新。此外对 ϵ \epsilon ϵ-greedy策略使用 ϵ \epsilon ϵ进行衰减

    while not done:decayed_epsilon = 1 * gamma ** step_num  # Doesn't have to be gammaaction = greedy_policy(q[state], decayed_epsilon)next_state, reward, done = env.step(action)# Q-Learning updategrid_action_values[state][action] += alpha * (reward + gamma * max(q[next_state]) - q[state][action])step_num += 1state = next_state
    

    在 Q-Learning 算法中,Q 值的更新可以用以下数学公式表示:
    Q ( s , a ) Q(s, a) Q(s,a) 表示在状态 s s s 下执行动作 a a a 的 Q 值。在时间步 t t t 时,智能体观察到状态 S t S_t St,执行动作 A t A_t At,然后到达新状态 S t + 1 S_{t+1} St+1 并获得奖励 R t + 1 R_{t+1} Rt+1。Q 值的更新公式为:
    Q ( S t , A t ) ← Q ( S t , A t ) + α [ R t + 1 + γ max ⁡ a ′ Q ( S t + 1 , a ′ ) − Q ( S t , A t ) ] Q(S_t, A_t) \leftarrow Q(S_t, A_t) + \alpha [R_{t+1} + \gamma \max_{a'} Q(S_{t+1}, a') - Q(S_t, A_t)] Q(St,At)Q(St,At)+α[Rt+1+γmaxaQ(St+1,a)Q(St,At)]
    其中:

    • α \alpha α 是学习率,取值在 0 到 1 之间,决定了新信息对旧信息的覆盖程度。
    • γ \gamma γ 是折扣因子,取值在 0 到 1 之间,用于平衡即时奖励和未来奖励。
    • max ⁡ a ′ Q ( S t + 1 , a ′ ) \max_{a'} Q(S_{t+1}, a') maxaQ(St+1,a) 表示在状态 S t + 1 S_{t+1} St+1 下所有可能动作的 Q 值中的最大值。
    • R t + 1 R_{t+1} Rt+1 是在时间步 t + 1 t+1 t+1 收到的奖励。
      这个公式表示,Q 值的更新等于当前 Q 值加上一个学习率 α \alpha α 乘以奖励 R t + 1 R_{t+1} Rt+1 和折扣后的未来最大 Q 值 γ max ⁡ a ′ Q ( S t + 1 , a ′ ) \gamma \max_{a'} Q(S_{t+1}, a') γmaxaQ(St+1,a) 与当前 Q 值 Q ( S t , A t ) Q(S_t, A_t) Q(St,At) 之差。这个差值称为 TD 误差(Temporal-Difference error),它衡量了基于当前估计的 Q 值和基于实际经验的新估计之间的差异。
  6. 最后一步,对状态-动作价值函数进行可视化

    visualize_grid_action_values(grid_action_values)
    
  7. 实现智能体要使用的 ϵ \epsilon ϵ-greedy策略

    def greedy_policy(q_values, epsilon):"""Epsilon-greedy policy """if random.random() >= epsilon:return np.argmax(q_values)else:return random.randint(0, 3)
    
  8. 实现__main__函数,并运行Q学习算法

    if __name__ == "__main__":max_episodes = 4000env = GridworldV2Env(step_cost=-0.1, max_ep_length=30)q_learning(env, max_episodes)
    

在这里插入图片描述

工作原理

Q学习算法中涉及Q值的更新,总结为: Q [ s , a ] = Q [ s , a ] + λ ∗ ( r + γ ∗ m a x a ′ ( Q [ s ′ , a ′ ] ) − Q [ s , a ] ) Q[s,a]=Q[s,a]+\lambda*(r+\gamma*max_{a^{\prime}}(Q[s^{\prime},a^{\prime}])-Q[s,a]) Q[s,a]=Q[s,a]+λ(r+γmaxa(Q[s,a])Q[s,a])

Q [ s , a ] Q[s,a] Q[s,a] 是当前状态s和动作q的Q函数值

m a x a ′ ( Q [ s ′ , a ′ ] ) max_{a^{\prime}}(Q[s^{\prime},a^{\prime}]) maxa(Q[s,a]) 用于从下一步可能的Q值中选择最大值

两者的主要区别

  • 策略依赖性:SARSA 使用当前策略来选择下一个动作,而 Q 学习不依赖当前策略来更新 Q 值。
  • 探索与利用:SARSA 的探索和利用是同步进行的,而 Q 学习在更新时完全依赖于最大 Q 值,可能会更倾向于探索。
  • 稳定性:SARSA 更稳定,因为它直接依赖于当前策略。Q 学习可能会因为其贪婪性质而在某些情况下导致不稳定的学习过程。

SARSA算法比Q学习算法具有更好的收敛性,因此它更适合在线学习或再真实系统上学习。

Q学习更适合于模拟环境或真实系统上资源(如时间/金钱)不太昂贵的情况下训练。

SARSA 算法的收敛性:

  • 同策略更新:SARSA 使用当前策略来选择下一个动作,这意味着它的更新是基于当前策略的动作后果。因此,它的学习过程与实际策略紧密相关,导致学习过程更加稳定。
  • 逐步学习:SARSA 在每个时间步都进行学习,而不是只依赖于最终的奖励。这种逐步的学习方式有助于避免由于过分依赖未来奖励估计而产生的潜在不稳定性和偏差。
  • 避免过估计:由于 SARSA 在更新 Q 值时考虑了下一个动作的 Q 值,而不是最大 Q 值,它不太可能产生过估计(overestimation)问题,这在 Q 学习中是一个常见问题。

SARSA 适合在线学习和真实系统:

  • 在线学习:在线学习要求算法能够从实时数据中快速且稳定地学习。SARSA 的稳定收敛性使其更适合于这种场景,因为它能够确保策略的持续改进而不会出现剧烈波动。
  • 真实系统:在真实系统中,错误的决策可能带来严重的后果。SARSA 的稳定性有助于减少这种风险,因为它不太可能因为过度探索而导致灾难性的决策。

Q 学习算法的适用性:

  • 探索性:Q 学习算法通过在每个时间步选择最大化未来奖励的动作来进行学习,这可能导致算法进行更多的探索。这种探索性在资源充足的情况下是有益的,因为它有助于快速发现最优策略。
  • 模拟环境:在模拟环境中,错误的决策不会带来实际损失,因此 Q 学习的探索性可以被充分利用,以快速找到最优解。
  • 资源成本:Q 学习可能需要更多的迭代和探索来达到收敛,这在时间和计算资源上可能比较昂贵。在资源受限的情况下,Q 学习可能不是最佳选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3248215.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

linux|多线程(一)

主要介绍了为什么要有线程 和线程的调用 和简单的对线程进行封装。 背景知识 a.重谈地址空间 我们知道物理内存的最小单元大小是4kB 物理内存是4G那么这样的单元友1M个 操作系统先描述再组织struct page[1M] 对于32位数据字长的机器,页表有2^32条也就是4G条&#…

随笔一、泰山派RK3566开发板调试串口波特率修改

摘要:立创泰山派RK3566开发板默认调试串口波特率是1500000bps,一般串口助手工具没有此波特率,为适应各种调试环境需要,打算修改调试串口波特率为115200bps 需要修改三个部分 1. uboot引导部分 修改tspi_linux_sdk/u-boot/config…

python数据可视化(10)——绘制地图图表

课程学习来源:b站up:【蚂蚁学python】 【课程链接:【【数据可视化】Python数据图表可视化入门到实战】】 【课程资料链接:【链接】】 python:3.12.3 所有库都使用最新版。 Python绘制中国地图和城市图表 from pyech…

CSS技巧专栏:一日一例 7 - 纯CSS实现炫光边框按钮特效

CSS技巧专栏:一日一例 7 - 纯CSS实现炫光边框按钮特效 本例效果图 案例分析 相信你可能已经在网络见过类似这样的流光的按钮,在羡慕别人做的按钮这么酷的时候,你有没有扒一下它的源代码的冲动?或者你当时有点冲动,却…

[第一期]带日期时间的LED滚动广告屏美化

效果图&#xff1a; 源代码&#xff1a; <style type"text/css">.studytextgzbox {background: #F9F9F9; border: 1px solid #999999;margin: 1px;text-align:center; float: left;line-height: 28px;height: 28px;overflow: hidden;width: 236px; }.hulik…

最新电子书|使用Anybus网关,轻松实现工业设备互联

无论何时&#xff0c;确保多网络连接 工业网关的关键角色 工业网关&#xff0c;又称为协议网关、协议转换器或协议翻译器&#xff0c;是实现工业设备互联的最简捷方法。作为信息的翻译器&#xff0c;它们使得不同工业协议的设备、机器、系统或网络能够无缝交换数据&#xff0c…

数据架构新篇章:存算一体与存算分离的协同演进

数据架构新篇章&#xff1a;存算一体与存算分离的协同演进 前言被误解的存算分离存算一体的概念存算一体的过往存算一体的演进 存算分离的定义存算分离的过往存算分离的演进 存算一体和分离示例总结 前言 降本增效大环境下&#xff0c;存算分离架构如火如荼&#xff0c;Why&am…

【STC89C51单片机】定时器中断系统

中断概念 中断是一种重要的硬件机制&#xff0c;用于在处理器正在执行程序时&#xff0c;能够及时响应某些外部或内部事件。中断可以临时中止当前正在执行的指令序列&#xff0c;转而去执行专门的中断服务程序&#xff08;ISR&#xff0c;Interrupt Service Routine&#xff0…

Stable Diffusion:解锁AI绘画新纪元的保姆级入门指南

在这个数字艺术日新月异的时代&#xff0c;Stable Diffusion如同一股清新的风&#xff0c;吹散了传统绘画的界限&#xff0c;让每个人都能成为创意无限的数字艺术家。作为一款基于Transformer结构的文本到图像生成模型&#xff0c;Stable Diffusion以其惊人的生成速度、细腻的画…

ubuntu22.04 配置grpc(优化官方教程)

优化了官方教程&#xff0c;2024.7.17顺利打通。 一&#xff1a;添加环境变量 打开root文件夹下的 .bashrc 文件 编辑文件&#xff1a;滚动到文件的底部&#xff0c;然后添加以下行&#xff1a; export MY_INSTALL_DIR$HOME/.local mkdir -p "$MY_INSTALL_DIR" exp…

AMEYA360:思瑞浦推出汽车级理想二极管ORing控制器TPS65R01Q

聚焦高性能模拟芯片和嵌入式处理器的半导体供应商思瑞浦3PEAK(股票代码&#xff1a;688536)发布汽车级理想二极管ORing控制器TPS65R01Q。 TPS65R01Q拥有20mV正向调节功能&#xff0c;降低系统损耗。快速反向关断(Typ&#xff1a;0.39μs)&#xff0c;在电池反向和各种汽车电气瞬…

注册安全分析报告:东方航空

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

base SAS programming学习笔记13(Array)

1.Array array-name{dimension} <elements> array-name&#xff1a;向量名称 dimension&#xff1a;向量长度&#xff0c;默认为1&#xff1b; elements:列出变量名&#xff0c;变量名要么全是数值变量或者全是字符变量 array-name和variable不能相同&#xff1b;也不能和…

人工智能实训室的核心功能有哪些?

随着人工智能技术的飞速发展&#xff0c;其在各行各业的应用日益广泛&#xff0c;对高素质、高技能的人工智能人才需求也随之增加。唯众紧跟市场趋势&#xff0c;致力于建设高标准、高质量的人工智能实训室&#xff0c;以满足职业院校及企业对人工智能技术应用型人才的培养需求…

HarmonyOS NEXT学习——@BuilderParam装饰器

初步理解&#xff0c;相当于VUE的插槽slot Builder function overBuilder() {}Component struct Child {label: string ChildBuilder customBuilder() {}Builder customChangeThisBuilder() {}BuilderParam customBuilderParam: () > void this.customBuilder; // 使用自定…

数据结构(双向链表)

链表的分类 链表的结构⾮常多样&#xff0c;以下情况组合起来就有8种&#xff08;2 x 2 x 2&#xff09;链表结构&#xff1a; 虽然有这么多的链表的结构&#xff0c;但是我们实际中最常⽤还是两种结构&#xff1a;单链表和双向带头循环链表 1.⽆头单向⾮循环链表&#xff1a…

图论(一):速概览无向图有向图图的可视化路径问题

一、图论速概览 研究图的性质和图之间的关系节点和边组成&#xff0c;节点表示对象&#xff0c;边表示对象之间的关系无向图&#xff1a;边没有方向&#xff0c;节点之间的连接是双向的。常用于描述简单的关系&#xff0c;如社交网络中的朋友关系。根据边有无权重分为无权重无…

工业控制:CANOpen(控制器局域网络)协议快速学习

文章目录 背景协议介绍CAN总线协议CANOpen协议介绍CANOpen诞生背景CANOpen的对象字典 CANOpen的服务数据对象&#xff08;SDO&#xff09; 参考附录问题CAN总线竞争原理在CAN协议中&#xff0c;帧中的ID是发送者的ID还是接收者的ID&#xff1f; 背景 目前很多CANOpen介绍的文章…

【操作系统】文件管理——文件存储空间管理(个人笔记)

学习日期&#xff1a;2024.7.17 内容摘要&#xff1a;文件存储空间管理、文件的基本操作 在上一章中&#xff0c;我们学习了文件物理结构的管理&#xff0c;重点学习了操作系统是如何实现逻辑结构到物理结构的映射&#xff0c;这显然是针对已经存储了文件的磁盘块的&#xff0…

简单实用的企业舆情安全解决方案

前言&#xff1a;企业舆情安全重要吗&#xff1f;其实很重要&#xff0c;尤其面对负面新闻&#xff0c;主动处理和应对&#xff0c;可以掌握主动权&#xff0c;避免股价下跌等&#xff0c;那么如何做使用简单实用的企业舆情解决方案呢&#xff1f; 背景 好了&#xff0c;提取词…