「機械学習と Azure ML Studio の基本」 第5回 #Cogbot 勉強会で登壇しました #mlstudio

2017年2月24日(土) 開催の、第5回 Cogbot勉強会! で、

機械学習と Azure ML Studio の基本

というテーマで1コマ担当しました。

https://docs.com/d/embed/D25191436-9794-8903-0940-001353508057%7eBfe5a7bff-fc39-9c7d-d35f-86e930988702

20分なのでかなり駆け足でしたが、学習モデルの作り方のデモを見ていただくこともできて、「機械学習って思ったよりもとっつきやすいな」と思ってもらえたら幸いです。
(ちゃんとやりだすと難しいと思いますが、まずは始めるのが先なので)

ハンズオン資料を別途公開しているので、そちらも参考にして機械学習を楽しんでください。

カテゴリー: Cogbot, 機械学習 | タグ: , , | コメントをどうぞ

Azure Machine Learning Studio でデータセットの列名を変更する方法

Azure ML Studio で学習モデルを作る際、データセットの列名を変更したいことがあります。

  • 既存データの列名が適切ではない場合・・・例えば、ありがちなのは“ID”列。「外部キーとして使いたいから名前が“XxxId”とかだと都合がいい」ということがあります
  • 入手したデータセットが列名なしのデータだった場合・・・例えば UC Irvine Machine Learning Repository のサンプルデータは列名なしの CSV ファイルで、ML Studio に取り込むと、自動的に Col1, Col2,  … と振られます

 

UC Irvine Machine Learning RepositoryIris Data Set を例に、列名をデフォルトの Col1, Col2, … から変更する方法を紹介します。
ちなみに Iris Data Set の  CSV データ はここ、列名などの情報は ここ にあります。

2017-02-18 0-17-44

2017-02-18 0-20-08

 


Iris Data Set の CSV ファイルを ML Studio にアップロードして、Experimental に読み込むとこんな風になります。

2017-02-18 11-00-59

2017-02-18 11-06-39

Col1, Col2, … となっています。これを Iris Data Set の列名情報の通り、

sepal length in cm, sepal width in cm, petal length in cm, petal width in cm, class

とします。

[Data Transformation]-[Manipulation]-[Edit Metadata] をドロップして、“All Columns”を指定します。

2017-02-18 11-47-28

2017-02-18 11-49-27

2017-02-18 11-48-50

“New column names” に “sepal length in cm, sepal width in cm, petal length in cm, petal width in cm, class”と入力します。

2017-02-18 11-50-16

これで期待通りの列名になりました。学習モデルが作りやすくなりますね。

2017-02-18 12-13-38

 


凝ったことでも難しいことでもないのですが、説明している資料が意外と見つからないので(Edit Metadata を見てみればわかることですが、私は苦労しました・・・)、機械学習の「学習」のお役に立てれば。

2017年3月に2週連続で勉強会を開催します。解説+ハンズオン(もくもく会)の形式です。
1週目は 3月4日 (土) に機械学習、2週目は 3月11日 (土) に Cognitive Services + Bot Framework を、それぞれ学習します。
これを書いている時点では 4日の機械学習編は定員に達していますが、今後キャンセルする人がいるかもしれません。興味のある方は早めにキャンセル待ち登録をお勧めします。11日の Cogbot 編はより実用的な内容を扱いいます。こちらもお申し込みをお待ちしています。

カテゴリー: 機械学習 | タグ: , | コメントをどうぞ

「Visual Studio で Bot Service をローカルデバッグする方法」 第4回 Cogbot 勉強会で登壇しました #cogbot #botservice #functions

2017年1月27日(金) 開催の 第4回 Cogbot 勉強会で、
Visual Studio で Bot Service をローカルデバッグする方法」というテーマでお話ししました。

https://docs.com/d/embed/D25191673-0444-5596-4310-001940935162%7eBfe5a7bff-fc39-9c7d-d35f-86e930988702

