news 2026/10/1 1:37:00

葡萄酒质量检测实战:从特征工程到分类模型的机器学习完整流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
葡萄酒质量检测实战:从特征工程到分类模型的机器学习完整流程

简介:面向计算机、电子信息工程、数学等专业学生的Python机器学习实践项目,聚焦葡萄酒质量检测场景,涵盖数据预处理、特征分析与模型训练等典型环节,适合作为课程设计、期末大作业或毕业设计的参考资料。压缩包为rar格式,整体大小26.59MB,内含项目源码、实验数据与说明文档,源码结构清晰,数据可直接用于模型验证,说明文档有助于快速理解项目思路与代码逻辑。资源内附带的说明文档还对运行环境、数据字段与代码模块做了梳理,便于读者快速上手。目前已有2696人学习下载,内容实用且贴近真实任务,适合具备一定Python与机器学习基础、希望参考完整项目流程来调试代码或扩展功能的读者。通过这份材料,可以学习如何将分类算法应用于实际数据集,并借鉴其工程化组织方式,为独立完成类似检测任务提供参考。

1. 葡萄酒质量检测项目到底在做什么:一个能跑通全流程的机器学习样板

拿到「基于Python机器学习的葡萄酒质量检测项目」这套东西,大多数人第一反应是:这不就是拿公开的Wine Quality数据集跑个分类模型吗?确实,数据集本身不稀奇,但把这个项目认真做完,你等于把机器学习入门到实战的一条完整链路走了一遍——从数据探查、特征工程、模型训练到结果评估,每一步都有坑在等你。这也是为什么大量Python机器学习教程和课程设计都会拿它当样板:数据量小、特征明确、标签清晰,新手看得懂,老手能玩出花。这套源码加数据加说明文档的组合,适合三类人:想交一份靠谱课程设计的在校生、刚入行需要练手的Python开发,以及想搞懂分类模型评估指标的检测类从业者。它能回答的不只是「葡萄酒好不好喝」,而是「机器学习的检测项目到底应该怎么做才规范」。

2. 先弄清楚数据和任务:红白葡萄酒要分开建模,更要先定分类还是回归

2.1 数据集长什么样:字段含义、质量分布和样本量差异

Wine Quality数据集是机器学习入门最常用的公开数据集之一,包含了红葡萄酒和白葡萄酒两个独立文件。常见做法是红白两份数据分开建模,而不是混在一起训练,原因后面会细说。每个文件是CSV格式,行是不同批次的葡萄酒样本,列是11个理化指标加1个质量评分。

这11个理化指标分别是:固定酸度(fixed acidity)、挥发性酸度(volatile acidity)、柠檬酸(citric acid)、残糖(residual sugar)、氯化物(chlorides)、游离二氧化硫(free sulfur dioxide)、总二氧化硫(total sulfur dioxide)、密度(density)、pH值、硫酸盐(sulphates)、酒精(alcohol)。质量评分是一个3到8(红)或3到9(白)的整数,来源是品酒师打分后的中位数,不是主观单次评分。

样本量方面,红葡萄酒大约1600条,白葡萄酒接近4900条。这个数量级对机器学习来说不算大,但做课程设计或者入门实战完全够用。要注意的是,两张表的特征数量一样,但数据分布差很多,比如白葡萄酒的残糖和二氧化硫含量明显更高。这就是为什么我拿到项目第一步不是急着训练模型,而是先加载数据,把两份文件的分布差异看清楚。

2.2 质量检测到底是分类任务还是回归任务:两种建模方式的取舍

同一个数据集可以有完全不同的建模方式,这是这个项目最值得想清楚的地方。如果把它当回归任务,就是用11个指标去预测质量评分这个连续数值,最后算均方误差(MSE)或者R²。如果把它当分类任务,常见做法是二分类——把评分大于等于7的列为「好酒」,其余为「普通酒」——或者三分类,把3到4归为低、5到6归为中、7以上归为高。

