こんそーるすーぷのレシピはこちら

いちおう仕事なのに趣味の人に劣って焦り

人工知能についてのメモ②「Python環境の設定」

人工知能についてのメモ①では人工知能についてを軽く知り、それを実現するためには機械学習または深層学習が方法としてあり、いろいろな言語があるけどPythonが一番人気というところまでやりました。
今回はPythonの環境を整えて少し触るところまでです。

Anacondaのインストール

Pythonを調べていると便利便利と書いてあるのでAnacondaというものを使用していきたいと思います。
Anacondaは「Python本体と、Pythonでよく利用されるライブラリ」がまとまっているパッケージらしいです。(開発ツールみたいなものと理解しておきました)
www.anaconda.com

Anacondaのダウンロードページから私はPython 3.6 version (64bit) のインストーラーをダウンロードしました。
途中に選択やチェックボックス等ありましたが一応そのまま「Next > Next > Install」といった感じでインストーラーに従いました。

※注意:インストール途中にcmd.exeが開きますが閉じてしまうとインストールできないものが出てきたりするので放置しましょう。

対話型実行環境 Jupyter Notebook

Pythonのコードを含んだWebページを作成できる機能(つまりGitをcmd.exeでやるかSourcetreeのようなGUIツール使うかみたいなものと認識しました)
これを使って可視化しながら簡単なものからやっていきたいと思います。

インストールしたツールはAnaconda-Navigatorから開けるようです。
f:id:nanokanato:20180228121348p:plain:w100f:id:nanokanato:20180228121829p:plain:w300

またJupyter Notebookの直接リンクがありますがブラウザの方が開かなかったことがあるのでAnaconda-Navigatorから手順を踏んで開いた方がよさそうです。

Jupyter Notebookを開くとJupyter NotebookのWindowとブラウザが立ち上がります。
f:id:nanokanato:20180228122544p:plain:w300

「Documents\Python Jupyter Note」のフォルダを作りそこで作業することにしました。

  1. Documentsをクリックして階層を移動。
  2. 右上のNewをクリックし「Folder」を選びリストにUntitled Folderを追加。
  3. Untitled Folderをチェックし、左上に出てくるRenameを押す。
  4. フォルダの名前が変更できますので適宜変更してください。

エクスプローラーでフォルダを作り、再度ブラウザを開くことでもOKです。

Pythonの基礎

作業フォルダの作成

Python Jupyter Noteのブラウザで先ほど作った「Documents\Python Jupyter Note」を開きます。
右上の「New」から「Folder」を選択し、Untitled Folderを作成します。
Untitled Folderを選択して、「Rename」でHello Pythonという名前に変更します。
今回は「Documents\Python Jupyter Note\Hello Python」を作業フォルダとして利用します。

Python3の作成

右上の「New」から「Python3」を選択します。
f:id:nanokanato:20180228133514p:plain:w300
作業フォルダにUntitled.ipynbが作成され、別のブラウザでチャットのような画面が開きます。
f:id:nanokanato:20180228133535p:plain:w300

Hello Python

作成したUntitled.ipynbの「In [ ]:」の横の入力欄に以下のコードを打って「Shift」+「Enter」を押してください。

print('Hello Python!!')

これで入力に足して「Hello Python!!」と出力されました。
f:id:nanokanato:20180228133835p:plain:w300

コードを入力し「Shift」+「Enter」で実行して出力という作業が、Jupyter NotebookでのPythonプログラミングの基本となります。

ちなみに一度入力した場所のコードを修正して実行することで出力結果も更新されます。

変数を用いた計算

変数を用いて計算なども可能です。

a = 12
b = 35
c = 53
a + b + c

aに12、bに35、cに53を代入してその3つを足した数、100を出力します。
f:id:nanokanato:20180228134726p:plain:w300

ファイルの読み込み

