Lewati ke konten utama

Membuat Dataset Acak yang Realistis dengan Trumania

Temukan Python Trumania, pustaka pembuat dataset acak berbasis skenario. Pelajari cara membuat dataset sintetis dan acak dalam tutorial langkah demi langkah ini.
Diperbarui 28 Sep 2026  · 15 mnt Baca

Jelajahi bersama AI

ChatGPTClaudePerplexity

Catatan editor: artikel ini ditulis bekerja sama dengan Milan van der Meer. Kedua penulis artikel ini adalah bagian dari tim Real Impact Analytics, sebuah startup big data inovatif asal Belgia yang menangkap nilai dalam data telekomunikasi dengan "mengaplikasikan big data".

Tutorial ini memberi gambaran singkat tentang mengapa Anda mungkin ingin membuat dataset acak dan apa yang dapat diharapkan darinya. Tutorial ini juga memandu Anda melalui beberapa contoh awal cara menggunakan Trumania, sebuah pustaka Python untuk pembuatan data.

Untuk informasi lebih lanjut, kunjungi GitHub Trumania!

Mengapa membuat dataset acak?

Pembuatan dataset acak relevan bagi data engineer dan data scientist. Mengapa data scientist dan data engineer bekerja dengan data sintetis dan bagaimana cara mereka mendapatkannya?

Sebagai data engineer, setelah Anda menulis aplikasi pemrosesan data baru yang hebat, Anda merasa saatnya memulai pengujian end-to-end dan karena itu Anda membutuhkan data masukan.

Sebagai data scientist, Anda dapat memanfaatkan pembuatan data karena memungkinkan Anda bereksperimen dengan berbagai cara mengeksplorasi dataset, algoritme, teknik visualisasi data, atau memvalidasi asumsi tentang perilaku suatu metode terhadap banyak dataset berbeda pilihan Anda.

Dalam kedua kasus, opsi yang menggoda adalah langsung menggunakan data nyata. Namun, masalah kecilnya adalah data produksi biasanya sulit didapat, bahkan sebagian, dan tidak menjadi lebih mudah dengan adanya undang-undang Eropa baru tentang privasi dan keamanan.

Mungkin Anda termasuk yang beruntung, Anda memiliki satu set data produksi lengkap yang bagus di laptop. Meski begitu, Anda akan menginginkan lebih banyak variasi dalam dataset untuk memvalidasi berbagai situasi seperti ukuran populasi yang berbeda, distribusi data yang berbeda, beragam masalah kualitas data seperti data hilang atau tidak valid...

Untuk bacaan yang lebih mendalam tentang mengapa membuat dataset acak itu berguna, lihat 'Mengapa data sintetis akan menjadi keunggulan kompetitif utama'.

Pembuatan Data Acak Berbasis Skema: Kita Butuh Relasi yang Baik!

Bagian ini mencoba mengilustrasikan pembuatan data acak berbasis skema dan menunjukkan keterbatasannya.

Sudah ada banyak alat untuk membuat dataset acak. Pendekatan umum di antara alat-alat tersebut adalah pembuatan berbasis skema yang memungkinkan Anda mendefinisikan cetak biru dan menggunakannya untuk membuat sejumlah entitas. Khermes dan LogSynth adalah dua contohnya.

Contoh konfigurasi berbasis skema mungkin mencakup skema-persona berikut:

{
  {
    "field": "Name",
    "class": NameGenerator
  },
  {
    "field": "Age",
    "class": RandomInt(18, 65)
  },
  {
    "field": "Gender",
    "class": RandomPicker(["Male", "Female", "Other"])
  } 
}

Skema ini mendefinisikan pembuatan sejumlah data tentang seseorang. Isinya nama, usia, dan gender. Sederhana, cepat, namun ada beberapa keterbatasan. Salah satu keterbatasan utama adalah memalsukan relasi antar entitas yang berbeda atau berbasis waktu.

Misalnya, bagaimana membuat beberapa nama lebih mungkin muncul berdasarkan gender? Atau bagaimana membuat log aksi pengguna di mana aksi lebih mungkin terjadi saat akhir pekan?

Pendekatan berbasis skema tidak memudahkan untuk mengekspos aplikasi baru Anda pada kekhasan atau kesulitan dunia nyata seperti:

  • Dataset tidak seimbang (kesulitan pada operasi seperti group-by);
  • Pola terklaster dalam jaringan entitas. Artinya, menemukan kelompok sosial melalui interaksi pengguna (misalnya, panggilan telepon);
  • Beragam profil aktivitas waktu. Aksi lebih mungkin terjadi pada waktu tertentu dalam sehari atau seminggu;
  • Hubungan kausal antar aksi. Misalnya, banyak aksi pembelian di sebuah toko yang pada akhirnya memicu peristiwa "kehabisan stok".

Trumania berbasis skenario untuk mengatasi kekurangan ini dan menghasilkan dataset yang lebih realistis. Saat skenario bergulir, berbagai populasi saling berinteraksi, memperbarui propertinya, dan memancarkan log.

Contoh skenario adalah orang-orang menelepon teman mereka. Saat seseorang menelepon, mereka membayar dalam menit, ketika menitnya habis mereka harus ke toko... Dataset yang dihasilkan bisa berupa log panggilan pengguna, log aksi belanja, dan level stok tiap jam. Aksi dalam sebuah skenario bisa acak atau deterministik.

Dalam Trumania, dataset yang dihasilkan biasanya berupa deret waktu karena merupakan hasil eksekusi skenario yang bergulir seiring waktu.

Membuat Data Saling Terkait dengan Trumania (alias Waktunya Tutorial!)

Pada contoh di bawah, Anda akan melihat bagaimana menyusun skenario dasar di mana berbagai orang saling mengirim pesan. Dataset yang dihasilkan akan berupa deret waktu pesan yang dipertukarkan antar orang.

Urutan langkah yang akan kita lalui sebagai berikut:

  • membuat circus Trumania, yaitu dunia tempat skenario akan dieksekusi
  • menambahkan cerita "hello world" yang akan menghasilkan log dasar yang di-hardcode
  • menambahkan sebuah relationship untuk menetapkan beberapa kutipan favorit ke setiap orang, yang akan digunakan untuk membuat konten pesan.
  • membuat parameter waktu cerita untuk mendapatkan distribusi pesan yang lebih realistis sepanjang hari
  • menambahkan relasi lain untuk mendefinisikan jejaring sosial, sehingga graf sosial yang muncul dari log pesan lebih realistis