Cognitive Service とも IoT とも仲良くできそうな、Bot Service は、ご承知の方も多いと思いますが、Azure Functions 上に展開されています。

Functions は当初デバッグが大変なサービスでした。
Azure ポータル上で print 分を使ってデバッグするか、Windows アプリでロジックを作った上で Functions のコードに貼り付けるかするくらいしかできませんでした。サーバーレス、ナノサービに分類されるサービスで、小さな処理を実行することを想定したサービスなので、それでも何とかできなくはないのですが、Visual Studio に慣れた身には面倒でした。


まだ「枯れた」とは言いがたいのですが、現在はいくつかの手順を踏めば Bot Service をローカルデバッグできます。Visual Studio のデバッグ機能も利用可能です。
ローカルデバッグするための手順は https://aka.ms/bf-docs-azure-debug で説明されているのですが、いくつかのページを移動しながらデバッグ準備を進めなければなりません。

そこで必要なツールやファイルのリンクと一緒に、画面キャプチャ付きで実際にデバッグを始めるまでのステップを紹介しました。

Visual Studio でブレークしたり、変数の値をウォッチしたりしながら、Bot Service を開発できるのは、やはりうれしいですね。
なお本稿の内容は、Bot Service だけではなく Azure Functions でも使えます。IoT でも Functions は使いどころがあるので、IoT 好きな方も参考にしてみてください。

カテゴリー: Azure Functions, Bot Service, Cogbot, Visual Studio | タグ: , , , | コメントをどうぞ

Windows 10 IoT をアプリでデバイスシャットダウンする方法

今回は、Windows 10 IoT でアプリからデバイスをシャットダウン(再起動)する方法。

他のマイコンボードだと、いきなり給電を止めても問題ありません。
microSD に書き込み中に電源を落としたりすると、カードの中身を破損する可能性はあると思うので絶対安全とは言えませんが、それほど神経質になることもないと思います。

それに対して、Windows 10 IoT はやむを得ない場合を除いて、ちゃんとシャットダウンしてあげるべきです。Windows です。“OS”です。
それなのにディスプレイもマウス・キーボードも接続していないということもあるでしょう。

そこでアプリでデバイスをシャットダウンしたくなります。タクトスイッチを押すとか、IoT Hub からメッセージを送るとかのタイミングでシャットダウンプロセスを起動することが考えられます。


Windows 10 IoT を楽しんでいる人ならば馴染みのある画面。

2017-01-26 23-08-27

ご承知のように、Windows 10 IoT はデフォルトシェルを持っていません。見慣れた画面も “IoT Core Default App” なるごく普通の UWP アプリケーション。
ソースコード が公開されているので、シャットダウンの方法もすぐにわかるでしょう

実際に、ソースコードを展開して、”Shutdown” を検索すればすぐに見つかります。
MainPage.xaml.csShutdownManager クラスの BeginShutdown  を呼び出しています。なるほど。

真似をしてこんなコードを書いてみました。起動して10秒後に自動的にシャットダウンしてしまうという、無意味この上ないアプリケーション(笑)。

using System;
using System.Threading.Tasks;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace ShutdownDemo01
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private void MainPage_OnLoaded(object sender, RoutedEventArgs e)
        {
            Task.Delay(TimeSpan.FromSeconds(10)).Wait();

            new System.Threading.Tasks.Task(() =>
            {
                ShutdownManager.BeginShutdown(ShutdownKind.Shutdown, TimeSpan.FromSeconds(0));
            }).Start();
        }
    }
}

 

実行してみるとこんなことになりました・・・。

2017-01-25 23-59-44

・・・“UnauthorizatedAccessException”。
さすが UWP アプリケーション、デバイスの機能を利用するには機能の指定が必要なようです。

残念ながら、ソリューションエクスプローラーの Package.appxmanifest をダブルクリックして開いても該当しそうな機能がリストに見つかりません。

2017-01-26 23-29-34

