読者です 読者をやめる 読者になる 読者になる

Dr. 三日坊主

日々の勉強の記録 AIそして英語

機械学習勉強動画まとめ

勉強で使った動画をまとめておく

Machine Learning Recipes


Hello World - Machine Learning Recipes #1

Google TensorFlow チームのJosh Gordonによる、機械学習入門動画シリーズ。
全7回で一本あたり10分ない程度の時間なのでさらりと見れる。

前半は、機械学習アルゴリズムの話はなく、学習データの作り方についての説明。
学習部分はブラックボックスとして扱っている。

後半では機械学習とは具体的になにを計算しているのかを説明した上で、学習アルゴリズムの実装まで行う。

プレイリスト
Machine Learning Recipes with Josh Gordon - YouTube

Neural Net in C++ Tutorial


Neural Net in C++ Tutorial on Vimeo

一時間で、ゼロからニューラルネットを実装する動画。
解説が丁寧なので、c++ に詳しくなくてもついて行けると思う。
クラス設計のお手本にもなった。

ただし、ニューラルネットの仕組みはある程度理解していることが前提となっており、
誤差伝搬の実装もサクサク進めていく。

この動画で書いたソースコードも公開されている
New Video Tutorial: Make a Neural Net Simulator in C++ | Dave Miller Blog

他にもみつけたら追加予定

ゲームAIスタディ-迎撃

今回はターゲットの動きを見て、それを迎撃するアルゴリズムを実装した。
前回の追跡アルゴリズムでは、プレデターの移動先 = ターゲットのいる場所だったが、
迎撃アルゴリズムでは、プレデターの移動先 = ターゲットと同時にたどり着く場所だ。

ターゲットと同時にたどり着く場所は、以下の手順で求めることができる。

1. ターゲットまでの距離を測る(相対距離)
2. どれくらいの速度でプレデターとターゲットが近づいていくのかをもとめる(相対速度)
3. 距離と速度から、ターゲットまでの距離が0になるまでの時間 t がもとまる
4. プレデターの移動先は、ターゲットが今の速度で時間 t 後に到達する点である


動かしてみるとこんな感じ。
ターゲットのお尻を追いかけるよりはスマートに見えるかな


今日はここまで


ゲーム開発者のためのAI入門

ゲーム開発者のためのAI入門

ゲームAIスタディ-追跡

挙動を確認できる下地を作ったので、今回からは本とサンプルを読みながら実際に実装してみる。
今回は、追跡のアルゴリズム
追いかけられる役をターゲット。追いかける役をプレデターと呼ぶことにする。

手始めに、なにも障害物などのない空間で考える。

走って追跡

プレデターが人間など、その場ですぐに方向を変えられるようなものの場合はとても簡単。
プレデターは、ターゲットの場所を把握すると、自分の場所からターゲットへの場所へ向かうベクトルをそのまま速度にしてやればよい。
ターゲットが動いても、そのたびに速度を更新すればずっと追いかけていける。

// キャラクタークラス.
class Character {
  ...
  // targetを設定.
  void SetTarget( Vector targetPos );
  void Update( float dt );
  ...

  Vector Pos;  // 位置.
  Vector Vel;  // 速度.
  float speed; // 速さ.

  ...
};

void Character::SetTarget( Vector targetPos ) {
   	Vector newVel = targetPos - m_pos;
	newVel.normalize();
	Vel = newVel * speed;
}

void Character::Update( float dt ) {
   	Pos += Vel*dt;
}

乗り物で追跡

しかし、乗り物で追跡する場合はそうはいかない。
もし後ろにターゲットがいることがわかったら、方向転換をしてから追いかける必要があるし、
追跡中にターゲットが移動して方向を変えなければならないとき、慣性力によってすぐには曲がれず、すこし遠回りに弧を描いて曲がるほうが自然に見える。

本の中では、前進する力自身を回転させる力を操作して操縦する乗り物を実装している。
実装には基本的な物理学の知識が必要だが、とても汎用性が高く、車や船、ロケットなどの挙動もこれで実装できてしまう。

