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

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

我们假设存在一个潜在的分布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.xdnf.cn/news/1452956.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

程序员“种种”副业,有没有适合你的?

点击下方“JavaEdge”&#xff0c;选择“设为星标” 第一时间关注技术干货&#xff01; 免责声明~ 任何文章不要过度深思&#xff01; 万事万物都经不起审视&#xff0c;因为世上没有同样的成长环境&#xff0c;也没有同样的认知水平&#xff0c;更「没有适用于所有人的解决方案…

Windows安装配置CUDA12.5

搞大模型往往都需要GPU加速&#xff0c;本次在家里的PC上安装CUDA来实现GPU加速。 一、环境准备 操作系统&#xff1a;Windows11 23H2 GPU&#xff1a;RTX 4070 Ti Super 显卡驱动&#xff1a;555.99 &#xff08;NVIDIA GeForce 驱动程序 - N 卡驱动 | NVIDIA&#xff09; …

Tailwind CSS v4.0 Alpha 发布:更快、更强大、更现代!

大家好&#xff0c;我是前端宝哥。 太棒了&#xff01; Tailwind CSS 终于发布了 4.0 版本的 Alpha 版本&#xff01; 还记得去年夏天在 Tailwind Connect 大会上&#xff0c;他们分享了 Oxide 的预告吗&#xff1f; 这个全新的高性能引擎是 Tailwind CSS 的全新升级&#xff0…

C++ string字符串的使用和简单模拟实现

目录 前言 1. string简介 2. string的使用和简单模拟实现 2.1 string类的定义 2.2 string(),~string()和c_str() 2.2 size&#xff0c;重载符号[ ]&#xff0c;begin和end函数 2.3 push_back&#xff0c;reserve&#xff0c;append&#xff0c;运算符重载 2.4 insert和…

WSL Ubuntu安装TensorFlow-GPU、PyTorch-GPU

在Windows 11的WSL Ubuntu中安装TensorFlow-GPU、PyTorch-GPU 0、WSL Ubuntu安装 在Windows 11的商店中下载即可&#xff0c;此处以Ubuntu22.04.3为例 1、CUDA Toolkit安装 参考公孙启的文章Windows11 WSL Ubuntu Pycharm Conda for deeplearning前往nVidia官网下载CUDA …

VCG显示——汉字,数字,图像

详细的介绍资料&#xff1a; 【从零开始走进FPGA】 玩转VGA http://www.cnblogs.com/spartan/archive/2011/08/16/2140546.html 【FPGA实验】基于DE2-115平台的VGA显示_vga接口实验 de2-115-CSDN博客 【FPGA】VGA显示文字、彩条、图片——基于DE2-115-CSDN博客 一.VCG原理 1.1…

LeetCode --- 401周赛

题目列表 3178. 找出 K 秒后拿着球的孩子 3179. K 秒后第 N 个元素的值 3180. 执行操作可获得的最大总奖励 I 3181. 执行操作可获得的最大总奖励 II 一、找出K秒后拿着球的孩子 这题可以直接模拟&#xff0c;从前往后&#xff0c;再从后往前走k次&#xff0c;最后直接返回…

uniapp使用css实现瀑布流

页面 <template><view><gj v-if"likeList.length 0"></gj><view v-else class"list"><view class"pbl" v-for"(item,index) in likeList" :key"index"><view class"image&quo…

如何通过在线封装APP快速上线?小猪APP分发帮你解决难题

你是否曾经为了上线一款APP而头疼不已&#xff1f;开发完成后&#xff0c;封装、测试、分发&#xff0c;这些繁琐的步骤让人望而却步。别担心&#xff0c;小猪APP分发来了&#xff01;这篇文章将带你了解如何通过在线封装APP快速上线&#xff0c;并且告诉你为什么选择小猪APP分…

英语学习笔记37——Making a bookcase