仕方ないのでここで改めて、先ほどダウンロードした IoT Core Default App のソースコードを参考にしてみます。

Package.appxmanifest を右クリックして、コードの表示を選択します。

2017-01-26 0-00-58

変更箇所は2か所。

Package 要素に属性を一つ追加。もう一つは一番下の Capabilities に要素を一つ追加。こうなります。

<?xml version="1.0" encoding="utf-8"?>

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10"
  IgnorableNamespaces="uap mp iot">

  <Identity
    Name="c626b4f7-7b52-4c90-90cb-9606fdce05c8"
    Publisher="CN=taka"
    Version="1.0.0.0" />

  <mp:PhoneIdentity PhoneProductId="c626b4f7-7b52-4c90-90cb-9606fdce05c8" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

  <Properties>
    <DisplayName>ShutdownDemo01</DisplayName>
    <PublisherDisplayName>taka</PublisherDisplayName>
    <Logo>Assets\StoreLogo.png</Logo>
  </Properties>

  <Dependencies>
    <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
  </Dependencies>

  <Resources>
    <Resource Language="x-generate"/>
  </Resources>

  <Applications>
    <Application Id="App"
      Executable="$targetnametoken$.exe"
      EntryPoint="ShutdownDemo01.App">
      <uap:VisualElements
        DisplayName="ShutdownDemo01"
        Square150x150Logo="Assets\Square150x150Logo.png"
        Square44x44Logo="Assets\Square44x44Logo.png"
        Description="ShutdownDemo01"
        BackgroundColor="transparent">
        <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
        <uap:SplashScreen Image="Assets\SplashScreen.png" />
      </uap:VisualElements>
    </Application>
  </Applications>

  <Capabilities>
    <Capability Name="internetClient" />
    <iot:Capability Name="systemManagement" />
  </Capabilities>
</Package>

 

以上で、無事にアプリからシャットダウンできるようになりました。めでたしめでたし。

カテゴリー: Windows 10 IoT | タグ: | コメントをどうぞ

IoT Hub 経由でデバイスにメッセージを送信する

IoT Hub にはデバイスにメッセージを送信する機能がありますが、前の記事では送信元として Device Explorer を使用しました。API が用意されているので、任意のアプリケーションから IoT Hub を経由してメッセージを送信することができます。今回はそのお話。

IoT Hub とデバイス(主に Windows 10 IoT)との通信や管理についての記事をいくつか投稿しました。本稿と合わせてご覧ください(以下の記事を順に読んで、最後に本稿を読むことをお勧めします)。


■ メッセージの送信の仕方

アプリケーションから IoT Hub 経由でデバイスにメッセージを送信するには、ServiceClient クラスの SendAsync メソッドを使います。

ServiceClient _client = ServiceClient.CreateFromConnectionString(ConnectionString);
await _client.SendAsync([デバイスID], [Message]);

こんな感じです。

Message は

var message = new Message(Encoding.ASCII.GetBytes(DeviceMessageBox.Text));

こんな感じでバイト配列にしておけば OK。

デバイスから IoT Hub にメッセージを送るのにそっくりです。
違いは、デバイスから IoT Hub に送る場合は DeviceClient クラスを使い、IoT Hub からデバイスにメッセージを送るには ServiceClient クラスを使うこと。
どちらも Client クラスのインスタンス生成は CreateFromConnectionString スタティックメソッドを使うのは同じです。


■ サンプルコード

サンプルコードのベースは こちらの記事 ですが、MainWindow.xaml および MainWindow.xaml.cs を以下のように変更してみました。デバイスにメッセージを送信するのは SendMessageButton_Click メソッドの部分です。

DeviceMaiager.cs は今回の内容には関係ないので、前の記事のままで持ってくればビルドに成功するはず。
もちろん送信元のアプリが WPF である必要はありません。

