Itsukaraの日記

最新IT技術を勉強・実践中。最近はDeep Learningに注力。

でんき家計簿:最新版及び将来変更への対応

1年半ぐらい前に、東京電力の「でんき家計簿」からデータをスクレイピングするプログラムを書いたのですが、当方は既に東京ガスに移ったので、放ってありました。しかし、最近になって、使いたいという方がいらっしゃたので、「でんき家計簿」の最新版に対応しました。また、将来の多少の変更にも対応できるようにしました。

かなり前に書いたので、かなり忘れていることも多く、またSeleniumの利用環境の準備方法も多少変わったので色々と修正が必要でしたが、良い復習になりました。

関連記事

itsukara.hateblo.jp

今週のはてなブログランキング [2018年2月第2週]に掲載!

今週のはてなブログランキング [2018年2月第2週]に載りました。
ずっと下の方の14位ではありますが、載って非常に嬉しいです。

blog.hatenablog.com

exp(π*i) = -1をPythonでも計算してみました

直前の記事でexp(π*i) = -1をrubyで計算しましたが、Pythonでも特殊メソッドを使うとでオーバーロードできるので、試しに書いてみました。

rubyのプログラムと同じ構造にしましたが、特殊メソッドの部分(__add__等)が、今一つ美しくない気がします。なお、計算結果は最後の桁まで全く同じでした。

プログラム

import math
class C():
    def __init__(self, r, i):
        self.r = r
        self.i = i

    def __add__(self, c2):
        if type(c2) != C:
            raise
        return C(self.r + c2.r, self.i + c2.i)

    def __mul__(self, c2):
        if type(c2) != C:
            raise
        return C(self.r * c2.r - self.i * c2.i, self.r * c2.i + self.i * c2.r)

    def __truediv__(self, r):
        if type(r) != float:
            raise
        return C(self.r / r, self.i / r)

    def __str__(self):
        return str(self.r) + " + " + str(self.i) + "i"

def cexp(c, n, c1):
    s = c1 + c
    num = c   # Numerator
    den = 1.0 # Denominator
    for i in range(2, n+1):
        print("i={}, s={}, 1/den={}".format(i, s, 1/den))
        num = num * c
        den = den * i
        s = s + num / den
    return s

pi_i = C(0, math.pi)
c1 = C(1.0, 0.0)
print("cexp(pi_i, 50, c1)={}".format(cexp(pi_i, 50, c1)))

計算結果

結果は、正確な-1にはならず、「-1.1e-16」程度の大きさの虚数部が残ってしまいましたが、rubyでの計算結果と全く同じでした(最後の桁まで同じ)。

