From ed5c09ef1993beba11e9b433403e9b185baf06be Mon Sep 17 00:00:00 2001 From: llll <2992513220@qq.com> Date: Wed, 16 Oct 2024 20:45:41 +0800 Subject: [PATCH] Initial commit --- .gitea/workflows/test.yaml | 27 ++++++++ .gitignore | 6 ++ README.md | 77 ++++++++++++++++++++++ function.py | 131 +++++++++++++++++++++++++++++++++++++ requirements.txt | 2 + 5 files changed, 243 insertions(+) create mode 100644 .gitea/workflows/test.yaml create mode 100644 .gitignore create mode 100644 README.md create mode 100644 function.py create mode 100644 requirements.txt diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml new file mode 100644 index 0000000..536b340 --- /dev/null +++ b/.gitea/workflows/test.yaml @@ -0,0 +1,27 @@ +name: Gitea Actions Experiment Test +run-name: 实验自动评测 Actions 🚀 +on: [push] + +jobs: + Experiment-Actions: + runs-on: ubuntu-latest + steps: + - name: 检出代码 + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: 安装依赖 + run: | + python -m venv ./.venv + . ./.venv/bin/activate + curl -s -o pip_cache.tar.gz ${{ vars.BACKEND_URL }}/download/pip_cache.tar.gz + tar -zxf pip_cache.tar.gz + pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple + rm -rf testDigits trainingDigits main.py + curl -s -o main.py ${{ vars.BACKEND_URL }}/public/experiment/knn/main.py + curl -s -o dataSet.tar.gz ${{ vars.BACKEND_URL }}/public/experiment/knn/dataSet.tar.gz + tar -zxf dataSet.tar.gz + - name: 评测结果 + run: | + . ./.venv/bin/activate + python main.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b5a9d55 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +__pycache__ +main.py +testDigits +trainingDigits +dataSet.tar.gz +二值手写数字数据集* diff --git a/README.md b/README.md new file mode 100644 index 0000000..1d43673 --- /dev/null +++ b/README.md @@ -0,0 +1,77 @@ +# 实验一:kNN 与二值手写数字识别 + +## 实验说明 + +- 自行在 [`function.py`](./function.py) 中编写实现数据加载与 kNN 的手写数字分类算法。 +- 函数输入: 待分类的样本 `input_vector`, 训练数据集 `dataSet`, 训练集对应的标签 `labels`。 +- 函数返回: 预测的分类标签。 + +所有成功上传的评测结果均会被记录,但不会公开展示。 + +评测次数不限,最终评测成绩取**最高分**。 + +## 注意事项 + +挑战赛与实验为两个**不同**的仓库,注意不要混淆! + +- 实验仓库,开头名称统一为 `Experiment` + - **有截止时间限制**! + - 记录成绩但不公开,并且**是实验成绩的一部分**。 + - 最终成绩取最高分。 +- 挑战赛仓库,开头名称统一为 `Challenge` + - 无截止时间限制。 + - 公开展示排行榜和最近的评测信息。 + +--- + +实验开始前必须在 [`function.py`](./function.py#L28-L29) 中填写自己的学号和姓名! + +- 可以自行导入其他库,需要在 [`requirements.txt`](./requirements.txt) 添加依赖,若未在 [`requirements.txt`](./requirements.txt) 中添加使用到的依赖,则无法自动评测,**不记录成绩**。 +- 需要在 [`function.py`](./function.py) 中实现完整的 kNN 分类算法。 +- 默认 **k=0**,需**自行设置**最佳的默认 k 值,不修改默认值将**无法通过**自动评测,**成绩为零**。 +- 自动评测脚本仅会加载 `classify` 和 `load_data` 函数,请勿修改函数名。 +- 仓库内不自带数据集,本地调试时,数据集需自行下载。 +- 本地调试完成后,**需要更新提交代码**,否则无法自动评测,**没有实验成绩**。 +- 评测的运行时间受机器性能影响,运行时间仅供参考。 +- 若有评测相关问题,请在[项目工单](https://git.intcplab.cn/LufsX/Evaluation-Backend/issues)处提出,或联系 QQ: `1968647927`。 + +代码提交后会进行自动评测,评测所用的环境如下: + +- CPU: Intel Xeon(R) CPU E3-1231 v3 @ 3.40GHz +- OS: Ubuntu 22.04.4 LTS +- Python: 3.10.12 +- numpy: 2.1.1 + +## 实验操作 + +本次实验因数据文件较多,故仓库内不自带数据集,本地调试时需自行下载数据集。 + +- [二值手写数字数据集.zip](https://git.intcplab.cn/yuhuapeng/Machine-Learning-in-Python/raw/branch/main/%E7%AC%AC9%E7%AB%A0%209.1%20KNN%E5%88%86%E7%B1%BB%E5%99%A8/%E4%BA%8C%E5%80%BC%E6%89%8B%E5%86%99%E6%95%B0%E5%AD%97%E6%95%B0%E6%8D%AE%E9%9B%86.zip) +- [二值手写数字数据集.tar.gz](https://git.intcplab.cn/LufsX/Evaluation-Backend/raw/branch/main/public/experiment/knn/dataSet.tar.gz) + +以上两文件解压内容相同,解压后得到 `trainDigits` 和 `testDigits` 文件夹,分别存放训练集和测试集。 + +本次实验强烈建议将代码克隆/下载到本地进行实验调试。 + +--- + +命令行操作: + +```bash +curl -s -o dataSet.tar.gz https://git.intcplab.cn/LufsX/Evaluation-Backend/raw/branch/main/public/experiment/knn/dataSet.tar.gz +tar -zxvf dataSet.tar.gz +``` + +--- + +注意 ⚠️ + +若要完成实验,请确保是在**本页面**点击「使用模版」来创建仓库,新仓库名称建议与模版名称相同,其余操作参见[挑战赛的说明](https://git.intcplab.cn/LufsX/Challenge-kNN#挑战操作)。 + +若要完成实验,评测时检查创建完成的**仓库信息**是否正确,本次实验标题为「**实验一:KNN 与二值手写数字识别**」! + +## 其它 + +若有流程、优化等相关建议和问题,欢迎在[评测后端项目工单](https://git.intcplab.cn/LufsX/Evaluation-Backend/issues)中提出。 + +同时欢迎参与[评测后端](https://git.intcplab.cn/LufsX/Evaluation-Backend)的开发与优化! diff --git a/function.py b/function.py new file mode 100644 index 0000000..b1f8c16 --- /dev/null +++ b/function.py @@ -0,0 +1,131 @@ +# function.py +import numpy as np +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 = "202210423xxx" +name = "test_name" + + +""" +参数说明: +- input_vector (numpy array): 输入待分类的样本。 +- dataSet (numpy array): 训练数据集。 +- labels (list or numpy array): 训练集对应的标签。 +- k (int): kNN 算法参数,请**自行设置默认值**,评测时仅会使用其默认值,不修改默认值将**无法通过**评测,**成绩为零**。 +返回值: +- int: 预测的分类标签。 +""" + + +# 这里写自己的代码实现 +def classify(input_vector, dataSet, labels, k=0): + """ + KNN 分类算法。 + + Args: + - input_vector (numpy array): 输入待分类的样本。 + - dataSet (numpy array): 训练数据集。 + - labels (list or numpy array): 训练集对应的标签。 + - k (int): kNN 算法参数,请**自行设置默认值**,评测时仅会使用其默认值,不修改默认值将**无法通过**评测,**成绩为零**。 + + Returns: + - int: 预测的分类标签。 + """ + + +# 这里也写自己的代码实现 +def load_dataset(directory): + """ + 从文件夹中加载数据,若不自行正确实现,则无法通过评测,**不记录成绩**。 + + Args: + - directory (str): 数据文件夹路径。 + + Returns: + - np.array: 特征数据。 + - np.array: 标签数据。 + """ + + +# 这里还写自己的代码实现 +def img_to_vector(filename): + """ + 将二值图像转换为向量。 + 该部分应为 load_dataset 函数的辅助子函数,可单独在这里实现,也可直接集成至 load_dataset 函数中。 + + Args: + - filename (str): 图像文件路径。 + + Returns: + - np.array: 二值图像向量。 + """ + + +if __name__ == "__main__": + # 以下代码可用于测试,可自行随意修改 + train_data, train_labels = load_dataset("trainingDigits") + + test_data = ( + "00000000000000110000000000000000" + "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" + ) + predicted_label = classify( + np.array([int(char) for char in test_data]).reshape(1, 1024), + train_data, + train_labels, + ) + + print(f"预测的标签: {predicted_label}") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..4bb300f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +numpy==2.1.1 +requests==2.32.3