利用强化学习Q-Learning实现最短路径算法

简介: 如果你是一名计算机专业的学生,有对图论有基本的了解,那么你一定知道一些著名的最优路径解,如Dijkstra算法、Bellman-Ford算法和a*算法(A-Star)等。

这些算法都是大佬们经过无数小时的努力才发现的,但是现在已经是人工智能的时代,强化学习算法能够为我们提出和前辈一样好的解决方案吗?

本文中我们将尝试找出一种方法,在从目的地a移动到目的地B时尽可能减少遍历路径。我们使用自己的创建虚拟数据来提供演示,下面代码将创建虚拟的交通网格:

 importnetworkxasnx
 
 # Create the graph object
 G=nx.Graph()
 
 # Define the nodes
 nodes= ['New York, NY', 'Los Angeles, CA', 'Chicago, IL', 'Houston, TX', 'Phoenix, AZ', 'Dallas, TX', 'Miami, FL']
 
 # Add the nodes to the graph
 G.add_nodes_from(nodes)
 
 # Define the edges and their distances
 edges= [('New York, NY', 'Chicago, IL', {'distance': 790}), 
          ('New York, NY', 'Miami, FL', {'distance': 1300}),
          ('Chicago, IL', 'Dallas, TX', {'distance': 960}),
          ('Dallas, TX', 'Houston, TX', {'distance': 240}),
          ('Houston, TX', 'Phoenix, AZ', {'distance': 1170}),
          ('Phoenix, AZ', 'Los Angeles, CA', {'distance': 380}),
          ('Los Angeles, CA', 'Dallas, TX', {'distance': 1240}),
          ('Los Angeles, CA', 'Chicago, IL', {'distance': 2010})]
 
 # Add the edges to the graph
 G.add_edges_from(edges)

运行起来没有报错,但是我们不知道数据是什么样子的,所以让我们先进行可视化,了解数据:

 importmatplotlib.pyplotasplt
 
 # set positions for the nodes (optional)
 pos=nx.spring_layout(G)
 
 # draw the nodes and edges
 nx.draw_networkx_nodes(G, pos, node_color='lightblue', node_size=500)
 nx.draw_networkx_edges(G, pos, edge_color='gray', width=2)
 
 # draw edge labels
 edge_labels=nx.get_edge_attributes(G, 'weight')
 nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
 
 # draw node labels
 node_labels= {node: node.split(',')[0] fornodeinG.nodes()}
 nx.draw_networkx_labels(G, pos, labels=node_labels)
 
 # show the plot
 plt.axis('off')
 plt.show()

我们有了一个基本的节点网络。但是这感觉太简单了。对于一个强化学习代理来说,这基本上没有难度,所以我们增加更多的节点:

这样就复杂多了,但是它看起来很混乱,比如从New York 到 Arizona就可能是一个挑战。

我们这里使用最常见且通用的Q-Learning来解决这个问题,因为它有动作-状态对矩阵,可以帮助确定最佳的动作。在寻找图中最短路径的情况下,Q-Learning可以通过迭代更新每个状态-动作对的q值来确定两个节点之间的最优路径。

上图为q值的演示。

下面我们开始实现自己的Q-Learning

 importnetworkxasnx
 importnumpyasnp
 
 defq_learning_shortest_path(G, start_node, end_node, learning_rate=0.8, discount_factor=0.95, epsilon=0.2, num_episodes=1000):
     """
     Calculates the shortest path in a graph G using Q-learning algorithm.
 
     Parameters:
         G (networkx.Graph): the graph
         start_node: the starting node
         end_node: the destination node
         learning_rate (float): the learning rate (default=0.8)
         discount_factor (float): the discount factor (default=0.95)
         epsilon (float): the exploration factor (default=0.2)
         num_episodes (int): the number of episodes (default=1000)
 
     Returns:
         A list with the shortest path from start_node to end_node.
     """