我一般建议项目优先做分类,理由有两条。第一,品酒师评分本身就是离散的整数,而且高度集中在5和6分,回归模型在6分附近会非常拥挤,误差大且难解释;第二,分类模型的评估指标(准确率、F1、混淆矩阵)对新手更直观,也更容易在说明文档里把逻辑写清楚。如果非要走回归,更适合的用途是预测某个特征调整后评分的相对变化趋势,而不是给出精确评分。

决定任务类型要在训练之前就定下来,因为它直接影响标签构造方式和评估指标。二分类是最稳的选择:把质量7分及以上视为「优质」,6分及以下视为「普通」,问题立刻变成「这瓶酒值不值得推荐」,贴合检测场景的实际语义。

2.3 用pandas做第一次数据探查:加载文件、看缺失值和基本统计量

动手第一步,先把CSV加载进来做基本检查。我习惯的流程是:读取文件、查看行列数、检查缺失值、看describe统计量、确认标签分布。这五步走完,这个数据集能不能用、该不该做清洗,心里就有数了。

import pandas as pd # 加载红白两份数据,注意sep=';',Wine Quality数据集是分号分隔 red = pd.read_csv('winequality-red.csv', sep=';') white = pd.read_csv('winequality-white.csv', sep=';') # 基础检查:形状、列名、缺失值 print("红葡萄酒形状:", red.shape) print("白葡萄酒形状:", white.shape) print("红葡萄酒缺失值:\n", red.isnull().sum().sum()) print("白葡萄酒缺失值:\n", white.isnull().sum().sum()) # 标签分布,看质量评分是否均衡 print("红葡萄酒质量分布:\n", red['quality'].value_counts().sort_index()) print("白葡萄酒质量分布:\n", white['quality'].value_counts().sort_index())

加载时最容易翻车的是分隔符。这个数据集的CSV不是逗号分隔,而是分号分隔,如果用默认的read_csv加载,会发现所有列挤成一列,后面全部代码白跑。缺失值这一项,两份数据基本都是0,这是好消息,意味着不需要做填充处理。质量分布会看到明显的长尾:红葡萄酒里5分和6分占了约75%,白葡萄酒同样集中在5分和6分,高分和低分样本都很少。这个不平衡直接决定了后续要不要做类别处理。

3. 特征工程与训练集划分:标准化、相关性筛选和类别不平衡

3.1 为什么葡萄酒特征必须先做标准化:量纲差异的真实影响

看一下描述统计就会发现问题:固定酸度动辄七八克每升,游离二氧化硫是几十毫克每升,酒精含量只有9到15,而密度是0.99到1.00这种小数点后两位的数值。这些特征的量纲差异不是一倍两倍,而是几十倍。如果不做标准化,直接丢给模型,逻辑回归这类基于距离和权重的模型会被量纲大的特征主导,模型权重完全失去可解释性。

标准化常见做法是StandardScaler,把每个特征变成均值0、方差1的标准正态分布。要注意标准化是在划分训练集和测试集之后做的,而且只能用在数值特征上。先把特征和标签拆开,再处理特征,最后才进入模型。

from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split # 特征和标签分离:假设已经构造好二分类标签,1代表优质酒 X = red.drop('quality', axis=1) y = red['quality'].apply(lambda x: 1 if x >= 7 else 0) # 先划分,再标准化,避免数据泄漏 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y ) scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test)

这串代码里的关键点有两个。第一是stratify=y,按标签比例分层采样,保证训练集和测试集里优质酒的比例一致;第二是scaler.fit_transform只用在训练集,测试集只用transform,绝对不能重新fit。一旦把测试集的均值方差混进标准化参数,得到的结果就是数据泄漏,评估分数会虚高。数据泄漏是这类检测项目里最隐蔽也最致命的错误。

3.2 相关性排查:哪些指标真正影响质量评分

特征之间高度相关会带来多重共线性,尤其在逻辑回归里会让权重估计不稳定。Wine Quality数据里最典型的例子是密度和残糖、游离二氧化硫和总二氧化硫之间相关性很强。可以画相关性热力图,也可以直接打印相关系数矩阵挑出高相关特征。