Membuat Trumania Circus

Tujuan

Langkah pertama adalah membuat circus, yaitu dunia tempat semua elemen skenario akan berada. Kita juga akan membuat populasi dasar persons. Karena banyak aspek Trumania bersifat acak, langkah ini juga memperkenalkan konsep generators yang digunakan untuk mengontrol banyak perilaku acak.

Kita belum akan menambahkan skenario pada titik ini, jadi semuanya akan statis.

Mari mulai!

Cara

Sebuah Trumania circus dibuat dengan sederhana sebagai berikut:

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

Di Trumania, semua elemen terkait waktu dikendalikan oleh sebuah jam pusat. Bagian terpenting dalam cuplikan kode di atas adalah step_duration=pd.Timedelta("1h"), yang mendefinisikan bahwa jam akan bertambah setiap 1 jam.

Selanjutnya, tambahkan populasi person ke circus. Populasi pada dasarnya adalah sekumpulan agen yang memiliki id dan beberapa atribut.

Nilai setiap atribut bisa Anda tentukan secara manual, namun dalam banyak kasus, Anda ingin membuatnya secara acak, jadi mari kita definisikan dulu beberapa generators untuk itu:

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

Sebuah generator Trumania bertugas menyediakan data ketika metodenya generate() dipanggil. Dalam contoh di atas, id_gen akan menghasilkan string seperti PERSON_0001, PERSON_0002, ... age_gen akan berulang kali mengambil sampel data dari distribusi normal dan name_gen akan memberikan nama orang secara acak.

Perhatikan bahwa setiap distribusi statistik dari numpy serta setiap penyedia Faker tersedia di Trumania, dan Trumania dapat dengan mudah diperluas dengan yang baru.

Dengan ini, Anda dapat menambahkan populasi 1000 orang dengan ID berurutan dan dua atribut acak dasar:

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)

Hasil

Anda sudah bisa melihat atribut yang dihasilkan dari semua anggota populasi person dengan memanggil 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 |
+-------------------+-----------------+---------+

Tip: jika Anda ingin melihat keseluruhan skrip untuk populasi pengguna dasar ini, lihat cuplikan di Github!

Pernyataan Hello World: Membuat Cerita

Tujuan

Mari buat ini sedikit lebih menarik dengan menambahkan sebuah story. Sebuah cerita Trumania pada dasarnya adalah bagian skenario yang merangkum aspek dinamis. Cerita dieksekusi setiap kali jam simulasi maju satu langkah.

Ingat bahwa Anda menetapkan step_duration=pd.Timedelta("1h") di circus di atas, sehingga ini berarti setiap jam logis, setiap cerita akan berkesempatan untuk dieksekusi.

Anda akan membuat cerita hello-world sederhana di mana semua anggota populasi person di atas akan secara berkala mengeluarkan pesan "hello world".

Cara

Aspek utama pertama yang ditentukan saat membuat story adalah populasi yang memulai cerita. Dalam kasus ini, itu adalah person. Aspek kedua adalah mendefinisikan timer, yang menentukan kapan setiap anggota populasi memicu aksi tersebut. Untuk saat ini, Anda menetapkannya ke 1, yang berarti semua anggota akan mengeksekusi cerita pada setiap langkah jam (Anda akan membuat timer yang lebih rumit pada langkah selanjutnya):

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

Sejauh ini, cerita masih kosong sehingga tidak melakukan apa pun: Anda perlu menambahkan beberapa operation ke dalamnya. Operation bisa acak atau deterministik, dapat membaca dan memperbarui atribut populasi mana pun atau bagian state lain di circus, dan bahkan memiliki efek samping.

Untuk saat ini, mari tambahkan dua operation deterministik sederhana dan sebuah logger agar benar-benar mendapatkan log:

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 menghasilkan stempel waktu acak di dalam interval waktu 1 jam saat ini dan ConstantGenerator hanya menghasilkan nilai konstan yang di-hardcode.

Hasil

Mari jalankan circus selama 48 jam waktu simulasi:

example_circus.run(
    duration=pd.Timedelta("48h"),
    log_output_folder="example_scenario",
    delete_existing_logs=True
)

Ini akan menghasilkan dataset dasar berikut, di mana masing-masing dari 1000 orang mengatakan "hello world" sebanyak 48 kali selama 2 hari.

Kolom pertama dari dataset yang dihasilkan, PERSON_ID, sesuai dengan member_id_field dari story. Dua kolom lainnya, TIME dan MESSAGE, sesuai dengan dua operation utama yang Anda masukkan ke dalam cerita.

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

Tip: lihat cuplikan lengkapnya di Github

Seseorang untuk disapa Hello World

Tujuan

Mari kita tingkatkan dengan menambahkan orang acak lain ke dalam percakapan. Untuk saat ini, Anda akan mengatakan bahwa siapa pun dapat berbicara dengan siapa pun dengan probabilitas yang sama, yang tidak terlalu realistis (Anda akan menambahkan jejaring sosial pada langkah selanjutnya). Juga, Anda akan memperkaya dataset dengan menambahkan nama orang berdasarkan ID mereka.

Cara

Anggaplah orang lain tersebut akan disimpan dalam kolom baru OTHER_PERSON. Dalam kasus sederhana ini, Anda hanya ingin menempatkan di kolom tersebut hasil seleksi acak tak berbobot dari populasi person. Anda cukup menggunakan operation acak select_one dari populasi tersebut:

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

Hasil

Saat Anda menjalankan circus lagi, Anda akan mendapatkan dataset dengan kolom OTHER_PERSON baru:

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

Tip: Anda dapat melihat seluruh kode di sini

Anda selalu mengatakan itu

Tujuan

Mari kita tingkatkan lagi dengan menghasilkan kalimat acak pada kolom MESSAGE alih-alih string hello world yang membosankan dan di-hardcode. Ini akan memungkinkan Anda mengilustrasikan penggunaan dasar pertama dari Relationship Trumania.

Anda akan mengaitkan setiap orang dengan 4 kutipan. Setiap kali seseorang mengirim pesan, kontennya akan dipilih dari 4 kutipan orang tersebut. Selain itu, Anda akan mengaitkan setiap kutipan dengan weight berbeda yang menentukan seberapa mungkin kutipan itu muncul: kutipan dengan bobot tinggi akan lebih sering dikirim oleh pemiliknya dibandingkan kutipan berbobot rendah.

Sekarang bagaimana memulainya?

Cara

