[CEP] Extending Oracle CEP with Predictive Analytics

はじめに
CQLで記述したビジネスロジックのルールのセットを実行し、ルールの結果に基づいて判断するビジネスルールエンジンとして、Oracle CEPをご利用いただくことがよくあります。アプリケーションが小さく、かつよく定義された静的なルールだけを取り扱えばよい場合には、手でルールを構成しても十分だという場合もありますが、多くの場合は事前にルールを定めることを嫌います。その大きな理由は以下の2件です。
  • 多くの要素を持つイベントを扱うので、それぞれの要素や、要素を組み合わせたルールを手動で作成するのはほぼ不可能
  • 確率論の結果には満足しており、100%の正確性を求めてはいない
前者は高次元のデータを取り扱う場合を指し、後者はアプリケーションが”偽”陽性を許容する場合、つまりBPMソフトウェアのHuman Taskコンポーネントなどを使って、詳細なチェック後にその結果を破棄できるというような場合を指しています。

このエントリのゴールは、以下の2点を考えています。
  • Oracle CEPとOracle Data Mining®という豊富なアルゴリズムと機能を組み合わせ、リアルタイムのストリームイベントの予測分析を実現すること
  • Oracle CEPをJDBCカートリッジを使って機能拡張し、RDBMSにある外部の任意の計算処理を呼び出すことができること。
以降で手順を説明します。なお、利用したデータセットは以下のエントリにあります。このデータセットを使ってトランザクションの異常や不正を検知しています。

Fraud and Anomaly Detection Made Simple
http://blogs.oracle.com/datamining/2010/01/fraud_and_anomaly_detection_made_simple.html


モデルの作成
先ほどのURLにある説明に従い、モデルを作成します。Oracle Data Mining組み込みのPL/SQLパッケージを使って、クレンジング、正規化し、データセットからモデルを作成します。Oracle Data Miner® を使ってモデルをグラフィカルに作成することもできます。
まとめると以下のことをする、ということです。
  • 使用するアルゴリズムを決めましょう。
    • 今回の場合、Support Vector Machinesを使って高次元のデータセットから異常を発見しようと考えています。
  • 利用を決めたアルゴリズムのために、データモデルをTable(表)に作成しましょう。
このサンプルでは、適切な権限を持つ scott スキーマに表を配置しました。

データソースの構成
このような連携を使うCEPアプリケーションを作成する第一ステップです。今回利用する、サーバーの構成ファイル中に記載されているデータソースは以下のようになっています。手でファイルを編集するよりは、Visualizerを使って起動中のサーバーへ追加することをお勧めします。

   <data-source>
        <name>DataMining</name>
        <data-source-params>
            <jndi-names>
                <element>DataMining</element>
            </jndi-names>
            <global-transactions-protocol>OnePhaseCommit</global-transactions-protocol>
        </data-source-params>
        <connection-pool-params>
            <credential-mapping-enabled></credential-mapping-enabled>
            <test-table-name>SQL SELECT 1 from DUAL</test-table-name>
            <initial-capacity>1</initial-capacity>
            <max-capacity>15</max-capacity>
            <capacity-increment>1</capacity-increment>
        </connection-pool-params>
        <driver-params>
            <use-xa-data-source-interface>true</use-xa-data-source-interface>
            <driver-name>oracle.jdbc.OracleDriver</driver-name>
            <url>jdbc:oracle:thin:@localhost:1522:orcl</url>
            <properties>
                <element>
                    <value>scott</value>
                    <name>user</name>
                </element>
                <element>
                    <value>{Salted-3DES}AzFE5dDbO2g=</value>
                    <name>password</name>
                </element>
                                <element>
                    <name>com.bea.core.
datasource.serviceName</name>
                    <value>oracle11.2g</value>
                </element>
                <element>
                    <name>com.bea.core.
datasource.serviceVersion</name>
                    <value>11.2.0</value>
                </element>
                <element>
                    <name>com.bea.core.
datasource.serviceObjectClass</name>
                    <value>java.sql.Driver</value>
                </element>
            </properties>
        </driver-params>
    </data-source>