我们的输入是整个的图,还有开始和结束的节点,首先就需要提取每个节点之间的距离,将其提供给Q-learning算法。

 # Extract nodes and edges data
     nodes=list(G.nodes())
     num_nodes=len(nodes)
     edges=list(G.edges(data=True))
     num_edges=len(edges)
     edge_distances=np.zeros((num_nodes, num_nodes))
     fori, j, datainedges:
         edge_distances[nodes.index(i), nodes.index(j)] =data['weight']
         edge_distances[nodes.index(j), nodes.index(i)] =data['weight']

创建一个Q-table ,这样我们就可以在不断更新模型的同时更新值。

 # Initialize Q-values table
     q_table=np.zeros((num_nodes, num_nodes))
     
     # Convert start and end node to node indices
     start_node_index=nodes.index(start_node)
     end_node_index=nodes.index(end_node)

下面就是强化学习算法的核心!

 # Q-learning algorithm
     forepisodeinrange(num_episodes):
         current_node=start_node_index
         print(episode)
         whilecurrent_node!=end_node_index:
             # Choose action based on epsilon-greedy policy
             ifnp.random.uniform(0, 1) <epsilon:
                 # Explore
                 possible_actions=np.where(edge_distances[current_node,:] >0)[0]
                 iflen(possible_actions) ==0:
                     break
                 action=np.random.choice(possible_actions)
             else:
                 # Exploit
                 possible_actions=np.where(q_table[current_node,:] ==np.max(q_table[current_node,:]))[0]
                 iflen(possible_actions) ==0:
                     break
                 action=np.random.choice(possible_actions)
 
             # Calculate reward and update Q-value
             next_node=action
             reward=-edge_distances[current_node, next_node]
             q_table[current_node, next_node] = (1-learning_rate) *q_table[current_node, next_node] +learning_rate* (reward+discount_factor*np.max(q_table[next_node, :]))
             # Move to next node
             current_node=next_node
             ifcurrent_node==end_node_index:
                 break
     print(q_table)

这里需要注意的事情是,我们鼓励模型探索还是利用一个特定的路径。

大多数强化算法都是基于这种简单的权衡制定的。 过多的探索的问题在于它可能导致代理花费太多时间探索环境,而没有足够的时间利用它已经学到的知识,可能导致代理采取次优行动并最终无法实现其目标。 如果探索率设置得太高,代理可能永远不会收敛到最优策略。但是如果探索率设置得太低,代理可能会陷入次优策略。 所以,需要在探索和利用之间取得平衡,确保代理进行足够的探索以了解环境,同时利用其知识来最大化回报。

而强化学习中过多利用的问题会使代理陷入次优策略,无法发现可能更好的动作或状态。 即使有更好的选择,代理也可能对其当前的政策过于自信。 这被称为“漏洞利用陷阱”或“局部最优”问题,代理无法从次优解决方案中逃脱。 在这种情况下,探索有助于发现更好的策略和避免“局部最优”。

回到我们的代码,我们需要检查Q-table ,并确保可以从中提取出最短路径。

 # Extract shortest path from Q-values table
     shortest_path= [start_node]
     current_node=start_node_index
     whilecurrent_node!=end_node_index:
         next_node=np.argmax(q_table[current_node, :])
         shortest_path.append(nodes[next_node])
         current_node=next_node
     shortest_path.append(end_node)
     returnshortest_path

最后,使用函数来检查否能够得到所需的输出。

 shortest_path=q_learning_shortest_path(G, 'New York, NY', 'Phoenix, AZ')
 print(shortest_path)

输出结果如下:

这就是我们数据中从New York, NY到Phoenix, AZ的最短路径!

如果你感兴趣或者想了解更多,可以在这个链接中查看完整的代码。

https://avoid.overfit.cn/post/a4d722175b984e39a8317a7fc44e8cd6

作者:Amos Eda

