如何模拟数据具有统计意义?

机器算法验证 机器学习 统计学意义 t检验 Python 模拟
2022-01-23 07:06:24

我在 10 年级,我正在寻找模拟机器学习科学博览会项目的数据。最终模型将用于患者数据,并将预测一周中某些时间之间的相关性以及这对单个患者数据中药物依从性的影响。依从性值将是二元的(0 表示他们没有服用药物,1 表示他们服用了)。我正在寻找一个机器学习模型,它能够从一周中的时间之间的关系中学习,并将一周分为 21 个时间段,一天中的每个时间段三个(1 是星期一早上,2 是星期一下午, ETC。)。我希望模拟 1,000 名患者的数据。每位患者将拥有 30 周的数据。我想插入与一周时间和依从性相关的某些趋势。例如,在一个数据集中,我可以说一周的第 7 个时间段与依从性有统计学上的显着关系。为了让我确定这种关系在统计上是否显着,需要我执行两个样本 t 检验,将一个时间段与其他时间段进行比较,并确保显着性值小于 0.05。

然而,与其模拟我自己的数据并检查我插入的趋势是否显着,我宁愿倒退,也许使用一个程序,我可以要求为某个时间段分配一个重要的趋势,并且它会返回包含我要求的趋势的二进制数据,以及包含一些噪声但不产生统计显着趋势的其他时隙的二进制数据。

有没有什么程序可以帮助我实现这样的目标?或者也许是一个python模块?

任何帮助(甚至是对我的项目的一般评论)都将不胜感激!

3个回答

普通的留言

  • “我在 10 年级,我正在寻找为机器学习科学博览会项目模拟数据。” 惊人的。我在 10 年级时根本不关心数学;我想我那年学了代数2之类的东西……?我等不及几年后你让我失业了!我在下面给出一些建议,但是:你想从这个模拟中学到什么?您在统计和机器学习方面已经熟悉什么?知道这一点将帮助我(和其他人)整理一些更具体的帮助。

  • Python 是一种非常有用的语言,但我认为 R 更适合模拟数据。我遇到的大多数关于模拟数据的书籍/博客/研究/课程(也就是人们所谓的“蒙特卡洛方法”)都是用 R 语言编写的。R 语言被称为“统计学家,统计学家, ” 并且大多数学者——依靠模拟研究来证明他们的方法有效——使用 R。许多很酷的函数都在基础 R 语言中(也就是说,不需要额外的包),例如rnorm正态分布,runif均匀分布分布,rbeta对于 beta 分布,等等。在 R 中,输入?Distributions会显示一个关于它们的帮助页面。但是,还有许多其他很酷的软件包,例如mvtnormsimstudy这是有用的。如果你只知道 Python,我会推荐 DataCamp.com 来学习 R;我认为它们很适合温和地介绍事物

  • 看起来你在这里做了很多事情:你想要随着时间的推移(纵向)、主题内(可能使用多级模型)的数据,并且它们具有季节性成分(可能是时间序列模型),所有预测二分法结果(类似于逻辑回归)。我认为很多从模拟研究开始的人(包括我自己)都想一次性投入一大堆东西,但这确实令人生畏和复杂。所以我建议做的是从一些简单的事情开始——也许制作一两个函数来生成数据——然后从那里开始构建。

具体意见

看起来您的基本假设是:“一天中的时间可以预测某人是否坚持服药。” 您希望两个创建两个模拟数据集:一个有关系,一个没有关系。

您还提到模拟数据以表示来自同一个人的多个观察结果。这意味着每个人都有自己的依从概率,也许还有他们自己的斜率,用于一天中的时间和遵守概率之间的关系。我建议研究这种类型的关系的“多级”或“分层”回归模型,但我认为你可以开始比这更简单。

此外,您提到时间和坚持服药方案的概率之间的连续关系,这也让我认为时间序列建模(特别是查看季节性趋势)会对您有所帮助。这也是可模拟的,但我认为我们可以从更简单的开始。

假设我们有 1000 人,我们测量他们是否只吃过一次药。我们还知道他们是否被分配在早上、下午或晚上进行。假设服用药物为 1,不服用药物为 0。我们可以使用rbinom从二项分布中抽取数据来模拟二分数据。我们可以设置每个人以给定的概率进行 1 次观察。假设人们早上服用的可能性为 80%,下午服用的可能性为 50%,晚上服用的可能性为 65%。我粘贴下面的代码,后面有一些评论#

set.seed(1839) # this makes sure the results are replicable when you do it
n <- 1000 # sample size is 1000
times <- c("morning", "afternoon", "evening") # create a vector of times
time <- sample(times, n, TRUE) # create our time variable

