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

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

Pythonのお勉強(1)

with文

コンテキストマネージャとして利用して、動作を制御することができる。(enterメソッド、exitメソッド)

以下の場合、writeメソッドの後、必ずファイルrobot.txtが閉じられる。

with open('robot.txt', 'r', encoding = 'utf8') as f:
    all_text = f.read()
    print(all_text) 

以下のように書くと、エラー処理などでファイルが閉じられない可能性があるため、上記のように書くことを推奨。

f = open('robot.txt', 'r', encoding = 'utf8')
for line in f:
    print(line , end='')
f.close()

ラムダ式

lambda 引数:命令

is_even = lambda x: x % 2 == 0
is_even(2)
-> True

引数

可変引数
  • *のときタプルになる
>>> def func(*hoge):
...   print hoge
...
>>> func("1","2","3")
('1', '2', '3')
  • **のとき辞書型になる
>>> def func(**hoge):
...   print hoge
...
>>> func(a=1,b=2,c=3)
{'a': 1, 'c': 3, 'b': 2}
>>>

イテレータ

参考;

10.1. itertools — 効率的なループ実行のためのイテレータ生成関数 — Python 3.6.5 ドキュメント

ジェネレータ

イテレータの一種

def robot_num(m):
    print("%d robot num" % m)
    while m < 5:
        if m == 4:
            print("m=4")
        yield m
        m += 1
    print("stop product robot")
    return

実行結果

In [2]: cnt = robot_num(2)

In [3]: next(cnt)
2 robot num
Out[3]: 2

In [4]: next(cnt)
Out[4]: 3

In [5]: next(cnt)
m=4
Out[5]: 4

In [6]: next(cnt)
stop product robot
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-6-77509b5792d1> in <module>()
----> 1 next(cnt)

StopIteration: 

デコレータ

関数やクラスの機能変更、拡張を行うための機構

@robot_log
def calc_add(robot1,robot2):
    return robot1+robot2

は以下と同じ

def calc_add(robot1,robot2):
    return robot1+robot2
calc_add = robot_log(calc_add)

ここで、robot_logを正しく作ると、この関数を呼ぶとlogをとるような機能を追加できる

スコープ

参考:RubyプログラマがPythonを学び始めて知ったこと10選 ④ - donghai821の日記

Pythonのクラスメンバのスコープまとめ - Qiita

Pythonメモ: privateやprotectedは

pythonにprivate変数がない件:千里の道も一歩から:So-netブログ

Python - Pythonの変数やメソッドの命名について(アンダーバー)(41277)|teratail

クロージャ

参考:Python Tips: Python でクロージャを使いたい - Life with Python

クラス継承

参考:

[Python]クラス継承(super) - Qiita

Python の super() 関数の使い方 - Life with Python

クラス属性とインスタンス属性

大事な考え方。要復習。クラスと名前空間と関連付けて整理しよう。

参考:Pythonでのクラス属性とインスタンス属性 - gogochephy’s diary

スタティックメソッド

以下のようにインスタンスに作用しないメソッド

class robot_calc(object):
    @staticmethod
    def robot_add(x,y): #selfがない
        return x+y

a = robot_calc.robot_add(1,2)

クラスメソッド

インスタンスではなくクラスそのものに作用するメソッド

class RoboVar:
    ene = 1

    @classmethod
    def full(cls, power):
        return cls.ene * power

class FullPower(RoboVar):
    ene = 2

x = FullPower.full(3) # RoboVar.full(FullPower,3) 

プライベートメンバ

  1. アンダースコアひとつ _robot → クラス内部だけで利用する
  2. アンダースコアふたつ __robot → クラス外部から参照できなくなる(厳密には_<クラス名>__<属性名>とすればアクセスできるがより安全)

Linuxコマンドを呼ぶ

#!/usr/bin/env python

import subprocess

p_test = subprocess.check_call(['ls','-a'])

