sageは、mathematicaのような数式処理を行うオープンソースのソフトウェアです。Maxima, R等の既存のオープンソースパッケージをPythonをベースとしたインタフェースで結合し、ブラウザー(firefox)から簡単に操作できるノートブックを提供していることが特徴です。
sageの目標は、商用のMagma, Maple, MathematicaそしてMatlabの代わりとなるフリーかつオープンソースのシステムを開発ことです。
sageは、ウィリアム・スタイン (William Stein)によって2005年2月に開発がスタートし、2006年2月のUCSD SAGE Days 1でSage 1.0が公開されました。*1
最新のバージョンは、4.2.1(2009-11-14)です。
sageに含まれるオープンソースのコンポーネントは、以下のURLで見ることができます。
http://www.sagemath.org/links-components.html
主なコンポーネントは、以下の通りです。*2
計算処理 | GMP, MPFR |
可換環論 | Singular (libcf, libfactor y) |
暗号処理 | OpenSSL, PyOpenSSL, PyCrypto |
組み合わせ | GAP |
グラフ理論 | NetworkX |
数論 | PARI, NTL |
数値計算 | GSL, Numpy |
計算機代数 | Maxima |
統計処理 | R |
特殊数値計算 | 多くの C/C++個別プログラム |
コマンドライン処理 | IPython |
グラフィックインタフェース | Notebook, jsmath, Moin wiki |
プロット処理 | Matplotlib, Tachyon, libgd |
ネットワーク処理 | Twisted |
データベース | ZODB, Python Pickles |
プログラミング言語 | Python, SageX (compiled python) |
Sageのおもしろいところは、sageをインストールしなくてもオンラインでsageを使うことができるところです。
Sageのホームページ(http://www.sagemath.org/)のTry Sage Onlineをクリックして、Sign up for a new Sage Notebook accountでアカウントを作成してください。
ログインが完了すると以下のようなNotebook画面になります。
sageの式で変数として認識させるには変数をvar関数で宣言しなくてなりません。
変数の宣言は、
var('変数名')
複数の変数を宣言する場合には、スペースを空けて指定します。 宣言される変数を参照したりする場合には、
x, y = var('x y')
のようにpython変数x, yに宣言したsage変数を代入します。
変数の値を指定して、関数の返す値を調べるには、
f1(x=1.5)
のように式を表す変数にカッコを付けて、x=1.5と値を指定するとその時の関数の値が表示されます。
sage入力:
x = var('x') f1 = (x - 1)*(x^2 - 1) f1(x=1.5)
sage出力:
0.625000000000000
変数をx, yと複数存在する場合の例をです。f5にf5(x, y)=x^2+yを定義し、f5(x=2, y=3)でx=2, y=3の時の値を出力します。
sage入力:
var('x y w') f5=x^2 + y f5(x=2, y=3)
sage出力:
7
規則の代入には、subs_exprを使います。
sage入力:
f6=x^2 + 1; f6
sage出力:
x^2 + 1
sage入力:
f6.subs_expr(x^2 == w)
sage出力:
w + 1
sageで関数を定義する方法が2つあります。
です。
手続き的な関数を定義する場合には、python関数を使うと便利です。
pythonでは
def 関数名(引数のリスト): 関数の本体
のように定義します。
以下にx^3を返す関数cubeをpythonの関数を使って定義します。
sage入力:
def cube(x): return x^3 cube(2)
sage出力:
8
sage入力:
x, y = var('x y') cube(x+y)
sage出力:
(x + y)^3
つぎにlambda式を使って関数を定義する方法を示します。 x^3のように式で表現できる場合には、lambda関数が便利です。
lambda 変数のリスト: 式 のように定義します。 先ほどと同じx3を返す関数の例を以下に示します。
sage入力:
f = lambda x: x^3 f(2)
sage出力:
f(x+y)
この例題は、以下のURLでノートブックを参照することができます。
http://www.sagenb.org/pub/1182/
計量経済学では、経済の構造をモデルで表現し、モデルの要素間の 相互関係を連立方程式で表し、過去の経済統計データからモデルの 係数を求め、未来の予測を行います。
ここでは、「MathematicaによるOR」4章で紹介されているモデル と経済データを元に、sageの活用例を紹介します。
以下のモデルでは、矩形を要素としY:所得、C:消費、I:投資、 G:政府支出とし、矢印の方向は影響与える向きを表します。 消費は自分自身へ矢印があり、これは前年度の消費が次年度の 消費に影響を与えていることを表しています。
このモデルを連立方程式で表すと、以下のようになります。
$$ \begin{array}{l c l} C_t & = & a_0 + a_1 Y_t + a_2 C_{t-1} \\ I_t & = & b_0 + b_1 Y_t \\ Y_t & = & C_t + Y_t + G_t \\ \end{array} $$
sageでは、統計情報の分析に有益なRパッケージとのインタフェースを 持っています。 ここでは、Rのデータ取り込みを関数であるread.table関数を 使ってデータを読み込み、取り込んだデータをsageの形式に変換する方法を紹介 します。
経済データは、Econometrics.txtファイルに入っています。 最初の1行がYear, Ct, Yt, It, Gtのヘッダで、その後に 1965年から1989年までの各年度の消費、所得、投資、政府支出 の値が続きます。
sage入力:
# 計量経済学(Econometrics) # Rのread.table関数を使ってデータを読み込む fileName = DATA + 'Econometrics.txt' d = r("read.table('%s', header=T)" %fileName) ; d
sage出力:
Year Ct Yt It Gt 1 1965 57176.9 89662.8 10325.1 26408.3 2 1966 63042.7 100033.0 12874.9 29014.0 3 1967 69239.4 110974.0 16394.3 32237.9 4 1968 75771.6 125997.0 19831.2 36869.6 5 1969 83092.1 141402.0 25595.8 39998.9 6 1970 88847.4 153915.0 28909.3 45352.6 7 1971 94196.4 161688.0 27715.0 47546.6 8 1972 103848.0 176628.0 29409.4 53396.2 9 1973 110290.0 184569.0 33396.1 56225.9 10 1974 111694.0 183798.0 30345.5 52550.3 11 1975 115765.0 190875.0 29288.2 53985.8 12 1976 120366.0 199630.0 29478.3 56413.9 13 1977 125394.0 210235.0 29722.5 60068.7 14 1978 133154.0 221243.0 32393.5 64567.0 15 1979 140184.0 232878.0 35569.1 65560.4 16 1980 141398.0 242131.0 38293.4 63846.2 17 1981 144257.0 250159.0 39917.0 64394.4 18 1982 150360.0 258241.0 40698.0 64297.5 19 1983 154910.0 267700.0 42711.7 63274.3 20 1984 158910.0 281399.0 47631.2 64695.8 21 1985 163395.0 293982.0 53899.5 64404.0 22 1986 169016.0 301846.0 56236.0 68598.6 23 1987 176556.0 318109.0 61897.9 74350.9 24 1988 185318.0 334969.0 72617.1 76545.4 25 1989 191233.0 351877.0 84584.1 77764.1
読み込んだデータdをsageのデータ形式に変換するには、_sage_() 関数を呼び出します。 データはdsの、'DATA'要素にセットされ、Ct, Yt, It, Gtをキー として消費、所得、投資、政府支出の列データを取り出します。
sage入力:
# 読み込んだデータdをsageのデータに変換 ds = d._sage_() # Ct, Yt, It, Gtを取り出す CtData = ds['DATA']['Ct'] YtData = ds['DATA']['Yt'] ItData = ds['DATA']['It'] GtData = ds['DATA']['Gt']
連立方程式のCt, Itの係数a_0, a_1, a_2, b_0, b_1の値を回帰分析を 使って求めます。
CtList, YtList, GtListには、1966年から1984年のデータをセットし、 Ct1Listには、1年ずらしたCtの値をセットします。
sage入力:
# Ctのフィッティングは、前年度のCtであるCt-1を使うため1966年から1984年のデータを作成 CtList = CtData[1:20] Ct1List= CtData[0:19] YtList = YtData[1:20] GtList = GtData[1:20] ItList = ItData[1:20]
回帰分析には関数find_fitを使います。
find_fit(data, model, options) dataは、変数1の値, 変数2の値, ... , 変数nの値, 関数の値をタプルとするリストをセット modelは、model(変数1の値, 変数2の値, ... , 変数nの値)の引数を持つ関数をセット optionsで、solution_dict=Trueを指定すると係数名をキーとする辞書が戻されます
zip関数を使って各年度のYt, Ct1, Ctをタプルにまとめたリストを作成します。
sage入力:
# 各年度のYt, Ct1, Ctをタプルにまとめたリストを作成 data = zip(YtList, Ct1List, CtList); data
sage出力:
[(100033, 57176.900000000001, 63042.699999999997), (110974, 63042.699999999997, 69239.399999999994), (125997, 69239.399999999994, 75771.600000000006), (141402, 75771.600000000006, 83092.100000000006), (153915, 83092.100000000006, 88847.399999999994), (161688, 88847.399999999994, 94196.399999999994), (176628, 94196.399999999994, 103848), (184569, 103848, 110290), (183798, 110290, 111694), (190875, 111694, 115765), (199630, 115765, 120366), (210235, 120366, 125394), (221243, 125394, 133154), (232878, 133154, 140184), (242131, 140184, 141398), (250159, 141398, 144257), (258241, 144257, 150360), (267700, 150360, 154910), (281399, 154910, 158910)]
変数Yt, Ct1, a0, a1, a2とモデルCtModelを定義します。CtModelの式は、連立方程式の \( C_t=a0+a_1 Y_t+a_2 C_{t−1} \)の部分です。
が求まります。
sage入力:
# モデル関数と変数を定義 var('Yt Ct1 a0 a1 a2') CtModel(Yt, Ct1) = a0 + a1*Yt + a2*Ct1 # 最適な解のa0, a1, a2を求める CtFit = find_fit(data, CtModel, solution_dict=True); CtFit
sage出力:
{a0: 7518.3096037375299, a1: 0.21857976971146531, a2: 0.59268191617908206}
同様に、変数Yt, b0, b1とモデルItModelを定義します。CtModelの式は、連立方程式のIt=b0+b1Ytの部分です。
が求まります。
sage入力:
# 同様にItに対するb0, b1を求める data = zip(YtData, ItData) var('Yt b0 b1') ItModel(Yt) = b0 + b1*Yt ItFit = find_fit(data, ItModel, solution_dict=True); ItFit
sage出力:
{b0: -11736.272856134668, b1: 0.22718320402830394}
係数a0, a1, b2, b0, b1が決まったので、solve関数を使って連立方程式 を解きます。 係数を入力して式を定義する代わりに、
CtEq = (Ct == CtModel(Yt, Ct1)).subs(CtFit)
のようにsubs関数を使ってCt == a0 + a1*Yt + a2*Ct1のa0, a1, a2を代入しています。 これで、モデルを変更しても再計算が楽にできます。
sage入力:
# 連立方程式をCt, It, Ytに対して解く var('Gt It') CtEq = (Ct == CtModel(Yt, Ct1)).subs(CtFit) ItEq = (It == ItModel(Yt)).subs(ItFit) YtEq = (Yt == Ct + It + Gt) eqn = [CtEq, ItEq, YtEq]; eqn
sage出力:
[Ct == 0.592681916179082*Ct1 + 0.218579769711465*Yt + 7518.30960373753, It == 0.227183204028304*Yt - 11736.2728561347, Yt == Ct + Gt + It]
solveにsolution_dict=Trueのオプションを指定し、辞書形式で解取得します。
sage入力:
sol = solve(eqn, [Ct, It, Yt], solution_dict=True); sol
sage出力
[{Yt: 721680419112/674867923015*Ct1 + 506300280/280610363*Gt - 164437808222620/21606997951, Ct: 557726748944/674867923015*Ct1 + 110666997/280610363*Gt + 379515962234357/64820993853, It: 163953670168/674867923015*Ct1 + 115022920/280610363*Gt - 872829386902217/64820993853}]
前年度のzip関数を使って前年度消費と政府支出をタプルとするリストを作成します。
sage入力:
# 入力データをセット data = zip(Ct1List, GtList); data
sage出力:
[(57176.900000000001, 29014), (63042.699999999997, 32237.900000000001), (69239.399999999994, 36869.599999999999), (75771.600000000006, 39998.900000000001), (83092.100000000006, 45352.599999999999), (88847.399999999994, 47546.599999999999), (94196.399999999994, 53396.199999999997), (103848, 56225.900000000001), (110290, 52550.300000000003), (111694, 53985.800000000003), (115765, 56413.900000000001), (120366, 60068.699999999997), (125394, 64567), (133154, 65560.399999999994), (140184, 63846.199999999997), (141398, 64394.400000000001), (144257, 64297.5), (150360, 63274.300000000003), (154910, 64695.800000000003)]
連立方程式からCt式を取り出し、前年度消費Ct1と政府支出Gtを引数とするctFuncを定義します。
sage入力:
ctFunc(Ct1, Gt) = sol[0][Ct]; ctFunc
sage出力:
(Ct1, Gt) |--> 557726748944/674867923015*Ct1 + 110666997/280610363*Gt + 379515962234357/64820993853
dataの各タプルに対し、リスト内for文を使って計算結果をcalCtListにセットします。
sage入力:
calCtList = [ctFunc(Ct1, Gt).n() for (Ct1, Gt) in data]; calCtList
sage出力:
[64549.6971260734, 70668.7727491564, 77616.5194992103, 84249.0154719521, 92410.2390710246, 98031.8233620791, 104759.325753524, 113851.611245606, 117725.850212143, 119452.280771693, 123774.244126530, 129017.997396518, 134947.292700448, 141752.116171432, 146885.828296538, 148105.305379392, 150429.834945473, 155069.968723451, 159390.806476880]
list_plotを使って計算結果(青い線)と実データ(赤い点)をプロットします。
かなりよい精度で計算できていることが分かります。
sage入力:
# 計算値(青)と実測値(赤) calCtPlot = list_plot(calCtList, plotjoined=true) ctPlot = list_plot(CtList, rgbcolor='red') (calCtPlot + ctPlot).show(ymin=0)
sage出力:
同様に投資データも計算し、プロットします。
こちらはかなりずれていますが、傾向はつかんでいる感じです。これは計算精度が悪いのではなく モデルの表現力が足りないと理解した方がよいでしょう。
sage入力:
# 同様にItに対する計算値と実測値をプロット itFunc(Ct1, Gt) = sol[0][It] calItList = [itFunc(Ct1, Gt) for (Ct1, Gt) in data] calItPlot = list_plot(calItList, plotjoined=true) itPlot = list_plot(ItList, rgbcolor='red') (calItPlot + itPlot).show(ymin=0)
sage出力:
同様に所得データも計算し、プロットします。
よく一致しています。
sage入力:
# 同様にYtに対する計算値と実測値をプロット ytFunc(Ct1, Gt) = sol[0][Yt] calYtList = [ytFunc(Ct1, Gt) for (Ct1, Gt) in data] calYtPlot = list_plot(calYtList, plotjoined=true) ytPlot = list_plot(YtList, rgbcolor='red') (calYtPlot + ytPlot).show(ymin=0)
sage出力:
計量経済モデルの目標である、未来の予測をしてみましょう。
1985年から1989年までの政府支出Gtをプロットすると、直線上を変動しながら上昇している ことが見て取れます。これから、Gtを\(G_t(x)=c_0+c_1 x\)として回帰分析をします。
sage入力:
# 予測:Gtを予測し、それに対するIt, Yt, Ctを計算する gtPlot = list_plot(GtList, rgbcolor='red'); gtPlot.show()
sage出力:
sage入力:
# 1985年から1989年のデータを予測 var('x c0 c1') data = zip(range(20), GtList[0:20]) GtModel(x) = c0 + c1*x GtFit = find_fit(data, GtModel, solution_dict=True); GtFit
sage出力:
{c1: 1960.3166656122035, c0: 35741.149903570993}
直線回帰で求めた政府支出と実データをプロットすると以下のようになります。
sage入力:
gtFunc(x) = GtModel.subs(GtFit) calGtPlot = plot(gtFunc, [x, 0, 25]) (calGtPlot + gtPlot).show()
sage出力:
政府支出モデルgtFuncを使って、1985年から1989年まで政府支出を求め、前年度の消費Ct1List の値とgtFuncの値から消費、投資、所得を順番に計算します。
予測した消費を1985年から1989年までの実データと重ねてプロットします。 かなりよい一致を示しています。
sage入力:
# 予測 predCt1List = Ct1List predCtList = calCtList predItList = calItList predYtList = calYtList for i in range(19, 24): predCt1List.append(ctFunc(predCt1List[i-1], gtFunc(i))) predCtList.append(ctFunc(predCt1List[i], gtFunc(i))) predItList.append(itFunc(predCt1List[i], gtFunc(i))) predYtList.append(ytFunc(predCt1List[i], gtFunc(i))) # 予測値(青)と実測値(赤) predCtPlot = list_plot(predCtList, plotjoined=true) ctPlot = list_plot(CtData[1:25], rgbcolor='red') (predCtPlot + ctPlot).show(ymin=0)
sage出力:
同様に投資の予測と実データを重ねてプロットします。 計算の時と同様に実データとずれますが、傾向は同じです。
sage入力:
# 同様にItに対する予測値と実測値をプロット predItPlot = list_plot(predItList, plotjoined=true) itPlot = list_plot(ItData[1:25], rgbcolor='red') (predItPlot + itPlot).show(ymin=0)
sage出力:
最後に所得の予測と実データを重ねてプロットします。 こちらは、計算の時と同様にかなりよく一致します。
このようにsageを使うと簡単に計量経済モデルの計算をすることができます。 モデルやデータの変更も容易なので、モデルの改良も短時間にできるようになります。
sage入力:
# 同様にYtに対する予測値と実測値をプロット predYtPlot = list_plot(predYtList, plotjoined=true) ytPlot = list_plot(YtData[1:25], rgbcolor='red') (predYtPlot + ytPlot).show(ymin=0)
sage出力:
sageのホームページ http://www.sagemath.org/ で、Downloadボタンから使っているマシンのバイナリがダウンロードできます。
現在、sageがサポートしているOSは、
です。
MacOSXのインストールは、
をダウンロードし、をマウント(ダブルクリック)するとsageフォルダをハードディスクの適当な場所にコピーします。*3 ここでは、ホームディレクトリのlocalフォルダ以下にコピーしました。
次にコピーしたsageフォルダ内のsageアイコンをダブルクリックするとターミナルが起動し、初期設定を行った後以下のようなプロンプトを表示します。
sage:
ここで、notebook()と入力するとブラウザにSageのNotebook画面が表示されます。
plot(cos, -5, 5)と入力し、シフトキーとリターンキーを同時に押すと最初にご紹介したグラフが表示されます。
Windowsの場合、最初にVM Playerをインストールしてください。 VM Playerは、以下のURLからダウンロードできます。
http://www.vmware.com/products/player/
次にVMイメージファイルをダウンロードします
をダウンロードし、解凍します。
VM Playerで
すると、以下のような画面がでます。
sage login: プロンプトにnotebookと入力すると、
が表示されますので、
Open Firefox to the address http://172.16.137.131
の部分に記載されたURL(例ではhttp://172.16.137.131)をブラウザー(Firefox)から開いてください。
の画面がでたら、成功です。
VM Playerの画面で、Ctrl-Cを入力し、sage login: 画面になったら、offを入力すると仮想マシンがシャットダウンします。