Trumania如何生成随机数据集?探索 Python Trumania,一个基于场景的随机数据集生成器库。在此分步教程中了解如何生成合成和随机数据集。
本教程简要介绍了为什么要生成随机数据集以及对它们的期望。它还将引导你了解如何使用Trumania(一个数据生成 Python 库)的一些初步示例。
如何生成真实的随机数据集?更多信息,你可以访问Trumania 的 GitHub!下面是Trumania生成真实的随机数据集的详细介绍:
为什么要生成随机数据集?
生成随机数据集与数据工程师和数据科学家都相关。为什么数据科学家和数据工程师要使用合成数据,他们又是如何获得这些数据的?
作为一名数据工程师,在你编写了新的出色数据处理应用程序后,你认为是时候开始端到端测试了,因此你需要一些输入数据。
作为数据科学家,你可以从数据生成中受益,因为它允许你尝试各种探索数据集、算法、数据可视化技术的方法,或者针对你选择的许多不同数据集验证有关某些方法行为的假设。
在这两种情况下,一个诱人的选择就是使用真实数据。不过,一个小问题是,生产数据通常很难获得,甚至是部分获得,而且欧洲关于隐私和安全的新法律并没有变得更容易。
也许你是幸运的人之一,你的笔记本电脑上有一个很好的完整的生产数据集。即便如此,你还是希望数据集中有更多的可变性来针对各种情况进行验证,例如不同的人口规模、不同的数据分布、各种数据质量问题,例如丢失或无效的数据......
要更广泛地了解为什么生成随机数据集很有用,请前往“为什么合成数据即将成为主要竞争优势”。
基于模式的随机数据生成:我们需要良好的关系!
本节试图说明基于模式的随机数据生成并展示其缺点。
许多工具已经存在来生成随机数据集。这些工具中的一种常见方法是基于模式的生成,它允许你定义蓝图并使用它来生成一些实体。Khermes和LogSynth是此类工具的两个示例。
基于模式的配置的一个例子可能包括这个人模式:
{
{
"field": "Name",
"class": NameGenerator
},
{
"field": "Age",
"class": RandomInt(18, 65)
},
{
"field": "Gender",
"class": RandomPicker(["Male", "Female", "Other"])
}
}
这个模式定义了关于一个人的一些数据的生成。它包含姓名、年龄和性别。它很简单,速度很快,但有一些限制。一个主要限制是伪造不同实体之间或基于时间的关系。
例如,如何根据性别使一些名字更有可能?或者如何创建用户操作日志,哪些操作更有可能在周末发生?
基于模式的方法不容易将你的新应用程序暴露给现实世界的特殊性或困难,例如:
- 不平衡的数据集(分组操作的困难);
- 实体网络中的集群模式。即通过用户交互(例如电话)发现社交群体;
- 各种时间活动配置文件。行动更有可能发生在一天或一周的某个时间;
- 动作之间的因果关系。也就是说,商店的许多购买行为最终会触发“缺货”事件。
Trumania 基于场景,以解决这些缺点并生成更真实的数据集。随着场景的展开,各种种群相互交互,更新它们的属性并发出日志。
场景的一个例子是人们打电话给他们的朋友。当一个人打电话时,他们需要在几分钟内付款,当时间用完时,他们必须去商店......由此产生的数据集可能是用户通话记录、购物行为记录和每小时的库存水平。场景中的动作可以是随机的,也可以是确定性的。
在 Trumania 中,生成的数据集通常是时间序列,因为它们是执行随时间展开的场景的结果。
使用 Trumania 生成相互关联的数据(又名教程时间!)
在下面的示例中,你将看到如何详细说明各种人相互发送消息的基本场景。生成的数据集将是人与人之间交换消息的时间序列。
我们将执行的步骤顺序如下:
- 创建一个 Trumania马戏团,这是场景将在其中执行的世界
- 添加一个“hello world”故事,将生成基本的硬编码日志
- 添加一个关系来为每个人分配一些最喜欢的报价,这将用于创建消息的内容。
- 参数化故事的时间参数以获得更真实的全天信息分布
- 添加另一个关系来定义社交网络,使消息日志中出现的社交图更加真实
创建一个 Trumania 马戏团
目的
第一步是创建一个circus,这是一个场景中所有元素都将存在的世界。我们还将创建persons
. 由于 Trumania 的很多方面都是随机的,所以这一步也会引入 的概念generators
,用来控制很多随机行为。
此时我们不会添加任何场景,因此一切都将是静态的。
让我们开始吧!
如何
Trumania circus的简单创建如下:
from trumania.core import circus
example_circus = circus.Circus(name="example1",
master_seed=12345,
start=pd.Timestamp("1 Jan 2017 00:00"),
step_duration=pd.Timedelta("1h"))
如何生成真实的随机数据集?在 Trumania,所有与时间相关的元素都由中央时钟控制。上面代码片段中最重要的部分是step_duration=pd.Timedelta("1h")
,它定义了时钟将以 1 小时为单位递增。
接下来,你将person
人口添加到马戏团。群体本质上是一组具有一个id
和一些属性的代理。
可以手动指定每个属性的值,但在大多数情况下,你希望随机生成它们,因此让我们首先generators
为此定义一些:
from trumania.core.random_generators import SequencialGenerator, FakerGenerator, NumpyRandomGenerator
id_gen = SequencialGenerator(prefix="PERSON_")
age_gen = NumpyRandomGenerator(method="normal", loc=3, scale=5,
seed=next(example_circus.seeder))
name_gen = FakerGenerator(method="name", seed=next(example_circus.seeder))
Trumania如何生成随机数据集?Trumania 生成器负责在generate()
调用其方法时提供数据。在上面的示例中,id_gen
将生成像PERSON_0001
, PERSON_0002
, ... 这样的字符串,age_gen
将从正态分布中重复采样数据,并name_gen
提供随机人名。
请注意,任何来自numpy
以及任何Faker 提供商的统计分布都可以在 Trumania 中使用,并且 Trumania 可以轻松地扩展新的。
有了这个,你可以添加 1000 人的人口,这些人具有连续的 ID 和两个基本随机属性:
person = example_circus.create_population(name="person", size=1000, ids_gen=id_gen)
person.create_attribute("NAME", init_gen=name_gen)
person.create_attribute("AGE", init_gen=age_gen)
结果
你已经可以person
通过调用查看人口中所有成员的生成属性person.to_dataframe()
。
+-------------------+-----------------+---------+
| | NAME | age |
|-------------------+-----------------+---------|
| PERSON_0000000000 | Amy Berger | 28.588 |
| PERSON_0000000001 | Michael Curry | 28.7499 |
| PERSON_0000000002 | Robert Ramirez | 35.9242 |
| PERSON_0000000003 | Derek Gonzalez | 34.7091 |
| PERSON_0000000004 | Gregory Fischer | 25.6009 |
| PERSON_0000000005 | Erica Walker | 33.9758 |
| PERSON_0000000006 | Bradley Collins | 24.4428 |
| PERSON_0000000007 | James Rodriguez | 34.7835 |
| PERSON_0000000008 | Brandy Padilla | 34.6296 |
| PERSON_0000000009 | Mark Taylor | 38.2286 |
+-------------------+-----------------+---------+
提示:如果你想查看此基本用户群的整个脚本,请查看Github 上的此代码段!
Hello World 语句:创建故事
目的
让我们通过添加一个story
. Trumania 故事本质上是一个包含一些动态方面的场景。模拟时钟每前进一步,就会执行一个故事。
回想一下你step_duration=pd.Timedelta("1h")
在上面的马戏团中设置的场景,所以这意味着每个合乎逻辑的时间,每个故事都有机会被执行。
你将创建一个简单的 hello-world 故事,其中上述person
人口的所有成员将定期发出消息“hello world”。
如何
创建 a 时要指定的第一个主要方面story
是启动故事的人口。在这种情况下,这将是person
. 第二个方面是定义timer
,它定义了群体的每个成员何时触发该操作。现在,你只是将它们硬编码为 1,这意味着所有成员将在每个时钟步骤执行故事(你将在稍后的步骤中构建更精细的计时器):
hello_world = example_circus.create_story(
name="hello_world",
initiating_population=example_circus.populations["person"],
member_id_field="PERSON_ID",
timer_gen=ConstantDependentGenerator(value=1)
)
到目前为止,故事是空的,所以它没有做任何事情:你需要向其中添加一些操作。操作可以是随机的或确定性的,它们可以读取和更新任何群体的属性或马戏团中的其他状态,甚至会产生副作用。
现在,让我们添加两个简单的确定性操作和一个记录器来实际获取一些日志:
hello_world.set_operations(
example_circus.clock.ops.timestamp(named_as="TIME"),
ConstantGenerator(value="hello world").ops.generate(named_as="MESSAGE"),
FieldLogger(log_id="hello")
)
在example_circus.clock.ops.timestamp
正在产生1小时的当前时间间隔内的随机时间戳和ConstantGenerator
刚刚产生恒定硬编码值。
Trumania生成真实的随机数据集:结果
让我们在 48 小时的模拟时间内运行马戏团:
example_circus.run(
duration=pd.Timedelta("48h"),
log_output_folder="example_scenario",
delete_existing_logs=True
)
这应该会产生以下基本数据集,其中 1000 人中的每一个人在 2 天内说“hello world”48 次。
结果数据集的第一个字段PERSON_ID
对应于member_id_field
的story
。另外两个字段TIME
和MESSAGE
对应于你放入故事中的两个主要操作。
+-------+-------------------+---------------------+-------------+
| | PERSON_ID | TIME | MESSAGE |
|-------+-------------------+---------------------+-------------|
| 0 | PERSON_0000000000 | 2017-01-01 01:14:12 | hello world |
| 1 | PERSON_0000000001 | 2017-01-01 01:23:51 | hello world |
| 2 | PERSON_0000000002 | 2017-01-01 01:37:11 | hello world |
| 3 | PERSON_0000000003 | 2017-01-01 01:33:12 | hello world |
| 4 | PERSON_0000000004 | 2017-01-01 01:08:02 | hello world |
| 5 | PERSON_0000000005 | 2017-01-01 01:13:36 | hello world |
| 6 | PERSON_0000000006 | 2017-01-01 01:35:08 | hello world |
| 7 | PERSON_0000000007 | 2017-01-01 01:24:30 | hello world |
| 8 | PERSON_0000000008 | 2017-01-01 01:01:51 | hello world |
| 9 | PERSON_0000000009 | 2017-01-01 01:41:41 | hello world |
| ... |
| 23990 | PERSON_0000000990 | 2017-01-02 23:33:28 | hello world |
| 23991 | PERSON_0000000991 | 2017-01-02 23:15:26 | hello world |
| 23992 | PERSON_0000000992 | 2017-01-02 23:45:56 | hello world |
| 23993 | PERSON_0000000993 | 2017-01-02 23:25:16 | hello world |
| 23994 | PERSON_0000000994 | 2017-01-02 23:33:55 | hello world |
| 23995 | PERSON_0000000995 | 2017-01-02 23:41:45 | hello world |
| 23996 | PERSON_0000000996 | 2017-01-02 23:39:23 | hello world |
| 23997 | PERSON_0000000997 | 2017-01-02 23:45:53 | hello world |
| 23998 | PERSON_0000000998 | 2017-01-02 23:29:25 | hello world |
| 23999 | PERSON_0000000999 | 2017-01-02 23:12:24 | hello world |
+-------+-------------------+---------------------+-------------+
提示:在Github上查看整个片段
向某人说 Hello World
目的
让我们通过在对话中添加另一个随机人来稍微改进一下。现在,你要说任何人都可以以相等的概率与任何其他人交谈,这不太现实(你将在稍后的步骤中添加社交网络)。此外,你将通过添加基于 ID 的人名来丰富数据集。
如何
假设另一个人将被存储在一个新OTHER_PERSON
字段中。在这种简单的情况下,你只想在该字段中放入从person
总体中随机未加权选择的结果。你可以简单地使用该select_one
人口的随机操作:
example_circus.set_operations(
example_circus.clock.ops.timestamp(named_as="TIME"),
ConstantGenerator(value="hello world").ops.generate(named_as="MESSAGE"),
example_circus.populations["person"].ops.select_one(named_as="OTHER_PERSON"),
example_circus.populations["person"]
.ops.lookup(id_field="PERSON_ID", select={"NAME": "EMITTER_NAME"}),
example_circus.populations["person"]
.ops.lookup(id_field="OTHER_PERSON", select={"NAME": "RECEIVER_NAME"}),
FieldLogger(log_id="hello")
)
结果
当你再次运行马戏团时,你最终会得到一个包含新OTHER_PERSON
字段的数据集:
+-------+-------------------+---------------------+-------------+-------------------+---------------------+--------------------+
| | PERSON_ID | TIME | MESSAGE | OTHER_PERSON | EMITTER_NAME | RECEIVER_NAME |
|-------+-------------------+---------------------+-------------+-------------------+---------------------+--------------------|
| 0 | PERSON_0000000000 | 2017-01-01 01:14:12 | hello world | PERSON_0000000852 | Ann Cruz | Sophia Black |
| 1 | PERSON_0000000001 | 2017-01-01 01:23:51 | hello world | PERSON_0000000429 | Kimberly Sanchez | Jeffrey Ryan |
| 2 | PERSON_0000000002 | 2017-01-01 01:37:11 | hello world | PERSON_0000000925 | Bethany Smith | Regina Brown |
| 3 | PERSON_0000000003 | 2017-01-01 01:33:12 | hello world | PERSON_0000000347 | Frank Middleton | Jacob Ross |
| 4 | PERSON_0000000004 | 2017-01-01 01:08:02 | hello world | PERSON_0000000211 | Cheryl Decker | Joshua Miller |
| 5 | PERSON_0000000005 | 2017-01-01 01:13:36 | hello world | PERSON_0000000779 | Thomas Rodriguez | Nicole Tanner |
| 6 | PERSON_0000000006 | 2017-01-01 01:35:08 | hello world | PERSON_0000000331 | James Peters | Melissa Rogers |
| 7 | PERSON_0000000007 | 2017-01-01 01:24:30 | hello world | PERSON_0000000234 | Allison Hansen | Taylor Smith |
| 8 | PERSON_0000000008 | 2017-01-01 01:01:51 | hello world | PERSON_0000000678 | Candice Sellers | James Smith |
| 9 | PERSON_0000000009 | 2017-01-01 01:41:41 | hello world | PERSON_0000000108 | Maria White | James Nguyen |
| ... |
| 23990 | PERSON_0000000990 | 2017-01-02 23:33:28 | hello world | PERSON_0000000689 | Natasha Brown | Bailey Ramirez DDS |
| 23991 | PERSON_0000000991 | 2017-01-02 23:15:26 | hello world | PERSON_0000000250 | Shelly Ponce | Jordan Johnson |
| 23992 | PERSON_0000000992 | 2017-01-02 23:45:56 | hello world | PERSON_0000000413 | Steven Mendez | Crystal Duffy |
| 23993 | PERSON_0000000993 | 2017-01-02 23:25:16 | hello world | PERSON_0000000670 | Morgan Rice | Jonathan Obrien |
| 23994 | PERSON_0000000994 | 2017-01-02 23:33:55 | hello world | PERSON_0000000411 | Crystal Vincent | George Mathis |
| 23995 | PERSON_0000000995 | 2017-01-02 23:41:45 | hello world | PERSON_0000000563 | Dawn Kim | Jennifer Martinez |
| 23996 | PERSON_0000000996 | 2017-01-02 23:39:23 | hello world | PERSON_0000000668 | Jimmy Franco | Dr. Mark Ruiz MD |
| 23997 | PERSON_0000000997 | 2017-01-02 23:45:53 | hello world | PERSON_0000000268 | Christian Christian | Victoria Donovan |
| 23998 | PERSON_0000000998 | 2017-01-02 23:29:25 | hello world | PERSON_0000000829 | David Hernandez | Margaret Anderson |
| 23999 | PERSON_0000000999 | 2017-01-02 23:12:24 | hello world | PERSON_0000000944 | Tamara Ramirez | Andrew Curtis |
+-------+-------------------+---------------------+-------------+-------------------+---------------------+--------------------+
提示:你可以在此处查看整个代码
你总是这样说
目的
如何使用Trumania?让我们通过在MESSAGE
现场生成随机句子而不是无聊的hello world
硬编码字符串来进一步改进。这将允许你说明 Trumania 的第一个基本用法Relationship
。
你将每个人与 4 个引号相关联。任何时候一个人发出一条消息,内容都会从该人的 4 个引语中挑选出来。此外,你要将每个引用与weight
定义该引用的可能性的不同相关联:与权重低的引用相比,权重高的引用由其所有者发出的频率更高。
现在你如何开始?
如何
如何生成真实的随机数据集?第一步是创建一个报价生成器,它类似于Faker
你在上面看到的其他生成器:
quote_generator = FakerGenerator(method="sentence", nb_words=6, variable_nb_words=True,
seed=next(example_circus.seeder))
你可以story
像以前一样使用该生成器,但让我们通过限制每个人始终使用他们最喜欢的 4 个引语之一来使事情变得更有趣。你可以通过Relationship
在person
总体成员和一些句子值之间创建 a来做到这一点。
首先,你创建一个空关系:
quotes_rel = example_circus.populations["person"].create_relationship("quotes")
然后,你为每个人使用 4 个引号填充此关系。在下面的代码中,person.ids
是一个Series
大小为 1000的大熊猫,包含person
人口的所有 id ,并quote_generator.generate(size=person.size)
提供另一个Series
大小为 1000 的大熊猫,并带有随机引号。
这意味着下面的 for 循环的每次传递都会填充关系中的 1000 个关系:为 1000 个用户中的每个用户添加一个引用。前 1000 个报价将与 weight=1 相关联,下一个将通过将它们与 weight=2 相关联而变得更频繁,...
for w in range(4):
quotes_rel.add_relations(
from_ids=person.ids,
to_ids=quote_generator.generate(size=person.size),
weights=w
)
你现在可以ConstantGenerator
使用select_one
对该关系的操作替换你的故事中的。其内容如下:对于当前字段中的每个值PERSON_ID
,查找quotes
从该 ID 开始的关系并随机选择一个相关值。由于在下面的操作中没有覆盖权重,add_relations
因此使用上面定义的默认关系权重:
example_circus.set_operations(
example_circus.clock.ops.timestamp(named_as="TIME"),
example_circus.populations["person"].get_relationship("quotes")
.ops.select_one(from_field="PERSON_ID", named_as="MESSAGE"),
example_circus.populations["person"].ops.select_one(named_as="OTHER_PERSON"),
example_circus.populations["person"]
.ops.lookup(id_field="PERSON_ID", select={"NAME": "EMITTER_NAME"}),
example_circus.populations["person"]
.ops.lookup(id_field="OTHER_PERSON", select={"NAME": "RECEIVER_NAME"}),
FieldLogger(log_id="hello")
)
结果
当你运行马戏团时,该MESSAGE
字段现在应包含随机引用:
+-------+-------------------+---------------------+-----------------------------------------------------+-------------------+---------------------+---------------------+
| | PERSON_ID | TIME | MESSAGE | OTHER_PERSON | EMITTER_NAME | RECEIVER_NAME |
|-------+-------------------+---------------------+-----------------------------------------------------+-------------------+---------------------+---------------------|
| 0 | PERSON_0000000000 | 2017-01-01 01:14:12 | Become period risk wait now toward less. | PERSON_0000000158 | Ann Cruz | Victoria Washington |
| 1 | PERSON_0000000001 | 2017-01-01 01:23:51 | Month push down. | PERSON_0000000366 | Kimberly Sanchez | Steven Williams |
| 2 | PERSON_0000000002 | 2017-01-01 01:37:11 | Blue general carry else deep problem area. | PERSON_0000000613 | Bethany Smith | Frances Davis |
| 3 | PERSON_0000000003 | 2017-01-01 01:33:12 | Phone sister pretty suddenly allow conference. | PERSON_0000000086 | Frank Middleton | Ashley Fernandez |
| 4 | PERSON_0000000004 | 2017-01-01 01:08:02 | Each discussion several send wide process. | PERSON_0000000972 | Cheryl Decker | Latoya Flynn |
| 5 | PERSON_0000000005 | 2017-01-01 01:13:36 | Guess can issue writer. | PERSON_0000000030 | Thomas Rodriguez | Lindsay Bailey |
| 6 | PERSON_0000000006 | 2017-01-01 01:35:08 | Boy step claim camera common but our. | PERSON_0000000548 | James Peters | Thomas Ward |
| ... | 23993 | PERSON_0000000993 | 2017-01-02 23:25:16 | May course and kill from news. | PERSON_0000000202 | Morgan Rice | Patricia Williams |
| 23994 | PERSON_0000000994 | 2017-01-02 23:33:55 | Water door live hospital together safe. | PERSON_0000000268 | Crystal Vincent | Victoria Donovan |
| 23995 | PERSON_0000000995 | 2017-01-02 23:41:45 | Stage control management read although thousand. | PERSON_0000000466 | Dawn Kim | Ashley Baxter |
| 23996 | PERSON_0000000996 | 2017-01-02 23:39:23 | Their that region majority break article. | PERSON_0000000620 | Jimmy Franco | Alex Dominguez |
| 23997 | PERSON_0000000997 | 2017-01-02 23:45:53 | Lead simple audience response eye. | PERSON_0000000319 | Christian Christian | David Smith |
| 23998 | PERSON_0000000998 | 2017-01-02 23:29:25 | Vote man son yeah child. | PERSON_0000000487 | David Hernandez | Joshua Park |
| 23999 | PERSON_0000000999 | 2017-01-02 23:12:24 | Answer region wind condition someone bed cover. | PERSON_0000000237 | Tamara Ramirez | Beverly Rodriguez |
+-------+-------------------+---------------------+-----------------------------------------------------+-------------------+---------------------+---------------------+
用于引号的关系的要点在于,现在生成的数据集的字段是相关的:某些用户更频繁地使用某些句子。
提示:在 Github 上查看整个代码片段
这不是你做什么,而是你做的时间
目的
到目前为止,person
人口中的每个成员每天每小时都在产生一条消息。让我们让它更现实一点。
Trumania 使用两个概念的组合来控制故事执行的时间方面:活动级别和计时器配置文件。它们共同确定触发story
给定特定用户和一天中的时间的概率。
如何
你将更新story
和参数化这两个方面。
首先,让我们创建故事的计时器配置文件,它控制触发或多或少动作的时刻。此配置文件对于触发故事的所有成员都是相同的。
Trumania 内置了一些有趣的默认值,例如DefaultDailyTimerGenerator
,对应于我们在实际生产数据集上测量的日常电话使用情况:
让我们在你的场景中实例化一个:
from trumania.components.time_patterns.profilers import DefaultDailyTimerGenerator
story_timer_gen = DefaultDailyTimerGenerator(
clock=example_circus.clock,
seed=next(example_circus.seeder))
其次,有该故事的总体成员活动级别,它定义了该故事中每个用户的活跃程度。你可以自由地为每个成员设置不同的级别,以便某些成员比其他成员更频繁地或更少地触发该操作。
如果你愿意,你可以手动指定每个级别,但在这里你将只使用一个随机生成器,它将为每个人口成员分配一个活动级别。
首先,我们定义了平均每天 3、10 和 20 个触发器的三个活动级别:
low_activity = story_timer_gen.activity(n=3, per=pd.Timedelta("1 day"))
med_activity = story_timer_gen.activity(n=10, per=pd.Timedelta("1 day"))
high_activity = story_timer_gen.activity(n=20, per=pd.Timedelta("1 day"))
然后,你可以创建实际的活动生成器,这将是另一个Numpy
生成器,这次基于该choice
方法。下面的一个将低活动分配给 20% 的人口,中等活动分配给 70%,高活动分配给 10%:
activity_gen = NumpyRandomGenerator(
method="choice",
a=[low_activity, med_activity, high_activity],
p=[.2, .7, .1],
seed=next(example_circus.seeder))
你现在可以使用此计时器配置文件和活动生成器作为你故事的一部分:
hello_world = example_circus.create_story(
name="hello_world",
initiating_population=example_circus.populations["person"],
member_id_field="PERSON_ID",
timer_gen=story_timer_gen,
activity_gen=activity_gen
)
结果
Trumania如何生成随机数据集?生成的数据集具有与以前相同的架构:
+-------+-------------------+---------------------+---------------------------------------------------------+-------------------+---------------------+----------------------+
| | PERSON_ID | TIME | MESSAGE | OTHER_PERSON | EMITTER_NAME | RECEIVER_NAME |
|-------+-------------------+---------------------+---------------------------------------------------------+-------------------+---------------------+----------------------|
| 0 | PERSON_0000000016 | 2017-01-01 00:14:12 | Still try sex sure. | PERSON_0000000739 | Johnny Moore | Adam Barrett |
| 1 | PERSON_0000000063 | 2017-01-01 00:23:51 | Resource magazine wide. | PERSON_0000000511 | Cody Pham | Tina Simmons |
| 2 | PERSON_0000000064 | 2017-01-01 00:37:11 | Heat sure simple letter better forget. | PERSON_0000000044 | Katherine Fleming | Angela Gray |
| 3 | PERSON_0000000076 | 2017-01-01 00:33:12 | Star our conference always place ball. | PERSON_0000000959 | Benjamin Reese II | Barbara Alexander |
| 4 | PERSON_0000000088 | 2017-01-01 00:08:02 | Hot event five left become time commercial. | PERSON_0000000000 | Zachary Cook | Ann Cruz |
| ... |
| 28556 | PERSON_0000000962 | 2017-01-04 00:07:45 | Then include rock rule scientist condition. | PERSON_0000000448 | Johnny Washington | Melissa Adams |
| 28557 | PERSON_0000000980 | 2017-01-04 00:04:44 | Collection full argue interview property pattern never. | PERSON_0000000731 | James Ramirez | David Morrow |
| 28558 | PERSON_0000000983 | 2017-01-04 00:23:21 | High day prepare see. | PERSON_0000000509 | Evan Horne | Robert Sims |
| 28559 | PERSON_0000000988 | 2017-01-04 00:43:56 | Likely south school result case federal seat. | PERSON_0000000819 | Benjamin Campbell | Michelle Jackson DDS |
+-------+-------------------+---------------------+---------------------------------------------------------+-------------------+---------------------+----------------------+
Trumania生成真实的随机数据集:结果分析
你包含在场景配置中的时间模式现在应该在结果数据集的内部结构中可见。你可以通过对结果进行基本数据分析来证明这一点resulting_dataset
:
- 一天中每小时的消息数量应遵循指定的分布(注意它与
DefaultDailyTimerGenerator
上面的曲线有多相似):
time_profile = (
resulting_dataset[["MESSAGE", "TIME"]]
.groupby(by=example_5_df.TIME.dt.hour)["MESSAGE"]
.count()
)
time_profile.plot()
- 每个用户的消息数量直方图也应尊重你的配置:
- 你
low_activity
平均每天配置3 条消息,分别配置为med_activity
10 条和high_activity
20 条,并在 5 天内运行模拟。这应该产生 3 组person
大约 15、50 和 100 条消息,对应于下面直方图的 3 个中心 - 你将这些活动级别的概率配置为 0.2、0.7 和 0.1,这又大致对应于直方图每个“凸点”的相应区域:
- 你
usage_per_user = resulting_dataset[["MESSAGE", "PERSON_ID"]].groupby("PERSON_ID")["MESSAGE"].count()
usage_per_user.plot(kind="hist")
社交网络
目的
你可以通过连接人们来进一步改进场景,以便他们在你的故事执行期间向朋友发送消息,而不是随机发送给某个人。这将为结果数据集引入很多结构,因为现在应该可以从消息日志中发现社交图。
如何
你可以Relationship
再次使用 a 对社交网络进行建模,这与你在上面用于对报价进行建模的概念相同。你可能还记得,这种quotes
关系是有分量的。给定一个人,这个权重定义了哪个引用或多或少的可能性。你可以在这里做同样的事情,并使用权重来定义哪些朋友比其他人更有可能被称为。
如何使用Trumania?请注意,这里定义的是从person
到的关系person
,尽管通常 Trumania 允许你定义任何一对总体之间的关系。
有很多方法可以生成社交图的边缘。一种基本的经典算法就是简单地依赖鄂尔多斯-仁义算法。这在 Trumania 中特别容易,因为它已经内置在框架中。你只需要将它注入到你的场景中即可创建关系。
在这里,你将定义person
关系成员之间的社交图,其中每个人都有 20 个朋友。请注意,权重将自动添加到与帕累托分布的关系中。
from trumania.components.social_networks.erdos_renyi import WithErdosRenyi
# self is the circus here, see example code on github for details
self.add_er_social_network_relationship(
self.populations["person"],
relationship_name="friends",
average_degree=20)
有了这种关系,你可以再次重温我们的故事。这一次,OTHER_PERSON
将不再在人群中随机选取,而是在每个person
成员的朋友中选取,概率与社交网络中定义的权重成正比:
hello_world.set_operations(
self.clock.ops.timestamp(named_as="TIME"),
self.populations["person"].get_relationship("quotes")
.ops.select_one(from_field="PERSON_ID",named_as="MESSAGE"),
self.populations["person"]
.get_relationship("friends")
.ops.select_one(from_field="PERSON_ID", named_as="OTHER_PERSON"),
self.populations["person"]
.ops.lookup(id_field="PERSON_ID", select={"NAME": "EMITTER_NAME"}),
self.populations["person"]
.ops.lookup(id_field="OTHER_PERSON", select={"NAME": "RECEIVER_NAME"}),
operations.FieldLogger(log_id="hello_6")
)
结果
再一次,生成的数据集具有与以前相同的数据模式,尽管这一次由于你的基本社交网络而具有比以前更多的结构:
+-------+-------------------+---------------------+----------------------------------------------------+-------------------+-------------------+------------------+
| | PERSON_ID | TIME | MESSAGE | OTHER_PERSON | EMITTER_NAME | RECEIVER_NAME |
|-------+-------------------+---------------------+----------------------------------------------------+-------------------+-------------------+------------------|
| 0 | PERSON_0000000004 | 2017-01-01 00:14:12 | Clearly see sure. | PERSON_0000000321 | Cheryl Decker | Ian White |
| 1 | PERSON_0000000012 | 2017-01-01 00:23:51 | Offer or interview clear structure watch capital. | PERSON_0000000697 | Kelly Green | Ashley Turner |
| 2 | PERSON_0000000018 | 2017-01-01 00:37:11 | Recently race draw thousand around ahead. | PERSON_0000000989 | Laura Stephenson | Hannah James |
| 3 | PERSON_0000000040 | 2017-01-01 00:33:12 | To protect man image power beyond. | PERSON_0000000418 | Jeffrey Miller | Scott Collins |
... |
| 28966 | PERSON_0000000985 | 2017-01-04 00:09:23 | However agreement fear door land hotel. | PERSON_0000000211 | Laura Mason | Joshua Miller |
| 28967 | PERSON_0000000995 | 2017-01-04 00:48:08 | Top heat window quite forward friend somebody. | PERSON_0000000171 | Dawn Kim | Sandra Phillips |
| 28968 | PERSON_0000000999 | 2017-01-04 00:58:46 | Answer region wind condition someone bed cover. | PERSON_0000000252 | Tamara Ramirez | Jordan Collins |
+-------+-------------------+---------------------+----------------------------------------------------+-------------------+-------------------+------------------+
如何生成真实的随机数据集?结果分析
查看该社交网络的一种非常粗略的方法是简单地计算每个人呼叫的唯一朋友的数量。如果你运行模拟足够长的时间,这应该为你提供每个人社交网络中实际人数的下限(因为你使用帕累托分布的权重,许多人的朋友真的不太可能被称为,所以你需要模拟运行很长时间才能真正观察到每个可能被调用的人)。
你执行我们的场景 15 天模拟并获得了这个,它非常接近并略低于你在社交图中设置的平均度数 20:
social_group_size = (
resulting_dataset[["PERSON_ID", "OTHER_PERSON"]]
.groupby("PERSON_ID")
.agg(lambda friends_ids: len(friends_ids.unique()))
)
social_group_size.plot(kind="hist")
还有更多 !
这篇文章中没有描述 Trumania 的几个特性:
- 在一个场景中有几个人口
- 在一个场景中有几个故事
- 在故事之间添加概率相关性(例如,一个人在被呼叫后呼叫朋友)
- 状态更新(例如根据通话时间减少余额账户)
- 可重复使用的场景片段,例如地理位置、更多计时器配置文件……
- 场景片段的持久性
Trumania生成真实的随机数据集结论
我们在 Python 中引入了 Trumania 作为基于场景的数据生成器库。生成的数据集可用于广泛的应用,例如测试、学习和基准测试。
Trumania如何生成随机数据集?我们解释说,为了正确测试应用程序或算法,我们需要符合某些预期统计属性的数据集。我们在一个示例中说明了 Trumania 能够做到这一点,在该示例中,我们生成了一个基本的“消息日志”数据集,该数据集尊重每个用户的消息数量分布、一天中的时间分布以及社交图之间的呼叫分布.
我们希望我们还展示了 Trumania 组件的灵活性允许创建广泛的场景。
如何使用Trumania?Trumania 场景可以包括实体之间的关系,并且可以配置理论随机分布、在真实数据集中观察到的经验分布,甚至是真实的生产数据(例如,位置 ID 等的数据集)。我们通过重新使用在真实数据集中观察到的电话使用时间戳的统计分布来配置我们故事的时间随机计时器来证明这一点。