简介这份数据集面向深度学习入门者、计算机视觉学习者及需要图形分类实验的开发者提供星形、圆形、正方形、三角形四种基本形状的标注图像可用于图像分类、卷积神经网络训练、数据增强与模型评估等基础实验场景。压缩包共收录14973个文件其中14970个为png格式的200×200像素图片另有3个py脚本便于直接读取、预处理或搭建训练流程整体包体约21.57MB体量轻便、易于下载与本地部署。目前已有293人学习下载适合作为课堂作业、课程设计或算法验证的练手素材。数据集覆盖四种形状类别样本数量充足能支撑从数据加载、模型搭建到准确率对比的完整实验链路帮助读者快速验证分类网络效果也可用于测试不同优化器、学习率与网络深度对识别精度的影响是入门视觉任务的实用起点。1. 四种基本形状数据集从“玩具级”到“产线级”的落差在哪星形、圆形、正方形、三角形这四个词摆在一起很多人第一反应是“太简单了随便训个模型都能跑满”。我最初也这么想直到把它接到一条真实的零件分拣线上——现场光照不均、形状有旋转、边缘还有毛刺模型准确率直接从实验室的 99% 掉到 71%。四种基本形状的图片数据集表面看是入门级分类任务实际是检验数据工程、增强策略和部署鲁棒性的绝佳试金石。它解决的核心问题不是“能不能分类”而是“在受控条件下把分类做到可复现、可迁移、可解释”。适合谁刚接触视觉分类想跑通全流程的新手以及需要一个小而干净的数据集来验证新增强策略、新网络结构或新部署链路的老手。这一章先把边界划清楚它简单但简单不等于没有坑。2. 数据集构建与格式选型为什么我坚持从 200 张起步2.1 四种形状的类间差异与类内陷阱星形、圆形、正方形、三角形的类间差异在理想情况下是几何拓扑级别的圆形没有角点正方形有四个直角三角形有三个锐角星形有十个交替的凹凸。但真实数据里类内差异会吃掉这些优势。圆形在透视下会变成椭圆正方形旋转 45 度后和菱形难以区分星形的凹角在低分辨率下会糊成圆形三角形的钝角版本和扇形边界模糊。我一般会先做一次类内多样性盘点而不是急着写 DataLoader。具体做法是每个类别至少覆盖旋转0 到 360 度步长 15 度、尺度占画幅 20% 到 80%、背景纯色、纹理、渐变、边缘锐利、抗锯齿、轻微模糊四个维度。如果某个类别在某个维度上缺失训练出来的模型就会在那个维度上翻车。常见做法是每个类别先收集 200 张四个类共 800 张作为基线。这个量级在迁移学习下足够跑出 95% 以上的验证准确率同时小到可以在单卡上几分钟跑完一轮方便快速迭代增强策略。不要一上来就堆到几万张那样调参周期会拖垮你的验证节奏。2.2 目录结构与标注格式ImageFolder 还是 COCO四种基本形状是典型的单标签分类任务最省事的格式是 ImageFolder 式的按类分目录dataset/ ├── train/ │ ├── circle/ │ ├── square/ │ ├── star/ │ └── triangle/ ├── val/ │ ├── circle/ │ ├── square/ │ ├── star/ │ └── triangle/ └── test/ ├── circle/ ├── square/ ├── star/ └── triangle/这种结构的好处是 torchvision 的ImageFolder和 TensorFlow 的image_dataset_from_directory都能直接读零解析成本。但如果你后续要做形状检测画框而不是分类就得换成 COCO 或 YOLO 格式每个形状带边界框标注。我一般会同时保留两份分类用 ImageFolder检测用 COCO。转换脚本不复杂但要注意边界框的坐标归一化和类别 ID 映射。下面是一个把 ImageFolder 转成 COCO 风格 JSON 的最小脚本import json import os from PIL import Image # 类别映射顺序固定避免训练时标签错位 CLASS_MAP {circle: 0, square: 1, star: 2, triangle: 3} def build_coco(root_dir, split): images, annotations [], [] ann_id 1 img_id 1 split_dir os.path.join(root_dir, split) for cls_name, cls_id in CLASS_MAP.items(): cls_dir os.path.join(split_dir, cls_name) if not os.path.isdir(cls_dir): continue for fname in os.listdir(cls_dir): if not fname.lower().endswith((.png, .jpg, .jpeg)): continue path os.path.join(cls_dir, fname) w, h Image.open(path).size images.append({id: img_id, file_name: path, width: w, height: h}) # 分类任务转检测时默认整图作为一个框后续可替换为真实标注 annotations.append({ id: ann_id, image_id: img_id, category_id: cls_id, bbox: [0, 0, w, h], area: w * h, iscrowd: 0 }) ann_id 1 img_id 1 return {images: images, annotations: annotations, categories: [{id: v, name: k} for k, v in CLASS_MAP.items()]} if __name__ __main__: coco build_coco(./dataset, train) with open(train_coco.json, w) as f: json.dump(coco, f)逻辑说明脚本遍历每个类别目录读取图片尺寸生成 COCO 标准的 images 和 annotations 两个数组。参数说明CLASS_MAP的顺序一旦确定就不能改否则训练时标签和模型输出会对不上bbox这里默认整图是因为分类转检测时如果没有真实框标注整图框只能作为占位不能直接用于检测训练。如果你有真实标注把bbox替换成标注值即可。提示类别 ID 从 0 开始还是从 1 开始不同框架要求不同。COCO 官方类别 ID 从 1 开始但很多 PyTorch 实现从 0 开始。转换后务必用一小批数据验证标签是否对齐。2.3 训练集、验证集、测试集的划分比例与随机种子四种形状数据集因为类间差异大划分比例不需要太激进。我一般用 70/15/15即训练 70%、验证 15%、测试 15%。如果每个类只有 200 张训练集 140 张、验证 30 张、测试 30 张。验证集用来调增强策略和早停测试集只在最后跑一次避免信息泄漏。随机种子必须固定。我见过太多人因为划分时没固定种子导致两次实验的验证集不同指标波动 3 到 5 个百分点还以为是模型改了有效。下面是一个带固定种子的划分脚本import random import os import shutil SEED 42 random.seed(SEED) def split_dataset(src_dir, dst_dir, ratios(0.7, 0.15, 0.15)): classes [circle, square, star, triangle] for cls in classes: files sorted(os.listdir(os.path.join(src_dir, cls))) random.shuffle(files) n len(files) n_train int(n * ratios[0]) n_val int(n * ratios[1]) splits { train: files[:n_train], val: files[n_train:n_train n_val], test: files[n_train n_val:] } for split, flist in splits.items(): out_dir os.path.join(dst_dir, split, cls) os.makedirs(out_dir, exist_okTrue) for f in flist: shutil.copy(os.path.join(src_dir, cls, f), os.path.join(out_dir, f)) if __name__ __main__: split_dataset(./raw, ./dataset)逻辑说明先对每个类别的文件列表排序再打乱保证可复现然后按比例切分并复制到目标目录。参数说明SEED固定后每次运行划分结果一致ratios三个值之和必须为 1如果数据量很小可以调成 80/10/10但验证集不能少于每类 20 张否则指标抖动太大。3. 增强策略与基线模型把 800 张用出 8000 张的效果3.1 几何增强的边界旋转、翻转、裁剪的合理范围四种形状数据集的增强核心是几何增强。但几何增强有边界不是随便转。圆形旋转任意角度都不变所以对圆形做旋转增强是无效的甚至有害——它会让模型学到“圆形可以出现在任何角度”这种废话浪费容量。正方形旋转 90 度不变但旋转 45 度就变成菱形如果测试集里没有菱形模型会把菱形误判成正方形或圆形。三角形旋转 180 度后方向相反星形旋转 72 度后自重合。我一般会按类别设置增强范围圆形只做平移和缩放不做旋转正方形做 90 度整数倍旋转三角形做 0 到 360 度全旋转星形做 72 度整数倍旋转。翻转方面圆形和正方形水平垂直翻转都不变三角形和星形翻转后会改变手性如果测试集里没有翻转样本训练时就不要加翻转。下面是一个按类别配置增强的 PyTorch 示例import torchvision.transforms as T # 按类别定义增强避免无效增强浪费模型容量 def get_transform(cls_name, is_trainTrue): if not is_train: return T.Compose([T.Resize((128, 128)), T.ToTensor()]) if cls_name circle: # 圆形旋转不变只做平移缩放 return T.Compose([ T.Resize((128, 128)), T.RandomAffine(degrees0, translate(0.1, 0.1), scale(0.8, 1.2)), T.ToTensor() ]) elif cls_name square: # 正方形只做 90 度整数倍旋转 return T.Compose([ T.Resize((128, 128)), T.RandomApply([T.RandomRotation((90, 90))], p0.5), T.RandomAffine(degrees0, translate(0.1, 0.1), scale(0.8, 1.2)), T.ToTensor() ]) elif cls_name triangle: # 三角形全旋转 return T.Compose([ T.Resize((128, 128)), T.RandomRotation(180), T.RandomAffine(degrees0, translate(0.1, 0.1), scale(0.8, 1.2)), T.ToTensor() ]) else: # star # 星形 72 度整数倍旋转 return T.Compose([ T.Resize((128, 128)), T.RandomApply([T.RandomRotation((72, 72))], p0.5), T.RandomAffine(degrees0, translate(0.1, 0.1), scale(0.8, 1.2)), T.ToTensor() ])逻辑说明每个类别走不同的增强分支圆形不做旋转正方形和星形做对称旋转三角形做全旋转。参数说明translate(0.1, 0.1)表示水平和垂直各平移 10%scale(0.8, 1.2)表示缩放 80% 到 120%这两个范围对四种形状都安全RandomRotation(180)表示在 -180 到 180 度之间随机旋转对三角形适用。注意增强策略必须和测试集分布匹配。如果测试集里只有正向三角形训练时做全旋转会让模型对方向不敏感反而降低正向样本的准确率。先看测试集再定增强。3.2 从 ResNet18 到轻量 CNN基线模型怎么选四种形状数据集上ResNet18 从零训练就能到 95% 以上但参数量 11M推理延迟在边缘设备上不够看。如果目标是部署到产线我一般会先跑一个轻量 CNN 作为基线再和 ResNet18 对比。轻量 CNN 的结构可以很简单三个卷积块每个块是 Conv-BN-ReLU-MaxPool最后全局平均池化加全连接。下面是一个最小实现import torch.nn as nn class ShapeCNN(nn.Module): def __init__(self, num_classes4): super().__init__() self.features nn.Sequential( nn.Conv2d(3, 32, 3, padding1), nn.BatchNorm2d(32), nn.ReLU(), nn.MaxPool2d(2), nn.Conv2d(32, 64, 3, padding1), nn.BatchNorm2d(64), nn.ReLU(), nn.MaxPool2d(2), nn.Conv2d(64, 128, 3, padding1), nn.BatchNorm2d(128), nn.ReLU(), nn.AdaptiveAvgPool2d(1) ) self.classifier nn.Linear(128, num_classes) def forward(self, x): x self.features(x) x x.flatten(1) return self.classifier(x)逻辑说明三个卷积块逐步把空间尺寸从 128 降到 1通道数从 3 升到 128最后全连接输出 4 类。参数说明AdaptiveAvgPool2d(1)把任意空间尺寸压成 1x1这样输入图片尺寸可以灵活调整num_classes4对应四种形状。这个模型参数量约 0.1M在 CPU 上单张推理不到 5ms适合产线部署。训练时用交叉熵损失Adam 优化器学习率 1e-3batch size 32跑 50 个 epoch。如果验证准确率在 10 个 epoch 内没提升就降低学习率到 1e-4。我一般会同时跑 ResNet18 和 ShapeCNN如果 ShapeCNN 能达到 ResNet18 的 98% 准确率就选 ShapeCNN 部署。3.3 训练循环与早停别让模型在验证集上过拟合训练循环里最容易翻车的是早停策略。四种形状数据集小模型很容易在验证集上过拟合。我一般用验证损失而不是验证准确率作为早停指标因为准确率在 95% 以上时抖动大损失更平滑。import torch from torch.utils.data import DataLoader def train_one_epoch(model, loader, optimizer, criterion, device): model.train() total_loss 0 for imgs, labels in loader: imgs, labels imgs.to(device), labels.to(device) optimizer.zero_grad() outputs model(imgs) loss criterion(outputs, labels) loss.backward() optimizer.step() total_loss loss.item() return total_loss / len(loader) def evaluate(model, loader, criterion, device): model.eval() total_loss, correct, total 0, 0, 0 with torch.no_grad(): for imgs, labels in loader: imgs, labels imgs.to(device), labels.to(device) outputs model(imgs) loss criterion(outputs, labels) total_loss loss.item() correct (outputs.argmax(1) labels).sum().item() total labels.size(0) return total_loss / len(loader), correct / total # 早停验证损失连续 8 个 epoch 不降就停 best_loss float(inf) patience, wait 8, 0 for epoch in range(50): train_loss train_one_epoch(model, train_loader, optimizer, criterion, device) val_loss, val_acc evaluate(model, val_loader, criterion, device) if val_loss best_loss: best_loss val_loss wait 0 torch.save(model.state_dict(), best.pth) else: wait 1 if wait patience: print(fEarly stop at epoch {epoch}) break逻辑说明每个 epoch 先训练再验证验证损失创新低就保存模型并重置等待计数否则等待计数加一超过耐心值就停止。参数说明patience8表示连续 8 个 epoch 验证损失不降就停这个值对 800 张数据集体量合适best.pth保存的是验证损失最低的模型不是最后一个 epoch 的模型。4. 避坑与排查四种形状数据集上最容易翻车的 5 个点4.1 现象验证准确率 99%测试准确率 70%原因验证集和测试集划分时没有固定随机种子或者验证集被重复用于调参导致信息泄漏。更隐蔽的原因是增强策略在验证集上也生效了验证集分布和测试集不一致。解决固定随机种子验证集只做 Resize 和 ToTensor不做任何随机增强。测试集只在最后跑一次跑完之前不要看测试指标。4.2 现象圆形被大量误判为星形原因星形的凹角在低分辨率下被平滑掉轮廓接近圆形。如果训练集里星形图片分辨率普遍低于圆形模型会学到“低分辨率等于星形”这种伪特征。解决统一所有图片的输入分辨率至少 128x128。如果原始图片分辨率差异大先做一次分辨率归一化再送入训练。另外检查星形类别的边缘是否过于模糊必要时做锐化增强。4.3 现象训练损失震荡不收敛原因学习率太大或者 batch size 太小导致梯度噪声大。四种形状数据集小batch size 32 时每个 batch 只有 8 张每类梯度方差大。解决把学习率从 1e-3 降到 1e-4或者把 batch size 提到 64。如果显存不够用梯度累积模拟大 batch。另外检查数据归一化的均值和方差是否用了 ImageNet 的默认值如果数据集背景和 ImageNet 差异大最好重新计算。4.4 现象模型对旋转后的正方形识别率骤降原因训练时正方形只做了 90 度整数倍旋转但测试集里出现了 45 度旋转的正方形菱形。模型没见过这个角度把它判成了圆形或三角形。解决先确认测试集里是否有非 90 度倍数的正方形。如果有训练时必须加入对应角度的旋转增强。如果没有测试集就不应该出现这种样本检查测试集构建流程是否混入了异常数据。4.5 现象部署后推理结果和训练时不一致原因训练时用了 PIL 读图加 ToTensor部署时用了 OpenCV 读图通道顺序从 RGB 变成 BGR或者归一化参数不一致。这种问题在四种形状数据集上尤其明显因为形状颜色单一通道错位后颜色变化不大但模型看到的输入分布已经变了。解决训练和部署用同一套预处理代码或者至少用同一张图片对比两边预处理后的张量是否一致。我一般会写一个preprocess.py训练和部署都 import 这个模块避免手写两套。5. 进阶技巧用混淆矩阵和 t-SNE 把四种形状的边界看清楚训练完模型准确率只是一个数字。要真正理解模型学到了什么我一般会做两件事混淆矩阵和 t-SNE 可视化。混淆矩阵能告诉你哪两个类别最容易混。四种形状数据集上最常见的混淆是圆形和星形、正方形和三角形。如果混淆矩阵显示圆形和星形互混严重说明模型没有学到星形的凹角特征可能增强策略里星形的旋转范围不对或者分辨率不够。t-SNE 把最后一层特征降到二维看四个类别的聚类是否分开。如果圆形和星形在 t-SNE 上重叠说明特征空间里这两个类没有分离需要检查数据标注是否有误或者增加一个专门区分凹角的特征通道。下面是一个混淆矩阵和 t-SNE 的代码示例import numpy as np import matplotlib.pyplot as plt from sklearn.manifold import TSNE from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay # 收集测试集上的预测和特征 model.eval() all_preds, all_labels, all_feats [], [], [] with torch.no_grad(): for imgs, labels in test_loader: imgs imgs.to(device) feats model.features(imgs).flatten(1) # 取卷积特征 outputs model.classifier(feats) all_preds.extend(outputs.argmax(1).cpu().numpy()) all_labels.extend(labels.numpy()) all_feats.append(feats.cpu().numpy()) all_feats np.concatenate(all_feats, axis0) # 混淆矩阵 cm confusion_matrix(all_labels, all_preds) ConfusionMatrixDisplay(cm, display_labels[circle, square, star, triangle]).plot() plt.savefig(confusion_matrix.png) # t-SNE tsne TSNE(n_components2, random_state42, perplexity15) feats_2d tsne.fit_transform(all_feats) plt.figure() for cls_id, cls_name in enumerate([circle, square, star, triangle]): idx np.array(all_labels) cls_id plt.scatter(feats_2d[idx, 0], feats_2d[idx, 1], labelcls_name, s10) plt.legend() plt.savefig(tsne.png)逻辑说明先跑一遍测试集收集预测标签、真实标签和卷积层特征然后用 sklearn 的混淆矩阵和 t-SNE 分别可视化。参数说明perplexity15对 800 张数据集体量合适太大或太小都会让 t-SNE 图失去结构random_state42固定后每次图一致方便对比不同模型。看混淆矩阵时如果某一类的召回率低于 90%先看它的训练样本数是否偏少再看增强是否过度。看 t-SNE 时如果四个类聚成四团但有两团挨得很近说明模型能分但边界模糊可以尝试加一个对比损失或者中心损失来拉开距离。我自己的习惯是每次改完增强策略或模型结构先跑混淆矩阵确认没有类别被系统性误判再看 t-SNE确认特征空间没有塌缩。这两个图比准确率更能告诉我模型到底学到了什么。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
PaddleNLP 中的 ChatGLM-6B:模型解读、全场景微调与量化部署实践 PaddleNLP 中的 ChatGLM-6B:模型解读、全场景微调与量化部署实践 【免费下载链接】PaddleNLP Easy-to-use and powerful LLM and SLM library with awesome model zoo. 项目地址: https://gitcode.com/gh_mirrors/pa/PaddleNLP
ChatGLM-6B 是 THUDM 开源的中… · 2026/9/23 18:07:21
基于小程序的驾校报名系统源码解析与二次开发指南 简介:这是一套面向高校计算机专业毕业设计与课程设计场景的驾校报名小程序完整源码,采用Java后端搭配微信小程序前端与MySQL数据库,适合需要快速搭建可运行项目、完成答辩或课程作业的学生与开发者。项目按管理员、用户、驾校教练三类角色划分… · 2026/9/23 18:07:09
基于OpenCV的车牌识别停车场管理系统:C++毕设完整实现与避坑指南 简介:这份C毕业设计项目基于OpenCV实现车牌识别并搭建停车场管理系统,源码与论文齐备,面向计算机、通信、人工智能、自动化等专业学生及从业者,可作为课程设计、大作业或毕业设计的完整参考。项目在个人答辩中获得98分,… · 2026/9/23 18:07:09
2026最新本地安全策略命令避坑指南 2026最新本地安全策略命令避坑指南 凌晨三点,CI 流水线突然全红,构建机上的报错日志像瀑布一样刷下来。最让人头疼的不是那个显眼的 Permission Denied ,而是底下那一串长得像乱码的… · 2026/9/23 18:39:29
本地化NLP平台实战:多模态文本分析与知识图谱构建 简介:面向企业级AI文本分析场景的NLP软件系统完整源码包,专注解决企业私有化部署下的自然语言处理需求,可对网页、文档、音视频、图像等多模态数据进行智能解析与结构化处理,同时支持企业级知识图谱构建、实体识别与情感分析。资源… · 2026/9/23 18:39:29
色彩对比入门到精通:从代码底层原理看视觉差值计算 色彩对比入门到精通:从代码底层原理看视觉差值计算 刚学完 CSS 颜色属性或者前端绘图 API,是不是感觉语法都背下来了,但一到实战搭项目,面对“这个按钮颜色够不够醒目”、“这段文字在深色背景下对比度达标吗”这类需求,脑子瞬间一片空白?这种… · 2026/9/23 18:39:29
基于Python的网络舆情分析系统:从爬虫到可视化全流程实战 简介:一套基于 Python 的互联网舆情监测分析系统完整实现方案,源自哈尔滨工业大学课程实践项目,适用于人工智能课程学习、毕业设计及期末综合实践等场景,整体难度中等,代码均已编译测试,可快速部署验证。全… · 2026/9/23 18:39:29
从“不知道机构什么背景”到上岸二工大:一个专科生的选机构逻辑 一句话结论:选专升本机构,先看三件事——办学平台、考纲教研、师资身份。上海专升本是各校自主命题,资料错一年就白复习一年。这也是那位从中高职贯通考上上海第二工业大学的同学,最后留在指尖专升本的原因。一、起点比别人晚一年… · 2026/9/23 18:39:29
知识蒸馏实战:2MB极小模型实现人脸关键点检测CPU 22ms推理 简介:这份资源是面向计算机、人工智能及相关专业在校学生的本科毕业设计源码,核心目标是用知识蒸馏训练一个参数量极小的人脸关键点检测模型,适合作为毕设、课程设计或进阶练手项目。压缩包共约2000个文件,整体408.9MB,… · 2026/9/23 18:39:22
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29