PowerShell Core + イベント管理

これまで2002年より、Sakura-Conのゲストリレーションでスタッフをするにあたり、数々の技術を使用し、イベント計画などを立ててきました。過去には、Org-modeや小型のPythonスクリプトなどを使用してきましたが、今年は、PowerShell Coreを使用し、システムを構築しました。これまでに、PowerShellを使用して、多岐にわたるシステムを構築し、例えばカラオケ歌唱データの集計などがその一例で、他の領域での使用も検討していました。

目的

今回の目的としては、中核的なソリューションとして次を検討しました。

  • イベントスケジュールデータの集計と、可用性を高めたデータの作成。
  • カレンダーデータなどへの他の有用なデータ形式への変換の提供。

PowerShell Coreを選択した理由は以下のような理由からです。

  • LinuxとWindowsを使用している関係上、複数のプラットフォームで動作できる環境が重要でした。Androidで動けばなおプラスですが、この点に関してはUserLAndなどの環境を使用することで可能でした。(尚、Androidで使用する場合は、このようなキーボードの使用がおすすめです。
  • オフラインで使用可能なこと。イベント会場などではインターネット接続が劣悪になることがあり、インターネット接続なしでも使用できることが重要でした。

構成と内容

最初に作成したモジュールはスケジュールシステムより、データを取得するためのシステムでした。スケジュールシステムは、データを取得するためのAPIを持っておらず、この部分に関してはSeleniumを使用し、データを抽出しました。

Seleniumを使用したデータの抽出(守秘事項のため、使用しているソリューション名に関しては伏せてあります。)

Seleniumを使用してデータを取得するのには800件のエントリーで約30秒を要します。(実際に使用するデータはその8分の1程度。)SeleniumモジュールにおいてはUI上で必要な情報が存在している場所まで移動し、結果をDOMより抽出するようなものです。これはC#でプログラムしました。SeleniumはLinuxとWindowsでドライバが提供されているため、これはクロスプラットフォーム動作が可能です。(こちらは、Androidでは動きませんが、Androidで動作するドライバと対応するブラウザがあれば恐らく可能です。)

このシステムは以下のようなデータ構造を列として出力します。

   TypeName: SakuraCon.Relations.Data.Event
Name        MemberType     Definition
----        ----------     ----------
End Time    AliasProperty  End Time = EndTime
Event Title AliasProperty  Event Title = EventTitle
Start Time  AliasProperty  Start Time = StartTime
Equals      Method         bool Equals(System.Object obj)
GetHashCode Method         int GetHashCode()
GetType     Method         type GetType()
ToString    Method         string ToString()
EndTime     Property       datetime EndTime {get;set;}
EventId     Property       string EventId {get;set;}
EventTitle  Property       string EventTitle {get;set;}
Notes       Property       string Notes {get;set;}
Rating      Property       string Rating {get;set;}
StartTime   Property       datetime StartTime {get;set;}
Type        Property       string Type {get;set;}
Venue       Property       string Venue {get;set;}
Duration    ScriptProperty System.Object Duration {get=($this.EndTime - $this.StartTime);}

これに加え、以下のようなps1xmlを定義しました。

<Types>
    <Type>
        <Name>SakuraCon.Relations.Data.Event</Name>
        <Members>
            <MemberSet>
                <Name>PSStandardMembers</Name>
                <Members>
                    <PropertySet>
                        <Name>DefaultDisplayPropertySet</Name>
                        <ReferencedProperties>
                            <Name>Event Title</Name>
                            <Name>Venue</Name>
                            <Name>Type</Name>
                            <Name>Start Time</Name>
                            <Name>End Time</Name>
                            <Name>Duration</Name>
                            <Name>Notes</Name>
                        </ReferencedProperties>
                    </PropertySet>
                </Members>
            </MemberSet>
            <AliasProperty>
                <Name>Event Title</Name>
                <ReferencedMemberName>EventTitle</ReferencedMemberName>
            </AliasProperty>
            <AliasProperty>
                <Name>Start Time</Name>
                <ReferencedMemberName>StartTime</ReferencedMemberName>
            </AliasProperty>
            <AliasProperty>
                <Name>End Time</Name>
                <ReferencedMemberName>EndTime</ReferencedMemberName>
            </AliasProperty>
            <ScriptProperty>
                <Name>Duration</Name>
                <GetScriptBlock>($this.EndTime - $this.StartTime)</GetScriptBlock>
            </ScriptProperty>
        </Members>
    </Type>
</Types>

実際の運用では、このデータをClixmlとして出力し、後ほど読み込めるようにします。PowerShellではこれを可能にする便利なCmdletが用意されています。

$schedule | Export-Clixml schedule.xml

これを読み込むのも容易です。

$schedule = Import-Clixml schedule.xml

これにより、出力されたXMLは取得したデータのスナップショットになるので、オフラインでのアクセスが可能になります。

このデータをもとに、CSV (スケジュール情報等を集計するのに使用) する他、iCalendarなどのフォーマットを出力し、Google Calendarに入力することが可能になります。

このデータ構造により、Where-Objectを使用することにより、必要な情報を取り出すことができるようになります。例えば、「6C」で行われるイベントを知りたい場合は以下のようになります。

$schedule | ?{ $_.Venue -eq "6C" }

これに加え、以下のようなスクリプトを組み合わせました。

function Get-ScNextEvent {
    param(
        [parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $Schedule,
        [parameter(Mandatory = $false)]
        [uint] $Hour = 1
    )
    $result = $Schedule | Where-Object { ($_.StartTime -ge [DateTime]::Now) -and ($_.EndTime -le [DateTime]::Now.AddHours($Hour))}

    return ($result | Sort-Object StartTime)
}

function Get-ScCurrentEvent {
    param(
        [parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $Schedule
    )
    $result = $Schedule | Where-Object { ($_.StartTime -ge [DateTime]::Now) -and ($_.EndTime -le [DateTime]::Now)}

    return ($result | Sort-Object StartTime)
}

これにより、次のイベントや、現在進行中のイベントに関する情報を検索することができます。

他の分野でのPowerShell Coreの使用

PowerShell Core`はスケジュール管理以外の分野でも使用しました。他の部分で使用したのは定形文書を生成する管理システムです。ほとんどの定型文書はLaTeXソースとして生成されているため、コマンドラインより、パーソナライズされた情報を読み込む形式になっています。PowerShellはCSVをデータ構造に変換する仕組みを持っているため、必要な引数はCSVでまとめました。

Windowsでのコマンドラインの文字列の扱いには難があるため、これをWindowsで実行する場合にはWindows Subsystem for Linux (WSL)を使用する必要がありましたが、PowerShell CoreはLinuxでも動作するため、同じモジュールやスクリプトをそのまま使用することが可能でした。

これにより、20通を30秒程度で生成できます。

まとめ

PowerShell Coreにより、クロスプラットフォームな、一貫した環境をリレーション部内で使用する必要のある一部の情報の処理で使用しました。

今後はこのシステムを拡張し、スケジュールの競合探知、負荷確認や人員管理などにも適用できるようにしていく予定です。

機械学習の特徴などに関して

先日のニューラルネットワークはポケモンの夢を見るか、の記事ですが、記事中でも書いたように、基本的には「機械学習の余地が入る部分はあまりない」と書きましたが、その点に関してより詳しい解説を追加したいと思います。

まず、機械学習の特徴ですが、「プログラムが遭遇するケースを全て個別にプログラムをすることなく判断ができる技術」となります。通常、プログラムを組む場合、例えば、通常のアプリケーションなどではユーザーの入力に対し、どのような挙動を示すかがプログラムされています。例えば、ウェブブラウザにURLを入力するとそのページを読みだし、ウェブサイトが表示されます。これはウェブブラウザのプログラマがそのようにプログラムしたからです。

このため、すでに相性等が定義されているポケモンに関して言えば、機械学習を用いなくとも全てのケースに対しプログラムした方が信頼性が高い結果が得られることになります。(そもそもポケモン自体がそのようにプログラムされているわけです。)

上記とは異なり、機械学習が効果を発揮するのは以下のようなケースになります。

  • 入力する定義値やその組み合わせが膨大であり、全体をプログラムすることが現実的でない場合。
  • 期待される入力値に未知の部分や曖昧な部分が存在する場合。
  • 認識されるべき変化が非常に微細であるか、特徴が簡潔でない場合。(ある特徴を定義する特徴量が多く必要という点で、上記の定義値に関連します。)

上記を踏まえて、例えば、自動運転車の実現に非常に多大な労力が消費されているのは、認識する必要がある事項に関してほぼ無限の可能性があり、全てのケースに関してプログラムすることができないという点によります。(例えば、人が道に立っている、という認識をしたい場合、様々な天候や光の当り具合、人が立っている場所、その動きなどに対してその対応を全てプログラムすることは現実的ではありません。)

尚、例えば、信号などがその状況を発信したり、車同士が通信できたりすることにより、曖昧さは解消することができますので、現在は自動運転車は現行の車や環境と強調して走らせる、ということに比重を置いていますが、今後はその方面での交通インフラの検討は進むのではないかと考えます。

以前、GoogleのCEOが「自動車の方がコンピューターより先に発明されたのは間違いだった」というような発言をしていますが、そういう意味でもコンピューターが最初に発明されていれば、恐らく交通インフラ自体がそれを前提とする形になっていた、ということなのではないかと思います。

話をポケモンに戻すと、ポケモンの場合は各18種類の要素が最大2個まで重複できるような作りになっていますので、情報量的にはそこまで大きくなく、全てをプログラムするのはさほど困難ではありません。ただし、これが数百、数千となり、また重複もより多く可能などとなると全プログラムをするのは困難になってきます。(ただし、規則性を符号化することによって必ずしも全部を手作業で、ということにはなりませんが。)

ちなみに先日のポケモン要素判断のニューラルネットワークは、非常にシンプルなものというだけで、実はその延長に画像認識やその他の高度な認識があります。

今後、機械学習の「民主化」が進んでいくと思いますので、その一つとして個人的な研究テーマにしています。