<Window x:Class="IoTDeviceManager.MainWindow"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"         xmlns:local="clr-namespace:IoTDeviceManager"         mc:Ignorable="d"         Title="IoT Hub Device Manager" Height="350" Width="525">
    <Grid>
        <Label x:Name="DeviceIdLabel" Content="デバイスID" HorizontalAlignment="Left" Margin="31,28,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="DeviceIdBox" HorizontalAlignment="Left" Height="23" Margin="115,31,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="360"/>
        <Label x:Name="PrimaryKeyLabel" Content="プライマリキー" HorizontalAlignment="Left" Margin="31,81,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="PrimaryKeyBox" HorizontalAlignment="Left" Height="23" Margin="115,81,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="360" IsReadOnly="True"/>
        <Label x:Name="StateLabel" Content="状態" HorizontalAlignment="Left" Margin="31,131,0,0" VerticalAlignment="Top"/>
        <RadioButton x:Name="EnabledButton" Content="有効" HorizontalAlignment="Left" Margin="115,137,0,0" VerticalAlignment="Top" GroupName="StateGroup" IsChecked="True"/>
        <RadioButton x:Name="DisabledButton" Content="無効" HorizontalAlignment="Left" Margin="190,137,0,0" VerticalAlignment="Top" GroupName="StateGroup"/>
        <Label x:Name="DeviceMesageLabel" Content="メッセージ" HorizontalAlignment="Left" Margin="31,183,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="DeviceMessageBox" HorizontalAlignment="Left" Height="23" Margin="115,186,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="360"/>
        <Button x:Name="CreateButton" Content="登録" HorizontalAlignment="Left" Margin="31,260,0,0" VerticalAlignment="Top" Width="75" Click="CreateButton_Click"/>
        <Button x:Name="GetButton" Content="取得" HorizontalAlignment="Left" Margin="111,260,0,0" VerticalAlignment="Top" Width="75" Click="GetButton_Click"/>
        <Button x:Name="SetStateButton" Content="状態変更" HorizontalAlignment="Left" Margin="191,260,0,0" VerticalAlignment="Top" Width="75" Click="SetStateButton_Click"/>
        <Button x:Name="SendMessageButton" Content="送信" HorizontalAlignment="Left" Margin="271,260,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="0.353,0.629" Click="SendMessageButton_Click"/>
        <Button x:Name="DeleteButton" Content="削除" HorizontalAlignment="Left" Margin="400,260,0,0" VerticalAlignment="Top" Width="75" Click="DeleteButton_Click"/>
    </Grid>
</Window>
using System.Text;
using System.Windows;
using Microsoft.Azure.Devices;

namespace IoTDeviceManager
{
    public partial class MainWindow : Window
    {
        private const string ConnectionString = "HostName=[ホスト名].azure-devices.net;SharedAccessKeyName=[アクセスキー名];SharedAccessKey=[アクセスキー]";

        private readonly DeviceManager _manager;
        private readonly ServiceClient _client;

        public MainWindow()
        {
            InitializeComponent();

            _manager = new DeviceManager(ConnectionString);
            _client = ServiceClient.CreateFromConnectionString(ConnectionString);
        }

        private async void CreateButton_Click(object sender, RoutedEventArgs e)
        {
            PrimaryKeyBox.Text = string.Empty;
            if (string.IsNullOrEmpty(DeviceIdBox.Text))
                return;

            var device = await _manager.CreateDevice(DeviceIdBox.Text);
            if (device == null)
                return;

            PrimaryKeyBox.Text = device.Authentication.SymmetricKey.PrimaryKey;
            if (device.Status == DeviceStatus.Enabled)
                EnabledButton.IsChecked = true;
            else
                DisabledButton.IsChecked = true;
        }

