如何应对缺失值带来的分布变化?探索填充缺失值的最佳插补算法

本文将探讨了缺失值插补的不同方法,并比较了它们在复原数据真实分布方面的效果,处理插补是一个不确定性的问题,尤其是在样本量较小或数据复杂性高时的挑战,应选择能够适应数据分布变化并准确插补缺失值的方法。

我们假设存在一个潜在的分布P*,从中得出观察值X*。此外,还绘制了一个与X相同维数的0/1向量,我们称这个向量为M,实际观测到的数据向量X被M掩码为X。我们观测到联合向量(X,M)的n个独立同分布(i.i.d)副本。如果我们把它写成一个数据矩阵,它可能看起来像这样:

较小的x,m表示“观察到的”,而较大的值则表示随机数量。大家讨论的缺失机制就是对(X*,M)的关系或联合分布的假设:

完全随机缺失(MCAR):一个值丢失的概率就像抛硬币一样,与数据集中的任何变量无关。缺失值只是一件麻烦事。你可以忽略它们,只关注数据集中完全观察到的部分,这样就不会有偏差。在数学中,对于所有m和x:

随机缺失(MAR):缺失的概率现在可以依赖于数据集中观察到的变量。一个典型的例子是两个变量,比如收入和年龄,其中年龄总是被观察到,但收入可能会因为年龄的某些值而丢失。这可能听起来很合理,但这里可能会变得复杂。在数学中,对于所有m和x:

非随机缺失(MNAR):这里一切皆有可能,我们不能笼统地概括。但是最终我们需要学习给定一个模式m '中观测值的缺失值的条件分布,以便在另一个模式m中推算。

实现这一点的著名的方法称为链式方程多重插补(Multiple Imputation by Chained Equations, MICE):首先使用简单的插补方法填充值,例如均值插补。然后对于每一次迭代t,对每一个变量j,根据所有其他已插补的变量进行回归分析(这些变量已被插补)。然后将这些变量的值填入已学习的插补器中,用于所有未观察到的X_j。在R语言中,可以方便地使用mice包来实现。我这种方法在实际应用中效果非常好,MICE中重现某些实例的底层分布的能力非常惊人。我们下面会用一个非常简单的例子(只有一个变量缺失,因此我们可以手动编码),模拟MICE通常会迭代执行的过程,以更好地了解他的工作原理。

数据

我们将看一个非常简单但具有说明性的例子:考虑一个具有两个联合正态变量X_1, X_2的数据集。我们假设两个变量的方差为1,正相关系数为0.5。为了方便说明,我们假设X_1是收入的对数,X_2是年龄。另外我们设置收入X_1存在缺失机制,即当年龄“高”时,X_1往往会缺失。这就是我们设的:

当X_2(年龄)较大(即大于0)时,X_1(收入)缺失的概率为0.8。由于我们假设X_2总是被观察到,这是一个教科书式的MAR示例,它有两种模式,一种是所有变量都被完全观察到(m1),另一种是(m2),其中X_1缺失。尽管这个例子很简单,但如果我们假设年龄越大,收入越高,那么从一种模式转换到另一种模式时,收入和年龄的分布就会发生明显的变化。在模式m2中,收入缺失,观察到的年龄和(未观察到的)收入的值都趋向于更高。

我们先看一下生成数据的代码:

 library(MASS)library(mice)set.seed(10)n<-3000Xstar<-mvrnorm(n=n, mu=c(0,0), Sigma=matrix( c(1,0.7,0.7,1), nrow=2, byrow=T   ))colnames(Xstar) <-paste0("X",1:2)## Introduce missing mechanismsM<-matrix(0, ncol=ncol(Xstar), nrow=nrow(Xstar))M[Xstar[,2] >0, 1]<-sample(c(0,1), size=sum(Xstar[,2] >0), replace=T, prob=c(1-0.8,0.8) )## This gives rise to the observed dataset by masking X^* with M:X<-XstarX[M==1] <-NA## Plot the distribution shiftpar(mfrow=c(2,1))plot(Xstar[!is.na(X[,1]),1:2], xlab="", main="", ylab="", cex=0.8, col="darkblue", xlim=c(-4,4), ylim=c(-3,3))plot(Xstar[is.na(X[,1]),1:2], xlab="", main="", ylab="", cex=0.8, col="darkblue", xlim=c(-4,4), ylim=c(-3,3))

插补是一个分布预测问题

