21
Gitea Actions Experiment Test / Experiment-Actions (push) Successful in 22s

This commit is contained in:
lzh
2024-10-17 00:10:40 +08:00
parent 7911f5d792
commit f7476b362a
+119 -69
View File
@@ -41,79 +41,123 @@ name = "廖子豪"
# 这里写自己的代码实现
import numpy as np
import os
from collections import Counter
def classify(input_vector, dataSet, labels, k_values=[1,31]):
"""
KNN 加权投票分类算法,针对多个k值进行预测,并选出不同k值下得票最多的类别。
def img_to_vector(filename):
"""
将二值图像转换为向量。
Args:
- filename (str): 图像文件路径。
Returns:
- np.array: 二值图像向量。
"""
with open(filename, 'r') as file:
return np.array([int(char) for line in file for char in line.strip()])
def load_dataset(directory):
"""
从文件夹中加载数据。
Args:
- directory (str): 数据文件夹路径。
Returns:
- np.array: 特征数据。
- np.array: 标签数据。
"""
features = []
labels = []
for label_dir in os.listdir(directory):
label_dir_path = os.path.join(directory, str(label_dir))
if os.path.isdir(label_dir_path):
for filename in os.listdir(label_dir_path):
file_path = os.path.join(label_dir_path, filename)
image_vector = img_to_vector(file_path)
features.append(image_vector)
labels.append(int(label_dir))
return np.array(features), np.array(labels)
def classify(input_vector, dataSet, labels, k=3):
"""
KNN 分类算法。
Args:
- input_vector (numpy array): 输入待分类的样本。
- dataSet (numpy array): 训练数据集。
- labels (list or numpy array): 训练集对应的标签。
- k (int): kNN 算法参数,默认值为 3。
- k_values (list of int): 多个kNN 算法的k值列表。
Returns:
- int: 预测的分类标签。
- int: 预测的分类标签(基于多个k值投票的结果)。
"""
distances = np.sqrt(np.sum((input_vector - dataSet) ** 2, axis=1))
k_indices = np.argsort(distances)[:k]
k_nearest_labels = labels[k_indices]
label_count = Counter(k_nearest_labels)
return label_count.most_common(1)[0][0]
num_samples = dataSet.shape[0] # 读取样本数量
# step 1: 计算欧式距离
diff = np.tile(input_vector, (num_samples, 1)) - dataSet # 元素逐个相减
squared_diff = diff ** 2 # 平方
squared_dist = np.sum(squared_diff, axis=1) # 按行求和
distance = squared_dist ** 0.5 # 计算欧式距离
# step 2: 对距离进行排序,返回排序后的索引
sorted_dist_indices = np.argsort(distance)
# 保存每个k值对应的预测结果
vote_results = []
for k in k_values:
class_count = {} # 定义一个空字典
for i in range(k):
# step 3: 选择距离最小的k个样本
vote_label = labels[sorted_dist_indices[i]]
dist = distance[sorted_dist_indices[i]]
# step 4: 使用距离倒数作为权重(避免除0,设置一个最小距离)
weight = 1 / (dist + 1e-5) # 添加一个小常数避免除以0
# step 5: 进行加权投票
class_count[vote_label] = class_count.get(vote_label, 0) + weight
# step 6: 找到加权后得票最多的类别作为该k值的预测结果
max_vote = max(class_count, key=class_count.get)
vote_results.append(max_vote)
# step 7: 对所有k值的预测结果进行投票,统计出现次数最多的标签
final_vote_count = {}
for result in vote_results:
final_vote_count[result] = final_vote_count.get(result, 0) + 1
# step 8: 返回得票最多的类别作为最终分类结果
final_result = max(final_vote_count, key=final_vote_count.get)
return final_result
# 这里也写自己的代码实现
def load_dataset(directory):
"""
从文件夹中加载数据,若不自行正确实现,则无法通过评测,**不记录成绩**。
Args:
- directory (str): 数据文件夹路径。
Returns:
- np.array: 特征数据。
- np.array: 标签数据。
"""
"""
从文件夹中加载数据。
Args:
- directory (str): 数据文件夹路径。
Returns:
- np.array: 特征数据。
- np.array: 标签数据。
"""
labels = []
file_list = os.listdir(directory)
num_samples = len(file_list)
dataset = np.zeros((num_samples, 1024))
for i, filename in enumerate(file_list):
label = int(filename.split("_")[0]) # 从文件名中提取标签
labels.append(label)
dataset[i, :] = img_to_vector(os.path.join(directory, filename))
return dataset, np.array(labels)
# 这里还写自己的代码实现
def img_to_vector(filename):
"""
将二值图像转换为向量。
该部分应为 load_dataset 函数的辅助子函数,可单独在这里实现,也可直接集成至 load_dataset 函数中。
Args:
- filename (str): 图像文件路径。
Returns:
- np.array: 二值图像向量。
"""
rows = 32
columns = 32
img_vector = np.zeros((1, rows * columns))
file_in = open(filename)
for row in range(rows):
line_str = file_in.readline()
for col in range(columns):
img_vector[0, row * 32 + col] = int(line_str[col])
return img_vector
if __name__ == "__main__":
train_dir = "trainingDigits" # 训练集目录
test_dir = "testDigits" # 测试集目录
train_data, train_labels = load_dataset(train_dir)
test_data, test_labels = load_dataset(test_dir)
print("训练集特征形状:", train_data.shape)
print("训练集标签形状:", train_labels.shape)
print("测试集特征形状:", test_data.shape)
print("测试集标签形状:", test_labels.shape)
# 测试 classify 函数
test_data_vector = np.array([int(char) for char in (
# 以下代码可用于测试,可自行随意修改
train_data, train_labels = load_dataset("trainingDigits")
test_data = (
"00000000000000110000000000000000"
"00000000000011111000000000000000"
"00000000000011111100000000000000"
@@ -132,8 +176,9 @@ if __name__ == "__main__":
"00000001111111100000000000000000"
"00000001111111111111000000000000"
"00000001111111111111111000000000"
"00000011111111111111111100000000"
"00000011111111111111111100000000"
"00000001111111111111111100000000"
"00000011111111111111111110000000"
"00000011111111111111111110000000"
"00000001111111111111111110000000"
"00000001111111111111111110000000"
"00000000111111111100111111100000"
@@ -145,6 +190,11 @@ if __name__ == "__main__":
"00000000000011111111111100000000"
"00000000000001111111110000000000"
"00000000000000000111100000000000"
)]).reshape(1, 1024)
predicted_label = classify(test_data_vector, train_data, train_labels)
print(f"预测的标签: {predicted_label}")
)
predicted_label = classify(
np.array([int(char) for char in test_data]).reshape(1, 1024),
train_data,
train_labels,
)
print(f"预测的标签: {predicted_label}")