        private async void GetButton_Click(object sender, RoutedEventArgs e)
        {
            PrimaryKeyBox.Text = string.Empty;
            if (string.IsNullOrEmpty(DeviceIdBox.Text))
                return;

            var device = await _manager.GetDevice(DeviceIdBox.Text);
            if (device == null)
                return;

            PrimaryKeyBox.Text = device.Authentication.SymmetricKey.PrimaryKey;
            if (device.Status == DeviceStatus.Enabled)
                EnabledButton.IsChecked = true;
            else
                DisabledButton.IsChecked = true;
        }

        private async void SetStateButton_Click(object sender, RoutedEventArgs e)
        {
            PrimaryKeyBox.Text = string.Empty;
            if (string.IsNullOrEmpty(DeviceIdBox.Text))
                return;

            var device = await _manager.GetDevice(DeviceIdBox.Text);
            if (device == null)
                return;

            device.Status =
                EnabledButton.IsChecked.HasValue && EnabledButton.IsChecked.Value ?
                DeviceStatus.Enabled : DeviceStatus.Disabled;

            device = await _manager.SetDeviceStatus(device);
            if (device == null)
                return;

            PrimaryKeyBox.Text = device.Authentication.SymmetricKey.PrimaryKey;
            if (device.Status == DeviceStatus.Enabled)
                EnabledButton.IsChecked = true;
            else
                DisabledButton.IsChecked = true;
        }

        private async void DeleteButton_Click(object sender, RoutedEventArgs e)
        {
            PrimaryKeyBox.Text = string.Empty;
            if (string.IsNullOrEmpty(DeviceIdBox.Text))
                return;

            await _manager.DeleteDevice(DeviceIdBox.Text);
        }

        // アプリから Iot Hub 経由でデバイスにメッセージを送信する
        private async void SendMessageButton_Click(object sender, RoutedEventArgs e)
        {
            var message = new Message(Encoding.ASCII.GetBytes(DeviceMessageBox.Text));
            await _client.SendAsync(DeviceIdBox.Text, message);
        }
    }
}

 

本稿を含めて 4会の記事で、IoT Hub とデバイスとの通信についての説明は終わり。
IoT Hub を使って面白いシステムをどんどん作ってみてください。

カテゴリー: IoT, Iot Hub, Windows 10 IoT | タグ: , , | 1件のコメント

2017年は Windows Development のカテゴリーで MVP を受賞しました

あけましておめでとうございます。

今年もマイクロソフトの MVP を受賞しました。
今回は Windows Development カテゴリーでの受賞です。

昨年は活動の「数」は例年より少なくなってしまい(マイクを持っていた時間は増えているんですが)、それに対して情報の範囲が広くなったために散漫な感じになってしまったかもしれません。

今年は受賞対象である Windows Development  を核に情報発信していきたいと考えています。もちろん他の分野の技術についても、デバイス開発との関連を意識して扱っていきます。

本年も、イベントでブログで、よろしくお願いします。

カテゴリー: 未分類 | コメントをどうぞ

IoT Hub から送信されるメッセージを Windows 10 IoT Core デバイスで受信する

Azure IoT Hub の特徴の一つが、IoT Hub からデバイス個別にメッセージをデバイス個別に送信する機能です。

今回は、クラウドから送信されるメッセージを Windows 10 IoT デバイスで受信する方法。
本稿は「Windows 10 IoT Core から IoT Hub にメッセージを送信するアプリをスクラッチで書いてみる」の関連、続きの記事です。新規プロジェクトの作り方は本稿では説明していないので、まずはこちらの記事で読んでから本稿を読むことをお勧めします。


■ IoT Hub からのメッセージの受信の仕方

IoT Hub からメッセージを受信するには、DeviceClient クラスの ReceiveAsync メソッドを使います。

var message = await _client.ReceiveAsync();

こんな感じ。
※ DeviceClient は、DeviceClient.CreateFromConnectionString(ConnectionString); で事前にインスタンス化しておきます。

注意点としては、メッセージを取得した時、またはタイムアウト(デフォルトでは1分)した時(=指定の時間内にメッセージが届かなかった時)に、非同期で ReceiveAsync メソッドが返ってくるところ。タイムアウト時間を明示的に指定できますが、どちらにしてもメッセージがなければ null が返ってくるので、次の ReceiveAsync でメッセージ取得を待ちます。

