wordpress怎么做站内站,建设四川网站,驰业网站建设,阿里云网站建设基本流程这段代码的背景是玩一个游戏。游戏的参数有NUM_TURNS#xff0c;在第i回合#xff0c;你可以从一个整数[-2,2,3#xff0c;-3]*#xff08;NUM_TURNS1-i#xff09;中进行选择。例如#xff0c;在一个4回合的游戏中#xff0c;在第1回合#xff0c;你可以从[-8,8,12在第i回合你可以从一个整数[-2,2,3-3]*NUM_TURNS1-i中进行选择。例如在一个4回合的游戏中在第1回合你可以从[-8,8,12-12]中选择在第2回合你也可以从[-6,6,9-9]中选择。在每一个转弯处所选择的数字都会累积为一个聚合值。游戏的目标是使累积值尽可能接近0。
定义MCTS 标量。标量越大利用exploitation更大标量越小探索 exploration更大。 接下来使用了logging模块用于设置和获取日志记录器logger。 查看日志是开发人员日常获取信息、排查异常、发现问题的最好途径日志记录中通常会标记有异常产生的原因、发生时间、具体错误行数等信息这极大的节省排查时间无形中提高了编码效率。 有关日志的更多信息。 logging.basicConfig(levellogging.WARNING) logging.basicConfig()用于快速设置日志系统的基本配置。levellogging.WARNING设置日志系统的最低日志级别为WARNING。这意味着只有WARNING、ERROR和CRITICAL级别的日志消息会被处理并显示。低于WARNING级别的消息如DEBUG和INFO将被忽略。使用basicConfig方法后所有后续的日志消息除非明确指定了其他logger都会使用这些基本设置。 logger logging.getLogger(MyLogger) logging.getLogger(MyLogger)这是获取或创建一个名为MyLogger的日志记录器的方法。如果名为MyLogger的logger已经存在该方法将返回该logger的引用。如果不存在它将创建一个新的logger。默认情况下新创建的logger会继承root logger的配置即basicConfig设置的配置。但你可以为特定logger设置特定的处理器handlers、格式器formatters和级别levels。
这两个语句之间的关系是basicConfig为整个日志系统包括所有logger设置了基本配置而getLogger则允许你获取或创建一个特定的logger并可以为其设置特定的配置如果需要的话。
一个简单的例子
import logging # 设置基本配置所有日志级别为WARNING及以上的消息都会被处理
logging.basicConfig(levellogging.WARNING) # 获取一个名为MyLogger的logger
logger logging.getLogger(MyLogger) # 由于basicConfig已经设置了级别为WARNING所以下面的消息将被记录
logger.warning(This is a warning message.) # 下面的消息将不会被记录因为级别低于WARNING
logger.info(This is an info message.) 建立类State 类变量 NUM_TURNS表示游戏或决策过程中的回合数这里默认是10。GOAL表示目标值状态的值达到这个值时会获得最大的奖励这里默认是0。MOVES表示每次状态变化时可能的移动值这里默认是[2,-2,3,-3]。MAX_VALUE根据公式计算得出用于后续的归一化奖励。num_movesMOVES列表的长度。 __init__方法 用于初始化一个State对象。value表示当前状态的值。moves一个列表表示到目前为止所采取的所有移动。turn表示当前的回合数。 next_state方法 基于当前状态生成下一个状态。随机选择一个移动值并更新状态的值、移动列表和回合数。返回新的State对象。 terminal方法 判断当前状态是否是终止状态即回合数是否为0。如果是终止状态返回True否则返回False。 reward方法 计算并返回当前状态的奖励值奖励值基于当前状态的值与目标值之间的差异来计算。 __hash__方法 为State对象提供一个哈希值以便可以在哈希表中使用。使用MD5哈希算法对移动列表进行哈希。 __eq__方法 使用哈希值来判断两个State对象是否相等。 __repr__方法 返回一个字符串包括状态的值和移动列表表示State对象的状态。 建立类Node用于表示决策树或搜索树中的节点。在MCTS算法中每个节点代表一个可能的状态并且每个节点都存储了关于该状态的信息如访问次数、累积奖励等。 __init__方法 state表示该节点对应的状态。parent表示该节点的父节点默认为None。visits表示该节点被访问的次数初始化为1。reward表示从该节点开始到终止状态所获得的累积奖励初始化为0.0。children一个列表存储该节点的所有子节点。add_child方法 用于向当前节点添加一个子节点。child_state子节点对应的状态。创建一个新的Node对象并将其作为子节点添加到children列表中。update方法 用于更新节点的reward和visits属性。reward从该节点开始到终止状态所获得的奖励。该方法将奖励累加到self.reward并将self.visits加1。fully_expanded方法 检查当前节点是否已经完全扩展即是否已经有了所有可能的子节点。num_moves_lambda一个可选的函数用于计算给定节点的子节点数量。如果提供了这个函数它将覆盖self.state.num_moves来计算子节点数量。如果当前节点的子节点数量等于可能的子节点数量则返回True否则返回False。__repr__方法 返回一个字符串表示节点的简要信息。包括子节点的数量、访问次数和累积奖励。 建立函数UCTSEARCH 实现了UCTUpper Confidence Bound for Trees搜索算法的函数。UCT是一种常用于蒙特卡洛树搜索MCTS的策略它结合了随机模拟与基于树结构的搜索以找到最优的决策序列。 参数
budget这是一个整数表示模拟的总次数或预算。算法将运行这么多次模拟来寻找最佳策略。root这是搜索树的根节点代表初始状态。num_moves_lambda这是一个可选的lambda函数用于自定义计算给定节点子节点数量的方式。如果未提供将使用节点状态中的num_moves属性。
主要步骤 循环模拟算法将进行budget次模拟。在每次模拟中算法会从根节点开始选择一系列的动作直到达到终止状态。 日志记录每进行10000次模拟算法会记录当前的模拟次数并输出根节点的信息。这有助于观察搜索过程的进展。 树策略TREEPOLICY在每次模拟中算法使用TREEPOLICY函数从当前节点开始根据UCT公式选择一个子节点作为下一步。这个步骤基于已有的信息如节点的访问次数和奖励来做出决策。 默认策略DEFAULTPOLICY算法使用DEFAULTPOLICY函数从选定的节点front.state开始执行一系列动作直到达到终止状态并计算累积奖励。 回溯BACKUP在模拟结束后算法将累积的奖励回溯到搜索树中更新每个访问过的节点的统计信息如访问次数和累积奖励。 选择最佳子节点BESTCHILD在所有模拟结束后算法使用BESTCHILD函数从根节点开始基于节点的统计信息选择一个最佳子节点作为下一步。
最终UCTSEARCH函数返回从根节点开始的最佳子节点序列这些子节点代表了一系列的动作构成了在给定预算下找到的最优策略。 建立函数TREEPOLICY 基于当前节点的信息和UCT公式来决定是扩展一个新节点即执行一个新的动作还是选择一个已经存在的子节点进行进一步的搜索。函数在搜索过程中平衡了探索扩展新节点和利用选择已知的最佳子节点之间的关系以实现更有效的搜索。
参数
node当前搜索树中的节点代表当前的状态。num_moves_lambda一个可选的函数用于计算给定节点的子节点数量。如果未提供将使用节点状态中的 num_moves 属性。
函数流程 检查终止状态首先函数检查当前节点是否处于终止状态即游戏是否结束。如果是终止状态则不再继续搜索直接返回当前节点。 处理空子节点如果当前节点没有子节点即还没有进行过任何扩展则调用 EXPAND 函数来扩展一个新的子节点并返回这个新节点。 随机选择如果当前节点有子节点函数会随机决定是否选择一个最佳子节点还是扩展一个新的子节点。这是通过生成一个0到1之间的随机数来实现的。 如果随机数小于0.5则调用 BESTCHILD 函数选择当前节点中根据UCT公式计算出的最佳子节点并将该节点设置为新的当前节点。如果随机数大于或等于0.5则进入下一步。 检查是否完全扩展使用 fully_expanded 方法检查当前节点是否已经完全扩展即是否已经有了所有可能的子节点。 如果当前节点没有完全扩展则调用 EXPAND 函数来扩展一个新的子节点并返回这个新节点。如果当前节点已经完全扩展则调用 BESTCHILD 函数选择当前节点中根据UCT公式计算出的最佳子节点并将该节点设置为新的当前节点。 返回节点函数最终返回选择的节点这个节点可能是新扩展的节点也可能是根据UCT公式选择的最佳子节点。 建立函数EXPAND用于扩展当前节点的一个新的子节点即在当前状态下尝试一个新的动作或决策。
参数
node当前搜索树中的节点代表当前的状态。
函数流程 获取已尝试的子节点状态首先函数创建一个列表 tried_children其中包含当前节点所有已存在子节点的状态。这是为了确保不会重复扩展已经尝试过的相同状态。 生成新的状态调用当前节点状态对象的 next_state() 方法来生成一个新的状态 new_state。这个方法通常代表在当前状态下可以采取的下一个动作或决策。 检查状态是否已尝试函数使用一个 while 循环来检查新生成的状态 new_state 是否已经作为子节点尝试过。这是通过检查 new_state 是否存在于 tried_children 列表中并且该状态不是终止状态来实现的。如果 new_state 已经尝试过或是一个终止状态则继续生成新的状态。 添加新子节点一旦找到一个新的、未尝试过的状态 new_state函数使用 add_child 方法将其作为新的子节点添加到当前节点中。 返回新子节点最后函数返回新添加的子节点这样调用者可以进一步处理或从这个新状态开始进行模拟。 建立函数BESTCHILD用于从当前节点的子节点中选择一个最佳子节点来继续搜索。这个函数同样基于UCT公式来平衡探索和利用的权衡。
参数
node当前搜索树中的节点代表当前的状态。scalar用于调整探索和利用之间的权衡。较大的 scalar 值将增加探索的倾向而较小的值将更注重利用已知信息。
函数流程 初始化最佳分数和最佳子节点列表函数首先初始化 bestscore 为0.0用于存储当前找到的最佳分数。同时bestchildren 列表用于存储具有相同最佳分数的子节点。 遍历子节点对于当前节点的每一个子节点 c函数计算其UCT分数。 计算利用部分exploit c.reward / c.visits 是利用部分它表示子节点 c 的平均奖励与其被访问次数之间的比率。这反映了子节点 c 的已知价值。 计算探索部分explore math.sqrt(2.0 * math.log(node.visits) / float(c.visits)) 是探索部分它基于子节点 c 的访问次数和父节点 node 的总访问次数来计算。这反映了选择较少访问的子节点以进行进一步探索的倾向。 计算UCT分数score exploit scalar * explore 是子节点 c 的UCT分数。它结合了利用部分和探索部分其中 scalar 用于调整两者之间的平衡。 更新最佳分数和最佳子节点如果子节点 c 的UCT分数大于当前的 bestscore则更新 bestscore 为该分数并重置 bestchildren 列表只包含当前子节点 c。如果分数等于 bestscore则将子节点 c 添加到 bestchildren 列表中。 处理无最佳子节点的情况如果遍历完所有子节点后 bestchildren 列表为空这通常是一个错误情况表明没有子节点被访问过则记录一个警告日志。 返回最佳子节点最后函数从 bestchildren 列表中随机选择一个子节点作为最佳子节点返回。这允许在多个具有相同最佳分数的子节点之间进行随机选择。 建立函数DEFAULTPOLICY用于在没有其他特定策略可用时选择一个默认的动作。
参数
state当前的状态对象代表游戏或决策过程的当前状态。
函数流程 检查终止状态函数首先检查当前状态 state 是否是终止状态即游戏是否结束。如果是终止状态则不再继续执行因为终止状态没有后续的动作或决策。 选择下一个状态如果当前状态不是终止状态函数使用 next_state() 方法来选择或生成下一个状态。这通常意味着在当前状态下执行一个默认的动作或决策。 迭代过程函数将当前状态更新为下一个状态并重复上述过程直到达到一个终止状态。 返回奖励当达到终止状态时函数调用 reward() 方法来获取该状态的奖励值并将其作为结果返回。 建立函数BACKUP用于在模拟结束后更新从根节点到叶节点的路径上所有节点的统计信息。具体来说它会遍历这条路径增加每个节点的访问次数visits和累计奖励reward。
参数
node需要进行回溯的起始节点通常是一个叶节点。reward模拟结束时获得的奖励值。
函数流程 检查起始节点函数首先检查起始节点 node 是否为 None。如果是 None则不执行任何操作并直接返回。 遍历路径并更新统计信息 如果起始节点不是 None函数进入一个 while 循环该循环将继续执行直到遍历到根节点或遇到 None 节点为止。在循环内部函数首先增加当前节点 node 的访问次数visits和累计奖励reward。这通过 node.visits 1 和 node.reward reward 实现。然后函数将当前节点更新为其父节点 node.parent以便在下一次循环迭代中处理父节点。 返回函数完成后返回 None。 主程序入口
if __name____main__:这是一个常见的Python模式用于检查脚本是否作为主程序运行而不是被导入为模块。argparse.ArgumentParser()创建一个命令行参数解析器。parser.add_argument(--num_sims, ...)添加一个命令行参数 --num_sims它是一个必需的整数参数用于指定模拟的次数。parser.add_argument(--levels, ...)添加一个命令行参数 --levels它也是一个必需的整数参数用于指定搜索的层数。它的值必须在 0 到 State.NUM_TURNS 之间包括两端。args parser.parse_args()解析命令行参数并将结果存储在 args 对象中。
current_node Node(State())创建一个根节点其状态由 State() 确定。for l in range(args.levels):对于每个指定的搜索层数 l执行以下操作 current_node UCTSEARCH(args.num_sims/(l1), current_node)对当前节点执行UCT搜索模拟次数随着层数的增加而减少这是一个常见的策略因为随着树深度的增加每个节点的模拟次数通常会减少。打印当前层数、当前节点的子节点数量以及每个子节点的信息。print(Best Child: %s % current_node.state)打印当前节点下具有最佳UCT分数的子节点的状态。print(--------------------------------)打印一个分隔符以便于阅读输出。 #!/usr/bin/env python
import random
import math
import hashlib
import logging
import argparse
A quick Monte Carlo Tree Search implementation. For more details on MCTS see See http://pubs.doc.ic.ac.uk/survey-mcts-methods/survey-mcts-methods.pdfThe State is a game where you have NUM_TURNS and at turn i you can make
a choice from an integeter [-2,2,3,-3]*(NUM_TURNS1-i). So for example in a game of 4 turns, on turn for turn 1 you can can choose from [-8,8,12,-12], and on turn 2 you can choose from [-6,6,9,-9]. At each turn the choosen number is accumulated into a aggregation value. The goal of the game is for the accumulated value to be as close to 0 as possible.The game is not very interesting but it allows one to study MCTS which is. Some features
of the example by design are that moves do not commute and early mistakes are more costly. In particular there are two models of best child that one can use
#MCTS scalar. Larger scalar will increase exploitation, smaller will increase exploration.
SCALAR1/(2*math.sqrt(2.0))logging.basicConfig(levellogging.WARNING)
logger logging.getLogger(MyLogger)class State():NUM_TURNS 10 GOAL 0MOVES[2,-2,3,-3]MAX_VALUE (5.0*(NUM_TURNS-1)*NUM_TURNS)/2num_moveslen(MOVES)def __init__(self, value0, moves[], turnNUM_TURNS):self.valuevalueself.turnturnself.movesmovesdef next_state(self):nextmoverandom.choice([x*self.turn for x in self.MOVES])nextState(self.valuenextmove, self.moves[nextmove],self.turn-1)return nextdef terminal(self):if self.turn 0:return Truereturn Falsedef reward(self):r 1.0-(abs(self.value-self.GOAL)/self.MAX_VALUE)return rdef __hash__(self):return int(hashlib.md5(str(self.moves).encode(utf-8)).hexdigest(),16)def __eq__(self,other):if hash(self)hash(other):return Truereturn Falsedef __repr__(self):sValue: %d; Moves: %s%(self.value,self.moves)return sclass Node():def __init__(self, state, parentNone):self.visits1self.reward0.0 self.statestateself.children[]self.parentparent def add_child(self,child_state):childNode(child_state,self)self.children.append(child)def update(self,reward):self.rewardrewardself.visits1def fully_expanded(self, num_moves_lambda):num_moves self.state.num_movesif num_moves_lambda ! None:num_moves num_moves_lambda(self)if len(self.children)num_moves:return Truereturn Falsedef __repr__(self):sNode; children: %d; visits: %d; reward: %f%(len(self.children),self.visits,self.reward)return sdef UCTSEARCH(budget,root,num_moves_lambda None):for iter in range(int(budget)):if iter%100009999:logger.info(simulation: %d%iter)logger.info(root)frontTREEPOLICY(root, num_moves_lambda)rewardDEFAULTPOLICY(front.state)BACKUP(front,reward)return BESTCHILD(root,0)def TREEPOLICY(node, num_moves_lambda):#a hack to force exploitation in a game where there are many options, and you may never/not want to fully expand firstwhile node.state.terminal()False:if len(node.children)0:return EXPAND(node)elif random.uniform(0,1).5:nodeBESTCHILD(node,SCALAR)else:if node.fully_expanded(num_moves_lambda)False: return EXPAND(node)else:nodeBESTCHILD(node,SCALAR)return nodedef EXPAND(node):tried_children[c.state for c in node.children]new_statenode.state.next_state()while new_state in tried_children and new_state.terminal()False:new_statenode.state.next_state()node.add_child(new_state)return node.children[-1]#current this uses the most vanilla MCTS formula it is worth experimenting with THRESHOLD ASCENT (TAGS)
def BESTCHILD(node,scalar):bestscore0.0bestchildren[]for c in node.children:exploitc.reward/c.visitsexploremath.sqrt(2.0*math.log(node.visits)/float(c.visits)) scoreexploitscalar*exploreif scorebestscore:bestchildren.append(c)if scorebestscore:bestchildren[c]bestscorescoreif len(bestchildren)0:logger.warn(OOPS: no best child found, probably fatal)return random.choice(bestchildren)
def DEFAULTPOLICY(state):while state.terminal()False:statestate.next_state()return state.reward()def BACKUP(node,reward):while node!None:node.visits1node.rewardrewardnodenode.parentreturnif __name____main__:parser argparse.ArgumentParser(descriptionMCTS research code)parser.add_argument(--num_sims, actionstore, requiredTrue, typeint)parser.add_argument(--levels, actionstore, requiredTrue, typeint, choicesrange(State.NUM_TURNS1))argsparser.parse_args()current_nodeNode(State())for l in range(args.levels):current_nodeUCTSEARCH(args.num_sims/(l1),current_node)print(level %d%l)print(Num Children: %d%len(current_node.children))for i,c in enumerate(current_node.children):print(i,c)print(Best Child: %s%current_node.state)print(--------------------------------)