cv.cm

コーディング · プログラミング言語

MATLAB入門

約10分で読めます

結論

MATLABは、MathWorks社が提供する数値計算向けの言語・環境で、すべての値が行列です。行列積は A * B、要素ごとの乗算は A .* B と書き、添字は1から始まり、多くのループをベクトル化した式に置き換えられます。グラフ描画機能と、工学・科学向けの豊富なツールボックスを備えています。GNU Octaveは無料のオープンソースの代替で、基本的なMATLABコードの大半をそのまま実行できます。

MATLABとは何か、誰が使っているのか

MATLAB(「matrix laboratory」)は、線形代数ライブラリを手軽に使えるようにしたいCleve Molerのツールとして始まり、MathWorks社の商用製品になりました。言語、対話型デスクトップ、グラフ描画に加え、信号処理、制御系、最適化、統計、画像処理、機械学習のツールボックスを備えています。関連製品のSimulinkは、ブロック線図で動的システムをモデル化します。

MATLABは、工学・科学の授業、研究室、自動車・航空宇宙・金融などの業界で広く使われています。有償ライセンスが必要です(多くの大学が提供しています)。GNU Octaveは文法がほぼ互換のフリーソフトウェアで、中核の言語と多くの関数をカバーしますが、MathWorks社のツールボックスやSimulinkには対応しません。

インストールとHello, world

MathWorks社からMATLABをインストールするか、ブラウザーでMATLAB Onlineを使うか、octave.orgからGNU Octave(Windows、macOS、Linux)をインストールします。コードは .m ファイルに保存します。スクリプトはコマンドを並べたファイルで、コマンドウィンドウで .m を除いた名前を入力して実行します。

% hello.m
disp('Hello, world!')
matlab -batch "hello"   # MATLAB from a terminal
octave hello.m          # GNU Octave
# Hello, world!

コメントは % で始めます。セミコロンなしで終わる行は結果を表示するので、x = 5 は x = 5 と表示し、x = 5; は何も表示しません。

変数と基本の型

変数は代入で作られ、宣言は不要です。数値は既定で double(64ビット浮動小数点数)で、単一の数でも1行1列の行列です。

型例備考
doublex = 3.14既定の数値型
整数型n = int32(42)int8 から int64、uint8 から uint64。演算は飽和する
logicalok = truex > 2 のような比較の結果
文字配列name = 'Ana'シングルクォート。文字の行ベクトル
strings = "Ana"MATLABの文字列オブジェクト。Octaveではダブルクォートも文字配列として扱う
セル配列c = {'Ana', 30}異なる型の値を保持できる
structp.name = 'Ana'名前付きのフィールド
x = 10;
y = 3;
x / y              % 3.3333
mod(x, y)          % 1
x ^ 2              % 100
name = 'Ana';
fprintf('%s is %d years old\n', name, 30)
% Ana is 30 years old
class(x)           % 'double'

ベクトルと行列

角括弧で配列を作ります。スペースまたはカンマで列を、セミコロンで行を区切ります。添字は丸括弧で指定し、1から始まります。end は最後の添字、: は「すべて」を意味します。

v = [3 1 4 1 5];
v(1)               % 3
v(end)             % 5
v(2:4)             % [1 4 1]
v * 2              % [6 2 8 2 10]
v(v > 2)           % [3 4 5]   logical indexing
A = [1 2; 3 4];
A(2, :)            % second row: [3 4]
A'                 % transpose:  [1 3; 2 4]
A * A              % matrix product: [7 10; 15 22]
A .* A             % element-wise:   [1 4; 9 16]
b = [5; 11];
x = A \ b          % solves A*x = b: [1; 2]
z = zeros(2, 3);   % also ones, eye, rand
r = 0:0.25:1;      % [0 0.25 0.5 0.75 1]

ドット付きの演算子(.*、./、.^)は要素ごとに働き、ドットなしは線形代数の規則に従います。バックスラッシュ演算子は連立一次方程式を解き、inv(A) * b を計算するより精度が高くなります。

制御構文

score = 85;
if score >= 90
    disp('A')
elseif score >= 80
    disp('B')
else
    disp('C')
end

total = 0;
for k = 1:10
    total = total + k;
end
fprintf('total = %d\n', total)   % total = 55

n = 3;
while n > 0
    n = n - 1;
end

switch 'red'
    case {'red', 'green'}
        disp('a color')
    otherwise
        disp('unknown')
end

すべてのブロックは end で終わります。多くのループはベクトル化した式に置き換えられます。上のループは sum(1:10) と同じで、より短く、たいていは高速です。どうしてもループで配列を作る場合は、先に領域を確保しておきます(例:result = zeros(1, 1000);)。

関数と無名関数

関数は、関数名と同じ名前の専用ファイルに書きます。関数は複数の出力を返せます。最近のMATLABのバージョンでは、スクリプトの末尾にローカル関数を置くこともできます。

