Japanese

Analytics
自然言語処理とSAS (1)

こんにちは!SAS Institute Japanの堀内です。今回は自然言語処理について紹介いたします。 自然言語処理とは、人間が普段会話したりメールしたりする際に使う言語(日本語や英語など)を、一種の信号とみたてて、その信号を機械が理解し、機械によって意味のある出力を得られるように工夫して処理することを指します。”自然”と明記しているのは機械にとっての日常語であるプログラム言語や機械言語と区別するためです。近年のAIやディープラーニングの発展とともに、この自然言語処理の分野も驚異的な進歩が見られ、私たちの日常生活の様々な分野で実際に活用されるようになってきました。第1回目の本投稿では、その内のいくつかを紹介いたします。第2回目以降は、実際にSASを使った自然言語処理の例を解説していく予定です。最後まで読んでいただければ、自然言語処理のホットトピックの内のいくつかを実装レベルで把握することができるようになるかと思いますのでどうぞお付き合いください。 最近の自然言語処理の実務適用例 チャットボット フリーテキストを入力欄に書き込むと、それに応じてボット(プログラムされた自動応答マシン)が適切な返答をテキストで返してくれるものです。様々なウェブページやアプリケーションに内蔵されるようになってきました。 例えば、不動産検索アプリに内蔵されたチャットボットでは、希望の条件をフリーテキストで入力すると、条件に合う物件を瞬時にレコメンドしてくれます。これによりユーザーが不動産検索サイトで条件を指定したり、相談窓口に電話して担当者に希望を伝えたりする手間が省けるようになってきています。   文書検索 手元にある長文の文書(例えば小説や論文など)と類似する文書を探したいとき、皆さんはどうしていますか?検索キーワードをいくつかピックアップしてGoogleなどのサーチエンジンで検索する、というのが最もオーソドックスな方法かと思いますが、最近では文書をまるごとサーチエンジンに入力し、似ている文書を探してくる文書検索ができるようになってきました。似ている文書がどのくらい似ているのかという指標も併せて返してくれるので、大量の論文を検索しなければならないビジネスや研究分野においては、検索の手間が大幅に減り大変便利です。   自動採点 皆さんも学校の国語や英語の授業で、長文を読んで質問に対して答えを書くという長文読解問題を解いたことがあるかと思います。私はこの手の問題が大の苦手でした。なぜならまず長文を読まなければならないのと、答えも一定の長さの文章を書かなければならず、とても手間に感じていました。実はこれ、テストを受ける生徒が嫌がるだけでなく、採点をする先生も同じくらい嫌だったのではないかなと思います。生徒の書いた解答文を読み解き、模範解答とされる文章と意味的に合致しているかという判断を下さなければならないのは結構手間がかかるはずです。実は最近の自然言語処理の発展により、この採点の部分を自動化することができるようになってきています。生徒の書いた文章と模範解答文との意味的距離をモデルが計算し、意味が近ければ正解、遠ければ不正解とすることができます。 また、長文のどの部分が解答となる要素を含んでいるか、というところまで判断し、解答文を自動作成することもできるようになってきました。これはQAタスクと呼ばれる自然言語処理の代表的なタスクの直接的な応用例になります。   オートフィル機能・スペルチェック機能(ライティング支援機能) 文書をタイピングする際、先読みして候補の単語をレコメンドしてくれたり、タイプした文のスペルチェックをしてくれたりする機能を皆さんも使ったことがあるかと思いますが、最近のものは複数行のセンテンスをレコメンドしてくれるようになってきました。またプログラミングの支援機能として書きたい内容をフリーテキストで書くと、該当のコードを提案してくれる機能がGitHubに実装されるなど、世の中はますます便利になりつつあります。(今私はブログを書いているわけですが、書きたいことの概要だけを書くと実際のブログ記事が提案されるようになったらどんなに仕事が捗るかと思います。) このように、これまで人間が苦労をして行っていた言語処理を機械ができるようになってきました。上にあげた例は実務適用例のごく一部です。様々な分野で自然言語処理が適用されようとしています。では、実際にSASではどのような事例が扱われているのでしょうか?   SASによる事例紹介 ここではSASがこれまで手掛けてきた自然言語処理のプロジェクトの一部を紹介します。 MR活動最適化 フランスの製薬企業において、SNSデータを解析することでKOL (Key Opinion Leader: 製薬企業の販売促進に影響力を持つ医師などの専門家) のセグメンテーションを行い、MR活動の最適化を行いました。SNSデータの解析にVTA¹が用いられました。 紹介記事: https://www.linkedin.com/pulse/how-does-hcp-behavioral-segmentation-help-build-full-olivier-bouchard/   院内有害事象発生防止の取り組み ノルウェー北部の中規模病院にて院内有害事象発生の未然防止のため標準的なツールGTT(トリガーツール)を半自動化する改良を加えることで、同等の精度を保ちながら院内有害事象の発見に要する時間を94%削減させました。電子カルテにはフリーテキストで記載された様々な様式の文書がありますが、そこから院内有害事象のトリガーとなる事象を抽出する部分にSASの自然言語処理の技術が使われました。 紹介記事: https://www.sas.com/da_dk/customers/helse-nord-patient-safety.html   有害事象発生予測 市販後の医薬品安全性監視において、FDA(アメリカ食品医薬品局)に寄せられた患者テキストの内、対象とする有害事象の発生を真に報告しているものをディープラーニングにより自動抽出する試みがなされました。テキスト解析とそれに続くディープラーニングによる予測モデルの構築にSASの技術が使われました。 紹介記事: https://communities.sas.com/t5/SAS-Global-Forum-Proceedings/Developing-a-SAS-Deep-Learning-MedDRA-encoder-MedDRA-DeepCoder/ta-p/735360   院内感染発生状況モニタリングシステム デンマーク南部地域一体の病院における、院内感染発生状況をモニタリングするシステムの開発が行われましたが、フリーテキストで記載された電子カルテの文書の中から、院内感染が疑われる箇所を抽出するアルゴリズムにSASの自然言語処理の技術が使われました。 紹介記事: https://www.sas.com/da_dk/customers/the-region-of-southern-denmark.html   消費者安全に関する報告のテキスト解析 消費者安全を担当するアメリカの政府機関に寄せられた消費者による様々な商品の安全性に関する報告文書を、VTAで解析し, VA²で可視化することで、単なる検索では得られないインサイトを得られることが分かりました。

