えまログ

機械学習、プログラミング、数学に関する記事を書いていきます。

aws SDK for .NETでの認証方法

C#でEC2インスタンスの監視するアプリを作りたかったのですが、認証に失敗して躓いたので記事に残そうと思います。

認証方法

以下の3つがあります。今回は1のSDKストアを使用します。
方法1.SDKストアを使う
ユーザーのホームディレクトリに認証情報ファイルを暗号化して作成し、それを参照します。

方法2.Credentialファイルを使う
キーIDとシークレットキーIDを書いたテキストファイルを指定すれば良いので簡単ですが、ファイルを見ればIDがわかってしまうのでおすすめしません。

方法3.環境変数を使う
こちらもIDが見えるのでおすすめしません。

以下、手順です。

1. プロファイル作成

以下を一度実行すればプロファイルが作成されます。

using Amazon.Runtime.CredentialManagement;
using System;


namespace CreateProfile
{
    class Program
    {
        static void Main(string[] args)
        {
            string profileName = "[プロファイル名]";
            string keyId = "[KEY_ID]";
            string secretKey = "SECRET_KEY";
            WriteProfile(profileName, keyId, secretKey);
        }

        static void WriteProfile(string profileName, string keyId, string secretKey)
        {
            Console.WriteLine($"Create the [{profileName}] profile");
            var options = new CredentialProfileOptions
            {
                AccessKey = keyId,
                SecretKey = secretKey
            };
            var profile = new CredentialProfile(profileName, options);
            var netSdkStore = new NetSDKCredentialsFile();
            netSdkStore.RegisterProfile(profile);
        }
    }
}