参考: pythonでLinuxコマンドを実行する - ihit's diary

入出力

csv
import csv

with open('robodata.csv','r',encoding='utf8') as f:
    robodata = [k for k in csv.reader(f)]

with open('roboout.csv','w',newline='') as f:
    writer = csv.writer(f)
    writer.writerows(robodata)
pickle

以下のようにすることでオブジェクトの保存ができる

import pickle

mydata = [1,2,3]

with open('pickle_test.pickle','wb') as f: #バイナリ形式で開くこと
    pickle.dump(mydata,f)

with open('pickle_test.pickle','rb') as f:
    pic_data = pickle.load(f)

複数のオブジェクトを保存するときは以下のように記述

import pickle
import numpy as np

robo1 = np.float(28.0)
robo2 = np.array([[1.0,2.0],[3.0,4.0]])
robo3 = {'tetsujin':21, 'atom':'1000000'}

with open('pickle_test2.pickle','wb') as f: #バイナリ形式で開くこと
    pickle.dump([robo1,robo2,robo3],f)

with open('pickle_test2.pickle','rb') as f:
    [r1,r2,r3] = pickle.load(f)

print(r3['tetsujin'])

ソケット通信

  • connect : サーバーに接続
  • send : データ送信
  • sendall : すべて送りきるまで終わらない
  • settimeout : タイムアウト値を設定する
  • recv : データ受信
  • socket.timeout : exception OSErrorのサブクラス
  • socket.error : exception OSErrorの非推奨のエイリアス

参考:

スレッド

参考:

その他

  • struct.pack("i",data) : int型でdataをパックする
  • unicode() : unicodeへ変換
  • .split() : 単語を分割してリストへ
  • ~[-1] : リストの最後のもの
  • ~[0:-1] : リストの最初から最後から一つ手前まで
  • .append : リストの最後に追加
  • time.sleep : ~s待つ
  • .first()
  • .join() : 連結して一つの文字にする
  • .items() : 辞書をリストに変換
  • continue : 現在のループを終了して次のループへ

参考:

スクリプト言語コンパイル言語の違い

参考:

lint

*args **kwargs

glob

rosテストのお勉強(python)

unittest

CMakeLists.txt

catkin_python_setup()

if(CATKIN_ENABLE_TESTING)
  find_package(rostest REQUIRED)
  add_rostest(test/mytest.test)
endif()

package.xml

<test_depend>rostest</test_depend>
<test_depend>python-nose</test_depend>

↑テストにnoseをつかう場合

mytest.test

<launch>
  <node pkg="mypkg" type="mynode" name="mynode" />
  <test test-name="test_mynode" pkg="mypkg" type="test_mynode.py" />
</launch>

test_mynode.py

#!/usr/bin/env python

from nose.tools import eq_, raises

import unittest
import rostest, rospy

from mypkg.mytest import MyTest


class TestMyTest(unittest.TestCase):
    def setUp(self):
        pass

    @raises(rospy.ROSException)
    def test_mytest1(self):
        instance = MyTest()
        
    def test_mytest2(self):
        eq_(10 / 5, 2)

if __name__ == '__main__':
    rospy.init_node('test_sample')
    rostest.rosrun('mypkg',
                   'test_sample',
                   TestMyTest)

実行

$rostest test_rospy/test/mytest.test

setup.py

#!/usr/bin/env python

from distutils.core import setup

from catkin_pkg.python_setup import generate_distutils_setup

setup_args = generate_distutils_setup(
    packages=['rostest'],
    package_dir={'': 'src'},
)

setup(**setup_args)

rostest-test.test

<launch>
  <test test-name="test_rostest" pkg="rostest" type="test_rostest.py" />
</launch>

ディレクトリ構成

/src/rostest/src/rostest/~.py

参考:

ja/rospy_tutorials/Tutorials/Makefile - ROS Wiki

2. setup スクリプトを書く — Python 3.6.5 ドキュメント

