处理异构语义类型
PyTorch Frame 支持多种异构的 stypes
,包括但不限于 multicategorical
、timestamp
和 embedding
。
在本教程中,我们将向您展示一个使用 PyTorch Frame 处理异构数据类型的简单示例。
处理异构列
首先,让我们创建一个包含许多不同样本类型的数据集。
import random
import numpy as np
import pandas as pd
# Numerical column
numerical = np.random.randint(0, 100, size=10)
# Categorical column
simple_categories = ['Type 1', 'Type 2', 'Type 3']
categorical = np.random.choice(simple_categories, size=100)
# Timestamp column
time = pd.date_range(start='2023-01-01', periods=100, freq='D')
# Multicategorical column
categories = ['Category A', 'Category B', 'Category C', 'Category D']
multicategorical = [
random.sample(categories, k=random.randint(0, len(categories)))
for _ in range(100)
]
# Embedding column (assuming an embedding size of 5 for simplicity)
embedding_size = 5
embedding = np.random.rand(100, embedding_size)
# Create the DataFrame
df = pd.DataFrame({
'Numerical': numerical,
'Categorical': categorical,
'Time': time,
'Multicategorical': multicategorical,
'Embedding': list(embedding)
})
df.head()
>>>
Numerical Categorical Time Multicategorical Embedding
0 44 Type 2 2023-01-01 [Category D, Category A, Category B] [0.2879910043632805, 0.38346222503494787, 0.74...
1 47 Type 2 2023-01-02 [Category C, Category A, Category B, Category D] [0.0923738894608982, 0.3540466620838102, 0.551...
2 64 Type 2 2023-01-03 [Category D, Category C] [0.3209972413734975, 0.22126268518378278, 0.14...
3 67 Type 1 2023-01-04 [Category C, Category A] [0.2603409275874047, 0.5370225213757797, 0.447...
4 67 Type 2 2023-01-05 [Category A] [0.46924917399024213, 0.8411401297855995, 0.90...
现在让我们将pandas.DataFrame
加载到torch_frame.data.Dataset
类中,以便我们可以从中生成TensorFrame
表示。
dataset = Dataset(
df, col_to_stype={
'Numerical': stype.numerical,
'Categorical': stype.categorical,
'Time': stype.timestamp,
'Multicategorical': stype.multicategorical,
'Embedding': stype.embedding
})
dataset.materialize()
dataset.tensor_frame
>>> TensorFrame(
num_cols=4,
num_rows=100,
categorical (1): ['Categorical'],
timestamp (1): ['Time'],
multicategorical (1): ['Multicategorical'],
embedding (1): ['Embedding'],
has_target=True,
device='cpu',
)
对于每个stype
,我们需要在stype_encoder_dict
中指定其编码器。
from torch_frame.nn import (
EmbeddingEncoder,
LinearEmbeddingEncoder,
LinearEncoder,
MultiCategoricalEmbeddingEncoder,
TimestampEncoder,
)
stype_encoder_dict = {
stype.categorical: EmbeddingEncoder(),
stype.numerical: LinearEncoder(),
stype.embedding: LinearEmbeddingEncoder(),
stype.multicategorical: MultiCategoricalEmbeddingEncoder(),
stype.timestamp: TimestampEncoder()
}
现在我们可以为选择的模型指定stype_encoder_dict
。
注意
一些预实现的模型不支持所有的stypes
。
例如,TabTransformer
仅支持数值和分类的stypes
。
from torch_frame.nn.models.ft_transformer import FTTransformer
model = FTTransformer(
channels=16,
out_channels=1,
num_layers=2,
col_stats=dataset.col_stats,
col_names_dict=dataset.tensor_frame.col_names_dict,
stype_encoder_dict=stype_encoder_dict,
)
model(dataset.tensor_frame)
>>> tensor([[ 0.9405],
[ 0.3857],
[ 0.5265],
[-0.3747],
[ 0.7496],
[ 0.0486],
[ 0.2895],
[ 0.1326],
[ 0.4388],
[-0.1665]], grad_fn=<AddmmBackward0>)
语义类型的自动推断
我们提供了一个简单的实用函数 infer_df_stype
来自动推断提供的 DataFrame
中不同列的 stype
。
infer_df_stype(df)
>>> {'Numerical': <stype.numerical: 'numerical'>,
'Categorical': <stype.categorical: 'categorical'>,
'Time': <stype.timestamp: 'timestamp'>,
'Multicategorical': <stype.multicategorical: 'multicategorical'>,
'Embedding': <stype.embedding: 'embedding'>}
然而,推理可能并不总是对你的数据正确/最佳。 我们建议你在继续之前自己再次检查正确性。
处理复杂的原始数据
通常,来自数据集的原始数据可能很复杂。 例如,不同的多类别列可能具有不同的分隔符,不同的时间列可能具有不同的时间格式。
目前,支持类型为list
或str
的原始列数据用于multicategorical
。
您还可以通过torch_frame.data.Dataset
中的col_to_sep
参数为不同的列指定不同的分隔符。
如果指定了一个字符串,则所有多类别列将使用相同的分隔符。
如果提供了一个字典,我们将为每列使用指定的不同分隔符。
注意
您需要为所有多类别列指定分隔符,其中原始数据是str
,否则每个单元格的值将被视为一个类别值。
这是一个处理具有多个多类别列的DataFrame
的示例。
categories = ['Category A', 'Category B', 'Category C', 'Category D']
multicategorical1 = [
random.sample(categories, k=random.randint(0, len(categories)))
for _ in range(100)
]
multicategorical2 = [
','.join(random.sample(categories, k=random.randint(0, len(categories))))
for _ in range(100)
]
multicategorical3 = [
'/'.join(random.sample(categories, k=random.randint(0, len(categories))))
for _ in range(100)
]
# Create the DataFrame
df = pd.DataFrame({
'Multicategorical1': multicategorical1,
'Multicategorical2': multicategorical2,
'Multicategorical3': multicategorical3,
})
dataset = Dataset(
df, col_to_stype={
'Multicategorical1': stype.multicategorical,
'Multicategorical2': stype.multicategorical,
'Multicategorical3': stype.multicategorical,
}, col_to_sep={'Multicategorical2': ',', 'Multicategorical3': '/'})
dataset.col_stats
>>>> {'Multicategorical1': {<StatType.MULTI_COUNT: 'MULTI_COUNT'>:
(['Category B', 'Category D', 'Category A', 'Category C'], [61, 60, 56, 49])},
'Multicategorical2': {<StatType.MULTI_COUNT: 'MULTI_COUNT'>:
(['Category D', 'Category A', 'Category B', 'Category C'], [53, 52, 51, 46])},
'Multicategorical3': {<StatType.MULTI_COUNT: 'MULTI_COUNT'>:
(['Category D', 'Category B', 'Category C', 'Category A'], [52, 52, 51, 46])}}
对于timestamp
,您可以类似地在col_to_time_format
中指定时间格式。
有关支持的格式的更多信息,请参阅strfttime文档。
如果未指定,将使用pandas
内部的to_datetime()
函数自动解析时间列。
dates = pd.date_range(start="2023-01-01", periods=5, freq='D')
df = pd.DataFrame({
'Time1': dates, # ISO 8601 format (default)
'Time2': dates.strftime('%Y-%m-%d %H:%M:%S'),
})
df.head()
>>> Time1 Time2
0 2023-01-01 2023-01-01 00:00:00
1 2023-01-02 2023-01-02 00:00:00
2 2023-01-03 2023-01-03 00:00:00
3 2023-01-04 2023-01-04 00:00:00
4 2023-01-05 2023-01-05 00:00:00
dataset = Dataset(
df, col_to_stype={
'Time1': stype.timestamp,
'Time2': stype.timestamp,
}, col_to_time_format='%Y-%m-%d %H:%M:%S')
dataset.materialize()
dataset.col_stats
>>> {'Time1': {<StatType.YEAR_RANGE: 'YEAR_RANGE'>: [2023, 2023],
<StatType.NEWEST_TIME: 'NEWEST_TIME'>: tensor([2023, 0, 4, 3, 0, 0, 0]),
<StatType.OLDEST_TIME: 'OLDEST_TIME'>: tensor([2023, 0, 0, 6, 0, 0, 0]),
<StatType.MEDIAN_TIME: 'MEDIAN_TIME'>: tensor([2023, 0, 2, 1, 0, 0, 0])},
'Time2': {<StatType.YEAR_RANGE: 'YEAR_RANGE'>: [2023, 2023],
<StatType.NEWEST_TIME: 'NEWEST_TIME'>: tensor([2023, 0, 4, 3, 0, 0, 0]),
<StatType.OLDEST_TIME: 'OLDEST_TIME'>: tensor([2023, 0, 0, 6, 0, 0, 0]),
<StatType.MEDIAN_TIME: 'MEDIAN_TIME'>: tensor([2023, 0, 2, 1, 0, 0, 0])}}