Analytics
0
電力平準化問題に対するSASのアプローチ(2)

はじめに 前回のブログでは、電力平準化問題が数理最適化のスケジューリング問題として扱えること、SASのCLP Procedureで簡単にモデリング可能であることを紹介しました。今回は具体的にサンプル問題でCLP Procedureの使い方を見ていきます(ブログ末尾にサンプルコード記載)。 CLP Procedureの使い方 ここではプロシジャの使い方を分かりやすく示すため、図1のような3タスク、2設備の簡略化された問題のスケジューリングを例として説明します。タスクの詳細な設定は表1の通りとします。   中身の詳しい説明に入る前に、一つだけ最適化の処理で理解しておくべき概念として、Resourceというものを紹介します。Resourceとはタスクを実行するために必要な何かしらの資源で、CLP Procedureによるスケジューリングでは「ある時間帯の使用電力がXである=電力という資源をX占有する」のように読み替えることがポイントです。図1を例にとると、全体のResourceとしては電力設備M1とM2が1つずつ、電力は設定した電力上限分が用意されており、タスクA実行中は電力設備M1というResourceを1つ、電力というResourceを電力波形で表される分だけ各時間で占有する、と見なすことができます。最終的に実行可能なスケジュール(同じ時間帯に複数のタスクが同じ設備で実行されない、電力上限を超過しない)を作成することは、各タスクが上限の範囲内で上手くResourceを分け合うような割り当てを作成することに置き換えられます。 では、実際にSASコードでCLP Procedureを呼び出してスケジューリングを行う部分ですが、必要なのは以下のコードだけです。 proc clp actdata=act resdata=res schedtime=outtime schedres=outres; run; “schedtime”と”schedres”は出力先データセットの指定なので、ユーザーが用意する必要があるのは入力データの”actdata”と”resdata”のみです。では、それぞれのデータセットの内容を確認してみましょう。 “resdata”ではResourceの設定を行います。上での説明の通り、電力設備M1とM2が1つずつで、使用可能な電力総量の上限が“12”であることを表現しており非常に簡潔な設定です。 “actdata”はスケジューリングの対象となる最小要素であるActivityの設定を行います。今回の例では、タスクを図1のように分割したフェーズそれぞれを一つのActivityと考えます。こちらのデータセットは様々な要素が一行に並んでいるのでやや複雑ですが、設定項目は大まかに5種類の系統に分かれます。 まず_ACTIVITY_列では、各Activityにそれぞれ固有のIDを設定します。タスクAを例にとると、各フェーズの電力使用に当たるA01~A05と、タスク全体として設備M1を使用することを表すA00を設定しています。今回の問題では「設備M1を使用している間電力を使用する」という前提なので、A00の_DURATION_とA01~A05の合計が一致していることが確認できます。問題によっては「待ち時間などで使用電力0だが設備は占有したまま」のような状況で、両者の_DURATION_が異なる設定もあり得ます。 _SUCCESSOR_は前後関係を設定する対象のActivityを示しており、前後関係の種類と程度は_LAG_と_LAGDUR_で指定します。例えばFSは、「当該ActivityのFinishと_SUCCESSOR_で指定するActivityのStartの差が_LAGDUR_で指定する値以上」を示しています。今回の例では一つのタスクを分割したフェーズに相当するActivityは常に間を空けることなく実行されるため、_LAG_=FSE(FinishとStartが_LAGDUR_にEqual)、_LAGDUR_=0と設定しています。6行目のように、「タスクAの後3時間単位空けてタスクBを開始する」という業務的な意味での前後関係を表すのにも使用できます。また1行目のA00では、_LAG_=SSE(StartとStartが_LAGDUR_にEqual)でA01と開始が一致するように設定されていることにも注意が必要です。設定の詳細はマニュアルをご覧ください。 _ALIGNDATE_と_ALIGNTYPE_の組み合わせは_SUCCESSOR_と_LAG_の関係に似ていて、当該Activityと_ALIGNDATE_で指定した期日の間に_ALIGNTYPE_で指定する前後関係を設定します。例えば作業に着手可能になる時期や納期を表すのに使用でき、12行目では_ALIGNTYPE_=FEQ(Finishが_ALIGNDATE_=24にEqual)で「タスクB(のフェーズ5)が時刻24丁度に終了すること」を指定しています。 この設定でCLP Procedureを実行すると以下のような結果が得られ、時間に関する結果の”schedtime”とResourceに関する結果の”schedres”が出力されます。”schedtime”は各Activityをどの時間枠に割り当てるかという関心のある結果そのもの、”schedres”には例えば(今回の問題とは異なり)タスクを実行する設備にも選択肢がある場合のResourceの割り当てが出力されています。 最後に少しデータの加工が必要ですが、以下のようにガントチャートや電力波形に可視化して、諸々の条件が満たされたスケジュールになっていることが確認できます。図2 では"resdata"(表2)で指定した、「使用可能な電力総量の上限が“12”」を下回っていることが確認できます。 なお前回も記載しましたが、「ピーク値をどこまで下げることができるか?」を知りたい場合は、「使用可能な電力総量の上限」の指定値を下げて計算し、その条件を満たすスケジュールが作成可能かを調べることで下限を得ることができます。 まとめ 本ブログでは電力平準化問題を例として、CLP Procedureの使い方を見てきました。手順の中心となる入力データ準備の部分は、他のプログラミング言語で用意したものを読み込ませても良いですし、規模が小さければExcel上で作成してしまうことも可能です。SAS言語の知識も最適化の知識も最小限で、便利にスケジューリング機能が使えると感じていただけたなら幸いです。(反響があれば、設備の割り当ても考える場合など、より高度なモデリング方法についても取り上げます) サンプルコード 入力データは全てdataステップで作成しています。ganttプロシジャはclpプロシジャの結果である"schedtime"をほとんどそのまま使用できます(今回はグループ化の処理だけ追加しています)。使用電力の棒グラフについては、今回説明していないデータ加工が多少必要になるため、ソースコードからは割愛しています。 data res; input _RESOURCE_ $ _CAPACITY_; datalines; M1 1 M2 1 El 12 ;  

1 17 18 19 20 21 79