i=2, s=1.0 + 3.141592653589793i, 1/den=1.0
i=3, s=-3.934802200544679 + 3.141592653589793i, 1/den=0.5
i=4, s=-3.934802200544679 + -2.0261201264601763i, 1/den=0.16666666666666666
i=5, s=0.1239099258720886 + -2.0261201264601763i, 1/den=0.041666666666666664
i=6, s=0.1239099258720886 + 0.5240439134171684i, 1/den=0.008333333333333333
i=7, s=-1.2113528429825005 + 0.5240439134171684i, 1/den=0.001388888888888889
i=8, s=-1.2113528429825005 + -0.0752206159036235i, 1/den=0.0001984126984126984
i=9, s=-0.9760222126236073 + -0.0752206159036235i, 1/den=2.48015873015873e-05
i=10, s=-0.9760222126236073 + 0.006925270707504691i, 1/den=2.7557319223985893e-06
i=11, s=-1.0018291040136214 + 0.006925270707504691i, 1/den=2.755731922398589e-07
i=12, s=-1.0018291040136214 + -0.00044516023820965686i, 1/den=2.505210838544172e-08
i=13, s=-0.9998995297042175 + -0.00044516023820965686i, 1/den=2.08767569878681e-09
i=14, s=-0.9998995297042175 + 2.1142567557955476e-05i, 1/den=1.6059043836821613e-10
i=15, s=-1.0000041678091423 + 2.1142567557955476e-05i, 1/den=1.1470745597729725e-11
i=16, s=-1.0000041678091423 + -7.72785889874728e-07i, 1/den=7.647163731819816e-13
i=17, s=-0.9999998647395553 + -7.72785889874728e-07i, 1/den=4.779477332387385e-14
i=18, s=-0.9999998647395553 + 2.2419510272822888e-08i, 1/den=2.8114572543455206e-15
i=19, s=-1.00000000352908 + 2.2419510272822888e-08i, 1/den=1.5619206968586225e-16
i=20, s=-1.00000000352908 + -5.289187244469688e-10i, 1/den=8.22063524662433e-18
i=21, s=-0.9999999999243491 + -5.289187244469688e-10i, 1/den=4.110317623312165e-19
i=22, s=-0.9999999999243491 + 1.0347741813843647e-11i, 1/den=1.9572941063391263e-20
i=23, s=-1.0000000000013562 + 1.0347741813843647e-11i, 1/den=8.896791392450574e-22
i=24, s=-1.0000000000013562 + -1.7072990308840883e-13i, 1/den=3.8681701706306835e-23
i=25, s=-0.9999999999999793 + -1.7072990308840883e-13i, 1/den=1.6117375710961184e-24
i=26, s=-0.9999999999999793 + 2.292021495202086e-15i, 1/den=6.446950284384474e-26
i=27, s=-1.0000000000000002 + 2.292021495202086e-15i, 1/den=2.4795962632247972e-27
i=28, s=-1.0000000000000002 + -1.405396847913007e-16i, 1/den=9.183689863795546e-29
i=29, s=-1.0 + -1.405396847913007e-16i, 1/den=3.2798892370698385e-30
i=30, s=-1.0 + -1.1097266936275162e-16i, 1/den=1.1309962886447718e-31
i=31, s=-1.0 + -1.1097266936275162e-16i, 1/den=3.769987628815906e-33
i=32, s=-1.0 + -1.1128644865909646e-16i, 1/den=1.2161250415535181e-34
i=33, s=-1.0 + -1.1128644865909646e-16i, 1/den=3.800390754854744e-36
i=34, s=-1.0 + -1.1128351600992583e-16i, 1/den=1.151633562077195e-37
i=35, s=-1.0 + -1.1128351600992583e-16i, 1/den=3.387157535521162e-39
i=36, s=-1.0 + -1.1128354033268814e-16i, 1/den=9.67759295863189e-41
i=37, s=-1.0 + -1.1128354033268814e-16i, 1/den=2.6882202662866367e-42
i=38, s=-1.0 + -1.112835401524659e-16i, 1/den=7.265460179153072e-44
i=39, s=-1.0 + -1.112835401524659e-16i, 1/den=1.9119632050402823e-45
i=40, s=-1.0 + -1.1128354015366612e-16i, 1/den=4.902469756513544e-47
i=41, s=-1.0 + -1.1128354015366612e-16i, 1/den=1.225617439128386e-48
i=42, s=-1.0 + -1.112835401536589e-16i, 1/den=2.989310827142405e-50
i=43, s=-1.0 + -1.112835401536589e-16i, 1/den=7.11740673129144e-52
i=44, s=-1.0 + -1.1128354015365895e-16i, 1/den=1.6552108677421951e-53
i=45, s=-1.0 + -1.1128354015365895e-16i, 1/den=3.761842881232262e-55
i=46, s=-1.0 + -1.1128354015365895e-16i, 1/den=8.359650847182804e-57
i=47, s=-1.0 + -1.1128354015365895e-16i, 1/den=1.8173154015614793e-58
i=48, s=-1.0 + -1.1128354015365895e-16i, 1/den=3.866628513960594e-60
i=49, s=-1.0 + -1.1128354015365895e-16i, 1/den=8.055476070751238e-62
i=50, s=-1.0 + -1.1128354015365895e-16i, 1/den=1.643974708316579e-63
cexp(pi_i, 50, c1)=-1.0 + -1.1128354015365895e-16i

参考にした記事

d.hatena.ne.jp

exp(π*i) = -1をrubyで計算してみました

仕事でRubyを少し使っていたのですが、これまでは、Rubyの勉強をあまりせずに、既存のプログラムを見よう見まねで改修していました。少し深く理解したいと思い、Rubyのリファレンスマニュアルを読んだので、試しにプログラムを書いてみました。