今回はこの乗り物を使って追跡のアルゴリズムを実装してみた。
仕組みはとても簡単。プレデターからみて、ターゲットが右側にいれば右回転するように力を与え、左側にいれば左回転するようにしているだけ。
本に載っているように、乗り物にくっついた局所座標(ローカル座標)と、ゲーム画面の座標(グローバル座標)を分けると、計算がとても楽になった。


動きはこんな感じ。

下のロケット(ターゲット)は、マウスがクリックした場所を目指して飛び、
左のロケット(プレデター)は、ターゲットを追いかけるように飛ぶようにした。
プレデターは、ターゲットより1.5倍速く動けるようにしてある。
目標の位置は毎フレームセットし直して、その都度速度を更新している。

急な方向転換はできず、慣性ですこし遠回りしながら方向を変えているところが乗り物として自然に見えるかな。


今日はここまで


ゲーム開発者のためのAI入門

ゲーム開発者のためのAI入門

【英語】The 比較級, the 比較級

今日の英会話の学びは

The competitive, the competitive. 

用語では double competitive というらしい。日本語ではなんていうんだろう。

 

特に、The 〜, the better. という表現はよく使うらしい。

The bigger, the better.
大きければ大きいほどよい. 

The sooner, the better.
早ければ早いほどよい.

The less luggage you have, the better.
荷物は少なければ少ないほどよい.

 

もちろんthe better以外も使える.

 

The more I know him, the more I love him.  
知れば知るほど、ますます彼を好きになる. 

The colder it gets, the less I go out.  
寒くなれば寒くなるほど、外へ出なくなる.

The sooner we leave, the earlier we will arrive.
早く出れば早く出るほど、早く着く.

 

The harder you study, the better your Enlglish. 

 

【AI】ゲームAIスタディ-準備(2/2)

画面遷移

前回から引き続き、画面遷移を作る。
遷移先からホーム画面に戻れるようにしたいので、戻るボタンだけを持った画面を作っておく。
これをベースクラスとして、それぞれの遷移先画面は、このクラスを継承する。

 

LayerBase.h

// createScene定義マクロ.
#define CREATESCENE_FUNC(__TYPE__) \
static cocos2d::Scene* createScene() \
{ \
auto scene = cocos2d::Scene::create(); \
auto layer = __TYPE__::create(); \
\
scene->addChild(layer); \
\
return scene; \
}

// createSceneとcreateを両方定義するマクロ.
#define DECLEAR_H( __TYPE__ ) \
CREATESCENE_FUNC(__TYPE__) \
CREATE_FUNC(__TYPE__)


#include "cocos2d.h"

class LayerBase : public cocos2d::LayerColor
{

public:
	LayerBase();
	~LayerBase();
	
	bool init();
	virtual void addinit();
	virtual void update(float delta);
	
	// a selector callback
	virtual void menuCloseCallback(cocos2d::Ref* pSender);
	
private:
	cocos2d::MenuItemImage* pcloseBtn;	// 閉じるボタン.
	
};

 

createScene関数も毎回書くのがだるいのでマクロ化。
create関数とcreateScene関数を両方定義してくれるマクロも追加。
このマクロをLayerBaseを継承した子クラスで呼ぶことにする。

addinit関数は、子クラスで追加されたメンバーを初期化するときに使う。

 

LayerBase.cpp

USING_NS_CC;
#include "LayerBase.h"


LayerBase::LayerBase() : pcloseBtn(NULL)
{
}

LayerBase::~LayerBase()
{
}

