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

空飛ぶロボットのつくりかた

ロボットをつくるために必要な技術をまとめます。ロボットの未来についても考えたりします。

pythonのテストを書いてみる2

Python Test

数値微分

プロダクションコード

# -*- coding:utf-8 -*-                                                          

# 2次関数の数値微分を行うクラス                                                 
class Diff:
    # 2次関数                                                                   
    def f(self,x):
        y = x**2
        return y

    # 数値微分                                                                  
    def numerical_diff(self,f,x,dx):
        if dx == 0:
            raise ValueError('division by zero')
        else:
            x_diff = (f(x+dx)-f(x-dx))/(2*dx)
            return x_diff

if __name__ == '__main__':
    diff = Diff()
    print diff.numerical_diff(diff.f,3,0.001)

テストコード

# -*- coding:utf-8 -*-                                                 
import unittest, numerical_diff

class TestDiff(unittest.TestCase):
    # 前処理                                                           
    def setUp(self):
        self.diff = numerical_diff.Diff()

    # 後片付け                                                         
    def tearDowm(self):
        pass

    # 3の2乗のテスト                                                   
    def test_func1(self):
        self.assertEqual(self.diff.f(3),9)

    # 4の2乗のテスト                                                   
    def test_func2(self):
        self.assertEqual(self.diff.f(4),16)

    # 数値微分ができているかのテスト                                   
    def test_numerical_diff(self):
        self.assertAlmostEqual(self.diff.numerical_diff(self.diff.f,3,0.001),6.0, delta=1e-8)
        self.assertEqual(round(self.diff.numerical_diff(self.diff.f,3,0.001)),6.0)

    # 0で割られたときの例外のテスト                                    
    def test_numerical_diff_zero_error(self):
        with self.assertRaises(ValueError) as cm:
            self.diff.numerical_diff(self.diff.f,3,0.0)
        exception = cm.exception
        self.assertEqual(exception.message, 'division by zero')

文字の変換

プロダクションコード

#-*- coding:utf-8 -*-
import re

class StringUtils:
    def to_snake_case(self,text):
        if len(text) is 0:
            raise ValueError('snake case error')
        else:
            snake = re.sub("([A-Z])",lambda x:"_" + x.group(1).lower(),text)
            return re.sub("^_","",snake)

    def to_camel_case(self,text):
        if len(text) is 0:
            raise ValueError('camel case error')
        else:
            camel = re.sub("_(.)",lambda x:x.group(1).upper(),text)
            return re.sub("^(.)",lambda x:x.group(1).upper(),camel)

if __name__ == '__main__':
    camel = "CamelCase"
    snake = "snake_case"
    string_utils = StringUtils()
    print string_utils.to_snake_case(camel)
    print string_utils.to_camel_case(snake)

テストコード

# -*- coding:utf-8 -*-
import unittest, string_utils

class TestStringUtils(unittest.TestCase):
    # 前処理
    def setUp(self):
        self.su = string_utils.StringUtils()

    # 後片付け
    def tearDowm(self):
        pass

    # camel->snake, snake->camelへの変換テスト
    def test_to_snake_case1(self):
        self.assertEqual(self.su.to_snake_case("CamelCase"),"camel_case")

    def test_to_snake_case2(self):
        self.assertEqual(self.su.to_snake_case("camelCase"),"camel_case")

    def test_to_snake_case3(self):
        self.assertEqual(self.su.to_snake_case("camelcase"),"camelcase")

    def test_to_camel_case1(self):
        self.assertEqual(self.su.to_camel_case("snake_case"),"SnakeCase")

    def test_to_camel_case2(self):
        self.assertEqual(self.su.to_camel_case("Snake_Case"),"SnakeCase")

    def test_to_camel_case3(self):
        self.assertEqual(self.su.to_camel_case("SnakeCase"),"SnakeCase")


    # 文字がない場合の例外のテスト
    def test_snake_error(self):
        with self.assertRaises(ValueError) as cm:
            self.su.to_snake_case("")
        exception = cm.exception
        self.assertEqual(exception.message, 'snake case error')

    def test_camel_error(self):
        with self.assertRaises(ValueError) as cm:
            self.su.to_camel_case("")
        exception = cm.exception
        self.assertEqual(exception.message, 'camel case error')

