去除具有数量级差异的异常值

数据挖掘 离群值 sql
2022-03-06 10:58:43

我有一个来自移动游戏应用程序的虚拟货币收入和支出事件数据集。不幸的是,人们在游戏中作弊以获得更多货币。这些作弊者使用不同的技术,因此很难在游戏中全部检测到。数据集也大约 50 TB,所以我唯一的选择是使用 SQL(在 Google Bigquery 上)。

它试图制作一个标准的异常值检测系统,在该系统中,我可以找到每个级别的货币收入和支出的平均值和标准差。这适用于最大的异常值。但是,有些人作弊是为了赚取,例如 1e15 金币,而另一些人则“只”作弊以获得 10000 金币。正常的金币赚取率不应高于 1000 左右。标准的异常值检测系统适用于 1e15 的金币赚取者,但由于该人的 avg 和 std 如此之高,因此 10000 金币并未被发现是异常值.

有谁知道如何成功找到这些异常值?

我的数据集看起来像这样。(应该注意,作弊者并不经常出现,并且数据集有数十亿行):

user_id, currency, earn_or_spend, source_or_sink, amount
'user_1', 'gold', 'earn', 'quest', 3
'user_1', 'cash', 'earn', 'building_collect', 10000
'user_3', 'gold', 'spend', 'quest', 1
'user_2', 'gold', 'earn', 'quest', 4
'user_1', 'cash', 'earn', 'building_collect', 50000
'user_1', 'gold', 'earn', 'quest', 5
'user_4', 'gold', 'earn', 'quest', 99999 # cheater
'user_3', 'gold', 'spend', 'quest', 3
'user_5', 'gold', 'earn', 'quest', 1E15 # cheater
'user_3', 'cash', 'earn', 'level_up', 100000
'user_1', 'gold', 'earn', 'quest', 3
'user_1', 'cash', 'spend', 'build_building', 50000

可以使用以下代码在 Google BigQuery 中生成它:

WITH data as (
  SELECT 
    * 
  FROM UNNEST
  (
    ARRAY<STRUCT<user_id STRING, currency STRING, earn_or_spend STRING, source_or_sink STRING, amount FLOAT64>>
    [
      ('user_1', 'gold', 'earn', 'quest', 3),
      ('user_1', 'cash', 'earn', 'building_collect', 10000),
      ('user_3', 'gold', 'spend', 'quest', 1),
      ('user_2', 'gold', 'earn', 'quest', 4),
      ('user_1', 'cash', 'earn', 'building_collect', 50000),
      ('user_1', 'gold', 'earn', 'quest', 5),
      ('user_4', 'gold', 'earn', 'quest', 99999), # cheater
      ('user_3', 'gold', 'spend', 'quest', 3),
      ('user_5', 'gold', 'earn', 'quest', 1E15), # cheater
      ('user_3', 'cash', 'earn', 'level_up', 100000),
      ('user_1', 'gold', 'earn', 'quest', 3),
      ('user_1', 'cash', 'spend', 'build_building', 50000)
    ]
  )
)

SELECT * FROM data
1个回答

我设法做到了。我终于使用了三个异常值过滤器。

  • 过滤极端作弊者:按[级别、货币来源或汇、类型(赚取/支出)、付款人/非付款人、开始月份(如果游戏随时间变化,新人可能以不同于以前的方式赚取或消费)] I计算货币收入/支出金额的中位数和中位数绝对偏差 (MAD)。在以下情况下过滤用户:收入/支出金额 > 100 * 中位数 + 100 * MAD
  • 过滤花费超过他们所赚取的货币的用户。
  • 过滤通过应用内购买 (IAP) 赚取货币但在该级别没有产生任何实际货币收入的用户(即他们进行了 IAP 但没有为此付费)。