R、SOM、Kohonen 包、异常值检测

2023-12-27

我用 SOM 做了一些实验。首先,我在 Python 中使用 MiniSOM,但没有留下深刻的印象,于是改用 R 中的 kohonen 包,它比以前提供了更多功能。基本上,我将 SOM 应用到三个用例:(1) 使用生成的数据进行二维聚类,(2) 使用更多维数据进行聚类:内置葡萄酒数据集,以及 (3) 异常值检测。我解决了所有三个用例,但我想提出一个与我应用的异常值检测有关的问题。为此,我使用了向量索姆$距离,其中包含输入数据集每行的距离。具有出色距离的值可能是异常值。但是,我不知道这个距离是如何计算的。包描述(https://cran.r-project.org/web/packages/kohonen/kohonen.pdf https://cran.r-project.org/web/packages/kohonen/kohonen.pdf)该指标的状态:“到最近单位的距离”。

  1. 你能告诉我这个距离是如何计算的吗?
  2. 您能评论一下我使用的异常值检测吗?你会怎么做呢? (在生成的数据集中,它确实找到了异常值。在 真实的葡萄酒数据集中,177个葡萄酒品种中,有四个相对优秀的数值。看 下面的图表。我突然想到使用条形图来描述这一点,我真的很喜欢。)

Charts:

  • Generated data, 100 point in 2D in 5 distinct clusters and 2 outliers (Category 6 shows the outliers): enter image description here

  • Distances shown for all the 102 data points, the last two ones are the outliers which were correctly identified. I repeated the test with 500, and 1000 data points and added solely 2 outliers. The outliers were also found in those cases. enter image description here

  • Distances for the real wine data set with potential outliers: enter image description here

潜在异常值的行 ID:

# print the row id of the outliers
# the threshold 10 can be taken from the bar chart,
# below which the vast majority of the values fall
df_wine[df_wine$value > 10, ]

it produces the following output:
    index    value
59     59 12.22916
110   110 13.41211
121   121 15.86576
158   158 11.50079

我带注释的代码片段:

        data(wines)

        scaled_wines <- scale(wines)

        # creating and training SOM
        som.wines <- som(scaled_wines, grid = somgrid(5, 5, "hexagonal"))
        summary(som.wines)

        #looking for outliers, dist = distance to the closest unit
        som.wines$distances

        len <- length(som.wines$distances)
        index_in_vector <- c(1:len)
        df_wine<-data.frame(cbind(index_in_vector, som.wines$distances))
        colnames(df_wine) <-c("index", "value")

        po <-ggplot(df_wine, aes(index, value)) + geom_bar(stat = "identity") 
        po <- po + ggtitle("Outliers?") + theme(plot.title = element_text(hjust = 0.5)) + ylab("Distances in som.wines$distances") + xlab("Number of Rows in the Data Set")
        plot(po)

        # print the row id of the outliers
        # the threshold 10 can be taken from the bar chart,
        # below which the vast majority of the values fall
        df_wine[df_wine$value > 10, ]

更多代码示例

关于评论中的讨论,我还发布了所需的代码片段。据我记得,负责聚类的代码行是根据我在 Kohonen 包的描述中找到的示例构建的(https://cran.r-project.org/web/packages/kohonen/kohonen.pdf https://cran.r-project.org/web/packages/kohonen/kohonen.pdf)。不过,我不太确定,那是一年多前的事了。该代码按原样提供,没有任何保证:-)。请记住,特定的聚类方法可能会在不同的数据上以不同的精度执行。我还建议将其与葡萄酒数据集上的 t-SNE 进行比较(data(wines)在 R 中可用)。此外,实施热图来演示如何定位有关各个变量的数据。 (在上面有 2 个变量的示例中,这并不重要,但对于葡萄酒数据集来说会很好)。

具有五个聚类和 2 个离群值的数据生成和绘图

            library(stats)
            library(ggplot2)

            library(kohonen)


            generate_data <- function(num_of_points, num_of_clusters, outliers=TRUE){
              num_of_points_per_cluster <- num_of_points/num_of_clusters
              cat(sprintf("#### num_of_points_per_cluster = %s, num_of_clusters = %s \n", num_of_points_per_cluster, num_of_clusters))
              arr<-array()
              
              standard_dev_y <- 6000
              standard_dev_x <- 2
              
              # for reproducibility setting the random generator
              set.seed(10)
              
              for (i in 1:num_of_clusters){
                centroid_y <- runif(1, min=10000, max=200000)
                centroid_x <- runif(1, min=20, max=70)
                cat(sprintf("centroid_x = %s \n, centroid_y = %s", centroid_x, centroid_y ))
                
                vector_y <- rnorm(num_of_points_per_cluster, mean=centroid_y, sd=standard_dev_y)
                vector_x <- rnorm(num_of_points_per_cluster, mean=centroid_x, sd=standard_dev_x)
                cluster <- array(c(vector_y, vector_x), dim=c(num_of_points_per_cluster, 2))
                cluster <- cbind(cluster, i)
                
                arr <- rbind(arr, cluster)
              }
              
              if(outliers){
                #adding two outliers
                arr <- rbind(arr, c(10000, 30, 6))
                arr <- rbind(arr, c(150000, 70, 6))
              }
              
              colnames(arr) <-c("y", "x", "Cluster")
              # WA to remove the first NA row
              arr <- na.omit(arr)
              return(arr)
            }

            scatter_plot_data <- function(data_in, couloring_base_indx, main_label){
              
              df <- data.frame(data_in)
              colnames(df) <-c("y", "x", "Cluster")

              pl <- ggplot(data=df, aes(x = x,y=y)) + geom_point(aes(color=factor(df[, couloring_base_indx]))) 
              pl <- pl + ggtitle(main_label) + theme(plot.title = element_text(hjust = 0.5))
              print(pl)
              
            }

            ##################
            # generating data
            data <- generate_data(100, 5, TRUE)
            print(data)
            scatter_plot_data(data, couloring_base_indx<-3, "Original Clusters without Outliers \n 102 Points")

准备、聚类和绘图

我使用了 Kohonen Map (SOM) 的层次聚类方法。

            normalising_data <- function(data){
              # normalizing data points not the cluster identifiers
              mtrx <- data.matrix(data)
              umtrx <- scale(mtrx[,1:2])
              umtrx <- cbind(umtrx, factor(mtrx[,3]))
              colnames(umtrx) <-c("y", "x", "Cluster")
              return(umtrx)
            }

            train_som <- function(umtrx){
              # unsupervised learning
              set.seed(7)
              g <- somgrid(xdim=5, ydim=5, topo="hexagonal")
              #map<-som(umtrx[, 1:2], grid=g, alpha=c(0.005, 0.01), radius=1, rlen=1000)
              map<-som(umtrx[, 1:2], grid=g)
              summary(map)
              
              return(map)
            }

            plot_som_data <- function(map){
              par(mfrow=c(3,2))
              # to plot some charactristics of the SOM map
              plot(map, type='changes')
              plot(map, type='codes', main="Mapping Data")
              plot(map, type='count')
              plot(map, type='mapping') # how many data points are held by each neuron
              plot(map, type='dist.neighbours') # the darker the colours are, the closer the point are; the lighter the colours are, the more distant the points are
              
              #to switch the plot config to the normal
              par(mfrow=c(1,1))
            }

            plot_disstances_to_the_closest_point <- function(map){
              
              # to see which neuron is assigned to which value 
              map$unit.classif
              
              #looking for outliers, dist = distance to the closest unit
              map$distances
              max(map$distances)
              
              len <- length(map$distances)
              index_in_vector <- c(1:len)
              df<-data.frame(cbind(index_in_vector, map$distances))
              colnames(df) <-c("index", "value")
              
              po <-ggplot(df, aes(index, value)) + geom_bar(stat = "identity") 
              po <- po + ggtitle("Outliers?") + theme(plot.title = element_text(hjust = 0.5)) + ylab("Distances in som$distances") + xlab("Number of Rows in the Data Set")
              plot(po)
              
              return(df)
              
            }


            ###################
            # unsupervised learning

            umtrx <- normalising_data(data)

            map<-train_som(umtrx)
            plot_som_data(map)

            #####################
            # creating the dendogram and then the clusters for the neurons
            dendogram <- hclust(object.distances(map, "codes"), method = 'ward.D')
            plot(dendogram)

            clusters <- cutree(dendogram, 7)
            clusters
            length(clusters)

            #visualising the clusters on the map
            par(mfrow = c(1,1))
            plot(map, type='dist.neighbours', main="Mapping Data")
            add.cluster.boundaries(map, clusters)

聚类图

您还可以为选定的变量创建漂亮的热图,但我还没有实现它们以使用 2 个变量进行聚类,这实际上没有意义。如果您为葡萄酒数据集实现它,请将代码和图表添加到本文中。

            #see the predicted clusters with the data set
            # 1. add the vector of the neuron ids to the data
            mapped_neurons <- map$unit.classif
            umtrx <- cbind(umtrx, mapped_neurons)

            # 2. taking the predicted clusters and adding them the the original matrix
            # very good description of the apply functions:
            # https://www.guru99.com/r-apply-sapply-tapply.html
            get_cluster_for_the_row <- function(x, cltrs){
              return(cltrs[x])
            }

            predicted_clusters <- sapply (umtrx[,4], get_cluster_for_the_row, cltrs<-clusters)

            mtrx <- cbind(mtrx, predicted_clusters)
            scatter_plot_data(mtrx, couloring_base_indx<-4, "Predicted Clusters with Outliers \n 100 points")

请参阅下面的预测集群,了解是否存在异常值。


  1. 虽然我不太确定,但我经常发现驻留在特定维度空间中的两个物体的距离测量主要使用欧几里德距离。例如,位置为A(x=3,y=4)和B(x=6,y=8)的二维空间中的两个点A和B相距5个距离单位。它是执行平方根((3-6)^2 + (4-8)^2)计算的结果。这也适用于维度较大的数据,通过添加特定维度中两点值之差的两个尾随幂。如果 A(x=3, y=4, z=5) 和 B(x=6, y=8, z=7) 则距离为平方根((3-6)^2 + (4-8)^ 2 + (5-7)^2),依此类推。在kohonen中,我认为模型完成训练阶段后,算法会计算每个数据到所有节点的距离,然后将其分配给最近的节点(与其距离最小的节点)。最终,模型返回的变量“距离”内的值是每个数据到其最近节点的距离。脚本中需要注意的一件事是,算法不会直接测量与数据所具有的原始属性值的距离,因为它们在将数据输入模型之前已经进行了缩放。距离测量应用于数据的缩放版本。缩放是消除一个变量对另一个变量的主导地位的标准程序。
  2. 我相信你的方法是可以接受的,因为“距离”变量内的值是每个数据到最近节点的距离。因此,如果一个数据与其最近的节点之间的距离值很高,那么这也意味着:该数据到其他节点的距离显然要高得多。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

R、SOM、Kohonen 包、异常值检测 的相关文章

  • 删除字符串末尾的句点和数字

    如何删除尾随句点 后面紧跟一个数字 长度为一位或两位数字 例子 z lt c awe p 56 red 45 ted 5 you 88 tom 我只想删除 45和 5 你只需要一个简单的正则表达式 z new gsub 0 9 z 一些评论
  • 对 data.table 中的列表列执行操作

    假设我有一个data table 例如dt lt data table foo list 1 3 4 6 bar c 2 7 如何使用 dt 框架对 foo 向量列表执行操作 操作可能是将 bar 添加到 foo 返回列表 3 5 11 1
  • R 中按时间划分的平均值

    我每秒测量一次化合物浓度 我想求 30 秒和 60 秒的平均值 我一直在阅读这里的帖子 我尝试过lubridate and dplyr 但没有运气 我正在努力完成这项工作 但我一直没能做到 我正在从 SAS 过渡到 R 所以请耐心等待 这是
  • 如何在knitr和RStudio中为word和html设置不同的全局选项?

    我正在使用 RStudio 0 98 932 和 knitr 1 6 想要为word和html设置不同的全局knitr选项 例如 想要将word的fig width和fig height设置为6 html的fig width和fig hei
  • 获取函数的命名空间

    我正在开发一个包 我希望在其中向对象添加编辑历史记录 该包允许其他包注册用于编辑对象的函数 我正在寻找一种方法来记录注册用于编辑的函数的包的版本 问题是 给定一个函数 如何从导出的位置获取包 我的想法是调查它的搜索路径 但是search 仅
  • randomForest 包在删除一个预测类时的奇怪行为

    我正在运行一个随机森林模型 它产生的结果从统计角度来看对我来说完全没有意义 因此我确信有些东西mustrandomForest 包的代码出现错误 至少在模型的本次迭代中 预测 左侧变量是具有 3 种可能结果的政党 ID 民主党 独立党 共和
  • 正态分布平均值的贝叶斯推理玩具 R 代码 [降雪量数据]

    我有一些降雪观测 x lt c 98 044 107 696 146 050 102 870 131 318 170 434 84 836 154 686 162 814 101 854 103 378 16 256 我被告知它遵循正态分布
  • 警告消息 - 来自 dummies 包的 dummy

    我正在使用 dummies 包为分类变量生成虚拟变量 其中一些变量具有两个以上类别 testdf lt data frame A as factor c 1 2 2 3 3 1 B c A B A B C C C c D D E D D E
  • picker输入字体或背景颜色

    我在闪亮的仪表板中使用 pickerInput 这很好 除了一个问题 背景颜色和字体颜色太相似 使得过滤器选择难以阅读 有什么办法可以改变背景或字体颜色吗 如果可能的话 我想继续使用 pickerInput 但如果有一个带有 selectI
  • 如何纠正 data.frame 上的字符编码

    我有一个像这样的数据框 data names lt data frame DATA c 1 5 rownames data names lt c IV xc1N JOS xc9 LUC xcdA RAM xd3N TO xd1O data
  • 我可以使用哪个 R 函数来查找两条线的交点?

    我刚刚研究了 stackoverflow 上所有的 在 R 中寻找交集 问题 它们要么是关于曲线 要么是关于分布像这个 https stackoverflow com questions 20519431 finding point of
  • 如何在 R 中的 for 循环内将值存储在向量中

    我正在开始使用 R 但我对以下问题感到非常沮丧 我试图将 for 循环内完成的某些计算的值存储到我之前定义的向量中 问题是如何进行索引 因为for循环迭代代码的次数取决于用户的输入 所以变量i不一定要从1开始 它可以从80开始 for举个例
  • 在 R 的 for 循环中创建动态命名对象并分配动态值

    我正在尝试创建一套动态命名的新对象 例如 temp2015 使用 for 循环 并存储动态值 具体来说 其他对象的名称 例如 Y2015 和 for 循环中使用的值 例如 2015 在动态命名的新对象中 我不确定为什么下面的代码不起作用 Y
  • 从 data.frame 在 ggplot 图例中添加信息

    我想在图例中添加信息 哪个传感器具有该值 这是我的代码 z lt data frame a c sensor 1 sensor 2 sensor 3 sensor 4 sensor 5 sensor 6 sensor 7 sensor 8
  • R Shinydashboard 自定义 CSS 到 valueBox

    我一直在尝试将 valueBox 的颜色更改为自定义颜色 超出 validColors 中可用的颜色 但一直无法这样做 我知道有一种方法可以使用标签来包含自定义 CSS 但是我无法将它们放在正确的位置 ui lt dashboardPage
  • 在 RMarkdown 输出到 PDF 时缩进而不添加项目符号点或编号

    之前有人问过如何在没有项目符号的情况下缩进文本 RMarkdown 中的点 但这是针对 HTML 输出的 在 RMarkdown 中缩进而不添加项目符号点或数字 https stackoverflow com questions 47087
  • 在包加载之前如何知道 R 中特定函数属于哪个包?

    例如 我知道许多流行的功能 例如tbl df 我通常不记得它属于哪个包 即data table or dplyr 所以我必须始终记住并加载一个包 但我做不到 tbl df除非我加载了正确的包 在 R 控制台本身加载或安装包之前 有没有办法知
  • R:按组,测试一个变量的每个值是否存在于另一个变量中

    我有一个数据框架 结构如下 a lt c 1 1 1 2 2 2 3 3 3 3 4 4 b lt c 1 2 3 1 2 3 1 2 3 4 1 2 c lt c NA NA 2 NA 1 1 NA NA 1 1 NA NA df lt
  • 增加雷达图中长轴标签的空间

    我想创建一个雷达图ggirahExtra ggRadar 问题是我的标签很长并且被剪掉了 我想我可以通过添加在标签和绘图之间创建更多空间margin margin 0 0 2 0 cm to element text in axis tex
  • 如何为自定义 S3 类实现提取/取子集 ([ [<-, [[ [[<-)] 函数?

    我有一个自定义的 S3 类foo 它在正常的基础上添加了一些自定义行为data frame foo object lt data frame class foo object lt c foo data frame 对于这个类 还应该有一个

随机推荐

  • Rails 中同一个类的多个关联的最佳实践?

    我认为我的问题最好作为一个例子来描述 假设我有一个名为 Thing 的简单模型 它有一些简单数据类型的属性 就像是 Thing foo string goo string bar int 这并不难 db 表将包含具有这三个属性的三列 我可以
  • 如何用 PHP 计算 AWS 签名?

    我正在 bref 中编写一个 webhook 并希望它向 SQS 发送消息 为此使用整个 AWS SDK 是一种巨大的浪费 我如何计算签名 const AWS DATETIME FORMAT Ymd THis Z url getenv SQ
  • 如何查看php的执行时间? [复制]

    这个问题在这里已经有答案了 我的网站中有大量 PHP 代码 我想知道执行时间处理时间的处理 我怎样才能做到这一点 您可以使用microtime as the start and end你的 PHP 代码
  • Spark 结构化流 ForeachWriter 和数据库性能

    我已经尝试过像这样实现结构化流 myDataSet map r gt StatementWrapper Transform r writeStream foreach MyWrapper myWriter start awaitTermin
  • 如何在 ASP.NET Core 中将备用文件夹配置为 wwwroot?

    是否可以配置不同的文件夹来替换wwwroot在 ASP NET Core 中 如果是的话 怎么办 这种改变有副作用吗 目前唯一包含的配置wwwroot在整个项目中发现project json如下面的代码所示 但用新文件夹的名称替换该值对于静
  • 高阶函数,如何在不铸造的情况下从模型中推导出注入类型

    我有点坚持这个非常简单的想法 想象一下 我们有一个简单的高阶函数 它接受另一个函数和某个对象并返回另一个函数 const hof callback data gt model gt callback data model 现在我想做的是 类
  • 如何在 iOS 7 和 iOS 8 中锁定设备方向

    我的应用程序有问题 我无法锁定应用程序的方向 我需要做的就是将一个视图控制器锁定为横向模式 其余的为纵向模式 这是我的应用程序的层次结构 Navigation Controller TabBarController ViewControll
  • 更新函数内的全局 js 变量并将更新后的内容发送到 HTML 文档

    我在更新全局变量并将更新后的内容发送到 HTML 时遇到了很大的困难 我在 HTML 中有以下内容 We found places for you 在 JavaScript 中 var mainCount 3 Global variable
  • 如何在 PyMuPDF 中获取文本的背景颜色

    我试图看看是否可以使用文本的背景和前景色识别 PDF 内表格中可能的表格标题 通过 PyMuPDF 文本提取 我能够获得前景色 想知道是否有办法也获得背景颜色 我使用 pymupdf 1 16 2 和 python 3 7 我已检查过文档
  • NSPointerArray 奇怪的压缩

    我有一个弱者NSPointerArray和一些NSObject已被释放 致电之前compact我看到的是 lldb po currentArray count 1 lldb po currentArray pointerAtIndex 0
  • Next.js - router.push 无需滚动到顶部

    我正在通过导入使用下一个路由器useRouter from next router 我正在尝试找到一种解决方案 当我更改 URL 的查询时 该解决方案不会滚动到页面顶部 有什么解决办法吗 我知道 Next 的 Link 组件有这个选项 但我
  • 创建 CSS 网格布局

    我需要使用 CSS 网格创建一个布局 如下图所示 分辨率高于 900px For resolutions below 900px I need the layout to look like this 到目前为止 我已经尝试过 contai
  • 如何在Java中获取当前日期/时间[重复]

    这个问题在这里已经有答案了 在 Java 中获取当前日期 时间的最佳方法是什么 在 Java 中获取当前日期 时间的最佳方法是什么 没有 最好 的方法 这取决于您想要什么形式的日期 时间 If you want the date time
  • 如何使用 ANTLR4 创建 AST?

    我对此进行了很多搜索 但找不到任何有用的东西可以真正帮助我构建 AST 我已经知道 ANTLR4 不像 ANTLR3 那样构建 AST 每个人都说 嘿 使用访问者 但我找不到任何示例或更详细的解释如何做到这一点 我有一个必须像 C 语言一样
  • LINQ 内部如何工作?

    我喜欢在 NET 中使用 LINQ 但我想知道它的内部工作原理是什么 询问 LINQ 的某个特定方面更有意义 这有点像问 Windows 是如何工作的 从 C 的角度来看 LINQ 的关键部分对我来说是 表达式树 这些是代码作为数据的表示
  • 带有选项字段的 F# 记录在 Asp.Net WebApi 2.x 应用程序中无法正确反序列化

    我有一个 C Asp Net MVC 5 2 7 应用程序 支持面向 Net 4 5 1 的 WebApi 2 x 我正在尝试使用 F 并向解决方案中添加了一个 F 库项目 Web 应用程序引用 F 库 现在 我希望能够让 C WebApi
  • System.Data.Entity.Infrastruct.CommitFailedException:C# 多线程和 SQL Server 2012

    我们有一个 C 多线程 100 个线程 程序 它从数据库读取记录 每个线程获取一条记录 每个线程一个实体框架连接 并更新单个数据库表 在最初的几分钟 5 分钟 内 程序运行良好 没有异常 然后突然所有线程开始抛出以下错误消息 大约 1 分钟
  • 参数化 SQL、ORACLE 与带有正则表达式的 SQL Server

    Oracle 和 Sql 服务器在参数化字符串中使用不同的参数前缀 sql使用 p1 ORA使用 p1 我想在我的 SQL 中使用 如果使用 ORA 数据库 字符应替换为 你能帮我创建正则表达式吗 下面是一些 SQL 示例 update t
  • c# 仍然返回错误的核心数

    好的 所以我发布了在 C 中 GetEnvironmentVariable NUMBER OF PROCESSORS 返回错误的数字 https stackoverflow com questions 11571994 in c sharp
  • R、SOM、Kohonen 包、异常值检测

    我用 SOM 做了一些实验 首先 我在 Python 中使用 MiniSOM 但没有留下深刻的印象 于是改用 R 中的 kohonen 包 它比以前提供了更多功能 基本上 我将 SOM 应用到三个用例 1 使用生成的数据进行二维聚类 2 使