内容は、e^{{\pi}i}を計算して、値が-1になるか確認するものです。

代入や加減乗除オーバーロードにより非常に簡潔に書け、便利と感じました。

プログラム

RubyにはComplex型があるのですが、意図的にこれを使わずに、自前で複素数演算クラスを定義しています。

class C
  attr_reader :r, :i
  def initialize(r, i)
    @r = r; @i = i
  end

  def +(c)
    raise unless c.class == C
    C.new(@r + c.r, @i + c.i)
  end

  def *(c)
    raise unless c.class == C
    C.new(@r * c.r - @i * c.i, @r * c.i + @i * c.r)
  end

  def /(r2)
    raise unless r2.class == Float
    C.new(@r / r2, @i / r2)
  end
  
  def to_s
    @r.to_s + " + " + @i.to_s + "i"
  end
end

def exp(c, n, c1)
  s = c1 + c
  num = c   # Numerator
  den = 1.0 # Denominator
  for i in 2..n
    puts "i=#{i}, s=#{s}, 1/den=#{1/den}"
    num = num * c
    den = den * i
    s = s + num / den
  end
  return s
end

pi_i = C.new(0, Math::PI)
c1 = C.new(1.0, 0.0)
puts "exp(pi_i, 50, c1)=#{exp(pi_i, 50, c1)}"

計算結果

結果は、正確な-1にはならず、「-1.1e-16」程度の大きさの虚数部が残ってしまいました。原因は、Ruby浮動小数点の精度の限界によるものですね。

