強化學習課程:stanford_cs234 學習筆記(3)introduction to RL

文章目錄

  • 前言
  • 7 markov 實踐
    • 7.1 markov 過程再敘
    • 7.2 markov 獎勵過程 MRP(markov reward process)
    • 7.3 markov 價值函數與貝爾曼方程
    • 7.4 markov 決策過程MDP(markov decision process)的 狀態價值函數
      • 7.4.1 狀態價值函數
      • 7.4.2 狀態價值函數的 貝爾曼期望方程(Bellman Expectation Equation)
    • 7.5 markov 決策過程MDP(markov decision process)的 動作價值函數
      • 7.5.1 動作價值函數
      • 7.5.2 動作價值函數和狀態價值函數
      • 7.5.3 動作價值函數的貝爾曼期望等式
    • 7.6 動作價值和狀態價值例子
      • 7.6.1 邊緣化(marginalization),就


前言

第一節課的后半段其實就是一個馬爾可夫的實際案例教學,我這里在網上找到一個合適案例進行學習,cs234 的課程感覺有點空。
在這里插入圖片描述

7 markov 實踐

7.1 markov 過程再敘

markov 過程就是一個狀態轉移過程,且該當前狀態只和上一個狀態有關,和歷史無關。
即: P ( s t ∣ s t ? 1 ) = P ( s t ∣ s t ? 1 , s t ? 2 , s t ? 3 , . . . , s n ) P(s_t| s_{t-1}) = P(s_t | s_{t-1}, s_{t-2}, s_{t-3},...,s_n) P(st?st?1?)=P(st?st?1?,st?2?,st?3?,...,sn?)