カウント

プロダクションコード

# -*- coding:utf-8 -*-

class Counter:
    def __init__(self):
        self.count = 0
    def increment(self):
        self.count += 1
        return self.count

if __name__ == '__main__':
    counter = Counter()
    for i in range(10):
        print counter.increment()

テストコード

# -*- coding:utf-8 -*-
import unittest, counter

class TestCounter(unittest.TestCase):
    # 前処理
    def setUp(self):
        self.ct = counter.Counter()

    # 後片付け
    def tearDowm(self):
        pass

    # カウントできているかのテスト
    def test_count_init(self):
        self.assertEqual(self.ct.increment(),1)

    def test_count_2(self):
        self.ct.increment()
        self.assertEqual(self.ct.increment(),2)

    def test_count_100(self):
        for i in range(100):
            self.ct.increment()
        self.assertEqual(self.ct.increment(),101)

偶数判定

プロダクションコード

# -*- coding:utf-8 -*-

class NumberUtils:
    def even(self,num):
        return num % 2 == 0

if __name__ == '__main__':
    number = NumberUtils()
    print number.even(2)
    print number.even(3)

テストコード

# -*- coding:utf-8 -*-
import unittest, number_utils

class TestStringUtils(unittest.TestCase):
    # 前処理
    def setUp(self):
        self.nu = number_utils.NumberUtils()

    # 後片付け
    def tearDowm(self):
        pass

    def test_even(self):
        self.assertTrue(self.nu.even(2))

    def test_odd(self):
        self.assertFalse(self.nu.even(3))

物品管理

プロダクションコード

# -*- coding:utf-8 -*-

class Item:
    def __init__(self,name,price):
        self.name = name
        self.price = price

    def get_name(self):
        return self.name

    def get_price(self):
        return self.price

class ItemStock:
    def __init__(self):
        self.item_dic = {}

    def add(self, item):
        num = self.item_dic.get(item.name)
        if num is None:
            num = 0
        num +=1
        self.item_dic[item.name] = num

    def get_num(self, item):
        num = self.item_dic.get(item.name)
        if num is not None:
            return num
        else:
            return 0

if __name__ == '__main__':
    drone = Item("drone",6800)
    robot = Item("robot",10000)
    item_stock = ItemStock()
    item_stock.add(drone)
    item_stock.add(drone)
    item_stock.add(robot)
    print drone.get_name(),drone.get_price()
    print item_stock.get_num(drone)
    print robot.get_name(),robot.get_price()
    print item_stock.get_num(robot)

テストコード

# -*- coding:utf-8 -*-
import unittest, item_stock

class TestItemSocket(unittest.TestCase):
    # 前処理
    def setUp(self):
        self.itemstock = item_stock.ItemStock()
        self.drone = item_stock.Item("drone",6800)
        self.robot = item_stock.Item("robot",10000)

    # 後片付け
    def tearDowm(self):
        pass

    def test_init(self):
        self.assertEqual(self.itemstock.get_num(self.drone),0)

    def test_one_object_add_1(self):
        self.itemstock.add(self.drone)
        self.assertEqual(self.itemstock.get_num(self.drone),1)

    def test_one_object_add_2(self):
        self.itemstock.add(self.drone)
        self.itemstock.add(self.drone)
        self.assertEqual(self.itemstock.get_num(self.drone),2)

    def test_two_object_add_2_and_1(self):
        self.itemstock.add(self.drone)
        self.itemstock.add(self.drone)
        self.itemstock.add(self.robot)
        self.assertEqual(self.itemstock.get_num(self.drone),2)
        self.assertEqual(self.itemstock.get_num(self.robot),1)

スレッド

(TBD)

プロダクションコード

テストコード

参考: Python コメント、Pydoc - @//メモ Pythonで学ぶ 基礎からのプログラミング入門 (32) マルチスレッド処理を理解しよう(前編) | マイナビニュース

