新闻详情

新闻详情

首页 / 资讯中心 / 详情

PyTorch卷积神经网络实战:牙齿健康识别与Web部署全流程

发布时间:2026/9/28 16:43:51来源:尧图网络
PyTorch卷积神经网络实战:牙齿健康识别与Web部署全流程
简介这是一套面向深度学习入门者与计算机视觉实践者的牙齿健康识别项目源码基于Python与PyTorch构建卷积神经网络完成从数据读取、模型训练到网页端交互的完整闭环。资源包共269个文件以262张jpg牙齿图像构成分类数据集另含3个Python脚本、3个txt说明与1个html页面压缩包约13.89MB结构紧凑便于本地复现。运行流程清晰先由数据集脚本生成图片路径与标签文本再通过训练脚本读取训练集与验证集并保存模型及逐轮验证损失与准确率日志最后启动服务脚本生成网页交互地址在浏览器中即可上传图片查看识别结果。内容预览中可见多张经过旋转、翻转等增强处理的牙齿样本图说明数据已做扩充有助于提升模型泛化能力。目前已有108人学习适合希望掌握PyTorch图像分类全流程、需要可运行案例练手的读者参考。1. 从一份牙齿图片数据集说起这套 PyTorch HTML 方案到底能跑出什么手里拿到一个压缩包名字很长——「web网页html版基于python卷积神经网络训练识别牙齿是否健康-含图片数据集.zip」。解压之后你会看到一堆散落的图片文件sfb_rotated45.jpg、sfb_flip.jpg、sfbq.jpg、hjfi.jpg、hui_rotated45.jpg、hui_flip.jpg、sjh_flip.jpg、sjh_rotated45.jpg、huig.jpg外加一个index.html。这不是一个成品 App而是一套「数据集 训练脚本 网页推理服务」的最小闭环。它的价值在于你不用自己从零标注牙齿健康图片也不用纠结前端怎么搭直接顺着01到03三个脚本跑一遍就能在浏览器里输入http://127.0.0.1:4399看到分类结果。适合谁正在学 CNN 图像分类、想找一个能跑通全流程的小项目练手的人或者手里有类似二分类需求、想拿它当模板改的人。不适合指望开箱即用、精度直接上生产的人——数据集规模摆在那它更像一个教学骨架而不是工业级诊断工具。2. 环境配置与数据集结构先把地基踩实2.1 依赖安装的两种路径项目正文里给了一条 CSDN 博文链接作为环境安装参考同时压缩包里应该带了一个requirement.txt。我一般会先看requirement.txt里锁定的版本因为 PyTorch 的版本和 CUDA 驱动之间的对应关系是新手翻车最密集的地方。如果你本机没有 NVIDIA 显卡或者不想折腾 CUDA直接装 CPU 版 PyTorch 也能跑只是训练会慢一些。常见做法是建一个独立虚拟环境避免和系统里已有的包打架# 创建虚拟环境python 版本建议 3.8 到 3.10 python -m venv tooth_env # 激活环境Windows tooth_env\Scripts\activate # 激活环境Linux / macOS source tooth_env/bin/activate # 安装依赖requirement.txt 在解压目录下 pip install -r requirement.txt -i https://pypi.tuna.tsinghua.edu.cn/simple这里用国内镜像源是为了避开下载超时-i后面跟的是清华源地址。如果你机器上已经有配好的 PyTorch 环境也可以跳过虚拟环境这一步但要注意torch和torchvision的版本必须匹配否则import torchvision时会报RuntimeError。装完之后用一行命令验证import torch print(torch.__version__) print(torch.cuda.is_available()) # 有显卡且驱动正常会返回 True如果torch.cuda.is_available()返回False但你确实有显卡大概率是 CUDA 版本和 PyTorch 版本对不上这时候要么重装对应版本的 PyTorch要么就老老实实用 CPU 跑别在这上面耗太久。2.2 数据集目录长什么样从正文描述和文件名来看数据集文件夹下按类别分了子目录。sfb、hui、sjh、hjfi、huig这些前缀大概率对应不同的牙齿状态类别。每个类别文件夹里放着原始图片以及经过旋转rotated45、翻转flip增强后的副本。这种命名方式说明作者已经做了一部分数据增强把增强后的图片直接落盘成了独立文件而不是在训练时动态增强。文件名模式含义推测用途sfbq.jpg/sfb_rotated45.jpg/sfb_flip.jpg同一类别的原图、旋转 45 度、翻转版本扩充该类别样本量hjfi.jpg另一类别原图分类目标之一hui_rotated45.jpg/hui_flip.jpg/huig.jpg第三类别的增强图与原图分类目标之一sjh_flip.jpg/sjh_rotated45.jpg第四类别的增强图分类目标之一你需要确认的是每个类别文件夹下的图片数量是否均衡。如果某一类只有两三张而另一类有几十张训练出来的模型会严重偏向多数类。我一般会先跑一段统计脚本import os data_dir dataset # 替换成你实际的 dataset 路径 for class_name in os.listdir(data_dir): class_path os.path.join(data_dir, class_name) if os.path.isdir(class_path): count len([f for f in os.listdir(class_path) if f.endswith((.jpg, .png, .jpeg))]) print(f{class_name}: {count} 张)这段代码遍历dataset下每个子目录统计图片文件数量。如果发现某类样本过少要么补充图片要么在训练脚本里加类别权重。这一步不做后面训练出来的准确率数字再好看也是虚的。3. 从图片到文本01 脚本到底生成了什么3.1 数据集文本生成脚本的逻辑01数据集文本生成制作.py这个脚本的核心任务就一件事遍历数据集目录把每张图片的路径和它对应的类别标签写成一个 txt 文件。这个 txt 后续会被02脚本读取作为训练和验证的数据索引。常见做法是按比例划分训练集和验证集比如 8:2 或 7:3。脚本里大概率用了os.listdir或glob来收集路径然后用random.shuffle打乱后切分。import os import random def generate_txt(data_dir, output_txt, val_ratio0.2): data_dir: 数据集根目录下面按类别分子文件夹 output_txt: 输出的 txt 文件路径 val_ratio: 验证集比例 lines [] classes sorted(os.listdir(data_dir)) for label, class_name in enumerate(classes): class_path os.path.join(data_dir, class_name) if not os.path.isdir(class_path): continue images [f for f in os.listdir(class_path) if f.lower().endswith((.jpg, .png, .jpeg))] for img in images: img_path os.path.join(class_path, img) lines.append(f{img_path}\t{label}) random.shuffle(lines) split_idx int(len(lines) * (1 - val_ratio)) train_lines lines[:split_idx] val_lines lines[split_idx:] with open(output_txt, w, encodingutf-8) as f: for line in train_lines: f.write(line \n) with open(output_txt.replace(.txt, _val.txt), w, encodingutf-8) as f: for line in val_lines: f.write(line \n) print(f训练集 {len(train_lines)} 条验证集 {len(val_lines)} 条) if __name__ __main__: generate_txt(dataset, train.txt)这段代码里几个关键点label是用enumerate按类别文件夹排序后自动分配的所以类别顺序取决于文件夹名的字母序这一点要记住后面推理时类别映射必须一致。val_ratio控制验证集比例样本少的时候可以调到 0.3让验证结果更有统计意义。输出格式是「路径 Tab 标签」这是 PyTorch 自定义 Dataset 里最常见的读取格式。3.2 路径分隔符与编码的坑Windows 下路径用反斜杠\Linux 和 macOS 用正斜杠/。如果你在 Windows 上生成 txt然后拿到 Linux 上训练路径会全部失效。稳妥的做法是在脚本里用os.path.normpath或直接统一替换成/。另外如果数据集文件夹名包含中文open的时候必须指定encodingutf-8否则在部分系统上会抛UnicodeDecodeError。这些细节在脚本里可能已经处理了但如果你要改路径或换数据集得自己留意。提示运行完01脚本后先打开生成的 txt 看一眼确认每行格式是「图片路径 Tab 数字标签」路径真实存在。这一步花三十秒能省掉后面半小时的排查。4. 训练脚本拆解CNN 结构、超参与日志解读4.1 模型定义与训练循环02深度学习模型训练.py是整个项目的核心。它要做的事包括读取01生成的 txt、构建 Dataset 和 DataLoader、定义一个 CNN 网络、跑训练循环、保存模型和日志。CNN 结构大概率是几个卷积层 池化层 全连接层的堆叠输入尺寸可能是 224×224 或 128×128。下面是一个典型的 CNN 定义和训练骨架import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import Dataset, DataLoader from torchvision import transforms from PIL import Image class ToothDataset(Dataset): def __init__(self, txt_path, transformNone): self.samples [] with open(txt_path, r, encodingutf-8) as f: for line in f: path, label line.strip().split(\t) self.samples.append((path, int(label))) self.transform transform def __len__(self): return len(self.samples) def __getitem__(self, idx): path, label self.samples[idx] img Image.open(path).convert(RGB) if self.transform: img self.transform(img) return img, label class SimpleCNN(nn.Module): def __init__(self, num_classes): super().__init__() self.features nn.Sequential( nn.Conv2d(3, 16, 3, padding1), nn.ReLU(), nn.MaxPool2d(2), nn.Conv2d(16, 32, 3, padding1), nn.ReLU(), nn.MaxPool2d(2), nn.Conv2d(32, 64, 3, padding1), nn.ReLU(), nn.MaxPool2d(2), ) self.classifier nn.Sequential( nn.Flatten(), nn.Linear(64 * 28 * 28, 128), nn.ReLU(), nn.Linear(128, num_classes) ) def forward(self, x): return self.classifier(self.features(x)) # 数据预处理 transform transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean[0.5, 0.5, 0.5], std[0.5, 0.5, 0.5]) ]) train_dataset ToothDataset(train.txt, transformtransform) val_dataset ToothDataset(train_val.txt, transformtransform) train_loader DataLoader(train_dataset, batch_size16, shuffleTrue) val_loader DataLoader(val_dataset, batch_size16, shuffleFalse) device torch.device(cuda if torch.cuda.is_available() else cpu) model SimpleCNN(num_classes4).to(device) # num_classes 按实际类别数改 criterion nn.CrossEntropyLoss() optimizer optim.Adam(model.parameters(), lr1e-3) for epoch in range(30): model.train() for imgs, labels in train_loader: imgs, labels imgs.to(device), labels.to(device) optimizer.zero_grad() outputs model(imgs) loss criterion(outputs, labels) loss.backward() optimizer.step() # 验证 model.eval() correct, total 0, 0 with torch.no_grad(): for imgs, labels in val_loader: imgs, labels imgs.to(device), labels.to(device) outputs model(imgs) _, predicted torch.max(outputs, 1) total labels.size(0) correct (predicted labels).sum().item() print(fEpoch {epoch1}, Val Acc: {correct/total:.4f})几个参数需要你根据实际情况调整num_classes必须等于数据集类别数batch_size在样本少的时候可以降到 8 或 4lr如果训练损失震荡可以调到1e-4。Resize的尺寸要和模型全连接层的输入维度匹配上面代码里 224×224 经过三次池化变成 28×28所以全连接层写的是64 * 28 * 28。如果你改了输入尺寸或卷积层数量这个数字要跟着算。4.2 日志文件里该看什么训练完成后本地会生成 log 日志里面记录了每个 epoch 的验证集损失和准确率。我一般重点看两件事验证集准确率是否在上升后趋于平稳以及验证集损失是否在准确率还在涨的时候就开始回升。后者是过拟合的典型信号。如果验证损失连续几个 epoch 都在涨而训练损失还在降说明模型开始死记训练样本了。这时候可以加 Dropout、减小模型容量、或者提前停止训练。日志里如果出现准确率从第一轮就卡在某个值不动大概率是标签映射错了或者数据加载有问题回去检查01生成的 txt。注意样本量少的时候验证集准确率波动会很大单个 epoch 的数字不用太当真看趋势比看绝对值重要。5. 网页交互服务03 脚本与 4399 端口的那些事5.1 服务启动与 URL 访问03html_server.py的作用是启动一个本地 HTTP 服务把训练好的模型加载进来接收浏览器上传的图片返回分类结果。正文里明确写了访问地址是http://127.0.0.1:4399。这个端口号是脚本里写死的如果你本机 4399 被占用了需要去脚本里改port参数。启动方式就是直接运行python 03html_server.py运行后终端会打印出监听地址。然后在本机浏览器地址栏手动输入http://127.0.0.1:4399注意不要输成https也不要在末尾多加斜杠或路径。如果页面打不开先确认终端有没有报错、端口有没有被防火墙拦、以及是不是在虚拟环境里运行的。5.2 前后端交互的数据流这个项目的网页交互逻辑大概率是这样的index.html里有一个文件上传控件和一个提交按钮用户选图后通过表单或 Fetch API 把图片发给后端后端用训练好的模型推理再把类别结果返回前端显示。index.html里可能内嵌了 JavaScript 来处理请求和展示结果。如果你要改前端样式或增加功能直接编辑index.html即可不需要重新训练模型。但要注意前端显示的类别名称必须和后端模型输出的标签索引对应上这个映射关系通常在03脚本里定义改的时候两边要同步。组件文件职责前端页面index.html图片上传、结果展示后端服务03html_server.py加载模型、接收请求、推理、返回结果模型文件训练时保存的.pth或.pt存储网络权重标签映射脚本内字典或列表数字索引到类别名的转换如果上传图片后页面没反应打开浏览器开发者工具看 Network 面板确认请求是否发出、后端是否返回了 200。常见问题是图片格式不被 PIL 支持或者上传的图片尺寸过大导致预处理超时。6. 避坑与排查那些跑通之前大概率会遇到的坎6.1 环境装完 import 报错现象pip install -r requirement.txt跑完没报错但import torch时提示DLL load failed或ImportError。原因通常是 PyTorch 版本和 Python 版本不匹配或者 CUDA 运行时库缺失。解决先确认 Python 版本在 3.8 到 3.10 之间然后去 PyTorch 官网用版本选择器生成对应的安装命令不要直接照搬requirement.txt里可能过时的版本号。6.2 训练时 loss 变成 nan现象训练几个 batch 后损失值变成nan准确率不再变化。原因一般是学习率太大或者输入数据没有归一化。解决把lr从1e-3降到1e-4甚至1e-5确认transforms.Normalize的均值和标准差设置合理检查图片路径里有没有损坏文件导致读入全黑或全白图像。6.3 网页上传图片后报 500现象浏览器页面能打开但选图提交后返回 500 错误。原因可能是后端加载模型时类别数对不上或者上传的图片格式后端没处理。解决看终端报错栈如果是size mismatch说明num_classes和训练时不一致如果是UnidentifiedImageError说明上传的文件不是有效图片换一张 jpg 再试。6.4 端口被占用导致服务起不来现象运行03html_server.py后终端提示Address already in use。原因4399 端口被其他程序占了。解决在脚本里找到port4399改成4400或其他空闲端口然后访问地址也要同步改成http://127.0.0.1:4400。6.5 验证集准确率虚高现象验证集准确率到了 95% 以上但拿新图片测试完全不准。原因01脚本划分训练集和验证集时没有打乱或者同一张图片的增强版本同时出现在训练集和验证集里造成数据泄漏。解决确认random.shuffle在划分之前执行并且增强后的图片如果和原图高度相似最好按原图分组划分而不是按文件随机划分。7. 把模型换成自己的数据类别映射与增量训练的一个实用技巧这套代码最值钱的地方不是它现在的识别效果而是它提供了一个可以替换数据集的骨架。你完全可以把dataset文件夹里的牙齿图片换成其他二分类或四分类图片比如 PCB 焊点缺陷、零件表面划痕只要按类别建子文件夹、跑一遍01到03就行。但有一个细节很容易被忽略类别映射的顺序。01脚本里用sorted(os.listdir(data_dir))给类别编号这意味着如果你新增了一个类别文件夹字母序变了所有标签都会错位。我一般会在01脚本里把类别列表显式写死成一个列表而不是依赖sortedCLASSES [class_a, class_b, class_c, class_d] # 显式定义顺序 for label, class_name in enumerate(CLASSES): class_path os.path.join(data_dir, class_name) # ... 后续逻辑不变这样无论文件夹怎么增删标签索引都是稳定的。另一个技巧是增量训练如果你已经有一个训练好的模型想在新数据上继续训练而不是从头开始可以在02脚本里加载已有权重model.load_state_dict(torch.load(best_model.pth, map_locationdevice)) # 然后用较小的学习率继续训练 optimizer optim.Adam(model.parameters(), lr1e-4)注意map_locationdevice是为了在 CPU 和 GPU 之间迁移时不报错。加载权重后学习率要调小否则新数据会把旧知识冲掉。验证方法也简单拿几张旧类别的图片和新类别的图片混在一起测看旧类别是否还能分对。如果旧类别准确率掉得厉害说明发生了灾难性遗忘需要降低学习率或冻结前面的卷积层。从那以后我每次换数据集都强制先跑一遍类别统计和标签映射检查确认01生成的 txt 里标签和类别名的对应关系没变再开始训练。这个习惯帮我省掉过好几次「训练半天发现标签全错」的后悔药。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

