Comment simuler des données statistiquement significatives?

18

Je suis en 10e année et je cherche à simuler des données pour un projet de salon des sciences de l'apprentissage automatique. Le modèle final sera utilisé sur les données des patients et prédira la corrélation entre certains moments de la semaine et l'effet que cela a sur l'adhésion au médicament dans les données d'un seul patient. Les valeurs d'adhésion seront binaires (0 signifie qu'ils n'ont pas pris le médicament, 1 signifie qu'ils l'ont pris). Je cherche à créer un modèle d'apprentissage automatique capable d'apprendre de la relation entre l'heure de la semaine et j'ai divisé la semaine en 21 plages horaires, trois pour chaque heure de la journée (1 le lundi matin, 2 le lundi après-midi, etc.). Je cherche à simuler 1000 données de patients. Chaque patient disposera de 30 semaines de données. Je veux insérer certaines tendances associées à un moment de la semaine et à l'adhésion. Par exemple, dans un ensemble de données, je peux dire que l'intervalle de temps 7 de la semaine a une relation statistiquement significative avec l'observance. Pour que je puisse déterminer si la relation est statistiquement significative ou non, il me faudrait effectuer un test t à deux échantillons comparant un intervalle de temps à chacun des autres et m'assurer que la valeur de signification est inférieure à 0,05.

Cependant, plutôt que de simuler mes propres données et de vérifier si les tendances que j'ai insérées sont significatives ou non, je préférerais travailler en arrière et peut-être utiliser un programme auquel je pourrais demander d'attribuer à une certaine tranche de temps une tendance significative avec adhérence, et cela reviendrait des données binaires qui contiennent en elles la tendance que j'ai demandée, ainsi que des données binaires pour les autres intervalles de temps qui contiennent du bruit mais ne produisent pas de tendance statistiquement significative.

Y a-t-il un programme qui peut m'aider à réaliser quelque chose comme ça? Ou peut-être un module python?

Toute aide que ce soit (même des commentaires généraux sur mon projet) sera extrêmement appréciée !!

Neelasha Bhattacharjee
la source
4
c'est une excellente question. Et quelque chose comme ça est ce que la plupart des scientifiques devraient faire avant de demander une subvention, dans la phase de conception de l'étude. Je vois beaucoup trop souvent que les gens collectent d'abord leurs données et essaient de comprendre comment les analyser ensuite, avec pour résultat que le statisticien ne peut que dire de quoi est morte l'expérience, selon les mots de Ronald Fisher .
S.Kolassa - Rétablir Monica
@StephanKolassa Cependant, il est très difficile d'évaluer quelles données seront disponibles dans certaines expériences avec des données humaines, et dans d'autres contextes, on utilise des données disponibles et ne peut pas collecter plus ...
llrs
2
@llrs: C'est tout à fait correct. Et cela devrait bien sûr informer l'exercice de simulation. Mieux vaut penser à l' avance aux données disponibles, plutôt que de découvrir après l'expérience que des données cruciales ne peuvent pas être obtenues.
S.Kolassa - Rétablir Monica
(+1) Je trouve le vote pour clore cette question quelque peu répréhensible
Robert Long
@RobertLong, pourquoi dites-vous cela? Je pose la question simplement parce que je veux m'assurer de ne rien manquer dans la réponse qui la rende moins crédible.
Neelasha Bhattacharjee

Réponses:

14