robonchu.hatenablog.com

テストを学ぼう (1) ! ~ユニットテストについて~

Test Python

ユニットテストってなんでするの?

書いたコードがちゃんと動くか不安だから。

テストを書いておくといくらかの安心を得ることができます。安心大事。

また、大胆にリファクタリングだってできちゃう。

以下の考え方はユニットテストが基盤

  1. 継続的テスト
  2. テスト駆動開発
  3. ビヘイビア駆動開発

継続的テストとは

テストを早い段階から(できれば自動的に)回すことが大事。その心は、手戻り、リグレッション(テストに失敗→修正→新たな問題が発生)が発生するからです。

ユニットテストは最小クラスの部品などを対象とするため、早い段階から回すことができます。また、自動化がしやすく、ローコストで繰り返し行うことができます。

こうすることで、修正による影響がすぐにフィードバックされ、安心してリリースができる。

参考:継続的テスト: IBM の見解  継続的テストの利点

テスト駆動開発とは

プロダクションコードを書く前にテストを書く方法。テストファースト。目的が明確になるため、目的にあったすっきりとしたコードがかける。

参考:@IT:特集 「テスト駆動開発」はプログラマのストレスを軽減するか?

ビヘイビア駆動開発とは

仕様を起点とした開発手法。テストファーストに対してスペックファーストという。

pythonでは「behave」という振舞駆動開発ツールがある。

参考: 振る舞い駆動開発入門  ビヘイビア駆動開発 - Wikipedia  Welcome to behave! — behave 1.2.5 documentation  ビヘイビア駆動開発ツール 

ユニットテストを書いてみよう

pythonでunittestを用いるものとする

参考: Pythonでエラーが発生することをテストする - Misc Notes

以下のプロダクトコードとテストコードを同じフォルダに配置する

プロダクトコード

数値微分をしてみる

以下をnumerical_diff.pyとして保存

# -*- coding:utf-8 -*-                                                          

# 2次関数の数値微分を行うクラス                                                 
class Diff:
    # 2次関数                                                                   
    def f(self,x):
        y = x**2
        return y

    # 数値微分                                                                  
    def numerical_diff(self,f,x,dx):
        if dx == 0:
            raise ValueError('division by zero')
        else:
            x_diff = (f(x+dx)-f(x-dx))/(2*dx)
            return x_diff

if __name__ == '__main__':
    diff = Diff()
    print diff.numerical_diff(diff.f,3,0.001)

テストコード

以下をtest_numerical_diff.pyとして保存

# -*- coding:utf-8 -*-                                                 
import unittest, numerical_diff

class TestDiff(unittest.TestCase):
    # 前処理                                                           
    def setUp(self):
        self.diff = numerical_diff.Diff()

    # 後片付け                                                         
    def tearDowm(self):
        pass

    # 3の2乗のテスト                                                   
    def test_func1(self):
        self.assertEqual(self.diff.f(3),9)

    # 4の2乗のテスト                                                   
    def test_func2(self):
        self.assertEqual(self.diff.f(4),16)

    # 数値微分ができているかのテスト                                   
    def test_numerical_diff(self):
        self.assertAlmostEqual(self.diff.numerical_diff(self.diff.f,3,0.001),6.0, delta=1e-8)
        self.assertEqual(round(self.diff.numerical_diff(self.diff.f,3,0.001)),6.0)

    # 0で割られたときの例外のテスト                                    
    def test_numerical_diff_zero_error(self):
        with self.assertRaises(ValueError) as cm:
            self.diff.numerical_diff(self.diff.f,3,0.0)
        exception = cm.exception
        self.assertEqual(exception.message, 'division by zero')

実行方法

以下を上記フォルダ内で実行

python -m unittest test_numerical_diff

実行結果

....
----------------------------------------------------------------------
Ran 4 tests in 0.000s

OK

小型USBにubuntu16.04をいれてみる(macbookから起動できるように編)

Linux

myenigma.hatenablog.com

MyEnigmaさんの記事に刺激を受け、小型USBにubuntu16.04を入れてみました。