# make adherence probabilities based on time
adhere_prob <- ifelse(
  time == "morning", .80, 
  ifelse(
    time == "afternoon", .50, .65
  )
)

# simulate observations from binomial distribution with those probabilities
adhere <- rbinom(n, 1, adhere_prob)

# run a logistic regression, predicting adherence from time
model <- glm(adhere ~ time, family = binomial)
summary(model)

该摘要部分显示:

Coefficients:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept)  0.02882    0.10738   0.268  0.78839    
timeevening  0.45350    0.15779   2.874  0.00405 ** 
timemorning  1.39891    0.17494   7.996 1.28e-15 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

代表下午,Intercept我们可以看到晚上和早上的坚持概率明显更高。关于逻辑回归的很多细节我无法在这篇文章中解释,但t -tests 假设您有一个条件正态分布的因变量。当您有这样的二分法(0 对 1)结果时,逻辑回归模型更合适。大多数介绍性统计书籍都会讨论t检验,许多介绍性机器学习书籍会讨论逻辑回归。我认为《统计学习简介:R中的应用程序》很棒,作者将整个内容发布在网上:https://www-bcf.usc.edu/~gareth/ISL/ISLR%20First%20Printing.pdf

我不太确定用于模拟研究的好书;我只是从捣乱、阅读其他人所做的以及从我学习统计计算的研究生课程中学到的(教授的资料在这里: http: //pj.freefaculty.org/guides/)。

最后,您还可以通过将所有时间设置为具有相同概率来模拟没有效果:

set.seed(1839)
n <- 1000
times <- c("morning", "afternoon", "evening")
time <- sample(times, n, TRUE)
adhere <- rbinom(n, 1, .6) # same for all times
summary(glm(adhere ~ time, binomial))

返回:

Coefficients:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept)  0.40306    0.10955   3.679 0.000234 ***
timeevening -0.06551    0.15806  -0.414 0.678535    
timemorning  0.18472    0.15800   1.169 0.242360    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

这表明时间之间没有显着差异,正如我们所期望的那样,不同时间的概率是相同的。

如果您已经了解一些 Python,那么您肯定能够使用基础 Python 以及numpy和/或pandas. 正如 Mark White 所建议的那样,许多模拟和统计相关的东西都融入了 R,所以绝对值得一看。

下面是一个基本框架,说明如何使用 Python 类来解决这个问题。您可以使用np.random.normal调整baseline_adherence每个主题的 以插入一些噪音。这为您提供了伪随机依从性,您可以在特定日期添加有针对性的降低依从性。

import pandas as pd
import numpy as np

from itertools import product

class Patient:

    def __init__(self, number, baseline_adherence=0.95):
        self.number = number
        self.baseline_adherence = baseline_adherence
        self.schedule = self.create_schedule()

    def __repr__(self):
        return "I am patient number {}".format(self.number)

    def create_schedule(self):

        time_slots = []
        for (day, time) in product(range(1, 8), range(1, 4)):
            time_slots.append("Day {}; Slot {}".format(day, time))
        week_labels = ["Week {}".format(x) for x in range(1, 31)]
        df = pd.DataFrame(np.random.choice([0, 1],
                                           size=(30, 21),#1 row per week, 1 column per time slot
                                           p=(1-self.baseline_adherence, self.baseline_adherence)),
                          index=week_labels,
                          columns=time_slots
                         )
        return df

    def targeted_adherence(self, timeslot, adherence=0.8):

        if timeslot in self.schedule.columns:
            ad = np.random.choice([0, 1],
                                  size=self.schedule[timeslot].shape,
                                  p=(1-adherence, adherence)
                                 )
            self.schedule[timeslot] = ad


sim_patients = [Patient(x) for x in range(10)]
p = sim_patients[0]
p.targeted_adherence("Day 1; Slot 3")

这是一个伟大的项目。像这样的项目存在挑战,而您使用模拟数据的方法是评估它的好方法。

您是否有先验假设,例如“人们在晚上更健忘”?在这种情况下,比较晚上和早上的遗忘频率的统计测试将对其进行测试。正如之前的响应者所说,这是一个伯努利分布。

另一种方法是搜索数据以找出哪个时间段的故障率最高。肯定会有一个,所以问题是“这只是一个偶然的结果吗?”。在这种情况下,显着性阈值更高。如果您想了解此内容,请搜索“错误发现率”。

在您的情况下,系统非常简单,您可以稍微考虑一下来计算阈值。但也可以使用通用方法:模拟 1000 个没有速率变化的数据集,然后找出巧合低数的频率分布。将您的真实数据集与它进行比较。如果 1pm 是真实数据中的稀疏槽,但 50/1000 模拟数据集具有同样稀疏的槽,则结果不稳健。