22、数据降维与缺失值处理技术详解

数据降维与缺失值处理技术详解

在数据分析和机器学习领域,数据降维和缺失值处理是两个重要的环节。数据降维可以减少数据的复杂度,提高模型的训练效率;而缺失值处理则直接影响到模型的准确性和可靠性。本文将详细介绍几种常见的数据降维方法和缺失值处理策略,并结合具体的代码示例进行说明。

1. 深度学习自动编码器

深度学习自动编码器是一种无监督学习模型,它可以通过学习数据的特征表示来实现数据的降维。在一个示例中,输入层有563个节点,连接到第一个隐藏层的128个节点,然后到第二个隐藏层的64个节点,第三个隐藏层是我们感兴趣的2个以上节点,接着回到64个节点,再到第五个也是最后一个隐藏层的128个节点,最后输出到563个输出节点。

以下是使用H2O库实现堆叠自动编码器的代码示例:

m1 = h2o.estimators.deeplearning.H2OAutoEncoderEstimator(
  hidden = [128,64,11,64,128], activation = "Tanh", epochs = 400
  )
m1.train(x = range(1,564), training_frame = tfidf)
f1 = m1.deepfeatures(tfidf, layer = 2)
m2 = h2o.estimators.deeplearning.H2OAutoEncoderEstimator(
  hidden = [2], activation = "Tanh", epochs = 400
  )
m2.train(x = range(0,11), training_frame = f1)
f2 = m2.deepfeatures(f1, layer = 0)

在这个示例中,模型m1有5个隐藏层,中间层有11个神经元,它在原始数据tfidf上进行训练。然后提取第三个隐藏层的数据到f1中,f1是tfidf的一个转换,仍然有100行,但现在只有11列。模型m2使用f1作为输入,构建了一个更简单的模型,将11个输入节点减少到2个隐藏节点,然后再输出到11个输出节点。最终结果存储在f2中,f2有2列,但仍然有100行,每行对应一部电影。

2. 主成分分析(PCA)

主成分分析(PCA)是另一种常用的数据降维方法,它可以通过线性变换将原始数据转换为一组新的正交变量,这些变量称为主成分。在H2O API和R中,PCA被称为prcomp。

以下是使用R语言实现PCA的代码示例:

library(h2o)
h2o.init(nthreads = -1)
tfidf <- h2o.importFile("./datasets/movie.tfidf.csv")
m <- h2o.prcomp(tfidf, 2:564, k = 2)
p <- h2o.predict(m, tfidf)

在这个示例中,我们将tf-idf分数用于描述100部电影的563个术语的数据降维到2个维度,以便进行可视化。运行代码后,p将有2列和100行。

3. 广义低秩模型(GLRM)

广义低秩模型(GLRM)是一种用于减少数据列数的算法,它可以在保持尽可能多的信息的同时处理非数值数据和缺失数据。GLRM还可以作为一种有损压缩算法,用于减少存储需求,并填充缺失值。

以下是使用R语言实现GLRM的代码示例:

library(h2o)
h2o.init(nthreads = -1)
tfidf <- h2o.importFile("./datasets/movie.tfidf.csv")
m <- h2o.glrm(tfidf, cols = 2:564, k = 2)
X <- h2o.getFrame(m@model$representation_name)
# Y <- m@model$archetypes

在这个示例中,GLRM将563列100行的数据转换为两个较小的矩阵:X(2列100行)和Y(563列2行)。通过这种方式,56300个单元格被减少到200 + 1126 = 1326个单元格。

4. 缺失值处理

在实际数据中,缺失值是一个常见的问题。不同的数据集中缺失值的情况可能不同,因此需要根据具体情况选择合适的处理方法。

4.1 数据集中缺失值情况分析

以足球数据集为例,训练集、验证集和测试集中的缺失字段各不相同。在训练集中,所有以“Bb”开头的列有60%的数据缺失,其他博彩赔率列的缺失率在35%到55%之间,34%的行没有比赛统计数据,26%的行没有半场结果。验证集的数据情况完全不同,只有2.3%的比赛受到影响,且仅涉及博彩赔率列。测试集中,85%的SJH、SJD、SJA列数据缺失。

以下是使用R语言分析缺失值的代码示例:

d <- as.data.frame(train)
dv <- as.data.frame(valid)
dt <- as.data.frame(test)

# 计算无缺失值的行数
sum(complete.cases(d))
mean(complete.cases(d))

# 计算每列的缺失值百分比
colMeans(is.na(d))
4.2 缺失值处理方法

常见的缺失值处理方法有两种:丢弃和填充。

  • 丢弃(Throw It Out) :例如,我们可以通过删除SJH、SJD和SJA列来处理测试集中的缺失值,这样可以使完整数据的比例从15%提高到99.8%。在H2O中,可以通过复制数据并指定要保留的列来删除列。