機械学習にはデータの入力が必要です。
いちいちデータを手で入力していてはキリがないのでファイルを読み込む機能を使用します。

まずは読み込むためのファイルを作成します。
作業フォルダにて右上の「New」から「Text File」を選択します。
その後作成されたUntitled.txtをチェックして左上の「Rename」でData.csvに名前を変更します。
Data.csvを開いてcsvのコンマ区切り形式で適当にデータを作ります。
f:id:nanokanato:20180228141432p:plain:w300

作成したファイルをUntitled.ipynbと同じフォルダに配置します。
f:id:nanokanato:20180228140100p:plain:w300

以下のコードを実行することでファイルを読み込んで出力することができます。

import pandas as pd
data = pd.read_csv('Data.csv')
data

f:id:nanokanato:20180228141704p:plain:w300
一番左の太字の0,1,2は何個目のデータかを表しており、その右側はファイルに入力したものと一致しています。
全て空白の行があった場合はスルーされます。

また、ファイルの拡張子がtxtの場合でもコンマ区切りになっていれば問題ないようです。
※しかし一般的には拡張子はcsvなので合わせた方が良いでしょう。
f:id:nanokanato:20180228142337p:plain:w300

「import pandas as pd」はpdにpandasというデータ分析に特化したライブラリをインポートしており、そこからデータを読み込むことでエクセルやCSVデータを簡単に扱うことが可能になっています。

ファイルの保存

画面上の「Untitled」という部分を任意の名前(HelloPython)に変更し、左上の「File」の下にある保存ボタン(フロッピーディスクのアイコン)を押して完了です。

保存したファイルをPythonとして書き出す

画面左上の「File > Download as > Python(.py)」を押すことで.pyファイルとして書き出せます。

人工知能についてのメモ③では教師なし学習を行います。

人工知能についてのメモ①「基礎知識の確認」

ほぼ個人メモなので雑です。理解していくために書き殴ります。
人工知能などに関しての技術進歩が速いので今のうちに基礎を理解しておかないとチンプンカンプンになると思ったのではじめました。(使用だけだと簡易ライブラリなどは出てきていますが...原理的な部分)
定期で何かわかったことがあれば追記したりします。
解釈の違いなど当然あると思いますのでご指摘いただけると嬉しいです。

そもそも人工知能(AI)とは

膨大なデータを元に分析して分析・判断し、検出・抽出を行う機能、仕組み。
今回のような分析・判断するAIを強いAIと呼び、
プログラムで書かれたような知能の低いAIのことを弱いAIと呼ぶそうです。

よく出てくる単語

  • アルゴリズム
    • 学習したデータから検出・抽出する方法のこと。
  • データ
    • 主に学習の材料になるデータのこと。
      画像解析なら同じ対象が映った複数画像の集合や、Excelのような表など。
  • 入力
    • 機械学習のプログラムに対してデータを入力すること。
  • 出力
    • 入力から機械学習のプログラムが導き出した答えのこと。
  • ラベル
    • 入力とそれに対応すべき出力を人間が例として示した見本のこと
  • データマイニング
    • 様々なデータ解析の技法を大量のデータに網羅的に適用することで知識を取り出す技術のこと。
      通常では想像が及びにくい、発見ができる可能が多い。