Langkah pertama adalah membuat generator kutipan, yang mirip dengan generator Faker lain yang Anda lihat di atas:

quote_generator = FakerGenerator(method="sentence", nb_words=6, variable_nb_words=True,
                                 seed=next(example_circus.seeder))

Anda dapat menggunakan generator itu apa adanya dalam story seperti sebelumnya, tetapi mari kita buat lebih menarik dengan membatasi setiap orang untuk selalu menggunakan salah satu dari 4 kutipan favoritnya. Anda melakukan ini dengan membuat sebuah Relationship antara anggota populasi person dan sejumlah nilai kalimat.

Pertama, buat relationship kosong:

quotes_rel = example_circus.populations["person"].create_relationship("quotes")

Kemudian, isi relationship ini dengan 4 kutipan untuk setiap orang. Dalam kode di bawah ini person.ids adalah Series pandas berukuran 1000 berisi semua id dari populasi person, dan quote_generator.generate(size=person.size) menyediakan Series pandas lain juga berukuran 1000, berisi kutipan acak.

Ini berarti setiap putaran for-loop di bawah mengisi 1000 relasi dalam relationship: menambahkan satu kutipan untuk masing-masing dari 1000 pengguna. 1000 kutipan pertama akan dikaitkan dengan weight=1, berikutnya akan dibuat lebih sering dengan 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
    )

Sekarang Anda dapat mengganti ConstantGenerator dalam cerita dengan operation select_one pada relationship tersebut. Ini berarti: untuk setiap nilai yang saat ini ada di kolom PERSON_ID, cari relationship di quotes yang berawal dari ID tersebut dan pilih secara acak salah satu nilai terkait. Karena tidak ada bobot yang ditimpa dalam operation di bawah, bobot relationship default yang didefinisikan di add_relations di atas akan digunakan:

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

Hasil

Saat Anda menjalankan circus, kolom MESSAGE sekarang akan berisi kutipan acak:

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

Inti dari relationship yang digunakan untuk kutipan adalah kini kolom-kolom pada dataset yang dihasilkan saling terkait: beberapa kalimat lebih sering digunakan oleh pengguna tertentu.

Tip: lihat cuplikan kode lengkap di Github

Bukan apa yang Anda lakukan, tapi kapan Anda melakukannya

Tujuan

Sejauh ini, setiap anggota populasi person menghasilkan tepat satu pesan setiap jam. Mari buat sedikit lebih realistis.

Trumania menggunakan kombinasi 2 konsep untuk mengendalikan aspek waktu eksekusi sebuah cerita: tingkat aktivitas dan profil timer. Keduanya bersama-sama menentukan probabilitas memicu story mengingat pengguna spesifik dan waktu dalam sehari.

Cara

Anda akan memperbarui story dan membuat parameter untuk kedua aspek tersebut.

Pertama, mari buat profil timer cerita, yang mengontrol momen ketika lebih banyak atau lebih sedikit aksi dipicu. Profil ini sama untuk semua anggota populasi yang memicu cerita.

Trumania hadir dengan beberapa default menarik, seperti DefaultDailyTimerGenerator, yang sesuai dengan penggunaan telepon harian yang kami ukur pada dataset produksi nyata:

Trumania Default Daily Timer Generator Visualization

Mari instansiasi satu di skenario Anda:

from trumania.components.time_patterns.profilers import DefaultDailyTimerGenerator

story_timer_gen = DefaultDailyTimerGenerator(
    clock=example_circus.clock, 
    seed=next(example_circus.seeder))

Kedua, ada tingkat aktivitas anggota populasi untuk cerita tersebut, yang mendefinisikan seberapa aktif setiap pengguna dalam cerita itu. Anda bebas menetapkan level berbeda untuk setiap anggota, sehingga beberapa anggota memicu aksi itu lebih sering atau lebih jarang daripada yang lain.

Anda bisa menentukan setiap level secara manual jika ingin, meskipun di sini Anda akan menggunakan generator acak yang akan menetapkan level aktivitas ke setiap anggota populasi.

Pertama, kita definisikan tiga tingkat aktivitas sebanyak 3, 10, dan 20 pemicu per hari rata-rata:

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

Kemudian, Anda dapat membuat generator aktivitas aktual, yang akan menjadi generator Numpy lain, kali ini berdasarkan metode choice. Yang di bawah ini akan menetapkan aktivitas rendah ke 20% populasi, aktivitas sedang ke 70% dan aktivitas tinggi ke 10%:

activity_gen = NumpyRandomGenerator(
    method="choice", 
    a=[low_activity, med_activity, high_activity],
    p=[.2, .7, .1],
    seed=next(example_circus.seeder))

Dan sekarang Anda dapat menggunakan profil timer dan generator aktivitas ini sebagai bagian dari cerita Anda:

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
)

Hasil

Dataset yang dihasilkan memiliki skema yang sama seperti sebelumnya:

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

Tip: lihat cuplikan di Github

Analitik Hasil

Pola waktu yang Anda masukkan dalam konfigurasi skenario kini seharusnya terlihat dalam struktur internal dataset yang dihasilkan. Anda dapat mendemonstrasikannya dengan melakukan analisis data dasar pada resulting_dataset:

  • jumlah pesan pada setiap jam dalam sehari seharusnya mengikuti distribusi yang ditentukan (perhatikan betapa miripnya dengan kurva DefaultDailyTimerGenerator di atas):
time_profile = (
    resulting_dataset[["MESSAGE", "TIME"]]
    .groupby(by=example_5_df.TIME.dt.hour)["MESSAGE"]
    .count()
)
time_profile.plot()

Trumania Default Daily Timer Generator Visualization

  • Histogram jumlah pesan per pengguna juga seharusnya sesuai dengan konfigurasi Anda:
    • Anda mengonfigurasi low_activity menjadi rata-rata 3 pesan per hari, med_activity menjadi 10 dan high_activity menjadi 20 serta menjalankan simulasi selama 5 hari. Ini seharusnya menghasilkan 3 kelompok person dengan kira-kira 15, 50, dan 100 total pesan, yang sesuai dengan 3 pusat histogram di bawah
    • Anda mengonfigurasi probabilitas level aktivitas ini menjadi .2, .7, dan .1, dan ini juga kurang lebih sesuai dengan luas masing-masing "tonjolan" histogram:
usage_per_user = resulting_dataset[["MESSAGE", "PERSON_ID"]].groupby("PERSON_ID")["MESSAGE"].count()
usage_per_user.plot(kind="hist")

Visualisasi histogram & graf frekuensi pesan per pengguna

Jejaring Sosial

Tujuan

Anda dapat lebih meningkatkan skenario dengan menghubungkan orang-orang sehingga mereka mengirim pesan kepada teman mereka selama eksekusi cerita, alih-alih ke orang acak. Ini akan memperkenalkan banyak struktur pada dataset yang dihasilkan karena kini graf sosial seharusnya dapat ditemukan dari log pesan.

Cara

Anda dapat memodelkan jejaring sosial dengan Relationship lagi, konsep yang sama seperti yang Anda gunakan untuk memodelkan kutipan. Anda mungkin ingat bahwa relationship quotes memiliki bobot. Bobot itu menentukan kutipan mana yang lebih atau kurang mungkin, mengingat seseorang. Anda dapat melakukan hal yang sama di sini dan menggunakan bobot untuk menentukan teman mana yang lebih atau kurang mungkin dipanggil daripada yang lain.

Perhatikan bahwa di sini Anda mendefinisikan relationship dari person ke person, meskipun secara umum Trumania memungkinkan Anda mendefinisikan relationship antara pasangan populasi mana pun.

Ada banyak cara untuk menghasilkan sisi-sisi graf sosial. Salah satu yang dasar dan klasik adalah mengandalkan algoritme Erdos-Renyi. Ini sangat mudah di Trumania karena sudah terpasang dalam kerangka kerja. Anda hanya perlu menyuntikkannya ke skenario untuk membuat relationship.

Di sini, Anda akan mendefinisikan graf sosial antarangota relationship person di mana setiap orang memiliki 20 teman. Perhatikan bahwa bobot akan otomatis ditambahkan ke relationship tersebut dengan distribusi Pareto.

from trumania.components.social_networks.erdos_renyi import WithErdosRenyi

# self adalah circus di sini, lihat contoh kode di github untuk detailnya
self.add_er_social_network_relationship(
    self.populations["person"],
    relationship_name="friends",
    average_degree=20)

Dengan relationship ini, Anda dapat meninjau kembali cerita kita sekali lagi. Kali ini, OTHER_PERSON tidak lagi dipilih secara acak dari populasi, tetapi akan dipilih dari teman setiap anggota person, dengan probabilitas proporsional terhadap bobot yang didefinisikan dalam jejaring sosial:

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

Hasil

Sekali lagi, dataset yang dihasilkan memiliki skema data yang sama seperti sebelumnya, meskipun kali ini bahkan lebih berstruktur berkat jejaring sosial dasar Anda:

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

Tip: Anda dapat melihat cuplikan di Github

Analitik Hasil

Cara yang sangat sederhana untuk melihat jejaring sosial tersebut adalah dengan menghitung jumlah teman unik yang dihubungi oleh setiap orang. Jika Anda menjalankan simulasi cukup lama, ini akan memberi Anda batas bawah dari jumlah orang sebenarnya dalam jejaring sosial masing-masing orang (karena Anda menggunakan bobot dengan distribusi Pareto, banyak orang memiliki teman yang sangat kecil kemungkinannya dipanggil, jadi Anda perlu menjalankan simulasi sangat lama untuk benar-benar mengamati setiap orang yang mungkin dipanggil).

Anda mengeksekusi skenario selama 15 hari simulasi dan memperoleh ini, yang terpusat sangat dekat dan sedikit di bawah derajat rata-rata 20 yang Anda tetapkan di graf sosial:

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

Histogram ukuran kelompok sosial yang teramati

Masih banyak lagi!

Beberapa fitur Trumania yang belum dijelaskan dalam artikel ini:

  • memiliki beberapa populasi dalam satu skenario
  • memiliki beberapa cerita dalam satu skenario
  • menambahkan ketergantungan probabilistik antar cerita (misalnya seseorang menelepon teman setelah sebelumnya ditelepon)
  • pembaruan state (misalnya mengurangi saldo berdasarkan durasi panggilan telepon)
  • potongan skenario yang dapat digunakan ulang, seperti geografi, lebih banyak profil timer, ...
  • persistensi potongan skenario

Kesimpulan

Kami memperkenalkan Trumania sebagai pustaka pembuat data berbasis skenario di Python. Dataset yang dihasilkan dapat digunakan untuk berbagai aplikasi seperti pengujian, pembelajaran, dan benchmarking.

Kami menjelaskan bahwa untuk menguji aplikasi atau algoritme dengan benar, kita memerlukan dataset yang menghormati beberapa sifat statistik yang diharapkan. Kami mengilustrasikan bahwa Trumania mampu melakukannya dalam contoh ketika kami membuat dataset "log pesan" dasar yang menghormati distribusi jumlah pesan per pengguna, distribusi waktu dalam sehari serta distribusi panggilan di antara graf sosial.

Semoga kami juga menunjukkan bahwa fleksibilitas komponen Trumania memungkinkan pembuatan berbagai skenario.

Skenario Trumania dapat mencakup relationship antar entitas dan dapat dikonfigurasi dengan distribusi acak teoretis, distribusi empiris yang diamati pada dataset nyata atau bahkan data produksi nyata (misalnya dataset id lokasi atau sejenisnya). Kami mendemonstrasikannya dengan menggunakan ulang distribusi statistik stempel waktu penggunaan telepon yang diamati dalam dataset nyata untuk mengonfigurasi timer acak waktu pada cerita kami.

Dengan ini, silakan bereksperimen! Kunjungi Github Trumania dan tulis skenario Anda sendiri ;)

Jika tidak, jangan ragu untuk menghubungi Svend Vanderveken atau rekan penulis Milan van der Meer:

  • Svend Vanderveken adalah software engineer lepas dengan keahlian dalam solusi pemrosesan data, terutama di Kafka, Scala, SQL, Python... Ikuti melalui blognya svend.kelesia.com dan Twitter @sv3ndk.
  • Milan van der Meer saat ini bekerja sebagai software engineer di Real Impact Analytics. Anda selalu dapat terhubung dengannya di LinkedIn

Catatan editor: artikel ini ditulis bekerja sama dengan Milan van der Meer. Kedua penulis artikel ini adalah bagian dari tim Real Impact Analytics, sebuah startup big data inovatif asal Belgia yang menangkap nilai dalam data telekomunikasi dengan "mengaplikasikan big data".

Tutorial ini memberi gambaran singkat tentang mengapa Anda mungkin ingin membuat dataset acak dan apa yang dapat diharapkan darinya. Tutorial ini juga memandu Anda melalui beberapa contoh awal cara menggunakan Trumania, sebuah pustaka Python untuk pembuatan data.