手順は少し異なります。

準備

  1. 適当USB 4GB
  2. 小型USB 64GB↓

安い!小さい!

https://www.amazon.co.jp/SANDISK-USB3-0%E3%83%95%E3%83%A9%E3%83%83%E3%82%B7%E3%83%A5-64GB-SDCZ43-064G-ULTRA/dp/B00LLEODCK/ref=pd_bxgy_147_img_2?_encoding=UTF8&psc=1&refRID=CJARWHRR2CQR1XTV6RKC

手順

  1. UNetbootin - Homepage and Downloadsのインストール
  2. ubuntu16.04のISOファイルのダウンロード
  3. unetbootinを用いてISOファイルを適当USBへイン
  4. この適当USBと小型USBをMacbookに指しoptionキーを押しながら再起動
  5. ubuntuを選択し、インストールなしで実行を選択
  6. Ubuntu14.04LTSをUSBメモリにインストールする - 余白を参考に小型USBのパーティションを分ける
  7. ここで、分けたパーティションにubuntu16.04をインストール
  8. 再起動
  9. rEFIndを小型USBに作成したFAT32パーティションへコピー(上記MyEnigmaさんのブログ参考)
  10. リカバリーモード、command+rキーを押しながら再起動
  11. ターミナルを開いて$ /Volumes/~/refind-installを実行
  12. 再起動でUbuntuMacを選択できるように!!!

以上の手順でMacbookの環境を汚さずにUSBからUBUNTUが起動できるようになりました。 やった〜!!!

便利なツール

SDカードフォーマッター - SD Association

Ubuntu14.04(CPU only)でSegNetを使ってみる

Machine Learning

手順

  • caffe-segnetのダウンロード
git clone https://github.com/alexgkendall/caffe-segnet.git

Caffe | Installation: Ubuntu

CPU only の設定に変更

Caffe | Installation

For CPU-only Caffe, uncomment CPU_ONLY := 1 in Makefile.config.

caffe-segnetの中のpythonフォルダ

export PYTHONPATH={適切なpathの設定}/caffe-segnet/python:$PYTHONPATH 
cd /
git clone https://github.com/alexgkendall/SegNet-Tutorial.git
mv SegNet-Tutorial SegNet
cd /SegNet/Example_Models
wget http://mi.eng.cam.ac.uk/projects/segnet/models/segnet_weights_driving_webdemo.caffemodel
  • サンプルプログラムを以下のように修正

SegNet/Script/webcam_demo.pyを写真から読みこむ設定に変更

名前はpicture_demo.pyに変更

(TBD)
  • サンプルの実行
python picture.py --model /SegNet/Example_Models/segnet_model_driving_webdemo.prototxt --weights /SegNet/Example_Models/segnet_weights_driving_webdemo.caffemodel --colours /SegNet/Scripts/camvid12.png
  • 実行結果

参考:

SegNet

OpenCV 備忘録: SegNetをUbuntuで試してみた

reveal.js参考まとめ(Markdownでプレゼン資料作り)

Memo Editor

参考

reveal.js – The HTML Presentation Framework

Reveal.js、Markdown、Githubでスライドを作成する。 - Qiita

reveal.js で markdown を使う(2015年3月版) - Qiita

reveal.jsを使ってみる - Faster and Faster

プレゼンもmarkdownでね!reveal.jsで資料を作成してみた - Qiita

PyCharmの使い方

Editor

windowspythonの開発をするときとかに便利

ライブラリのインストール

  • File -> Setting -> Project Interpreter の+ボタンで追加

簡単にインストールできる。numpyとか検索してワンクリックでインストール

python2 or 3 の指定

キーマップの変更

  • File -> Setting -> key map

Emacsキーバインドもあるよ

データセットの作り方参考まとめ

Machine Learning

chainerのデータセットの作り方 LinearやCNN - Qiita

機械学習で用いる顔画像データセットの一作り方(1:WebAPIサービスを用いて候補画像取得) - Qiita

【pylearn2】自分のデータセットを使ってカンタンにGRBMしよう - CORDEA blog