ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

大数据中药材分类系统实战:数据清洗与架构设计全记录

2026/9/29 16:40:01 拓冰建站 浏览量
大数据中药材分类系统实战:数据清洗与架构设计全记录 很多人以为做一套基于大数据的中药材分类及信息管理系统最难的环节是算法选型和模型调参。我做完这个项目之后最大的体会是这个题目真正的难题根本不在模型而在数据本身。中药材分类这件事放到大数据视角下看首先是一团乱麻。同一味药有十几个别名、产地不同药效不同、药典记载和药材市场流通数据的口径完全对不上。更麻烦的是这些数据分散在药典文本、市场流通记录、电商平台、产地气候记录和科研文献里格式各不相同。传统做法是靠老药工的经验人工判断但一旦需要处理几万条数据人眼和经验就顶不住了。这篇文章不是课程设计报告的套话而是我实际把一个中药材分类系统从零搭起来、跑通、上线验证的全过程记录。内容包括整体架构设计、数据清洗链路、分类模型构建、管理系统功能拆解以及最后实测遇到的坑。适合正在做大数据相关毕设、或者想在中药材领域做信息化产品的开发者参考。1. 真正要解决的不是分类而是分类数据的一团乱麻在动手写代码之前我花了两周时间泡在数据里。第一步不是选框架而是找人请教中药材行业到底是怎么分类的。问了一圈之后发现这个行业的分类逻辑和互联网人想象的很不一样。1.1 中药材数据的三笔糊涂账同名异物、道地产区、记载口径不一第一笔糊涂账是同名异物。药材市场里叫三七的和植物学里的菊三七是两种完全不同的东西。前者是五加科人参属后者是菊科植物药效甚至相反。类似的情况还有北沙参和南沙参、川贝母和浙贝母名字里只差一个字价格差好几倍功效侧重点也完全不同。如果系统只是按名称去重这些药材会被误合并成同一条记录。第二笔糊涂账是道地产区。同一味枸杞子宁夏中宁产的和河北产的价格差了将近一倍有效成分含量也有差异。按照传统中医药理论产地直接决定了药材质量行业内叫道地药材概念。但市场数据里产地字段经常是空的或者只写到省份有的甚至写南方北方这种模糊词——这类数据对分类模型来说几乎是噪声。第三笔糊涂账是记载口径不统一。我拿到的数据来源里《中国药典》对药材的描述用的是规范的拉丁名、性味归经和功能主治药材市场流通记录用的却是俗称、简称和市斤单价电商平台的数据更乱标题里塞满了野生精选特级这类营销词。同一味药三个来源给出的属性字段重合度不到五成。这三笔糊涂账直接决定了系统的设计思路核心不是做一个分类算法而是先把这些异构、不规整的数据洗成一套能喂给模型的标准化数据结构。1.2 大数据在这个场景里能做什么不能做什么很多人对大数据在传统行业的落地有误解以为就是堆服务器、跑跑Hadoop。我在这个项目里的体会是大数据的价值不在于大而在于全。它能把原本割裂在不同体系里的数据打通——把药典的文本描述、市场的流通价格、产地气候记录、文献里的功效记载拼在一起形成一条完整的药材数据画像。拿当归举例药典告诉你它补血活血市场数据告诉你当前价格大约每公斤多少元、主产区在甘肃岷县气候数据告诉你岷县的海拔和降水量适合当归生长文献数据告诉你近十年研究热点集中在当归多糖的免疫调节作用。这些信息单独拿出来没什么用合并到一起就能支撑一个多维度的分类和检索系统。但大数据也有不能做的事。它不能替代药师的最终质量判断。中药饮片讲究辨状论质有些细微的色泽、气味差异机器目前还捕捉不到。所以我的系统把分类结果设计成辅助决策而不是最终结论每个分类结果后面都保留了人工审核入口。这个定位很重要直接决定了系统的信任度。1.3 系统边界把分类和管理拆开看顺着上面的定位我把系统拆成了两条线分类引擎负责药材的自动识别、归类和相似药材推荐。它处理的是这味药材是什么、它和哪些药材相近的问题。信息管理系统负责药材基础信息的增删改查、检索、可视化展示和知识图谱探索。它处理的是药材数据怎么存、怎么查、怎么看的问题。这两部分如果揉在一起代码耦合度高后期维护很痛苦。我在设计时让分类引擎独立成一个服务对外只暴露API信息管理系统调用它的结果。这样即使以后分类算法换掉了管理端几乎不用动。这也是整个项目里我做得最正确的一个决策。2. 整体架构设计四层大数据架构在中药场景里的落地形态我第一版架构图是按照教科书画的——采集层、存储层、计算层、应用层四层结构。但真正落地的时候每一层都做了不少调整因为中药材数据有自己的脾气。2.1 采集层数据源梳理与获取策略数据采集是整个项目的地基。我一共接了六个数据源按照重要程度排序数据源数据类型获取方式规模预估《中国药典》部分内容药材性状、性味归经、功能主治PDF解析约600种药材中药材市场流通记录品名、规格、产地、价格合作方提供Excel约6万条电商平台公开数据标题、价格、产地描述爬虫守法合规采集公开信息约3万条气象开放接口产区海拔、温度、降水省级气象数据接口按产区聚合文献摘要库功效研究、成分分析公开学术摘要筛选约8000条专家知识库药材别名、混用品鉴别人工整理录入约2000条规则这里有个很关键的取舍——一开始我想接更多的数据源比如药材的实时市场行情、产地土壤检测数据但现实是大部分数据要么不开放要么格式烂到无法使用。我的策略是先把手头能拿到的数据用起来再考虑扩源。与其追求数据量不如先把六类数据源之间的关联关系理顺。2.2 存储层关系型数据库、分布式文件与NoSQL如何分工存储层如果没有规划好后面清洗和查询都会很难受。我的方案是混合存储让不同类型的数据库干自己擅长的事MySQL存放标准化后的主数据。药材ID、标准名、别名、产地、价格、功效标签这些强结构化字段都放这里。主表大概有4万多条标准化记录MySQL完全扛得住。HDFS存放原始文件和中间日志。合作方给的Excel、爬虫抓取的原始JSON、清洗前的数据快照全部归档到HDFS。这样做的好处是如果清洗逻辑出了Bug还能从原始数据重新跑一遍不至于把源头数据污染掉。MongoDB存放半结构化特征。药材的外观描述、成分含量文本、文献摘要解析结果这些字段长度不一、结构变化大塞进MySQL反而麻烦MongoDB的文档模型更合适。Elasticsearch负责检索。药材名称检索涉及别名、拼音、模糊匹配MySQL的LIKE查询太慢ES的倒排索引天然适合这种场景。当时也有人建议直接用HBase这种列式存储我评估后放弃了。原因很简单这个项目的数据量远没到HBase的规模MySQL加MongoDB的组合在成本、维护难度和查询便利性上明显更有优势。技术选型不是越分布式越好够用且好维护才是王道。2.3 计算层与应用层Spark负责什么管理系统负责什么计算层用的是Spark但它承担的不是那种每天跑一次亿级日志的重活而是一套日级批处理任务数据标准化每天凌晨把新增的药材流通记录、电商数据拉取下来跑一遍清洗流程统一别名、统一单位、补全产地字段。特征计算把清洗后的数据转成分类模型需要的特征向量更新到特征库里。模型重训每周用累积的新数据对分类模型做一次增量训练确保新出现的药材品名能被识别。应用层就是信息管理系统本体用Spring Boot搭后端Vue做前端页面ECharts做可视化图表Neo4j做知识图谱存储。我特别想强调一点这套系统里Spark并不是主角但它解决了定时、批量、可重跑的问题。如果不用Spark完全可以用Python脚本加crontab实现。选择Spark是因为它有完善的任务调度和数据血缘管理后期加任务、排查问题都更方便——对大数据的毕设项目来说使用Spark集群也能完整覆盖大数据架构的核心考点。3. 数据清洗是决定成败的那一步如果只让我用一句话总结这个项目那就是分类模型的准确率由数据清洗和标准化的质量决定。模型本身用的都是成熟算法但清洗环节做不好再好的模型也白搭。3.1 别名归一化一个药材十几个名字怎么处理中药材的别名问题严重到什么程度比如大黄别名有将军、川军、锦纹、黄良黄芪别名有绵芪、北芪、箭芪三七别名有田七、参三七、金不换。一个标准药材名可能对应十几个别名而且不同地区叫法还不一样。我的做法是建立一张药材别名映射表大概长这样标准名别名集合备注三七田七、参三七、金不换、山漆注意菊三七为混用品大黄将军、川军、锦纹、黄良酒大黄为炮制品单独标记黄芪绵芪、北芪、箭芪、黄耆区分炙黄芪与生黄芪清洗的时候先把所有数据里的品名统一到一个标准名上。匹配规则用优先级排列完全匹配 → 别名映射表匹配 → 去除修饰词后匹配比如去掉精选特级野生等前缀→ 模糊匹配。这里有个容易踩的坑不能光靠别名映射表直接替换因为存在同名异物。比如沙参这个名在有些市场记录里指的是北沙参有些指的是南沙参。我的处理方式是结合产地字段做二次判断——产地是山东的倾向北沙参产地是浙江的倾向南沙参。如果产地缺失就把记录标记为待人工审核而不是强行归类。3.2 结构化清洗单位、价格、缺失值和异常值的处理策略除了别名还有几个让人头疼的问题单位不统一。市场记录里的价格有的按公斤有的按市斤还有按克标价的。我在清洗时全部统一换算成元/公斤。市斤换算成公斤要乘以0.5这个简单麻烦的是有些记录写着25元/两如果不注意单位直接入库后期做价格趋势分析会得出完全错误的结论。价格异常值。电商平台上偶尔会出现离谱价格比如1元当归点进去发现是卖空袋子的或者商家为了排名故意标低价。我用了一个简单有效的方法按产区药材品类的维度计算价格的中位数和四分位距超出中位数上下三倍四分位距的记录直接判为异常不参与价格统计。缺失值处理。产地缺失是最常见的占比大概三成。我的策略是优先用同批次记录里其他字段反推比如甘肃产当归里的省份信息反推不了就按未知处理而不是随便填一个高频值。因为产地信息直接关系道地药材判断填错比不填更危险。3.3 一条清洗链路示例我用一段伪代码说明整个清洗流程的思路方便你复现def clean_raw_record(record): # 1. 品名归一化 standard_name alias_map.get(record[raw_name]) # 匹配失败时先去除营销修饰词再尝试 if standard_name is None: cleaned_name remove_ads_prefix(record[raw_name]) standard_name alias_map.get(cleaned_name) # 2. 单位统一为元/公斤 price_per_kg normalize_unit(record[price], record[unit]) # 3. 产地补全和归一省级粒度 origin normalize_origin(record[origin]) if origin is None: origin infer_origin_from_batch(record[batch_id]) # 4. 异常值过滤 if is_outlier(standard_name, origin, price_per_kg): return None # 标记为异常不进入主数据 # 5. 结构化输出 return { standard_name: standard_name, origin: origin, price: price_per_kg, spec: normalize_spec(record[spec]), source: record[source], clean_time: now() }这段代码看着简单但实际跑的时候我调了一个多星期。最大的问题是去除修饰词这步——我一开始用正则硬匹配结果把野生黄芪里的野生去掉了后面又遇到了半野生仿野生栽培这类词正则规则越写越长。最后换成了词表匹配的方式先维护一个修饰词表包含近百个常见营销词再按词表逐个过滤逻辑清晰多了。4. 分类模型构建多源特征融合而不是单靠一个算法清洗完数据之后才是真正做分类的地方。我一开始天真地以为用现成的图像识别模型或者单纯的文本分类模型就能搞定。结果发现中药材分类是个典型的多源数据融合问题——单靠哪一类特征都不够。4.1 药材特征体系从性状、理化到生态和药性文本我设计的特征体系分四组总共36个特征维度性状特征外观颜色、形状、质地、断面特征、气味。这些数据主要来自药典描述和专家知识库的整理是分类的基础特征。理化特征有效成分含量、浸出物比例、水分占比、灰分等。这些来源于文献和质检数据虽然不是每味药材都有完整记录但只要有对分类的贡献就很大。生态特征产地的海拔范围、年均温、年降水量。这些数据可以从气象接口按产地聚合得到。生态特征对判断这个药材是不是道地产区的很有帮助。药性文本特征性味甘、苦、酸等、归经肝经、肺经等、功能主治的文本描述。这部分需要做文本向量化。分组设计的原因很直接不同维度的特征分布差异太大性状特征是分类变量理化特征是连续变量药性文本是非结构化文本不可能扔进同一个模型里直接训练。所以我把它们拆开先各自建模再做融合。4.2 算法选型为什么用随机森林做初筛再用BERT做功效分类我试过几种方案最终采用的是随机森林初筛 文本模型精分类的两级策略。第一级随机森林做药材大类初筛。把36维特征中的数值型特征理化成分、生态数据和编码后的分类型特征颜色、形状、质地一起喂给随机森林目标是把药材分到37个常见大类里。选随机森林而不是XGBoost主要因为样本量不够大而且特征里有不少缺失值随机森林对缺失值的容忍度比梯度提升类模型好得多。第二级BERT做药性功效的文本分类。把药典里功能主治的文本输入预训练BERT模型输出药材的治疗领域类别比如补虚类、清热类、活血化瘀类、解表类等。选BERT是因为它在短文本分类上的泛化能力比传统TF-IDF加机器学习模型强不少特别是在功效描述这类高度专业化的文本上。最后融合规则是随机森林给出大类得分BERT给出功效类别得分两者做加权合并。如果两个模型判断一致置信度会很高如果不一致就把该条记录标记为低置信样本进入人工复核队列。4.3 相似药材推荐与增量学习除了硬分类系统里还做了一个相似药材功能用的是改良的协同过滤思路。传统协同过滤基于用户行为但药材领域没有用户评分这种数据我用的是特征相似度——把每味药材的特征向量算出来用余弦相似度找最接近的几味药材。这个功能实际用起来很有意思。比如搜索当归系统不仅告诉你当归的信息还会推荐川芎白芍熟地黄——从特征上看它们确实都偏补血活血类配伍上也常用在一起。药师看了觉得有点意思。增量学习方面我用的是周级重训策略每周日凌晨用Spark把过去一周新增的标准化数据合并进训练集重新训练一次模型然后自动评估指标如果准确率下降超过阈值就回滚到上一版本。初期模型上线后前三周准确率有小幅波动到第四周开始稳定新数据的吸收确实让模型对市场俗名的识别能力变强了。5. 信息管理系统不只是增删改查而是把分类结果变成可用产品分类模型做出来之后还要有人能用起来。这套信息管理系统我定位成给药师和研究人员用的数据产品而不只是一个后台管理页面。5.1 检索与筛选几个关键交互设计检索是整个系统使用频率最高的功能。我做了三类检索来覆盖不同人群的需求关键词检索支持标准名、别名、拼音首字母。这一层用的是Elasticsearch的倒排索引查询响应基本在毫秒级。分类浏览按37个大类和8个功效类别逐级筛选。药师习惯先选大类再找具体品种和程序员习惯的搜索框逻辑不太一样。组合筛选药材产地、价格区间、功效标签、数据来源等字段自由组合过滤。页面交互有个细节值得提检索结果是双栏展示左栏是药材列表右栏是选中药材的详情卡片包含特征概览、相似药材推荐、产地分布和价格趋势。药师不需要来回跳页面浏览效率高很多。这个设计后来被合作方的药师评价为最实用的功能。5.2 可视化大屏让分类结果可以一眼看懂大屏是给管理层汇报用的但我不想做成一个只有好看图表的汇报工具。我的做法是把可视化分成三个层次概览层药材总量、分类别占比、产地分布热力图、价格区间分布。一屏看全适合汇报。分析层特定药材的价格趋势折线图、不同产地成分含量对比图、同类药材功效相似度关系图。适合做决策参考。明细层点击图表上的任何一个点可以直接穿透到对应的数据列表。这个下钻能力很关键否则大屏看完还得回列表查体验就会打折扣。图表用的ECharts地图用国内省市GeoJSON。整个系统部署在内网用Nginx做静态资源服务。5.3 知识图谱产地、功效、配伍关系的关联展示这算是系统的进阶功能。我用Neo4j构建了药材知识图谱节点包括药材、产地、功效、化学成分和常见配伍药材关系包括产自具有功效含有成分常与配伍四种。构建逻辑是把分类结果和清洗后的结构化数据做映射导入Neo4j。比如当归节点连接甘肃节点产自关系、补血节点具有功效关系、白芍节点常与配伍关系。知识图谱的价值在于它提供了一种探索式的信息获取方式。药师输入白术图谱不仅展示白术本身的信息还能看到它常和茯苓甘草配伍而茯苓又对应利水渗湿的功效——这种关联是传统列表式管理系统完全给不了的。我在后续迭代中加了一个最短路径查询比如补血到活血之间经过哪些药材研究药对配伍的同事用了都说方便。6. 实测效果与踩坑记录系统跑通之后我对它做了完整的评估。效果和问题都得拿出来说说特别是那些书上不会写的坑。6.1 分类准确率到底多少为什么没有盲目追求高指标在自己整理的标准化数据集上药材大类分类的准确率是87%左右功效分类准确率在82%左右。这个数字不算惊艳但已经达到了可用的水平。我没有盲目追求更高的准确率原因有三训练数据的标注本身存在不一致。药典、市场、电商三个来源对同一味药的功效描述并不完全一致标注的波定性决定了模型的天花板。分类错误的样本主要集中在同名异物和产地混淆上。这两类问题靠提高模型复杂度解决不了需要靠业务规则和人工审核兜底。系统定位是辅助决策工具必须保留人工复核环节。与其追求99%的自动准确率不如把剩下1%明确暴露出来让人处理。在报告中我如实区分了模型可自动处理和需要人工复核的比例。这样做的结果是药师对系统的接受度比我预想的高很多——他们不信任一个自称完美的东西但信任一个清楚知道自己边界的工具。6.2 三个印象最深的坑第一个坑是药典PDF解析。我最初用Python的PDF库直接提取文本结果表格、脚注、上下标混在一起一页能提取出好几段乱码。后来换成先转图片再OCR的方案准确率才上来。这个坑几乎折磨了我将近一周后来总结的经验就是处理任何扫描版PDF之前先想清楚里面是文本层还是纯图片别上来就写正则。第二个坑是电商数据里的野生前缀。我一开始把野生黄芪和黄芪归为同一条药材后来发现不对——野生和种植的黄芪有效成分含量有差异价格差异更大。系统的解决方式是保留是否野生这个字段作为规格属性而不是把它当噪声清洗掉。从中我得到的教训是别急着清理你自认为是噪声的数据有些字段在行业里恰恰是关键区分维度。第三个坑是冷启动问题。新的市场品种进入系统时没有历史数据分类模型对它一无所知。我的兜底方案是零样本规则新药材先走别名映射和存在规则判断判断不了就强制走人工审核审核通过后再补充进训练集。冷启动不可能完全自动化但可以设计一条最小人工干预的流程让审核效率尽量高。6.3 给想做类似项目的人的建议梳理完整个项目之后我给自己做了几条总结也送给正准备做这类系统的人数据规范文档写得比代码还详细。这个项目最值钱的不是那些模型而是清洗逻辑里沉淀下来的别名表、修饰词表和单位换算规则。这些经验一旦丢失重新再建的成本极高。搭架构时一定要预留重跑能力。清洗和模型训练任务做成可重跑的批处理配合数据快照可以把系统出Bug的成本压到最低。别贪数据量。初期6万条记录里真正能进主数据的只有4万余条剩下的都因为质量问题被过滤掉了。数据质量不够的时候堆数据量是没意义的。学会向行业专家低头。我一开始设计的分类体系被药师否了两次。后来才明白系统是给人用的不是给算法证明自己的。专家说这个分类不合理那就是真的不合理哪怕模型准确率再高。整套系统做下来最大的成就感反而不是模型跑通了而是看着药房里的人开始习惯用系统查药材信息、看价格趋势、找相似药材。数据能把老师傅脑子里那些模糊的经验变成一个可检索、可追溯、可分析的资产——这件事本身比任何高深的算法都更有价值。