リアルタイムAI/MLアプリケーションの機能を開発する場合、貴重な洞察が得られる可能性があるため、データ内の時間ベースのパターンを理解することが重要です。ただし、一時的なクエリを表現すると課題が生じる可能性があります。直感的でシームレスな時間の処理を維持しながら、時間の経過に伴うユーザーの行動を簡単に分析し、正確な時間的結合を実行し、さまざまなイベント間のアクティビティのパターンを調査できる機能を想像してみてください。ここで、時間データを操作するための高レベルの抽象化であるタイムラインが非常に貴重であることがわかります。
この記事では、タイムラインの世界を深く掘り下げていきます。イベント、そして重要なことに、イベント間の一時的なクエリを簡単に表現できるだけでなく直感的に表現する方法を示します。この記事は、シリーズの 2 番目です。
直感的タイムラインは時間順に並べられているため、クエリも順番に動作するのが自然です。時間の経過とともに、追加のイベント (入力) が発生し、クエリの出力に反映されます。時間の経過に伴う計算についてのこの考え方は、私たちがイベントを観察する方法と一致するため、直感的です。
宣言的時間操作 (ウィンドウ処理やシフトなど) は、時間が抽象化の一部であるため、タイムラインを操作するときに明確に宣言されます。
コンポーザブルすべての操作はタイムラインを取得し、タイムラインを生成します。これは、意図した結果を生成するために必要に応じて操作を連鎖させることができることを意味します。
以下では、タイムラインの利点を示す 4 つの実際の例を詳しく説明します。集計のための単純なクエリから始めて、より複雑な時間ウィンドウ、データ依存ウィンドウ、および時間的に正しい結合に徐々に取り組んでいきます。最後には、タイムラインによって単純な一時的なクエリを SQL と同じくらい簡単に作成できるようになり、タイムラインによってどのようにしてより困難な質問に取り組むことができるようになるのかを深く理解できるようになっているはずです。
タイムラインはSQLで実行できるすべてをサポートし、長期にわたって操作できるように直感的に拡張されています。高度な一時クエリのためのいくつかの新機能を説明する前に、単純なもの、つまり集計について見てみましょう。単純なクエリを書くのは簡単です。実際、タイムラインは時間順に並べられ、エンティティごとにグループ化されているため、SQL よりもさらに簡単です。
各ユーザーがいくら使ったかという質問を考えてみましょう。これをイベントごとに考えると、購入を順番に処理し、各ユーザーが費やした金額を時間の経過とともに更新するのが自然です。結果は、連続的なタイムラインを生成する累積和になります。
対応するクエリを 2 つの同等の方法で記述したものを以下に示します。 1 つ目は、購入に適用される合計を強調し、2 つ目は、「購入を取得してから合計を適用する」という、私たちが構築した一連の操作を強調します。ここからは後者を使用します。これは、処理タイムラインについての考え方によく一致するためです。
sum(Purchases.amount)
#OR
Purchases.amount | sum()
タイムラインを使用した単純な一時クエリの作成は、SQL と同じくらい簡単でした。イベントを順番に処理することは、時間をかけて操作する直感的な方法です。もちろん、すべてのイベントを集計することは、集計方法の 1 つにすぎません。次の例では、時間ウィンドウを使用してこのクエリを拡張し、最近のイベントに焦点を当てる方法を見ていきます。
一時的なクエリについて考えるとき、最近の過去、つまり年初から今日までまたは過去 30 日間について質問するのは非常に自然です。イベントを順番に処理する直感から、「各ユーザーが今月いくら使ったか」という質問に答えるには、毎月の初めに値をリセットするだけで十分であることがわかります。そして、この直感は、まさにこの種の時間ウィンドウがタイムラインでどのように機能するかです。
一時的なクエリを以下に示します。これは、上で表明した意図を明確に示しています。つまり、毎月の初めからの購入を取得して集計します。
Purchases.amount
| sum(window=since(monthly()))
時間は本質的にすべてのタイムラインの一部であるため、すべての集計は時間ウィンドウ内で動作できます。次の例では、より洗練されたウィンドウを使用した集計など、より複雑なクエリを操作することがいかに簡単であるかを見ていきます。
すべてのウィンドウが時間に関して定義されているわけではありません。多くの場合、イベントを使用して集計に使用するウィンドウを決定すると便利です。さらに、これまでのすべての例は単一タイプのイベント ( purchases
を対象としていましたが、因果関係を特定するには、異なるイベント間のアクティビティのパターンを調査することが重要です。
この例では、タイムラインを利用して、データ定義のウィンドウと複数の種類のイベントを使用してクエリを宣言的に表現します。また、クエリの作成中に後のステップで使用される値を制御するために、中間タイムラインを特定のポイントにフィルター処理します。
私たちが答える質問は、「各ユーザーの各購入間の平均ページビュー数はどれくらいですか?」です。まず、最後の購入以降のページビューを計算し、各購入時にそれらを観察して、平均を取ります。
最初に行うことは、最後の購入以降のページビュー数を計算することです。前の例では、月の初めからウィンドウ化しました。ただし、月の始まりを定義するタイムラインには特別なことは何もありません。他のタイムラインとウィンドウを調整することができます。
PageViews
| count(window=since(is_valid(Purchases)))
データ定義のウィンドウ処理に加えて、複数の種類のイベントを処理する方法についても説明します。すべてのタイムラインは時間順に並べられ、エンティティごとにグループ化されているため、すべてのタイムラインを時間ごとに並べ、エンティティごとに自動的に結合できます。
前のステップでは、最後の購入以降のページビューが得られました。しかし、それは次の購入までページビューごとに増加する継続的なタイムラインでした。前回の購入以降のページビューを表す、各購入時の単一の値を持つ個別のタイムラインを求めています。これを行うには、 when
操作を使用します。これにより、特定の時点でタイムラインを観察し、必要に応じて補間することができます。
when 操作は一時クエリのどこでも使用でき、出力に存在するポイントをフィルタリングしたり、後の集計に渡したりすることができます。
購入間のページビュー数が計算されると、この値の平均を計算できるようになりました。必要なのは、 mean
集計を使用することだけです。
完全なクエリを以下に示します。この手順は、上で説明した論理的な手順と一致していることがわかります。ロジックはかなり複雑でしたが、クエリは比較的単純で、計算したい内容についてのアイデアを捉えています。難しい質問も可能です。
PageViews
| count(window=since(is_valid(Purchases)))
| when(is_valid(Purchases))
| mean()
この種のクエリは、ページ ビュー アクティビティのさまざまなパターンを分析するために一般化できます。おそらく、ユーザーはそのアイテムにさらに集中していると考えて、すべてのアイテムではなく、最も頻繁に表示されるアイテムのページ ビューのみを確認したいと考えます。おそらく、任意の購入ではなく、同じ商品の購入以来ウィンドウを表示したいと考えています。
このクエリは、タイムラインを使用して複雑な時間クエリを表現できる方法をいくつか示しました。
順序付けにより、グループ化のために各値から「ウィンドウ ID」を計算する必要がなく、ウィンドウの開始時と終了時の区切り文字によってウィンドウを定義できるようになります。
順序付けにより、同じ式内で複数のタイムライン (この場合は、 pageviews
とpurchases
を使用することもできます。
連続性により、任意の時点で値を補間し、 when
操作を使用してフィルタリングすることができます。
構成可能性により、任意の操作の結果を後の操作で使用して、一時的な質問を表現できるようになります。これにより、複雑な質問を一連の単純な操作として表現できるようになります。
これらの機能により、原因と結果のパターンを特定できます。今購入したことで後で購入することになるかもしれませんが、テープがなくなって追加購入したり、キャンプ旅行の予定を立てて買いだめしたりするなど、他のイベントの方がより強い関係があることもよくあります。他のイベント ( purchases
) によって定義されたウィンドウ内でアクティビティ ( pageviews
) を確認できることは、それらのイベント間の関係を理解するために重要です。
タイムラインを使用して、同じエンティティに関連付けられた複数の種類のイベントを操作できる方法をすでに説明しました。ただし、多くの場合、複数のエンティティとの連携も必要になります。たとえば、母集団全体に関する情報を使用して、各ユーザーの値を正規化します。最後の例では、複数のエンティティを操作し、一時的な結合を実行する方法を示します。
最後の質問は、「各購入時の製品レビューの最低平均値 (スコア) はどれくらいですか?」です。これを行うには、まず各製品に関連付けられたレビューを処理して平均スコアを計算し、次に各購入を対応する平均レビューと結合します。
まず、各項目の平均製品レビュー (スコア) を計算します。現在、レビューはユーザーごとにグループ化されているため、 with キー操作を使用して項目ごとに再グループ化する必要があります。それが完了したら、すでに見た平均集計を使用できます。
各購入 (ユーザーごとにグループ化) について、対応するアイテムの平均レビュー スコアを調べたいと考えています。これにはlookup
操作が使用されます。
すべてをまとめると、 min
集計によるルックアップを使用して、各ユーザーが購入したアイテムの最小平均評価を決定します。
Reviews.score
| with_key(Reviews.item)
| mean()
| lookup(Purchases.item)
| min()
別のエンティティに再グループ化し、集計を実行し、値を検索する (または元のエンティティに戻す) というこのパターンは、データ処理タスクでは一般的です。この場合、結果の値が検索されて直接使用されました。他の場合には、各ユーザーの値をその都市の平均値に関連付けるなど、正規化に役立ちます。
順序付けとグループ化により、タイムラインで異なるエンティティ間の操作を明確に表現できるようになります。ルックアップの結果は、ルックアップが実行された時点のものです。これにより、時間的に正しい「現在の」結合が提供されます。
正しいタイミングで結合を実行することは、モデルを適用するときに使用される特徴値と比較できる過去のトレーニング例を計算するために重要です。同様に、クエリの結果に対して実行されるダッシュボード、視覚化、または分析が、その時点では利用できなかった情報を使用するのではなく、あたかも過去の値を参照しているかのように実際に正しいことを保証します。
私たちは、時間データを処理するための高レベルの抽象化としてのタイムラインの力を実証しました。直感的で宣言的で構成可能な操作を通じて、タイムラインによってイベントおよびイベント間の一時的なクエリを効率的に表現できる方法を示しました。単純な集計から、データ依存ウィンドウや時間的に正しい結合などの高度なクエリまでの例を使用して、タイムライン操作を連鎖させて意図した結果を生成する方法を説明しました。タイムラインの有効性は、単純な時間的質問を簡単に表現し、複雑な時間的クエリに直感的に拡張できる能力にあります。
合計支出から最小レビュー スコアまで、時間クエリにおけるタイムラインの機能を強調する 4 つの具体例を説明しました。私たちは累積集計、時間的ウィンドウ処理を調査し、データ定義のウィンドウ処理が複雑な時間的質問を表現する機能をどのように提供するかを観察しました。また、タイムラインによって複数エンティティの処理と一時的な結合がどのように容易になるかについても説明しました。これらの例は、タイムラインを使用すると、原因と結果のパターンを特定し、モデルを適用するときに比較的有効なトレーニング サンプルを計算するための強力なツールがあることを示しています。
今後は、タイムライン上の一時クエリのダイナミクスをさらに詳しく掘り下げていきます。タイムラインのプロパティを利用して、これらのクエリがどのように効率的に実行されるかを調査します。\
ぜひお勧めします