CustomFeatureExtractor インターフェース
名前空間
使用方法
カスタム特徴抽出インターフェースは、特徴抽出パラメータを入力として取り、使用事例に応じて必要なビジネスロジックを実行し、抽出された特徴を <key,value> の対応付けとして返します。対応付けのキーとしては次のものが想定されています。
- columnNames:List<String> — モデルに必要な入力特徴名です。
- rawData:List<List<String>> — 各特徴の値を同じ順序で含む二次元配列と、複数レコードの一括特徴取得用の二次元配列。
不動産物件の価格を予測する ML の使用事例について考えてみましょう。これを実行するには、ML モデルに物件の平方フィート、場所、寝室の数、建築年、築年数などの特徴が必要になります。築年数以外のすべての特徴が物件レコードにあるとします。この場合、AI アクセラレータ API は特徴抽出を呼び出して、実行時に現在の年から建築年を引くことで築年数を計算します。特徴抽出では、さまざまなエンティティを結合したり、一定期間のデータの合計や平均を計算したりといった複雑なロジックも使用できます。
カスタム特徴抽出インターフェース実装の動作は、使用事例設定ファイルで設定される FeatureExtractorType プロパティの値によって異なります。
- Apex — デフォルトの特徴抽出実装がカスタム特徴抽出実装で上書きされます。
- Hybrid (ハイブリッド) — デフォルトの特徴抽出実装が使用され、カスタム特徴抽出実装によって拡張できます。
- Java — デフォルトの特徴抽出実装がカスタム特徴抽出実装で上書きされます。
カスタム特徴抽出のインターフェースを実装するときの考慮事項は次のとおりです。
- すべての実装はパラメータを対応付けの recordList と以前抽出された特徴の対応付けとして受け取ります。
- 特徴抽出に複数の Apex クラスが含まれている場合や複数のクラス間で中間の抽出特徴を渡す必要がある場合、実装はパラメータを以前抽出された特徴の対応付けとして受け取ります。
- 使用事例の実装に入力パラメータの検証を追加します。検証では必須キーや実装に必要な列の存在を確認します。
- すべての実装で、新しく抽出した特徴を以前抽出した特徴とマージし、マージした出力を返す必要があります。以前抽出された特徴は null になる場合もあります。
- 使用事例に複数の実装の順次実行または並列実行が必要な場合は、必要な特徴抽出を呼び出すラッパーを提供します。ラッパークラス名を設定ファイル内に記述します。
- 使用事例によっては、抽出すべき特徴が少なく、その他の値を入力要求で未加工データとして提供する必要があることがあります。そのような使用事例の実装では、抽出された特徴と未加工データの値をマージして最終的な出力を提供する必要があります。
- Java とハイブリッドの特徴抽出では、すべての Java 実装クラスで、パラメータを渡すことを必要とせずにデフォルトのコンストラクタを公開する必要があります。
- AI アクセラレータプラットフォームでは、特徴抽出実装の出力の対応付けを検証して、未加工データと列名の空で���いリストが含まれていることを確認します。
- 未加工データはリストのリストであり、内側の各リストがレコードの特徴の値を表します。外側のリストは一括抽出をサポートします。
- 列名には特徴名のリストが保存されます。
CustomFeatureExtractor のメソッド
CustomFeatureExtractor のメソッドは次のとおりです。
extractFeatures(var1, var2)
署名
public Map<String,Object> extractFeatures(List<Map<String,Object>> var1, Map<String,Object> var2)
パラメータ
- var1
- 型: List<Map<String,Object>>
- 特徴抽出を行うための入力パラメータを表します。たとえば、特徴抽出の実装ロジック���従って DB クエリに必要な recordId などです。
- var2
- 型: Map<String,Object>
- 特徴抽出に複数のクラスが関与している場合に、以前抽出された特徴の対応付けを表します。これは、使用事例設定ファイルの FeatureExtractorType 設定で Hybrid が指定されており、カスタム特徴抽出の実装によってデフォルトの特徴抽出の実装が拡張される場合に適用されます。
戻り値
型: Map<String,Object>
CustomFeatureExtractor の実装例
これは、aiaccelerator.CustomFeatureExtractor インターフェースの実装例です。
- この特徴抽出実装はテスト実装です。実際には DB クエリを実行せず、最終出力で返される rawData の対応付けにすべてが存在することを想定しています。
- 特徴抽出パラメータには rawData キーが含まれています。これは、いくつかの特徴の値を直接渡すために使用できます (該当する場合)。
- 実際には、storeId や productId などのキーを特徴導出のための DB クエリ内でパラメータとして使用できます。rawData のキーと値は抽出された特徴とマージできます。
1global virtual class SampleCustomFeatureExtractor implements CustomFeatureExtractor {
2
3 private static final String RAW_DATA = 'rawData';
4 private static final String COL_NAMES = 'columnNames';
5
6 /**
7 * A Sample implementation that extracts "rawData" key from the map
8 * and prepares response of columnNames list and rawData list of list.
9 * @request:
10 * [{
11 * "storeId":"st1",
12 * "productId":"p1",
13 * "rawData":{
14 * "storeCategory":"PREMIUM"
15 * "day": MONDAY
16 * }
17 * }]
18 * @return
19 * {
20 * "rawData":[[PREMIUM, MONDAY]]
21 * "columnNames": ["storeCategory", "day"]
22 * }
23 * */
24 global virtual Map<String,Object> extractFeatures(List<Map<String,Object>> request, Map<String,Object> extractedFeatures) {
25 if (request == null || request.size() == 0) {
26 return extractedFeatures;
27 }
28 Set<String> cols = new Set<String>();
29 List<List<String>> rawDataList = new List<List<String>>();
30
31 //iterating list
32 for (Map<String, Object> record: request) {
33
34 //iterating outer map
35 for (String key: record.keySet()) {
36 List<String> row = new List<String>();
37
38 //extract rawData and add to output features
39 if ('rawData' == key) {
40 Object value = record.get(key);
41 if (value instanceof Map<String,Object>) {
42 Map<String,Object> raw = (Map<String, Object>) value;
43 for (String keyRawData: raw.keySet()) {
44 cols.add(keyRawData);
45 row.add((String) raw.get(keyRawData));
46 }
47 }
48 rawDataList.add(row);
49 }
50 }
51
52 }
53
54 return mergeFeatures(extractedFeatures, new List<String>(cols), rawDataList);
55 }
56
57 private Map<String, Object> mergeFeatures(Map<String, Object> extractedFeatures, List<String> columnNames, List<List<String>> rawDataList) {
58 Map<String, Object> features = new Map<String, Object>();
59 if (extractedFeatures == null || extractedFeatures.isEmpty() || extractedFeatures.get(COL_NAMES) == null
60 || extractedFeatures.get(RAW_DATA) == null) {
61 features.put(COL_NAMES, columnNames);
62 features.put(RAW_DATA, rawDataList);
63 return features;
64 }
65 if (columnNames.isEmpty()) {
66 return extractedFeatures;
67 }
68 List<String> oldCols = (List<String>) extractedFeatures.get(COL_NAMES);
69 List<List<String>> oldRows = (List<List<String>>) extractedFeatures.get(RAW_DATA);
70 List<String> extractedCols = new List<String>();
71 List<List<String>> extractedRows = new List<List<String>>();
72 extractedCols.addAll(oldCols);
73 extractedCols.addAll(columnNames);
74
75 for (Integer i = 0; i < rawDataList.size(); i++) {
76 List<String> mergedRow = new List<String>();
77 mergedRow.addAll(oldRows.get(i));
78 mergedRow.addAll(rawDataList.get(i));
79 extractedRows.add(mergedRow);
80 }
81 features.put(COL_NAMES, extractedCols);
82 features.put(RAW_DATA, extractedRows);
83 return features;
84 }
85}