强化学习基础三大优化方法:(一)动态规划

2023-11-19


一、简介

强化学习是一类解决马尔可夫决策过程的方法,其中,动态规划、蒙特卡洛以及时序差分是强化学习算法的三大基础算法。本文就其实际效果来对比三种方法以及其子方法的不同与优缺点。本文就动态规划方法进行简单介绍。

二、动态规划(DP,Dynamic Planning)方法

动态规划是一类优化方法,在给定一个马尔可夫决策过程(MDP)描述的完备环境模型的情况下,其可以计算最优的策略。其中心思想是通过将一个系列性的复杂问题进行分解来简化问题的求解。对于强化学习问题,传统的DP算法,作用比较有限:一是完备的环境模型只是一种假设;二是它的计算复杂度极高。但是,它仍然是一个非常重要的理论。对于之后的方法而言,DP提供了一个必要的基础。

(一)策略评估

策略评估即对于任意一个策略 π \pi π,计算其状态价值函数 v π v_{\pi} vπ.在这里直接给出迭代策略评估算法,用于估计 V ≈ v π V≈v_{\pi} Vvπ

  1. 输入待评估的策略 π \pi π
  2. 算法参数:小阈值 θ \theta θ>0,用于确定估计量的精度
  3. 对于任意状态 s ∈ S + s\in S^{+} sS+,任意初始化 V ( s ) V(s) V(s),其中 V ( 终止状态 ) = 0 V(终止状态)=0 V(终止状态)=0
  4. 循环:
    Δ ← 0 \Delta \leftarrow 0 Δ0
    对每一个 s ∈ S + s\in S^{+} sS+循环:
    v ← V ( s ) v \leftarrow V(s) vV(s)
    V ( s ) ← ∑ a π ( a ∣ s ) ∑ s ′ , a p ( s ′ , r ∣ s , a ) [ r + γ V ( s ′ ) ] V(s) \leftarrow \sum_{a}{\pi(a|s)\sum_{s^{'},a}{p(s^{'},r|s,a)[r+\gamma V(s^{'})]}} V(s)aπ(as)s,ap(s,rs,a)[r+γV(s)]
    Δ ← m a x ( Δ , ∣ v − V ( s ) ∣ ) \Delta \leftarrow max(\Delta,|v-V(s)|) Δmax(Δ,vV(s))
    till Δ < 0 \Delta<0 Δ<0

我们从上述算法中也可以看到,所谓完备环境的含义即是,对于任意的 ( s , a ) (s,a) (s,a)二元组都能够得到确定的 p ( s ′ , r ∣ s , a ) p(s^{'},r|s,a) p(s,rs,a)以及对于任意状态 s s s,我们都可以得到 p ( s ∣ a ) p(s|a) p(sa)。因此,如果没有这种比较完备的环境,就不适合使用动态规划方法。

(二)策略迭代

1.策略改进

对于一个策略 π \pi π,如果我们想要改进它,那么一个直观的方法是针对于某一个状态 s s s,我们可以采用一个动作 a ≠ π ( s ) a \neq \pi(s) a=π(s),而当处于其他状态时,依旧按照策略 π \pi π来采取动作。如果采取新动作 a a a之后的动作价值 q ( s , a ) ≥ v π ( s ) q(s,a) \ge v_{\pi}(s) q(s,a)vπ(s),那么我们就可以认定采取新动作的策略 π ′ \pi ^{'} π比之前的策略 π \pi π更好。所以我们在策略改进的过程中的目标就是采用一个不同于原策略 π \pi π的新动作 a a a,从而使得a的动作价值大于原策略价值。
π ′ ( s ) = a r g m a x a ∑ p ( s ′ , r ∣ s , a ) [ r + γ v π ( s ′ ) ] \pi^{'}(s)=argmax_{a}\sum{p(s^{'},r|s,a)[r+\gamma v_{\pi}(s^{'})]} π(s)=argmaxap(s,rs,a)[r+γvπ(s)]

2.策略迭代

一旦一个策略 π \pi π根据 v π v_{\pi} vπ产生了一个更好的策略 π ′ \pi^{'} π,我们就可以通过计算 v π ′ v_{\pi^{'}} vπ来得到一个更好的策略 π ′ ′ \pi^{''} π′′。通过这样的一个链式的方法就可以得到一个不断改进的策略和价值函数的序列:
π 0 → v π 0 → π 1 → v π 1 → . . . → π ∗ → v π ∗ \pi_{0} \rightarrow v_{\pi_{0}} \rightarrow \pi_{1} \rightarrow v_{\pi_{1}} \rightarrow ... \rightarrow \pi* \rightarrow v_{\pi*} π0vπ0π1vπ1...πvπ

3.迭代算法

  1. 初始化
    对于 s ∈ S s \in S sS,任意设定 V ( s ) ∈ R V(s) \in R V(s)R以及 π ( s ) ∈ A ( s ) \pi(s) \in A(s) π(s)A(s)
  2. 策略评估
    输入待评估的策略 π \pi π
    算法参数:小阈值 θ \theta θ>0,用于确定估计量的精度
    对于任意状态 s ∈ S + s\in S^{+} sS+,任意初始化 V ( s ) V(s) V(s),其中 V ( 终止状态 ) = 0 V(终止状态)=0 V(终止状态)=0
    循环:
    Δ ← 0 \Delta \leftarrow 0 Δ0
    对每一个 s ∈ S + s\in S^{+} sS+循环:
    v ← V ( s ) v \leftarrow V(s) vV(s)
    V ( s ) ← ∑ a π ( a ∣ s ) ∑ s ′ , a p ( s ′ , r ∣ s , a ) [ r + γ V ( s ′ ) ] V(s) \leftarrow \sum_{a}{\pi(a|s)\sum_{s^{'},a}{p(s^{'},r|s,a)[r+\gamma V(s^{'})]}} V(s)aπ(as)s,ap(s,rs,a)[r+γV(s)]
    Δ ← m a x ( Δ , ∣ v − V ( s ) ∣ ) \Delta \leftarrow max(\Delta,|v-V(s)|) Δmax(Δ,vV(s))
    till Δ < 0 \Delta<0 Δ<0
  3. 策略改进
    p o l i c y − s t a b l e ← t r u e policy-stable \leftarrow true policystabletrue
    对于每一个 s ∈ S s \in S sS
    o l d − a c t i o n old-action oldaction ← π ( s ) \leftarrow \pi(s) π(s)
    π ( s ) ← a r g m a x a ∑ s ′ , r p ( s ′ , r ∣ s , a ) [ r + γ V ( s ′ ) ] \pi(s) \leftarrow argmax_{a}\sum_{s',r}{p(s',r|s,a)[r+\gamma V(s')]} π(s)argmaxas,rp(s,rs,a)[r+γV(s)]
    如果 o l d − a c t i o n ≠ π ( s ) old-action \neq \pi(s) oldaction=π(s),那么 p o l i c y − s t a b l e ← f a l s e policy-stable \leftarrow false policystablefalse
    如果 p o l i c y − s t a b l e policy-stable policystable t r u e true true,那么停止并返回 V ≈ v ∗ V≈v* Vv以及 π ≈ π ∗ \pi ≈ \pi* ππ

三、编程实践

本文的小实验基于这里完成。自定义的环境基本上是把Gym官网的例子简单改了一下。大致描述就是:
在一个5*5的方格中,有一个蓝色的小球,其初始化位置在方格正中央,也就是[2,2]的位置上。在方格的四个角[0,0],[4,0],[0,4],[4,4]分别有4块奖励区域,分别对应着-1,-2,2,1。本案例使用动态规划方法(近乎于蒙特卡洛方法)找到使小球能够以最短路径找到奖励最大的路径,我找到了一个其他大佬用冰湖(FrozenLake)环境写的一个动态规划,由于其创作时间为2020年,故将其代码进行稍事修改,放在文章末端。其图示如下:
在这里插入图片描述

(一)环境介绍

环境大致如上所述,需要补充的是小球每次只能上下左右移动一个方格,当小球的运动超出方格时,这里作取模运算,即如果小球走到如图所示的最右边[1,4],那么如果小球继续向右的话,它就会移动到同行最左侧的[1,0],其他方向同理。四角不同颜色的红色代表不同奖励值的区域。环境编辑代码如下:
(本文以个人学习记录为主,需要学习交流的大佬请在评论区留言~)


import gym
from gym import spaces
import pygame
import numpy as np

class GridWorldEnv(gym.Env):
    metadata = {"render_modes":["human","rgb_array"],"render_fps":4}

    def __init__(self,render_mode=None,size=5):
        self.size=size    #The size of the square grid
        self.window_size=512    #The size of the PyGame window

        #Obervations are dictionaries with the agent's and the target's loaction
        #Each location is encoded as an element of {0,...,'size'}^2,i.e. MultiDiscrete([size,size])

        self.observation_space=spaces.Dict(
            {
                "agent":spaces.Box(0,size-1,shape=(2,),dtype=int),
                "target": spaces.Box(0, size - 1, shape=(2,), dtype=int)

            }
        )
        #We have 4 actions,corresponding to "right,left,up,down"
        self.action_space=spaces.Discrete(4)
        self._action_to_direction={
            0:np.array([1,0]),
            1:np.array([0,1]),
            2:np.array([-1,0]),
            3:np.array([0,-1])
        }
        #We set the four rewars at the four corners for -1,-2,1,2
        self.reward_range = (-2, 2)
        self._reward = {
            (0,0):-1,
            (4,0):-2,
            (0,4):2,
            (4,4):1
        }
        assert render_mode is None or render_mode in  self.metadata['render_modes']
        self.render_mode=render_mode
        """
                If human-rendering is used, `self.window` will be a reference
                to the window that we draw to. `self.clock` will be a clock that is used
                to ensure that the environment is rendered at the correct framerate in
                human-mode. They will remain `None` until human-mode is used for the
                first time.
                """

        self.window=None
        self.clock=None
        #Used to save the steps process under the some policy
        self.policy_steps=[]
        #用来保存当前的动作序列
        self.action_list=[]
    def _get_obs(self):
        return {"agent":self._agent_location,"target":self._target_location}

    # def _get_info(self):
    #     return {"distance":np.linalg.norm(self._agent_location-self._target_location,ord=1)}
    def _get_info(self):
        return {"actions":self.action_list}
    def reset(self,seed=None,options= None,location=None) :
        #We need to following line to seed self.np_random
        super(GridWorldEnv, self).reset(seed=seed)
        #Choose the agent's location uniformly at random
        # self._agent_location=self.np_random.integers(0,self.size,size=2,dtype=int)
        # Agent initial location is always at [1,1]
        self._agent_location=location if np.array(location).any() else np.array([(self.size-1)/2,(self.size-1)/2],dtype=int)
        #We will sample the target's location randomly until it does not coincide with the agents's location
        # self._target_location=self._agent_location
        # while np.array_equal(self._agent_location,self._target_location):
        #      self._target_location=self.np_random.integers(0,self.size,size=2,dtype=int)
        self.action_list=[]
        self._target_location=[
            np.array([0,0],dtype=int),
            np.array([self.size-1,0],dtype=int),
            np.array([0,self.size-1],dtype=int),
            np.array([self.size-1,self.size-1],dtype=int)]

        observation=self._get_obs()
        info=self._get_info()

        if self.render_mode=="human":
            self._render_frame()

        return observation,info

    def step(self, action):
         #Add the action to the action_list
         self.action_list.append(action)

         #Map the action to the direction we walk in

         direction=self._action_to_direction[action]
         #We use np.clip to make sure we don't leave the grid
         # self._agent_location=np.clip(self._agent_location+direction,0,self.size-1)
         # terminated=np.array_equal(self._agent_location,self._target_location)
         self._agent_location=(self._agent_location+direction)%self.size
         terminated=False
         terminated_loaction=None
         for target_location in self._target_location:
             if np.array_equal(self._agent_location,target_location):
                 terminated=True
                 terminated_loaction=target_location
        #reward well be decided by the terminated location

         reward=self._reward[tuple(terminated_loaction)] if terminated else 0
         observation=self._get_obs()
         info=self._get_info()

         if self.render_mode=="human":
            self._render_frame()

         return observation,reward,terminated,False,info


    def render(self):
         if self.render_mode=="rgb_array":
            return self._render_frame()

    def _render_frame(self):
        if self.window is None and self.render_mode=="human":
          pygame.init()
          pygame.display.init()
          self.window=pygame.display.set_mode((self.window_size,self.window_size))
        if self.clock is None and self.render_mode=="human":
            self.clock=pygame.time.Clock()

        canvas=pygame.Surface((self.window_size,self.window_size))
        canvas.fill((255,255,255))

        pix_square_size=(self.window_size/self.size)  #Size of single grid square in pixels

        #First we draw the target
        i=50
        for target in self._target_location:
            pygame.draw.rect(canvas,(i,0,0),pygame.Rect(pix_square_size*target,(pix_square_size,pix_square_size)))
            i+=50
        #Then draw the agent

        pygame.draw.circle(canvas,(0,0,255),(self._agent_location+0.5)*pix_square_size,pix_square_size/3)

        #Finally,add some gridlines
        for x in range(self.size+1):
            pygame.draw.line(
                canvas,0,(0,pix_square_size*x),(self.window_size,pix_square_size*x),width=3
            )
            pygame.draw.line(
                canvas,
                0,(pix_square_size*x,0),(pix_square_size*x,self.window_size),width=3
            )

        if self.render_mode=="human":
            #The following line copies our drawing from 'canvas' to the visible window
            self.window.blit(canvas,canvas.get_rect())
            pygame.event.pump()
            pygame.display.update()

            #We need to ensure that human-rendering occurs at the predefined framerate.
            #The following line will automatically add a delay to keep the framerate stable
            self.clock.tick(self.metadata["render_fps"])

        else:#rgb_array
            return np.transpose(
                np.array(pygame.surfarray.pixels3d(canvas)),axes=(1,0,2)
            )

    def close(self):
        if self.window is not None:
            pygame.display.quit()
            pygame.quit()

(二)策略编写

1. 初始化

先初始化一条策略,无需理会其最终奖励值大小以及走过的步数。在以下代码中,我将初始化策略所走过的轨迹用数组保存起来,即policy_steps。并返回轨迹和奖励reward

对于 s ∈ S s \in S sS,任意设定 V ( s ) ∈ R V(s) \in R V(s)R以及 π ( s ) ∈ A ( s ) \pi(s) \in A(s) π(s)A(s)

import random
import gym
from gym.envs.registration import register
import numpy as np
register(id="GridWorld",
         entry_point="grid_mdp_modi:GridWorldEnv",
         max_episode_steps=200)

env=gym.make(id="GridWorld",render_mode="human")
env.reset()
def initial_policy():
    policy_steps = []
    policy_steps.append(np.array([2,2]))
    while True:
        # action=np.random.randint(0,4,1)
        action = random.randint(0, 3)
        observation,reward,terminated,truncated,info= env.step(action)
        policy_steps.append(observation["agent"])
        if terminated:
            break
    print("Initial policy finished.")
    return policy_steps,reward

2.价值评估

我在第三节开头写道,由于环境限制,我采用的办法并非是纯动态规划的方法,其原因就在于动态规划中的价值评估是需要对每个状态的策略价值 V ( s ) V(s) V(s)进行评估,即 V ( s ) ← ∑ a π ( a ∣ s ) ∑ s ′ , a p ( s ′ , r ∣ s , a ) [ r + γ V ( s ′ ) ] V(s) \leftarrow \sum_{a}{\pi(a|s)\sum_{s^{'},a}{p(s^{'},r|s,a)[r+\gamma V(s^{'})]}} V(s)aπ(as)s,ap(s,rs,a)[r+γV(s)],这就需要确定的环境,即上式中的 p ( s ′ , r ∣ s , a ) {p(s^{'},r|s,a)} p(s,rs,a) π ( a ∣ s ) \pi(a|s) π(as)已知。(但是我用的这个gym官方的自定义环境它做不到这一点(悲,当然,也是我自己懒得去构造一个这样的理想环境。
所以,最终我的做法是用走到四个角落里所获得的奖励reward/小球运动的步数来评估这个价值value。代码如下:

def value_estimate(policy_steps,reward):
    length = len(policy_steps)
    # Let the reward/length=reward
    reward = reward / float(length)

    return reward

3.策略改进

策略改进也和上述算法
p o l i c y − s t a b l e ← t r u e policy-stable \leftarrow true policystabletrue
对于每一个 s ∈ S s \in S sS
o l d − a c t i o n old-action oldaction ← π ( s ) \leftarrow \pi(s) π(s)
π ( s ) ← a r g m a x a ∑ s ′ , r p ( s ′ , r ∣ s , a ) [ r + γ V ( s ′ ) ] \pi(s) \leftarrow argmax_{a}\sum_{s',r}{p(s',r|s,a)[r+\gamma V(s')]} π(s)argmaxas,rp(s,rs,a)[r+γV(s)]
如果 o l d − a c t i o n ≠ π ( s ) old-action \neq \pi(s) oldaction=π(s),那么 p o l i c y − s t a b l e ← f a l s e policy-stable \leftarrow false policystablefalse
如果 p o l i c y − s t a b l e policy-stable policystable t r u e true true,那么停止并返回 V ≈ v ∗ V≈v* Vv以及 π ≈ π ∗ \pi ≈ \pi* ππ
有所不同。因为如果不走到最后的话,就无法确认某一动作价值的优劣性。因此,在这里我做的办法就是对于上一个策略 π \pi π所产生的轨迹中的每一步作评判,如果我改变了该步下一个动作,并且最终取得了更好的价值,那么我就认定新生成的策略比之前的策略要好,并用新策略覆盖旧策略。代码如下:

def policy_update( policy_steps,old_reward):
    for step_num in range(len(policy_steps)):
        action_temp = random.randint(0, 3)         #随机生成一个动作
        if len(policy_steps)>step_num+1:
            update=policy_steps[step_num+1]
        else:
            break
        while np.array_equal(update,policy_steps[step_num + 1]):  # 如果该动作生成的位移和原策略的位置相同,那么就继续产生随机动作,直至产生不同的位置
            env.reset(location=policy_steps[step_num])
            action_temp = random.randint(0,3)
            observation = env.step(action_temp)
            update=observation[0]["agent"]
        temp_policy_steps = []
        temp_policy_steps.append(update)
        while True:
            action_temp=random.randint(0,3)
            observation,reward,terminated,truncated,info = env.step(action_temp)
            temp_policy_steps.append(observation["agent"])
            if terminated:
                temp_reward=reward
                break
        value = value_estimate(temp_policy_steps,temp_reward)
        value = value * len(temp_policy_steps) / (step_num+1+len(temp_policy_steps))
        if value > old_reward:
            new_policy_steps = policy_steps[:step_num+1]
            new_policy_steps.extend(temp_policy_steps)
            return new_policy_steps,value
            # break
    # if policy_steps!=new_policy_steps:
    #     return new_policy_steps, value
    print("Can't find the better policy")
    return policy_steps,old_reward

最后就是主函数,首先随机生成一个策略,随后进行策略迭代,只有当价值达到最大时(毕竟就一5*5的方格,肉眼可以计算出最大价值=0.4),停止更新.

initial_policy,initial_reward=initial_policy()
initial_reward=value_estimate(initial_policy,initial_reward)
print("The initial reward has been produced which is {}".format(initial_reward))
print("The initial policy is {}".format(initial_policy))

old_reward=initial_reward
policy=initial_policy
episode_num=0
while True:
    policy,new_reward=policy_update(policy,old_reward)
    print("This episode the reward is {}".format(new_reward))
    print("This episode the policy steps is {}".format(len(policy)))
    print("The policy steps is {}".format(policy))
    episode_num+=1
    print("The episode number is {}".format(episode_num))
    if abs(new_reward-old_reward)<old_reward/10 and new_reward>=0.4:
        print("The policy has converged to the condition")
        break
    old_reward=new_reward

由于每一步的动作都是随机生成的,因此,每次运行程序的结果都会不一样,但最后都会收敛到最优路径。截取某次运行的结果。
在这里插入图片描述

4.其他大佬的冰湖环境动态规划

运行前注意,你的gym里要有冰湖环境(FrozenLake8x8-v1),没有的记得pip一下。
在这里插入图片描述

import gym
import time
import numpy as np

def value_iteration(env, threshold=1e-4, gamma=0.9):
    env.reset()
    start = time.time()
    # 初始化策略
    policy = np.zeros(64, dtype=int)   # 默认为float类型
    # 初始化value表 (初始化0)
    value_table = np.zeros(64)
    new_value_table = np.zeros(64)
    delta = 2 * threshold
    while delta > threshold:
        for state in range(64):
            action_value = np.zeros(4)
            for action in range(4):
                for prob, next_state, reward, done in env.P[state][action]:
                    action_value[action] += prob * (reward + gamma*value_table[next_state])
            # 1.利用max操作更新V(s),区别与Policy Iteration
            new_value_table[state] = max(action_value)
            # 2.Policy Improvement
            policy[state] = np.argmax(action_value)
        delta = sum( np.fabs(new_value_table - value_table) )
        value_table = np.copy(new_value_table)   # 注:需用copy拷贝副本,否则两个变量指向同一位置,则赋值时同时改变
    print('===== Value Iteration ======\nTime Consumption: {}s\nIteration: {} steps\nOptimal Policy(gamma={}): {}'.format(time.time()-start, 1, gamma, policy))
    return value_table, policy

def play_game(env, policy, episodes=5, timesteps=150):
    for episode in range(episodes):
        env.reset()
        state=0
        for t in range(timesteps):
            action = policy[state]
            state, reward, done, truncated,info = env.step(action)
            if done:
                print("===== Episode {} finished ====== \n[Reward]: {} [Iteration]: {} steps".format(episode+1, reward, t+1))
                env.render()
                break

env = gym.make('FrozenLake8x8-v1',render_mode="human")
# 价值迭代
value_table, policy = value_iteration(env, gamma=0.9)
# 使用迭代计算得到的策略打游戏
play_game(env, policy, episodes=3)
env.close()

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

强化学习基础三大优化方法:(一)动态规划 的相关文章

  • 从 RabbitMQ 迁移到 Amazon SQS [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我们的初创公司目前正在使用RabbitMQ with Python Django 对于消息队列 现在我们计划转移到Amazon SQS其高可用性
  • 将 3D 矩阵转换为级联 2D 矩阵

    我有一个3Dpython中的矩阵如下 import numpy as np a np ones 2 2 3 a 0 0 0 2 a 0 0 1 3 a 0 0 2 4 我想转换这个3D矩阵到一组2D矩阵 我努力了np reshape但这并没
  • 在 Python 中打开 Alteryx .yxdb 文件?

    有没有办法将 yxdb Alteryx 数据库文件 导入到 Pandas Python 中 而不使用 Alteryx 作为中间人 简短的回答是否定的 目前还不行 更长的答案 yxdb 支持的原始 C 是可以在 github 上找到 http
  • UnicodeDecodeError:“charmap”编解码器|安装 pip python-stdnum==1.8 时出错

    我对编程还很陌生 所以请耐心等待 当我为正在使用的模块安装一些必需的软件包时 我无法安装python stdnum 1 8 我收到以下错误消息 File C Users 59996 AppData Local Programs Python
  • 在 Linux 上创建线程与进程的开销

    我试图回答在 python 中创建线程与进程有多少开销的问题 我修改了类似问题的代码 该问题基本上运行一个带有两个线程的函数 然后运行带有两个进程的相同函数并报告时间 import time sys NUM RANGE 100000000
  • PyPDF2 复制后返回空白 PDF

    def EncryptPDFFiles password directory pdfFiles success 0 Get all PDF files from a directory for folderName subFolders f
  • OpenCV Python 和 SIFT 功能

    我知道有很多关于Python and OpenCV但我没有找到有关这个特殊主题的帮助 我想提取SIFT关键点来自 python OpenCV 中的图像 我最近安装了 OpenCV 2 3 可以访问 SURF 和 MSER 但不能访问 SIF
  • Pandas 将 NULL 读取为 NaN 浮点数而不是 str [重复]

    这个问题在这里已经有答案了 给定文件 cat test csv a b c NULL d e f g h i j k l m n 其中第三列被视为str 当我对列执行字符串函数时 pandas已阅读NULLstr 作为一个NaN float
  • 使用 Pandas 读取带有额外逗号且没有 quotechar 的 CSV?

    Data from io import StringIO import pandas as pd s ID Level QID Text ResponseID responseText date key 375280046 S D3M Wh
  • 按共同日期对数组数据进行排序

    我有一个包含许多行和 3 列的 csv 文件 日期 代表和销售额 我想使用 Python 生成一个新数组 该数组按日期对数据进行分组 并且对于给定日期 按销售额对代表进行排序 例如 我的输入数据如下所示 salesData 201703 B
  • 使用 Click 在 python 中创建命令行应用程序

    我正在使用 Python 创建一个命令行应用程序Click http click pocoo org 接受名称作为输入的库 但如果未输入名称 则返回默认值 这是我到目前为止的代码 hello py import click click ve
  • 如何在 pygame 中水平翻转图像?

    这是在 pygame 如何翻转图像 假设一个图像 猪向右看 时向左看 我按向左箭头键 然后保持这样 即使我不按任何键或者按向上和向下箭头键 那么 当我按向右箭头键时 如何再次将其切换回向右看 并使其保持这种状态 即使我不按任何键或按向上和向
  • 如何从 google place api for python 中的地点 id 获取地点详细信息

    我正在使用 Google Places API 和 Python 来构建一个食品集体智能应用程序 例如周围有哪些餐馆 他们的评级如何 营业时间是什么 等等 我正在Python中执行以下操作 from googleplaces import
  • 如何根据python中的文件名检索每个文件的datemodtime?

    我当前的流程涉及循环遍历源目录并将每个文件的名称添加到 python 中的数据帧中 我也想获取每个文件的修改日期 import datetime import os import pandas as pd set src directory
  • 树莓派上的 /dev/mem 访问被拒绝

    我正在使用我的 Raspberry Pi 并且正在编写一个 cgi python 脚本 该脚本创建一个网页来控制我的 gpio 输出引脚 当我尝试将 RPi GPIO 作为 GPIO 导入时 我的脚本崩溃了 这是我收到的错误 File co
  • 使用 South 更改 Django 模型列默认值

    我在 Django 项目中使用 South 和 Postgresql DB 我想更改一个模型字段的默认值以供继续使用 我不需要以前的记录 刚刚新记录 我是否需要为此进行迁移 或者只是更改模型 旧场详细信息 background style
  • Python,socket.error:[Errno 10049]

    在开发一个简单的聊天客户端的基础上 遇到以下错误 socket error Errno 10049 The requested address is not valid in its context 代码是 from socket impo
  • 在硬件级别模拟按键 - Windows

    我正在寻找一种语言或库 使我能够在最大可能的水平上模拟击键 而无需实际按下按键 我对击键级别的具体衡量标准是 当我的计算机已经运行按键侦听器 例如鼠标键和粘滞键 时 它是否会产生与物理按键相同的输出 我尝试过很多击键模拟的方法 java A
  • 识别左侧由 delta 链接的簇,右侧由不同 delta 链接的簇

    考虑排序后的数组a a np array 0 2 3 4 5 10 11 11 14 19 20 20 如果我指定了左增量和右增量 delta left delta right 1 1 这就是我期望的集群分配方式 a 0 2 3 4 5 1
  • 为什么 Pytest 对夹具参数执行嵌套循环

    使用 Pytest 我想编写一个测试函数 该函数接受多个装置作为参数 每个灯具都有几个参数 例如 test demo py 中是一个函数test squared is less than 10需要固定装置 negative integer

随机推荐

  • JavaScript Table行填充

    使用JS脚本操作Table元素 在不同浏览器中操作方法不尽相同 当新建一行之后 IE中可以使用单元格操作来完成单元格的添加 而在FireFox中无法正确通过单元格来操作 而只能使用 td td 来实现 因此 在编写填充函数时 要注意检测浏览
  • 基础算法题——帅到没朋友(唯一性)

    帅到没朋友 当芸芸众生忙着在朋友圈中发照片的时候 总有一些人因为太帅而没有朋友 本题就要求你找出那些帅到没有朋友的人 输入格式 输入第一行给出一个正整数N 100 是已知朋友圈的个数 随后N行 每行首先给出一个正整数K 1000 为朋友圈中
  • 用TensorFlow.js实现AI换脸 !所以你知道某些网站视频的明星是怎么来的了吗?

    前言 相信很多小伙伴对TensorFlow js早已有所耳闻 它是一个基于JavaScript的深度学习库 可以在Web浏览器中运行深度学习模型 AI换脸是一种基于深度学习的图像处理技术 将一张人脸照片的表情 头发 嘴唇等特征转移到另一张人
  • python遇到can not import xxx错误

    一种不容易被发现的问题是循环引用导致该问题的发生 具体可参考 ImportError cannot import name xxxxxx 的三种类型的解决方法 Activewaste的博客 CSDN博客 cannot import name
  • Android NDK 编译 三方库记录 及 jni库封装问题

    因工作需求 要将原先的c 库跨平台编译 在Android上运行 其依赖了几个第三方库 也需要一起编译 在此做个记录 所需工具 centos 系统上完成 1 cmake 3 15 6 2 ndk android ndk r21e NDK 下载
  • Python自动抢红包,从此再也不会错过微信红包了!

    作者 上海小胖 来源 Python专栏 ID xpchuiit 目录 0 引言 1 环境 2 需求分析 3 前置准备 4 抢红包流程回顾 5 代码梳理 6 后记 0 引言 提到抢红包 就不得不提Xposed框架 它简直是个抢红包的神器 但使
  • windows禁用输入法

    Rime 呼出菜单的快捷键 ctrl grave 跟 vs code 呼出底部命令行的快捷键冲突了 每次用 vs code 时都会用 ctrl space 将输入法禁用 让它变成一个圈叉 由 1 这个快捷键是 windows 系统禁用输入法
  • vue中的事件修饰符

    vue中的事件修饰符 1 prevent 阻止默认事件 常用 a href http www baidu com a 2 stop 阻止事件冒泡 常用 margin top 20px demo1 height 50px background
  • Es中查询数据存在某个字段或者数据的不存在某个字段(must_not,must的使用)

    一 存在 二 不存在 包含两种意思 1 这条数据根本就没有这个字段 2 这条数据的字段的值为null
  • 区块链大作业前期热身报告

    作业内容 使用已有的开源区块链系统FISCO BCOS 完成私有链的搭建以及新节点的加入 截图说明搭建流程 自行编写一个智能合约并部署到私有链上 同时完成合约调用 截图说明部署流程 使用命令查看一个区块 并对各个字段进行解释 单群组FISC
  • 利用pytorch训练网络---垃圾分类,(resnet18)

    数据集包含6种垃圾 分别为cardboard 纸箱 glass 玻璃 metal 金属 paper 纸 plastic 塑料 其他废品 trash 数据数量较小 仅供学习 数据集标准备工作 包括将数据集分为训练集和测试集 制作标签文件 代码
  • redhat7.6 19c Rac禁用透明大页问题-/etc/default/grub:行8: 寻找匹配的 `“‘ 是遇到了未预期的文件结束符

    在安装redhat7 6的oracle 19c rac中 由于之前参考文档为centos版本 在执行禁用透明大页操作时报以下错误 原过程为 1 修改grub文件 cp etc default grub etc default grub ba
  • 百度智能云助力华瑞园智慧社区项目荣获IDC大奖

    在当今数字化 智能化的时代 科技的力量正日益显现 它改变着我们的生活方式 提高着我们的生活质量 9月15日 2023年IDC中国未来企业大奖优秀奖名单公布 在公众投票与专家评选团的严格评选下 百度智能云提供技术支持的 华瑞园智慧社区 项目荣
  • 运维_win server2008关闭危险端口445,135,137,138,139的方法

    昨晚爆出的onion勒索病毒 通过校园网传播 感染了很多同学的电脑 新闻 就在刚刚过去的5月12日晚上20点左右 全国各地的高校学生纷纷反映 自己的电脑遭到病毒的攻击 文档被加密 壁纸遭到篡改 并且在桌面上出现窗口 强制学生支付等价300美
  • 最短Hamilton路径

    题目 题目链接 题解 状压dp f i j 表示从0点按照路径i走到j点的最短距离 其中i为二进制数 1表示走过某点 0表示未走过某点 比如10010表示经过了1 4两个点 而不经过0 2 3点 状态转移为 假设沿路径i走到j点经过k点 且
  • UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0x80 in position 0: illegal multibyte sequence

    f open testData testData pickle load f 错误提醒 gt UnicodeDecodeError gbk codec can t decode byte 0x80 in position 0 illegal
  • 如何在linux下开启FTP服务

    1 首先服务器要安装ftp软件 查看是否已经安装ftp软件下 which vsftpd 如果看到有vsftpd的目录说明服务器已经安装了ftp软件 2 查看ftp 服务器状态 service vsftpd status 3 启动ftp服务器
  • Ubuntu 16 安装IDEA

    1 安装JDK sudo mkdir usr local java cd usr loca java 将jdk 8u171 linux x64 tar gz移动到此处 然后 sudo tar zxvf jdk 8u171 linux x64
  • 三次iframe框架切换

    记录一次坑 做UI自动化 页面是嵌套的frame框架 整个页面是一个iframe 在iframe里面 上方是一个frame 下方是一个frame 下方frame里又分为左右两个frame 所以要定位右侧页面元素 需要三次切入frame框架
  • 强化学习基础三大优化方法:(一)动态规划

    文章目录 一 简介 二 动态规划 DP Dynamic Planning 方法 一 策略评估 二 策略迭代 1 策略改进 2 策略迭代 3 迭代算法 三 编程实践 一 环境介绍 二 策略编写 1 初始化 2 价值评估 3 策略改进 4 其他