(通用的)插补的目标应该是尽可能地复制底层数据分布。为了说明这一点,考虑第一个例子,其中p=0,这样只有X_1缺失值现在将尝试使用著名的MICE方法来插补这个例子。由于只有X_1缺失,可以手动实现这一点。我们从均值插补开始,简单地计算在观测到的模式中X_1的均值,并将这个均值填补到NA的位置。我们还使用了更为复杂的回归插补:在观测到X_1的模式中,将X_1对X_2进行回归分析,然后对每个缺失的X_1观测值,我们插入回归的预测值。最后,对于高斯插补,我们从X_1对X_2的同样回归开始,但随后通过从高斯分布中抽取来插补每个缺失的X_1值。也就是说我们不是仅插补条件期望(即条件分布的中心),而是从这个分布中抽取。这导致了一种随机插补,起初可能有些违反直觉,但实际上会带来最好的结果:

 ## (0) Mean Imputation: This would correspond to "mean" in the mice R package ### 1. Estimate the meanmeanX<-mean(X[!is.na(X[,1]),1])## 2. Imputemeanimp<-Xmeanimp[is.na(X[,1]),1] <-meanX## (1) Regression Imputation: This would correspond to "norm.predict" in the mice R package ### 1. Estimate RegressionlmodelX1X2<-lm(X1~X2, data=as.data.frame(X[!is.na(X[,1]),])   )## 2. Imputeimpnormpredict<-Ximpnormpredict[is.na(X[,1]),1] <-predict(lmodelX1X2, newdata=as.data.frame(X[is.na(X[,1]),])  )## (2) Gaussian Imputation: This would correspond to "norm.nob" in the mice R package ### 1. Estimate Regression#lmodelX1X2<-lm(X1~X2, X=as.data.frame(X[!is.na(X[,1]),])   )# (same as before)## 2. Imputeimpnorm<-Xmeanx<-predict(lmodelX1X2, newdata=as.data.frame(X[is.na(X[,1]),])  )var<-var(lmodelX1X2$residuals)impnorm[is.na(X[,1]),1] <-rnorm(n=length(meanx), mean=meanx, sd=sqrt(var) )## Plot the different imputationspar(mfrow=c(2,2))plot(meanimp[!is.na(X[,1]),c("X2","X1")], main=paste("Mean Imputation"), cex=0.8, col="darkblue", cex.main=1.5)points(meanimp[is.na(X[,1]),c("X2","X1")], col="darkred", cex=0.8 )plot(impnormpredict[!is.na(X[,1]),c("X2","X1")], main=paste("Regression Imputation"), cex=0.8, col="darkblue", cex.main=1.5)points(impnormpredict[is.na(X[,1]),c("X2","X1")], col="darkred", cex=0.8 )plot(impnorm[!is.na(X[,1]),c("X2","X1")], main=paste("Gaussian Imputation"), col="darkblue", cex.main=1.5)points(impnorm[is.na(X[,1]),c("X2","X1")], col="darkred", cex=0.8 )#plot(Xstar[,c("X2","X1")], main="Truth", col="darkblue", cex.main=1.5)plot(Xstar[!is.na(X[,1]),c("X2","X1")], main="Truth", col="darkblue", cex.main=1.5)points(Xstar[is.na(X[,1]),c("X2","X1")], col="darkgreen", cex=0.8 )

研究这张图可以立即发现,均值和回归插补并不好,因为它们完全未能重现原始数据分布。相比之下,高斯插补看起来相当不错,事实上,我认为很难将其与真实情况区分开来。这可能看起来只是一个技术概念,但这有其后果。想象一下,如果你得到了任何这些插补的数据集,现在你想要找到在将X_2对X_1进行回归时的回归系数(与我们用于插补的操作相反)。在这种情况下,真实值由beta=cov(X_1, X_2)/var(X_1)=0.7给出。

 ## Regressing X_2 onto X_1## mean imputation estimatelm(X2~X1, data=data.frame(meanimp))$coefficients["X1"]## beta= 0.61## regression imputation estimateround(lm(X2~X1, data=data.frame(impnormpredict))$coefficients["X1"],2)## beta= 0.90## Gaussian imputation estimateround(lm(X2~X1, data=data.frame(impnorm))$coefficients["X1"],2)## beta= 0.71## Truth imputation estimateround(lm(X2~X1, data=data.frame(Xstar))$coefficients["X1"],2)## beta= 0.71