成功すると、 [%USERPROFILE%\AppData\Local\AWSToolkit\RegisteredAccounts.json に認証情報ファイルが暗号化した状態で保存されます。

キャプチャ

2. プロファイルを利用してインスタンスのステータスを監視する

以下のように実装しました。

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Threading;

using Amazon;
using Amazon.EC2;
using Amazon.EC2.Model;
using Amazon.Runtime;
using Amazon.Runtime.CredentialManagement;

namespace CheckStatus
{

    class Program
    {
        static void Main(string[] args)
        {
            var instanceId = "i-0xxxxxxxxxxxxxxx";
            var instanceIds = new List<string> { instanceId };
            DescribeInstancesResponse responseDescribe;
            var requestDescribe = new DescribeInstancesRequest
            {
                InstanceIds = instanceIds,
            };

            var ec2Client = new AmazonEC2Client(RegionEndpoint.APNortheast1);
            
            int wait = 2000; // miliseconds
            while (true)
            {
                Console.Write("");
                var response = ec2Client.DescribeInstancesAsync(requestDescribe).Result.Reservations;
                foreach(var reservations in response)
                {
                    foreach (var instance in reservations.Instances)
                    {
                        Console.WriteLine("{0}: {1}",instance.InstanceId, instance.State.Name);
                        //     0 : pending
                        //     16 : running
                        //     32 : shutting-down
                        //     48 : terminated
                        //     64 : stopping
                        //     80 : stopped
                        //     You can ignore the high byte value by zeroing out all of the bits above 2^8 or
                        //     256 in decimal.
                    }
                    Thread.Sleep(wait);
                }
            } 
        }
    }
}

設定は以下のようになっています。"AWSProfileName"="sample_profile"と指定しておけば自動で参照してくれます。

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="AWSProfileName" value="sample_profile"/>
    </appSettings>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
</configuration>

実行結果

停止していたインスタンスをマネジメントコンソールから起動→停止したときの挙動です。

i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: pending
i-0xxxxxxxxxxxxxxx: pending
i-0xxxxxxxxxxxxxxx: pending
i-0xxxxxxxxxxxxxxx: pending
i-0xxxxxxxxxxxxxxx: pending
i-0xxxxxxxxxxxxxxx: pending
i-0xxxxxxxxxxxxxxx: pending
i-0xxxxxxxxxxxxxxx: pending
i-0xxxxxxxxxxxxxxx: running
i-0xxxxxxxxxxxxxxx: running
i-0xxxxxxxxxxxxxxx: running
i-0xxxxxxxxxxxxxxx: running
i-0xxxxxxxxxxxxxxx: running
i-0xxxxxxxxxxxxxxx: running
i-0xxxxxxxxxxxxxxx: running
i-0xxxxxxxxxxxxxxx: stopping
i-0xxxxxxxxxxxxxxx: stopping
i-0xxxxxxxxxxxxxxx: stopping
i-0xxxxxxxxxxxxxxx: stopping
i-0xxxxxxxxxxxxxxx: stopping
i-0xxxxxxxxxxxxxxx: stopping
i-0xxxxxxxxxxxxxxx: stopping
i-0xxxxxxxxxxxxxxx: stopping
i-0xxxxxxxxxxxxxxx: stopping
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped
i-0xxxxxxxxxxxxxxx: stopped

この記事は以下を参考にしました。

docs.aws.amazon.com

行列式の対数を行列で偏微分する公式の証明

今回は,線形代数でよく使う以下の公式の証明を行います.

 \frac{\partial}{\partial A}ln|A| = (A^ {-1})^ T

ここで, Aは正則な正方行列とします.

導出

 \frac{\partial}{\partial A}ln|A| 
= \frac{1}{|A|}\frac{\partial |A|}{\partial A} \\\\  
= \frac{1}{|A|} |A|(A^ {-1})^ T \qquad(\because \frac{\partial |A|}{\partial A} = |A|(A^ {-1})^ T )\\\\  
= (A^{T})^{-1} \qquad \qquad(\because (A^{T})^{-1} = (A^{-1})^{T})

公式を使って式を変形するだけなので,わかりやすいかと思います.
 \frac{\partial |A|}{\partial A} = |A|(A^ {-1})^ T の公式の証明を以下の記事に載せているので,よろしければ参考にしてください.

行列式を行列で偏微分する公式の証明 - えまログ

参考文献

この記事は,以下を参考にしました.

余因子と余因子展開 | 大学1年生もバッチリ分かる線形代数入門

転置行列の意味・重要な7つの性質と証明 | 高校数学の美しい物語

行列式を行列で偏微分する公式の証明

機械学習の勉強をしているのですが,EMアルゴリズムの数式を理解できず,線形代数の勉強を始めました...
今回は,線形代数でよく使う以下の公式の証明を行います.

 \frac{\partial |A|}{\partial A} = |A|(A^ {-1})^ T

ここで, Aはn次元の正則な正方行列とします.
できるだけ視覚的にわかりやすく示せればと思っています. では,証明を初めていきます.

|A|はスカラーなので,Aで偏微分すると,以下のようになります.

  
 \frac{\partial |A|} {\partial A} =
\begin{pmatrix}
\frac{\partial |A|}{\partial a_{11}} & \cdots & \frac{\partial |A|}{\partial a_{1n}} \\\\
\vdots & \ddots & \vdots \\\\
\frac{\partial |A|}{\partial a_{n1}} & \cdots & \frac{\partial |A|}{\partial a_{nn}}  
\end{pmatrix}

ここで, a_{ij}は行列Aのi行j列成分を表しています.
では,それぞれの要素について考えることにします.

行列Aに対する (i, j)成分の余因子を A_{ij}とします.
|A|は余因子展開により,Aのそれぞれの行,列について,以下のように表すことができます.


|A| = a_{i1}A_{i1} + a_{i2}A_{i2} + \cdots + a_{in}A_{in}

|A| = a_{1j}A_{1j} + a_{2j}A_{2j} + \cdots + a_{nj}A_{nj}

以上より,求めたい各要素の偏微分について以下の式が成り立ちます.


\frac{\partial |A|}{\partial a_{ij}} =  
A_{ij}

よって,以下が成り立ちます.

  
 \frac{\partial |A|}{\partial A} =
\begin{pmatrix}
A_{11} & \cdots & A_{1n} \\\\
\vdots & \ddots & \vdots \\\\
A_{n1} & \cdots & A_{nn} \tag{1}
\end{pmatrix} 

ここで,余因子行列は以下のように表せます.

  
 \tilde{A} =
\begin{pmatrix}
A_{11} & \cdots & A_{n1} \\\\
\vdots & \ddots & \vdots \\\\
A_{1n} & \cdots & A_{nn}
\end{pmatrix} \tag{2}

2つの式(1), (2)を見比べると,転置になっていることがわかります. したがって,(1)はAの転置行列の余因子行列ということになります.

  
 \begin{align}
\frac{\partial |A|}{\partial A} &=
\begin{pmatrix}
A_{11} & \cdots & A_{1n} \\\\
\vdots & \ddots & \vdots \\\\
A_{n1} & \cdots & A_{nn} 
\end{pmatrix} \\\\
&= \tilde{A^ T} 
\end{align}

逆行列の定義  A^ {-1} = \frac{1}{|A|}\tilde{A} を用いて,以下のように変形します.

  
 \begin{align}
\frac{\partial |A|}{\partial A} 
&= \tilde{A^ T}  \\\\
&= {|A^ T|}(A^ {T})^ {-1} \\\\
&= |A|(A^ {-1})^ {T}
\end{align}

以上より,題意を示すことができました.

いかがだったでしょうか.偏微分したときに,なぜ転置が起こるのかの理解の助けになれば幸いです.

参考文献

この記事は,以下を参考にしました.

余因子と余因子展開 | 大学1年生もバッチリ分かる線形代数入門

転置行列の意味・重要な7つの性質と証明 | 高校数学の美しい物語

動画ファイルから指定フレームをキャプチャする方法

C++で画像処理をされる方が多いからか、C#OpenCVを使う記事がなかなか見つからなくて困っています。

自分が苦労したことを共有し、誰かの助けになれば幸いです。

今回は、OpenCVSharpを使って、動画ファイルから指定したフレームの画像を取得する方法を紹介いたします。

サンプルコード

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace CaptureFrame
{
    class Capture
    {
        static void Main(string[] args)
        {
            // vtest.avi ファイルの500フレーム画像を取得する
            var frame = CaptureFrame("vtest.avi", 500);
            if (0 < frame.Width && 0 < frame.Height)
            {
                Cv2.ImShow("frame", frame);
                Cv2.WaitKey(0);
            }
        }

        static Mat CaptureFrame(string fileName, int frameNo)
        {
            var frame = new Mat();
            using (var videoCapture = new VideoCapture(fileName))
            {
                // 次にキャプチャされるフレームのインデックスを
                // 引数で受け取ったフレーム番号にセットする
                videoCapture.Set(CaptureProperty.PosFrames, frameNo);
                videoCapture.Read(frame);
            }
            return frame;
        }
    }
}

結果

目的の画像が表示されました!

注意

①Dispose漏れ

VideoCaptureを使用したあとは、必ずDisposeしましょう!
Disposeし忘れを防止するために、usingステートメントを使用することを勧めます!

②フレーム開始番号

フレームの番号は0から始まります。 サンプルコードではフレーム番号を500と指定しています。 よって、動画の最初のフレームから501番目のフレームを取得していることになります。

動画

動画は以下からダウンロードしました。 github.com

参考記事

動画を扱う — OpenCV-Python Tutorials 1 documentation www.sejuku.net