commit 161b7a0eea76ab096a49189f38df19c537016e25 Author: fly6516 Date: Sun Mar 30 02:52:03 2025 +0800 feat: 添加聚类算法和 Q 学习算法 - 新增 clustering_algorithms.py 文件,实现 K 均值和 K 中心点聚类算法 - 新增 route.py 文件,实现基于 Q学习的路径规划算法 - 添加分析聚类结果和可视化功能 - 实现并行 Q学习训练,提高训练效率 diff --git a/clustering_algorithms.py b/clustering_algorithms.py new file mode 100644 index 0000000..179c75b --- /dev/null +++ b/clustering_algorithms.py @@ -0,0 +1,77 @@ +# 导入必要的库 +import numpy as np +from sklearn.datasets import load_iris +from sklearn.cluster import KMeans +from sklearn_extra.cluster import KMedoids +from sklearn.metrics import silhouette_score +import matplotlib.pyplot as plt +import matplotlib +import os +import psutil + +# 设置环境变量以消除Joblib警告 +os.environ['LOKY_MAX_CPU_COUNT'] = str(psutil.cpu_count(logical=False)) + +# 设置Matplotlib支持中文的字体 +matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体 +matplotlib.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 + +# 加载Iris数据集 +iris = load_iris() +X = iris.data # 特征数据 +y = iris.target # 目标标签 + +# K均值聚类算法 +def kmeans_clustering(X, n_clusters=3): + """ + 使用K均值算法对数据进行聚类 + :param X: 输入数据 + :param n_clusters: 聚类数量 + :return: 聚类标签 + """ + kmeans = KMeans(n_clusters=n_clusters, random_state=42) # 初始化KMeans对象 + kmeans.fit(X) # 拟合数据 + labels = kmeans.labels_ # 获取聚类标签 + return labels + +# K中心点聚类算法 +def kmedoids_clustering(X, n_clusters=3): + """ + 使用K中心点算法对数据进行聚类 + :param X: 输入数据 + :param n_clusters: 聚类数量 + :return: 聚类标签 + """ + kmedoids = KMedoids(n_clusters=n_clusters, random_state=42) # 初始化KMedoids对象 + kmedoids.fit(X) # 拟合数据 + labels = kmedoids.labels_ # 获取聚类标签 + return labels + +# 分析聚类结果 +def analyze_clustering(X, labels, algorithm_name): + """ + 分析聚类结果并可视化 + :param X: 输入数据 + :param labels: 聚类标签 + :param algorithm_name: 算法名称 + """ + silhouette_avg = silhouette_score(X, labels) # 计算轮廓系数 + print(f"{algorithm_name} 轮廓系数: {silhouette_avg}") + + # 可视化聚类结果 + plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis') + plt.title(f"{algorithm_name} 聚类结果") + plt.show() + +# 主函数 +def main(): + # 使用K均值算法进行聚类 + kmeans_labels = kmeans_clustering(X) + analyze_clustering(X, kmeans_labels, "K均值") + + # 使用K中心点算法进行聚类 + kmedoids_labels = kmedoids_clustering(X) + analyze_clustering(X, kmedoids_labels, "K中心点") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/myplot-1.png b/myplot-1.png new file mode 100644 index 0000000..407f587 Binary files /dev/null and b/myplot-1.png differ diff --git a/myplot-2.png b/myplot-2.png new file mode 100644 index 0000000..6ace5a4 Binary files /dev/null and b/myplot-2.png differ diff --git a/route.py b/route.py new file mode 100644 index 0000000..6055782 --- /dev/null +++ b/route.py @@ -0,0 +1,97 @@ +import numpy as np # Import NumPy for numerical operations +import random # Import random module for exploration +import multiprocessing as mp # Import multiprocessing for parallel computing +#import cupy as cp + + +try: + import cupy as cp # Import CuPy for GPU acceleration + + GPU_AVAILABLE = True # Set flag if CuPy is available +except ImportError: + GPU_AVAILABLE = False # Set flag if CuPy is not available + +# Define the environment +grid_size = (4, 4) # Grid size (4x4) +start = (0, 0) # Start position +end = (3, 3) # End position +obstacles = {(1, 0), (2, 1), (1, 2), (0, 3), (3, 2)} # Set of obstacles + +# Define possible actions and their effects on position +actions = {'up': (-1, 0), 'down': (1, 0), 'left': (0, -1), 'right': (0, 1)} + + +def is_valid(state): + """Check if a state is within the grid and not an obstacle.""" + return (0 <= state[0] < grid_size[0]) and (0 <= state[1] < grid_size[1]) and (state not in obstacles) + + +def get_next_state(state, action): + """Get the next state based on the current state and action.""" + new_state = (state[0] + actions[action][0], state[1] + actions[action][1]) + return new_state if is_valid(new_state) else state + + +# Q-Learning parameters +alpha = 0.5 # Learning rate +gamma = 0.9 # Discount factor +epsilon = 0.1 # Increased exploration rate for better exploration +episodes = 5000 # Increased total training episodes for better learning +np.random.seed(42) # Set random seed for reproducibility +random.seed(42) + +# Initialize the Q-table with all states and actions +grid_states = [(i, j) for i in range(grid_size[0]) for j in range(grid_size[1]) if (i, j) not in obstacles] +Q = {state: {action: 0 for action in actions} for state in grid_states} + +# GPU acceleration setup (if available) +if GPU_AVAILABLE: + Q = {state: {action: 0.0 for action in actions} for state in grid_states} # Initialize Q-table on GPU + actions_list = list(actions.keys()) # Store actions as a list + +def train_q_learning(_): + """Function to train Q-learning in parallel using multiple processes.""" + local_Q = {state: Q[state].copy() for state in grid_states} # Create a local copy of Q-table + for _ in range(episodes // mp.cpu_count()): # Each process handles a fraction of episodes + state = start # Start at the initial position + while state != end: # Run until reaching the goal + # Choose an action using ε-greedy policy + action = max(local_Q[state], key=local_Q[state].get) if random.uniform(0, 1) > epsilon else random.choice( + list(actions)) + next_state = get_next_state(state, action) # Get the next state + reward = 1 if next_state == end else -0.1 # Define rewards + # Update Q-value using the Bellman equation + local_Q[state][action] += alpha * ( + reward + gamma * max(local_Q[next_state].values()) - local_Q[state][action]) + state = next_state # Move to next state + return local_Q # Return the updated local Q-table + +# Parallel Q-learning training +if __name__ == "__main__": + num_processes = max(1, mp.cpu_count() // 2) # Use half the available CPU cores + with mp.Pool(num_processes) as pool: # Create a process pool with reduced number of CPU cores + results = pool.map(train_q_learning, range(num_processes)) # Distribute training across multiple processes + + # Merge Q-tables from all processes + for state in grid_states: + for action in actions: + Q[state][action] = sum(r[state][action] for r in results) / len(results) # Average Q-values + + +# Compute the optimal path from start to end +def get_best_path(): + """Find the best path using the learned Q-values.""" + state = start # Start at the initial position + path = [state] # Initialize path + visited = set() # Track visited states to avoid loops + while state != end: + if state in visited: + break # Avoid infinite loops + visited.add(state) # Mark state as visited + action = max(Q[state], key=Q[state].get) # Choose the best action based on Q-values + state = get_next_state(state, action) # Move to the next state + path.append(state) # Append to path + return path # Return the computed path + + +print(get_best_path()) # Print the optimal path \ No newline at end of file