高斯插补的结果非常接近0.7(0.71),更重要的是,它非常接近使用完整(未观测)数据得到的估计!而均值插补低估了beta值,回归插补则高估了beta值。回归插补因为条件均值插补人为地增强了变量之间的关系,这将导致在科学和(数据科学)实践中估计出的效应被过高估计!

回归插补可能看起来过于简单,但是在机器学习和其他领域中非常常用的插补方法正是这样工作的。例如,knn插补和随机森林插补(即missForest)。特别是随机森林插补在几篇基准测试论文中受到赞扬和推荐,且应用非常广泛。missForest是在观测数据上拟合一个随机森林,然后简单地通过条件均值进行插补,使用它的结果将与回归插补非常相似,从而导致变量之间关系的人为强化和估计的偏差!

如何评估插补方法?

上面我们已经说了应将插补视为一个分布预测的问题,那么这个分布预测的问题应该如何评估呢?

设想我们开发了一种新的插补方法,现在想要与已存在的方法如missForest、MICE或GAIN进行基准测试。这种情况下,我们人为地引入缺失值。然后将这个真实数据集与我们的插补结果进行比较。我们假设上面的回归插补是一种新方法,我们想要将其与均值和高斯插补进行比较。

即使在最有声望的会议中,也是通过计算均方根误差(RMSE)来完成的:

但是使用RMSE来评估我们的插补将偏向于那些插补条件均值的方法,如回归插补、knn插补和missForest。

而就像我们要说明的问题,由于插补本质上是一个分布预测问题,因此除了使用RMSE等统计指标之外,还应评估插补方法是否能够恢复数据的整体分布。这可以通过比较不同插补方法生成的数据分布的统计特性(如均值、方差、偏度等)或使用更复杂的分布相似性度量(如地球移动者距离或Kullback-Leibler散度)来实现。这里使用使用能量距离来衡量完全观测数据的分布与插补“分布”之间的差异

能量距离:能量距离是一种度量两个分布之间差异的统计量,它基于从两个分布中随机抽取样本对的距离。在插补的上下文中,它能有效地评估插补数据分布与原始数据分布之间的相似性。

通过使用能量距离等分布敏感的评估指标,我们可以更准确地评估插补方法是否能够恢复数据的原始统计特性,而不仅仅是平均水平上的接近性。这种方法特别适合于评估那些旨在捕捉数据复杂依赖性和分布特征的高级插补技术。

 library(energy)## Function to calculate the energy distance:# impX is the imputed data set# Xstar is the fully observed data set## Calculating the energy distance using the eqdist.e function of the energy packageenergycalc<-function(impX, Xstar){# Note: eqdist.e calculates the energy statistics for a test, which is actually# = n^2/(2n)*energydistance(impX,Xstar), but we we are only interested in relative valuesround(eqdist.e( rbind(Xstar,impX), c(nrow(Xstar), nrow(impX))  ),2)}

现在我们将这两个分数应用到这个研究项目中,并测试我们的回归imputation是否比其他两个更好:

 par(mfrow=c(2,2))## Same plots as before, but now with RMSE and energy distance ## addedplot(meanimp[!is.na(X[,1]),c("X2","X1")], main=paste("Mean Imputation", "\nRMSE", RMSEcalc(meanimp, Xstar), "\nEnergy", energycalc(meanimp, Xstar)), cex=0.8, col="darkblue", cex.main=1.5)points(meanimp[is.na(X[,1]),c("X2","X1")], col="darkred", cex=0.8 )plot(impnormpredict[!is.na(X[,1]),c("X2","X1")], main=paste("Regression Imputation","\nRMSE", RMSEcalc(impnormpredict, Xstar), "\nEnergy", energycalc(impnormpredict, Xstar)), cex=0.8, col="darkblue", cex.main=1.5)points(impnormpredict[is.na(X[,1]),c("X2","X1")], col="darkred", cex=0.8 )plot(impnorm[!is.na(X[,1]),c("X2","X1")], main=paste("Gaussian Imputation","\nRMSE", RMSEcalc(impnorm, Xstar), "\nEnergy", energycalc(impnorm, Xstar)), col="darkblue", cex.main=1.5)points(impnorm[is.na(X[,1]),c("X2","X1")], col="darkred", cex=0.8 )plot(Xstar[!is.na(X[,1]),c("X2","X1")], main="Truth", col="darkblue", cex.main=1.5)points(Xstar[is.na(X[,1]),c("X2","X1")], col="darkgreen", cex=0.8 )