% stats.m
function [m, s] = stats(x)
%STATS Mean and sample standard deviation of a vector.
    m = mean(x);
    s = std(x);
end
[m, s] = stats([2 4 4 5 7])   % m = 4.4000, s = 1.8166
[biggest, where] = max([3 9 2])   % biggest = 9, where = 2

f = @(x) x.^2 + 1;            % anonymous function
f(3)                          % 10
f([1 2 3])                    % [2 5 10]
fzero(@(x) x.^2 - 2, 1)       % 1.4142, a root near 1
integral(f, 0, 1)             % 1.3333

@ で作る無名関数は、fzero、integral、arrayfun、最適化ルーチンなど、ほかの関数に渡すためによく使われます。ベクトルにも使えるように、要素ごとの演算子(.^)で書きましょう。

構造体とセル配列

person.name = 'Ana';
person.age = 30;
fprintf('%s is %d\n', person.name, person.age)   % Ana is 30

c = {'Ana', 30, [1 2 3]};   % cell array with mixed types
c{2}                         % 30 (curly braces get the content)
class(c(2))                  % 'cell' (parentheses get a sub-cell)
names = {'Ana', 'Ben', 'Cleo'};
numel(names)                 % 3
upper(names{1})              % 'ANA'

MATLABには、スプレッドシートのように名前付き変数を持つ列指向のデータを扱う table 型もあります。readtable でCSVやExcelファイルを読み込めます。

エラー処理

error でエラーを発生させます。'demo:negative' のような識別子を付けることもでき、try ... catch で処理します。捕捉したオブジェクト(MATLABでは MException)には identifier と message のフィールドがあります。

% safe_sqrt.m
function r = safe_sqrt(x)
    if x < 0
        error('demo:negative', 'Input must be non-negative, got %g', x);
    end
    r = sqrt(x);
end
try
    safe_sqrt(-4);
catch err
    fprintf('%s: %s\n', err.identifier, err.message)
end
% demo:negative: Input must be non-negative, got -4

プログラムを止めるべきでない問題には warning(...) を使います。チェックがなければ、sqrt(-4) はまったく失敗せず、複素数 0 + 2i を返します。

小さな完成プログラム:データの分析とグラフ描画

% temps.m - analyze a week of temperatures
temps = [21.5 23.0 19.8 25.1 24.3 18.9 22.7];
days = 1:numel(temps);

avg = mean(temps);
[hottest, idx] = max(temps);
above = days(temps > avg);

fprintf('Average: %.2f\n', avg)
fprintf('Hottest: %.1f on day %d\n', hottest, idx)
fprintf('Days above average: %s\n', mat2str(above))

plot(days, temps, '-o')
hold on
plot(days, avg * ones(size(days)), '--')
xlabel('Day'); ylabel('Temperature (C)')
title('Temperatures this week')
legend('Daily', 'Average')
% Average: 22.19
% Hottest: 25.1 on day 4
% Days above average: [2 4 5 7]

このスクリプトは、論理インデックスを使ってループなしで平均を上回る日を見つけ、マーカー付きの折れ線グラフと破線の平均線を描きます。同じコードがGNU Octaveでも動きます。

次のステップ

  • MathWorks社のMATLABドキュメント。まずは入門ページから。
  • MATLAB Onramp:MathWorks社が提供する無料の対話型入門コース。
  • Octaveを使う場合は、MATLAB互換性に関する注意も載っているGNU Octaveマニュアル。
  • 次は、ベクトル化、データファイル用の readtable、グラフ描画関数を学びましょう。

よくある質問

MATLABの無料版はありますか?

MATLAB本体にはライセンスが必要ですが、MathWorks社は試用版を提供しており、多くの大学がキャンパスライセンスを用意しています。GNU Octaveは無料のオープンソースプログラムで、基本的なMATLABコードの大半を実行できます。

MATLABの * と .* の違いは何ですか?

* は線形代数の行列積で、内側の次元が一致している必要があります。.* は、同じサイズの2つの配列の対応する要素どうしを掛けます。

GNU OctaveはMATLABと完全に互換ですか?

完全ではありません。中核の文法、行列、関数、グラフ描画はほぼ互換ですが、OctaveにはMathWorks社のツールボックス、Simulink、一部の新しいMATLAB機能がなく、独自に追加の構文もいくつか受け付けます。

MATLABの添字はなぜ1から始まるのですか?

MATLABは数学の表記に従っており、ベクトルや行列の最初の要素は1番目の要素です。Fortran、R、Juliaも同じ規則です。

MATLABとPythonはどちらを学ぶべきですか?

授業や研究室、会社でMATLABを使うなら、特にSimulinkや特定のツールボックスを使うなら、MATLABを学びましょう。NumPy、SciPy、Matplotlibを使うPythonは無料でより汎用的で、考え方は両者で通用します。

コーディング講座の一覧