Observations générales

  • "Je suis en 10e année et je cherche à simuler des données pour un projet de salon des sciences de l'apprentissage automatique." Impressionnant. Je ne me souciais pas du tout des mathématiques en 10e année; Je pense que j'ai pris quelque chose comme Algebra 2 cette année-là ...? Je ne peux pas attendre jusqu'à ce que vous me mettiez au chômage dans quelques années! Je donne quelques conseils ci-dessous, mais: qu'essayez-vous d'apprendre de cette simulation? Que connaissez-vous déjà en statistiques et en apprentissage automatique? Savoir cela m'aiderait (ainsi que d'autres) à rassembler une aide plus spécifique.

  • Python est un langage très utile, mais je suis d'avis que R est meilleur pour simuler des données. La plupart des livres / blogs / études / classes que j'ai rencontrés sur la simulation de données (aussi ce que les gens appellent "les méthodes de Monte Carlo" pour être fantaisistes) sont en R. Le langage R est connu comme étant "par les statisticiens, pour les statisticiens, "et la plupart des universitaires - qui s'appuient sur des études de simulation pour montrer que leurs méthodes fonctionnent - utilisent R. Beaucoup de fonctions intéressantes sont dans le langage R de base (c'est-à-dire, aucun package supplémentaire n'est nécessaire), comme rnormpour une distribution normale, runifpour l'uniforme distribution, rbetapour la distribution bêta, etc. Dans R, la saisie ?Distributionsvous montrera une page d'aide à leur sujet. Cependant, il existe de nombreux autres packages sympas comme mvtnormousimstudyqui sont utiles. Je recommanderais DataCamp.com pour apprendre R, si vous ne connaissez que Python; Je pense qu'ils sont bons pour s'initier doucement aux choses

  • Il semble que vous ayez beaucoup de choses à faire ici: vous voulez des données qui sont au fil du temps (longitudinal), au sein du sujet (peut-être en utilisant un modèle à plusieurs niveaux), et qui ont une composante saisonnière (peut-être un modèle de série chronologique), toutes prédisant un résultat dichotomique (quelque chose comme une régression logistique). Je pense que beaucoup de gens qui commencent par des études de simulation (y compris moi-même) veulent jeter un tas de choses à la fois, mais cela peut être vraiment intimidant et compliqué. Donc, ce que je recommanderais de faire, c'est de commencer par quelque chose de simple - peut-être de créer une fonction ou deux pour générer des données - puis de construire à partir de là.

Commentaires spécifiques

Il semble que votre hypothèse de base soit: "L'heure de la journée prédit si quelqu'un adhère ou non à la prise de ses médicaments." Et vous voudriez que deux créent deux ensembles de données simulés: un où il y a une relation et un où il n'y en a pas .

Vous mentionnez également la simulation de données pour représenter plusieurs observations d'une même personne. Cela signifie que chaque personne aurait sa propre probabilité d'adhésion ainsi que, peut-être, sa propre pente pour la relation entre l'heure de la journée et la probabilité d'adhésion. Je suggérerais d'étudier des modèles de régression "multiniveaux" ou "hiérarchiques" pour ce type de relation, mais je pense que vous pourriez commencer plus simplement que cela.

En outre, vous mentionnez une relation continue entre le temps et la probabilité d'adhérer au régime médicamenteux, ce qui me fait également penser que la modélisation de séries chronologiques - en particulier en regardant les tendances saisonnières - serait utile pour vous. Il est également possible de simuler, mais encore une fois, je pense que nous pouvons commencer plus simplement.

Disons que nous avons 1 000 personnes et nous mesurons si elles ont ou non pris leurs médicaments une seule fois. Nous savons également s'ils ont été chargés de le prendre le matin, l'après-midi ou le soir. Disons que prendre le médicament est 1, ne pas le prendre est 0. Nous pouvons simuler des données dichotomiques en utilisant rbinomdes tirages à partir d'une distribution binomiale. Nous pouvons définir chaque personne pour avoir 1 observation avec une probabilité donnée. Disons que les gens sont 80% susceptibles de le prendre le matin, 50% l'après-midi et 65% la nuit. Je colle le code ci-dessous, avec quelques commentaires après #:

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)

Ce résumé montre, en partie:

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

Le Interceptreprésente l'après-midi, et nous pouvons voir que le soir et le matin ont une probabilité d'adhésion significativement plus élevée. Il y a beaucoup de détails sur la régression logistique que je ne peux pas expliquer dans ce post, mais les tests t supposent que vous avez une variable dépendante conditionnellement distribuée normalement. Les modèles de régression logistique sont plus appropriés lorsque vous avez des résultats dichotomiques (0 contre 1) comme ceux-ci. La plupart des livres de statistiques d'introduction parleront du test t , et beaucoup de livres d'initiation à l'apprentissage automatique parleront de régression logistique. Je pense que l' introduction à l'apprentissage statistique: avec des applications en R est géniale, et les auteurs ont publié le tout en ligne:https://www-bcf.usc.edu/~gareth/ISL/ISLR%20First%20Printing.pdf

Je ne suis pas aussi sûr de bons livres pour les études de simulation; J'ai appris simplement en jouant, en lisant ce que les autres ont fait et en suivant un cours de troisième cycle, j'ai suivi l'informatique statistique (les documents du professeur sont ici: http://pj.freefaculty.org/guides/ ).

Enfin, vous pouvez également simuler sans effet en définissant toutes les heures pour avoir la même probabilité:

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))

Qui retourne:

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

Cela ne montre pas de différences significatives entre les époques, comme nous nous attendrions à ce que la probabilité soit la même à travers les époques.

