背景介绍
中药炮制是根据中医药理论,依照临床辨证施治用药的需要和药物自身性质,以及调剂、制剂的不同要求,将中药材制备成中药饮片所采取的一项制药技术。平时我们老百姓能接触到的中药,主要指自己回家煎煮或者请医院代煎煮的中药,都是中药饮片,也就是中药炮制这个技术的结果。而中药炮制饮片,大部分涉及到水火的处理,一定需要讲究“程度适中”,炮制火候不够达不到最好药效,炮制火候过度也会丧失药效。
- “生品”一般是指仅仅采用简单净选得到的饮片,通常没有经过火的处理,也是后续用火加工的原料。
- “不及”就是“炮制不到位”,没有达到规定的程度,饮片不能发挥最好的效果。
- “适中”是指炮制程度刚刚好,正是一个最佳的炮制点位,也是通常炮制结束的终点。
- “太过”是指炮制程度过度了,超过了“适中”的最佳状态,这时候的饮片也会丧失药效,不能再使用了。
过去的炮制饮片程度的判断,都是采用的老药工经验判断,但随着老药工人数越来越少,这种经验判断可能存在“失传”的风险。而随着人工智能的发展,使用深度神经网络模型对饮片状态进行判断能达到很好的效果,可以很好的实现经验的“智能化”和经验的传承。
ResNet网络简介
ResNet50网络是2015年由微软实验室的何恺明提出,获得ILSVRC2015图像分类竞赛第一名。
数据集介绍
我们使用“中药炮制饮片”数据集,该数据集由成都中医药大学提供,共包含中药炮制饮片的 3 个品种,分别为:蒲黄、山楂、王不留行,每个品种又有着4种炮制状态:生品、不及适中、太过,每类包含 500 张图片共12类5000张图片,图片尺寸为 4K,图片格式为 jpg。 下面是数据集中的一些样例图片:
实训实践
按照提示,运行实训代码
进入实训平台:https://xihe.mindspore.cn/projects
选择“jupyter 在线编辑器”
启动“Ascend开发环境” :Ascend开发环境需要申请,大家可以申请试试看
启动开发环境后,在左边的文件夹中,选择“应用实践”-“热门LLM及其它AI应用”-“应用实践/热门LLM及其他AI应用/基于MindSpore实现ResNet50中药分拣.ipynb”
打开这个ipynb文件后,选择“运行全部”
训练还是需要一些时间的,数据集处理也需要一些时间,主要是原图片尺寸为4k比较大,需要预处理将图片resize到指定尺寸,比较耗费时间。
数据集划分
代码还是比较全面的,所以看起来有点复杂
from sklearn.model_selection import train_test_split
import shutildef split_data(X, y, test_size=0.2, val_size=0.2, random_state=42):"""This function splits the data into training, validation, and test sets."""# Split the data into training and test setsX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=random_state)# Split the training data into training and validation setsX_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=val_size/(1-test_size), random_state=random_state)return X_train, X_val, X_test, y_train, y_val, y_testdata_dir = "dataset1/zhongyiyao"
floders = os.listdir(data_dir)
target = ['train','test','valid']
if set(floders) == set(target):# 如果已经划分则跳过pass
elif 'train' in floders:# 如果已经划分了train,test,那么只需要从train里边划分出validfloders = os.listdir(data_dir)new_data_dir = os.path.join(data_dir,'train')classes = os.listdir(new_data_dir)if '.ipynb_checkpoints' in classes:classes.remove('.ipynb_checkpoints')imgs = []labels = []for (i,class_name) in enumerate(classes):new_path = new_data_dir+"/"+class_namefor image_name in os.listdir(new_path):imgs.append(image_name)labels.append(class_name)imgs_train,imgs_val,labels_train,labels_val = X_train, X_test, y_train, y_test = train_test_split(imgs, labels, test_size=0.2, random_state=42)print("划分训练集图片数:",len(imgs_train))print("划分验证集图片数:",len(imgs_val))target_data_dir = os.path.join(data_dir,'valid')if not os.path.exists(target_data_dir):os.mkdir(target_data_dir)for (img,label) in zip(imgs_val,labels_val):source_path = os.path.join(data_dir,'train',label)target_path = os.path.join(data_dir,'valid',label)if not os.path.exists(target_path):os.mkdir(target_path)source_img = os.path.join(source_path,img)target_img = os.path.join(target_path,img)shutil.move(source_img,target_img)
else:phones = os.listdir(data_dir)imgs = []labels = []for phone in phones:phone_data_dir = os.path.join(data_dir,phone)yaowu_list = os.listdir(phone_data_dir)for yaowu in yaowu_list:yaowu_data_dir = os.path.join(phone_data_dir,yaowu)chengdu_list = os.listdir(yaowu_data_dir)for chengdu in chengdu_list:chengdu_data_dir = os.path.join(yaowu_data_dir,chengdu)for img in os.listdir(chengdu_data_dir):imgs.append(img)label = ' '.join([phone,yaowu,chengdu])labels.append(label)imgs_train, imgs_val, imgs_test, labels_train, labels_val, labels_test = split_data(imgs, labels, test_size=0.2, val_size=0.2, random_state=42)img_label_tuple_list = [(imgs_train,labels_train),(imgs_val,labels_val),(imgs_test,labels_test)]for (i,split) in enumerate(spilits):target_data_dir = os.path.join(data_dir,split)if not os.path.exists(target_data_dir):os.mkdir(target_data_dir)imgs_list,labels_list = img_label_tuple_list[i]for (img,label) in zip(imgs_list,labels_list):label_split = label.split(' ')source_img = os.path.join(data_dir,label_split[0],label_split[1],label_split[2],img)target_img_dir = os.path.join(target_data_dir,label_split[1]+"_"+label_split[2])if not os.path.exists(target_img_dir):os.mkdir(target_img_dir)target_img = os.path.join(target_img_dir,img)shutil.move(source_img,target_img)
训练两个epoch精度就达到了99%,模型还是很厉害的
Epoch 1
-------------------------------
loss: 2.545927 [ 0/137]
loss: 0.205195 [100/137]
loss: 0.227581 [136/137]
Test: Accuracy: 96.9%, Avg loss: 0.110591 precision recall f1-score supportsz_tg 1.000 1.000 1.000 111wblx_tg 1.000 1.000 1.000 90wblx_sz 1.000 1.000 1.000 91ph_sp 1.000 0.978 0.989 90sz_bj 0.762 1.000 0.865 93ph_bj 0.977 1.000 0.989 86sz_sz 1.000 1.000 1.000 82wblx_bj 1.000 1.000 1.000 99sz_sp 1.000 0.651 0.788 83wblx_sp 1.000 1.000 1.000 85ph_sz 0.963 1.000 0.981 79ph_tg 1.000 0.970 0.985 99accuracy 0.969 1088macro avg 0.975 0.967 0.966 1088
weighted avg 0.975 0.969 0.968 1088Epoch 2
-------------------------------
loss: 0.078420 [ 0/137]
loss: 0.035822 [100/137]
loss: 0.079931 [136/137]
Test: Accuracy: 99.6%, Avg loss: 0.025822 precision recall f1-score supportsz_tg 1.000 1.000 1.000 111wblx_tg 1.000 1.000 1.000 90wblx_sz 1.000 1.000 1.000 91ph_sp 1.000 0.978 0.989 90sz_bj 1.000 0.978 0.989 93ph_bj 0.977 1.000 0.989 86sz_sz 1.000 1.000 1.000 82wblx_bj 1.000 1.000 1.000 99sz_sp 0.976 1.000 0.988 83wblx_sp 1.000 1.000 1.000 85ph_sz 1.000 1.000 1.000 79ph_tg 1.000 1.000 1.000 99accuracy 0.996 1088macro avg 0.996 0.996 0.996 1088
weighted avg 0.996 0.996 0.996 1088
后面的推理结果相当不错!