【機械学習基礎固め】線形回帰(Linear Regression)の初歩的ポイントを再確認して書いておく
昨年の今頃、CourseraのMachine Learningの講座を受講しましたが、 急いで詰め込んだ情報ってのは、やっぱり消えていくのも早いようです。
当時、仕事で炎上案件の火消し作業に関わっておりまして、 深夜に帰宅し、晩御飯をいただきながらネットで受講。 字幕付きの英語のビデオを視聴して、週一で課題提出というサイクル。 特に後半は睡眠時間の確保が難しくなり気持ち的にも駆け足で、次第に「講座を終わらせること」が目的になっていました。
どうにか8月末に修了したけど、達成感とか感じる前に「炎上案件なんだかなあ?」な状況で、学習内容はすぐに蒸発。 理解が曖昧なところが起点になって、急速に知識の最小単位の輪郭がぼやけていくんですよ怖い怖い。
てなことで、一年経って新たな気持ちで講座のテキストや受講中に取ったノートをめくりながら復習中。 気長にじっくりポイント押さえて経年劣化の激しいニューラルネットワークにしっかり刻みつけていきたいなあと思っております。 ただし、ここに書いているのは私個人が理解したと思っているものに過ぎませんので気を付けてくださいね。
以下の記事では、実際に線形回帰をやってみています。結果はいまいち満足していないですが、ご参考に。
ちなみに、数式はMathJax使って書いています。LaTeXの書式で数式を書けば、きれいに整形してくれるスクリプト。まともに使ったことがなかったのですが、なかなか便利。ブログはMarkdownで書いているので _
や^
を\
でエスケープしないといけないようで少々わずらわしいのですが、理屈が分かればなんとかなります。
やはり、いくつになってもお勉強です。
- Courseraの権利を侵害するのはまずいので、本記事の内容は箇条書きに毛が生えた程度のものです。またテキストの内容をそのまま書いたりもしませんよ。
- 詳しい内容を知りたい方は、ぜひとも同講座を受講してみてくださいね。非常に興味深い内容です。
- 受講のためには、少なくとも、行列演算の基礎を理解している必要があると思います。それと課題や試験の文章が英語なので、辞書片手にでもよいので英文の読解力がある程度必要です。講義の動画では日本語の字幕が付きますが、私が受講したときは、字幕が追い付いていない場面が何か所かありました。また、字幕を読んでいる時は、表示されてる式を見逃すということも。ヒヤリングができるに越したことはないですよ。
- まあしかし、無料なので気軽に受けてみるのもアリかもしれない。構えて撃ってから狙いましょう。
ところで、Octave for Windowsの不便な点
ハナから横道に逸れますゴメンナサイ。先日からWindows 10でMinGW/MSYSからOctaveを使っていますが、不便な点が以下3つ。
gccでビルドすれば解決できそうな気がするのですが、またそのうち。
線形回帰(Linear regression)とはなんであるか
線形回帰(分析)とは、線形モデルによる回帰分析ということらしい。データセット内のデータの相関をモデル化する方法・・・かな?
線形モデルは、以下のような式で定義されます(Wikipediaから引用)。
\[ Y=\beta_{0} + \beta_{1}X_{1} + \beta_{2}X_{2} + \dots + \beta_{p}X_{p} + \varepsilon \]
\[ \begin{eqnarray*} Y & : & 出力値\\ X_i & : & 入力値\\ \beta_i & : & 線形モデルのパラメータ \end{eqnarray*} \]
実は自分、\(\varepsilon\)が何物なのか理解できていません。切片は\(\beta_{0}\)だし・・・。 まあ、とにかく、与えられたデータセットに対して、このような線形モデルの仮説を立てて、そのパラメータである\(\beta_i\)を決定しましょうということですね。
例えば、日毎の最高気温と湿度、アイスキャンデーの売上額というデータセットがあって、 ある日の天気予報から売上予測を行う場合、 最高気温は\(X_1\)、湿度は最高気温は\(X_2\)、売上額は\(Y\)ですが、\(\beta\)の値がわからない。 データセットは観測(測定)データであり、計算して出したものではありませんから。
てことで、与えられた実際のデータセットを線形回帰分析して、\(\beta_{0 \dots 2}\)をちょうどよい値に調整するということですね。
参考サイト
仮説関数(hypothesis function)
仮説関数。これは、与えられた問題を解決するための関数であって、いわゆる上で書いている線形モデルそのものですね。 既知のデータから作成された入力と出力の相関を表すための式ですから、実データXを与えれば実データY(に近い値)を出力し、未知の入力に対しても仮説に基づいた値を出力する。つまり、これを使って予測ができるということになる。
線形回帰では仮説関数が線形モデルになっているということですね。
上のWikipediaからの引用では、モデルのパラメータを\(\beta\)としていましたが、Courseraの講座では一貫して\(\theta\)で統一されていました。 自分にとってはすでにこちらのほうがなじみがあるので、以降\(\theta\)で通します。
講座では、以下のような単純な仮説が立てられていました。(\(x\)が入力。\(y\)は仮説に基づいて出力される値)
\[ y=\theta_0 + \theta_1x_1 + \theta_2x_2 \]
この仮説関数は、\(x_0 = 1\)と置くと以下のように書けます。
\[ y=\theta_0x_0 + \theta_1x_1 + \theta_2x_2 \]
そしてこれは行列を使用して以下のように記述できます。日常的に行列を扱っていないので、上の式を見てすぐ行列演算に結び付けられないが、それも慣れなのだろう。
\[ h_\theta(x) = \theta^{T}x = \theta_0 + {\theta_1}x_1 + {\theta_2}x_2 \]
\(\theta^{T}\)のTは転置(Transpose)の意味です。以下参照。
\[ \theta^T = {\begin{bmatrix} \theta_0\\ \theta_1\\ \theta_2 \end{bmatrix}}^T = \begin{bmatrix} \theta_0 &\theta_1 &\theta_2 \end{bmatrix} \]
\(\theta_{0 \dots 2}\)が、線形モデルのパラメータ(初期値は1とか乱数とか)。後述の勾配降下法によって、コスト関数の出力が少なくなる(つまり誤差が少ない)値を決定するのです。これが線形回帰分析ですね。
※ \(x_1\)の添え字の1は、最初の入力値という意味であり、データセットのインデックスではありません。
コスト関数(Cost function)
コスト関数は、仮説関数がどれくらい的を得ているかを表します。 実データと理論値の差分の絶対値に関する値で。 線形回帰では、たいてい以下の式で定義されるらしく、全サンプルの二乗平均誤差に比例する値です。
\[ J(\theta) = \frac{1}{2m} \sum_{i=1}^{m} ({{h_\theta}{(x^{(i)})-y^{(i)}})^{2}} \]
下図は、Courseraの講座で描いたコスト関数の三次元グラフです。縦方向がコストです。
勾配降下法(Gradient Descent)
売り上げランキング: 34,160
線形回帰の目的は、コスト関数の結果を最小化する\(\theta\)を見つけること。 そのために、勾配降下法を使用して、線形回帰のパラメータである\(\theta\)を、データセットにフィットさせます。 勾配降下法にも種類があるようですが、最初はバッチ勾配降下法(Batch Gradient Descent)が取り上げられていました。 これまた「それが何たるや?」は、よくわかっていないので、そのうち確認してみます。 とりあえず、コスト関数\(J(\theta)\)の出力を最小化する\(\theta\)を見つける方法の一つということで。
その名のとおり、坂を下りていくようなアルゴリズム。x軸を\(\theta_0\)、y軸を\(\theta_1\)、z軸をコスト関数の出力として、x-yをスイープして描いた三次元のグラフについて、特定のx-y位置からz成分が小さくなる方向へ徐々に移動(\(\theta_0\)と\(\theta_1\)を更新)していくものです。最終的に逆向きのピークに落ち着くというわけですね。
下図は、講座の中で、コスト関数の等高線を描いたものです。赤い×印が一番コストの低い場所です。
このように、データを可視化して、処理が正しく行われているかを確認する必要があります。 θの要素数が多い場合は全てを使ってグラフを描けませんが、特定の軸を抜き出して描けばよいです。勾配降下に関する考え方は同じです。 また、複雑な仮説関数では、くぼんでいるが、一番低いわけではない場所に落ち込んでしまう場合がありますが、そういった問題の回避方法や、速めに収束させるためのテクニックなどが講座で細かく紹介されていました。
線形回帰のパラメータθを繰り返し更新する
実際の演算ではθをスイープするのではなく(演算量が大きすぎるし意味がない)、ある出発地点を選んで、その場所のコスト/θの傾きに応じて、コストが低い場所へ移動することを繰り返します。
ある地点の傾きが関わってくるので、偏微分といった(自分的に)難しい内容も関連し、きちんと理解していませんが、とりあえず、個々の繰り返しでθを更新するのは、以下の式を使うらしい。
\[ \theta_j := \theta_j-\alpha \frac{1}{m} \sum_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})x^{(i)}_j \]
- \(i\)は、データセットのインデックス。
- \(j\)は、線形回帰パラメータの添え字。
- \(\alpha\)は学習率(learning rate)を表す値です。小さな値では\(\theta\)の収束が遅くなり、大きな値だと早く収束します。
ここで大切なのは、\(\theta\)の全要素を同時更新するということです。\(\theta\)の要素がひとつでも変化すると、仮説関数 \(h_\theta(x^{(i)})\) は別の式になり、その値は変化してしまいますが、全要素を更新するまで仮説関数は変化すべきではないということです。
繰り返しによって線形回帰のパラメータ\(\theta_j\)は、コスト関数\(J(\theta)\)を最小化する値に近づいていきます。
Octave/MATLABの使い方
CSVを読み込む
データセットがカンマ区切りのテキストデータとして用意されている場合、Octave/MATLABで以下のようにして行列に読み込みます。
data = load('data.csv'); % カンマ区切りのテキストデータを読み込む
例えばCSVにn列m行のデータがあるなら、dataの中身は以下のようになっています。
\[ data= \begin{bmatrix} d_11 &d_{21} &\dots &d_{(n-1)1} &d_{n1}\\ d_12 &d_{22} &\dots &d_{(n-1)2} &d_{nn2}\\ d_13 &d_{23} &\dots &d_{(n-1)3} &d_{n3}\\ \vdots &\vdots &\vdots &\vdots &\vdots\\ d_{1m} &d_{2m} &\dots &d_{(n-1)m} &d_{nm} \end{bmatrix} \]
行列の一部を取り出す
行列の一部分を別の行列へコピーするには、以下のようにします。
data = load('data.csv'); n=length(data(1,:)); X = data(:, 1:n-1); y = data(:, n); % m = length(y); %
ここでは、CSVから読み込んだデータセットの左側の(n-1)列をXに代入。一番右の1列をyに代入しています。 この時点で各変数の中身は以下のようになっています。
\[ data= \begin{bmatrix} x_11 &x_{21} &\dots &x_{n1} &y_1\\ x_12 &x_{22} &\dots &x_{n2} &y_2\\ x_13 &x_{23} &\dots &x_{n3} &y_3\\ \vdots &\vdots &\vdots &\vdots &\vdots\\ x_{1m} &x_{2m} &\dots &x_{nm} &y_m \end{bmatrix} , X= \begin{bmatrix} x_{11} &x_{21} &\dots &x_{n1}\\ x_{12} &x_{22} &\dots &x_{n2}\\ x_{13} &x_{23} &\dots &x_{n3}\\ \vdots &\vdots &\vdots &\vdots\\ x_{1m} &x_{2m} &\dots &x_{nm} \end{bmatrix} , y= \begin{bmatrix} y_1\\ y_2\\ y_3\\ \vdots\\ y_m \end{bmatrix} \]
行列の転置
Octave/MATLABで転置するには、シングルコーテーションを使います。
octave:5> theta theta theta = 34.624 30.287 octave:6> theta' theta' ans = 34.624 30.287 octave:7>
列の挿入
行列\(data\)の全行の最初の列に1を挿入するには以下のようにします。
octave:5> data=load("data.csv") data=load("data.csv") data = 6.11010 17.59200 5.52770 9.13020 8.51860 13.66200 7.00320 11.85400 5.85980 6.82330 8.38290 11.88600 ・ ・ ・ ・ ・ ・ 8.29340 0.14454 13.39400 9.05510 5.43690 0.61705 octave:6> m = length(data(:,1)) m = length(data(:,1)) m = 97 octave:7> data=[ones(m,1),data] data=[ones(m,1),data] data = 1.00000 6.11010 17.59200 1.00000 5.52770 9.13020 1.00000 8.51860 13.66200 1.00000 7.00320 11.85400 1.00000 5.85980 6.82330 1.00000 8.38290 11.88600 ・ ・ ・ ・ ・ ・ ・ ・ ・ 1.00000 8.29340 0.14454 1.00000 13.39400 9.05510 1.00000 5.43690 0.61705 octave:8>
データの可視化
Octave/MATLABで、散布図(a scatter plot)を描くためには、以下のようにします。
plot(X(:,1), y, 'x'); % 散布図を描きます ylabel('Amount'); % Y軸のラベルを設定 xlabel('Max temperture'); % X軸のラベルを設定
以下は、Courseraの講座で実際に表示したデータです。
Octave-Forge for Windows をインストールしてMinGW / MSYSから利用する
MinGW用(?)Octave-Forge for Windows を、Windows 10 にインストールして、MSYS(GitHub for WindowsについてるGitBash)で利用できるようにセットアップしたので、その手順を書いておきます。
photo credit: I23 - SPANning an octave via photopin (license)
しかし、ほとんど Windowsで利用するための手順であって、MinGW / MSYSに関連するのは、PATHとエイリアスの設定だけです。どこがどうMinGW向けなのか、いまだによくわかりませんが、まあいいです。
関係ないけど、いまだにMinGWとMSYSの関係がイメージとして把握できていないので、こういう記事でトンチンカンなことを書いていないか心配です。毎日使っているのにね。
ところで、Octaveってナンデスカ?
OctaveはGNUのフリーソフトウェアで、MATLAB互換の数値演算向け高水準プログラミング言語です。 MATLABは結構お高いのですが、Octaveは無料で利用可能です。
強力な行列演算の機能を備えていて、対話的にも利用できますから、とっても便利。
昨今世間を席巻している画像処理や機械学習、人工知能など、行列演算に依存するアルゴリズム開発のプロトタイピングに利用しやすいというわけです。
OpenCVやNumpy等、行列を扱う各種ライブラリでも、似たような関数名が使えます(zerosやeye等)、使い方を覚えておいて損はないと思います。 理系の学生さんとかは私なんかが言うまでもなく使えるのだとは思いますが。
スタンフォード大学の機械学習の講義でも使います
昨年(2015年)一部界隈で話題になったCourseraのMOOC、スタンフォード大学のMachine Learningの講義でも、MATLABかOctaveを使用するのが前提です。MATLAB/Octaveで課題に取り組んで、コマンド打ってオンラインで提出するシステムになっていました。
※ しかし、Windows版のOctaveではオンラインでの課題提出機能にバグがあるらしく、Windowsユーザーが受講するには講義中だけ特別に無料利用できるMATLABを使っていました。 てことで今回、講義履修後一年近く経過して、テキスト使って復習したいと思いまして、やっぱりOctave入れなきゃね、となったわけです。
第一人者もお薦めです
CourseraのCEOであり、Machine Learningの第一人者でもある同講義の講師、Andrew NG 先生によれば、「まずはアルゴリズム(演算内容)をMATLAB/Octaveで確認すべし」とのことですよ。
他の開発言語でも行列演算は行えますが、アルゴリズムの開発に集中するために、MATLAB/Octaveを使いなさいと。格段に効率が上がるからと。
じゃあ、Octave-Forgeってなに?
実はよく知りませんでした(笑)
ダウンロードページには、「A collection of packages providing extra functionality for GNU Octave」と書いてあるので、GNU Octaveのための追加機能を提供しているパッケージを集めたものということでしょう。
ということで、インストール手順はこちらです
取り立てて難しいことはなく、敢えて言うなら英語でズラズラ書いてあるのと、ファイルの説明が長い点。 それからWindows 10についての言及が無かったところ。
作業は、圧縮ファイルをダウンロードして、フォルダに展開、実行モジュールへのショートカットを作れば、Windowsから利用するだけなら、ほぼ完了。 Windows 8 以降なら、コマンドラインスイッチの追加設定が必要ですね。
そして、繰り返しになりますが、MinGW / MSYS向けには、PATHの設定とエイリアス。
ということで、詳細手順は以下のメニューでレッツゴー
- 事前準備:7-Zipのインストール
- 圧縮ファイルのダウンロード
- セットアップフォルダの作成
- 圧縮ファイルの展開
- Octave本体のファイルをコピー(もしくは移動)
- ショートカットの作成
- Windows 8 / 10でのコマンドラインスイッチの追加
- ショートカットのアイコン指定
- Octave-forge パッケージのコピー
- Octave-forge パッケージのビルド
- 起動時ワーニングの抑制
- オプショナルだが推奨される(?) エディタの設定
1.事前準備:7-Zipのインストール
ダウンロードする圧縮ファイルが、拡張子が7z
の7-Zipですので、必要な人は、7-Zipのダウンロードページから、お使いのシステムに応じたものをインストールしておきましょう。
2.圧縮ファイルのダウンロード
Octave 3.6.4 のダウンロードページから、 以下の2つをダウンロードします。
- Octave3.6.4_gcc4.6.2_20130408.7z - Octave 3.6.4 for Windows 本体
- Octave3.6.4_gcc4.6.2_20130408.7z - 利用可能なパッケージ
3.セットアップフォルダの作成
C:\
にOctave
というフォルダを作ります。実際にはどのような名前でも良いと説明書に書いてありますが、圧縮ファイルに入っているショートカットなどが、このフォルダを参照してるっぽいので、なるべくならこれに従ったほうが良いと思います。
4.圧縮ファイルの展開
ダウンロードした2つの7z
をC:\Octave
以下にディレクトリごと展開します。以下のようになってるはず。
C:\Octave\ +-- Octave3.6.4_gcc4.6.2_20130408\ | +-- Octave3.6.4_gcc4.6.2\ | +-- Octave3.6.4_gcc4.6.2(ショートカット) | +-- octave3.6.4_gcc4.6.2_docs(ショートカット) | +-- Octave3.6.4_gcc4.6.2_libblas_readme.txt | +-- Octave3.6.4_gcc4.6.2_readme.txt +-- Octave3.6.4_gcc4.6.2_pkgs_20130402\ +-- Octave3.6.4_gcc4.6.2\ +-- Octave3.6.4_gcc4.6.2_pkgs_list.txt +-- Octave3.6.4_gcc4.6.2_pkgs_readme.txt
5.Octave本体のファイルをコピー(もしくは移動)
この時点でC:\Octave\
以下に2つのフォルダがあって、そのどちらにも、Octave3.6.4_gcc4.6.2
というサブフォルダがありますね。
このうち、Octave3.6.4_gcc4.6.2_20130408\Octave3.6.4_gcc4.6.2
をC:\Octave\
の直下へフォルダごとコピー(または移動)します。
ここでインストールフォルダは以下のようになっているはず。
C:\Octave\ +-- Octave3.6.4_gcc4.6.2\ | +-- bin\ | +-- doc\ | +-- etc\ | . | . | . | +-- Octave3.6.4_gcc4.6.2_20130408\ | +-- Octave3.6.4_gcc4.6.2\(移動したならこれはない) | +-- Octave3.6.4_gcc4.6.2(ショートカット) | +-- octave3.6.4_gcc4.6.2_docs(ショートカット) | +-- Octave3.6.4_gcc4.6.2_libblas_readme.txt | +-- Octave3.6.4_gcc4.6.2_readme.txt +-- Octave3.6.4_gcc4.6.2_pkgs_20130402\ +-- Octave3.6.4_gcc4.6.2\ +-- Octave3.6.4_gcc4.6.2_pkgs_list.txt +-- Octave3.6.4_gcc4.6.2_pkgs_readme.txt
※ Windows 7 で単に使うだけなら、この時点で、C:\Octave\Octave3.6.4_gcc4.6.2\bin\octave.exe
を実行すれば使えます。残りの手順は、ショートカットを作ったり、ショートカットのアイコンを設定したりという手順です。
※ ちなみに、セットアップが完了したら、Octave3.6.4_gcc4.6.2_20130408
とOctave3.6.4_gcc4.6.2_pkgs_20130402
の2つのフォルダは丸ごと消してかまいません。
6.ショートカットの作成
ということで、任意の場所に Octave の実行ファイルへのショートカットを作成します。
Octave の実行ファイル C:\Octave\Octave3.6.4_gcc4.6.2\bin\octave.exe
を右クリックして、コンテキストメニューから「ショートカットの作成」を選択して、あとは任意の場所へ移動します。
とりあえずデスクトップでいいと思います。
7.Windows 8 / 10でのコマンドラインスイッチの追加
Windows 8では、対話式のコマンドラインの入力機能がうまく動かないそうで、ショートカットにコマンドラインスイッチ(オプション)の設定が必要です。 Windows 10でも同様です。
上で作ったショートカットを右クリックして、[プロパティ]を選択して、リンク先の最後にスペースを空けて、-i --line-editing
と追加します。
これで対話式のコマンドラインの編集機能が正しく動作するらしいです。
8.ショートカットのアイコン指定
動作にはまったく関係ありませんが、ショートカットのアイコンをOctaveのものに変更します。
「アイコンの変更」をクリックして、
C:\Octave\Octave3.6.4_gcc4.6.2\doc\octave\icons
のアイコンファイルを指定します。
アイコン選んで「OK」「OK」でOKです。
9.Octave-forge パッケージのコピー
次に、Octave3.6.4_gcc4.6.2_pkgs_20130402\Octave3.6.4_gcc4.6.2
をC:\Octave\
の直下へフォルダごとコピー(または移動)します。
フォルダの見た目は特に変わりませんね。
C:\Octave\ +-- Octave3.6.4_gcc4.6.2\ | +-- bin\ | +-- doc\ | +-- etc\ | . | . | . | +-- Octave3.6.4_gcc4.6.2_20130408\ | +-- Octave3.6.4_gcc4.6.2\ | +-- Octave3.6.4_gcc4.6.2(ショートカット) | +-- octave3.6.4_gcc4.6.2_docs(ショートカット) | +-- Octave3.6.4_gcc4.6.2_libblas_readme.txt | +-- Octave3.6.4_gcc4.6.2_readme.txt +-- Octave3.6.4_gcc4.6.2_pkgs_20130402\ +-- Octave3.6.4_gcc4.6.2\(移動したならこれはない) +-- Octave3.6.4_gcc4.6.2_pkgs_list.txt +-- Octave3.6.4_gcc4.6.2_pkgs_readme.txt
10.Octave-forge パッケージのビルド
実はこの部分について、ちゃんと理解していないのですが、「Octaveを使ってMinGW用パッケージをビルドして、Octave起動時に自動的に読み込むように設定するそうです(棒読み)」
上で作ったショートカットをダブルクリックして、Octaveを起動して、以下の5つのコマンドを実行します。 不要なものもあるようですが、とりあえず全部実行して問題は発生しませんでした。
pkg rebuild -auto pkg rebuild -noauto ad pkg rebuild -noauto nan pkg rebuild -noauto gsl pkg rebuild -auto java
11.起動時ワーニングの抑制
これまでの手順で、ほとんどの設定が完了していますが、この時点で実行すると、大量のワーニングが出ます。
このワーニングは、統計パッケージのfstat関数に関するものらしく、古くて使用されないfstatも多重定義されているというもので、無視してよいと説明されています。
抑制するには、octave起動時に実行されるスタートアップファイルC:\Octave\Octave3.6.4_gcc4.6.2\share\octave\site\m\startup\octaverc
に、以下の一行を付け加えます。場所はとりあえずプロンプト設定の直後としました。
## System-wide startup file for Octave. ## ## This file should contain any commands that should be executed each ## time Octave starts for every user at this site. more off PS1('octave:\#> ') ## ワーニング抑制 warning('off', 'Octave:shadowed-function')
これで大量のワーニングは抑制されましたが、まだ2つほどワーニングが出ています。 この2つは、ワーニングの情報が表示されないので、どうやって抑制してよいかわかりませんでした。ま、2つなので我慢してます。
12.オプショナルだが推奨される(?) エディタの設定
オプショナルですが推奨されるエディタの設定です。
こちらもスタートアップファイルC:\Octave\Octave3.6.4_gcc4.6.2\share\octave\site\m\startup\octaverc
に設定します。
エディタとしてはNOTEPAD++が推奨されているみたいで、コメントを外せばいいよとされていますが、私はKaoriyaさんのGvimを使っているので以下のように設定しました。
## Uncomment and change any of the following lines for your preferred editor ## EDITOR('C:\\Program Files (x86)\\Notepad++\\notepad++.exe'); ## EDITOR('C:\\Program Files\\Notepad++\\notepad++.exe'); EDITOR('C:\\Program Files\\vim74-kaoriya-win32\\gvim.exe');
ただ、実際この設定が、どこに効いてくるのか知りません。
お疲れ様です。以上で設定完了です。
あとは、MSYSでC:\Octave\Octave3.6.4_gcc4.6.2\bin
にPATHを通して、Windows 8 / 10のユーザーならば ~/.bash_profile
や.bashrc
で、alias octave=octave -i --line-editing
と、エイリアスを設定しておけば便利に使えます。
以下、5x5の魔法陣を表示してみました。やあ、数学は美しいですね。
$ octave GNU Octave, version 3.6.4 Copyright (C) 2013 John W. Eaton and others. This is free software; see the source code for copying conditions. There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, type `warranty'. Octave was configured for "i686-pc-mingw32". Additional information about Octave is available at http://www.octave.org. Please contribute if you find this software useful. For more information, visit http://www.octave.org/get-involved.html Read http://www.octave.org/bugs.html to learn how to submit bug reports. For information about changes from previous versions, type `news'. warning: gmsh does not seem to be present some functionalities will be disabled warning: dx does not seem to be present some functionalities will be disabled octave:1> magic(5) magic(5) ans = 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 octave:2>
リンク
WPFのDataGrid:カラムの表示・非表示をバインディングで切り替える
WPFのDataGridで、特定の列の表示・非表示をバインディングで切り替える方法を書いておきます。
photo credit: National Building Museum via photopin (license)
当初、「Visibilityをバインドするんでしょ?」と、簡単にやってみたけど無理でした。 調査の結果「プロキシー(代替)オブジェクトで中継する」と。 「なんのこっちゃ」と思いながらも試行錯誤。どうにか機構を把握して、自力で書けるようになりました。
ここでは、DataGridTextColumn
のVisibility
をCheckBox
のIsChecked
へプロキシを介してバインドしていますが、
他のバインディングターゲットにも適用できると思います。
以下、チェックボックスによって切り替えるコードです。XAMLだけで出来るのですね。
MainWindow.xaml
コードの説明
12~13行目: BooleanからVisibilityの値へ変換するコンバーターを宣言しています。チェックボックスのIsCheckedをVisibilityへ変換するためのものです。
15~16行目:
<FrameworkElement x:Key="ProxyColumnVisibility" DataContext="{Binding Path=IsChecked, ElementName=checkBoxShowColumn}"/>
GridのResource内に、DataContextをCheckBoxのIsCheckedへバインドしたFrameworkElementを宣言。20~21行目:
<ContentControl Visibility="Collapsed" Content="{StaticResource ProxyColumnVisibility}"/>
非表示にしたContentControlのContentに上で定義しているProxyColumnVisibilityを入れています。22~24行目:
<CheckBox x:Name="checkBoxShowColumn"
FrameworkElementからバインドされるチェックボックスです。32行目:
Visibility="{Binding DataContext, Source={StaticResource ProxyColumnVisibility},Converter={StaticResource BooleanToVisibilityConverter}}"
Visibilityを、ProxyColumnVisibilityのDataContextへバインド。
参考にさせていただいたURL
以下のサイトにお世話になりました。ありがたい。
- [WPF]DataGridColumnへのバインディング | OITA: Oika's Information Technological Activities
- c# - Bind datagrid column visibility MVVM - Stack Overflow
いくつになってもお勉強
WPFもXAMLも年に一度、数か月程しか使わないので、毎年「ややこしいわーわけわからんわー」から始まって、同じところでつまづいて、調べなおして「へぇー」とか言って、そのうち「うわ、これ便利やん」にたどり着く感じ。
系統立てた知識がないのが問題かなと。これを機会に明快な理解を試みようと思っています。
いくつになってもお勉強です。
関連情報(MSDNへのリンク)
「FrameworkElementって何者なの?」「てかResourceってなに?」「ContentControlは必要?」とか、フツフツと沸いてくる疑問に、うまく答えられないワタシがいる。なので、以下にMSDNのWPF関連のリンクを並べておきます。そのうち自分で調べる用です。
ShellでZIPの特定ディレクトリ以下全ファイルをUnzip
CLIのunzipで、ZIPファイルから特定ディレクトリ以下の全ファイルを取り出す方法の覚書き。
photo credit: A Bag of Colors via photopin (license)
GUIのツールだと何も問題ありませんが、シェルから使うunzip(Info-Zipのunzip?)では、取り出すファイルを全て指定する必要があるようです。数によっては現実的にちょっと無理。ひとつふたつならOKですけどね。
「なんでオプション無いのかねえ・・・」と、しばらく途方に暮れていたのですが、以下のようにして解決しました。
$ unzip -d Foo Foo.zip `zipinfo -1 Foo.zip | grep '^Path\\/To\\/Target'`
- バッククォート内で、
zipinfo
コマンドを使って、全ファイル名を標準出力へ出力。-1
オプションでファイル名(だけ)の出力。 - 同じバッククォート内で、パイプで標準出力をgrepへ渡して、正規表現で特定のパス以下のファイル名だけに絞り込み。
- その出力を、コマンド置換で、unzipのコマンドラインに展開して抽出。ここでは
-d
オプションは出力先ディレクトリを指定しています。無くてもいいけど念のため。
何が有り難いってバッククォートでのコマンド置換(標準出力をコマンドラインへ展開)。
さらに今回初めて知ったのですが、$(command)
でも同じことらしいですね。
知ってるつもりでも、調べてみると、さらに深い発見があったりして、いくつになってもお勉強ですな。
参考
unzipとzipinfoのヘルプ出力。
$ unzip -h UnZip 6.00 of 20 April 2009, by Info-ZIP. Maintained by C. Spieler. Send bug reports using http://www.info-zip.org/zip-bug.html; see README for details. Usage: unzip [-Z] [-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir] Default action is to extract files in list, except those in xlist, to exdir; file[.zip] may be a wildcard. -Z => ZipInfo mode ("unzip -Z" for usage). -p extract files to pipe, no messages -l list files (short format) -f freshen existing files, create none -t test compressed archive data -u update files, create if necessary -z display archive comment only -v list verbosely/show version info -T timestamp archive to latest -x exclude files that follow (in xlist) -d extract files into exdir modifiers: -n never overwrite existing files -q quiet mode (-qq => quieter) -o overwrite files WITHOUT prompting -a auto-convert any text files -j junk paths (do not make directories) -aa treat ALL files as text -U use escapes for all non-ASCII Unicode -UU ignore any Unicode fields -C match filenames case-insensitively -L make (some) names lowercase -X restore UID/GID info -V retain VMS version numbers -K keep setuid/setgid/tacky permissions -M pipe through "more" pager See "unzip -hh" or unzip.txt for more help. Examples: unzip data1 -x joe => extract all files except joe from zipfile data1.zip unzip -p foo | more => send contents of foo.zip via pipe into program more unzip -fo foo ReadMe => quietly replace existing ReadMe if archive file newer
$ zipinfo -h ZipInfo 3.00 of 20 April 2009, by Greg Roelofs and the Info-ZIP group. List name, date/time, attribute, size, compression method, etc., about files in list (excluding those in xlist) contained in the specified .zip archive(s). "file[.zip]" may be a wildcard name containing *, ?, [] (e.g., "[a-j]*.zip"). usage: zipinfo [-12smlvChMtTz] file[.zip] [list...] [-x xlist...] or: unzip -Z [-12smlvChMtTz] file[.zip] [list...] [-x xlist...] main listing-format options: -s short Unix "ls -l" format (def.) -1 filenames ONLY, one per line -m medium Unix "ls -l" format -2 just filenames but allow -h/-t/-z -l long Unix "ls -l" format -v verbose, multi-page format miscellaneous options: -h print header line -t print totals for listed files or for all -z print zipfile comment -T print file times in sortable decimal format -C be case-insensitive -M page output through built-in "more" -x exclude filenames that follow from listing
DynamoDB:条件式のプレースホルダを自動生成してみましょう
コンソールから AWSを操作するコマンドセットを提供するNodeモジュール(npm)のご紹介。 DynamoDBのクエリやスキャンでプレースホルダーを自動生成するAPIも提供してます。
DynamoDBから条件付きでQueryやScanを行う場合、条件式等の中で使われている単語がDynamoDBのキーワード(予約語)と一致する場合、その単語をプレースホルダーに変換して、別途指定しなければなりません。
プレースホルダーは2種類あります。属性名を置き換える属性名のプレースホルダーと、検索条件等で指定する値を置き換える値のプレースホルダーで、それぞれ別の対応が必要です。DynamoDBのキーワードの数はかなり多く、全部覚えていられないし、一般的な単語がたくさん含まれてるので厄介なんです。
てなことで、怒りに任せて、条件式をテーブルの属性名や値をそのまま使って記述してDynamoDBからクエリできるnode.jsのコマンド群をnpmとして公開しているのでご紹介。DynamoDB関係以外のコマンドセットも含まれています(Lambda, API Gateway, IoT, IAM等)。 コンソールからデータの有無や内容を、軽く確認する時に、ちょっと便利。
最新バージョン(v0.8.6以降)では、DynamoDBをSQLで扱うためのステートメントクラスも使えるようになりました。 これについては、以下の記事で説明してます。
npmは以下↓からどうぞ。
DynamoDBのプレースホルダを気にせず使える3つのコマンド
※ AWS CLIのデフォルトユーザー、デフォルトリージョンで接続します。
セットアップ
npmでグローバルにインストールしてください。
$ npm install aws-node-util --global
1. aws-dynamodb-putItem - 項目追加・更新
テーブルに項目を追加、または更新します。item-expressionで指定したキーがすでにあるなら上書きされ、なければ追加されます。
aws-dynamodb-put-item [options] <tableName> <item-expression>
パラメータ
tableName - 操作対象のテーブル名
item-expression - 追加・更新する項目を
属性名=属性値,属性名=属性値
という形式で記述します。
項目には、少なくともテーブルの全てのキー属性が含まれていなくてはなりません。キーの値によって項目が追加されるか更新されるかが決まるからです。これはDynamoDBの仕様です。
属性名と属性値のプレースホルダーは自動的に生成されるので、気にする必要はありません。
実行例
$ aws-dynamodb-put-item stars "mainStar = 'SUN', role='planet', orbitOrder=3, name='EARTH', mass=5.97, diameter=12756, density=5514, gravity=9.8, escapeVelocity=11.2, rotation=23.9"; OK. $ aws-dynamodb-put-item stars "mainStar = 'EARTH', role='satellite', orbitOrder=1, name='MOON', mass=0.0073, diameter=3475, density=3340, gravity=1.6, escapeVelocity=2.4, rotation=655.7"; OK. $
値の型
属性値は、文字列、数値、ブーリアンの3つの型に対応しています。
文字列は引用符でくくられている必要があり、ブーリアンはtrue
かfalse
のどちらかです。
MAP型のデータを表現するには
MAP型のデータは、属性名をドットで区切ってpath.to.the.subitem
という形式で記述します。これによって、指定されたキーの名前を持つMAP型のデータを自動生成します。
2. aws-dynamodb-query - 項目のクエリ
キーを指定してテーブルから項目を抽出します。
aws-dynamodb-query [options] <tableName> <keyConditionExpression>
オプション
オプション | 長いオプション | 説明 |
---|---|---|
-p | --projection-expression=ARG | 表示する属性名をカンマ区切りで指定 |
-f | --filter-expression=ARG | 検索後のフィルター条件式 |
-c | --max-items=ARG | 表示する件数(既定値は20) |
-s | --sort-item=ARG | 表示時に並び替える項目名を指定 |
-d | --desc | 降順の並び替えを指定 |
パラメータ
- tableName - 操作対象のテーブル名
- keyConditionExpression - 抽出するキーの条件式を与えます。
実行例
$ aws-dynamodb-query stars 'mainStar="SUN"'\ --projection-expression 'name,orbitOrder,mass,diameter, gravity,density,rotation'\ --sort-item orbitOrder Count: 9 ROWNUM mass rotation name gravity orbitOrder density diameter 1 0.33 1407.6 MERCURY 3.7 1 5427 4879 2 4.87 -5832.0 VENUS 8.9 2 5243 12104 3 5.97 23.9 MARS 9.8 3 5514 12756 4 0.642 24.6 MARS 3.7 4 3933 6792 5 1898.0 9.9 JUPITER 23.1 5 1326 142984 6 568.0 10.7 SATURN 9.0 6 687 120536 7 86.8 -17.2 URANUS 8.7 7 1271 51118 8 102.0 16.1 NEPTUNE 11.0 8 1638 49528 9 0.0146 -153.3 PLUTO 0.7 9 2095 2370 ScannedCount: 9 $
※ 上記表形式でのコンソール出力は、以下の記事でご紹介している npm list-itを利用しています。
3. aws-dynamodb-scan - 項目のスキャン
テーブルをScanします。キーの条件式は指定できませんが、その他の使い方はQueryとほぼ同じです。
aws-dynamodb-scan [options] <tableName>
オプション
オプション | 長いオプション | 説明 |
---|---|---|
-p | --projection-expression=ARG | 表示する属性名をカンマ区切りで指定 |
-f | --filter-expression=ARG | 検索後のフィルター条件式 |
-c | --max-items=ARG | 表示する件数(既定値は20) |
-s | --sort-item=ARG | 表示時に並び替える項目名を指定 |
-d | --desc | 降順の並び替えを指定 |
パラメータ
- tableName - 操作対象のテーブル名
実行例
$ aws-dynamodb-scan stars \ --projection-expression 'name,orbitOrder,mass,diameter, gravity,density,rotation'\ --filter-expression 'role="planet"'\ --sort-item orbitOrder --desc Count: 10 ROWNUM mass rotation name gravity orbitOrder density diameter 1 0.0146 -153.3 PLUTO 0.7 9 2095 2370 2 102.0 16.1 NEPTUNE 11.0 8 1638 49528 3 86.8 -17.2 URANUS 8.7 7 1271 51118 4 568.0 10.7 SATURN 9.0 6 687 120536 5 1898.0 9.9 JUPITER 23.1 5 1326 142984 6 0.642 24.6 MARS 3.7 4 3933 6792 7 5.97 23.9 MARS 9.8 3 5514 12756 8 4.87 -5832.0 VENUS 8.9 2 5243 12104 9 0.33 1407.6 MERCURY 3.7 1 5427 4879 ScannedCount: 10 $
共通オプション
以下は各コマンド共通のオプションです。
オプション | 長いオプション | 説明 |
---|---|---|
-j | --output-json | AWSのレスポンスを複数行のJSONとして表示 |
-J | --output-json-oneline | AWSのレスポンスを1行のJSONとして表示 |
-h | --help | ヘルプを表示。 |
※ ヘルプは、オプションの説明しか表示しません。
参考
オプション --projection-expression
、--filter-expression
、--key-condition-expression
と、パラメータkeyConditionExpression
の表記内容や使用可能な演算子については、Query - Amazon DynamoDB、または、Scan - Amazon DynamoDBを参考にしてください。
ただし、プレースホルダ―については、自動的に変換しますので気にしなくて結構です。
制限事項
使用可能な型は、文字列(S)、数字(N)、真偽値(BOOL)、マップ(M)だけです。 リスト(L)はできれば対応したいと思っています。
表示時のカラムの順序は指定できません。一見、projectionExpressionで指定した順番でデータを取得すればよいように思えるのですが、AWSから得られるデータの並びが、この順になっているわけではないからです。とはいえ、なんとか順序を指定できるようにしたいとは思っています。
リポジトリ
その他
同モジュールでは、他にも雑多なコマンドがたくさん含まれていますが、ドキュメントだけでなく動作確認等、まったく追いついていません。
不具合、御要望、改善案などございましたらGitHubのissueでご指摘ください。もちろん他の方法でも構いません。
また、個人的な取り組みとして最近ドキュメントは全て英文でチャレンジしていますので、妙な表現、文法間違い、Typoなど、山ほどあるかと思います。 こちらについても、おかしなところがあれば、ご指摘くださいヨロシクお願いいたします。
AWSへの接続について
※ 以下、~
はホームディレクトリを表します。Windowsなら、C:\Users\<ユーザー名>
などに読み替えてください。
aws-sdkでは、AWSへの接続のため、以下のAWS CLIで作成される認証情報を使用しているようです。 しかし、同じくAWS CLIが生成するデフォルトリージョンは利用してくれないため、このコマンド独自に読み込んでいます。
認証情報 ~/.aws/credential
[default] aws_access_key_id = <アクセスキー> aws_secret_access_key = <シークレットアクセスキー>
コンフィグ ~/.aws/configure
[default] output = json region = ap-northeast-1
DynamoDBのプレースホルダーについての基本
DynamoDBのテーブル操作の「式」の中で、プレースホルダ―を使用しなければならないケースがある。プレースホルダ―は以下2種類。
- 「属性名のプレースホルダ―」 - 式の中の属性名を置き換える。式の中には予約済みキーワードを表記できないので、属性名が予約済みキーワードとかぶった場合に使用。
- 「属性値のプレースホルダ―」 - 式の中の値を置き換えるためのもの。式の中には値を直接表記できないから、全ての値を置き換える必要がある。
予約済みのキーワードが多く、また一般的な単語も多く含まれている。 属性名に関して、予約済みキーワードがどうかにかかわらず全部置き換えても構わない。