《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(terminal?state,?)=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?+γmaxa?Q(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') maxa?Q(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') γmaxa?Q(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://www.pswp.cn/web/46302.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/46302.shtml
英文地址,請注明出處:http://en.pswp.cn/web/46302.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HDC使用常見命令

HDC(HarmonyOS Device Connector)是為開發人員提供的用于調試的命令行工具,通過該工具可以在windows/linux/mac系統上與真實設備進行交互。 使用HDC前,需要配置相關環境變量: 在此電腦 > 屬性 > 高級系統設置 &g…

Git常用命令以及使用IDEA集成Gitee

目錄 一、設置用戶簽名 二、初始化本地庫 三、查看本地庫狀態 四、添加文件到暫存區 五、提交本地庫 六、修改文件 七、版本穿梭 八、Git分支 九、分支的操作 9.1、查看分支 9.2、創建分支 9.3、切換分支 9.4、合并分支 十、團隊協作 十一、Idea集成Git 11.1、配…

Github 2024-07-15 開源項目周報 Top15

根據Github Trendings的統計,本周(2024-07-15統計)共有15個項目上榜。根據開發語言中項目的數量,匯總情況如下: 開發語言項目數量Python項目5非開發語言項目4JavaScript項目3TypeScript項目2Go項目1Solidity項目1Java項目1Rust項目1免費編程學習平臺:freeCodeCamp.org 創建…

3.1-RNN存在的問題以及LSTM的結構

文章目錄 1 RNN存在的問題1.1梯度消失問題1.2梯度爆炸問題1.3梯度爆炸的對策 2梯度消失的對策——LSTM2.1輸出門2.2遺忘門2.3輸入門2.4總結2.5 LSTM梯度的流動 1 RNN存在的問題 RNN存在梯度消失和梯度爆炸的問題。 書上以下圖的這句話為例,進行說明;為了…

前瞻斷言與后瞻斷言:JavaScript 正則表達式的秘密武器

JavaScript 中的前瞻斷言(lookahead)和后瞻斷言(lookbehind)相信用過的小伙伴就知道它的威力了,在一些特定的需求場景下,可以做到四兩撥千斤的作用,今天讓我們來盤點一下在 JavaScript 正則表達…

昇思25天學習打卡營第14天|munger85

基于MindNLPMusicGen生成自己的個性化音樂 這個所謂的個性化的音樂就是指你輸入一段文字它會根據這個文字輸出一段音樂這個音樂是貼近于那段文字的所以叫做文生成音樂, 如果網絡正常的話就可以直接從下載這個模型。 那么音樂生成的有兩種方式呢有兩種方式&#xff…

【C++初階】C/C++內存管理

【C初階】C/C內存管理 🥕個人主頁:開敲🍉 🔥所屬專欄:C🥭 🌼文章目錄🌼 1. C/C內存分布 2. C語言中動態內存管理方式:malloc/calloc/realloc/free 3. C內存管理方式 3…

DP學習——組合模式

學而時習之,溫故而知新。 組合模式 和代理模式相比 和代理模式相比,有點類似。引用類和被引用類都繼承于同一個接口類。 但是感覺組合模式是對代理模式的更加豐富化(升級版、超進化),集合化或者說聚合化。 組合模…

拉格朗日乘子法和KKT條件

拉格朗日乘子法(Lagrange Multiplier) 和 KKT(Karush-Kuhn-Tucker) 條件是求解約束優化問題的重要方法,在有等式約束時使用拉格朗日乘子法,在有不等約束時使用 KKT 條件。當然,這兩個方法求得的結果只是必要條件,只有當目標函數…

ssrf復習(及ctfshow351-360)

1. SSRF 概述 服務器會根據用戶提交的URL發送一個HTTP請求。使用用戶指定的URL,Web應用可以獲取圖片或者文件資源等。典型的例子是百度識圖功能。 如果沒有對用戶提交URL和遠端服務器所返回的信息做合適的驗證或過濾,就有可能存在“請求偽造"的缺陷…

C#中錯誤與異常處理

1、錯誤和異常 如果程序運行期間發生錯誤,異常就會發生。異常會中止當前的程序流,如果不采取措施,程序將停止運行。 錯誤和異常是兩個不同的概念,但它們都與程序的穩定性和可維護性有關。 1.1、錯誤 錯誤通常是指編譯時的語法錯誤…

FPGA學習筆記(一) FPGA最小系統

文章目錄 前言一、FPGA最小系統總結 前言 今天學習下FPGA的最小系統一、FPGA最小系統 FPGA最小系統與STM32最小系統類似,由供電電源,時鐘電路晶振,復位和調試接口JTAG以及FLASH配置芯片組成,其與STM32最大的不同之處就是必須要有…

關于Hyperf高并發性能的一些配置詳解和硬件推薦

目錄 工作進程的管理 自定義配置示例(EasySwoole): 自動生成: 結論: 集群部署與協程數的關系: 設置 max_coroutine 的考慮因素: 集群部署時的配置: 示例配置: C…

鏈表面試練習習題集(Java)

1. 思路&#xff1a; 因為楊輝三角是由二維數組構成&#xff0c;所以要先創建一個二維數組&#xff0c;如何用順序表表示二維數組&#xff0c;可以通過List<List<Interger>>來表示一個二維數組&#xff0c;可以這樣理解&#xff1a;先創建一個一維數組List&#x…

modbus slave 設備通過 網關thingsboard-gateway 將數據上傳到thingsboard云平臺

搭建thingsboard物聯網云平臺花了大量時間&#xff0c;從小白到最后搭建成功&#xff0c;折磨了好幾天&#xff0c;也感謝網友的幫助&#xff0c;提供了思路最終成功搞定&#xff0c;特此記錄。 一、thingsboard環境搭建&#xff08;Ubuntu20.04LTS&#xff09; 參考官方文檔&a…

java之 junit單元測試案例【經典版】

一 junit單元測試 1.1 單元測試作用 單元測試要滿足AIR原則&#xff0c;即 A&#xff1a; automatic 自動化&#xff1b; I: Independent 獨立性&#xff1b; R&#xff1a;Repeatable 可重復&#xff1b; 2.單元測試必須使用assert來驗證 1.2 案例1 常規單元測試 1.…

PSINS工具箱函數介紹——r2d

介紹工具箱里面r2d這個小函數的作用。 程序源碼 function deg r2d(rad) % Convert angle unit from radian to degree % % Prototype: deg r2d(rad) % Input: rad - angle in radian(s) % Output: deg - angle in degree(s) % % See also r2dm, r2dms, d2r, dm2r, dms2r% …

設計模式使用場景實現示例及優缺點(行為型模式——觀察者模式)

阿爾法的身體內部有一個智能芯片&#xff0c;這個芯片能夠根據環境和需求自動改變它的行為模式。當阿爾法需要完成不同任務時&#xff0c;它的內部狀態會發生變化&#xff0c;進而改變它的行為&#xff0c;就像是它變成了另一個機器人一樣。 一天&#xff0c;智能城的市長接到一…

多種方式實現 元素高度絲滑的從0-1顯示出來

選擇合適的方式&#xff0c;給用戶更好的體驗&#xff0c;多種方式實現 元素高度絲滑的從0-1顯示出來。 能用 CSS 實現的動畫&#xff0c;就不要采用 JS 去實現。 1、瀏覽器可以對CSS動畫進行優化&#xff0c;其優化原理類似于requestAnimationFrame&#xff0c;會把每一幀的…

java基礎學習:序列化之 - Fast serialization

在Java中&#xff0c;序列化是將對象的狀態轉換為字節流的過程&#xff0c;以便保存到文件、數據庫或通過網絡傳輸。Java標準庫提供了java.io.Serializable接口和相應的機制來進行序列化和反序列化。然而&#xff0c;標準的Java序列化機制性能較低&#xff0c;并且生成的字節流…