在使用均方根误差(RMSE)评估时,回归插补看起来表现非常好!它超过了均值插补和高斯插补。但是这与我们上面的分析相冲突,选择回归插补可能会导致高度偏见的结果。而(标度化的)能量距离正确地识别出高斯插补是最佳方法,这与视觉和更好的参数估计相一致。

所以,当评估插补方法时(当真实数据可用时),应避免使用像RMSE和MAE这样的度量。而应该被视为并作为分布预测问题来评估,应使用诸如能量距离之类的分布度量。将RMSE作为评估工具的过度使用对这一领域的研究有一些严重的影响。

当底层观察数据不可用时,评估问题变得更加困难。这篇论文[1]中,开发了一个分数,即使在这种情况下也能对插补方法进行排名!

 library(mice)source("Iscore.R")methods<-c("mean",       #mice-mean"norm.predict",   #mice-sample"norm.nob") # Gaussian Imputation## We first define functions that allow for imputation of the three methods:imputationfuncs<-list()imputationfuncs[["mean"]] <-function(X,m){ # 1. Estimate the meanmeanX<-mean(X[!is.na(X[,1]),1])## 2. Imputemeanimp<-Xmeanimp[is.na(X[,1]),1] <-meanXres<-list()for (lin1:m){res[[l]] <-meanimp}return(res)}imputationfuncs[["norm.predict"]] <-function(X,m){ # 1. Estimate RegressionlmodelX1X2<-lm(X1~., data=as.data.frame(X[!is.na(X[,1]),])   )## 2. Imputeimpnormpredict<-Ximpnormpredict[is.na(X[,1]),1] <-predict(lmodelX1X2, newdata=as.data.frame(X[is.na(X[,1]),])  )res<-list()for (lin1:m){res[[l]] <-impnormpredict}return(res)}imputationfuncs[["norm.nob"]] <-function(X,m){ # 1. Estimate RegressionlmodelX1X2<-lm(X1~., data=as.data.frame(X[!is.na(X[,1]),])   )## 2. Imputeimpnorm<-Xmeanx<-predict(lmodelX1X2, newdata=as.data.frame(X[is.na(X[,1]),])  )var<-var(lmodelX1X2$residuals)res<-list()for (lin1:m){impnorm[is.na(X[,1]),1] <-rnorm(n=length(meanx), mean=meanx, sd=sqrt(var) )res[[l]] <-impnorm}return(res)}scoreslist<-Iscores_new(X,imputations=NULL, imputationfuncs=imputationfuncs, N=30)  scores<-do.call(cbind,lapply(scoreslist, function(x) x$score ))names(scores)<-methodsscores[order(scores)]#    mean       norm.predict     norm.nob #  -0.7455304   -0.5702136   -0.4220387 

无需看到缺失数据的值,分数也能够识别分布,特别是当数据有两个以上的维度时。

随机缺失比你想象的更奇怪

当阅读关于缺失值插补的文献时,人们容易认为在缺失数据机制为MAR(Missing At Random,随机缺失)的情况下问题已经解决,而所有的缺失问题都来自于是否可以假设为MAR。虽然在使用最大似然等标准程序时这可能是正确的,但如果想要找到一个好的(非参数的)插补方法,情况并非如此。

论文[1]讨论了在MAR下可能发生的复杂分布变化,当从完全观测的模式变化到一个想要插补的模式时,在观测变量中是否可能发生的分布变化呢?回到上面的例子,其中将X_1设为收入,将X_2设为年龄。在第一幅图中就能看到的,分布看起来相当不同。而条件分布 X_1 | X_2 保持不变!这在原则上允许识别正确的插补分布。

这一发现对于理解和处理MAR下的缺失数据具有重要意义。尽管数据可能看起来在全面观测和部分缺失时有不同的分布,通过关注条件分布的稳定性,可以更精确地插补缺失值。也就是说非参数插补技术能够适应数据的这种内在复杂性,而不仅仅是简单地应用参数方法或假设数据具有均匀分布。在实际应用中,这种深入分析揭示了为何简单的插补方法(如均值插补或条件均值插补)可能不足以捕捉数据的真实结构,尤其是在涉及复杂关联和动态分布时。

 library(drf)## mice-DRF ##par(mfrow=c(2,2))#Fit DRFDRF<-drf(X=X[!is.na(X[,1]),2, drop=F], Y=X[!is.na(X[,1]),1, drop=F], num.trees=100)impDRF<-X# Predict weights for unobserved pointswx<-predict(DRF, newdata=X[is.na(X[,1]),2, drop=F]  )$weightsimpDRF[is.na(X[,1]),1] <-apply(wx,1,function(wxi) sample(X[!is.na(X[,1]),1, drop=F], size=1, replace=T, prob=wxi))plot(impDRF[!is.na(X[,1]),c("X2","X1")], main=paste("DRF Imputation", "\nRMSE", RMSEcalc(impDRF, Xstar), "\nEnergy", energycalc(impDRF, Xstar)), cex=0.8, col="darkblue", cex.main=1.5)points(impDRF[is.na(X[,1]),c("X2","X1")], col="darkred", cex=0.8 )## mice-cart##impcart<-Ximpcart[is.na(X[,1]),1] <-mice.impute.cart(X[,1], ry=!is.na(X[,1]), X[,2, drop=F], wy=NULL)plot(impDRF[!is.na(X[,1]),c("X2","X1")], main=paste("cart Imputation", "\nRMSE", RMSEcalc(impcart, Xstar), "\nEnergy", energycalc(impcart, Xstar)), cex=0.8, col="darkblue", cex.main=1.5)points(impDRF[is.na(X[,1]),c("X2","X1")], col="darkred", cex=0.8 )plot(impnorm[!is.na(X[,1]),c("X2","X1")], main=paste("Gaussian Imputation","\nRMSE", RMSEcalc(impnorm, Xstar), "\nEnergy", energycalc(impnorm, Xstar)), col="darkblue", cex.main=1.5)points(impnorm[is.na(X[,1]),c("X2","X1")], col="darkred", cex=0.8 )

虽然mice-cart和mice-DRF都做得不错,但它们仍然不如高斯插补那么好。这本身并不令人惊讶,因为在这种情况下,高斯插补是理想的插补方法(因为 (X_1, X_2) 确实是高斯分布的)。而X_2中的分布变化可能可能导致mice-cart和mice-DRF在恢复3000个观测值的分布时遇到困难(这些方法通常非常有效)。

论文还讨论了一个类似的,但更极端的例子,涉及两个变量(X_1, X_2)。在这个例子中,分布变化更为显著,基于森林的方法相应地面临挑战:

分布变化的影响:当底层数据的分布发生显著变化时,基于模型的插补方法(如基于决策树或随机森林的方法)可能难以准确地恢复数据的真实分布。这是因为这些模型依赖于数据中存在的模式和结构,而当这些模式和结构因为缺失数据而改变时,模型的效果可能会下降。

高斯插补的适用性:高斯插补假设数据遵循高斯分布,这使得它在处理本质上呈高斯分布的数据时非常有效。对于这种类型的数据,高斯插补能够更好地捕捉数据的整体统计特性,包括均值和协方差结构。

方法选择的重要性:选择正确的插补方法对于确保插补结果的质量至关重要。在面对复杂的数据和分布时,理解每种方法的优势和局限性可以帮助研究人员和实践者选择最适合他们数据特征的插补方法。

总结

缺失值确实是一个棘手的问题。,处理缺失值的最佳方式是尽量避免它们的出现,但是这几乎是不可能的,所以即使只考虑随机缺失(MAR),寻找插补方法的工作还远未结束。我们仍然缺乏一种能够(1)进行非参数分布预测和(2)适应在MAR下可能发生的分布变化的方法。有时也感觉人们将问题复杂化了,因为一些MICE方法表现得非常出色,可能已经足以解决许多缺失值问题。

有一些非常先进的机器学习方法,如GAIN及其变体,试图使用神经网络来插补数据。方法可能是正确的,因为它们遵循了正确的思路:插补在观察到的情况下缺失的条件分布。但是使用它们一段时间后,性能并不能让人满意,尤其是与MICE相比。

所以如果我遇到一个缺失值问题,可以首先尝试的是mice-cart或在论文中开发的新方法mice-DRF。它们重现数据的能力非常惊人。但是这些方法需要至少一个中等的样本大小,例如超过200或300。如果在少于200个观察的情况下,可以选择更简单的方法,如高斯插补。如果你想从这些方法中找到最好的,可以尝试使用论文中的评分规则来找到最好的方法。

最后别忘了这些方法都无法有效地处理插补不确定性!因为我们在这篇文章中只讨论了单一插补。正确的多重插补将需要考虑插补方法本身的不确定性,这通常使用贝叶斯方法完成,这可能又是一篇论文了。

最后:因为原论文都是使用R进行编写,我又对R不太熟悉,自己使用进行Python复现有几段出现了问题,所以就直接贴R的代码了,有兴趣的小伙伴请自行使用 Python重写。另外,GPT4的改写效果也不好,而copilot则直接提示无法改写,所以如果你有成功的的GPT4改写的Prompt也可以联系我,感谢。

最后本文引用的论文:

What Is a Good Imputation Under MAR Missingness? [1]

https://avoid.overfit.cn/post/9f66c5f8cd204ed685af0744b935ddd5

作者: Jeffrey Näf

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/28841.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java】已解决:Java.lang.OutOfMemoryError: GC overhead limit exceeded

文章目录 问题背景可能出错的原因错误代码示例正确代码示例注意事项 问题背景 java.lang.OutOfMemoryError: GC overhead limit exceeded 是Java虚拟机&#xff08;JVM&#xff09;在运行时遇到的一种内存溢出错误。这种错误通常发生在应用程序的堆内存&#xff08;Heap Memor…

香港Web3时代:比特币可以成为「收益性资产」吗?

原文标题&#xff1a;《CAN BITCOIN BE A PRODUCTIVE ASSET?》撰文&#xff1a;Pascal Hgli编译&#xff1a;Chris&#xff0c;Techub News本文来源香港Web3媒体 Techub News 比特币正在经历一场大的变化&#xff0c;人们对其性质有不同的看法。有些人将其视为日常交易的货币…

数据结构试题 16-17

先这样吧&#xff0c;&#xff0c;专业课不是统考&#xff0c;我发现每年的卷子风格都不太一样&#xff0c;侧重点也不一样。以及21的和16的发生了很大的改变。等明年1月再看看吧 那就先over啦 数据结构撒花&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&am…

基于single flight来解决缓存击穿

目录 1. 缓存击穿2. 常见解决方案3.single flight方式3.1 模拟业务场景3.2 使用single flight的方式 缓存雪崩、缓存击穿、缓存穿透不单单是缓存领域的经典场景&#xff0c;更是面试当牛马时必备&#xff08;背&#xff09;八股文。 我们来讨论下缓存击穿场景下的解决方案。 …

【AI开发】RAG基础

RAG的基本流程&#xff1a; 用一个loader把knowledge base里的知识做成一个个的document&#xff0c;然后把document切分成snippets&#xff0c;把snippets通过embedding&#xff08;比如openai的embedding模型或者huggingface的&#xff09;向量化&#xff0c;存储到vectordb…

git 配置私人令牌

这里写自定义目录标题 获取私人令牌配置个人令牌 获取私人令牌 在个人设置里点击私人令牌选型&#xff0c;之后生成令牌即可。注意&#xff1a;令牌只会出现一次&#xff0c;务必保存好。 配置个人令牌 个人令牌&#xff1a;3c15c866fa61066212a83c66fd8133ba # 进入项目文…

护眼灯对眼睛有伤害吗?千万要小心的行业四大弊端内幕

护眼灯&#xff0c;作为现代家居与办公环境中不可或缺的照明伴侣&#xff0c;因其普及性广受青睐。然而&#xff0c;随着大众对视觉健康意识的逐渐增强&#xff0c;一个疑问悄然滋生&#xff1a;护眼灯对眼睛有伤害吗&#xff1f;这一问题不仅触及到了人们对视觉健康的深层担忧…

MLOps模型部署的三种策略:批处理、实时、边缘计算

机器学习运维&#xff08;MLOps&#xff09;是一组用于自动化和简化机器学习&#xff08;ML&#xff09;工作流程和部署的实践。所选择的部署策略可以显著影响系统的性能和效用。所以需要根据用例和需求&#xff0c;采用不同的部署策略。在这篇文章中&#xff0c;我们将探讨三种…

Java家政预约系统源码 家政上门APP源码 家电安装、维修、清洗、美容系统源码、家政系统各端功能细分

Java家政预约系统源码 家政上门APP源码 家电安装、维修、清洗、美容系统源码、家政系统各端功能细分 家政服务系统是一种提供家政服务的系统&#xff0c;它可以为客户提供上门家庭清洁、钟点工、保姆、月嫂、育婴师、护理员等家政服务。节省时间和成本&#xff0c;提高效率&…

网络层只懂路由?这9个知识点被严重低估了

号主&#xff1a;老杨丨11年资深网络工程师&#xff0c;更多网工提升干货&#xff0c;请关注公众号&#xff1a;网络工程师俱乐部 下午好&#xff0c;我的网工朋友。 网络层想必你已经耳熟能详&#xff0c;它的作用自然是不容小觑。 它负责将数据从源头准确地投递到目的地&am…

onnx基本概念

onnx基本概念 参考 文章目录 onnx基本概念Input, Output, Node, Initializer, AttributesSerialization with protobuf元数据List of available operators and domains支持的类型Opset版本Subgraphs, tests and loopsExtensibilityFunctionsShape (and Type) Inferencetools O…

编码在网络安全中的应用和原理

前言:现在的网站架构复杂&#xff0c;大多都有多个应用互相配合&#xff0c;不同应用之间往往需要数据交互&#xff0c;应用之间的编码不统一&#xff0c;编码自身的特性等都很有可能会被利用来绕过或配合一些策略&#xff0c;造成一些重大的漏洞。 什么是编码&#xff0c;为什…

UniVue更新日志:使用Carousel组件实现轮播图效果

github仓库 稳定版本仓库&#xff1a;https://github.com/Avalon712/UniVue 开发版本仓库&#xff1a;https://github.com/Avalon712/UniVue-Develop UniVue扩展框架-UniVue源生成器仓库&#xff1a;https://github.com/Avalon712/UniVue-SourceGenerator 更新说明 今天的更…

吴恩达深度学习笔记:机器学习(ML)策略(1)(ML strategy(1))1.11-1.12

目录 第三门课 结构化机器学习项目&#xff08;Structuring Machine Learning Projects&#xff09;第一周 机器学习&#xff08;ML&#xff09;策略&#xff08;1&#xff09;&#xff08;ML strategy&#xff08;1&#xff09;&#xff09;1.11 超过人的表现&#xff08;Surp…

报错:C1189#error: The <experimental/filesystem> header providing 解决方案

今天开发过程中&#xff0c;需要使用文件系统experimental/filesystem&#xff0c;报错C1189#error: The &#xff1c;experimental/filesystem&#xff1e; header providing &#xff0c;通过以下解决方案&#xff0c;成功运行程序。 目录 一、打开项目下的属性 二、选择C/…

算法02 递归算法及其相关问题【C++实现】

递归 在编程中&#xff0c;我们把函数直接或者间接调用自身的过程叫做递归。 递归处理问题的过程是&#xff1a;通常把一个大型的复杂问题&#xff0c;转变成一个与原问题类似的&#xff0c;规模更小的问题来进行求解。 递归的三大要素 函数的参数。在用递归解决问题时&…

VMware挂载NAS存储异常处理

问题概述 由于非法关机或恢复&#xff0c;NFS存储可能会出现以下问题&#xff1a; 数据存储处于挂起状态或无法正常识别。虚拟机的配置文件或虚拟磁盘仍然注册在异常数据存储上。系统误认为有虚拟机在使用该数据存储。 问题对策 下面是详细的排查步骤和解决对策&#xff1a…

PFA烧杯带把手带刻度1000ml3000mlPFA氟树脂温度范围-270~250℃

随着越来越多的痕量分析实验需要对ppb和ppt级的浓度进行测定。目前所使用的一般材料由于无特别处理&#xff0c;不可避免会与所储存的样品&#xff0c;试剂或标准液反应&#xff0c;导致痕量分析实验得到不正确的结果。但我厂的PFA产品刚好能弥补其不足。PFA金属元素空白值低&a…

前端锚点 点击 滑动双向绑定

一. 页面样式 二. 代码 <div class"flexBox"><div class"mdDiv" v-for"(item,index) in tabList" :key"index" :class"nowChooseindex?choosed:" click"jumpMD(index, item.id)">{{item.name}}&l…

风光储一体化园区 | 图扑新能源可视化

随着全球能源结构转型加速&#xff0c;可再生能源成为能源发展的重要方向。风能、太阳能作为清洁、绿色的能源&#xff0c;得到了广泛的开发和应用。与此同时&#xff0c;储能技术的发展为解决风能和太阳能发电的间歇性和波动性问题提供了有效途径。 风光储园区作为整合风电、…