50+营销Skill赋能AI Agent:垂直场景专业化的开源实践 2026/9/28 17:26:49

50+营销Skill赋能AI Agent:垂直场景专业化的开源实践

“把 50 多种营销 Skill 装进 AI Agent”,这个方案一开始我只当是又一个赶热度的开源项目,直到我把它拉下来跑了一遍,才发现这东西做的其实比你想象中要正经得多。它解决的是一个很实在的问题:AI Agent 在营销场景里经常被吹得很全…

阅读更多 →
glog 输出行为调优:flags.md 全解 —— 命令行参数、环境变量与程序内动态控制 2026/9/28 17:26:43

glog 输出行为调优:flags.md 全解 —— 命令行参数、环境变量与程序内动态控制

后端 【免费下载链接】glog C implementation of the Google logging module 项目地址: https://gitcode.com/gh_mirrors/glog6/glog 点击查看 免费下载 glog(Google Logging Library)作为 C14 实现的流式日志库,其输出行为的控制…

阅读更多 →
Agent-Native架构实战:从工具调用到原生智能体的设计指南 2026/9/28 17:26:43

Agent-Native架构实战:从工具调用到原生智能体的设计指南

1. 从“工具调用”到“原生智能体”:agent-native 到底在说什么第一次听到 “agent-native” 这个词,是在和几个做 AI 应用的朋友闲聊时。有人抛出一句:“现在做产品,如果不按 agent-native 的思路来设计,基本等于白做…