# 计算特征之间的相关系数,找出高度相关的对 corr = X.corr() high_corr_pairs = [] for i, col in enumerate(corr.columns): for j in range(i + 1, len(corr.columns)): if abs(corr.iloc[i, j]) > 0.7: high_corr_pairs.append((corr.columns[i], corr.columns[j], round(corr.iloc[i, j], 2))) for pair in high_corr_pairs: print(pair)

输出里你会看到密度和残糖的相关系数在0.5到0.7之间,总二氧化硫和游离二氧化硫更是接近0.7。这个阈值取0.7是我习惯的经验值,大于0.7说明两个特征携带了大量重复信息。处理方式倒不一定直接删除,因为随机森林和XGBoost对多重共线性不敏感,但对逻辑回归来说,保留高度相关的特征会让系数解释变得别扭。我一般会在说明文档里记录这些相关对,然后选择保留业务含义更明确的一个,比如保留酒精和硫酸盐这种与发酵过程直接相关的指标。

3.3 类别不平衡要不要处理:评分集中在中段带来的模型偏置

前面已经看到,优质酒(7分以上)在红葡萄酒里只占约15%,白葡萄酒里更低。这就是典型的类别不平衡。如果不处理,模型为了最小化损失,会倾向于把绝大多数样本预测为普通酒——准确率看着很高,可能超过85%,但优质酒几乎全部被漏掉。对于一个检测项目来说,漏报优质酒比误报普通酒更严重,因为检测的意义就是要把少数关键样本找出来。

处理不平衡有几种常见做法。最简单的是改阈值:模型预测概率大于0.3就算优质,而不是默认的0.5。更常规的是用class_weight='balanced',让少数类样本按比例获得更高权重。SMOTE过采样也常被提到,但对这个数据集来说,样本量本来就不大,合成样本容易过拟合,我不太推荐在课程设计里用。先用class_weight,再看混淆矩阵判断效果,这个路径最稳。

4. 用scikit-learn训练基线模型:逻辑回归、随机森林、XGBoost

4.1 为什么这三个模型作为基线组合最有代表性

这个项目选模型,我一般固定三件套:逻辑回归、随机森林、XGBoost。逻辑回归是线性基线,跑得快,结果够直观,权重系数能直接解读为「酒精每提高一个标准差,优质概率上升多少」;随机森林是非线性树的代表,能自动处理特征交互,不需要太多预处理;XGBoost则是梯度提升树,通常在准确率上能刷新前两者的上限,但也最容易过拟合。

三件套的另一个好处是能覆盖「线性模型 vs 树模型」的对比维度,这在说明文档里是很好的分析素材。读者做课程设计或面试讲项目时,可以明确说出「逻辑回归在测试集上准确率多少,随机森林提升多少,XGBoost在高分样本的召回率上又强在哪里」。光是这个对比表,就够撑起大半个项目的技术深度。

4.2 逻辑回归训练:默认参数先跑一遍,看权重和基线分数

先用默认参数跑一遍逻辑回归,拿到基线数字,再谈优化。这里要注意max_iter,默认的100次迭代在标准化后的数据上经常不收敛,跑出告警,直接改成1000省心。模型评估我用准确率和F1同时看,因为准确率在不平衡数据上会骗人,F1才能反映少数类的真实表现。

from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score, f1_score, classification_report # 逻辑回归,线性基线,max_iter给足 lr = LogisticRegression(max_iter=1000, class_weight='balanced') lr.fit(X_train_scaled, y_train) y_pred_lr = lr.predict(X_test_scaled) print("逻辑回归准确率:", accuracy_score(y_test, y_pred_lr)) print("逻辑回归F1:", f1_score(y_test, y_pred_lr)) print(classification_report(y_test, y_pred_lr))

class_weight='balanced'在这里作用很明显,它按类别频率反向调整样本权重,让优质酒的误判代价更大。跑完打印的classification_report里有precision、recall、F1,重点看优质酒那一行的recall,如果低于0.5,说明这个模型根本没把少数类当回事。权重可以打印出来看生活:coefficient绝对值最大的特征,往往是酒精、挥发性酸度、硫酸盐这几个,和葡萄酒工艺的经验吻合。这个可解释性是逻辑回归独有的价值,树模型给不了。

