Files
Experiment-kNN/function.py
T
lzh 19665a8133
Gitea Actions Experiment Test / Experiment-Actions (push) Successful in 10s
11
2024-10-16 23:44:59 +08:00

152 lines
5.7 KiB
Python

# function.py
import numpy as np
from collections import Counter
import os
"""
实验说明:
- 自行编写实现数据加载与 kNN 的手写数字分类算法。
- 函数输入: 待分类的样本 input_vector, 训练数据集 dataSet, 训练集对应的标签 labels。
- 函数返回: 预测的分类标签。
注意事项:
- 在 function.py 中实现 kNN 分类算法。
- 可以自行导入其他库,需要在 requirements.txt 添加依赖,若未在 requirements.txt 中添加使用到的依赖,则无法自动评测,成绩为零。
- 自动评测脚本仅会加载 classify 和 load_data 函数,请勿修改函数名。
- 训练集和测试集需手动下载解压,并放入当前目录下。
测评环境:
- CPU: Intel Xeon(R) CPU E3-1231 v3 @ 3.40GHz
- OS: Ubuntu 22.04.4 LTS
- Python: 3.10.12
- numpy: 2.1.1
"""
"""
请在这里填写学号和姓名,不填写即成绩无效。
"""
id = "202210423221"
name = "廖子豪"
"""
参数说明:
- input_vector (numpy array): 输入待分类的样本。
- dataSet (numpy array): 训练数据集。
- labels (list or numpy array): 训练集对应的标签。
- k (int): kNN 算法参数,请**自行设置默认值**,评测时仅会使用其默认值,不修改默认值将**无法通过**评测,**成绩为零**。
返回值:
- int: 预测的分类标签。
"""
# 这里写自己的代码实现
import numpy as np
import os
from collections import Counter
def img_to_vector(filename):
"""
将二值图像转换为向量。
Args:
- filename (str): 图像文件路径。
Returns:
- np.array: 二值图像向量。
"""
with open(filename, 'r') as file:
lines = file.readlines()
vector = [int(pixel) for line in lines for pixel in line.strip()]
return np.array(vector)
def load_dataset(directory):
"""
从文件夹中加载数据。
Args:
- directory (str): 数据文件夹路径。
Returns:
- np.array: 特征数据。
- np.array: 标签数据。
"""
images = []
labels = []
for label_dir in os.listdir(directory):
label_dir_path = os.path.join(directory, 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)
images.append(image_vector)
labels.append(int(label_dir))
return np.array(images), 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。
Returns:
- int: 预测的分类标签。
"""
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]
if __name__ == "__main__":
train_dir = "trainingDigits" # 训练集目录
test_dir = "testDigits" # 测试集目录
train_images, train_labels = load_dataset(train_dir)
test_images, test_labels = load_dataset(test_dir)
print("训练集特征形状:", train_images.shape)
print("训练集标签形状:", train_labels.shape)
print("测试集特征形状:", test_images.shape)
print("测试集标签形状:", test_labels.shape)
# 测试 classify 函数
test_data = np.array([int(char) for char in "00000000000000110000000000000000000" # 示例数据
"00000000000011111000000000000000"
"00000000000011111100000000000000"
"00000000001111111110000000000000"
"00000000001111111110000000000000"
"00000000001111111100000000000000"
"00000000011111111000000000000000"
"00000000111111111000000000000000"
"00000000111111110000000000000000"
"00000000111111110000000000000000"
"00000000111111110000000000000000"
"00000000111111110000000000000000"
"00000000111111100000000000000000"
"00000001111111100000000000000000"
"00000001111111100000000000000000"
"00000001111111100000000000000000"
"00000001111111111111000000000000"
"00000001111111111111111000000000"
"00000001111111111111111100000000"
"00000011111111111111111110000000"
"00000011111111111111111110000000"
"00000001111111111111111110000000"
"00000001111111111111111110000000"
"00000000111111111100111111100000"
"00000000111111111000111111100000"
"00000000011111111001111111100000"
"00000000011111111111111111000000"
"00000000001111111111111111000000"
"00000000000111111111111111000000"
"00000000000011111111111100000000"
"00000000000001111111110000000000"
"00000000000000000111100000000000"] * 4).reshape(1, 1024)
predicted_label = classify(test_data, train_images, train_labels)
print(f"预测的标签: {predicted_label}")