阅读更多 →
顺易教育规模怎么样,服务体系完善吗 2026/9/28 17:26:43

顺易教育规模怎么样,服务体系完善吗

时光倏忽,九年一瞬。艺考升学赛道里,无数教育机构起起落落,山东顺易教育科技集团有限公司始终扎根济南本土,在艺考生文化课辅导这片细分领域稳扎稳打,从最初的小体量工作室,成长为覆盖初高中艺术升学全阶段…

阅读更多 →
金融级系统设计必修课:幂等、金额精度与高可用实践 2026/9/28 17:26:43

金融级系统设计必修课:幂等、金额精度与高可用实践

1. 为什么金融服务的"服务"二字没那么简单前阵子一个做支付网关的朋友半夜打电话给我,说渠道回调丢了,用户显示已付款,但他们的系统里订单还是待支付状态。我让他先别急着补单,把请求日志和数据库流水拉出来对一遍。查了…

阅读更多 →
FPGA软核处理器MicroBlaze实战:从搭建到固化全流程 2026/9/28 17:26:43

FPGA软核处理器MicroBlaze实战:从搭建到固化全流程

1. 为什么软核处理器值得花时间啃下来做FPGA开发的朋友多半有过这样的纠结:逻辑代码写完了,时序也收敛了,但一涉及到系统控制、协议调度、人机交互这些“带脑子”的活儿,纯硬件状态机就显得捉襟见肘。这时候MicroBlaze这类软核处理…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