以下是一个增强版的将 A* 算法与卷积神经网络(CNN)结合的代码实现,其中 CNN 增加了卷积层的数量,并对卷积核大小进行了调整。整体思路依然是先利用 A* 算法生成训练数据,再用这些数据训练 CNN 模型,最后使用训练好的模型进行路径规划。
python
import numpy as np
import heapq
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
# A* 算法实现
class Node:
def __init__(self, x, y, g=float('inf'), h=float('inf'), parent=None):
self.x = x
self.y = y
self.g = g
self.h = h
self.f = g + h
self.parent = parent
def __lt__(self, other):
return self.f < other.f
def heuristic(current, goal):
return abs(current[0] - goal[0]) + abs(current[1] - goal[1])
def astar(grid, start, goal):
rows, cols = grid.shape
open_list = []
closed_set = set()
start_node = Node(start[0], start[1], g=0, h=heuristic(start, goal))
heapq.heappush(open_list, start_node)
while open_list:
current_node = heapq.heappop(open_list)
if (current_node.x, current_node.y) == goal:
path = []
while current_node:
path.append((current_node.x, current_node.y))
current_node = current_node.parent
return path[::-1]
closed_set.add((current_node.x, current_node.y))
neighbors = [(0, 1), (0, -1), (1, 0), (-1, 0)]
for dx, dy in neighbors:
new_x, new_y = current_node.x + dx, current_node.y + dy
if 0 <= new_x < rows and 0 <= new_y < cols and grid[new_x][new_y] == 0 and (new_x, new_y) not in closed_set:
new_g = current_node.g + 1
new_h = heuristic((new_x, new_y), goal)
new_node = Node(new_x, new_y, g=new_g, h=new_h, parent=current_node)
found = False
for i, node in enumerate(open_list):
if node.x == new_x and node.y == new_y:
if new_g < node.g:
open_list[i] = new_node
heapq.heapify(open_list)
found = True
break
if not found:
heapq.heappush(open_list, new_node)
return None
# 生成训练数据
def generate_training_data(grid, num_samples):
rows, cols = grid.shape
inputs = []
outputs = []
for _ in range(num_samples):
start = (np.random.randint(0, rows), np.random.randint(0, cols))
goal = (np.random.randint(0, rows), np.random.randint(0, cols))
path = astar(grid, start, goal)
if path:
input_data = np.zeros((1, rows, cols))
input_data[0, start[0], start[1]] = 1
input_data[0, goal[0], goal[1]] = 2
output_data = np.zeros((1, rows, cols))
for point in path:
output_data[0, point[0], point[1]] = 1
inputs.append(input_data)
outputs.append(output_data)
return np.array(inputs), np.array(outputs)
# 自定义数据集类
class PathDataset(Dataset):
def __init__(self, inputs, outputs):
self.inputs = torch.tensor(inputs, dtype=torch.float32)
self.outputs = torch.tensor(outputs, dtype=torch.float32)
def __len__(self):
return len(self.inputs)
def __getitem__(self, idx):
return self.inputs[idx], self.outputs[idx]
# 定义增强版卷积神经网络模型
class EnhancedPathCNN(nn.Module):
def __init__(self):
super(EnhancedPathCNN, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=5, padding=2)
self.relu1 = nn.ReLU()
self.conv2 = nn.Conv2d(32, 64, kernel_size=5, padding=2)
self.relu2 = nn.ReLU()
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
self.relu3 = nn.ReLU()
self.conv4 = nn.Conv2d(128, 64, kernel_size=3, padding=1)
self.relu4 = nn.ReLU()
self.conv5 = nn.Conv2d(64, 1, kernel_size=3, padding=1)
def forward(self, x):
x = self.relu1(self.conv1(x))
x = self.relu2(self.conv2(x))
x = self.relu3(self.conv3(x))
x = self.relu4(self.conv4(x))
x = self.conv5(x)
return x
# 训练神经网络
def train_model(model, dataloader, criterion, optimizer, epochs):
for epoch in range(epochs):
running_loss = 0.0
for inputs, labels in dataloader:
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f'Epoch {epoch + 1}, Loss: {running_loss / len(dataloader)}')
# 主程序
if __name__ == "__main__":
# 示例地图
map_grid = np.array([
[0, 0, 0, 0, 0],
[0, 1, 1, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 1, 1, 0],
[0, 0, 0, 0, 0]
])
# 生成训练数据
num_samples = 1000
inputs, outputs = generate_training_data(map_grid, num_samples)
# 创建数据集和数据加载器
dataset = PathDataset(inputs, outputs)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
# 初始化增强版 CNN 模型
model = EnhancedPathCNN()
# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 训练模型
epochs = 10
train_model(model, dataloader, criterion, optimizer, epochs)
# 使用训练好的模型进行路径规划
start = (0, 0)
goal = (4, 4)
input_data = np.zeros((1, 1, map_grid.shape[0], map_grid.shape[1]))
input_data[0, 0, start[0], start[1]] = 1
input_data[0, 0, goal[0], goal[1]] = 2
input_tensor = torch.tensor(input_data, dtype=torch.float32)
output = model(input_tensor)
output_path = output.detach().numpy()[0, 0]
path_points = np.argwhere(output_path > 0.5)
print("增强版 CNN 预测的路径点:", path_points)
代码解释
1. A* 算法部分
这部分和之前的实现基本一致,Node
类用于表示地图中的节点,heuristic
函数计算启发式代价,astar
函数通过维护开放列表和关闭列表来搜索从起点到终点的最短路径。
2. 数据生成部分
generate_training_data
函数随机生成起点和终点,调用 A* 算法计算路径,将起点、终点信息作为输入,路径信息作为输出,生成训练数据。
3. 数据集和数据加载器部分
PathDataset
类继承自 torch.utils.data.Dataset
,用于封装训练数据,DataLoader
用于批量加载数据并支持随机打乱。
4. 增强版卷积神经网络部分
EnhancedPathCNN
类定义了一个更复杂的 CNN 模型,增加了卷积层的数量,同时调整了卷积核的大小。具体来说,前两层使用 5x5 的卷积核,后三层使用 3x3 的卷积核,每层卷积后都接一个 ReLU 激活函数,最后一层卷积输出单通道的预测路径。train_model
函数使用均方误差损失函数(nn.MSELoss
)和 Adam 优化器对模型进行训练,在多个 epoch 中不断更新模型参数。
5. 主程序部分
定义示例地图,生成训练数据,创建数据集和数据加载器,初始化增强版 CNN 模型,定义损失函数和优化器,训练模型,最后使用训练好的模型进行路径规划并输出预测的路径点。
注意事项
- 增加卷积层和调整卷积核大小可能会增加模型的复杂度和训练时间,需要确保有足够的计算资源和训练数据。
- 可以根据实际情况进一步调整模型结构、卷积核大小、学习率等超参数,以获得更好的性能。
- CNN 模型预测的路径不一定是最优路径,A* 算法能保证最优路径,但 CNN 可以在效率上有一定提升。