test <- test[!(colnames(test) %in% c('SJH', 'SJD', 'SJA'))]
  • 填充(Make It Up) :最简单的填充方法是将缺失值设置为零,但这种方法可能会影响数据的分布。更复杂的方法是使用列的均值、中位数或众数来填充缺失值。GLM和深度学习模型可以通过指定missing_values_handling = “MeanImputation”来自动执行均值填充。此外,H2O还提供了h2o.impute()函数,支持均值、中位数和众数填充。
# 均值填充示例
# 在GLM和深度学习模型中设置
# missing_values_handling = "MeanImputation"

# 使用h2o.impute()函数
# h2o.impute(data, column, method = "mean")

然而,这两种方法都有其局限性。在某些情况下,使用零填充对于树算法可能更好,因为零是一个罕见的值;而对于GLM等算法,均值填充可能更合适。理想的方法是能够保持数据直方图的形状。

5. 使用GLM填充缺失值

在处理足球数据集的缺失值时,作者尝试使用GLRM算法,但遇到了恢复值超出原始数据范围的问题。因此,作者转而使用GLM算法,为每个有缺失值的列建立一个线性模型,根据其他列的值来预测该列的缺失值。

以下是使用GLM填充缺失值的代码示例:

# 丢弃2000/2001赛季之前的数据
train2000 <- h2o.assign(train[14237:nrow(train),], "train2000")

# 填充博彩赔率列
dNew <- as.data.frame(train2000)
colnames(dNew) <- colnames(train2000)
lapply(oddFields, function(y){
  missingCount = sum(is.na(dNew[,y]))
  if(missingCount == 0)return(NULL)
  m <- h2o.glm(setdiff(oddFields, y), y,
    train2000, model_id = paste0("GLM_",y),
    lambda_search = TRUE
    )
  res <- h2o.predict(m, train2000[is.na(train2000[,y]),])
  v <- as.vector(res)
  dNew <- get('dNew', envir = .GlobalEnv)
  dNew[is.na(dNew[,y]),y] <- as.vector(res)
  assign('dNew', dNew, envir=.GlobalEnv)
  })
train2000x <- as.h2o(dNew, destination_frame = "train2000x")

# 填充其他列
mostFields <- setdiff(colnames(train), c("Date", "HomeTeam", "AwayTeam") )
lapply(statFields, function(y){
  missingCount <- sum(is.na(dNew[,y]))
  if(missingCount == 0)return(NULL)
  m <- h2o.glm(setdiff(mostFields, y), y,
    train2000x, model_id = paste0("GLM_",y),
    lambda_search = TRUE
    )
  res <- h2o.predict(m, train2000x[is.na(train2000x[,y]),])
  v <- as.vector(res)
  dNew <- get('dNew', envir = .GlobalEnv)
  dNew[is.na(dNew[,y]),y] <- as.vector(res)
  assign('dNew', dNew, envir=.GlobalEnv)
  })
train2000x <- as.h2o(dNew, destination_frame = "train2000x")

# 合并训练集和验证集
trainValid <- h2o.rbind(train2000x,valid)

# 合并训练集、验证集和测试集
trainValidTest <- h2o.rbind(train2000x, valid2000x, test)

# 导出数据到CSV文件
path = "/path/to/datasets/"
h2o.exportFile(train2000x, paste0(path, "football.train2.csv"))
h2o.exportFile(valid2000x, paste0(path, "football.valid2.csv"))
h2o.exportFile(test2000x, paste0(path, "football.test2.csv"))

通过使用GLM算法填充缺失值,作者得到了较好的结果。最终,HS和HS1的分布在填充后几乎完全相同。

6. 缺失值处理策略总结

不同的缺失值处理方法适用于不同的情况。以下是一个生日列缺失值处理的示例,说明了不同方法的优缺点:
| 方法 | 处理方式 | 优缺点 |
| ---- | ---- | ---- |
| 零填充 | 所有人的生日都设为1月1日 | 简单,但可能严重扭曲数据分布 |
| 均值填充 | 所有人的生日都设为6月30日 | 相对简单,但可能掩盖数据的真实特征 |
| GLM等模型填充 | 每个人得到一个任意生日,因为没有有用的预测因子 | 可能更准确,但需要合适的预测因子 |
| 跳过 | 忽略所有未告知生日的人 | 简单,但会丢失部分数据 |

综上所述,在处理缺失值时,需要根据数据的特点和具体的应用场景选择合适的方法。同时,对于时间序列数据,需要注意避免将未来的信息引入训练数据中。

数据降维与缺失值处理技术详解

7. 不同降维方法的对比

为了更直观地了解不同降维方法的特点,我们可以从多个方面对深度学习自动编码器、主成分分析(PCA)和广义低秩模型(GLRM)进行对比。

