ためすう
第6章 部分から全体を組み立てる: Composite
2019-06-24「Rubyによるデザインパターン」の読書メモです。
時々、個人の見解入りです。
「全体が部分のように振る舞う」という状況を表すデザインパターン
コンポジットオブジェクトの役割
1つにコンポジットオブジェクトはコンポーネントとしての役割を持っています。その一方で、コンポジットオブジェクトはコンポーネントのコレクションとしての役割も持っています。
例
class Task
attr_reader :name
def initialize(name)
@name = name
end
def get_time_required
0.0
end
end
class CompositeTask < Task
def initialize(name)
super(name)
@sub_tasks = []
end
def add_sub_task(task)
@sub_tasks << task
end
def remove_sub_task(task)
@sub_tasks.delete(task)
end
def get_time_required
time = 0.0
@sub_tasks.each {|task| time += task.get_time_required}
time
end
end
class AddDryIngredientsTask < Task
def initialize
super('Add dry ingredients')
end
def get_time_required
1.0
end
end
class MixTask < Task
def initialize
super('Mix that better up!')
end
def get_time_required
3.0
end
end
class MakeBatterTask < CompositeTask
def initialize
super('Make batter')
@sub_tasks = []
add_sub_task(AddDryIngredientsTask.new)
add_sub_task(MixTask.new)
end
end
p MakeBatterTask.new.get_time_required
演算子を実装したバージョン
class Task
attr_reader :name
def initialize(name)
@name = name
end
def get_time_required
0.0
end
end
class CompositeTask < Task
def initialize(name)
super(name)
@sub_tasks = []
end
def <<(task)
@sub_tasks << task
end
def [](index)
@sub_tasks[index]
end
def []=(index, value)
@sub_tasks[index] = value
end
def remove_sub_task(task)
@sub_tasks.delete(task)
end
def get_time_required
time = 0.0
@sub_tasks.each {|task| time += task.get_time_required}
time
end
end
class AddDryIngredientsTask < Task
def initialize
super('Add dry ingredients')
end
def get_time_required
1.0
end
end
class MixTask < Task
def initialize
super('Mix that better up!')
end
def get_time_required
3.0
end
end
class MakeBatterTask < CompositeTask
def initialize
super('Make batter')
@sub_tasks = []
@sub_tasks << AddDryIngredientsTask.new
@sub_tasks << MixTask.new
end
end
p MakeBatterTask.new.get_time_required
pandas の read_csv を使ってみる
2019-06-24やったこと
pandas で csv ファイルを読み込みます。
確認環境
$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
import pandas as pd
print(pd.__version__)
0.20.3
調査
read_csv
csv ファイルを読み込みます。
train = pd.read_csv("./train.csv")
戻り値は下記です。
DataFrame or TextParser
shape
shape を使って、行数と列数を確認します。
train.shape
(114321, 133)
size
train.size
15204693
参考
第5章 変更に追従する: Observer part2
2019-06-24「Rubyによるデザインパターン」の読書メモです。
時々、個人の見解入りです。
注意点
Observerパターンを使うときに発生する問題の多くは、更新の頻度とタイミングについてです。
実際に何か変更されたのでなければ、おそらくオブザーバに通知すべきではありません。
変更された時のみ通知を送るようにするパターン
require 'observer'
class Payroll
def update(changed_employee)
puts("#{changed_employee.name}のために小切手を切ります!")
puts("彼の給料はいま#{changed_employee.salary}です!")
end
end
class Employee
include Observable
attr_reader :name, :title, :salary
def initialize(name, title, salary)
@name = name
@title = title
@salary = salary
end
# 変更があった時だけ、通知を送るようにします
def salary=(new_salary)
if @salary == new_salary
nil
end
@salary = new_salary
changed
notify_observers(self)
end
end
fred = Employee.new('Fred', 'Crane Operator', 3000)
payroll = Payroll.new
fred.add_observer(payroll)
fred.salary = 3000
fred.salary = 3100
変更をまとめて通知するパターン
require 'observer'
class Payroll
def update(changed_employee)
puts("#{changed_employee.name}のために小切手を切ります!")
puts("title: #{changed_employee.title}")
puts("彼の給料はいま#{changed_employee.salary}です!")
end
end
class Employee
include Observable
attr_reader :name, :title, :salary
def initialize(name, title, salary)
@name = name
@title = title
@salary = salary
end
def salary=(new_salary)
if @salary == new_salary
nil
end
@salary = new_salary
end
def title=(new_title)
if @title == new_title
nil
end
@title = new_title
end
def changes_complete
changed
notify_observers(self)
end
end
fred = Employee.new('Fred', 'Crane Operator', 3000)
payroll = Payroll.new
fred.add_observer(payroll)
fred.title = 'superman'
fred.salary = 9000
fred.changes_complete
Jupyter Notebook で全ての行を表示する
2019-06-23やったこと
Jupyter Notebook で行数が多いデータを表示する時、省略されてしまうことがあります。
全部表示してみます。
ちなみに列数が多い場合は下記で対応できます。
確認環境
$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
print(pd.__version__)
0.20.3
調査
csv ファイルを読み込みます。
train = pd.read_csv("./train.csv")
train.dtypes
出力は省略
最大の表示行数を 150 に設定します。
# 現在の設定確認
print(pd.get_option("display.max_rows"))
pd.set_option('display.max_rows', 150)
60
これで150行まで表示されるようになりました。
参考
Jupyter Notebook で全ての列を表示する
2019-06-23やったこと
Jupyter Notebook で列数が多いデータを表示する時、省略されてしまうことがあります。
全部表示してみます。
確認環境
$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
print(pd.__version__)
0.20.3
調査
csv ファイルを読み込みます。
train = pd.read_csv("./train.csv")
train.shape
(114321, 133)
最大の表示列数を 200 に設定します。
# 現在の設定確認
print(pd.get_option("display.max_columns"))
pd.set_option('display.max_columns', 200)
20
参考
pandas のデータ構造 (Series と DataFrame ) を学ぶ
2019-06-23やったこと
pandas のデータ構造である
- Series
- DataFrame
について調べたことを書きます。
確認環境
$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
import pandas as pd
print(pd.__version__)
0.20.3
調査
Series (シリーズ)
シリーズは1次元の配列のようなオブジェクトです。シリーズには、(NumPayが持つデータ型の)データ配列とそれに関連付けられたインデックスというデータラベルの配列が含まれます。
obj = Series([4, 7, -5, 3])
obj
0 4
1 7
2 -5
3 3
dtype: int64
DataFrame (データフレーム)
データフレームはテーブル形式のスプレッドシート風のデータ構造を持ち、順序付けられた列を持っています。各列には別々の型(数値型、文字列型、ブール型、など)を持たせることができます。データフレームは行と列の両方にインデックスを持っています。
data = {'state': ['Ohio', 'Nevada'],
'year': [2000, 2001]}
df = DataFrame(data)
df
出力結果
state | year | |
---|---|---|
0 | Ohio | 2000 |
1 | Nevada | 2001 |
参考
- Pythonによるデータ分析入門
Jupyter Notebook で実行時間を計測するために %%time を使う
2019-06-23やったこと
Jupyter Notebook で処理の実行時間を計測する方法を調べました。
機械学習のモデルに学習させるときに、時間がかかりすぎることがあったため
実行時間を計測してみることにしました。
確認環境
$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
調査
セルごとに実行時間を計測します。
%%time
import numpy as np
import pandas as pd
CPU times: user 7 µs, sys: 1 µs, total: 8 µs
Wall time: 11.2 µs
何度か繰り返し実行して、実行時間のレポートが出力されます。
%%timeit
import numpy as np
import pandas as pd
191 ns ± 2.12 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
行ごとの実行時間を計測します。
%time 2**128
%time 2**128
CPU times: user 3 µs, sys: 1 µs, total: 4 µs
Wall time: 16.2 µs
CPU times: user 2 µs, sys: 1 µs, total: 3 µs
Wall time: 5.96 µs
340282366920938463463374607431768211456
参考
Jupyter Notebook について
2019-06-23やったこと
Jupyter Notebook について調べたことを書きます。
調査
Jupyter Notebook は、Jupyter プロジェクトによって開発されており、さまざまなプログラミング言語をサポートするインタラクティブなシェル環境である。
ここで、単語について記します。
IPython
インタラクティブシェル
Jupyter Notebook (IPython Notebook)
IPython をブラウザで利用できるようにしたもの
使ってみるにはどうするのかというと Anaconda をインストールすることで使えるようになります。
環境確認してみましょう。
$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
公式ドキュメントはこちらです
参考
- Python 機械学習プログラミング
Metrics optimization
学習目標
- Describe the role of correct metric optimization method in a competition
- Analyze new metrics
- Create constant baselines
- Recall the most important classification and regression metrics
- Describe what libraries can be used to optimize a particular metric
Regression metrics review II
今回対象のメトリクス
- ®MSPE, MAPE
- ®MSLE
MSPE: Mean Square Percentage Error
$$ MSPE = \frac{100\%}{N}\sum_{i=1}^N(\frac{y_i - \hat{y_i}}{y_i})^2 $$
最適な定数は加重平均
MAPE: Mean Absolute Percentage Error
$$ MSPE = \frac{100\%}{N}\sum_{i=1}^N|\frac{y_i - \hat{y_i}}{y_i}| $$
最適な定数は加重中央値
®MSLE: Root Mean Square Logarithmic Error
対数スケールで計算された RMSE
$$ RMSLE = \sqrt{\frac{1}{N}\sum_{i=1}^N (log({y_i}+1) - log(\hat{y_i} + 1))^2} $$
$$ = RMSE(log({y_i}+1), log(\hat{y_i} + 1) = \sqrt{MSE(log({y_i}+1), log(\hat{y_i} + 1)} $$
対数空間で RMSE の定数を見つけ、対数空間から逆変換する必要がある
参考
第5章 変更に追従する: Observer part1
2019-06-22「Rubyによるデザインパターン」の読書メモです。
時々、個人の見解入りです。
用語
Subject: サブジェクト
ニュースを持っているクラス
Observer: オブザーバ
ニュースを得ることに関心のあるオブジェクト
変更前
class Payroll
def update(changed_employee)
puts("#{changed_employee.name}のために小切手を切ります!")
puts("彼の給料はいま#{changed_employee.salary}です!")
end
end
class Employee
attr_reader :name, :title, :salary
def initialize(name, title, salary, payroll)
@name = name
@title = title
@salary = salary
@payroll = payroll
end
def salary=(new_salary)
@salary = new_salary
@payroll.update(self)
end
end
payroll = Payroll.new
fred = Employee.new('Fred', 'Crane Operator', 3000, payroll)
fred.salary = 3500
継承を利用したパターン
class Subject
def initialize
@observers = []
end
def add_observer(observer)
@observers << observer
end
def delete_observer(observer)
@observers.delete(observer)
end
def notify_observers
@observers.each do |observer|
observer.update(self)
end
end
end
class Payroll
def update(changed_employee)
puts("#{changed_employee.name}のために小切手を切ります!")
puts("彼の給料はいま#{changed_employee.salary}です!")
end
end
class Employee < Subject
attr_reader :name, :title, :salary
def initialize(name, title, salary)
super()
@name = name
@title = title
@salary = salary
end
def salary=(new_salary)
@salary = new_salary
notify_observers
end
end
fred = Employee.new('Fred', 'Crane Operator', 3000)
payroll = Payroll.new
fred.add_observer(payroll)
fred.salary = 3500
モジュールを利用したパターン
module Subject
def initialize
@observers = []
end
def add_observer(observer)
@observers << observer
end
def delete_observer(observer)
@observers.delete(observer)
end
def notify_observers
@observers.each do |observer|
observer.update(self)
end
end
end
class Payroll
def update(changed_employee)
puts("#{changed_employee.name}のために小切手を切ります!")
puts("彼の給料はいま#{changed_employee.salary}です!")
end
end
class Employee
include Subject
attr_reader :name, :title, :salary
def initialize(name, title, salary)
super()
@name = name
@title = title
@salary = salary
end
def salary=(new_salary)
@salary = new_salary
notify_observers
end
end
fred = Employee.new('Fred', 'Crane Operator', 3000)
payroll = Payroll.new
fred.add_observer(payroll)
fred.salary = 3500
ライブラリを利用したパターン
require 'observer'
class Payroll
def update(changed_employee)
puts("#{changed_employee.name}のために小切手を切ります!")
puts("彼の給料はいま#{changed_employee.salary}です!")
end
end
class Employee
include Observable
attr_reader :name, :title, :salary
def initialize(name, title, salary)
@name = name
@title = title
@salary = salary
end
def salary=(new_salary)
@salary = new_salary
changed
notify_observers(self)
end
end
fred = Employee.new('Fred', 'Crane Operator', 3000)
payroll = Payroll.new
fred.add_observer(payroll)
fred.salary = 3500