bool LayerBase::init()
{
	//////////////////////////////
	// 1. super init first
	if ( !Layer::init() )
	{
		return false;
	}
	
	// スケジューラーへ登録.
        // これを呼んでおくと、update(float delta)が呼ばれるようになる。
	this->scheduleUpdate();
	
	Size visibleSize = Director::getInstance()->getVisibleSize();
	Vec2 origin = Director::getInstance()->getVisibleOrigin();
	
	/////////////////////////////
	// 2. add a menu item with "X" image, which is clicked to quit the program
	//    you may modify it.
	
	// add a "close" icon to exit the progress. it's an autorelease object
	pcloseBtn = MenuItemImage::create("CloseNormal.png",
					  "CloseSelected.png",
					  CC_CALLBACK_1(LayerBase::menuCloseCallback, this));
	
	pcloseBtn->setPosition(Vec2(origin.x + visibleSize.width - pcloseBtn->getContentSize().width/2 ,
			            origin.y + pcloseBtn->getContentSize().height/2));
	
	// create menu, it's an autorelease object
	auto menu = Menu::create(pcloseBtn, NULL);
	menu->setPosition(Vec2::ZERO);
	this->addChild(menu, 1);
	
	addinit();
	
	return true;
}

void LayerBase::addinit()
{
}

void LayerBase::update(float delta)
{
}

void LayerBase::menuCloseCallback(Ref* pSender)
{
	Director::getInstance()->popScene();
	
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
	exit(0);
#endif
}

 

遷移先画面

Chapter 2に向けた画面を作ってみる。
LayerBaseクラスで必要最低限の実装をしたので、かなりシンプルに実装できた。
背景色は白に変えてみた。

 

Chapter2Dlg.h

#include "LayerBase.h"
class Chapter2Dlg : public LayerBase {
	
public:
	Chapter2Dlg(){};
	~Chapter2Dlg(){};
	DECLEAR_H(Chapter2Dlg);

	void addinit();
	void update(float delta);
};

 

Chapter2Dlg.cpp

USING_NS_CC;
#include "Chapter2Dlg.h"

#define BASE_LAYER LayerBase

void Chapter2Dlg::addinit()
{
	// 背景色を白に.
	LayerColor::initWithColor(Color4B(255,255,255,255));
	BASE_LAYER::addinit();
}

void Chapter2Dlg::update(float delta)
{
	BASE_LAYER::update(delta);
}

 

 

 画面遷移処理

ログを出すだけだったボタン押下処理を修正
HelloWorldScene.cpp

// 画面遷移ボタン.
void HelloWorld::selectchapterbtn(cocos2d::Ref* pSender, int btnid)
{
	switch (btnid) {
		case eBUTTON_CHAPTER2:
		{
			log("chapter 2");
                        //  追記↓
			auto scene = Chapter2Dlg::createScene();
			Director::getInstance()->pushScene(scene);
		}
			break;
		case eBUTTON_CHAPTER3:
			log("chapter 3");
			break;
		default:
			break;
	}
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
	exit(0);
#endif
}

 

pushScene関数を使うことで、前画面に戻れるようになっている。

 

テストするとちゃんと白い画面に遷移した。
右下のボタンからホーム画面に戻れる。

f:id:merakuma:20170110005346p:plain

 今日はここまで

 

 

ゲーム開発者のためのAI入門

ゲーム開発者のためのAI入門

 

 

【AI】ゲームAIスタディ-準備(1/2)

「ゲーム開発者のためのAI入門」を1周読破。

追跡や迎撃、群れの挙動から、ニューラルネットワーク遺伝的アルゴリズムまで、アルゴリズムの仕組みから実装まで詳しく書かれており、読むだけでも十分おもしろい本だった。

ゲーム開発者のためのと謳っているが、ゲーム以外のところでも十分使えそうな内容。

 

サンプルコードもダウンロードできるので、2周目は実際に手を動かしながら読み進めたい。サンプルは以下のページ右側のDownloaded Example Codeから。

www.oreilly.com

 

サンプルコードを見ると、サンプルによって環境が違う...

windowsのVC6かmacのCodewarrior8か。

 

開発環境はmacしかないので、xcodeで動かす準備をした。

アルゴリズムの勉強だけならコマンドラインツール環境でもいいのだが、せっかくなので連続動作環境で開発したい。

しかし残念ながら、Cocoa Applicationをc++で開発することはできないようなので、Cocos2d-xを使うことにした。

 

導入は以下のブログを参考にさせていただいた。

qiita.com

 

準備

とりあえず、作成されたプロジェクトを開き、macのアプリとして実行してみる。

タイトル画面のような画面がでるので、これをそのままホーム画面として使わせてもらおう。

ちなみに画面のサイズはここで変更できる。

 

AppDelegate.cpp

static cocos2d::Size designResolutionSize = cocos2d::Size(1024, 768);

 

ホーム画面

"Hello World"を"AI for Game Developer"に変更。

その下にそれぞれのチャプターごとの稼働場所へ飛ぶボタンを作った。

 

HelloWorldScene.h

class HelloWorld : public cocos2d::Layer
{
public:
	enum eBUTTON {
		eBUTTON_START = 0,
		eBUTTON_CHAPTER2 = eBUTTON_START,
		eBUTTON_CHAPTER3,
		eBUTTON_NUM,
	};
public:
    static cocos2d::Scene* createScene();

    virtual bool init();
    
    // a selector callback
    void menuCloseCallback(cocos2d::Ref* pSender);
	
    // 画面遷移ボタン押下時の挙動.
    void selectchapterbtn(cocos2d::Ref* pSender, int btnid);
    
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
	
};

 

HelloWorldScene.cpp

static const std::string btntext[HelloWorld::eBUTTON_NUM] = {
	"Chapter 2",	// eBUTTON_CHAPTER2
	"Chapter 3",	// eBUTTON_CHAPTER3
};

bool HelloWorld::init() {

   /* --- 略 --- */
    /////////////////////////////
    // 3. add your codes below...

    // add a label shows "Hello World"
    // create and initialize a label
    
    auto titlelabel = Label::createWithTTF("AI for Game Developer", "fonts/arial.ttf", 24);
    
    // position the label on the center of the screen
    Vec2 titlePos(Vec2(origin.x + visibleSize.width/2,
		   origin.y + visibleSize.height - titlelabel->getContentSize().height));
    titlelabel->setPosition(titlePos);

    // add the label as a child to this layer
    this->addChild(titlelabel, 1);
	
	// 画面遷移ボタン.
	for (int i = eBUTTON_START; i < eBUTTON_NUM; ++i) {
		Vec2 pos( titlePos.x, titlePos.y - 20 - 25*(i+1) );
		Label* pbtnlabel = Label::createWithTTF(btntext[i], "fonts/arial.ttf", 20);
		pbtnlabel->setTag(i);
		auto pBtn = MenuItemLabel::create(pbtnlabel, CC_CALLBACK_1(HelloWorld::selectchapterbtn, this, i));
		
		Menu* pMenu = Menu::create(pBtn, NULL);
		pMenu->setPosition(pos);
		this->addChild(pMenu, 1);
	}
/* --- 略 --- */
}

// 画面遷移ボタン.
void HelloWorld::selectchapterbtn(cocos2d::Ref* pSender, int btnid)
{
	switch (btnid) {
	case eBUTTON_CHAPTER2:
		log("chapter 2");
		break;
	case eBUTTON_CHAPTER3:
		log("chapter 3");
		break;
	default:
		break;
	}
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
	exit(0);
#endif
}

とりあえず、ボタンを押すとログだけ出るようにした。

背景のアイコンは「ゲーム開発者のためのAI入門」で作ったidenticonに変更。
デバッグ情報も出さないようにした。

f:id:merakuma:20170110005359p:plain

 今日はここまで

 

ゲーム開発者のためのAI入門

ゲーム開発者のためのAI入門

 

 

【海外ドラマ】SUITS シーズン4 Ep.2

Transcript

www.springfieldspringfield.co.uk

 

覚えておきたい表現

be willing to do

〜しても構わない 喜んで〜する

 

He's willing to decimate a company just to put some money in his pocket. 

You'll rearize that I'm willing to go to the distance.  

You'll not only be willing to give it to me, you're gonna be begging to give it to me.