Mark White
la source
Merci beaucoup pour la recommandation du livre! Juste ce dont j'avais besoin pour lire pendant les vacances!
MD-Tech
Merci beaucoup pour ça! Je savais que j'avais besoin d'un modèle de régression logistique pour l'aspect d'apprentissage automatique de mon projet, mais il semble également avoir une application pour simuler les données. Cependant, j'avais l'impression que la régression logistique nécessite que l'ordre des temps compte, mais dans ce cas, ce n'est pas le cas car chaque fois c'est une catégorie différente sans rapport avec l'autre. Je suis arrivé à cette conclusion après avoir discuté avec mon professeur de mathématiques, mais nous pourrions très bien nous tromper tous les deux. Pourriez-vous, s'il vous plaît, expliquer pourquoi une régression logistique exacte peut être utilisée ici?
Neelasha Bhattacharjee
@NeelashaBhattacharjee Simuler les données et ajuster le modèle de régression logistique sont deux étapes distinctes - nous aurions pu simuler les mêmes données et les analyser à l'aide d'un tableau de contingence et de statistiques khi deux si nous le voulions. Vous avez raison de dire que le modèle que j'adapte n'encode aucun ordre à l'époque. Cependant, les modèles de régression font des hypothèses sur la façon dont la variable dépendante est distribuée, pas les variables indépendantes. Nous aurions pu ordonner des prédicteurs, des prédicteurs continus, des prédicteurs de comptage, etc., et tous seraient parfaits pour la régression logistique.
Mark White
@NeelashaBhattacharjee La régression logistique peut être utilisée ici car nous modélisons une variable dépendante dichotomique, c'est-à-dire une avec deux et seulement deux résultats possibles. Ce que fait une régression logistique, c'est d'utiliser la «fonction de lien logistique» pour que toutes les valeurs prédites pour l'équation de régression (par exemple, b0 + b1 * x) soient comprises entre 0 et 1. Et nous appelons ces nombres la probabilité qu'une personne ait la valeur variable dépendante de 1.
Mark White
Merci beaucoup! Cependant, je me demandais comment vous pouviez regarder les valeurs de p entre les deux ensembles de données simulés et déterminer si l'un avait une tendance significative et l'autre. Pour moi, les deux ensembles ont des valeurs de p qui varient suffisamment pour être significatives.
Neelasha Bhattacharjee
4

Si vous connaissez déjà du Python, vous pourrez certainement obtenir ce dont vous avez besoin en utilisant Python de base avec numpyet / ou pandas. Comme Mark White le suggère cependant, beaucoup de choses liées à la simulation et aux statistiques sont intégrées dans R, donc ça vaut vraiment le coup d'œil.

Vous trouverez ci-dessous un cadre de base sur la façon dont vous pourriez aborder cela en utilisant une classe Python. Vous pouvez utiliser np.random.normalpour régler le baseline_adherencesujet de chaque sujet pour insérer du bruit. Cela vous donne une adhérence pseudo-aléatoire, à laquelle vous pouvez ajouter l'adhérence réduite ciblée certains jours.

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")
Andrew
la source
1

Ceci est un grand projet. Il existe un défi pour des projets comme celui-ci, et votre méthode d'utilisation des données simulées est un excellent moyen de les évaluer.

Avez-vous une hypothèse a priori, par exemple "les gens sont plus oublieux le soir"? Dans ce cas, un test statistique qui compare la fréquence de l'oubli le soir par rapport au matin le testera. Il s'agit d'une distribution de Bernoulli, comme l'ont dit les précédents intervenants.

L'autre approche consiste à parcourir vos données pour découvrir quel intervalle de temps présente le taux d'échec le plus élevé. Il y en a forcément un, donc la question est "est-ce juste un résultat fortuit?". Le seuil de signification est plus élevé dans ce cas. Si vous souhaitez en savoir plus à ce sujet, recherchez «taux de fausses découvertes».

Dans votre cas, le système est assez simple pour que vous puissiez calculer le seuil avec un peu de réflexion. Mais la méthode générale pourrait également être utilisée: simuler 1000 jeux de données sans variation de taux, puis trouver la distribution de fréquence des nombres faibles coïncidents. Comparez-y votre véritable ensemble de données. Si 13 h est le créneau clairsemé dans les données réelles, mais que les jeux de données simulés 50/1000 ont un créneau également clairsemé, le résultat n'est pas robuste.

chrishmorris
la source