福州做网站价格,桂林网络推广外包,wordpress页面,263企业邮箱账号格式离线评估方法离线评估的基本原理是在离线环境中#xff0c;将数据集划分为“训练集”和“测试集”#xff0c;用“训练集”训练模型#xff0c;用“测试集”评估模型#xff0c;根据数据集划分方法的不同#xff0c;离线评估可以分为以下3种。Holdout检验Holdout检验是基础… 离线评估方法离线评估的基本原理是在离线环境中将数据集划分为“训练集”和“测试集”用“训练集”训练模型用“测试集”评估模型根据数据集划分方法的不同离线评估可以分为以下3种。Holdout检验Holdout检验是基础的离线评估方法它将原始的样本集合随机的划分为训练集和验证集两部分。通常选择7:3作为划分比例70%的样本用于模型的训练30%的样本用于模型的评估。Holdout的缺点是在验证集上计算出来的评估指标与训练集和验证集的划分有直接的关系如果仅进行少量的Holdout检验则得到的结论存在较大的随机性。为了消除这种随机性“交叉检验”的思想被提出。交叉检验 k-fold交叉验证先将全部样本划分成k个大小相等的样本子集依次遍历这k个子集每次都先把当前子集作为验证集其余所有子集作为训练集进行模型的训练和评估最后把所有k次的评估指标的平均值作为最终的评估指标。在实际经验中k通常取10。留一验证每次留下一个样本作为验证集其余所有样本作为测试集。样本总数为n依次遍历所有n个样本进行n次验证再将评估指标求平均得到最终指标。在样本总数较多的情况下留一验证发的时间开销极大。事实上留一验证是留p验证的特例。留p验证是指每次留下p个样本作为验证集而从n个元素中选择p个元素有种可能因此它的时间开销远远高于留一验证故很少在实际工程中应用。自助法不管是holdout检验还是交叉检验都是基于划分训练集和测试集的方法进行模型评估的然后当样本规模比较小时将样本集进行划分会让训练集进一步减小这可能会影响模型的训练效果。自助法可以在一定程度上解决这个问题。自助法(Bootstrap)是基于自采样的检验方法对于总数为n的样本集合进行n次有放回的随机采样得到大小为n的训练集。在n次采样过程中有的样本会被重复采样有的样本没有被采样过这些没有被采样的样本作为验证集进行模型验证这就是自助法的验证过程。离线评估指标准确率准确率(Accuracy)是指分类正确样本占总样本个数的比例即其中为被正确分类的样本个数为总样本个数TP表示预测为正并且实际也为正的样本个数TN表示预测为负并且实际也为负的样本个数FP表示预测为正但实际为负的样本个数FN表示预测为负但实际为正的样本个数。准确率是分类任务中较直观的评价指标虽然其具有较强的可解释性但也存在缺陷(1)当不同类别的样本比例非常不均衡时占比大的类别往往成为影响准确率的最主要因素。例如如果负样本占99%那么分类器把所有样本都预测为负样本可以获得99%的准确率。(2)结果太笼统实际应用中我们可能更加关注某一类别样本的情况。比如搜索时会关心 “检索出的信息有多少是用户感兴趣的”“用户感兴趣的信息有多少被检测出来了” 等等。相应地还有错误率分类错误的样本占总样本的比例。其公式化描述如下更一般的分类错误率定义为其中I() 是指示函数当条件为真时指示函数的函数值为1否则为0。基于此准确率可以表示为而更一般的对于数据分布D和概率密度函数p(⋅)错误率与精度可分别描述为采用sklearn计算准确率demo如下from sklearn.metrics import accuracy_scorey_pred [0, 0, 1, 1]y_true [1, 0, 1, 0]accuracy_score(y_true, y_pred) # 0.5精确率与召回率精确率和召回率与混淆矩阵密切相关混淆矩阵是将分类(二分类)结果通过矩阵的形式直观展现出来真实情况预测结果为正例预测结果为反例正例TP(真正例)FN(假反例)反例FP(假正例)TN(真反例)精确率(Precision)也称为查准率反映的是模型判定的精确度预测为正样本里面有多少是真实的正样本。可公式化描述如下召回率(Recall)也叫查全率定义为分类正确的正样本个数占真正的正样本个数的比例意味着真实的正样本有多少被找出来了。可公式化描述如下精确率和召回率是矛盾统一的两个指标为了提高精确率分类器需要尽量在“更有把握时”才把样本预测为正样本但往往会因为过于保守而漏掉很多“没有把握”的正样本导致召回率很低。比如我们想要一个模型精确率达到 100%那就意味着要保证每一个结果都是真正例这就会导致有些正例被放弃相反要保证模型能将所有正例都预测为正例意味着有些反例也会混进来。这背后的根本原因就在于我们的数据往往是随机、且充满噪声的并不是非黑即白。采用sklearn得到精确率和召回率的代码如下from sklearn.metrics import precision_score from sklearn.metrics import recall_score Precision precision_score(y, guesses) Recall recall_score(y, guesses)采用sklearn得到混淆矩阵的代码如下from sklearn.metrics import confusion_matrix confusion_matrix(y, guesses)P-R曲线Precision-Recall曲线(精确率召回率曲线简称P-R曲线)。P-R曲线的横轴是召回率纵轴是精确率。P-R曲线上的一个点代表“在某一阈值下模型将大于该阈值的结果判定为正样本将下于该阈值的结果判定为负样本时模型预测结果对应的召回率和精确率”。P-R曲线绘制方法如下对模型的学习结果进行从大到小排序(一般都有一个概率值)按照上面的顺序逐个把样本作为正例进行预测每次都可以得到一个PR值将得到的PR值按照R为横坐标P为纵坐标绘制曲线图。绘制P-R曲线的Demo如下from typing import List, Tupleimport matplotlib.pyplot as pltdef get_confusion_matrix( y_pred: List[int], y_true: List[int] ) - Tuple[int, int, int, int]: length len(y_pred) assert length len(y_true) tp, fp, fn, tn 0, 0, 0, 0 for i in range(length): if y_pred[i] y_true[i] and y_pred[i] 1: tp 1 elif y_pred[i] y_true[i] and y_pred[i] 0: tn 1 elif y_pred[i] 1 and y_true[i] 0: fp 1 elif y_pred[i] 0 and y_true[i] 1: fn 1 return (tp, fp, tn, fn) def calc_p(tp: int, fp: int) - float: return tp / (tp fp) def calc_r(tp: int, fn: int) - float: return tp / (tp fn) def get_pr_pairs( y_pred_prob: List[float], y_true: List[int] ) - Tuple[List[int], List[int]]: ps [1] rs [0] for prob1 in y_pred_prob: y_pred_i [] for prob2 in y_pred_prob: if prob2 prob1: y_pred_i.append(0) else: y_pred_i.append(1) tp, fp, tn, fn get_confusion_matrix(y_pred_i, y_true) p calc_p(tp, fp) r calc_r(tp, fn) ps.append(p) rs.append(r) ps.append(0) rs.append(1) return ps, rsy_pred_prob [0.9, 0.8, 0.7, 0.6, 0.55, 0.54, 0.53, 0.52, 0.51, 0.505, 0.4, 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33, 0.3, 0.1]y_true [1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0]y_pred [1] * 10 [0] * 10ps, rs get_pr_pairs(y_pred_prob, y_true)fig, ax plt.subplots(nrows1, ncols1, figsize(12, 5))ax.plot(rs, ps);如果有多个模型就可以绘制多条 P-R 曲线如果某个模型的曲线完全被另外一个模型 “包住”(即后者更加凹向原点)那么后者的性能一定优于前者。如果多个模型的曲线发生交叉此时不好判断哪个模型较优一个较为合理的方法是计算曲线下面积但这个值不太好估算。为了获得模型优劣需要综合P(精确率)和R(召回率)平衡点BEP(Break-Even Point)是其中一种判断方法它是 PR 时的取值BEP越远离原点说明模型效果越好。如下图中A的BEP是0.8B的BEP是0.73因此可以认为模型A比模型B效果更好。由于BEP过于简单为了综合反映Precision和Recall的结果可以使用F1-score(F1值)。F1-scoreF1-score是精确率和召回率的调和平均值其定义如下F1-score有更一般的形式当β 1时更偏向召回率当β 1时更偏好精确率当β 1时平衡精确率和召回率即为 F1F1 其实来自精确率和召回率的加权调和平均多个二分类混淆矩阵的综合考查当有多个混淆矩阵(多次训练、多个数据集、多分类任务)时有两种方式估算 “全局” 性能(1)macro 方法先计算每个 PR取平均后再计算 F1。这样得到的就是宏查准率(macro-P)、宏查全率(macro-R)以及相应的宏 F1(macro-F1)(2)micro 方法先计算混淆矩阵元素的平均再计算 PR 和 F1。这样得到的就是微查准率(micro-P)微查全率(micro-R)微F1(micro-F1)采用sklearn得到f1-score的代码如下from sklearn.metrics import f1_scoref1_score(y_truey_test, y_predy_pred)ROC曲线与AUCROC曲线的全称是the Receiver Operating Characteristic曲线中文译为“受试者工作特征曲线”。ROC曲线的横坐标为FalsePositive Rate(FPR假阳性率)定义为负例样本中被错误判定为正例的样本比例纵坐标为True Positive Rate(TPR真阳性率也称为敏感度(Sensitivity))定义为正例样本中被正确判定为正例的样本数比例。通常来说ROC曲线越光滑过拟合程度越小。FPR和TPR的计算方法如下在上式中P是真实正样本的数量N是真实负样本的数量TP是P个正样本中被分类器预测为正样本的个数FP是N个负样本中被分类器预测为正样本的个数。 对于一个特定的分类器和样本集合只能计算得到一对 FPR 和 TPR也就是曲线上的一个点而要得到一个曲线我们需要一系列 FPR 和 TPR 的值这又是如何得到的呢通常分类器在预测某个样本的类型时会给出这个样本具有多大的概率属于正类然后根据设定的某个阈值预测其为正类还是负类。根据某个阈值我们可以计算出相应的一对 FPR 和 TPR通过改变阈值的大小就可以计算出一系列的FPR和TPR了。随着阈值的逐渐减小越来越多的样本被划分为正类但是这些正类中同样也掺杂着真正的负类即 TPR 和 FPR 会同时增大。当阈值取最大值1时对应坐标点为(0,0)当阈值取最小值0时对应坐标点为 (1,1)。采用sklearn得到ROC的代码如下from sklearn.metrics import roc_curve, roc_auc_curveroc_curve(y, guesses)roc_auc_curve(y, guesses)自实现的方式得到ROC曲线的代码如下def calc_fpr(fp: int, tn: int) - float: return fp / (fp tn) def calc_tpr(tp: int, fn: int) - float: return tp / (tp fn) def get_ftpr_pairs( y_pred_prob: List[float], y_true: List[int] ) - Tuple[List[int], List[int]]: fprs [0] tprs [0] for prob1 in y_pred_prob: y_pred_i [] for prob2 in y_pred_prob: if prob2 prob1: y_pred_i.append(0) else: y_pred_i.append(1) tp, fp, tn, fn get_confusion_matrix(y_pred_i, y_true) fpr calc_fpr(fp, tn) tpr calc_tpr(tp, fn) fprs.append(fpr) tprs.append(tpr) fprs.append(1) tprs.append(1) return fprs, tprs fprs, tprs get_ftpr_pairs(y_pred_prob, y_true)fig, ax plt.subplots(nrows1, ncols1, figsize(12, 5))ax.plot(fprs, tprs)除此之外还有一种绘制 ROC 曲线的方法假设有m个正例m-个负例首先把分类阈值设为最大即把所有样例均设为反例此时真正例率和假正例率均为0在坐标(0,0)处记一个点然后依次将每个样本的预测值作为阈值(即将该样本作为正例)假设前一个坐标为(x, y)若当前为真正例对应标记点为(x, y1/m)若当前为假正例则对应标记点为(x1/m-, y)将所有点相连即可得到ROC曲线上面这种方法和下面这种方法是一样的将纵坐标的刻度间隔设为 1/m横坐标的刻度间隔设为 1/m-从(0,0)开始每遇到一个真正例就沿着纵轴绘制一个刻度间隔的曲线假正例就沿着横轴绘制一个刻度间隔的曲线最终就可以得到 ROC曲线。这种方法的代码如下def get_ftpr_pairs2( y_pred_prob: List[float], y_true: List[int] ) - Tuple[List[int], List[int]]: mplus sum(y_true) msub len(y_true) - mplus pairs [(0, 0)] prev (0, 0) length len(y_pred_prob) assert length len(y_true) for i in range(length): if y_true[i] 1: pair (prev[0], prev[1] 1/mplus) else: pair (prev[0] 1/msub, prev[1]) pairs.append(pair) prev pair pairs.append((1, 1)) fprs, tprs [], [] for pair in pairs: fprs.append(pair[0]) tprs.append(pair[1]) return fprs, tprs fprs, tprs get_ftpr_pairs2(y_pred_prob, y_true)fig, ax plt.subplots(nrows1, ncols1, figsize(12, 5))ax.plot(fprs, tprs)ROC曲线中曲线相对于随机线的最高点表示正例和负例分布的分离程度(一般来说分离程度越大ROC曲线的“小山包”隆起越明显)“小山包”的面积(ROC曲线和随机线围住的面积)就是Gini指数如下图所示多个模型时与 P-R 曲线也是类似如果某个模型的曲线完全 “包住” 另一个则前者性能好于后者。如果曲线相互交叉则比较曲线下面积AUC(Area Under ROC Curve)AUC越大性能越好。AUC 取值一般在 0.5-1 之间处于 yx 直线的上方(如果不是的话把预测概率翻转成 1-p 就能获得更好的模型)。AUC 值越大说明模型越可能把真正例排在前面性能越好。此时假正例率很低同时真正例率很高意味着召回高并且误判率小。对角线对应着随机模型(各占 50%)(01)点对应的是理想模型即所有正例 100% 召回且没有一个负例被判别为正例。由于 ROC 曲线越靠近坐标点 (0,1) 分类器越优所以从 AUC 判断分类器优劣的标准如下AUC 1完美分类器采用这个预测模型时存在至少一个阈值能得出完美预测。0.5 AUC 1优于随机猜测。这个分类器妥善设定阈值的话能有预测价值。AUC 0.5跟随机猜测效果一样分类器没有预测价值。AUC 0.5比随机猜测还差但只要总是反预测而行就优于随机猜测。简单来说就是 AUC 值越大则分类器越优。AUC 面积可以通过以下公式进行估算若AUC考虑的是样本预测的排序质量与排序误差紧密相连排序 “损失” loss 可定义为该式子的意思是如果正例预测值小于负例计1个罚分如果相等则计 0.5 个罚分。显然该式对应的就是 ROC 曲线上面的面积。因此有与P-R曲线相比ROC曲线有一个特点当正负样本的分布发生变化时ROC曲线形状能基本保持不变而P-R曲线的形状一般会发生比较剧烈的变化。因此当数据不均匀时ROC曲线更能够反映模型好坏。而这背后的原因是P-R曲线关注的是真实的正例和预测的正例中(分别对应 Recall 和 Precision)实际是正例的比例ROC曲线关注的是真实的正例和负例中(分别对应 TPR 和 FPR)被预测为正例的比例采用sklearn计算AUC-score的代码如下import numpy as np from sklearn.metrics import roc_auc_score y_true np.array([0, 0, 1, 1]) y_scores np.array([0.1, 0.4, 0.35, 0.8]) roc_auc_score(y_true, y_scores)平均精度均值平均精确均值(meanAverage PrecisionmAP)是对平均精度(Average PrecisionAP)再次平均。因此需要先了解什么是平均精度下面举例说明。假设模型对6个样本的预测结果如下序列N1N2N3N4N5N6真实标签100111其中1代表正样本0代表负样本。按顺序计算每个位置上的精确率如下序列N1N2N3N4N5N6真实标签100111Precision1/11/21/32/43/54/6AP的计算只取正样本处的precision进行平均。则此序列的AP(1/1 2/4 3/5 4/6)/40.6917代价曲线在某些现实任务中不同类型的错误造成的后果不同。例如在医疗诊断中将一名癌症患者错误地诊断成健康人士将一名健康人士错误地诊断为癌症患者这两种情况要承担的后果是截然不同的后者仅是增加了进一步检查的麻烦而前者若丧失佳治疗时机则要付出生命的代价。为此我们为错误赋予非均等代价(unequal cost)来权衡不同类型错误所造成的不同损失。以二分类任务为例我们可以为任务设置一个代价矩阵(cost matrix)如下表所示其中costij表示第i类样本错误预测为第j类的代价。一般情况下costii0这是因为预测正确了就没 有代价了。我们规定若将第0类判别为第一类的所造成的损失更大那么就有cost01cost10 损失程度越大则两者相差越大。但这个“相差”不是表示两者之间的差值表示的是比值举个例子 cost01:cost105:1的效果和 cost01:cost1050:10是相同的。前面我们考虑的性能度量都是假设在均等代价的情况下也就是说以减小错误次数为主但不考虑不同的错误类型造成的后果的严重程度。而在非均等代价下我们希望小化总体代价(total cost)。若设上表中第0类为正类第1类为反类令D和D−分别代表样本集中的正类样本子集和反类样本子集则代价敏感(cost-sensitive)错误率为由此我们可以推出其它性能度量的代价敏感版本或者是基于分布定义的代价敏感错误率。若 costij中的值不局限于01还可以定义出多分类任务的代价敏感性能度量。在非均等代价下我们用代价曲线(cost curve)代替ROC曲线表现学习器的期望总体代价。代价曲线图横轴是取值为[0,1]的正例概率代价其中p表示样例为正例的概率。纵轴是取值为[0,1]的归一化代价归一化是规范化(normalization)的特例规范化表示将不同变化范围的值映射到某相同、固定 的范围当中常见的固定范围是[0,1]这个时候就是“归一化”。FPR即之前定义的假正例率FNR1-TPR 是假反例率代价曲线的绘制方式(1)ROC曲线上每一点对应代价平面上的一条线段设ROC曲线上的坐标为(FPRTPR)计算出相应的FNR(2)在代价平面上绘制一条从(0FPR)到(1FNR)的线段线段下的面积就表示了该条件下的期望总体代价(3)将ROC曲线上的每个点转化为代价平面上的一条线段然后取所有线段的下界围成的面积即为在所有条件下学习器的期望总体代价马修斯相关系数马修斯相关系数简称MCC与F1-score一样是分类的综合评估指标。其公式化描述如下从公式中可以看出MCC和2*2列联表的卡方检验很相近。MCC的值域为[-1,1]。MCC的好处是正例和负例的不同划分对于最终结果没有影响① TP 0, FP 0; TN 5, FN 95.② TP 95, FP 5; TN 0, FN 0.这两种条件下(正例和负例的划分不一样)得到的F1-Score差异非常大(①中为0②中为0.97)从这里还可以看出F1-Score在正负例样本比例差异不一致的情况下会高估模型的分类效果。综合考虑了正负例样本比例不一致的情况TP 90, FP 4; TN 1, FN 5. 这种条件下得到的分类正确率(Accuracy)为0.91F1-Score为0.95MCC得到的值为0.135. 例如风控业务中“坏”用户占整体用户的比例很小如果看正确率或者F1-Score那就入坑了此时MCC可能更合适。Balanced Classification RateBalanced Classification Rate简称BCRBCR为正例样本和负例样本中各自预测正确率的均值与F1-score一样是分类的综合评估指标。其公式化定义为其中TNR (True False Rate)指负例样本中被正确判定为负例的样本数比例,也称为Specificity(特异度)。其公式化描述如下与BCR对应的是BER(Balanced Error Rate)也称为Half Total Error Rate(HTER)。同MCC一样正负例的标签选择对BCR的计算没有影响而且一定程度上也能克服正负例样本不均衡导致的评估指标虚高。均方误差均方误差(Mean Squared Error简称MSE)误差函数把输出向量和真实向量映射到笛卡尔 坐标系的两个点上通过计算这两个点之间的欧式距离(准确地说是欧式距离的平方)来衡 量两个向量之间差距。其公式化描述如下更一般的对于数据分布D和概率密度函数p(⋅)均方误差可描述为MSE 误差函数的值总是大于等于0当MSE函数达到最小值0时输出等于真实标签 此时神经网络的参数达到最优状态。均方差误差函数广泛应用在回归问题中。在 TensorFlow 中可以通过函数方式或层方式实现MSE误差计算。例如使用函数方式实现MSE计算代码如下# 构造网络输出 o tf.random.normal([2,10])# 构造真实值 y_onehot tf.constant([1,3]) y_onehot tf.one_hot(y_onehot, depth10) # 计算均方差loss keras.losses.MSE(y_onehot, o) # 注意MSE 函数返回的是每个样本的均方差需要在样本维度上再次平均来获得平均样本的均方差# 计算 batch 均方差loss tf.reduce_mean(loss) 也可以通过层方式实现对应的类为keras.losses.MeanSquaredError()和其他层的类一样调用__call__函数即可完成前向计算代码如下# 创建 MSE 类 criteon keras.losses.MeanSquaredError() # 计算 batch 均方差loss criteon(y_onehot, o) 采用sklearn方式得到的均方误差的代码如下from sklearn.metrics import mean_squared_error y_true [3, -0.5, 2, 7]y_pred [2.5, 0.0, 2, 8] mean_squared_error(y_true, y_pred)假设均方误差损失函数表达式为上式中1/2项用于简化计算也可以利用1/K进行平均这些缩放运算均不会改变梯度方向。则它的偏导数可以展开为利用复合函数导数法则分解为考虑到仅当ki时才为1其它点都为0也就是说偏导数只与第i号节点相关与其它节点无关因此上式中的求和符号可以去掉。均方误差函数的导数可以推导为R²R²(R squared, Coefficient of determination)中文翻译为“决定系数”或者“拟合优度”反映的是预测值对实际值的解释程度。其取值范围是(0,1)R²越接近1说明拟合效果越好。其公式化描述如下注意R²和相关系数的平方不是一回事(只在简单线性回归条件下成立).R2分数R2分数(R2 Score)通过将我们的模型与最简单的可能模型相比得出。所谓最简单的可能模型比如我们要拟合一个散点图我们可以直接画一条直线穿过这些点。然后求出该直线模型下的均方误差。我们希望期望模型的均方误差比这个直线模型要小而且是小得多从而使得R2分数趋向于1。采用sklearn得到R2分数的代码如下from sklearn_metrics import r2_score y_true [1, 2, 4] y_pred [1.3, 2.5, 3.7] r2_score(y_true, y_pred)均方根误差均方根误差(RootMean Square ErrorRMSE)经常用于评估回归模型的好坏。其公式化定义如下其中是第i个样本点的真实值是第i个样本点的预测值n是样本点的个数。一般情况下RMSE能够很好的反映回归模型的预测值与真实值的偏离程度。但如果存在一些偏离程度非常大的离群点那么即使离群点数量非常少也会让RMSE指标变得很差。为了解决这个问题可以使用鲁棒性更强的平均绝对百分比误差(MeanAbsolute Percent ErrorMAPE)进行评估。平均绝对百分比误差平均绝对百分比误差(MeanAbsolute Percent ErrorMAPE)进行评估MAPE的定义如下相比RMSEMAPE相当于把每个点的误差进行了归一化降低了离群点带来的绝对误差的影响。从MAPE公式中可以看出有个明显的缺陷当实际值趋向0时就会得到无穷大值(实际 值的绝对值1也会过度放大误差)。为了避免这个问题MAPE一般用于实际值不会为 0的情形。为了解决这个问题提出了MAAPE(mean arctangent absolute percentage error)。MAAPEMAAPE(mean arctangent absolute percentage error)在保持MAPE的算法思想下解决了当实际值趋向0时就会得到无穷大值的缺陷。其公式化定义为平均绝对误差平均绝对误差(Mean Absolute Error)又被称为L1范数损失(l1-norm loss)定义为预测值与真实值之差的绝对值加起来求其平均。采用sklearn得到平均绝对误差的代码如下from sklearn.metrics import mean_absolute_errorfrom sklearn.linear_model import LinearRegressionclassifier LinearRegression()classifier.fit(X, y)guesses classifier.predict(X)error mean_absolute_error(y, guesses)欢迎关注一起学习参考王喆深度学习推荐系统。龙书TensorFlow深度学习。https://mp.weixin.qq.com/s/21421H7Yp-kGDXrJtGtDZAhttps://mp.weixin.qq.com/s/oBV-WFWsCbpQcN1FssYf6Ahttps://mp.weixin.qq.com/s/Epu4g7IKOwZbxJBEK8CMIghttps://mp.weixin.qq.com/s/_38dpogJ4r3JArY9rdNDOwhttps://mp.weixin.qq.com/s/R7XUko-dpvfu6WNBTv7YRwhttps://mp.weixin.qq.com/s/0WPrEeN5rKLRxFME0dneSghttps://mp.weixin.qq.com/s/pj97tGpLdcDpOHJ9rYBmTAhttps://mp.weixin.qq.com/s/vGuNd0guGzSFMpj81r3Z2Ahttps://mp.weixin.qq.com/s/93Qs0-NqLZkP_GKO373QHwhttps://mp.weixin.qq.com/s/5kWdmi8LgdDTjJ40lqz9_A