参考:

ROS勉強記録: catkinでのpythonのtestについて

ROS C++コード用テストライブラリgtestの使い方(日本語訳) - MyEnigma

rostest - ROS Wiki

rostest - Minimum Working Example - ROS Answers: Open Source Q&A Forum

nose まとめ 1 - kuma8の日記

noseで気軽にテストを書く(+geventの場合) - Qiita

Pythonのデコレータについて - Qiita

ROSにおけるUnit/Integration/Regression Test (日本語訳) - MyEnigma

「rostest」 の使い方 - うごくものづくりのために

google test のインストールでハマったのでメモ - Qiita

pythonのテストを書いてみる

unittest

Robot and Animal

roboani.py

class Robot:
    def get_name(self):
        return "robot"
    def get_legs(self):
        return 2

class Animal:
    def get_name(self):
        return "animal"
    def get_legs(self):
        return 4

def calc_roboani_legs(robot,animal,heads,legs):
    robo_l = robot.get_legs()
    ani_l = animal.get_legs()
    robot_name = robot.get_name()
    animal_name = animal.get_name()
    animal_num = (legs - (robo_l*heads)) // (ani_l-robo_l)
    robot_num = heads - animal_num
    print "------"
    print "head",heads,"leg",legs
    print robot_num,animal_num
    return robot_num,animal_num

if __name__ == '__main__':
    calc_roboani_legs(Robot(),Animal(),heads=10,legs=28)

Test

test_roboani.py

import unittest, roboani

class TestRobotAnimal(unittest.TestCase):

    def setUp(self):
        self.robot = roboani.Robot()
        self.animal = roboani.Animal()

    def tearDown(self):
        pass

    def test_legs(self):
        self.assertEqual(self.robot.get_legs(),2,"leg num")
        self.assertEqual(self.animal.get_legs(),4,"leg num")

    
    def test_roboani(self):
        robot, animal = roboani.calc_roboani_legs(
            self.robot,self.animal,
            heads = 10, legs = 28)

        self.assertEqual((robot,animal) ,(6,4), "robot animal calc")

テスト実行

$ python -m unittest test_roboani

結果

.------
head 10 leg 28
6 4
.
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

mocktest

RobotDataBaseConnect

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

import unittest
from mock import Mock, patch

class DataBaseConnect(object):
    def __init__(self):
        pass

    def find(self, param):
        print('find ' + param)

class CalculationMovement(object):
    def __init__(self, data):
        self.__dataget = data

    def execute(self):
        return self.__dataget.find('param')

calc = CalculationMovement(DataBaseConnect())
calc.execute()

# ---------------- mock test --------------------------#

class CalculationModelTestCase(unittest.TestCase):
    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_execute_1(self):
        mock_test = Mock()  
        mock_test.find.return_value = 'mock_test'
        test_obj = CalculationMovement(mock_test)
        self.assertEqual('mock_test', test_obj.execute())
        self.assertEqual(mock_test.find.call_count, 1)
        self.assertEqual(list(mock_test.find.call_args_list[0]),
                         [('param',),{}])

    def test_execute_2(self):
        DataBaseConnect.find = Mock(return_value='mock_test')
        mock_test = DataBaseConnect()
        test_obj = CalculationMovement(mock_test)
        self.assertEqual('mock_test', test_obj.execute())

    def test_execute_3(self):
        with patch('__main__.DataBaseConnect') as mock_test:
            mock_test.find.return_value = 'with_mock_test'
            test_obj = CalculationMovement(mock_test)
            self.assertEqual('with_mock_test', test_obj.execute())

unittest.main()

結果

find param
...
----------------------------------------------------------------------
Ran 3 tests in 0.002s

OK

参考:

PythonでMockを使ったユニットテスト - 工作とかプログラミングとか

python - How to unittest that a thread is spawned? - Stack Overflow

サンプルでみる Python の Mock ライブラリ Mox の使い方 | CUBE SUGAR STORAGE