i=2, sum=1.0 + 3.141592653589793i, 1/den=1.0
i=3, sum=-3.934802200544679 + 3.141592653589793i, 1/den=0.5
i=4, sum=-3.934802200544679 + -2.0261201264601763i, 1/den=0.16666666666666666
i=5, sum=0.1239099258720886 + -2.0261201264601763i, 1/den=0.041666666666666664
i=6, sum=0.1239099258720886 + 0.5240439134171684i, 1/den=0.008333333333333333
i=7, sum=-1.2113528429825005 + 0.5240439134171684i, 1/den=0.001388888888888889
i=8, sum=-1.2113528429825005 + -0.0752206159036235i, 1/den=0.0001984126984126984
i=9, sum=-0.9760222126236073 + -0.0752206159036235i, 1/den=2.48015873015873e-05
i=10, sum=-0.9760222126236073 + 0.006925270707504691i, 1/den=2.7557319223985893e-06
i=11, sum=-1.0018291040136214 + 0.006925270707504691i, 1/den=2.755731922398589e-07
i=12, sum=-1.0018291040136214 + -0.00044516023820965686i, 1/den=2.505210838544172e-08
i=13, sum=-0.9998995297042175 + -0.00044516023820965686i, 1/den=2.08767569878681e-09
i=14, sum=-0.9998995297042175 + 2.1142567557955476e-05i, 1/den=1.6059043836821613e-10
i=15, sum=-1.0000041678091423 + 2.1142567557955476e-05i, 1/den=1.1470745597729725e-11
i=16, sum=-1.0000041678091423 + -7.72785889874728e-07i, 1/den=7.647163731819816e-13
i=17, sum=-0.9999998647395553 + -7.72785889874728e-07i, 1/den=4.779477332387385e-14
i=18, sum=-0.9999998647395553 + 2.2419510272822888e-08i, 1/den=2.8114572543455206e-15
i=19, sum=-1.00000000352908 + 2.2419510272822888e-08i, 1/den=1.5619206968586225e-16
i=20, sum=-1.00000000352908 + -5.289187244469688e-10i, 1/den=8.22063524662433e-18
i=21, sum=-0.9999999999243491 + -5.289187244469688e-10i, 1/den=4.110317623312165e-19
i=22, sum=-0.9999999999243491 + 1.0347741813843647e-11i, 1/den=1.9572941063391263e-20
i=23, sum=-1.0000000000013562 + 1.0347741813843647e-11i, 1/den=8.896791392450574e-22
i=24, sum=-1.0000000000013562 + -1.7072990308840883e-13i, 1/den=3.8681701706306835e-23
i=25, sum=-0.9999999999999793 + -1.7072990308840883e-13i, 1/den=1.6117375710961184e-24
i=26, sum=-0.9999999999999793 + 2.292021495202086e-15i, 1/den=6.446950284384474e-26
i=27, sum=-1.0000000000000002 + 2.292021495202086e-15i, 1/den=2.4795962632247972e-27
i=28, sum=-1.0000000000000002 + -1.405396847913007e-16i, 1/den=9.183689863795546e-29
i=29, sum=-1.0 + -1.405396847913007e-16i, 1/den=3.2798892370698385e-30
i=30, sum=-1.0 + -1.1097266936275162e-16i, 1/den=1.1309962886447718e-31
i=31, sum=-1.0 + -1.1097266936275162e-16i, 1/den=3.769987628815906e-33
i=32, sum=-1.0 + -1.1128644865909646e-16i, 1/den=1.2161250415535181e-34
i=33, sum=-1.0 + -1.1128644865909646e-16i, 1/den=3.800390754854744e-36
i=34, sum=-1.0 + -1.1128351600992583e-16i, 1/den=1.151633562077195e-37
i=35, sum=-1.0 + -1.1128351600992583e-16i, 1/den=3.387157535521162e-39
i=36, sum=-1.0 + -1.1128354033268814e-16i, 1/den=9.67759295863189e-41
i=37, sum=-1.0 + -1.1128354033268814e-16i, 1/den=2.6882202662866367e-42
i=38, sum=-1.0 + -1.112835401524659e-16i, 1/den=7.265460179153072e-44
i=39, sum=-1.0 + -1.112835401524659e-16i, 1/den=1.9119632050402823e-45
i=40, sum=-1.0 + -1.1128354015366612e-16i, 1/den=4.902469756513544e-47
i=41, sum=-1.0 + -1.1128354015366612e-16i, 1/den=1.225617439128386e-48
i=42, sum=-1.0 + -1.112835401536589e-16i, 1/den=2.989310827142405e-50
i=43, sum=-1.0 + -1.112835401536589e-16i, 1/den=7.11740673129144e-52
i=44, sum=-1.0 + -1.1128354015365895e-16i, 1/den=1.6552108677421951e-53
i=45, sum=-1.0 + -1.1128354015365895e-16i, 1/den=3.761842881232262e-55
i=46, sum=-1.0 + -1.1128354015365895e-16i, 1/den=8.359650847182804e-57
i=47, sum=-1.0 + -1.1128354015365895e-16i, 1/den=1.8173154015614793e-58
i=48, sum=-1.0 + -1.1128354015365895e-16i, 1/den=3.866628513960594e-60
i=49, sum=-1.0 + -1.1128354015365895e-16i, 1/den=8.055476070751238e-62
i=50, sum=-1.0 + -1.1128354015365895e-16i, 1/den=1.643974708316579e-63
cexp(pi_i, 50, c1)=-1.0 + -1.1128354015365895e-16i


docs.ruby-lang.org

Google Colaboratory記事の俄人気に御礼!

Google Colaboratoryが凄いという記事を書いたら、
当方のブログでは今まで見たこともない多数のアクセスを頂きました。

記念に、アクセス解析の結果を載せます。(普段は1日100PV位です)

おそらく、フォロワーの多い方が取り上げてくれたおかげと思います。

ありがとうございました。

f:id:Itsukara:20180206220657p:plain

ただ、記事を書いたときの懸念(下記)が現実化しそうで心配です。

「あまりに便利・高速なので、沢山の人が使い始める可能性があり、それによって Colaboratoryが終了してしまうのが心配」

追記

はてなブックマークのテクノロジー分野のトップ記事一覧に初めて載ったので、
記念にスクリーンキャプチャを取りました! 御礼!!!

f:id:Itsukara:20180206225328p:plain

Google Colaboratoryが便利・高速で凄過ぎる

Googleが研究の一環で提供しているColaboratoryを試してみました。

Jupyterと同じようなGUIPythonのプログラムを実行可能で、GPUも使えます。