4.3 随机森林与XGBoost:树模型的优势和过拟合风险

随机森林用默认参数先跑,不用急着调。它不需要标准化,所以直接拿原始特征训练就可以,但要注意训练集上的准确率,如果接近100%而测试集只有80%出头,就是过拟合的典型信号。树深限制、最小样本数这些参数可以稍后再动。

from sklearn.ensemble import RandomForestClassifier # 随机森林,树模型不需要标准化,直接用原始特征 rf = RandomForestClassifier(n_estimators=200, random_state=42) rf.fit(X_train, y_train) y_pred_rf = rf.predict(X_test) print("随机森林准确率:", accuracy_score(y_test, y_pred_rf)) print("随机森林F1:", f1_score(y_test, y_pred_rf))

n_estimators=200是经验值,太少容易欠拟合,太多收益递减还拖慢速度。树模型在这里表现通常优于逻辑回归,因为酒精、挥发酸这类特征对质量的贡献不是线性的,比如酸度过低和过高都不好,中间有个最佳区间,决策树天然能切出这种非线性边界。但如果项目说明文档里只写了随机森林,而不对比其他模型,这个项目的分析深度一眼就会被看穿。

XGBoost的用法稍微多两行。要注意两个参数习惯。第一,eval_metric建议用logloss而不是默认的准确率,因为梯度提升过程需要概率输出;第二,early_stopping_rounds配合验证集可以自动在过拟合前停住,这是最实用的调参手段。

from xgboost import XGBClassifier # XGBoost,用early_stopping在过拟合前停住 xgb_model = XGBClassifier( n_estimators=300, max_depth=5, learning_rate=0.1, eval_metric='logloss', early_stopping_rounds=20, random_state=42 ) xgb_model.fit( X_train, y_train, eval_set=[(X_test, y_test)], verbose=False )

这串代码里的eval_set用来指定早停监控的验证集,early_stopping_rounds=20表示连续20轮验证损失不下降就停。注意,早停之后n_estimators会被实际使用的树数量覆盖,打印xgb_model.best_iteration能看到训练真正用了多少棵树。XGBoost在这个数据上一般能跑到比随机森林高两三个点的F1,但代价是训练时间变长,且调参空间大,容易在无关参数上浪费时间。

4.4 评估指标怎么选:准确率、F1和混淆矩阵的适用场景

单看准确率会掩盖关键问题。红葡萄酒里优质样本只有15%,一个「全都预测普通」的模型准确率也能有85%,但完全没用。检测类项目里,漏检少数类的代价远高于误检,所以必须同时看F1和混淆矩阵。

from sklearn.metrics import confusion_matrix # 混淆矩阵:行是真实类别,列是预测类别 cm = confusion_matrix(y_test, y_pred_rf) print("混淆矩阵:") print(cm) # 输出格式 [[TN, FP], [FN, TP]] sensitivity = cm[1, 1] / (cm[1, 1] + cm[1, 0]) specificity = cm[0, 0] / (cm[0, 0] + cm[0, 1]) print("召回率:", round(sensitivity, 3)) print("精确率:", round(cm[1, 1] / (cm[1, 1] + cm[0, 1]), 3))

混淆矩阵的四格一眼就能看出模型在哪个方向上犯错。左下角的FN是「实际优质但被漏掉」的样本,这个数越小越好。如果它远大于右上角的FP,说明模型偏保守,宁可漏检也不误报,这在葡萄酒检测里未必是坏事,取决于使用场景。做说明文档时,把三个模型的三个混淆矩阵并排放在一起,结论自然就出来了:逻辑回归偏保守但可解释性强,随机森林均衡,XGBoost在高分段的召回率最高。

5. 葡萄酒质量检测项目的避坑手册:数据泄漏、过拟合和评分偏移