EasyMockでSocketクラスのモックを作る - Yのはてな

Pythonのテストコードでmockを使ってみた | DevelopersIO

Pythonのコードをきれいに書くためのTips | TRIVIAL TECHNOLOGIES 4 @ats のイクメン日記

http://momijiame.tumblr.com/post/22379282563/モックオブジェクトフレームワーク-pymox-を使って-python-のテストを書く

標準ライブラリのunittestで例外の発生を確認するテスト - podhmoの日記

unit testing - How do you test that a Python function throws an exception? - Stack Overflow

BeautifulSoupの使い方

BeautifulSoupを使ったスクレイピング

from BeautifulSoup import BeautifulSoup
import re

doc = ['<html><head><title>Page title</title></head>',
       '<body><p id="firstpara" align="center">This is paragraph <b>one</b>.',
       '<p id="secondpara" align="blah">This is paragraph <b>two</b>.',
       '</html>']
soup = BeautifulSoup(''.join(doc))

print soup.prettify()

print soup.contents[0].name
# u'html'

soup.findAll('p', align="center")
# [<p id="firstpara" align="center">This is paragraph <b>one</b>. </p>]

soup.find('p', align="center")
# <p id="firstpara" align="center">This is paragraph <b>one</b>. </p>

soup('p', align="center")[0]['id']
# u'firstpara'

参考:

`apt-get install`するまえに`apt-cache` でバージョンを調べる方法 - Qiita

正規表現

参考: Pythonでの正規表現の簡単なまとめ - minus9d's diary

Emacsの使い方

設定読み込み順

  • ~.emacs、~/.emacs.el、~/.emacs.d/init.elの順番に検索される
  • このうち複数のファイルがあったときはひとつしか読み込まれない

一括コメントアウト

  1. Mark set
  2. M-;

一括インデント

  1. Mark set
  2. C-c > or C-c <

対話置換

  1. M-%
  2. OK: y , NO: n , ALL: ! , EXIT: q

位置画面上・下

上. C-v 下. M-v

