原文
这篇博客主要用来记录 SMAC 环境中的代码细节,对于每一个环境transition中,smac环境state和observation到底返回了些什么。建议自己去看代码, debug 一遍看看输出。
SMAC论文概括
1. Action maskDI-engine code
No-np (如果health>0,则无法执行这个动作,=0。否则只能执行这个动作)STOP=1(停止,这个动作除非health=0,否则永远可以执行)Direction.NORTH=1(如果可以向北移动的话)Direction.SOUTH=1Direction.EAST=1Direction.WEST=17 ~ n 其它动作则需要考虑对手/治疗(医疗运输舰可以无视距离治疗友方非飞行物单位)目标是否在射程之内,如果飞蛇和感染虫存在,发动技能,则要看他们的能量是否足够: def get_avail_Agent_actions(self, agent_id, engine, is_opponent=False, s湛江体检kip_mirror=False): """Returns the available actions for agent_id.""" medivac_id = engine.medivac_id_opponent if is_opponent else engine.medivac_id unit = self.get_unit_by_id(agent_id, engine, is_opponent) if unit.healt排卵试纸h > 0: # cannot choose no-op when alive avail_actions = [0] * self.n_actions # stop should be allowed avail_actions[1] = 1 # see if we can move if self.can_move(unit, Direction.NORTH): avail_actions[2] = 1 if self.can_move(unit, Direction.SOUTH): avail_actions[3] = 1 if self.can_move(unit, Direction.EAST): avail_actions[4] = 1 if self.can_move(unit, Direction.WEST): avail_actions[5] = 1 # Can attack only alive units that are alive in the shooting range shoot_range = self.unit_shoot_range(unit) target_items = engine.enemies.items() if not is_opponent else engine.agents.items() self_items = engine.agents.items() if not is_opponent else engine.enemies.items() if engine.map_type == 华南农业大学研究生院34;MMM" and unit.unit_type == medivac_id: # Medivacs cannot heal themselves or other flying units target_items = [(t_id, t_unit) for (t_id, t_unit) in self_items if t_unit.unit_type != medivac_id] for t_id, t_unit in target_items: 钨铼热电偶 if t_unit.health > 0: dist = distance(unit.pos.x, unit.pos.y, t_unit.pos.x, t_unit.pos.y) if dist <= shoot_range: if engine.map_type == "infestor_v花生好车iper": value = 0 # viper 滑触线 if unit.unit_type == 499: if unit.energy >= 125: value = 1 # infestor else: if unit.energy >= 50: value = 1 节度天下 avail_actions[t_id + self.n_actions_no_attack] = value else: avail_actions[t_id + self.n_actions_no_attack] = 1 else: # only no-op allowed avail_actions = [1] + [0] * (self.n_actions - 1) if (not skip_mirror) and self.mirror_opponent and is_opponent: avail_actions[MOVE_EAST], avail_actions[MOVE_WEST] = \ avail_actions[MOVE_WEST], avail_actions[MOVE_EAST] return avail_actions2. Observation所有的observation的维度一开始就已经决定好了,下面的内容只是往里面填空。所以一些没有观测到的东西就还是0.,而不是没有这个维度。另外,如何当前的单位自己的生命值等于0,则观测为全0.。1. 移动相关 move_feats4个方向的可移动性 + 以自己为圆心,周围8个固定半径点的可移动性和高度,以及自己当前所处的1个点的高度 = 4+8+8+1 = 21
def get_movement_features(self, agent_id, engine, is_opponent=False): unit = self.get_unit_by_id(agent_id, engine, is_opponent=is_opponent) move_feats_dim = self.get_obs_move_feats_size() move_feats = np.zeros(move_feats_dim, dtype=np.float32) if unit.health > 0: # otherwise dead, return all zeros # Movement features avail_actions = self.get_avail_agent_actions(agent_id, engine, is_opponent=is_opponent) for m in range(self.n_actions_move): move_feats[m] = avail_actions[m + 2] ind = self.n毁灭世界_a台式电脑组装配置单ctions_move if self.obs_pathing_grid: move_feats[ind:ind + self.n_obs_pathing # TODO self.n_obs_pathing ? ] = self.get_surrounding_pathing(unit) ind += self.n_obs_pathing if self.obs_terrain_height: move_feats[ind:] = self.get_surrounding_height(unit) return move_feats周围8个点选点代码:
def get_surrounding_points(self, unit, include_self=False): """Returns the surrounding points of the unit in 8 directions.""" x = int(unit.pos.x) y = int(unit.pos.y) ma = self._move_amount points = [ (x, y + 2 * ma), (x, y - 2 * ma), (x + 2 * ma, y), (x - 2 * ma, y), (x 结婚回礼+ ma, y + ma), (x - ma, y - ma), (x + ma, y - ma), (x - ma, y + ma), ] if include_self: points.append((x, y)) return points2. 敌方特征 enemy_feats只能看到周围在 视野范围内(dist<sight_range) 的 活着(e_unit.health>0) 的敌方单位的特征。enemy_num(4+1+1+unit_type_bits)=enemy_num(6+unit_type_bits).对于每一个看得到敌方单位:
1 该单位能否攻击?(通过判断该单位距离是否小于shoot_range)enemy_feats[e_id, 0] = avail_actions[self.action_helper.n_actions_no_attack + e_id] # available2 相对距离、相对x距离、相对y距离enemy_feats[e_id, 1] = dist / sight_range # distanceenemy_feats[e_id, 2] = (e_x - x) / sight_range # relative Xenemy_feats[e_id, 3] = (e_y - y) / sight_range # relative Y3 血量、护盾的相对值ind = 4 # 前面四个位置已经被占据if self.obs_all_health: enemy_feats[e_id, ind] = (e_unit.health / e_unit.health_max) # health ind += 1 if self.shield_bits_enemy > 0: max_shield = self.unit_max_shield(e_unit, not is_opponent) enemy_feats[e_id, ind] = (e_unit.shield / max_shield) # shield ind += 14 敌方单位类别:one-hotenemy_feats[e_id, ind + type_id] = 1 # unit type每个地图的兵种id数量都不相同,所以无法确定这个维度是多少。
3. 友军特征:ally_feats只能看到周围在视野范围内(dist<sight_range)的活着(e_unit.health>0)的友方单位的特征。(ally_num-1)(4+1+1+unit_type_bits)=(ally_num-1)(6+unit_type_交易所债券bits).对每一个看得到的友方单位(除自己)
1 该单位可以看见ally_feats[i, 0] = 1 # visible2 相对距离、相对x距离、相对y距离ally_feats[i, 1] = dist / sight_range # distanceally_feats[i, 2] = (al_x - x) / sight_range # relative Xally_fe左侧肋骨下疼ats[i, 3] = (al_y - y) / sight_range # relative Y3 血量、护盾的相对值ind = 4if self.obs_all_health: ally_feats[i, ind] = (al_unit.health / al_unit.health_max) # health ind += 1 if self.shield_bits_ally > 0: max_shield = self.unit_max_shield(al_unit, is_opponent) ally_feats[i, ind] = (al_unit.shield / max_shield) # shield ind += 14 单位类别ally_feats[i, ind + type_id] = 1需要注意的是,观测observation无法看到友军最后一个动作,只有状态state才有。
4. 自己的特征:own_feats1 血量护盾的的相对值ind = 0if self.obs_own_health: own_feats[ind] = unit.health / unit.health_max ind += 1 if self.shield_bits_ally > 0: max_shield = self.unit_max_shield(unit, is_opponent) own_feats[ind] = unit.shield / max_shield ind += 12 自己的兵种类别if self.unit_type_bits > 0: type_id = self.get_unit_type_id(unit, True, is_opponent) own_feats[ind + type_id] = 1 ind += self.unit_type_bits3 自己的上一个动作,也是所有动作中的one-hot向量own_feats[ind:] = self.action_helper.get_last_action(is_opponent)[agent_id]5. 自己的id智能体数量,one-hot向量
agent_id_feats[agent_id] = 13. State除了智能体的观测外,游戏还为每个智能体在各自观测的基础上,额外提供全局信息,辅助训练:所有智能体的坐标医疗运输舰的能量以及剩余友方单位的冷却所有智能体的上一个动作4. Reward返回一个归一化的标量,其shape和智能体数量无关。
Example: 3s5z reset时的情况elif self.special_global_state: return { 'agent_state': self.get_obs(), 'global_state': self.get_global_special_state(), 'action_mask': self.get_avail_actions(), }1. agent_state = self.get_obs()对于每一个agent:由于只有两个兵种(追猎和叉子),所以 unit_type_bits = 2初始化时:avail_actions
avail_actions[0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]len(avail_actions)146 + 8 = 14所以在 3s5z 的初始场景,改智能体只能向四个方向移动或停止动作,由于8个敌人都没有进入射程,所以无法攻击。
1.1 move_featsdef get_obs_move_feats_size(self): """Returns the size of the vector containing the agents's movement-related features.""" move_feats = self.n_actions_move if self.obs_pathing_grid: # False move_feats += self.n_obs_pathing if self.obs_terrain_height: # False move_feats += self.n_obs_height return move_featsn_action_move = 4-> move_feats = (4,)初始化时实例:
move_featsarray([1., 1., 1., 1.], dtype=float32)代表四个方向都能走
1.2 enemy_featsdef get_obs_enemy_feats_size(self): """美攻丑受 Returns the dimensions of the matrix containing enmalfoyemy features. Size is n_enemies x n_features. """ nf_en = 4 + self.unit_type_bits if self.obs_all_health: nf_en += 1 + self.shield_bits_enemy # 1是血量health return self.n_enemies, nf_en4 代表 能否攻击+相对距离+相对x+相对y
unit_type_bits = 2self.shield_bits_enemy = 1self.n_enemies, nf_en = 8, 8-> enemy_feats.shape = (8, 8)初始化时实例:enemy_featsarray([[0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32)8 = 能否攻击1+相对距离1+相对x1+相对y1+相对血量1+相对护盾1+兵种2 (按顺序)代表没有敌人进入可视距离
1.3 ally_featsdef get_obs_ally_feats_size(self): """Returns the dimensions of the matrix cont猥亵行为aining ally features. Size is n_allies x n_features. """ nf_al = 4 + self.unit_type_bits if self.obs_all_health: nf_al += 1 + self.shield_bits_ally # LJ fix # if self.obs_last_action: # nf_al += self.n_actions return self.n_agents - 1, nf_al4 代表 可以看见+相对距离+相对x+相对y
unit_type_bits = 2self.shield_bits_enemy = 1self.n_agents - 1, nf_al = 7, 8-> ally_feats.shape = (7, 8)初始化时实例:ally_featsarray([[ 1. , 0.13205296, 0. , 0.13205296, 1. , 1. , 1. , 0. ], [ 1. , 0.18675107, 0.13205296, 0.13205296, 1. , 1. , 1. , 0. ], [ 1. , 0.25094765, -0.16666667, 0.18760851, 1. , 1. , 0. , 1. ], [ 1. , 0.13489823, -0.11111111, 0.0764974 , 1. , 1. , 0. , 1. ], [ 1. , 0.24942972, -0.05555556, 0.24316406, 1. , 1. , 0. , 1. ], [ 1. , 0.35427517, 0. , 0.35427517, 1. , 1. , 0. , 1. ], [ 1. , 0.24942972, 0.05555556, 0.24316406, 1. , 1. , 0. , 1. ]], dtype=float32)8 = 可以看见1+相对距离1+相对x1+相对y1+相对血量1+相对护盾1+兵种2
不难发现,相对x=0,说明开始时是以列形势出生的,之间的距离为可视距离的0.13205296,血量护盾都满,且视野中有两个追猎和五个狂热,说明这是一个追猎者的视角。
1.4 own_featsdef get_obs_own_feats_size(self): """Returns the size of the vector containing the agents' own features. """ own_feats = self.unit_type_bits if self.obs_own_health: own_feats += 1 + self.shield_bits_ally if self.obs_timestep_number: # 这里是 False own_feats += 1 if self.obs_last_action: own_feats += self.n_actions return own_featsunit_type_bits = 2self.shield_bits_enemy = 1self.n_actions = 14 = 6 + (3 + 5)-> own_feats = (18,)初始化时实例:
own_feats.shape(18,)own_featsarray([1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)18 = 相对血量1+相对护盾1+兵种2+上一个动作one-hot 14动作部分全0.代表游戏刚刚开始。
1.5 agent_id_featsagent_id_feats = np.zeros(self.n_agents)agent_id_feats[agent_id] = 18 = 由己方控制的智能体单位数量初始化时第一个智能体观测实例:
agent_id_feats.shape(8,)agent_id_featsarray([1., 0., 0., 0., 0., 0., 0., 0.])1.6 合并agent_obs = np.concatenate( ( move_feats.flatten(), enemy_feats.flatten(), ally_feats.flatten(), own_feats.flatten(), agent_id_feats, ))实例:
move_feats.shape(4,)enemy_feats.shape(8, 8)ally_feats.shape(7, 8)own_feats.shape(18,)agent_id_feats.shape(8,)agent_obs.shape(150,)150 = 4 + 88 + 78 + 18 + 8
总结一下单个智能体的观测维度150 =
自己四个方向的可移动性4 +8个敌人 * (能否攻击1+相对距离1+相对x1+相对y1+相对血量1+相对护盾1+兵种2)8 +7个队友*(可以看见1+相对距离1+相对x1+相对y1+相对血量1+相对护盾1+兵种2)8 +自己的(相对血量1+相对护盾1+兵种2+上一个动作one-hot 14)18 +自己的智能体id * 8在这个环境的默认设置里面,obs不包含当前的时间步的信息。所以最后返回 (8, 150) 的ndarray2. global_state = get_global_special_state对于每一个agent:由于只有两个兵种(追猎和叉子),所以 unit_type_bits = 2初始化时:avail_actions
avail_actions[0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]len(avail_actions)146 + 8 = 14所以在 3s5z 的初始场景,改智能体只能向四个方向移动或停止动作,由于8个敌人都没有进入射程,所以无法攻击。还是举reset时候为例子:
2.1 enemy_feats如果该敌人health>0:
该敌人能否被攻击1相对距离1、相对x距离1、相对y距离1该敌人是否对于当前智能体可见1相对血量1、相对护盾1兵种2与地图中点的相对x1,相对y13s5z这张图中地图大小是32.0 * 32.0,视野范围是9.,射击范围是6.。11 = 1 + 3 + 1 + 2 + 2 + 2最后的shape:(8, 11)enemy_feats.shape(8, 11)enemy_featsarray([[ 0. , 1.5611506 , 1.5555556 , 0.13205296, 0. , 1. , 1. , 0. , 1. , 0.25 , 0. ], [ 0. , 1.5555556 , 1.5555556 , 0. , 0. , 1. , 1. , 0. , 1. , 0.25 , -0.04244559], [ 0. , 1.5195818 , 1.5 , 0.24316406, 0. , 1. , 1. , 1. , 0. , 0.23214285, 0.03571429], [ 0. , 1.629358 , 1.6111112 , 0.24316406, 0. , 1. , 1. , 1. , 0. , 0.26785713, 0.03571429], [ 0. , 1.5953883 , 1.5555556 , 0.35427517, 0. , 1. , 1. , 1. , 0. , 0.25 , 0.07142857], [ 0. , 1.4015025 , 1.3888888 , 0.18760851, 0. , 1. , 1. , 1. , 0. , 0.19642857, 0.01785714], [ 0. , 1.4464687 , 1.4444444 , 0.0764974 , 0. , 1. , 1. , 1. , 0. , 0.21428572, -0.01785714], [ 0. , 1.6927671 , 1.6876085 , 0.13205296, 0. , 1. , 1. , 0. , 1. , 0.2924456 , 0. ]], dtype=float32)2.2 ally_feats如果该队友health>0:
该队友是否对于当前智能体可见1相对距离1、相对x距离1、相对y距离1相对能量/武器冷却时间1(医疗运输舰是能量,其它单位是武器)相对血量1、相对护盾1与地图中点的相对x1,相对y1兵种2该队友上一个动作1425 = 1 + 3 + 1 + 2 + 2 + 2 + 14最后的市场细分shape:(7, 25)ally_feats.shape(7, 25)ally_featsarray([[ 1. , 0.13205296, 0. , 0.13205296, 0. , 1. , 1. , -0.25 , 0. , 1. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 1. , 0.18675107, 0.13205296, 0.13205296, 0. , 1. , 1. , -0.20755441, 0. , 1. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. 怎样修眉毛 , 0. , 0. , 0. , 0. , 0. ], 想念是会呼吸的痛 [ 1. , 0.25094765, -0.16666667, 0.18760851, 0. , 1. , 1. , -0.30357143, 0.01785714, 0. , 1. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0胎盘低置. , 0. , 0. , 0. ], [ 1. , 0.13489823, -0.11111111, 0.0764974 , 0. , 1. , 1. , -0.2857143 , -0.01785714, 0. , 1. , 0. , 0. 黑爵士 , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 1. , 0.24942972, -0.05555556, 0.24316406, 0. , 1. , 1. , -0.26785713, 0.03571429, 0. , 1. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 1. , 0.35427517, 0. , 0.35427517, 0. , 1. , 1. , -0.25 , 0.07142857, 0. , 1. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 1. , 0.24942972, 0.05555556, 0.24316406, 0. , 1. , 1. , -0.23214285, 0.03571429, 0. , 1. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ]], dtype=float32)2.3 own_feats自己对自己可见1相对距离1、相对x距离1、相对y距离1(这三个都是0)相对血量1、相对护盾1与地图中点的相对x1,相对y1兵种2自己的上一个动作1424 = 1 + 3 + 2 + 2 + 2 + 14own_featsarray([ 1. , 0. , 0. , 0. , 1. , 1. , -0.25 , -0.04244559, 1. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], dtype=float32)own_feats.shape(24,)2.4 agent_id_feats8维one-hot
agent_id_featsarray([1., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)agent_id_feats.shape(8,)2.5 合并
state.shape(295,)单个智能体的状态维度295 =
7个队友 * (该队友是否对于当前智能体可见1 + 相对距离1、相对x距离1、相对y距离1 + 相对能量/武器冷却时间1 + 相对血量1、相对护盾1 + 与地图中点的相对x1,相对y1 + 兵种2 + 该队友上一个动作14)25 +8个敌人 * (该敌人能否被攻击1 + 相对距离1、相对x距离1、相对y距离1 + 该敌人是否对于当前智能体可见1 + 相对血量1、相对护盾1 + 兵种2 + 与地图中点的相对x1,相对y1)11 +1自己特征 * (自己对自己可见1 + 相对距离1、相对x距离1、相对y距离1 + 相对血量1、相对护盾1 + 与地图中点的相对x1,相对y1 + 兵种2 + 自己的上一个动作14)24 +自己的智能体id * 8最后返回(8, 295)3. action_mask = get.avail_actions()返回(8, 14)
self.get_avail_actions()array([[0., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32)本文使用 Zhihu On VSCode 创作并发布本文发布于:2023-06-02 14:32:05,感谢您对本站的认可!
本文链接:http://www.ranqi119.com/ge/85/192033.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |