Data Slice Generator

The data slice generator is the underlying function used to generate data slices for the labeling function. If the label maker raises an error during the search or the output labels don’t seem correct, you need to check the logic in the labeling function or inspect the data for inherent errors. The data slice generator can help identify those problems. You also want to use the generator during the development of your labeling function as a best practice. But it is an optional step and not required to generate labels.

In this guide, use the data slice generator to inspect data slices and apply a labeling function. To get started, load a mock dataset of transactions and sample the data to see how the transactions look.

[1]:
import composeml as cp
[2]:
df = cp.demos.load_transactions()
df = df[df.columns[:7]]
df.sample(n=5, random_state=0)
[2]:
transaction_id session_id transaction_time product_id amount customer_id device
26 94 24 2014-01-01 05:55:20 5 100.42 5 tablet
86 274 7 2014-01-01 01:46:10 5 14.45 3 tablet
2 495 1 2014-01-01 00:14:05 5 69.45 2 desktop
55 275 4 2014-01-01 00:45:30 5 108.11 1 mobile
75 368 27 2014-01-01 06:36:30 5 139.43 1 mobile

Labeling Function

Define a labeling function that returns how much a customer spent given a slice of transactions.

[3]:
def total_spent(df):
    return df["amount"].sum()

Data Slices

The LabelMaker.slice() method creates the data slice generator. The parameters of this method can be passed directly to LabelMaker.search() to generate the labels. In the following sections, we explain how to use the data slice generator to make data slices consecutive, overlap, or spread out.

See also

For a conceptual explanation of the process, see Main Concepts.

Consecutive

When the gap size is equal to the window size, the data slices are consecutive. In other words, the data slices do not overlap and are not spread out (in other words, don’t skip any data). This is the default value for the gap size. To demonstrate this example, generate data slices using these parameters.

To start, create a label maker with the 2-hour window size.

[4]:
lm = cp.LabelMaker(
    target_dataframe_index="customer_id",
    time_index="transaction_time",
    labeling_function=total_spent,
    window_size="2h",
)

Next, create a data slice generator with the 2-hour gap size. The default value for the gap size is the window size.

Tip

You can directly set minimum_data as the first cutoff time.

[5]:
slices = lm.slice(
    df.sort_values("transaction_time"),
    num_examples_per_instance=-1,
    minimum_data="2014-01-01",
)

Consecutive - Data Slice #1

By printing this data slice, you can see that that it is the first slice of transactions (denoted by the slice_number) for customer 1. This data slice contains all of the customer’s transactions that occurred within the 2-hour window between 2014-01-01 00:00:00 and 2014-01-01 02:00:00. You can also see that the 2-hour gap aligns the cutoff times to the window, so the next data slice starts at the end of this data slice.

[6]:
ds = next(slices)
print(ds.context)
ds
customer_id                       1
slice_number                      1
slice_start     2014-01-01 00:00:00
slice_stop      2014-01-01 02:00:00
next_start      2014-01-01 02:00:00
[6]:
transaction_id session_id product_id amount customer_id device
transaction_time
2014-01-01 00:45:30 275 4 5 108.11 1 mobile
2014-01-01 00:46:35 101 4 5 112.53 1 mobile
2014-01-01 00:47:40 80 4 5 6.29 1 mobile
2014-01-01 00:52:00 163 4 5 31.37 1 mobile
2014-01-01 00:53:05 293 4 5 82.88 1 mobile
2014-01-01 00:57:25 103 4 5 20.79 1 mobile
2014-01-01 01:03:55 488 4 5 129.00 1 mobile
2014-01-01 01:05:00 413 4 5 119.98 1 mobile
2014-01-01 01:31:00 191 6 5 139.23 1 tablet
2014-01-01 01:37:30 372 6 5 114.84 1 tablet
2014-01-01 01:38:35 387 6 5 49.71 1 tablet

Apply the labeling function for the total amount spent on this data slice.

[7]:
total_spent(ds)
[7]:
914.7300000000001

Consecutive - Data Slice #2

In the second data slice, you can see the next 2 consecutive hours of transactions between 2014-01-01 02:00:00 and 2014-01-01 04:00:00. This is useful for generating labels that consecutively process the data only once.

[8]:
ds = next(slices)
print(ds.context)
ds
customer_id                       1
slice_number                      2
slice_start     2014-01-01 02:00:00
slice_stop      2014-01-01 04:00:00
next_start      2014-01-01 04:00:00
[8]:
transaction_id session_id product_id amount customer_id device
transaction_time
2014-01-01 02:28:25 287 9 5 50.94 1 desktop
2014-01-01 03:29:05 190 14 5 110.52 1 tablet
2014-01-01 03:39:55 7 14 5 107.42 1 tablet

Apply our labeling function for the total amount spent on this data slice.

[9]:
total_spent(ds)
[9]:
268.88

Overlap

When the the gap size is less than the window size, the data slices overlap. You can use this for rolling window based labeling processes. The amount of overlap is the difference between the window and gap size. For example, if the window size is 3 hours and the gap size is 1 hour, then 2 hours will overlap on each data slice. To demonstrate this example, generate data slices using these parameters.

To start, create a label maker with the 3-hour window size.

[10]:
lm = cp.LabelMaker(
    target_dataframe_index="customer_id",
    time_index="transaction_time",
    labeling_function=total_spent,
    window_size="3h",
)

Next, create a data slice generator with the 1-hour gap size.

[11]:
slices = lm.slice(
    df.sort_values("transaction_time"),
    num_examples_per_instance=-1,
    minimum_data="2014-01-01",
    gap="1h",
)

Overlap - Data Slice #1

The first data slice contains all of the customer’s transactions that occurred within the 3-hour window between 2014-01-01 00:00:00 and 2014-01-01 03:00:00. The 1-hour gap spaces apart the cutoff time of this data slice at 2014-01-01 00:00:00 from the cutoff time of the next data slice at 2014-01-01 01:00:00.

[12]:
ds = next(slices)
print(ds.context)
ds
customer_id                       1
slice_number                      1
slice_start     2014-01-01 00:00:00
slice_stop      2014-01-01 03:00:00
next_start      2014-01-01 01:00:00
[12]:
transaction_id session_id product_id amount customer_id device
transaction_time
2014-01-01 00:45:30 275 4 5 108.11 1 mobile
2014-01-01 00:46:35 101 4 5 112.53 1 mobile
2014-01-01 00:47:40 80 4 5 6.29 1 mobile
2014-01-01 00:52:00 163 4 5 31.37 1 mobile
2014-01-01 00:53:05 293 4 5 82.88 1 mobile
2014-01-01 00:57:25 103 4 5 20.79 1 mobile
2014-01-01 01:03:55 488 4 5 129.00 1 mobile
2014-01-01 01:05:00 413 4 5 119.98 1 mobile
2014-01-01 01:31:00 191 6 5 139.23 1 tablet
2014-01-01 01:37:30 372 6 5 114.84 1 tablet
2014-01-01 01:38:35 387 6 5 49.71 1 tablet
2014-01-01 02:28:25 287 9 5 50.94 1 desktop

Apply our labeling function for the total spent on this data slice.

[13]:
total_spent(ds)
[13]:
965.6700000000001

Overlap - Data Slice #2

In the second data slice, there is a 2-hour overlap on the transactions that occurred between 2014-01-01 01:00:00 and 2014-01-01 03:00:00. By adjusting the gap size, you can set the precise amount of overlap in the data slices. That is useful for generating labels with specific overlap.