随時便利だと思うものを追記していきますヽ(´ー`)ノ

参考:

EmacsでPythonソースコードのインデントを深くor浅くする技 | 三鷹台でひきこもるプログラマの日記

init.el設定

参考: Emacs のおすすめ基本設定 | プログラマーズ雑記帳

pyflakesの設定

(defun flymake-xml-init ())

参考: emacs+pyflakes+flymakeでpythonの構文チェックを勝手にしてもらう - yukke::note

How to disable Emacs-Flymake for html mode - Stack Overflow

flymakeでファイルが開けない時
(delete '("\\.html?\\'" flymake-xml-init) flymake-allowed-file-name-masks)

参考:How to disable Emacs-Flymake for html mode - Stack Overflow

行数設定
(require 'linum)            ;\左に行番号表示
(global-linum-mode)
(column-numb

[https://stackoverflow.com/questions/4095153/how-to-disable-emacs-flymake-for-html-mode:title]



[https://stackoverflow.com/questions/4095153/how-to-disable-emacs-flymake-for-html-mode]

er-mode t)               ; 行番号と列番号を表示する
対応する括弧を光らせる
;; 対応する括弧を光らせる
(show-paren-mode 1)
自動補完

~/.emacs.d/init.el に以下を追加

(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/") t)
(add-to-list 'package-archives '("marmalade" . "http://marmalade-repo.org/packages/"))
(package-initialize)

M-x list-packages でauto-completeをiで選択xでインストール

(require 'auto-complete-config)
(ac-config-default)

参考:

Emacs24のパッケージ管理機能を使う - 計算物理屋の研究備忘録

Emacs初心者だがオススメ設定を晒させてくれ - Qiita

プロキシ環境下でEmacsを使う - 計算物理屋の研究備忘録

ロードパスの設定
;; ロードパスの設定
(setq load-path (append
                 '("~/.emacs.d"
                   "~/.emacs.d/packages")

参考:

Emacsのオススメ基本設定まとめ(.emacs.el) - Qiita

Emacs ビギナーに贈る、これからバリバリ使い隊!!人のための設定講座 その1。 - 日々、とんは語る。

python設定

参考: Emacs で Python 開発環境を構築 | Futurismo

lintの設定
el-getのインストール
  • ~/.emacs.d/.に以下をクローン
$ git clone https://github.com/dimitri/el-get.git
  • ~/.emacs.d/init.elに以下を追記
;; load-path で ~/.emacs.d とか書かなくてよくなる
(when load-file-name
  (setq user-emacs-directory (file-name-directory load-file-name)))

;; el-get
(add-to-list 'load-path (locate-user-emacs-file "el-get"))
(require 'el-get)
;; el-getでダウンロードしたパッケージは ~/.emacs.d/ に入るようにする
(setq el-get-dir (locate-user-emacs-file ""))
fly-checkのインストール
(el-get 'sync 'flycheck)
(require 'python)

(defun tnoda/turn-on-flycheck-mode ()
  (flycheck-mode 1))
(add-hook 'python-mode-hook 'tnoda/turn-on-flycheck-mode)

参考:

el-getを使ってみる - Qiita

Flycheck を Python で使うためにしたことメモ - Qiita

emacs+pyflakes+flymakeでpythonの構文チェックを勝手にしてもらう - yukke::note

音声認識の原理のお勉強

連続音声認識と一般的なパターン認識の違い

  • 連続音声認識は特徴抽出部の出力がひとつのベクトルではなく、ベクトル系列になる
  • 音素や単語を一つのクラスに対応付け
  • 文はそれらの系列として表現
  • 認識結果もクラスの系列となる
  • 連続音声認識は特徴ベクトルの系列を入力として長さが未知のクラス系列を認識する問題

音声認識手法

ベイズの定理より、

“単語列からの特徴ベクトル系列が発生する確率” と “単語列の観測される確率”

の積を最大とするような単語列を求める問題に落とし込める

これらの確率を求めるため、前者は音響モデル後者は言語モデルを利用する

以下を考えることで問題が解くことができる

  1. 音響モデルを用いた確率
  2. 言語モデルを用いた確率
  3. 2つの積を最大化する単語列を探索

言語モデルの作成方法は大きく2つの方法がある

  1. 文法記述
  2. 統計から単語列の生成確率を求める方法

音響モデル

によって音響モデルを作り鍛えていく

また、精度を良くする場合、調音結合を考慮して隠れマルコフモデルの単位はトライフォンを用いるのが良い

言語モデル

進み次第 追記していきます

必要な知識

  1. ベイズ推定
  2. 最尤推定
  3. GMM(Gaussian Mixture Model)
  4. HMM(Hidden Markov Model)
  5. RNN(Recurrent Neural Network)
  6. DNN(Deep Neural Network)
  7. EMアルゴリズム
  8. パターン認識
  9. 尤度
  10. 伝達関数
  11. スペクトル分析
  12. フーリエ変換
  13. ケプストラム分析
  14. 回帰分析
  15. ビタビアルゴリズム
  16. 多次元正規分布
  17. DAE(Denoising AutoEncoder)
  18. RBM(Restricted Boltzmann Machine)
  19. LSTM(Long Short-Term Memory)

参考

一次元の正規分布から多次元正規分布へ - "機械学習","信号解析","ディープラーニング"の勉強

尤度とは何者なのか? - MyEnigma

ベイズ推定 - Wikipedia

EMアルゴリズム - Wikipedia

文系エンジニアのための機械学習の勉強法 - Qiita

http://www.ms.k.u-tokyo.ac.jp/2015/IPSJ-math-jp.pdf

機械学習の学習法・オススメ本のまとめのまとめ - bohemia日記

誤差逆伝播法(バック・プロパゲーション)