import numpy as np import os # KNN分类算法 def classify(input_vector, dataSet, labels, k=3, distance_metric='euclidean', weighted=False): """ KNN 分类算法。 Args: - input_vector (numpy array): 输入待分类的样本。 - dataSet (numpy array): 训练数据集。 - labels (list or numpy array): 训练集对应的标签。 - k (int): kNN 参数,默认为3。 - distance_metric (str): 距离度量方法,默认为'euclidean'。可选'manhattan', 'mahalanobis'。 - weighted (bool): 是否使用加权KNN。默认为False。 Returns: - int: 预测的分类标签。 """ if distance_metric == 'euclidean': distances = np.linalg.norm(dataSet - input_vector, axis=1) elif distance_metric == 'manhattan': distances = np.sum(np.abs(dataSet - input_vector), axis=1) elif distance_metric == 'mahalanobis': cov_matrix = np.cov(dataSet.T) inv_cov_matrix = np.linalg.inv(cov_matrix) delta = dataSet - input_vector distances = np.sqrt(np.einsum('ij,jk,ik->i', delta, inv_cov_matrix, delta)) else: raise ValueError("Unsupported distance metric") nearest_neighbors_indices = distances.argsort()[:k] nearest_labels = np.array(labels)[nearest_neighbors_indices] if weighted: weights = 1 / (distances[nearest_neighbors_indices] + 1e-5) # 防止除0错误 weighted_votes = np.bincount(nearest_labels, weights=weights) predicted_label = weighted_votes.argmax() else: predicted_label = np.bincount(nearest_labels).argmax() return predicted_label # 从文件夹加载数据 def load_dataset(directory): labels = [] data_list = [] for filename in os.listdir(directory): if filename.endswith(".txt"): # 确保读取的是 txt 文件 label = int(filename.split('_')[0]) labels.append(label) vector = img_to_vector(os.path.join(directory, filename)) data_list.append(vector) return np.array(data_list), np.array(labels) # 将二值图像转换为向量 def img_to_vector(filename): with open(filename, 'r') as f: # 确保使用文本模式读取 lines = f.readlines() vector = np.zeros((1024,), dtype=int) # 将其改为 (1024,) 的一维数组 for i in range(32): for j in range(32): vector[32 * i + j] = int(lines[i][j]) return vector # 测试代码 if __name__ == "__main__": train_data, train_labels = load_dataset("trainingDigits") test_data = ( "00000000000000110000000000000000" "00000000000011111000000000000000" # ... 中间数据省略 ... "00000000000001111111110000000000" "00000000000000000111100000000000" ) test_vector = np.array([int(char) for char in test_data]).reshape(1, 1024) predicted_label = classify(test_vector, train_data, train_labels, k=5, distance_metric='manhattan', weighted=True) print(f"预测的标签: {predicted_label}")