markov 狀態轉移矩陣:
P = [ p s 1 ∣ s 1 p s 2 ∣ s 1 . . . p s n ∣ s 1 p s 2 ∣ s 1 p s 2 ∣ s 2 . . . p s n ∣ s 2 . . . p s 1 ∣ s n p s 2 ∣ s n . . . p s n ∣ s n ] P= \begin{equation} \begin{bmatrix} p_{s_1|s_1} & p_{s_2|s_1} &...& p_{s_n|s_1} \\ p_{s_2|s_1} & p_{s_2|s_2} &...& p_{s_n|s_2} \\ ... \\ p_{s_1|s_n} & p_{s_2|s_n} &...& p_{s_n|s_n} \end{bmatrix} \end{equation} P= ?ps1?s1??ps2?s1??...ps1?sn???ps2?s1??ps2?s2??ps2?sn???.........?psn?s1??psn?s2??psn?sn??? ???
矩陣中的 第i行第j列表示狀態 s i s_i si? s j s_j sj? 的概率 p ( s i ∣ s j ) = p ( s t + 1 = s j ∣ s t = s i ) p(s_i|s_j) = p(s_{t+1}=s_j | s_{t} = s_i) p(si?sj?)=p(st+1?=sj?st?=si?)。稱
P ( s ′ ∣ s ) P(s' | s) P(ss) 為轉移函數。這里要求 從某個狀態到其他所有狀態的概率和必須為1, 即P矩陣每行概率和為1

如果我們按照滿足markov 性,根據狀態轉移矩陣,得到一個狀態轉移序列
s1->s1->s2->s3->s4->s5->s6 那么就得到了一個markov chain 即馬爾可夫鏈。

7.2 markov 獎勵過程 MRP(markov reward process)

馬爾可夫獎勵過程是 [S, P r, γ \gamma γ]
S:狀態集合
P:狀態轉移矩陣
r : reward
γ \gamma γ:discount factor

為什么要獎勵(reward)?
(1)一個穩定的世界需要反饋,合理的反饋可以讓我們趨于一個穩定。
因此引入獎勵機制。我們將獎勵機制和markov 過程結合,那么有
(2)我們針對不同場景,有不同的回報,因此獎勵機制可以調整我們如何適應變化的環境。

為什么要折扣(discount factor)
(1)一個馬爾可夫過程是有可能出現閉環,如果無限循環下去,那么獎勵就有可能無限累加,要避免這種獎勵因子不斷累加,那么就需要折扣。在想想這句古話:一股做氣,再而衰,三而竭。這不就是折扣因子么。
(2)有時候我們需要近期的效果,那么我們會將長遠利益打一些折扣。相反,我們關注長遠利益時,需要近期利益打折扣

將reward 和 discount factor 結合得到回報(Return)
G t = R t + γ ? R t + 1 + γ 2 ? R t + 2 + . . . = ∑ k = 0 ∞ γ k R t + k G_t=R_{t} + \gamma*R_{t+1} + \gamma^2*R_{t+2} + ... = \sum_{k=0}^{\infty}\gamma^kR_{t+k} Gt?=Rt?+γ?Rt+1?+γ2?Rt+2?+...=k=0?γkRt+k?

7.3 markov 價值函數與貝爾曼方程

價值(value):一個狀態的期望回報,即從這個狀態出發的未來累積獎勵的期望值,被稱為這個狀態的價值:

V ( s ) = E [ R t + γ ? R t + 1 + γ 2 ? R t + 2 + . . . ∣ s = s t ] = E [ R t + γ ( R t + 1 + γ ? R t + 2 + . . . ∣ s = s t ) ] = E [ R t + γ G ( s = s t + 1 ∣ s = s t ) ] = E [ R t + γ G t + 1 ∣ s = s t ] = E [ R t ∣ s t ] + E γ G t + 1 ∣ s t = r ( s ) + γ V t + 1 ∣ s = s t = r ( s ) + γ ∑ p ( s t + 1 ∣ s t ) V t + 1 , 注:我第一遍推成 r ( s ) + γ ∑ p ( s t + 1 ∣ s t ) V t ,導致后面直接推不下去了 = r ( s ) + γ ∑ p ( s ′ ∣ s ) V ( s ′ ) , s ′ ∈ S = 貝爾曼方程( B e l l m a n E q u a t i o n ) V(s)\\ = E[R_{t} + \gamma*R_{t+1} + \gamma^2*R_{t+2} + ... | s=s_t]\\ = E[R_t + \gamma (R_{t+1} + \gamma*R_{t+2} + ...| s=s_t)]\\ = E[R_t + \gamma G(s=s_{t+1}|s=s_{t})]\\ = E[R_t + \gamma G_{t+1}|s=s_{t}]\\ = E[R_t|s_t] + E\gamma G_{t+1}| s_t\\ = r(s) + \gamma V_{t+1}|s=s_{t}\\ = r(s) + \gamma \sum{ p(s_{t+1}|s_t)V_{t+1}},\textcolor{#FF0000}{注:我第一遍推成r(s) + \gamma \sum{ p(s_{t+1}|s_t)V_t},導致后面直接推不下去了}\\ = r(s) + \gamma \sum{ p(s'|s)V(s')}, s' \in S \\ = 貝爾曼方程(Bellman Equation) V(s)=E[Rt?+γ?Rt+1?+γ2?Rt+2?+...∣s=st?]=E[Rt?+γ(Rt+1?+γ?Rt+2?+...∣s=st?)]=E[Rt?+γG(s=st+1?s=st?)]=E[Rt?+γGt+1?s=st?]=E[Rt?st?]+EγGt+1?st?=r(s)+γVt+1?s=st?=r(s)+γp(st+1?st?)Vt+1?注:我第一遍推成r(s)+γp(st+1?st?)Vt?,導致后面直接推不下去了=r(s)+γp(ss)V(s),sS=貝爾曼方程(BellmanEquation

于是我們不難得到:
當s’= s1的時候:
[ V ( s 1 ) ] = [ r ( s 1 ) ] + γ [ p s 1 ∣ s 1 p s 2 ∣ s 1 . . . p s n ∣ s 1 ] [ V ( s 1 ) V ( s 2 ) . . . V ( s n ) ] \begin{equation} \begin{bmatrix} V(s_1) \\ \end{bmatrix} = \begin{bmatrix} r(s_1) \\ \end{bmatrix} + \gamma \begin{bmatrix} p_{s_1|s_1} & p_{s_2|s_1} &...& p_{s_n|s_1} \\ \end{bmatrix} \begin{bmatrix} V(s1) \\ V(s2) \\ ... \\ V(sn)\\ \end{bmatrix} \end{equation} [V(s1?)?]=[r(s1?)?]+γ[ps1?s1???ps2?s1???...?psn?s1???] ?V(s1)V(s2)...V(sn)? ???
當s’=s2的時候:
[ V ( s 2 ) ] = [ r ( s 2 ) ] + γ [ p s 1 ∣ s 2 p s 2 ∣ s 2 . . . p s n ∣ s 2 ] [ V ( s 1 ) V ( s 2 ) . . . V ( s n ) ] \begin{equation} \begin{bmatrix} V(s_2) \\ \end{bmatrix} = \begin{bmatrix} r(s_2) \\ \end{bmatrix} + \gamma \begin{bmatrix} p_{s_1|s_2} & p_{s_2|s_2} &...& p_{s_n|s_2} \\ \end{bmatrix} \begin{bmatrix} V(s1) \\ V(s2) \\ ... \\ V(sn)\\ \end{bmatrix} \end{equation} [V(s2?)?]=[r(s2?)?]+γ[ps1?s2???ps2?s2???...?psn?s2???] ?V(s1)V(s2)...V(sn)? ???

接下來,我們寫成矩陣形式:

[ V ( s 1 ) V ( s 2 ) . . . V ( s n ) ] = [ r ( s 1 ) r ( s 2 ) . . . r ( s n ) ] + γ [ p s 1 ∣ s 1 p s 2 ∣ s 1 . . . p s n ∣ s 1 p s 2 ∣ s 1 p s 2 ∣ s 2 . . . p s n ∣ s 2 . . . p s 1 ∣ s n p s 2 ∣ s n . . . p s n ∣ s n ] [ V ( s 1 ) V ( s 2 ) . . . V ( s n ) ] \begin{equation} \begin{bmatrix} V(s1) \\ V(s2) \\ ... \\ V(sn)\\ \end{bmatrix} = \begin{bmatrix} r(s1) \\ r(s2) \\ ... \\ r(sn)\\ \end{bmatrix} + \gamma \begin{bmatrix} p_{s_1|s_1} & p_{s_2|s_1} &...& p_{s_n|s_1} \\ p_{s_2|s_1} & p_{s_2|s_2} &...& p_{s_n|s_2} \\ ... \\ p_{s_1|s_n} & p_{s_2|s_n} &...& p_{s_n|s_n} \end{bmatrix} \begin{bmatrix} V(s1) \\ V(s2) \\ ... \\ V(sn)\\ \end{bmatrix} \end{equation} ?V(s1)V(s2)...V(sn)? ?= ?r(s1)r(s2)...r(sn)? ?+γ ?ps1?s1??ps2?s1??...ps1?sn???ps2?s1??ps2?s2??ps2?sn???.........?psn?s1??psn?s2??psn?sn??? ? ?V(s1)V(s2)...V(sn)? ???

于是就得到:
V = R + γ P V V=R+\gamma P V V=R+γPV
V ? γ P V = R V - \gamma P V=R V?γPV=R
( I ? γ P ) V = R (I - \gamma P)V = R (I?γP)V=R
V = ( I ? γ P ) ? 1 R V=(I - \gamma P)^{-1}R V=(I?γP)?1R

按照以往計算經驗,這個矩陣解起來巨麻煩,所以會用 動態規劃(dynamic programming)、 **蒙特卡羅(模擬特-Carlo method)**方法 或 時序差分(temporal difference)

7.4 markov 決策過程MDP(markov decision process)的 狀態價值函數

7.4.1 狀態價值函數

智能體(agent)的策略(Policy)通常用 π \pi π表示。策略 π ( a ∣ s ) = P ( A t = a ∣ S t = s ) \pi(a|s) = P(A_t = a| S_t = s) π(as)=P(At?=aSt?=s)是一個函數,表示在s狀態下采取a動作的概率。當一個策略是確定性策略(deterministic policy)的時候,那么智能體在每個狀態只輸出一個確定動作
當智能體的策略是隨機測策略(stochastic policy)時,那么這個函數輸出的是關于動作的概率分布。

狀態價值函數:
我們用 V π ( s ) V^{\pi}(s) Vπ(s)表示在MDP基于測率 π \pi π策略得到的價值函數期望:
V π ( s ) = E π [ G t ∣ S t = s ] V^{\pi}(s) = E_\pi[G_t | S_t= s] Vπ(s)=Eπ?[Gt?St?=s]
我這里專門推敲了下: V π V^\pi Vπ和 V 是一回事,只是為了講名是什么策略,因此加了 π \pi π,即乘以一個概率。

7.4.2 狀態價值函數的 貝爾曼期望方程(Bellman Expectation Equation)

根據上面貝爾曼方程算 V ( s ) V(s) V(s)
V ( s ) = r ( s ) + γ ∑ p ( s ′ ∣ s ) V ( s ′ ) , s ′ ∈ S V(s) = r(s) + \gamma \sum{ p(s'|s)V(s')}, s' \in S V(s)=r(s)+γp(ss)V(s),sS
當我們要將在那個策略下時,不難得到:
V π ( s ) = E π [ G t ∣ S t = s ] = ∑ π ( a ∣ s ) [ r ( s ) + γ ∑ p ( s ′ ∣ s ) V ( s ′ ) ] , s ′ ∈ S V^{\pi}(s) = E_\pi[G_t | S_t= s]\\ =\sum \pi(a|s) [ r(s) + \gamma \sum{ p(s'|s)V(s') } ], s' \in S Vπ(s)=Eπ?[Gt?St?=s]=π(as)[r(s)+γp(ss)V(s)],sS——因為需要策略 π \pi π得概率,因此需要乘以 π \pi π

V π ( s ) = r ( s , a ) + γ ∑ s ′ ∈ S p ( s ′ ∣ s , a ) ∑ a ′ ∈ A π ( a ∣ s ′ ) Q π ( s ′ , a ′ ) V^\pi(s)=r(s, a) + \gamma \sum_{s' \in S} p(s'|s, a) \sum_{a' \in A}\pi(a|s') Q^{\pi} (s',a') Vπ(s)=r(s,a)+γsS?p(ss,a)aA?π(as)Qπ(sa)

7.5 markov 決策過程MDP(markov decision process)的 動作價值函數

markov 決策過程MDP(markov decision process)—— 動作價值函數

7.5.1 動作價值函數

不同于MRP,在MDP過程中,由于動作的存在,額外定義一個動作價值函數(action-value function)。用 Q π Q^\pi Qπ 表示,在s 狀態下,執行動作a的得到的期望:
Q π ( s , a ) = E π [ G t ∣ S t = s , A t = a ] Q^\pi(s, a) = E_\pi[G_t | S_t = s, A_{t}=a] Qπ(s,a)=Eπ?[Gt?St?=s,At?=a] 。說實話我這里被定義給搞暈了,因此我理解這里就是不需要乘以 π ( a ∣ s ) \pi(a|s) π(as)

7.5.2 動作價值函數和狀態價值函數

所以得到 V π V^{\pi} Vπ Q π Q^\pi Qπ的關系:

(1) V π ( s ) = ∑ a ∈ A π ( a ∣ s ) Q π ( s , a ) V^{\pi}(s) = \sum_{a \in A} \pi(a|s) Q^\pi(s, a) Vπ(s)=aA?π(as)Qπ(s,a)
這個式子描述的是:使用策略 π \pi π, 狀態 s的價值期望,等于動作價值函數乘以發生動作概率的乘積的總和。這里是動作未發生,需要乘上動作的概率和動作的價值

(2) Q π ( s , a ) = r ( s , a ) + γ ∑ P ( s ′ ∣ s , a ) V π ( s ′ ) Q^\pi(s, a) = r(s,a) + \gamma \sum P(s' | s, a) V^\pi(s') Qπ(s,a)=r(s,a)+γP(ss,a)Vπ(s)
使用策略 π \pi π時,狀態s下采取a動作后的價值期望 等于 當下的獎勵加上 經過 γ \gamma γ衰減之后的所有狀態狀態轉移概率與相應價值的乘積。
這里是動作已經確定,但是狀態不確定,因此乘的是狀態轉移矩陣和狀態

也就是說狀態與狀態之間不再是單純的轉移,還有動作的這個價值反饋加進去。

7.5.3 動作價值函數的貝爾曼期望等式

根據定義:
Q π ( s , a ) = r ( s , a ) + γ ∑ s ′ ∈ S P ( s ′ ∣ s , a ) V π ( s ′ ) Q^\pi(s, a) = r(s,a) + \gamma \sum_{s'\in S} P(s' | s, a) V^\pi(s') Qπ(s,a)=r(s,a)+γsS?P(ss,a)Vπ(s)

又因為:
V π ( s ) = ∑ a ∈ A π ( a ∣ s ) Q π ( s , a ) V^{\pi}(s) = \sum_{a \in A} \pi(a|s) Q^\pi(s, a) Vπ(s)=aA?π(as)Qπ(s,a)
那么:
V π ( s ′ ) = ∑ a ∈ A π ( a ∣ s ′ ) Q π ( s ′ , a ) V^{\pi}(s') = \sum_{a \in A} \pi(a|s') Q^\pi(s', a) Vπ(s)=aA?π(as)Qπ(s,a)
上面的式子可以再變個型,帶入后:
Q π ( s , a ) = r ( s , a ) + γ ∑ s ′ ∈ S P ( s ′ ∣ s , a ) V π ( s ′ ) = r ( s , a ) + γ ∑ s ′ ∈ S P ( s ′ ∣ s , a ) ∑ a ∈ A π ( a ∣ s ′ ) Q π ( s ′ , a ) Q^\pi(s, a)= r(s,a) + \gamma \sum_{s'\in S} P(s' | s, a) V^\pi(s')\\ =r(s,a) + \gamma \sum_{s'\in S} P(s' | s, a) \sum_{a \in A} \pi(a|s') Q^\pi(s', a) Qπ(s,a)=r(s,a)+γsS?P(ss,a)Vπ(s)=r(s,a)+γsS?P(ss,a)aA?π(as)Qπ(s,a)
——————————————————————
動作價值函數和狀態價值函數的貝爾曼方程很常見,所以我這里推敲了下。
——————————————————————

7.6 動作價值和狀態價值例子

在這里插入圖片描述
圖中的
(1)虛線表示動作到狀態
(2)圖中的實現表示從當前狀態開始當前動作
(3)紅色的數字是標記狀態獎勵
(4)沒有標記數字的線表示概率為1,如果標記了表示對應概率。

7.6.1 邊緣化(marginalization),就

這里有個一般的計算MDP的方法,就是將測率的動作邊緣化:
(1) 得到一個沒有動作的mrp。即對于某個狀態,我跟將根據動作策略進行加權,就得到r’(s)是該狀態下的獎勵:
s ′ = ∑ a ∈ A π ( a ∣ s ) r ( s , a ) s'=\sum_{a \in A} \pi(a|s)r(s,a) s=aA?π(as)r(s,a)

(2)同理,將計算采取動作的概率 π \pi π與 將s轉移到s’轉移矩陣進行相乘再累加,就得到一個MRP的從s轉移到s‘的轉移概率。

這樣的做法有如下好處:
簡化問題結構
MDP 涉及狀態和動作兩層結構,分析和求解復雜。而給定策略后,動作選擇就變成確定的概率分布,這時只剩下狀態和狀態之間的轉移(+獎勵)——正好就是 MRP 的結構。
MRP 更容易求解
MRP 沒有動作維度,可以直接用線性代數(比如矩陣解法或貝爾曼方程迭代)來求解狀態值函數 𝑉(𝑠)非常方便。

這個方法是*給定策略下的通用方法。 如果你要做最優策略求解(如值迭代、Q-learning),那就不能只轉成 MRP,因為你需要在每一步決策中“尋找最優動作”,那就是另一套框架了(比如 Bellman Optimality Equation)。

實踐代碼如下:

import numpy as npdef join(str1, str2):return str1 + '-' + str2# markov_chain is a list that save the index of state 
# for example:s1->s1->s2->s3->s4->s5->s6 
# start_index: the start index for markov_chain, not the state index.
def get_return(start_index, markov_chain, rewards, gamma):G_t = 0# >>>>>>> the code is very tricky but effective! <<<<<<<for idx in reversed(range(start_index, len(markov_chain))):# the state index is start at 1 end in 6, so when we use the idx we need to minus 1G_t = gamma * G_t + rewards[markov_chain[idx] - 1]return G_tdef get_value(p_matrix, rewards, gamma):states_amount = len(rewards)rewards = np.array(rewards)rewards = rewards.reshape((-1, 1))value = np.dot(np.linalg.inv(np.eye(states_amount, states_amount) - gamma * p_matrix), rewards)return valuedef mrp_test():np.random.seed(0)p = [[0.8, 0.1, 0.1, 0.0, 0.0, 0.0],[0.0, 0.2, 0.5, 0.3, 0.0, 0.0],[0.0, 0.0, 0.5, 0.5, 0.0, 0.0],[0.1, 0.1, 0.1, 0.1, 0.3, 0.3],[0.2, 0.5, 0.1, 0.0, 0.1, 0.1],[0.0, 0.0, 0.2, 0.3, 0.4, 0.1],]p = np.array(p)# fist to checkt if the sum of each row is 1.0H, W = p.shapefor h in range(H):sum_h = np.sum(p[h,:])# for float compoare we can not suppose it will be exactly 1.0 actually is 0.999999999....if sum_h < 0.9999999 or sum_h > 1.0: print("error in line:" + str(h) + " sum:" + str(sum_h))exit()#          s1, s2, s3, s4, s5, s6rewards = [-1, -2,  0,  1,  2,  4] gamma = 0.7markov_chain = [1, 1, 2, 3, 4, 5, 6, 1]# get the return for agentG_t = get_return(0, markov_chain, rewards, gamma)# get the value for agentV_t = get_value(p, rewards, gamma)print(">>> markov finish!")def mdp_test():states = ["s1", "s2", "s3", "s4", "s5", "s6"]actions = ["hold_s1", "arrival_s2","arrival_s3","arrival_s4", "arrival_s5", "arrival_s6", "stochastic_arrival"]p = {"s1-hold_s1-s1": 1.0,"s1-arrival_s2-s2": 1.0,"s2-arrival_s1-s1": 1.0,"s2-arrival_s3-s3": 1.0,"s3-arrival_s4-s4": 1.0,"s3-arrival_s6-s6": 1.0,"s4-arrival_s5-s5": 1.0,"s5-arrival_s6-s6": 1.0,"s4-stochastic_arrival_s2": 0.2,"s4-stochastic_arrival_s3": 0.3,"s4-stochastic_arrival_s4": 0.5,}rewards = {"s1-hold_s1":   -1,"s1-arrival_s2": 0,"s2-arrival_s1":-1,"s2-arrival_s3":-2,"s3-arrival_s4":-2,"s3-arrival_s6": 7,"s4-arrival_s5": 2,"s5-arrival_s6": 8,"s4-stochastic_arrival_s2": 1,"s4-stochastic_arrival_s3": 1,"s4-stochastic_arrival_s4": 1 }gamma = 0.5mdp = (states, actions, p, gamma)pi_1 = {"s1-hold_s1": 0.5,"s1-arrival_s2": 0.5,"s2-arrival_s1": 0.5,"s2-arrival_s3": 0.5,"s3-arrival_s4": 0.5,"s3-arrival_s5": 0.5,"s4-arrival_s5": 0.5,"s4-stochastic_arrival": 0.5,} pi_2 = {"s1-hold_s1": 0.6,"s1-arrival_s2": 0.4,"s2-arrival_s1": 0.3,"s2-arrival_s3": 0.7,"s3-arrival_s4": 0.5,"s3-arrival_s5": 0.5,"s4-arrival_s5": 0.1,"s4-stochastic_arrival": 0.9,} # 轉化后的MRP的狀態轉移矩陣p_mdp2mrp_pi_1 = [# s1, s2,  s3,  s4,  s5,  s6[1.0 * 0.5, 1.0 * 0.5, 0.0,       0.0,       0.0,       0.0      ],[1.0 * 0.5, 0.0,       1.0 * 0.5, 0.0,       0.0,       0.0      ],[0.0,       0.0,       0.0,       1.0 * 0.5, 0.0,       1.0 * 0.5],[0.0,       0.2 * 0.5, 0.3 * 0.5, 0.5,       1.0 * 0.5, 0.0      ],[0.0,       0.0,       0.0,       0.0,       0.0,       1.0 * 0.5],[0.0,       0.0,       0.0,       0.0,       0.0,       1.0      ],]p_mdp2mrp_pi_1 = np.array(p_mdp2mrp_pi_1)R_mdp2mrp_pi_1 = [-1 * 0.5, -1 * 0.5 + -2 * 0.5,7 * 0.5 + -2 * 0.5,2 * 0.5 +  1 * 0.5, 8 * 0.5,0]# get the  mrp base on mdpv = get_value(p_mdp2mrp_pi_1, R_mdp2mrp_pi_1, gamma)print("mdp v=" + str(v))print("mdp finish!")if __name__ == "__main__":#mrp_test()mdp_test()

運行結果:
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/74659.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/74659.shtml
英文地址,請注明出處:http://en.pswp.cn/web/74659.shtml

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

相關文章

操作系統 4.5-文件使用磁盤的實現

通過文件進行磁盤操作入口 // 在fs/read_write.c中 int sys_write(int fd, const char* buf, int count) {struct file *file current->filp[fd];struct m_inode *inode file->inode;if (S_ISREG(inode->i_mode))return file_write(inode, file, buf, count); } 進程…

libreoffice-help-common` 的版本(`24.8.5`)與官方源要求的版本(`24.2.7`)不一致

出現此錯誤的原因主要是軟件包依賴沖突&#xff0c;具體分析如下&#xff1a; ### 主要原因 1. **軟件源版本不匹配&#xff08;國內和官方服務器版本有差距&#xff09; 系統中可能啟用了第三方軟件源&#xff08;如 PPA 或 backports 源&#xff09;&#xff0c;導致 lib…

使用Geotools中的原始方法來操作PostGIS空間數據庫

目錄 前言 一、原生PostGIS連接介紹 1、連接參數說明 2、創建DataStore 二、工程實戰 1、Maven Pom.xml定義 2、空間數據庫表 3、讀取空間表的數據 三、總結 前言 在當今數字化與信息化飛速發展的時代&#xff0c;空間數據的處理與分析已成為眾多領域不可或缺的一環。從…

訊飛語音合成(流式版)語音專業版高質量的分析

一、引言 在現代的 Web 應用開發中&#xff0c;語音合成技術為用戶提供了更加便捷和人性化的交互體驗。訊飛語音合成&#xff08;流式版&#xff09;以其高效、穩定的性能&#xff0c;成為了眾多開發者的首選。本文將詳細介紹在 Home.vue 文件中實現訊飛語音合成&#xff08;流…

走進未來的交互世界:下一代HMI設計趨勢解析

在科技日新月異的今天&#xff0c;人機交互界面&#xff08;HMI&#xff09;設計正以前所未有的速度發展&#xff0c;不斷引領著未來的交互世界。從簡單的按鈕和圖標&#xff0c;到如今的智能助手和虛擬現實&#xff0c;HMI設計不僅改變了我們的生活方式&#xff0c;還深刻影響…

洛谷題單3-P1217 [USACO1.5] 回文質數 Prime Palindromes-python-流程圖重構

題目描述 因為 151 151 151 既是一個質數又是一個回文數&#xff08;從左到右和從右到左是看一樣的&#xff09;&#xff0c;所以 151 151 151 是回文質數。 寫一個程序來找出范圍 [ a , b ] ( 5 ≤ a < b ≤ 100 , 000 , 000 ) [a,b] (5 \le a < b \le 100,000,000…

學習筆記,DbContext context 對象是保存了所有用戶對象嗎

DbContext 并不會將所有用戶對象保存在內存中&#xff1a; DbContext 是 Entity Framework Core (EF Core) 的數據庫上下文&#xff0c;它是一個數據庫訪問的抽象層它實際上是與數據庫的一個連接會話&#xff0c;而不是數據的內存緩存當您通過 _context.Users 查詢數據時&…

本地命令行啟動服務并連接MySQL8

啟動服務命令 net start mysql8 關閉服務命令 net stop mysql8 本地連接MySQL數據庫mysql -u [用戶名] -p[密碼] 這里&#xff0c;我遇到了個問題 —— 啟動、關閉服務時&#xff0c;顯示 “發生系統錯誤 5。拒絕訪問。 ” 解法1&#xff1a;在 Windows 上以管理員身份打開…

數據蒸餾:Dataset Distillation by Matching Training Trajectories 論文翻譯和理解

一、TL&#xff1b;DR 數據集蒸餾的任務是合成一個較小的數據集&#xff0c;使得在該合成數據集上訓練的模型能夠達到在完整數據集上訓練的模型相同的測試準確率&#xff0c;號稱優于coreset的選擇方法本文中&#xff0c;對于給定的網絡&#xff0c;我們在蒸餾數據上對其進行幾…

【spring cloud Netflix】Ribbon組件

1.基本概念 SpringCloud Ribbon是基于Netflix Ribbon 實現的一套客戶端負載均衡的工具。簡單的說&#xff0c;Ribbon 是 Netflix 發布的開源項目&#xff0c;主要功能是提供客戶端的軟件負載均衡算法&#xff0c;將 Netflix 的中間層服務連接在一 起。Ribbon 的客戶端組件提供…

P1036 [NOIP 2002 普及組] 選數(DFS)

題目描述 已知 n 個整數 x1?,x2?,?,xn?&#xff0c;以及 1 個整數 k&#xff08;k<n&#xff09;。從 n 個整數中任選 k 個整數相加&#xff0c;可分別得到一系列的和。例如當 n4&#xff0c;k3&#xff0c;4 個整數分別為 3,7,12,19 時&#xff0c;可得全部的組合與它…

在響應式網頁的開發中使用固定布局、流式布局、彈性布局哪種更好

一、首先看下固定布局與流體布局的區別 &#xff08;一&#xff09;固定布局 固定布局的網頁有一個固定寬度的容器&#xff0c;內部組件寬度可以是固定像素值或百分比。其容器元素不會移動&#xff0c;無論訪客屏幕分辨率如何&#xff0c;看到的網頁寬度都相同。現代網頁設計…

二分查找與二叉樹中序遍歷——面試算法

目錄 二分查找與分治 循環方式 遞歸方式 元素中有重復的二分查找 基于二分查找的拓展問題 山脈數組的頂峰索引——局部有序 旋轉數字中的最小數字 找缺失數字 優化平方根 中序與搜索樹 二叉搜索樹中搜索特定值 驗證二叉搜索樹 有序數組轉化為二叉搜索樹 尋找兩個…

字符串——面試考察高頻算法題

目錄 轉換成小寫字母 字符串轉化為整數 反轉相關的問題 反轉字符串 k個一組反轉 僅僅反轉字母 反轉字符串里的單詞 驗證回文串 判斷是否互為字符重排 最長公共前綴 字符串壓縮問題 轉換成小寫字母 給你一個字符串 s &#xff0c;將該字符串中的大寫字母轉換成相同的…

現代復古電影海報品牌徽標設計襯線英文字體安裝包 Thick – Retro Vintage Cinematic Font

Thick 是一種大膽的復古字體&#xff0c;專為有影響力的標題和懷舊的視覺效果而設計。其厚實的字體、復古魅力和電影風格使其成為電影海報、產品標簽、活動品牌和編輯設計的理想選擇。無論您是在引導電影的黃金時代&#xff0c;還是在現代布局中注入復古活力&#xff0c;Thick …

[C++面試] new、delete相關面試點

一、入門 1、說說new與malloc的基本用途 int* p1 (int*)malloc(sizeof(int)); // C風格 int* p2 new int(10); // C風格&#xff0c;初始化為10 new 是 C 中的運算符&#xff0c;用于在堆上動態分配內存并調用對象的構造函數&#xff0c;會自動計算所需內存…

Unity URP管線與HDRP管線對比

1. 渲染架構與底層技術 URP 渲染路徑&#xff1a; 前向渲染&#xff08;Forward&#xff09;&#xff1a;默認單Pass前向&#xff0c;支持少量實時光源&#xff08;通常4-8個逐物體&#xff09;。 延遲渲染&#xff08;Deferred&#xff09;&#xff1a;可選但功能簡化&#…

JDK8卸載與安裝教程(超詳細)

JDK8卸載與安裝教程&#xff08;超詳細&#xff09; 最近學習一個項目&#xff0c;需要使用更高級的JDK&#xff0c;這里記錄一下卸載舊版本與安裝新版本JDK的過程。 JDK8卸載 以windows10操作系統為例&#xff0c;使用快捷鍵winR輸入cmd&#xff0c;打開控制臺窗口&#xf…

python爬蟲:DrissionPage實戰教程

如果本文章看不懂可以看看上一篇文章&#xff0c;加強自己的基礎&#xff1a;爬蟲自動化工具&#xff1a;DrissionPage-CSDN博客 案例解析&#xff1a; 前提&#xff1a;我們以ChromiumPage為主&#xff0c;寫代碼工具使用Pycharm&#xff08;python環境3.9-3.10&#xff09; …

07-01-自考數據結構(20331)- 排序-內部排序知識點

內部排序算法是數據結構核心內容,主要包括插入類(直接插入、希爾)、交換類(冒泡、快速)、選擇類(簡單選擇、堆)、歸并和基數五大類排序方法。 知識拓撲 知識點介紹 直接插入排序 定義:將每個待排序元素插入到已排序序列的適當位置 算法步驟: 從第二個元素開始遍歷…