Making a bookcase 做书架 词汇 Vocabulary work v. 工作 ing形式&#xff1a;working 搭配&#xff1a;work on 工作 做……工作    work for 人 为……而工作 例句&#xff1a;我正在做我的家庭作业。    I am working on my homework.    我正在为Bobby工作。 …

MEMS:Lecture 18 Feedback

讲义 Linear feedback MEMS热板 Hotplate MEMS&#xff08;微机电系统&#xff09;热板是现代气体传感器的重要组成部分。它们通过加热一种活性材料来工作&#xff0c;这种材料与气体发生反应&#xff0c;从而改变其电阻。电阻的变化可以用来检测和测量特定气体的存在和浓度。…

Go注册GRPC服务遇到接口未实现报错处理方法

已经完成了proto文件中所有接口的实现 但是注册服务这里仍然会报错 且添加实现方法也无法解决 最终解决方法 在handle.go中的server结构体加入 proto.UnimplementedUserServer 可以避免方法未实现的错误

求导,积分

求导公式&#xff1a; 复合函数求导法则&#xff1a;两个函数导函数的乘积. 例如&#xff1a;f(x)2x1,f(x)2,g(x)x^24x4,g(x)2x4 那么复合函数&#xff1a; g(f(x))(2x1)^24(2x1)4 把&#xff08;2x1&#xff09;看做整体,则g2(2x1)4 然后再求&#xff08;2x1&#xff09;的导函…

使用PyMuPDF程序处理PDF

MuPDF 是一个 C/C 编写的跨平台 PDF 库&#xff0c;它提供强大的功能来处理 PDF 文件&#xff0c;包括提取文本、图像和元数据&#xff0c;以及支持PDF页面的添加、删除和旋转。PyMuPDF 是 MuPDF 的 Python 版本&#xff0c;允许 Python 程序使用 MuPDF 的强大功能。 首先&…

Spring Bean详解

Spring Bean作用域 默认情况下&#xff0c;所有的 Spring Bean 都是单例的&#xff0c;也就是说在整个 Spring 应用中&#xff0c; Bean 的实例只有一个 如果我们需要创建多个实例的对象&#xff0c;那么应该将 Bean 的 scope 属性定义为 prototype&#xff0c;如果 Spring 需…

热门开源项目ChatTTS: 国内语音技术突破,实现弯道超车

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

【Quartus 13.0】NIOS II 部署UART 和 PWM

打算在 EP1C3T144I7 芯片上部署 nios ii 做 uart & pwm控制 这个芯片或许不够做 QT 部署 这个芯片好老啊&#xff0c;但是做控制足够了&#xff0c;我只是想装13写 leader给的接口代码是用VHDL写的&#xff0c;我不会 当然verilog我也不太会 就这样&#xff0c;随便写吧 co…

Tensorflow-GPU工具包了解和详细安装方法

目录 基础知识信息了解 显卡算力 CUDA兼容 Tensorflow gpu安装 CUDA/cuDNN匹配和下载 查看Conda driver的版本 下载CUDA工具包 查看对应cuDNN版本 下载cuDNN加速库 CUDA/cuDNN安装 CUDA安装方法 cuDNN加速库安装 配置CUDA/cuDNN环境变量 配置环境变量 核验是否安…

51单片机STC89C52RC——2.1 独立按键控制LED亮灭

目录 目的 一&#xff0c;STC单片机模块 二&#xff0c;独立按键 2.1 独立按键位置 2.2 独立按键电路图 三&#xff0c;创建Keil项目 四&#xff0c;代码 五&#xff0c;代码编译、下载到51单片机 六&#xff0c;效果 目的 当独立K1按键按下时LED D1 点亮&#x…

IDEA上MySQL的jar包导入教程

jar包下载网址——》https://mvnrepository.com/ 1.进入界面&#xff0c;点击搜索框&#xff0c;搜索mysql&#xff1a; 外国网站&#xff0c;可能有点慢,耐心等待即可。 2.点击查询结果&#xff1a; 进入界面&#xff0c;点击前两个结果的其中一个&#xff0c;两个都可以 …