ihit's diary

ちょっとしたメモに

Octaveインストール

CourseraでOctaveを使うということでインストールしてみたが、長く険しい道だった。

ちなみに環境はMac OSX 10.9.3

まずはMacPorts
wikiによると
sudo port install octave +atlas+docs
で入るとか何とか。
でやってみる...入らない。
atlas入れるところで躓く。

しばらくやって諦め、今度はインストーラーを使うことに
URLはここ

まずOctaveを入れ、グラフの出力用にGnuplotも入れる。

Octaveを入れたらとりあえずターミナルでoctaveと打ってみる...成功!
続いてgnuplot...エラー!
リンクがどうこうと書いてあり、調べて対処法を試してみるも上手くいかない。
仕方なくアンインストールしてgnuplotMacPortsで入れてみたら入ることには入るが、今度はoctaveでplotをしようとしても反応してくれない!
もう諦めようかなと思っていたらこのページに辿り着いた。
ここの通りにやってみたところ成功!
良かった良かった。

ちなみに先程のページではX11でグラフを表示していたけどaquatermでやったほうがグラフは綺麗だった。
2つの違いはこのページに詳しく書いてある。
また、aquatermに設定してたけどX11で表示したくなったら
setenv("GNUTERM","x11")
と打つ。

長かった...

Coursera (week2)

線形回帰のコスト関数をどうやって最適化するか

J(\theta)=\sum_{k=0}^{n}x_k\theta_k

(x_0=1)
1. 最急降下法を使う
2. 正規方程式を解く

最急降下法を使う際には学習率の調整が必要になる。大きすぎなきゃ収束することが保証されているから、小さいのから大きいのを3倍ずつくらいに分割して学習率を調整するのがいいとのこと。
また、早く収束するためにはデータの正規化も有効。本コースでは単純に平均を引いて大きさで割って0~1の正規化を行っていたけれど、平均0分散1になる正規化もOKだと思う。

正規方程式は
y = \theta X
をムーア・ペンローズの擬似逆行列を用いて解くというものだ
\theta = \left(X^TX\right)^{-1}X^Ty
正規方程式を解くことの利点は学習率が存在しないのでパラメータ調整が必要ない。また、データの正規化も必要ない。
しかし\left(X^TX\right)^{-1}がデータの次元数×次元数の行列となっていて、次元数が大きくなると逆行列を解くコストが高くなる。実際、逆行列を掃き出し法で解くとO(n^3)のオーダーとなる。Andrewさんは次元数が10000を勾配法と正規方程式の選ぶ境目ぐらいだと言っていた。

Coursera

最近CourseraのMachine Learningの授業を受け始めた。
Coursera(Coursera.org)はいろいろな大学の授業のオンライン講座だ。
日本だと東大が参加している。
Courseraのすごいところは授業にテストや課題があって規定以上の成績を修めると修了証を貰えるところだ。(全部の授業がそうではないみたいだが)