EPN (Event Processing Network) の設計
このサンプルで作るEPNは非常にシンプルです。
各コンポーネントについて説明します。
  • アダプタ(DataMiningAdapter)が.csvファイルからデータを読み取り、CQLプロセッサに流します。イベントのペイロードは、Databaseの表と同じ構造になっています。この例では便宜上こうしていますが、いつもこうする必要はありません。ストリーミングイベント中のフィールドを省くこともできますし、データモデルとして作成する表の列とすべて一致させる必要もありません。もっと言うと、マイニング関数のUSING句でエイリアスを指定している限り、表の列名と同じである必要もありません(警告:とはいえ、類似のドメインや母集団からデータを引き出す必要があります。さもなければモデルの誤った使い方を定めてしまいます)。
  • ストリームイベントの確率をはじき出す、CQLプロセッサ(”DataMiningProc”)には2個の処理が含まれています。
    1. ユーザー定義のカートリッジ関数
      Oracle CEP CQLリファレンスマニュアルに定義方法の詳細が記述されていますので、ご確認ください。説明のために以下に丸ごと記載します。

      <?
      xml version="1.0" encoding="UTF-8"?>
      <jdbcctxconfig:config
          xmlns:jdbcctxconfig="http://www.bea.com/ns/wlevs/config/application"
          xmlns:jc="http://www.oracle.com/ns/ocep/config/jdbc">
             <jc:jdbc-ctx>
              <name>Oracle11gR2</name>
              <data-source>DataMining</data-source>
                    <function name="prediction2">           
                           <param name="CQLMONTH" type="char"/>
                           <param name="WEEKOFMONTH" type="int"/>
                           <param name="DAYOFWEEK" type="char" />
                           <param name="MAKE" type="char" />
                           <param name="ACCIDENTAREA"   type="char" />
                           <param name="DAYOFWEEKCLAIMED"  type="char" />
                           <param name="MONTHCLAIMED" type="char" />
                           <param name="WEEKOFMONTHCLAIMED" type="int" />
                           <param name="SEX" type="char" />
                           <param name="MARITALSTATUS"   type="char" />
                           <param name="AGE" type="int" />
                           <param name="FAULT" type="char" />
                           <param name="POLICYTYPE"   type="char" />
                           <param name="VEHICLECATEGORY"  type="char" />
                           <param name="VEHICLEPRICE" type="char" />
                           <param name="FRAUDFOUND" type="int" />
                           <param name="POLICYNUMBER" type="int" />
                           <param name="REPNUMBER" type="int" />
                           <param name="DEDUCTIBLE"   type="int" />
                           <param name="DRIVERRATING"  type="int" />
                           <param name="DAYSPOLICYACCIDENT"   type="char" />
                           <param name="DAYSPOLICYCLAIM" type="char" />
                           <param name="PASTNUMOFCLAIMS" type="char" />
                           <param name="AGEOFVEHICLES" type="char" />
                           <param name="AGEOFPOLICYHOLDER" type="char" />
                           <param name="POLICEREPORTFILED" type="char" />
                           <param name="WITNESSPRESNT" type="char" />
                           <param name="AGENTTYPE" type="char" />
                           <param name="NUMOFSUPP" type="char" />
                           <param name="ADDRCHGCLAIM"   type="char" />
                           <param name="NUMOFCARS" type="char" />
                           <param name="CQLYEAR" type="int" />
                           <param name="BASEPOLICY" type="char" />                      
                    <return-component-type>char</return-component-type>
                          
                          
                 <sql><![CDATA[
                  SELECT to_char(PREDICTION_PROBABILITY(CLAIMSMODEL, '0' USING *))
                    AS probability
                  FROM (SELECT  :CQLMONTH AS MONTH,                 
                                :WEEKOFMONTH AS WEEKOFMONTH,
                                :DAYOFWEEK AS DAYOFWEEK,
                                :MAKE AS MAKE,
                                :ACCIDENTAREA AS ACCIDENTAREA,
                                :DAYOFWEEKCLAIMED AS DAYOFWEEKCLAIMED,
                                :MONTHCLAIMED AS MONTHCLAIMED,
                                :WEEKOFMONTHCLAIMED,  
                                :SEX AS SEX,
                                :MARITALSTATUS AS MARITALSTATUS, 
                                :AGE AS AGE,
                                :FAULT AS FAULT,
                                :POLICYTYPE AS POLICYTYPE, 
                                :VEHICLECATEGORY AS VEHICLECATEGORY,
                                :VEHICLEPRICE AS VEHICLEPRICE,
                                :FRAUDFOUND AS FRAUDFOUND,
                                :POLICYNUMBER AS POLICYNUMBER,
                                :REPNUMBER AS REPNUMBER,
                                :DEDUCTIBLE AS DEDUCTIBLE, 
                                :DRIVERRATING AS DRIVERRATING,
                                :DAYSPOLICYACCIDENT AS DAYSPOLICYACCIDENT, 
                                :DAYSPOLICYCLAIM AS DAYSPOLICYCLAIM,
                                :PASTNUMOFCLAIMS AS PASTNUMOFCLAIMS,
                                :AGEOFVEHICLES AS AGEOFVEHICLES,
                                :AGEOFPOLICYHOLDER AS AGEOFPOLICYHOLDER,
                                :POLICEREPORTFILED AS POLICEREPORTFILED,
                                :WITNESSPRESNT AS WITNESSPRESENT,
                                :AGENTTYPE AS AGENTTYPE,
                                :NUMOFSUPP AS NUMOFSUPP,
                                :ADDRCHGCLAIM AS ADDRCHGCLAIM, 
                                :NUMOFCARS AS NUMOFCARS,
                                :CQLYEAR AS YEAR,
                                :BASEPOLICY AS BASEPOLICY
                      FROM dual)
                      ]]>
              </sql>
             </function>
          </jc:jdbc-ctx>
      </jdbcctxconfig:config>

    2. イベント毎に関数を起動
      関数を定義すると、以下のようにCQLから関数を起動できます。
      <?xml version="1.0" encoding="UTF-8"?>
      <wlevs:config xmlns:wlevs="http://www.bea.com/ns/wlevs/config/application">

      <processor>
          <name>DataMiningProc</name>
          <rules>
             <query id="q1"><![CDATA[
                          ISTREAM(SELECT S.CQLMONTH,
                                         S.WEEKOFMONTH,
                                         S.DAYOFWEEK, S.MAKE,
                                         :     
                                         S.BASEPOLICY,
                                         C.F AS probability
                                                       FROM
                                      StreamDataChannel [NOW] AS S,
                                      TABLE(prediction2@Oracle11gR2(S.CQLMONTH,
                                            S.WEEKOFMONTH,
                                            S.DAYOFWEEK
                                            S.MAKE, ...,
                                            S.BASEPOLICY) AS F of char) AS C)
                            ]]></query>
                      </rules>
                    </processor>
                </wlevs:config>
  • EPNの最後のステージでは、イベントの異常の確率を出力します。CQL内に閾値を定めて、正常なイベントをふるいにかけることができます。