Untuk informasi lebih lanjut, kunjungi GitHub Trumania!

Mengapa membuat dataset acak?

Pembuatan dataset acak relevan bagi data engineer dan data scientist. Mengapa data scientist dan data engineer bekerja dengan data sintetis dan bagaimana cara mereka mendapatkannya?

Sebagai data engineer, setelah Anda menulis aplikasi pemrosesan data baru yang hebat, Anda merasa saatnya memulai pengujian end-to-end dan karena itu Anda membutuhkan data masukan.

Sebagai data scientist, Anda dapat memanfaatkan pembuatan data karena memungkinkan Anda bereksperimen dengan berbagai cara mengeksplorasi dataset, algoritme, teknik visualisasi data, atau memvalidasi asumsi tentang perilaku suatu metode terhadap banyak dataset berbeda pilihan Anda.

Dalam kedua kasus, opsi yang menggoda adalah langsung menggunakan data nyata. Namun, masalah kecilnya adalah data produksi biasanya sulit didapat, bahkan sebagian, dan tidak menjadi lebih mudah dengan adanya undang-undang Eropa baru tentang privasi dan keamanan.

Mungkin Anda termasuk yang beruntung, Anda memiliki satu set data produksi lengkap yang bagus di laptop. Meski begitu, Anda akan menginginkan lebih banyak variasi dalam dataset untuk memvalidasi berbagai situasi seperti ukuran populasi yang berbeda, distribusi data yang berbeda, beragam masalah kualitas data seperti data hilang atau tidak valid...

Untuk bacaan yang lebih mendalam tentang mengapa membuat dataset acak itu berguna, lihat 'Mengapa data sintetis akan menjadi keunggulan kompetitif utama'.

Pembuatan Data Acak Berbasis Skema: Kita Butuh Relasi yang Baik!

Bagian ini mencoba mengilustrasikan pembuatan data acak berbasis skema dan menunjukkan keterbatasannya.

Sudah ada banyak alat untuk membuat dataset acak. Pendekatan umum di antara alat-alat tersebut adalah pembuatan berbasis skema yang memungkinkan Anda mendefinisikan cetak biru dan menggunakannya untuk membuat sejumlah entitas. Khermes dan LogSynth adalah dua contohnya.

Contoh konfigurasi berbasis skema mungkin mencakup skema-persona berikut:

{
  {
    "field": "Name",
    "class": NameGenerator
  },
  {
    "field": "Age",
    "class": RandomInt(18, 65)
  },
  {
    "field": "Gender",
    "class": RandomPicker(["Male", "Female", "Other"])
  } 
}

Skema ini mendefinisikan pembuatan sejumlah data tentang seseorang. Isinya nama, usia, dan gender. Sederhana, cepat, namun ada beberapa keterbatasan. Salah satu keterbatasan utama adalah memalsukan relasi antar entitas yang berbeda atau berbasis waktu.

Misalnya, bagaimana membuat beberapa nama lebih mungkin muncul berdasarkan gender? Atau bagaimana membuat log aksi pengguna di mana aksi lebih mungkin terjadi saat akhir pekan?

Pendekatan berbasis skema tidak memudahkan untuk mengekspos aplikasi baru Anda pada kekhasan atau kesulitan dunia nyata seperti:

  • Dataset tidak seimbang (kesulitan pada operasi seperti group-by);
  • Pola terklaster dalam jaringan entitas. Artinya, menemukan kelompok sosial melalui interaksi pengguna (misalnya, panggilan telepon);
  • Beragam profil aktivitas waktu. Aksi lebih mungkin terjadi pada waktu tertentu dalam sehari atau seminggu;
  • Hubungan kausal antar aksi. Misalnya, banyak aksi pembelian di sebuah toko yang pada akhirnya memicu peristiwa "kehabisan stok".

Trumania berbasis skenario untuk mengatasi kekurangan ini dan menghasilkan dataset yang lebih realistis. Saat skenario bergulir, berbagai populasi saling berinteraksi, memperbarui propertinya, dan memancarkan log.

Contoh skenario adalah orang-orang menelepon teman mereka. Saat seseorang menelepon, mereka membayar dalam menit, ketika menitnya habis mereka harus ke toko... Dataset yang dihasilkan bisa berupa log panggilan pengguna, log aksi belanja, dan level stok tiap jam. Aksi dalam sebuah skenario bisa acak atau deterministik.

Dalam Trumania, dataset yang dihasilkan biasanya berupa deret waktu karena merupakan hasil eksekusi skenario yang bergulir seiring waktu.

Membuat Data Saling Terkait dengan Trumania (alias Waktunya Tutorial!)

Pada contoh di bawah, Anda akan melihat bagaimana menyusun skenario dasar di mana berbagai orang saling mengirim pesan. Dataset yang dihasilkan akan berupa deret waktu pesan yang dipertukarkan antar orang.

Urutan langkah yang akan kita lalui sebagai berikut:

  • membuat circus Trumania, yaitu dunia tempat skenario akan dieksekusi
  • menambahkan cerita "hello world" yang akan menghasilkan log dasar yang di-hardcode
  • menambahkan sebuah relationship untuk menetapkan beberapa kutipan favorit ke setiap orang, yang akan digunakan untuk membuat konten pesan.
  • membuat parameter waktu cerita untuk mendapatkan distribusi pesan yang lebih realistis sepanjang hari
  • menambahkan relasi lain untuk mendefinisikan jejaring sosial, sehingga graf sosial yang muncul dari log pesan lebih realistis

Membuat Trumania Circus

Tujuan

Langkah pertama adalah membuat circus, yaitu dunia tempat semua elemen skenario akan berada. Kita juga akan membuat populasi dasar persons. Karena banyak aspek Trumania bersifat acak, langkah ini juga memperkenalkan konsep generators yang digunakan untuk mengontrol banyak perilaku acak.

Kita belum akan menambahkan skenario pada titik ini, jadi semuanya akan statis.

Mari mulai!

Cara

Sebuah Trumania circus dibuat dengan sederhana sebagai berikut:

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

Di Trumania, semua elemen terkait waktu dikendalikan oleh sebuah jam pusat. Bagian terpenting dalam cuplikan kode di atas adalah step_duration=pd.Timedelta("1h"), yang mendefinisikan bahwa jam akan bertambah setiap 1 jam.