方法 处理数据类型 降维原理 特点 适用场景
深度学习自动编码器 数值数据 通过神经网络学习数据的特征表示,将数据映射到低维空间 可以学习到数据的复杂非线性特征,各维度平等 适用于复杂数据,对特征有深入挖掘需求的场景
主成分分析(PCA) 数值数据 通过线性变换将原始数据转换为一组新的正交变量,每个新变量依次保留最大的方差 每个新维度携带的信息逐渐减少,维度之间有主次之分 适用于线性数据,希望快速提取主要信息的场景
广义低秩模型(GLRM) 数值和非数值数据,可处理缺失值 将数据分解为两个较小的矩阵,在减少列数的同时保留信息 能处理复杂数据类型和缺失值,可用于压缩和填充 适用于包含多种数据类型和缺失值的数据

以下是一个简单的mermaid流程图,展示了选择降维方法的大致思路:

graph LR
    A[数据类型和特征] --> B{是否为线性数据}
    B -- 是 --> C{是否有缺失值或非数值数据}
    C -- 是 --> D[GLRM]
    C -- 否 --> E[PCA]
    B -- 否 --> F{是否需要深入挖掘特征}
    F -- 是 --> G[深度学习自动编码器]
    F -- 否 --> H[其他方法]
8. 缺失值处理的进一步探讨

在实际应用中,缺失值处理不仅仅是选择一种方法那么简单,还需要考虑数据的特性、模型的需求以及业务的背景。

8.1 数据特性对处理方法的影响
  • 数据分布 :如果数据分布呈现明显的偏态,使用均值填充可能会导致数据分布的扭曲。例如,在收入数据中,少数高收入者会拉高均值,使用均值填充可能会使大部分低收入者的填充值偏高。
  • 数据相关性 :如果数据列之间存在较强的相关性,利用相关列的信息进行填充可能会得到更准确的结果。如在足球数据集中,博彩赔率列之间高度相关,因此可以利用其他赔率列来预测缺失的赔率值。
8.2 模型需求对处理方法的影响
  • 线性模型 :如GLM,对数据的数值准确性要求较高,均值填充可能更合适,因为它能保持数据的整体均值不变,有利于模型的线性计算。
  • 树模型 :树模型通过对数据进行分割来构建决策树,零填充可能更能体现缺失值的特殊性,因为零在数据中可能是一个罕见的值,能帮助树模型更好地区分不同情况。
8.3 业务背景对处理方法的影响

在某些业务场景中,数据的缺失可能具有特定的含义。例如,在医疗数据中,某些检查结果的缺失可能意味着患者没有进行该项检查,而不是数据录入的失误。在这种情况下,需要根据业务逻辑进行特殊处理,而不是简单地填充或丢弃。

9. 综合应用案例

假设我们有一个包含用户行为数据的数据集,其中包含用户的年龄、性别、消费金额、购买频率等信息,部分数据存在缺失值。我们的目标是对用户进行分类,以便进行精准营销。

9.1 数据预处理
  • 缺失值分析 :使用R语言的相关函数,分析各列的缺失值情况。
data <- read.csv("user_data.csv")
colMeans(is.na(data))
  • 缺失值处理 :根据数据特性和业务需求,选择合适的处理方法。对于年龄列,如果缺失值较少,可以使用均值填充;对于消费金额列,如果与其他列有较强的相关性,可以使用GLM模型进行填充。
# 均值填充年龄列
data$age[is.na(data$age)] <- mean(data$age, na.rm = TRUE)

# 使用GLM填充消费金额列
library(h2o)
h2o.init()
train <- as.h2o(data)
m <- h2o.glm(setdiff(colnames(train), "consumption_amount"), "consumption_amount",
             train, model_id = "GLM_consumption",
             lambda_search = TRUE)
res <- h2o.predict(m, train[is.na(train$consumption_amount),])
data$consumption_amount[is.na(data$consumption_amount)] <- as.vector(res)
9.2 数据降维

由于数据维度较多,为了提高模型的效率和准确性,我们可以使用PCA进行降维。

m <- h2o.prcomp(train, 1:ncol(train), k = 3)
p <- h2o.predict(m, train)
9.3 模型训练

使用降维后的数据进行模型训练,例如使用随机森林进行用户分类。

library(randomForest)
model <- randomForest(p, data$category, ntree = 100)
10. 总结与建议

在数据处理和分析过程中,数据降维和缺失值处理是两个关键的步骤。不同的降维方法和缺失值处理策略各有优缺点,需要根据数据的特点、模型的需求和业务的背景进行选择。

  • 降维方法选择 :如果数据具有复杂的非线性特征,深度学习自动编码器是一个不错的选择;如果数据是线性的且希望快速提取主要信息,PCA更为合适;如果数据包含多种类型和缺失值,GLRM是首选。
  • 缺失值处理 :对于简单的数据,可以使用零填充或均值填充;对于复杂的数据,建议使用模型填充,如GLM、随机森林等。同时,要注意避免在时间序列数据中引入未来信息。

在实际应用中,可以先对数据进行初步的探索和分析,确定大致的处理方向,然后通过实验对比不同方法的效果,选择最优的方案。希望本文能为你在数据降维和缺失值处理方面提供一些有益的参考和指导。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值