Jupyterと同様に、先頭に「!」を書くことで、Linuxのコマンドを実行可能であり、「!pip」「!conda」「!apt-get」などで機能を追加できます。

実行結果をファイルシステム上に保管でき、共有リンクを使って取り出せます。
ただし、12時間経過すると強制終了されて、ファイルは失われます。

しかし、Notebookが動いている仮想マシンGoogleドライブをマウント可能であり、これにより、実行結果をGoogleドライブ上のファイルとして保管できます。

Deep Learningでは、途中の状態をファイルに保管して、そこからResumeできるようにプログラムを書くことが多いので、12時間で一度強制終了しても、Googleドライブに保管したファイルを使って学習を再開可能です。

試しに、Wide Residual Networks(WRN)のコードを実行してみました。このコードは、2016年時点にCIFAR10で最高性能を出したコードです。Colaboratoryを使って、16時間程度(途中で一度強制終了し、そこから再開)で結果を出すことができました。なお、当方のPCではGPUメモリが足りず同じ設定では試せませんでした(2GBでは足りなかった)。少し問題サイズを小さくして(depth=16からdepth=10にした)試したところ、Colaboratoryの方が問題サイズが大きいにもかかわらず、Epoch当たり処理時間は短かったです(当方PC: 3分53秒、Colaboratory:3分37秒)。

Deep Learningを個人的に試すには最適と感じました。

f:id:Itsukara:20180205205704p:plain

世界最高レベルのコードをこんな簡単・高速に試せるなんて、凄過ぎます!

Wide Residual Networks試行用Notebook

下記がWRN試行環境として作ったColaboratoryのNoteookです。共有設定していますので、リンクをたどれば、簡単にColaboratoryで実行できるはずです。

WRNd16w10(pytorch-v0.4).ipynb

Wide Residual Networksのpytorch0.4対応により一部変更した版(2018/9/30)。
https://colab.research.google.com/drive/1fDdGmFhh7X2Tu_Cg9yoDSY-9bM78w41s


NotebookにはWide Residual NetworksのPythonコードは全く書かず、「git clone」でコードを取得し、「import main」でメインのPythonファイル「main.py」をインポートし、「main()」を直接呼び出すことで実行しています。

ただし、このままではプログラムに引数を渡せないので、下記のように、間接的に「main()」に引数を渡すようにしています。この方法は汎用性があるので、他のコードを試す際も活用できそうです。

import sys
new_argv = "main.py --save ./logs/resnet_20180204 --depth 16 --width 10 --ngpu 1 --gpu_id 0".split(" ")
sys.argv = new_argv
main()

下記は、学習状況を可視化するためのNotebookです。

visualize.ipynb

https://drive.google.com/file/d/1eq4wAkZijRmfxiaQLpy5nXsR6I9Tu89-/view?usp=sharing

WRNのコードが作成したログファイル「log.txt」をGoogleドライブで右クリックして共有リンクを取得した後、上記Notebookに共有リンク中IDを埋め込んで実行すると、先頭で示したように、学習状況を可視化できます。

上記コードは、WRNのコードに含まれていたものを流用し、可視化にBokehを使っています。なお、ColaboratoryのNotebookでBokehを使う際は、グラフを表示するセル内で「output_notebook()」を必ず実行する必要があります。これが分からず、最初はMatplotlibで表示していましたが、Bokehは、表示した後で部分的に拡大したりできるので便利ですね

WRNコードの場所(Github)

github.com

WRNの論文(Wide Residual Networks, 23 May 2016)

https://arxiv.org/abs/1605.07146

第一級陸上特殊無線技士の免許証が届きました

10月26に受験した第一級陸上特殊無線技士(一陸特)の免許証が届きました。
f:id:Itsukara:20171208211947j:plain

下記記事で書きましたように、1問を除き残りは全問正解でしたが(全36問中35問正解)、点数は通知されませんでした。せっかく良い点数が取れたはずなのに、残念です。

itsukara.hateblo.jp

なお、Oracle Java Certificate Programでは試験の点数を教えてくれます。私はSilverを受験し正解率94%でした。これを記事に書いたところ、少しアクセスしてくれている人もいるようで、励みになります。

itsukara.hateblo.jp