这一章是给你留后悔药的地方。我整理了自己做这个项目踩过的坑,按现象、原因、解决三步写,每一条都能直接对应到代码里查。

5.1 数据泄漏:标准化顺序错了,模型分数虚高还不自知

现象:标准化之后测试集准确率比训练集还高,或者跟训练集几乎一样,一看就觉得不对劲。

原因:对全量数据做了StandardScaler的fit,然后再划分训练集和测试集。这样的话,测试集的均值和方差已经被模型「偷看」了,评估结果是骗人的。更隐蔽的变种是在交叉验证里对整个数据集做标准化,每一折的验证集都泄漏了。

解决:永远先train_test_split,再对训练集fit_transform,对测试集只transform。写一个检查习惯:每次划分前问自己一句,scaler是fit在什么数据上的。如果要用交叉验证,标准化要放进Pipeline里,让每一折都重新fit,这是唯一正确的做法。

5.2 过拟合:训练集准确率99%,测试集却只有82%

现象:随机森林在训练集上准确率接近100%,但到测试集就掉到82%。XGBoost更夸张,树一加到300棵,训练集几乎全对,测试集纹丝不动甚至下降。

原因:决策树本身就是高方差模型,可以无限记住训练集的噪声点。数据量只有1600条,特征多,噪声占比相对高,树又足够深,过拟合几乎是必然。

解决:先把max_depth限制在5到7,不要放任默认值。然后看min_samples_leaf,调到10到20,强制每个叶子节点至少有十几个样本,模型自然变「钝」。最后用early stopping,这是对梯度提升最有效的一招。记住一个原则:模型复杂度增加的速度,必须慢于训练集拟合提升的速度。

5.3 红白葡萄酒评分分布差异大:混在一起训练让你的模型学偏

现象:把红白两份数据合到一张表里训练,准确率看着不低,但单独看白葡萄酒的优质酒召回率惨不忍睹。

原因:白葡萄酒的残糖和二氧化硫含量整体高于红葡萄酒,品酒师对两种酒的评分标准也不同。混合训练相当于强迫一个模型同时拟合两种分布,模型只能取中间地带,两边都不讨好。

解决:坚持红白分开建模。说明文档里写清楚两份数据的描述统计差异,分别展示各自的模型结果,这个项目瞬间从「跑通代码」变成「做了对比实验」。课程设计评分和面试提问都很吃这一套。

5.4 类别不平衡:全部预测为普通酒,准确率还行但项目毫无意义

现象:逻辑回归不设class_weight时,预测结果几乎全是0(普通酒),测试集F1只有0.2,但准确率还有85%。

原因:优质酒只占15%,模型计算损失时,少数类的总损失太小,自然被忽略。默认的0.5决策阈值对不平衡数据太「高」,模型概率输出很少能超过它。

解决:先加class_weight='balanced',多数情况够用。如果还不够,就把决策阈值下调,用predict_proba取概率列,大于0.3就判为优质。在说明文档里记录这个阈值调整过程,这是深度的体现。不建议在这个小数据集上上SMOTE,合成样本在树模型上容易引起额外过拟合。

5.5 运行报错:分号分隔、版本兼容和中文路径

现象:CSV读出来所有列挤在一起;sklearn和xgboost版本不匹配报ValueError;Windows下数据文件放在中文路径里读不了。

原因:Wine Quality数据是分号分隔,read_csv默认逗号分隔直接读错。xgboost函数签名在0.90和1.0之后有大变化,老代码直接报错。中文路径在部分Windows环境的编码处理上确实有兼容问题。

解决:读文件一律写sep=';'。环境上建议Python 3.8以上,scikit-learn装1.1以上版本,xgboost装1.6以上,安装完跑一行import xgboost先验证。数据文件路径全部用英文目录,这是最快最稳的规避方式。

6. 让模型结果站得住脚:交叉验证、网格调参和特征重要性

6.1 交叉验证:单次划分的结果不可信,用5折交叉验证看稳定性

单次划分测试集的结果只有一次运气成分,样本量小的时候尤其明显。用交叉验证跑一遍,看所有折的均值方差,才算给结果上了保险。