Selanjutnya, tambahkan populasi person ke circus. Populasi pada dasarnya adalah sekumpulan agen yang memiliki id dan beberapa atribut.

Nilai setiap atribut bisa Anda tentukan secara manual, namun dalam banyak kasus, Anda ingin membuatnya secara acak, jadi mari kita definisikan dulu beberapa generators untuk itu:

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

Sebuah generator Trumania bertugas menyediakan data ketika metodenya generate() dipanggil. Dalam contoh di atas, id_gen akan menghasilkan string seperti PERSON_0001, PERSON_0002, ... age_gen akan berulang kali mengambil sampel data dari distribusi normal dan name_gen akan memberikan nama orang secara acak.

Perhatikan bahwa setiap distribusi statistik dari numpy serta setiap penyedia Faker tersedia di Trumania, dan Trumania dapat dengan mudah diperluas dengan yang baru.

Dengan ini, Anda dapat menambahkan populasi 1000 orang dengan ID berurutan dan dua atribut acak dasar:

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)

Hasil

Anda sudah bisa melihat atribut yang dihasilkan dari semua anggota populasi person dengan memanggil 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 |
+-------------------+-----------------+---------+

Tip: jika Anda ingin melihat keseluruhan skrip untuk populasi pengguna dasar ini, lihat cuplikan di Github!

Pernyataan Hello World: Membuat Cerita

Tujuan

Mari buat ini sedikit lebih menarik dengan menambahkan sebuah story. Sebuah cerita Trumania pada dasarnya adalah bagian skenario yang merangkum aspek dinamis. Cerita dieksekusi setiap kali jam simulasi maju satu langkah.

Ingat bahwa Anda menetapkan step_duration=pd.Timedelta("1h") di circus di atas, sehingga ini berarti setiap jam logis, setiap cerita akan berkesempatan untuk dieksekusi.

Anda akan membuat cerita hello-world sederhana di mana semua anggota populasi person di atas akan secara berkala mengeluarkan pesan "hello world".

Cara

Aspek utama pertama yang ditentukan saat membuat story adalah populasi yang memulai cerita. Dalam kasus ini, itu adalah person. Aspek kedua adalah mendefinisikan timer, yang menentukan kapan setiap anggota populasi memicu aksi tersebut. Untuk saat ini, Anda menetapkannya ke 1, yang berarti semua anggota akan mengeksekusi cerita pada setiap langkah jam (Anda akan membuat timer yang lebih rumit pada langkah selanjutnya):

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

Sejauh ini, cerita masih kosong sehingga tidak melakukan apa pun: Anda perlu menambahkan beberapa operation ke dalamnya. Operation bisa acak atau deterministik, dapat membaca dan memperbarui atribut populasi mana pun atau bagian state lain di circus, dan bahkan memiliki efek samping.

Untuk saat ini, mari tambahkan dua operation deterministik sederhana dan sebuah logger agar benar-benar mendapatkan log:

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 menghasilkan stempel waktu acak di dalam interval waktu 1 jam saat ini dan ConstantGenerator hanya menghasilkan nilai konstan yang di-hardcode.

Hasil

Mari jalankan circus selama 48 jam waktu simulasi:

example_circus.run(
    duration=pd.Timedelta("48h"),
    log_output_folder="example_scenario",
    delete_existing_logs=True
)

Ini akan menghasilkan dataset dasar berikut, di mana masing-masing dari 1000 orang mengatakan "hello world" sebanyak 48 kali selama 2 hari.

Kolom pertama dari dataset yang dihasilkan, PERSON_ID, sesuai dengan member_id_field dari story. Dua kolom lainnya, TIME dan MESSAGE, sesuai dengan dua operation utama yang Anda masukkan ke dalam cerita.

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

Tip: lihat cuplikan lengkapnya di Github

Seseorang untuk disapa Hello World

Tujuan

Mari kita tingkatkan dengan menambahkan orang acak lain ke dalam percakapan. Untuk saat ini, Anda akan mengatakan bahwa siapa pun dapat berbicara dengan siapa pun dengan probabilitas yang sama, yang tidak terlalu realistis (Anda akan menambahkan jejaring sosial pada langkah selanjutnya). Juga, Anda akan memperkaya dataset dengan menambahkan nama orang berdasarkan ID mereka.

Cara

Anggaplah orang lain tersebut akan disimpan dalam kolom baru OTHER_PERSON. Dalam kasus sederhana ini, Anda hanya ingin menempatkan di kolom tersebut hasil seleksi acak tak berbobot dari populasi person. Anda cukup menggunakan operation acak select_one dari populasi tersebut:

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

Hasil

Saat Anda menjalankan circus lagi, Anda akan mendapatkan dataset dengan kolom OTHER_PERSON baru:

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

Tip: Anda dapat melihat seluruh kode di sini

Anda selalu mengatakan itu

Tujuan

Mari kita tingkatkan lagi dengan menghasilkan kalimat acak pada kolom MESSAGE alih-alih string hello world yang membosankan dan di-hardcode. Ini akan memungkinkan Anda mengilustrasikan penggunaan dasar pertama dari Relationship Trumania.

Anda akan mengaitkan setiap orang dengan 4 kutipan. Setiap kali seseorang mengirim pesan, kontennya akan dipilih dari 4 kutipan orang tersebut. Selain itu, Anda akan mengaitkan setiap kutipan dengan weight berbeda yang menentukan seberapa mungkin kutipan itu muncul: kutipan dengan bobot tinggi akan lebih sering dikirim oleh pemiliknya dibandingkan kutipan berbobot rendah.

Sekarang bagaimana memulainya?

Cara

Langkah pertama adalah membuat generator kutipan, yang mirip dengan generator Faker lain yang Anda lihat di atas:

quote_generator = FakerGenerator(method="sentence", nb_words=6, variable_nb_words=True,
                                 seed=next(example_circus.seeder))

Anda dapat menggunakan generator itu apa adanya dalam story seperti sebelumnya, tetapi mari kita buat lebih menarik dengan membatasi setiap orang untuk selalu menggunakan salah satu dari 4 kutipan favoritnya. Anda melakukan ini dengan membuat sebuah Relationship antara anggota populasi person dan sejumlah nilai kalimat.

Pertama, buat relationship kosong:

quotes_rel = example_circus.populations["person"].create_relationship("quotes")

Kemudian, isi relationship ini dengan 4 kutipan untuk setiap orang. Dalam kode di bawah ini person.ids adalah Series pandas berukuran 1000 berisi semua id dari populasi person, dan quote_generator.generate(size=person.size) menyediakan Series pandas lain juga berukuran 1000, berisi kutipan acak.

