ためすう
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
Ruby で MessagePack を使ってみる
2019-06-21やったこと
MessagePack を使ってみます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
$ gem list | grep msg
msgpack (1.2.10)
調査
gem インストール(もし必要だったら)
Gemfile
gem 'msgpack'
$ bundle install
pack と unpack してみる
MessagePack is an efficient binary serialization format
圧縮効率が良いらしいです。
$ rails c
Running via Spring preloader in process 56887
Loading development environment (Rails 5.2.3)
irb(main):001:0> msg = [1, 2, 3, "漢字"].to_msgpack
=> "\x94\x01\x02\x03\xA6\xE6\xBC\xA2\xE5\xAD\x97"
irb(main):002:0> MessagePack.unpack(msg)
=> [1, 2, 3, "漢字"]
メモリのサイズを見てみる
$ rails c
Running via Spring preloader in process 57354
Loading development environment (Rails 5.2.3)
irb(main):001:0> v = [1, 2, 3, "漢字"]
=> [1, 2, 3, "漢字"]
irb(main):002:0> require 'objspace'
=> true
irb(main):003:0> p ObjectSpace.memsize_of(v)
72
=> 72
irb(main):004:0> msg = [1, 2, 3, "漢字"].to_msgpack
=> "\x94\x01\x02\x03\xA6\xE6\xBC\xA2\xE5\xAD\x97"
irb(main):005:0> p ObjectSpace.memsize_of(msg)
40
=> 40
オブジェクトは圧縮されているようです。 (memsize_of で返される値は完全ではないらしい)
参考
第4章 アルゴリズムを交換する: Strategy part2
2019-06-20「Rubyによるデザインパターン」の読書メモです。
時々、個人の見解入りです。
クラスベースの Strategy ではなく、コードブロックベースの Strategy パターンで書いてみます。
Strategy を適用する (簡易版)
class Report
attr_reader :title, :text
attr_accessor :formatter
def initialize(&formatter)
@title = '月次報告'
@text = ['順調', '最高']
@formatter = formatter
end
def output_report
@formatter.call(self)
end
end
HTML_FORMATTER = lambda do |context|
puts '<html>'
puts "<head><title>#{context.title}</title></head>"
puts('<body>')
context.text.each do |line|
puts("<p>#{line}</p>")
end
puts('</body>')
puts '</html>'
end
PLAIN_TEXT_FORMATTER = lambda do |context|
puts("*****#{context.title}*****")
context.text.each do |line|
puts(line)
end
end
report = Report.new &HTML_FORMATTER
report.output_report
report = Report.new &PLAIN_TEXT_FORMATTER
report.output_report
コードブロックのストラテジは、そのインターフェースが単純で、1つのメソッドで事足りるようなときにのみ有効に働きます。
sidekiq で ログ出力する
2019-06-20やったこと
Rails5 で利用している sidekiq のログを出力します。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
$ gem list | grep sidekiq
sidekiq (5.2.7)
前提
sidekiq がインストール済みとします。
調査
ログ出力の設定
config/initializers/sidekiq.rb
Sidekiq::Logging.logger.level = Logger::DEBUG
sidekiq を再起動
$ bundle exec sidekiq -C config/sidekiq.yml
ログを確認
queue を登録して、worker を実行すると下記のログが流れます。
$ less log/sidekiq.log
2019-06-15T14:17:59.230Z 61557 TID-ovrdi8s0t TaskWorker JID-fe2e63bbd5eb7d0221a72f55 INFO: start
2019-06-15T14:17:59.233Z 61557 TID-ovrdi8s0t TaskWorker JID-fe2e63bbd5eb7d0221a72f55 INFO: id 出力
2019-06-15T14:17:59.233Z 61557 TID-ovrdi8s0t TaskWorker JID-fe2e63bbd5eb7d0221a72f55 INFO: 333
2019-06-15T14:17:59.233Z 61557 TID-ovrdi8s0t TaskWorker JID-fe2e63bbd5eb7d0221a72f55 INFO: done: 0.003 sec
参考
第4章 アルゴリズムを交換する: Strategy part1
2019-06-19「Rubyによるデザインパターン」の読書メモです。
時々、個人の見解入りです。
継承に基づいた設計は、いくつかの深刻な不利益をもたらします。たとえどんなに注意深くコードを設計しても、サブクラスはそのスーパークラスに依存してしまいます。
そこで、「委譲」を使ってコードを書き直してみます。
Strategy を適用する (version1)
class Formatter
def output_report(title, text)
raise 'Abstract method called'
end
end
class HTMLFormatter < Formatter
def output_report(title, text)
puts '<html>'
puts "<head><title>#{@title}</title></head>"
puts('<body>')
text.each do |line|
puts("<p>#{line}</p>")
end
puts('</body>')
puts '</html>'
end
end
class PlainTextFormatter < Formatter
def output_report(title, text)
puts("*****#{title}*****")
text.each do |line|
puts(line)
end
end
end
class Report
attr_reader :title, :text
attr_accessor :formatter
def initialize(formatter)
@title = '月次報告'
@text = ['順調', '最高']
@formatter = formatter
end
def output_report
@formatter.output_report(@title, @text)
end
end
report = Report.new(HTMLFormatter.new)
report.output_report
report.formatter = PlainTextFormatter.new
report.output_report
formatter を外から注入しているので、依存性の注入と言えそうです。
コンテキストとストラテジの間でのデータを共有する方法
- コンテキストがストラテジオブジェクトのメソッドを呼び出すときに引数で渡す
- ストラテジへと渡されたコンテキスト自身の参照を使う
- データの流れが単純化されますが、コンテキストとストラテジ間の結合度を上げてしまうことにもなります。
Strategy を適用する (version2)
Formatter クラスはインターフェースを規定するためにしか、存在しません。
Ruby のダックタイピングの哲学に反するため、削除します。
class HTMLFormatter
def output_report(title, text)
puts '<html>'
puts "<head><title>#{@title}</title></head>"
puts('<body>')
text.each do |line|
puts("<p>#{line}</p>")
end
puts('</body>')
puts '</html>'
end
end
class PlainTextFormatter
def output_report(title, text)
puts("*****#{title}*****")
text.each do |line|
puts(line)
end
end
end
class Report
attr_reader :title, :text
attr_accessor :formatter
def initialize(formatter)
@title = '月次報告'
@text = ['順調', '最高']
@formatter = formatter
end
def output_report
@formatter.output_report(@title, @text)
end
end
report = Report.new(HTMLFormatter.new)
report.output_report
report.formatter = PlainTextFormatter.new
report.output_report