FG (FeatureGenerator) は、生データをモデル用の特徴量に変換するプロセスです。このプロセスにより、オフラインとオンラインのサンプル生成からの出力の一貫性が保証されます。特徴量生成では、さまざまな種類の FG オペレーターを使用して、1 つ以上の特徴量を変換します。
特徴量生成は、オフラインとオンラインの両方のサンプル生成で必要な変換のみに焦点を当てています。変換がオフライン段階でのみ必要な場合は、FG 操作として定義しないでください。次の図は、推薦システムのアーキテクチャ内での FG モジュールの位置を示しています。
特徴量生成プロセスは、一連の特徴量変換オペレーター (FG オペレーター) で構成されます。これらのオペレーターは、設定ファイルで定義された有向非巡回グラフ (DAG) のトポロジーに従って並列に実行されます。
設定ファイルの例
features リストは、特徴量オペレーターを設定するために使用されます。各特徴量オペレーターには、feature_name と feature_type を含める必要があります。他の設定項目に関する詳細については、「組み込み特徴量オペレーター」をご参照ください。
reserves 設定項目は、オフラインタスク中にパススルーするフィールドを指定します。これらのフィールドは、特徴量変換なしで直接出力されます。
{
"features": [
{
"feature_name": "goods_id",
"feature_type": "id_feature",
"value_type": "string",
"expression": "item:goods_id",
"default_value": "-1024",
"need_prefix": false
},
{
"feature_name": "color_pair",
"feature_type": "combo_feature",
"value_type": "string",
"expression": ["user:query_color", "item:color"],
"default_value": "",
"need_prefix": false
},
{
"feature_name": "current_price",
"feature_type": "raw_feature",
"value_type": "double",
"expression": "item:current_price",
"default_value": "0",
"need_prefix": false
},
{
"feature_name": "usr_cate1_clk_cnt_1d",
"feature_type": "lookup_feature",
"map": "user:usr_cate1_clk_cnt_1d",
"key": "item:cate1",
"need_discrete": false,
"need_key": false,
"default_value": "0",
"combiner": "max",
"need_prefix": false,
"value_type": "double"
},
{
"feature_name": "recommend_match",
"feature_type": "overlap_feature",
"method": "is_contain",
"query": "user:query_recommend",
"title": "item:recommend",
"default_value": "0"
},
{
"feature_name": "norm_title",
"feature_type": "text_normalizer",
"expression": "item:title",
"max_length": 512,
"parameter": 0,
"remove_space": false,
"is_gbk_input": false,
"is_gbk_output": false
},
{
"feature_name": "title_terms",
"feature_type": "tokenize_feature",
"expression": "feature:norm_title",
"default_value": "",
"vocab_file": "tokenizer.json",
"output_type": "word_id",
"output_delim": ","
},
{
"feature_name": "query_title_match_ratio",
"feature_type": "overlap_feature",
"method": "query_common_ratio",
"query": "user:query_terms",
"title": "feature:title_terms",
"default_value": "0"
},
{
"feature_name": "title_term_match_ratio",
"feature_type": "overlap_feature",
"method": "title_common_ratio",
"query": "user:query_terms",
"title": "feature:title_terms",
"default_value": "0"
},
{
"feature_name": "term_proximity_min_cover",
"feature_type": "overlap_feature",
"method": "proximity_min_cover",
"query": "user:query_terms",
"title": "feature:title_terms",
"default_value": "0"
}
],
"input_alias": {
"non_exist_field1": "exist_field1",
"non_exist_field2": "exist_field2"
},
"reserves": [
"request_id",
"user_id",
"is_click",
"is_pay",
"sample_weight",
"event_unix_time"
]
}input_alias 設定項目は、特徴量の入力名をマッピングする辞書です。存在しない可能性のあるフィールド名を実際のフィールド名にマッピングします。注意:input_alias 設定はバージョン 1.0.0 からサポートされています。通常、この設定は省略できます。
ユースケース 1:長いフィールド名に短いエイリアスを設定する。
ユースケース 2:カスタム特徴量オペレーターが同じパラメーターを 2 回使用する場合に、2 番目のインスタンスにエイリアスを設定する。
同じ入力フィールドは、異なる特徴量間で再利用できますが、単一の特徴量変換内では再利用できません。この制限を回避するために input_alias を設定できます。
たとえば、カスタム特徴量オペレーターが 2 つの異なる入力パラメーターに対して同じフィールド
Aを必要とする場合、2 つの入力AとBを設定し、input_aliasを設定して"B": "A"をマッピングできます。実行中、フレームワークはカスタム特徴量オペレーターのパラメーターを (A, B) から (A, A) に置き換えます。
入力ドメイン
入力ドメインは、入力のソースエンティティを示します。次の 4 種類がサポートされています。
user:ユーザー側の特徴量。ユーザープロファイルやユーザーディメンションの統計的特徴量など。
context:時間、場所、天気など、頻繁に変化するコンテキスト特徴量。
item:アイテム側の特徴量。静的コンテンツ特徴量やアイテムディメンションの統計的特徴量など。
feature:現在の入力が別の特徴量変換の出力であることを示します。
特徴量の入力ドメインは、特徴量オペレーター間の依存関係を設定するために使用され、これにより DAG が形成されます。フレームワークは、これらの特徴量変換をトポロジー順に従って並列に実行します。次の図は、結果として得られるトポロジーを示しています。
デフォルトでは、DAG の中間ノードの出力は最終的な FG 出力に含まれません。この動作を変更するには、stub_type 設定項目を使用します。
複数値の型と区切り文字
FG は、MaxCompute の複合型と一致する、Array や Map などの複雑な入力型をサポートしています。
複数値の文字列特徴量には、chr(29) 区切り文字を使用できます。
たとえば、v1^]v2^]v3 では、^] は複数値の区切り文字を表します。これは 2 文字ではなく、ASCII コード "\x1D" を持つ 1 文字です。Emacs でこの文字を入力するには、C-q C-5 を押します。vi では、C-v C-5 を押します。
特徴量ビニング (離散化)
フレームワークは、次の 6 種類のビニング操作をサポートしています。
hash_bucket_size:特徴量変換の結果をハッシュ化し、剰余演算を実行します。
vocab_list:特徴量変換の結果をリスト内のインデックスに変換します。
vocab_dict:特徴量変換の結果を辞書内の値に変換します。値は int64 型に変換可能である必要があります。
vocab_file:ファイルから vocab_list または vocab_dict を読み取ります。
boundaries:ビニングの境界を指定し、特徴量変換の結果を対応するバケット ID に変換します。
num_buckets:特徴量変換の結果を直接ビニングバケット ID として使用します。
hash_bucket_size
特徴量変換の結果をハッシュ化し、剰余演算を実行します。これは、あらゆる型の特徴量値に適用されます。
結果の範囲:[0,
hash_bucket_size)空の特徴量のビニング結果は
hash(default_value)%hash_bucket_sizeです。
{
"hash_bucket_size": 128000,
"default_value": "default value"
}vocab_list
語彙リストに基づいてビニングを実行します。入力を語彙内のインデックスにマッピングします。ビニング結果は、vocab_list 配列内の特徴量値のインデックスです。
vocab_list配列の要素の型は、設定されたvalue_typeと同じである必要があります。num_oov_bucket:語彙外 (OOV) バケットの数を指定する非負の整数。すべての語彙外入力には、入力値のハッシュに基づいて [vocabulary_size, vocabulary_size+num_oov_bucket) の範囲の ID が割り当てられます。
default_bucketize_valueと共に正の num_oov_bucket を指定することはできません。
default_bucketize_value:語彙外の特徴量値に対して返される整数 ID 値。num_oov_bucketsが正の場合は指定できません。デフォルト値は
vocab_list.size()です。
{
"vocab_list": [
"",
"<OOV>",
"token1",
"token2",
"token3",
"token4"
],
"num_oov_bucket": 0,
"default_bucketize_value": 1
}vocab_dict
ビニング結果は、特徴量値に対応する vocab_dict 辞書の値です。これにより、異なる特徴量値を同じビニング結果にマッピングできます。
vocab_dict辞書のキーの型は、設定されたvalue_typeと同じである必要があります。vocab_dictの値はint64型に変換可能である必要があります。num_oov_bucket:語彙外バケットの数を指定する非負の整数。すべての語彙外入力には、入力値のハッシュに基づいて [vocabulary_size, vocabulary_size+num_oov_bucket) の範囲の ID が割り当てられます。
default_bucketize_valueと共に正の num_oov_bucket を指定することはできません。
default_bucketize_value:語彙外の特徴量値に対して返される整数 ID 値。num_oov_bucketsが正の場合は指定できません。デフォルト値は
vocab_dict.size()です。
{
"vocab_dict": {
"token1": 1,
"token2": 2,
"token3": 3,
"token4": 1
},
"num_oov_bucket": 0,
"default_bucketize_value": 4
}vocab_file
ファイルから vocab_list または vocab_dict を読み取ります。
{
"vocab_file": "vocab.txt",
"num_oov_bucket": 0,
"default_bucketize_value": 4
}vocab_file:ファイルパス。ファイルには語彙リストが含まれ、1 行に 1 つの語彙 term があります。オプションで、マッピングされた値を指定できます。
相対パスがサポートされています。オンラインサービスをデプロイする場合、ファイルを
fg.jsonと同じディレクトリに配置します。トークンのみが存在する場合、0 から始まる行番号にマッピングされます。値が存在する場合、トークンと値はスペースやタブなどの空白文字で区切られます。値は
int64型である必要があります。
num_oov_bucketとdefault_bucketize_valueの意味は、前述のとおりです。
boundaries
指定された境界に基づいて数値特徴量をビニングします。このメソッドは、境界によってバケット化された離散化された密な入力を表します。
boundaries配列の要素の型は、設定されたvalue_typeと同じである必要があります。バケットは左境界を含み、右境界を含みません。
たとえば、boundaries=[0., 1., 2.] は、(-inf, 0)、[0, 1)、[1, 2)、[2, +inf) のバケットを生成します。
{
"boundaries": [0.0, 1.0, 2.0],
"default_value": -1
}num_buckets
特徴量変換の結果を直接ビニングバケット ID として使用します。これは、特徴量値を整数に変換できる場合に適しています。
結果の範囲:[0,
num_buckets)特徴量値が設定された範囲外の場合、
default_bucketize_valueが割り当てられます。
{
"num_buckets": 128000,
"default_bucketize_value": 127999
}組み込み特徴量オペレーター
各特徴量オペレーターの設定方法は異なります。DAG のリーフノードになることができるすべての特徴量オペレーターは、特徴量ビニング設定をサポートしています。
詳細については、「組み込み特徴量オペレーター」をご参照ください。
特徴量の型 | 説明 |
id_feature | カテゴリ特徴量 |
raw_feature | 数値特徴量 |
expr_feature | 式特徴量 |
combo_feature | 組み合わせ特徴量 |
lookup_feature | 辞書ルックアップ特徴量 |
match_feature | 主キー-セカンダリキー辞書ルックアップ特徴量 |
overlap_feature | 重複特徴量 |
sequence_feature | シーケンス特徴量 |
text_normalizer | テキスト正規化 |
tokenize_feature | テキストトークン化特徴量 |
bm25_feature | BM25 テキスト関連度特徴量 |
kv_dot_product | KV ベクトル内積 |
str_replace_feature | 文字列置換 |
regex_replace_feature | 正規表現置換 |
slice_feature | 配列スライシング |
オペレーターの組み合わせ
DAG を設定することで、さまざまな組み込みオペレーターを組み合わせて、強力な特徴量変換を実行できます。
例 1:シーケンスの最初の 4 つの要素の平均を計算する
{
"features": [
{
"feature_name": "top_n_prices",
"feature_type": "sequence_raw_feature",
"expression": "user:clk_prices",
"separator": ",",
"sequence_length": 4,
"stub_type": true
},
{
"feature_name": "top_n_avg_price",
"feature_type": "expr_feature",
"expression":"reduce_mean(top_n_prices)",
"default_value": "-1",
"variables":["feature:top_n_prices"]
}
]
}例 2:シーケンス内で条件を満たす要素の平均を計算する
{
"features": [
{
"feature_name": "valid_list",
"feature_type": "expr_feature",
"expression":"clk_times < 10",
"variables":["user:clk_times"],
"value_dimension": 5
},
{
"feature_name": "top_n_prices",
"feature_type": "bool_mask_feature",
"expression": ["user:clk_prices", "feature:valid_list"],
"value_type": "float",
"separator": ","
},
{
"feature_name": "top_n_avg_price",
"feature_type": "expr_feature",
"expression":"reduce_mean(top_n_prices)",
"default_value": "-1",
"variables":["feature:top_n_prices"]
}
]
}注意:上記の例では、clk_prices と clk_times は 2 つの並列シーケンスです。
カスタム特徴量オペレーター
カスタム特徴量オペレーターは、プラグインとしてフレームワークによって動的にロードおよび実行できます。
詳細については、「カスタム特徴量オペレーター」をご参照ください。
パフォーマンス最適化のヒント
FG モジュールのパフォーマンスは、その設定と密接に関連しています。一般的な原則は、不要なデータ (特徴量) 変換を最小限に抑えることです。
データ処理と変換がオフラインまたはニアライン段階で実行できる場合は、FG 段階 (オンラインサービス) での実行を避けてください。
パフォーマンスを向上させるには、次のヒントに従ってください。
構造化された入力データには、STRING 型の代わりに、Map や Array などの MaxCompute テーブルの複合型を優先的に使用します。これにより、文字列解析のオーバーヘッドが削減されます。
EasyRec Processor や TorchEasyRec Processor などのオンラインサービスでは、オンラインストレージとして FeatureStore と FeatureDB を使用して、複合型のサポートを有効にします。
lookup_feature の場合、マップフィールドには Map 型を使用します。
sequence_feature、overlap_feature、および bm25_feature には、Array 型の入力を使用します。
match_feature は複合型をサポートしていないため、使用を避けてください。pkey と skey を組み合わせて lookup_feature を代わりに使用します。
データ型変換のオーバーヘッドを避けます。
特別な理由がない限り、raw_feature の
value_typeを float 以外の型に設定しないでください。lookup_feature の入力では、Map のキーの型がクエリフィールドの型と一致していることを確認してください。
num_buckets型の特徴量ビニングを設定する場合、value_typeをint64に設定します。データ列の最適な型がシナリオによって異なる場合は、異なる型のコピーを追加することを検討してください。
たとえば、ある列は
lookup_featureのクエリフィールドとして使用される場合は BIGINT 型である必要がありますが、combo_featureの一部として使用される場合は STRING 型である必要があります。この場合、適切な型の列のコピーを追加します。一方のコピーは BIGINT、もう一方は STRING にする必要があります。以下は SQL コードの例です。
SELECT int_data, int_data as str_data FROM ....
可能な限りコンポーネントを再利用するために、特徴量の依存関係 (DAG モード) を使用します。
グローバル設定
設定項目 | 型 | デフォルト値 | 説明 |
USE_CITY_HASH_TO_BUCKETIZE | string | 'false' | 特徴量ビニングのハッシュ関数として CityHash を使用するかどうかを指定します。 |
USE_MULTIPLICATIVE_HASH | string | 'false' | 特徴量ハッシュに剰余演算の代わりに乗法ハッシュを使用するかどうかを指定します。このオプションを有効にすることを推奨します。 |
DISABLE_FG_PRECISION | string | 'true' | 浮動小数点特徴量の精度制約を無効にするかどうかを指定します。無効にしない場合、FG は浮動小数点特徴量の小数点以下 6 桁のみを保持します。 |
DISABLE_STRING_TRIM | string | 'false' | 複数値の文字列特徴量を分割した後の先頭と末尾のスペースのトリミングを無効にするかどうかを指定します。 |
MONITOR_CUSTOM_OP_EVERY_N_SECONDS | string | '0' | カスタムオペレーターのパフォーマンスをモニターするかどうかを指定します。これは、パフォーマンスデータを表示する間隔 (秒) です。 |
IGNORE_CUSTOM_OP_EXCEPTION | string | 'false' | カスタムオペレーター内でスローされた例外を無視するかどうかを指定します。 |
注意:上記の設定は、オフラインとオンライン、トレーニングと推論を含むすべての実行環境で一貫している必要があります。そうしないと、オフライン環境とオンライン環境の間でスコアリングの不一致が発生する可能性があります。
ハッシュ衝突率
カーディナリティが異なる 26 の特徴量を持つ特定のデータセットで、各特徴量に対して hash_bucket_size をカーディナリティの 10 倍に設定しました。テスト結果は次のとおりです。
ハッシュの種類 | 合計特徴量カーディナリティ | 合計バケット数 | ハッシュ衝突率 |
std::hash | 882774549 | 840065238 | 4.8381% |
cityhash | 882774549 | 840072446 | 4.8373% |
std+cityhash | 882774549 | 840075948 | 4.8369% |
cityhash+multiplicative | 882774549 | 840072195 | 4.8373% |
std+multiplicative | 882774549 | 840077306 | 4.8367% |
まとめると、std::hash と MultiplicativeHash を組み合わせてモデルのパフォーマンスを最適化できます。std::hash はデフォルトで有効になっています。MultiplicativeHash は下位互換性を確保するためにデフォルトで無効になっています。使用するには、手動で有効にする必要があります。
さらに、CityHash は理論的にはより均一なハッシュ化メソッドですが、このデータセットでは大きな利点は見られませんでした。ご自身のデータセットでさらにテストすることができます。
オンラインスコアリングサービスの設定
これは、サーバー側の環境変数を介して設定できます。EasyRec Processor または TorchEasyRec Processor のサービス設定で設定できます。
{
"processor_envs": [
{
"name": "USE_MULTIPLICATIVE_HASH",
"value": "true"
}
]
}オフラインジョブの設定
MaxCompute 環境で FG オフラインタスクを実行するには、「オフラインタスクで FG を使用する」をご参照ください。
次のコードをご参照ください。
from pyfg100 import run_on_odps
fg_task = run_on_odps.FgTask(...)
fg_task.add_fg_setting('USE_CITY_HASH_TO_BUCKETIZE', 'false')
fg_task.add_fg_setting('USE_MULTIPLICATIVE_HASH', 'true')
fg_task.run(o)pyfg API を使用する場合の設定
pyfg API を使用する場合、たとえばトレーニング中に FG を実行する場合、次のように設定できます。
import pyfg
pyfg.set_env('USE_MULTIPLICATIVE_HASH', 'true')
pyfg.set_env('USE_CITY_HASH_TO_BUCKETIZE', 'false')