from sklearn.model_selection import cross_val_score # 5折交叉验证,cv值越大越稳但越慢 scores = cross_val_score(lr, X_train_scaled, y_train, cv=5, scoring='f1') print("每折F1:", scores) print("平均F1:", scores.mean(), "标准差:", scores.std())

cv=5表示5折,每折用80%数据训练、20%验证。标准差如果大于0.05,说明模型在不同数据子集上表现波动太大,优先回去处理过拟合而不是继续调参。交叉验证的结果在说明文档里比单次划分更有说服力,面试或答辩时直接拿这个数字说话。

6.2 参数搜索:GridSearchCV跑随机森林和XGBoost的调参方向

网格搜索不需要覆盖太多参数,每个模型挑两三个关键参数就好。随机森林看max_depth和min_samples_leaf,XGBoost看learning_rate和colsample_bytree。

from sklearn.model_selection import GridSearchCV # 随机森林:只搜树的深度和叶子最小样本数,减少搜索空间 param_grid = { 'max_depth': [5, 7, 10], 'min_samples_leaf': [5, 10, 20] } grid = GridSearchCV( RandomForestClassifier(n_estimators=200, random_state=42), param_grid, cv=5, scoring='f1', n_jobs=-1 ) grid.fit(X_train, y_train) print("最佳参数:", grid.best_params_) print("最佳F1:", grid.best_score_)

n_jobs=-1让所有CPU核心并行跑,速度快不少。搜索范围宁可小也不要大,参数组合从3乘3的9个起步,覆盖了主要方向,不会太慢。XGBoost的搜索同理,但加上learning_rate和n_estimators的联动:学习率小就得多加树,学习率大就早停,两个参数单独搜容易自相矛盾。

6.3 特征重要性:回答「什么决定了葡萄酒质量」这个核心问题

模型调完参数之后,最后一个让人信服的环节是解释特征重要性。随机森林直接有feature_importances_属性,XGBoost也有。把排名前五的特征列出来,对照葡萄酒工艺知识写进说明文档,整个项目就从「跑了几个模型」变成了「做了一次有业务洞察的分析」。

import numpy as np # 提取特征重要性,按从大到小排序,输出前5个最重要的特征 importance = rf.feature_importances_ feature_names = X.columns indices = np.argsort(importance)[::-1] for i in range(5): print(f"第{i+1}重要: {feature_names[indices[i]]}, 重要性评分: {importance[indices[i]]:.3f}")

输出里酒精、挥发性酸度、硫酸盐通常会排在前面。这三个指标恰好对应葡萄酒工艺里最核心的控制项:酒精是发酵产物,挥发性酸度直接决定酒是否变质,硫酸盐是防腐和抗氧化指标。把模型结果和这些常识对照上,项目的可信度就立住了。这是我做完这个项目后最深的体会——机器学习检测的意义不在于模型本身有多花哨,而在于它能不能帮你找出真正值得关注的那几个变量。希望这个项目的实践能帮到你,也帮你自己建立起「先看数据、再定任务、最后才选模型」的做事习惯。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 1:36:45

马德拉岛深度游:加强酒、水渠徒步与火山岛美食全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 1:36:30

CentOS 8 yum-utils找不到?本质是仓库EOL导致的系统代际迁移问题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 1:36:23

卡尔曼滤波连续到离散:嵌入式落地的核心转换

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 1:35:38

电磁阀选型核心:从位通逻辑到二位五通、三位五通与驱动电路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 1:33:17

DDI药物相互作用预测实战:PubMed规模数据+GraphDTA复现指南

简介:本资源是一套基于Python与Jupyter Notebook实现的深度学习药物相互作用预测完整项目,面向计算机、生物信息学或药学相关专业的本科生与研究生,适用于毕业设计、课程设计及科研入门实践。项目聚焦于利用图神经网络等深度学习方法建模药物…

作者头像 李华
网站建设 2026/10/1 1:33:02

Wine + FEX-Emu + DXMT:ARM设备运行Windows应用全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华