MacBook Pro (Mid 2012, 13インチ)のSATA cableの交換
2週間ほど前に、MACのOSが立ち上がらなくなりました。
結論から言うと、SATAケーブルを交換したら治ったのですが、その記録をここに書いておきます。
*特にMACBookPro Mid 2012モデルの方向けの追記をしました。
時系列
- MACを久々に再起動させようとすると、OSが起動しなくなってしまいました。最初はソフト的な問題かと思い、PRAMのリセットやディスクの修復などWebにある対処法を一通りやってみましたが、ダメでした。
- 次に、データやアプリケーションは消さずに(HDDをフォーマットせずに)OSXのみの再インストールを試みましたが、これも失敗しました。そこで、諦めて、HDDをフォーマットしてしまうことにしました。重要なデータはDropBox等に置いているのですが、バックアップを取っていないデータもあったので、救出しました。HDDから、データを救出する方法は、例えば、下のようなやり方があると思います。僕の場合は、1.の方法では外付けHDDとして認識されなかったので、方法2.でデータを取り出しました。
- MACの中のHDDを外付けのHDDとして、動かす(具体的には、他のMACとThunderboltケーブルでつないで、ターゲットディスクモードで他のMACからHDDのデータを取り出す)。詳しくは「ターゲットディスクモード Thunderbolt」などでググってください。
- リカバリーモードで使えるターミナルで、MACの中のHDDのデータをUSBメモリなどに移す。http://techracho.bpsinc.jp/morimorihoge/2014_07_09/18182を参照。上のリンクでは、ネットワーク経由でデータを吸いだしていますが、USBメモリや外付けHDDなどを使うほうが楽だと思います。また、最初、ターミナルからdfコマンドで、Macintosh HDが見えなくても、暗号化されている場合、ディスクユーティリティから、パスワードを入れることで、マウントできます(ディスクユーティリティからHDDが見れない場合はこの方法は無理だと思います)。この方法では、ターミナルからコマンドを使って、データを移動させないとダメです。シェルコマンドに慣れてない人はググる。
- MacBookからHDDを物理的に取り出して、SATA-USBケーブルなど(内蔵のHDDを外付けにできるケースを買うのが楽かもしれません)を使って、他のMACに差して、データを取り出す。
2つのarrayが近似的に同じか比べる
2つのNdarrayが近い値かどうかを比べるには、numpy.allcloseを使う。
- numpy.allclose(a, b, rtol=1e-05, atol=1e-08)
2つのarray a,bを受け取って(a,bは同じshapeのarrayでないといけない)、すべての成分が
absolute(a - b) ≦ (atol + rtol * absolute(b))
を満たせばTrueを、満たさない成分があればFalseを返す。
成分ごとに、比較したい場合はnumpy.iscloseを使う。
また、近い値かどうかではなく、exactに一致しているかどうかを調べたい時には、numpy.array_equalもしくはnumpy.array_equivを使う(numpy.array_equalはshapeが一致している時のみTrueで、numpy.array_equivはbroadcastedして一致するならTrue)。
Ref:
http://ibisforest.org/index.php?python%2Fnumpy#q0f5fdb7
http://docs.scipy.org/doc/numpy/reference/generated/numpy.allclose.html
http://docs.scipy.org/doc/numpy/reference/generated/numpy.isclose.html
http://docs.scipy.org/doc/numpy/reference/generated/numpy.array_equal.html
http://docs.scipy.org/doc/numpy/reference/generated/numpy.array_equiv.html
例)
import numpy as np A = np.array([1.0, 1.0]) B = np.array([1.0000001, 1.0]) print np.allclose(A,B) print np.isclose(A,B) print np.array_equal(A,B)
True
[ True True]
False
複素数型が実数に近かったら、実数型にする
complex型のndarrayが与えられた時に、もし複素数の部分が小さいなら、floatなどの実数の型で近似する方法。
そういう関数、ありそうだと思ってググったらNumpyの関数にnumpy.real_if_closeというのがあった。
numpy.real_if_close(a, tol=100)
この関数はNdarray aの虚部a_imagを見て、それがa_imag≦マシンイプシロン*tol(Tolerance)なら、虚部を無視した実部だけのNdarrayを返す。
a = a_real + i*a_imag → a = a_real
マシンイプシロンは
np.finfo(np.float).eps
で調べることができ、Pythonでは普通、2.22044604925e-16になっているみたいです。
tolはデフォルトでは100に設定されているので、a_imag≦2.22044604925e-14であれば虚部を無視することになります(tolはオプションで変更できます)。
このように、np.real_if_closeは虚部の絶対値をみて、小さいかどうかを判断する仕様になっている。
しかし、普通aの絶対値が大きくなると、誤差の絶対値も大きくなるので、虚部/絶対値が小さいかどうかを見るほうが、良い場合が多いと思う。:
print np.finfo(np.float).eps a_real = np.array([1.0e4]) a_imag = np.array([3e-12j]) a = a_real + a_imag print a.dtype a = np.real_if_close(a, tol=100*np.absolute(a)) print a.dtype
2.22044604925e-16
complex128
float64
Numpyは欲しい関数がたいてい用意されているのですごい!
http://docs.scipy.org/doc/numpy/reference/generated/numpy.real_if_close.html
http://docs.scipy.org/doc/numpy/reference/generated/numpy.absolute.html
2015.6.26 追記
オプションtolで1より小さい値を設定すると、real_if_closeは配列を常に実数型にしてしまうようです(本来は複素数型のままにして欲しい)。
そもそも、tolが1より小さいとa_imagがゼロでない値を持っていたら、最小値はマシンイプシロンなので、常に複素数のままになるべきですが、たぶんそういうtolを想定して関数が作られておらず、バグってしまうのだと思います。
上のtol=100*np.absolute(a)という設定はaの絶対値が大きい場合を想定していますが、逆に絶対値が小さい場合は使うときに注意してください。
Pythonの代入の挙動
Pythonで代入をした時に、各変数がどのオブジェクトを指すかをまとめておく。特に、list(リスト)とNdarray(配列)の違いをば。
前回の記事も参照 : http://oppython.hatenablog.com/entry/2015/01/15/014729
例1
前回の記事でも書いたようにPythonでは、代入(=)は変数に値(=オブジェクト)を格納しているのではなく(値渡し)、値(=オブジェクト)への参照を格納している(参照渡し)。
x = np.array([1]) y = x print 'id(x)_before =', id(x) print 'id(y)_berore =', id(y) x = np.array([2]) print 'id(x)_after =', id(x) print 'id(y)_after =', id(y) print y
id(x)_before = 4300100832
id(y)_berore = 4300100832
id(x)_after = 4300101152
id(y)_after = 4300100832
[1]
y = xとすると、変数yもxと同じオブジェクトnp.array([1])を指すようになる(参照渡し)。
変数xに新しいオブジェクトnp.array([2])を代入すると、xは新しいオブジェクトを参照するようになる。
もちろん、yには何もしていないので、始めのオブジェクトを参照したままである。
上の挙動は、ndarrayだけでなく、タプル、文字列、リスト、数値などでも共通(型が変更可能かどうかに依らない)。
Pythonの型の分類と代入
変数が指すオブジェクトがどれかなどの振る舞いをすぐ忘れてしまうのでメモしておく。
組み込み型の分類
まず、Pythonの組み込み型についてまとめておく。
管理方式
管理方式の違いで分類すると、以下のようになる。
- コレクション型(=コンテナ型):複数のデータをまとめたもの
+ シーケンス型:要素を順番に並べて管理。整数のindexでデータを管理できる。
例)文字列、リスト、タプル
+ マップ型:キーと値のペアで要素を管理。
例)ディクショナリ
- 非コレクション
例)数値型(int, float, long, complex)、ブール型、None
文字型がシーケンス型なのは面白い。シーケンスなので、たとえば、
a = "oppai" print a[4] #i
のようにスライスを使って、要素の指定とかができる。
変更可能性
変更可能性で分類すると、以下のようになる。
- 変更可能 (mutable)
例)リスト、ディクショナリ
- 変更不能 (immutable)
例)数値型、文字列、タプル
基本的に、代入なりなんなりをした時の挙動は、変更可能かどうかで決まる。
オブジェクトはメモリに保存されているが、変更可能ならば、そのメモリに書かれているオブジェクトは書き換え可能になる。
numpy.matrixとnumpy.ndarrayの違い
numpy.matrixと2次元のnumpy.ndarrayは同じことができるが、numpy.matrixでできることはすべてnumpy.ndarrayでできる。
numpy.matrixがある理由はたぶん、行列を扱う時にはnumpy.ndarrayより見やすいので。
行列以外の高次のテンソルを扱う時には、混乱を避けるため、numpy.ndarrayだけ使うようにしたほうがよいと思われ。
個人的には、行列以外のテンソルを扱うことも多いし、numpy.matrixを使う理由はなさそう。
Ref:
http://wiki.scipy.org/NumPy_for_Matlab_Users
http://docs.scipy.org/doc/scipy-0.14.0/reference/tutorial/linalg.html
固有値問題
Pythonで固有値問題を解く方法についてメモしておく。
メジャーな方法として、以下の3つがある
- numpy.linalgの関数を使う。
- scipy.linalgの関数を使う。
- scipy.sparse.linalgの関数を使う。
numpy.linalgとscipy.linalgには以下の4つの関数がある。
- eig:一般の行列の固有値・固有ベクトルを求める。
- eigh:エルミート(or 実対称)行列の固有値・固有ベクトルを求める。
- eigvals:一般の行列の固有値のみを求める。
- eigvalsh:エルミート(or 実対称)行列の固有値のみを求める。
関数名のhはHermitianの略。Scipyだと一般化固有値問題*1もオプションで出来る。
ちなみに、scipy.linalgはnumpy.linalgに含まれる関数はすべて含んでいて、さらに追加で他の関数も含んでいる。また、scipy.linalgが常にBLAS/LAPACKでコンパイルされるのに対し、numpy.linalgはそうとは限らないので、scipyの方が早い場合もある。なので、特別な理由(コードが既にnumpy.linalgで書かれていて、書きなおすのがめんどいとか)がない限り、scipy.linalgを使うほうがよい。たぶん。
http://docs.scipy.org/doc/scipy-0.14.0/reference/tutorial/linalg.html
scipy.sparse.linalgには以下の2つの関数がある。
関数名のsはsparseの略。一般化固有値問題も出来る。
続きを読む