今受けているMachine Learningの授業(https://class.coursera.org/ml-005)はもうすでに終わったものだが、もうすぐ新しいMachine Learning講座が始まるらしいのでそっちもチェックしていきたい。

まだChapter1(Chapter10まである)しか受けていないけど説明はわかりやすくなかなかいい感じだ。

CSVファイルを開くにあたって

とあるcsvファイルを読み込もうとして起きたエラーについて

あるtextファイルのデータをnumbesを使ってcsvファイルに変換し

data = csv.reader(open("sample.csv"))

としたら普通に読み込めた、しかしあるデータをExcelを使ってcsvにして同じようにしたら

_csv.Error: new-line character seen in unquoted field - do you need to open the file in universal-newline mode?

というエラーが出てきた。これはどうやらmacwindowsの改行文字の違いによるエラーらしい
解決策としては

data = csv.reader(open("sample.csv","rU"))

とするだけ。簡単

Project Euler 33

33番
分子と分母に共通した数字を取り除くと約分した結果と同じになる分数を探す問題

コードは下のようになったけど、正直あんまり良くない
reduce_keta関数が分母分子に共通した数字を取り除くんだけど0を含んだ数字を入れるとダメ
今回は0を含んだ数字は明らかに題意を満たさないってわかるから除外してreduce_ketaに入れることにした

#!/usr/bin/env python
# -*- coding: utf-8 -*-

def gcm(a,b):
	if a % b == 0:
		return b
	else:
		return gcm(b,a%b)

def reduce_keta(a,b):
	bunsi = map(lambda x:int(x),list(str(a)))
	bunbo = map(lambda x:int(x),list(str(b)))
	for i in bunsi:
		if i in bunbo:
			bunsi.remove(i)
			bunbo.remove(i)
	if len(bunbo) == 1 and len(bunsi) == 1:
		new_bunsi = bunsi[0] / gcm(bunbo[0],bunsi[0])
		new_bunbo = bunbo[0] / gcm(bunbo[0],bunsi[0])
		return [new_bunsi,new_bunbo]
	else:
		return []

ans_bunsi = 1
ans_bunbo = 1
for i in range(11,99):
	if i % 10 == 0:
		continue
	for j in range(i-1,10,-1):
		if j % 10 == 0:
			continue
		if reduce_keta(j,i) == [j/gcm(j,i),i/gcm(j,i)] and j/gcm(j,i) < 10 and i/gcm(j,i) < 10:
			ans_bunsi *= reduce_keta(j,i)[0]
			ans_bunbo *= reduce_keta(j,i)[1]
print ans_bunbo/gcm(ans_bunbo,ans_bunsi)

Project Euler 32

32番
パンデジタルといって1から9までの数字を1回ずつ使って掛け算の式を成立させる問題
できたもののイマイチ…

今回は順列を求めるのにitertoolsを使った
またリストやタプルの数字列を一つの数値にするためにreduceを使った
例 reduce(lambda x,y: x*10+y, [1,2,3]) →123

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import itertools

num_list = [1,2,3,4,5,6,7,8,9]
ans = 0
ans_list = []
#積は4桁しかない
#掛けられる数>掛ける数としたとき、掛けられる数は4桁か3桁
for i in [4,3]:
	now_num_list = num_list[:]
	for left_list in itertools.permutations(num_list,i):
		now_num_list = num_list[:]
		for k in left_list:
			now_num_list.remove(k)
		for right_list in itertools.permutations(now_num_list,5-i):
			new_now_num_list = now_num_list[:]
			for k in right_list:
				new_now_num_list.remove(k)
			answer = reduce(lambda x,y:10*x+y,left_list) * reduce(lambda x,y:10*x+y,right_list)
			if sorted(map(lambda x:int(x),list(str(answer)))) == new_now_num_list and not answer in ans_list:
				ans_list.append(answer)
				ans += answer
print ans

Project Euler 30, 31

30番
各桁を5乗して足すと同じになる数を求める
N桁の数の5乗和の最大値は
9^5*N

#!/usr/bin/env python
# -*- coding: utf-8 -*-

summary = 0
for i in range(2,9**5*6):
	right = 0
	left = i
	while left > 0:
		right += (left % 10)**5
		left /= 10
	if i == right:
		summary += i
print summary


31番
1,2,5,10,20,50,100,200ポンド硬貨でちょうど200ポンドは何通りできるか
再帰使うのがやっぱり楽かな

#!/usr/bin/env python
# -*- coding: utf-8 -*-

def count_variety(sum_money,money_list):
	count = 0
	if money_list == [1]:
		return count + 1
	for i in range(0,sum_money/money_list[0]+1):
		new_money_list = money_list[:]
		if sum_money - i*money_list[0] == 0:
			count += 1
		elif sum_money - i*money_list[0] > 0:
			new_money_list.pop(0)
			count += count_variety(sum_money - i*money_list[0],new_money_list)
		else:
			break
	return count

money_list = [200,100,50,20,10,5,2,1]
print count_variety(200,money_list)