目录
相关文章
|
2月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
83 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
2月前
|
机器学习/深度学习 算法 机器人
多代理强化学习综述:原理、算法与挑战
多代理强化学习是强化学习的一个子领域,专注于研究在共享环境中共存的多个学习代理的行为。每个代理都受其个体奖励驱动,采取行动以推进自身利益;在某些环境中,这些利益可能与其他代理的利益相冲突,从而产生复杂的群体动态。
205 5
|
4月前
|
机器学习/深度学习 算法 TensorFlow
深入探索强化学习与深度学习的融合:使用TensorFlow框架实现深度Q网络算法及高效调试技巧
【8月更文挑战第31天】强化学习是机器学习的重要分支,尤其在深度学习的推动下,能够解决更为复杂的问题。深度Q网络(DQN)结合了深度学习与强化学习的优势,通过神经网络逼近动作价值函数,在多种任务中表现出色。本文探讨了使用TensorFlow实现DQN算法的方法及其调试技巧。DQN通过神经网络学习不同状态下采取动作的预期回报Q(s,a),处理高维状态空间。
61 1
|
4月前
|
机器学习/深度学习 存储 算法
强化学习实战:基于 PyTorch 的环境搭建与算法实现
【8月更文第29天】强化学习是机器学习的一个重要分支,它让智能体通过与环境交互来学习策略,以最大化长期奖励。本文将介绍如何使用PyTorch实现两种经典的强化学习算法——Deep Q-Network (DQN) 和 Actor-Critic Algorithm with Asynchronous Advantage (A3C)。我们将从环境搭建开始,逐步实现算法的核心部分,并给出完整的代码示例。
279 1
|
4月前
|
自然语言处理 算法
HanLP — HMM隐马尔可夫模型 - 路径规划算法 - 求解最短路径 - 维特比(Viterbi)算法
HanLP — HMM隐马尔可夫模型 - 路径规划算法 - 求解最短路径 - 维特比(Viterbi)算法
61 0
HanLP — HMM隐马尔可夫模型 - 路径规划算法 - 求解最短路径 - 维特比(Viterbi)算法
|
4月前
|
测试技术 数据库
探索JSF单元测试秘籍!如何让您的应用更稳固、更高效?揭秘成功背后的测试之道!
【8月更文挑战第31天】在 JavaServer Faces(JSF)应用开发中,确保代码质量和可维护性至关重要。本文详细介绍了如何通过单元测试实现这一目标。首先,阐述了单元测试的重要性及其对应用稳定性的影响;其次,提出了提高 JSF 应用可测试性的设计建议,如避免直接访问外部资源和使用依赖注入;最后,通过一个具体的 `UserBean` 示例,展示了如何利用 JUnit 和 Mockito 框架编写有效的单元测试。通过这些方法,不仅能够确保代码质量,还能提高开发效率和降低维护成本。
54 0
|
5月前
|
算法 Java
Java语言实现最短路径算法(Shortest Path)
Java语言实现最短路径算法(Shortest Path)
62 3
|
5月前
|
机器学习/深度学习 存储 数据采集
强化学习系列:A3C算法解析
【7月更文挑战第13天】A3C算法作为一种高效且广泛应用的强化学习算法,通过结合Actor-Critic结构和异步训练的思想,实现了在复杂环境下的高效学习和优化策略的能力。其并行化的训练方式和优势函数的引入,使得A3C算法在解决大规模连续动作空间和高维状态空间的问题上表现优异。未来,随着技术的不断发展,A3C算法有望在更多领域发挥重要作用,推动强化学习技术的进一步发展。
|
4月前
|
算法 定位技术
路径规划算法 - 求解最短路径 - A*(A-Star)算法
路径规划算法 - 求解最短路径 - A*(A-Star)算法
101 0
|
4月前
|
算法
路径规划算法 - 求解最短路径 - Dijkstra(迪杰斯特拉)算法
路径规划算法 - 求解最短路径 - Dijkstra(迪杰斯特拉)算法
75 0