Ini berarti setiap putaran for-loop di bawah mengisi 1000 relasi dalam relationship: menambahkan satu kutipan untuk masing-masing dari 1000 pengguna. 1000 kutipan pertama akan dikaitkan dengan weight=1, berikutnya akan dibuat lebih sering dengan 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
    )

Sekarang Anda dapat mengganti ConstantGenerator dalam cerita dengan operation select_one pada relationship tersebut. Ini berarti: untuk setiap nilai yang saat ini ada di kolom PERSON_ID, cari relationship di quotes yang berawal dari ID tersebut dan pilih secara acak salah satu nilai terkait. Karena tidak ada bobot yang ditimpa dalam operation di bawah, bobot relationship default yang didefinisikan di add_relations di atas akan digunakan:

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

Hasil

Saat Anda menjalankan circus, kolom MESSAGE sekarang akan berisi kutipan acak:

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

Inti dari relationship yang digunakan untuk kutipan adalah kini kolom-kolom pada dataset yang dihasilkan saling terkait: beberapa kalimat lebih sering digunakan oleh pengguna tertentu.

Tip: lihat cuplikan kode lengkap di Github

Bukan apa yang Anda lakukan, tapi kapan Anda melakukannya

Tujuan

Sejauh ini, setiap anggota populasi person menghasilkan tepat satu pesan setiap jam. Mari buat sedikit lebih realistis.

Trumania menggunakan kombinasi 2 konsep untuk mengendalikan aspek waktu eksekusi sebuah cerita: tingkat aktivitas dan profil timer. Keduanya bersama-sama menentukan probabilitas memicu story mengingat pengguna spesifik dan waktu dalam sehari.

Cara

Anda akan memperbarui story dan membuat parameter untuk kedua aspek tersebut.

Pertama, mari buat profil timer cerita, yang mengontrol momen ketika lebih banyak atau lebih sedikit aksi dipicu. Profil ini sama untuk semua anggota populasi yang memicu cerita.

Trumania hadir dengan beberapa default menarik, seperti DefaultDailyTimerGenerator, yang sesuai dengan penggunaan telepon harian yang kami ukur pada dataset produksi nyata:

Trumania Default Daily Timer Generator Visualization

Mari instansiasi satu di skenario Anda:

from trumania.components.time_patterns.profilers import DefaultDailyTimerGenerator

story_timer_gen = DefaultDailyTimerGenerator(
    clock=example_circus.clock, 
    seed=next(example_circus.seeder))

Kedua, ada tingkat aktivitas anggota populasi untuk cerita tersebut, yang mendefinisikan seberapa aktif setiap pengguna dalam cerita itu. Anda bebas menetapkan level berbeda untuk setiap anggota, sehingga beberapa anggota memicu aksi itu lebih sering atau lebih jarang daripada yang lain.

Anda bisa menentukan setiap level secara manual jika ingin, meskipun di sini Anda akan menggunakan generator acak yang akan menetapkan level aktivitas ke setiap anggota populasi.

Pertama, kita definisikan tiga tingkat aktivitas sebanyak 3, 10, dan 20 pemicu per hari rata-rata:

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

Kemudian, Anda dapat membuat generator aktivitas aktual, yang akan menjadi generator Numpy lain, kali ini berdasarkan metode choice. Yang di bawah ini akan menetapkan aktivitas rendah ke 20% populasi, aktivitas sedang ke 70% dan aktivitas tinggi ke 10%:

activity_gen = NumpyRandomGenerator(
    method="choice", 
    a=[low_activity, med_activity, high_activity],
    p=[.2, .7, .1],
    seed=next(example_circus.seeder))

Dan sekarang Anda dapat menggunakan profil timer dan generator aktivitas ini sebagai bagian dari cerita Anda:

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
)

Hasil

Dataset yang dihasilkan memiliki skema yang sama seperti sebelumnya:

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

Tip: lihat cuplikan di Github

Analitik Hasil

Pola waktu yang Anda masukkan dalam konfigurasi skenario kini seharusnya terlihat dalam struktur internal dataset yang dihasilkan. Anda dapat mendemonstrasikannya dengan melakukan analisis data dasar pada resulting_dataset:

  • jumlah pesan pada setiap jam dalam sehari seharusnya mengikuti distribusi yang ditentukan (perhatikan betapa miripnya dengan kurva DefaultDailyTimerGenerator di atas):
time_profile = (
    resulting_dataset[["MESSAGE", "TIME"]]
    .groupby(by=example_5_df.TIME.dt.hour)["MESSAGE"]
    .count()
)
time_profile.plot()

Trumania Default Daily Timer Generator Visualization

  • Histogram jumlah pesan per pengguna juga seharusnya sesuai dengan konfigurasi Anda:
    • Anda mengonfigurasi low_activity menjadi rata-rata 3 pesan per hari, med_activity menjadi 10 dan high_activity menjadi 20 serta menjalankan simulasi selama 5 hari. Ini seharusnya menghasilkan 3 kelompok person dengan kira-kira 15, 50, dan 100 total pesan, yang sesuai dengan 3 pusat histogram di bawah
    • Anda mengonfigurasi probabilitas level aktivitas ini menjadi .2, .7, dan .1, dan ini juga kurang lebih sesuai dengan luas masing-masing "tonjolan" histogram:
usage_per_user = resulting_dataset[["MESSAGE", "PERSON_ID"]].groupby("PERSON_ID")["MESSAGE"].count()
usage_per_user.plot(kind="hist")

Visualisasi histogram & graf frekuensi pesan per pengguna

Jejaring Sosial

Tujuan

Anda dapat lebih meningkatkan skenario dengan menghubungkan orang-orang sehingga mereka mengirim pesan kepada teman mereka selama eksekusi cerita, alih-alih ke orang acak. Ini akan memperkenalkan banyak struktur pada dataset yang dihasilkan karena kini graf sosial seharusnya dapat ditemukan dari log pesan.

Cara

Anda dapat memodelkan jejaring sosial dengan Relationship lagi, konsep yang sama seperti yang Anda gunakan untuk memodelkan kutipan. Anda mungkin ingat bahwa relationship quotes memiliki bobot. Bobot itu menentukan kutipan mana yang lebih atau kurang mungkin, mengingat seseorang. Anda dapat melakukan hal yang sama di sini dan menggunakan bobot untuk menentukan teman mana yang lebih atau kurang mungkin dipanggil daripada yang lain.