もう一つ、メッセージを取得して処理に成功したら、DeviceClientCompleteAsync メソッドを呼び出すこと。
サーバー側では ReceiveAsync されてメッセージを渡すと、一時的にそのキューメッセージが不可視になり、一定時間後に改めてキュー上でメッセージが可視になり、改めて同じメッセージが取得可能になります。ということで、処理後には必ず CompleleteAsync してください。

■ サンプルコード

以上を、実際のコードで見てみると以下の通り。

using System;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Devices.Client;
using Newtonsoft.Json;

namespace IoTHubSendMessageDemo
{
    internal class SensorDevice
    {
        private readonly DeviceClient _client;
        private const string ConnectionString = "HostName=[ホスト名].azure-devices.net;DeviceId=[デバイスID];SharedAccessKey=[アクセスキー]";
        private const string DeviceId = "[デバイスID]";

        private double _delaySeconds = 5;

        public SensorDevice()
        {
            _client = DeviceClient.CreateFromConnectionString(ConnectionString);
        }

        internal async Task Run()
        {
            ReceiveMessageAsync();

            while (true)
            {
                var data = new SensorData
                {
                    DeviceId = DeviceId,
                    SensorValue = new Random().NextDouble()
                };

                var dataString = JsonConvert.SerializeObject(data);
                var message = new Message(Encoding.ASCII.GetBytes(dataString));
                await _client.SendEventAsync(message);

                Debug.WriteLine(dataString);

                Task.Delay(TimeSpan.FromSeconds(_delaySeconds)).Wait();
            }
        }

        private async void ReceiveMessageAsync()
        {
            while (true)
            {
                var message = await _client.ReceiveAsync();
                if (message == null)
                    continue;

                var msgString = Encoding.ASCII.GetString(message.GetBytes());
                Debug.WriteLine("Received a message : " + msgString);
                if (double.TryParse(msgString, out _delaySeconds))
                    Debug.WriteLine("Delay Seconds : " + msgString);

                await _client.CompleteAsync(message);
            }
        }
    }
}

■ サンプルコードの動作

念のためにサンプルコードの動作を説明します。

元になるコードは、こちらの記事で作った、疑似的なセンサーデータを送信するコードです。これにクラウドからのメッセージを受信する処理を追加しました。クラウド側は今回作っていないので、Device Explorer を使ってデータを送信してください。

2016-12-31 14-27-08

受信したデータの処は簡単のために数値のみです。(double.TryParse しているのでそれ以外のデータは捨てています)
受信した数値はセンサーデータ送信の間隔(秒)として使います。大きな値を指定すると間隔をあけてゆっくりとセンサーデータをアップロードするようになります。

2016-12-31 14-27-42

■ デバイスからのデータ送信のタイミングでメッセージを受信することに注意

この方法では、IoT Hub からデバイスへのメッセージを随時受信するわけではないことに注意してください。
デバイスから IoT Hub に接続したタイミングで、デバイス専用のキューにメッセージが積まれていた場合に メッセージを1件取得できるというものです。

このためデバイスから定期的に接続を行う、一般的にはセンサーデータの送信する必要があります。センサーデータ送信間隔によっては IoT Hub からのメッセージ取得するまでに時間がかかることに注意してください。だからと言って、通信の間隔が短すぎると余計な通信が発生してしまいます。適切な間隔を指定することが大事です。

万能な通信機能ではありませんが、デバイスごとに通信する内容を管理できますし、送信失敗した場合のリトライまで IoT Hub 側で責任を持ってくれます。
動きを理解した上で、デバイスとクラウドとの双方向の通信を使ってみてください。

カテゴリー: IoT, Iot Hub, Raspberry Pi, Windows 10 IoT | タグ: , , , | 1件のコメント