Analisis yang sama, kode yang sama, tetapi hasilnya berbeda antara dua eksekusi — atau berbeda antara komputer kita dan komputer rekan — adalah kegagalan reproduce: penelitian yang tidak bisa diulang. Di MATLAB, sumbernya hampir selalu salah satu dari lima faktor tersembunyi: seed acak, versi engine, data yang berubah, path absolut, dan hasil yang tertimpa. Chapter ini membahas cara menutup kelimanya:
- Seed tetap dengan
rngdan uji ulang dua eksekusi denganisequal. - Data terkunci dengan checksum, path relatif dengan
mfilename, manifest versi, dan penyimpanan hasil.
Sumber Ketak-Reproduksibel #
| Faktor | Gejala | Solusi |
|---|---|---|
| Seed acak | hasil beda setiap eksekusi | rng(seed) di awal pipeline |
| Versi MATLAB/toolbox | angka numerik bergeser halus | manifest versi + guard (chapter Dependency Management) |
| Data berubah | analisis lama tak bisa diulang | data terkunci + checksum |
| Path absolut | gagal di komputer/folder lain | mfilename + fullfile |
| Hasil tertimpa | riwayat hilang diam-diam | folder hasil/ + simpan hasil bersama parameternya |
Seed Tetap dan Uji Ulang #
Pipeline reproducible menyatukan data terkunci dan komponen acak dengan seed eksplisit:
function out = pipelineStok(seed)
%PIPELINESTOK Pipeline demo: data tetap + komponen acak ber-seed.
data = [120 135 150 180 90 210]; % harga historis (terkunci)
out.checksum = checksumManual(data);
out.nData = numel(data);
rng(seed); % seed tetap = deterministik
proyeksi = data(end) * (1 + 0.05 * randn(1, 30));
out.medianProyeksi = median(proyeksi);
out.maksProyeksi = max(proyeksi);
endMekanisme di balik layar: rng(seed) me-reset state generator angka acak ke titik yang sama setiap kali dipanggil, sehingga urutan randn berikutnya identik. Pengujiannya dua arah — jalankan dengan seed sama dua kali (harus identik), dan dengan seed beda (harus berbeda):
a = pipelineStok(42);
b = pipelineStok(42);
c = pipelineStok(7);
fprintf('data: %d harga historis, checksum %d\n', a.nData, a.checksum);
fprintf('percobaan 1 dan 2 identik (isequal): %d\n', isequal(a, b));
fprintf('seed berbeda mengubah hasil simulasi: %d\n', ~isequal(a, c));
assert(isequal(a, b));
assert(~isequal(a, c));Data Terkunci dengan Checksum #
Data yang dikunci tidak berubah selama analisis berjalan, dan kita bisa membuktikannya tidak berubah. Checksum manual sederhana — jumlah nilai byte representasi data, dimodulo — cukup untuk mendeteksi perubahan:
function k = checksumManual(data)
%CHECKSUMMANUAL Checksum sederhana untuk data integer.
k = mod(sum(uint8(sprintf('%d;', data))), 10000);
endSimpan checksum di laporan (contoh: 1209 untuk enam harga [120 135 150 180 90 210]), lalu bandingkan saat analisis diulang: checksum yang sama berarti data yang sama. Checksum sederhana ini bukan kriptografi (tabrakan mungkin), tetapi cukup sebagai penjaga perubahan tak sengaja pada data analisis. Untuk data penting, MATLAB juga dapat memakai fungsi hash dari toolbox keamanan — prinsipnya sama.
Path Relatif dan Manifest #
Path absolut (C:\Users\budi\proyek\data.csv) hanya hidup di satu komputer. Pola portabelnya berakar pada lokasi berkas itu sendiri:
root = fileparts(mfilename('fullpath'));
folderHasil = fullfile(root, 'hasil-demo');mfilename('fullpath') mengembalikan lokasi berkas yang sedang dieksekusi, sehingga root mengikuti ke mana pun proyek dipindah atau dibagikan — pola yang sama dengan startProyek.m di chapter Struktur Proyek. Manifest menutup faktor versi: catat version() dan toolbox terpasang bersama hasil (di sini dicetak sebagai baris version() = 10.3.0 ...; komputer Anda mencetak versi MATLAB Anda). Struktur penuh manifest proyek: versi engine, tanggal eksekusi, seed yang dipakai, dan checksum data — cukup satu blok kecil di awal laporan.
Simpan Hasil dan Uji Reproducibility #
Hasil disimpan bersama parameternya dalam satu berkas .mat, lalu ke-lengkapannya diverifikasi dengan load + isequal. contoh.m menggabungkan semuanya — dua eksekusi seed tetap, manifest, penyimpanan dari current folder yang sengaja dipindahkan, pemuatan ulang, dan pembersihan:
Output yang Dihasilkan (dari contoh.m lengkap):
== Bagian 1: dua kali eksekusi, seed tetap ==
data: 6 harga historis, checksum 1209
percobaan 1 dan 2 identik (isequal): 1
seed berbeda mengubah hasil simulasi: 1
== Bagian 2: manifest environment ==
version() = 10.3.0 (catat di manifest proyek)
== Bagian 3: path relatif + simpan/muat ==
folder hasil-demo dibuat di samping berkas pipeline
cwd berbeda, hasil tetap tersimpan relatif berkas: 1
roundtrip .mat identik setelah dimuat ulang: 1
== Bagian 4: pembersihan ==
folder hasil-demo dihapus: exist = 0
folder kerja sementara dihapus: exist = 0Alur lengkap ujinya digambarkan diagram berikut — hasil hanya dinyatakan reproducible setelah putaran uji ulang lulus:
Ringkasan #
Reproducibility ditutup lima kunci: rng(seed) tetap di awal pipeline, data terkunci dengan checksum yang dicatat, path dibangun dari fileparts(mfilename('fullpath')) bukan path absolut, manifest versi engine menyertai hasil, dan hasil disimpan bersama parameternya lalu diverifikasi load + isequal. Uji akhirnya sederhana dan tegas: jalankan dua kali, bandingkan — contoh.m melakukannya sampai bersih tanpa sisa berkas.