Perhatikan bahwa di sini Anda mendefinisikan relationship dari person ke person, meskipun secara umum Trumania memungkinkan Anda mendefinisikan relationship antara pasangan populasi mana pun.

Ada banyak cara untuk menghasilkan sisi-sisi graf sosial. Salah satu yang dasar dan klasik adalah mengandalkan algoritme Erdos-Renyi. Ini sangat mudah di Trumania karena sudah terpasang dalam kerangka kerja. Anda hanya perlu menyuntikkannya ke skenario untuk membuat relationship.

Di sini, Anda akan mendefinisikan graf sosial antarangota relationship person di mana setiap orang memiliki 20 teman. Perhatikan bahwa bobot akan otomatis ditambahkan ke relationship tersebut dengan distribusi Pareto.

from trumania.components.social_networks.erdos_renyi import WithErdosRenyi

# self adalah circus di sini, lihat contoh kode di github untuk detailnya
self.add_er_social_network_relationship(
    self.populations["person"],
    relationship_name="friends",
    average_degree=20)

Dengan relationship ini, Anda dapat meninjau kembali cerita kita sekali lagi. Kali ini, OTHER_PERSON tidak lagi dipilih secara acak dari populasi, tetapi akan dipilih dari teman setiap anggota person, dengan probabilitas proporsional terhadap bobot yang didefinisikan dalam jejaring sosial:

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

Hasil

Sekali lagi, dataset yang dihasilkan memiliki skema data yang sama seperti sebelumnya, meskipun kali ini bahkan lebih berstruktur berkat jejaring sosial dasar Anda:

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

Tip: Anda dapat melihat cuplikan di Github

Analitik Hasil

Cara yang sangat sederhana untuk melihat jejaring sosial tersebut adalah dengan menghitung jumlah teman unik yang dihubungi oleh setiap orang. Jika Anda menjalankan simulasi cukup lama, ini akan memberi Anda batas bawah dari jumlah orang sebenarnya dalam jejaring sosial masing-masing orang (karena Anda menggunakan bobot dengan distribusi Pareto, banyak orang memiliki teman yang sangat kecil kemungkinannya dipanggil, jadi Anda perlu menjalankan simulasi sangat lama untuk benar-benar mengamati setiap orang yang mungkin dipanggil).

Anda mengeksekusi skenario selama 15 hari simulasi dan memperoleh ini, yang terpusat sangat dekat dan sedikit di bawah derajat rata-rata 20 yang Anda tetapkan di graf sosial:

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

Histogram ukuran kelompok sosial yang teramati

Masih banyak lagi!

Beberapa fitur Trumania yang belum dijelaskan dalam artikel ini:

  • memiliki beberapa populasi dalam satu skenario
  • memiliki beberapa cerita dalam satu skenario
  • menambahkan ketergantungan probabilistik antar cerita (misalnya seseorang menelepon teman setelah sebelumnya ditelepon)
  • pembaruan state (misalnya mengurangi saldo berdasarkan durasi panggilan telepon)
  • potongan skenario yang dapat digunakan ulang, seperti geografi, lebih banyak profil timer, ...
  • persistensi potongan skenario

Kesimpulan

Kami memperkenalkan Trumania sebagai pustaka pembuat data berbasis skenario di Python. Dataset yang dihasilkan dapat digunakan untuk berbagai aplikasi seperti pengujian, pembelajaran, dan benchmarking.

Kami menjelaskan bahwa untuk menguji aplikasi atau algoritme dengan benar, kita memerlukan dataset yang menghormati beberapa sifat statistik yang diharapkan. Kami mengilustrasikan bahwa Trumania mampu melakukannya dalam contoh ketika kami membuat dataset "log pesan" dasar yang menghormati distribusi jumlah pesan per pengguna, distribusi waktu dalam sehari serta distribusi panggilan di antara graf sosial.

Semoga kami juga menunjukkan bahwa fleksibilitas komponen Trumania memungkinkan pembuatan berbagai skenario.

Skenario Trumania dapat mencakup relationship antar entitas dan dapat dikonfigurasi dengan distribusi acak teoretis, distribusi empiris yang diamati pada dataset nyata atau bahkan data produksi nyata (misalnya dataset id lokasi atau sejenisnya). Kami mendemonstrasikannya dengan menggunakan ulang distribusi statistik stempel waktu penggunaan telepon yang diamati dalam dataset nyata untuk mengonfigurasi timer acak waktu pada cerita kami.

Dengan ini, silakan bereksperimen! Kunjungi Github Trumania dan tulis skenario Anda sendiri ;)

Jika tidak, jangan ragu untuk menghubungi Svend Vanderveken atau rekan penulis Milan van der Meer:

  • Svend Vanderveken adalah software engineer lepas dengan keahlian dalam solusi pemrosesan data, terutama di Kafka, Scala, SQL, Python... Ikuti melalui blognya svend.kelesia.com dan Twitter @sv3ndk.
  • Milan van der Meer saat ini bekerja sebagai software engineer di Real Impact Analytics. Anda selalu dapat terhubung dengannya di LinkedIn
Topik
Python
Terkait

blogs

Spaghetti Plot dan Jalur Badai

Temukan alasan mengapa Anda sebaiknya (tidak) menggunakan spaghetti plot untuk menyampaikan ketidakpastian jalur prediksi badai serta dampaknya terhadap interpretasi.
Hugo Bowne-Anderson's photo

Hugo Bowne-Anderson

13 mnt

blogs

Tutorial Korelasi di R

Dapatkan pengenalan dasar-dasar korelasi di R: pelajari lebih lanjut tentang koefisien korelasi, matriks korelasi, plotting korelasi, dan sebagainya.
David Woods's photo

David Woods

13 mnt

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026

Kuasai pertanyaan wawancara basis data, dari konsep SQL dasar hingga skenario desain sistem tingkat lanjut. Panduan mendalam ini mencakup semua yang Anda perlukan untuk sukses di wawancara DBMS dan meraih peran berikutnya.
Dario Radečić's photo

Dario Radečić

15 mnt

blogs

12 Alternatif ChatGPT Terbaik yang Bisa Anda Coba pada 2026

Artikel ini menyajikan daftar alternatif ChatGPT yang akan meningkatkan produktivitas Anda.
Javier Canales Luna's photo

Javier Canales Luna

14 mnt

Lihat SelengkapnyaLihat Selengkapnya