[14]:
ds = next(slices)
print(ds.context)
ds
customer_id                       1
slice_number                      2
slice_start     2014-01-01 01:00:00
slice_stop      2014-01-01 04:00:00
next_start      2014-01-01 02:00:00
[14]:
transaction_id session_id product_id amount customer_id device
transaction_time
2014-01-01 01:03:55 488 4 5 129.00 1 mobile
2014-01-01 01:05:00 413 4 5 119.98 1 mobile
2014-01-01 01:31:00 191 6 5 139.23 1 tablet
2014-01-01 01:37:30 372 6 5 114.84 1 tablet
2014-01-01 01:38:35 387 6 5 49.71 1 tablet
2014-01-01 02:28:25 287 9 5 50.94 1 desktop
2014-01-01 03:29:05 190 14 5 110.52 1 tablet
2014-01-01 03:39:55 7 14 5 107.42 1 tablet

Apply our labeling function for the total spent on this data slice.

[15]:
total_spent(ds)
[15]:
821.6400000000001

Spread Out

When the the gap size is greater than the window size, there is data in-between data slices that is skipped. You can use this for labeling data at specific intervals of time. The amount of data skipped is the difference between the gap and window size. For example, if the gap size is 3 hours and the window size is 1 hour, then 2 hours of data will be skipped in-between data slices. To demonstrate this example, generate data slices using these parameters.

To start, create a label maker with the 1-hour window size.

[16]:
lm = cp.LabelMaker(
    target_dataframe_index="customer_id",
    time_index="transaction_time",
    labeling_function=total_spent,
    window_size="1h",
)

Next, create a data slice generator with the 3-hour gap size.

[17]:
slices = lm.slice(
    df.sort_values("transaction_time"),
    num_examples_per_instance=-1,
    minimum_data="2014-01-01",
    gap="3h",
)

Spread Out - Data Slice #1

The first data slice contains all of the customer’s transactions that occurred within the 1-hour window between 2014-01-01 00:00:00 and 2014-01-01 01:00:00. The 3-hour gap spaces apart the cutoff time of this data slice at 2014-01-01 00:00:00 from the cutoff time of the next data slice at 2014-01-01 03:00:00.

[18]:
ds = next(slices)
print(ds.context)
ds
customer_id                       1
slice_number                      1
slice_start     2014-01-01 00:00:00
slice_stop      2014-01-01 01:00:00
next_start      2014-01-01 03:00:00
[18]:
transaction_id session_id product_id amount customer_id device
transaction_time
2014-01-01 00:45:30 275 4 5 108.11 1 mobile
2014-01-01 00:46:35 101 4 5 112.53 1 mobile
2014-01-01 00:47:40 80 4 5 6.29 1 mobile
2014-01-01 00:52:00 163 4 5 31.37 1 mobile
2014-01-01 00:53:05 293 4 5 82.88 1 mobile
2014-01-01 00:57:25 103 4 5 20.79 1 mobile

Apply our labeling function for the total spent on this data slice.

[19]:
total_spent(ds)
[19]:
361.96999999999997

Spread Out - Data Slice #2

In the second data slice, you can see that 2 hours of transactions were skipped between 2014-01-01 01:00:00 and 2014-01-01 03:00:00. By adjusting the gap size, you can set the precise amount of data to skip in-between data slices. That is useful for generating labels that target specific portions of a dataset.

[20]:
ds = next(slices)
print(ds.context)
ds
customer_id                       1
slice_number                      2
slice_start     2014-01-01 03:00:00
slice_stop      2014-01-01 04:00:00
next_start      2014-01-01 06:00:00
[20]:
transaction_id session_id product_id amount customer_id device
transaction_time
2014-01-01 03:29:05 190 14 5 110.52 1 tablet
2014-01-01 03:39:55 7 14 5 107.42 1 tablet

Apply the labeling function for the total spent on this data slice.

[21]:
total_spent(ds)
[21]:
217.94

Data Slice Context

Each data slice has a context attribute to access its metadata. That is useful for integrating the context with the logic in the labeling function.

[22]:
vars(ds.context)
[22]:
{'next_start': Timestamp('2014-01-01 06:00:00'),
 'slice_stop': Timestamp('2014-01-01 04:00:00'),
 'slice_start': Timestamp('2014-01-01 03:00:00'),
 'slice_number': 2,
 'customer_id': 1}