サンプルの実行
イベントがCEPを流れるときの挙動を確認しましょう。簡単のため、2個のイベント(正常時、異常時)のみを使います。
正常時のイベントは、異常の確率が60%未満としておきます。

Event is: eventType=DataMiningOutEvent object=q1  time=2904821976256 S.CQLMONTH=Dec, S.WEEKOFMONTH=5, S.DAYOFWEEK=Wednesday, S.MAKE=Honda, S.ACCIDENTAREA=Urban, S.DAYOFWEEKCLAIMED=Tuesday, S.MONTHCLAIMED=Jan, S.WEEKOFMONTHCLAIMED=1, S.SEX=Female, S.MARITALSTATUS=Single, S.AGE=21, S.FAULT=Policy Holder, S.POLICYTYPE=Sport - Liability, S.VEHICLECATEGORY=Sport, S.VEHICLEPRICE=more than 69000, S.FRAUDFOUND=0, S.POLICYNUMBER=1, S.REPNUMBER=12, S.DEDUCTIBLE=300, S.DRIVERRATING=1, S.DAYSPOLICYACCIDENT=more than 30, S.DAYSPOLICYCLAIM=more than 30, S.PASTNUMOFCLAIMS=none, S.AGEOFVEHICLES=3 years, S.AGEOFPOLICYHOLDER=26 to 30, S.POLICEREPORTFILED=No, S.WITNESSPRESENT=No, S.AGENTTYPE=External, S.NUMOFSUPP=none, S.ADDRCHGCLAIM=1 year, S.NUMOFCARS=3 to 4, S.CQLYEAR=1994, S.BASEPOLICY=Liability, probability=.58931702982118561 isTotalOrderGuarantee=true\nAnamoly probability: .58931702982118561

次のイベントでは異常確率89%というイベントです。何かが悪いのですが、よく見ると、”deductivity”(控除免責金額)が10000となっていて、これが問題のようです。では正確には何が正しい値なのでしょうか。deductive列の値を、distinctを指定してクエリを発行すると、{300、400、500、700} が返ってきます。

Event is: eventType=DataMiningOutEvent object=q1  time=2598483773496 S.CQLMONTH=Dec, S.WEEKOFMONTH=5, S.DAYOFWEEK=Wednesday, S.MAKE=Honda, S.ACCIDENTAREA=Urban, S.DAYOFWEEKCLAIMED=Tuesday, S.MONTHCLAIMED=Jan, S.WEEKOFMONTHCLAIMED=1, S.SEX=Female, S.MARITALSTATUS=Single, S.AGE=21, S.FAULT=Policy Holder, S.POLICYTYPE=Sport - Liability, S.VEHICLECATEGORY=Sport, S.VEHICLEPRICE=more than 69000, S.FRAUDFOUND=0, S.POLICYNUMBER=1, S.REPNUMBER=12, S.DEDUCTIBLE=10000, S.DRIVERRATING=1, S.DAYSPOLICYACCIDENT=more than 30, S.DAYSPOLICYCLAIM=more than 30, S.PASTNUMOFCLAIMS=none, S.AGEOFVEHICLES=3 years, S.AGEOFPOLICYHOLDER=26 to 30, S.POLICEREPORTFILED=No, S.WITNESSPRESENT=No, S.AGENTTYPE=External, S.NUMOFSUPP=none, S.ADDRCHGCLAIM=1 year, S.NUMOFCARS=3 to 4, S.CQLYEAR=1994, S.BASEPOLICY=Liability, probability=.89171554529576691 isTotalOrderGuarantee=true\nAnamoly probability: .89171554529576691

まとめ
このサンプルから、以下のことがわかりました。
  • Oracle Data Miningを利用とCEPを組み合わせると、リアルタイムにイベントのスコア(得点)をつけることができる。
  • CEPアプリケーションから、RDBMSで実行する、複雑な任意の外部計算処理(送料の算出など)を実行できる。
原文はこちら。
http://blogs.oracle.com/CEP/2011/02/extending_oracle_cep_with_pred.html

0 件のコメント:

コメントを投稿