人工知能を実現する方法

  • 機械学習
    機械学習を一言で表すと「明示的にプログラムしなくても学習する能力をコンピュータに与える研究分野」
    • 教師あり学習(Supervised Learning)
      • 入力と出力の関係を学習する方法。
        ラベルを提示することでそこから解釈されるアルゴリズムを生成する。
    • 教師なし学習(Unsupervised Learning)
    • 強化学習(Reinforcement Learning
      • 価値・評価を最大化するような行動を学習する方法。
        人間が与えた環境を観測し、どう行動すべきかを学習する。行動によって環境に影響が出て、環境から報酬という形でフィードバックを得ることで学習アルゴリズムのガイドとする。
        例として「将棋をして、より勝率の高い戦略を学習させる」などという方が個人的にはわかりやすい。
  • 深層学習(ディープラーニング
    ディープラーニング機械学習をさらに発展させたもの。主にデータを分析する際に使う枠組みが異なっていて、人間の神経を真似て作った「ニューラルネットワーク」で、コンピューターによるデータの分析と学習を強化している。
    機械学習ではデータに対して「入力と出力の関係」や「データの構造」「価値・評価を最大化する」など重点を人間が用意したのに対し、その部分もディープラーニングに学習させ判断させようとしているらしい....。(相手が何を求めているかを考えることでより人間に近くなっている!)

人工知能を作るにあたって選べる言語

  1. Python
  2. Java
  3. R
  4. C++
  5. C
  6. JavaScript
  7. Scala
  8. Julia

個人的にはJava,Js,C++あたりがうれしいのですが、一般的にはPythonが多く、記事も多いのでまずはPythonではじめるのが無難な感じでした。

人工知能についてのメモ②ではPythonの環境を整えます。

【Unity】WindowsPCのスクリーンをキャプチャして再生する

以下のほうが高機能で高速です。
tips.hecomi.com

しかし...GTX10XX系を搭載したゲーミングPCでは動かないそうで...??
実際、GTX1070を積んだノートで動作しなかった...

なので動作としては遅いが何となくPC画面をUnity内に描画したくてやってみました。
他に解決策があればぜひ教えていただきたいです。

ソースはこちら、サンプルをいくつか用意したのでどうぞ
github.com

実際に動かしてみるとこんな感じです。
exeでもWindowsであればもちろん動きます。
・Windows10
・Unity2017.3.1

【Unity】UnityEditor上でScriptのUpdate()などを動作させる

スクリプトを Edit モードで実行します
簡潔に「[ExecuteInEditMode]」をつけるだけです。

using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
public class ExampleClass : MonoBehaviour {
    public Transform target;
    void Update() {
        if (target)
            transform.LookAt(target);
        
    }
}

Editor上でログを出力したり、UIを動的に変更するのに使いました。

  • Update はシーンの何かが変更されたときのみ呼び出しされます。
  • OnGUI はゲームビューが Event を受け取った時のみ呼び出しされます。
  • OnRenderObject および他のレンダリング コールバック関数はシーンビューまたはゲームビューの再描画の都度、呼び出しされます。

と公式に書いてますので、他にもOnGUIやOnRenderObjectも動作するようです。

docs.unity3d.com

【Unity】Windows, Macで画像を印刷する方法

Windows, Macからデフォルトのプリンター設定を呼び出して印刷をやったのでメモとして残します。

検証環境
Unity : 2017.3.0f3
Mac : Sierra 10.12.6
Windows : Windows10, Windows7

はじめに

WindowsでもMacでも画像を印刷する際にパスの指定が必要になるため、画像の保存が必要です。
念のため記載しておきます。

Texture2Dをタイムスタンプをファイル名としてpngで保存します。
保存先はアクセス可能な場所である必要があります。

using UnityEngine;
using System.IO;

public class hogehoge
{
    public string SaveTexture2D(Texture2D texture2D)
    {
        byte[] bytes = texture2D.EncodeToPNG();
        string fileName = "image_" + (System.DateTime.Now.Ticks / 10000000) + ".png";
        string filePath = "hogehoge/hoge/"+fileName;
        if (bytes != null && 0 < bytes.Length) File.WriteAllBytes(filePath, bytes);
        else filePath = null;
        
        return filePath;
    }
}

Macで印刷する方法

Macだとlprコマンドで印刷するのが楽です。

using UnityEngine;
using System.Diagnostics;

public class hogehoge
{
    public delegate void PrintCallBack(string message);

    public void Print(string filePath, PrintCallBack callback)
    {
        if (callback == null) return;
        if (filePath == null)
        {
            callback("filePath is null");
            return;
        }

        string cmd = "lpr "+filePath;
        
        var process = new Process();
        process.StartInfo.FileName = "/bin/bash";
        process.StartInfo.Arguments = "-c \" " + cmd + " \"";
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.RedirectStandardOutput = true;
        process.Start();

        string output = process.StandardOutput.ReadToEnd();
        process.WaitForExit();
        process.Close();
        
        callback();
    }
}

Windows

Windowsだとlprコマンドの場合、ネットワークプリンタのIPと名前が必要だったりと厄介なのでSystem.Drawing.dllを使用します。

以下はdllを使用する上での設定です。

  • Assets以下の階層にPluginsフォルダを作成し、System.Drawing.dllを複製します。
    dllはだいたいここにあります。
    「C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll」
  • File>Build Setting>PlayerSettingsのOther SettingsでOptimizationのApi Compatibility Levelを「.NET2.0」に変更。

もし、VisualStudioが「using System.Drawing」などでエラーを出す場合

ソリューションエクスプローラーのプロジェクト名の下にある参照を開く。
Boo.LangやSystem.hogehogeなどを右クリックし、オブジェクトブラウザーで表示を押す。
オブジェクトブラウザーでSystem.Drawingを選択。
オブジェクトブラウザーの上方にある、+ボタン(ソリューションエクスプローラー内の選択されたプロジェクトに参照を追加)を押す。

using UnityEngine;
using System.Drawing;
using System.Drawing.Printing;

public class hogehoge
{
    public delegate void PrintCallBack(string message);
    private string imagePath = null;
    private PrintCallBack printCallback;

    public void Print(string filePath, PrintCallBack callback)
    {
        if (callback == null) return;
        if (filePath == null)
        {
            callback("filePath is null");
            return;
        }

        imagePath = filePath;
        printCallback = callback;

        //PrintDocumentオブジェクトの作成
        PrintDocument pd = new PrintDocument();

        //PrintPageイベントハンドラの追加
        pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);

        //Print
        pd.EndPrint += new PrintEventHandler(pd_PrintEnd);

        //PrintControllerプロパティをStandardPrintController
        pd.PrintController = new StandardPrintController();
        try
        {
            //印刷を開始する
            pd.Print();
        }
        catch (System.Exception ex)
        {
            if (printCallback != null) printCallback(ex.Message);
            printCallback = null;
        }
    }
    
    //プリントが終了した
    private static void pd_PrintEnd(object sender, PrintEventArgs e)
    {
        if (printCallback != null) printCallback(imagePath);
        printCallback = null;
    }

    //プリント画像を指定する
    private static void pd_PrintPage(object sender, PrintPageEventArgs e)
    {
        //印刷画像を読み込む
        System.Drawing.Image printImg = null;
        if (System.IO.File.Exists(imagePath))
        {
            printImg = System.Drawing.Image.FromFile(imagePath);
            if (printImg != null)
            {
                DrawAspectFillImage(e.Graphics, printImg, new RectangleF(0,//e.PageSettings.PrintableArea.Left,
                                                                         0,//e.PageSettings.PrintableArea.Top, 
                                                                         e.PageSettings.PrintableArea.Width,
                                                                         e.PageSettings.PrintableArea.Height), true);
                printImg.Dispose();
            }
        }
        //次のページがないことを通知する
        e.HasMorePages = false;
    }

    //プリント画像を描画する
    public static void DrawAspectFillImage(System.Drawing.Graphics graphics, Image image, RectangleF rectangle, bool isKeepAspectRatio)
    {
        if (graphics == null) throw new System.ArgumentNullException();
        if (rectangle.Width <= 0 || rectangle.Height <= 0) throw new System.ArgumentOutOfRangeException();
        if (image == null) return;

        Debug.Log("("+rectangle.Left+","+rectangle.Top+") - ("+rectangle.Width+","+rectangle.Height+")");
        var l = rectangle.Left;
        var t = rectangle.Top;
        var w = (float)image.Width;
        var h = (float)image.Height;
        if (isKeepAspectRatio)
        {
            var r = h / w;
            w = rectangle.Height / r;
            h = rectangle.Height;
            if (w > rectangle.Width)
            {
                w = rectangle.Width;
                h = rectangle.Width * r;
            }
            l += (rectangle.Width - w) / 2;
            t += (rectangle.Height - h) / 2;
        }
        graphics.DrawImage(image, l, t, w, h);
    }
}

注意としてはUnityEditorでは動くけど、exeにすると動かない場合は「.NET2.0」の設定を見直してみてください。

【Maya】Pythonで線を描画する

MayaをPythonでいじれるということなので手始めに検証です。
今回は線を引いてみました。

import maya.cmds as cmds

transform = cmds.createNode('transform', n='curve1')
nurbsCurve = cmds.createNode('nurbsCurve',n='curveShape1', p=transform)
cmds.curve(nurbsCurve, p=[(0, 0, 0), (3, 5, 6), (10, 12, 14), (9, 9, 9)])
  1. transformのcurve1を作成
  2. curve1を親にしてnurbsCurveのcurveShape1を作成
  3. curveShape1にカーブの値を設定

表示結果はこんな感じ
nurbsCurveで指定したので綺麗な曲線になるかと思ったのですがカクカクになってますね....
f:id:nanokanato:20180118155418p:plain:w400

【GAS】SpreadSheetでのデータ管理を簡単にする

GoogleAppScript(以下GAS)ではGoogleSpreadSheetを使って処理のログや通信結果を残すことができます。
しかし、SpreadSheetをもっと簡単に扱えるようにできないかと思いCS_SpreadSheetというライブラリを作成しました。

中でやっていること

どこらへんが簡単になっているのかというと...

  1. SpreadSheetのファイル名とシート名を指定してSheetを返す。
  2. 該当するものがGoogleDriveになければ新規作成、場所はScriptと同じ階層に作られます。

というだけの処理をやっています。
毎回Scriptを作るたびに専用のSpreadSheetを用意したりしなくていいというわけです。

導入方法

ライブラリの追加に必要なプロジェクトキー

1PtvvZ_GesDNbwjKDC3rig95f-5jMUM0lkLRlP6bKrDZHV5Q25oy7PugW

CS_SpreadSheetの使用方法

CS_SpreadSheet.FileName = "ファイル名";
CS_SpreadSheet.SheetName = "シート名";

function myFunction() {
    //シートの取得
    var sheet = CS_SpreadSheet.GetSheet();
    if (sheet == null) return;
    
    //中身の確認
    var maxRow = sheet.getMaxRows();
    var maxColumns = sheet.getMaxColumns();
    var values = sheet.getSheetValues(1, 1, maxRow, maxColumns);
    for (var i = 0; i < values.length; i++) 
    {
        var value = value[i];
        //ここでなにか比較など...(value[0] == "title")
    }
    
    //一番下にデータを追加はこれが簡単(上の比較で存在しなければ追加的な...)
    sheet.appendRow(["title", "message", "2018/01/17 11:22:00 +900", "hogehoge"]);
}

Sheetの操作方法は公式にあるので詳しくはそちらをどうぞ
Class Sheet  |  Apps Script  |  Google Developers

活用方法

ちょっと簡単にログを残す機能としてやウェブアプリケーションでエラーが出ている時のログツールとして活躍すると思います。

今回これを作った経緯として、
Webhookで受け取った内容をTwitterに投稿するために作りました。
受信データがどんな形式なのかのログツールとしてと、送信済みのデータを残しておくために使っています。

GASでSNS投稿については過去にまとめていますのでそちらをどうぞ。

Chatworkに投稿

madgenius.hateblo.jp