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 rng dan uji ulang dua eksekusi dengan isequal.
  • Data terkunci dengan checksum, path relatif dengan mfilename, manifest versi, dan penyimpanan hasil.

Sumber Ketak-Reproduksibel #

FaktorGejalaSolusi
Seed acakhasil beda setiap eksekusirng(seed) di awal pipeline
Versi MATLAB/toolboxangka numerik bergeser halusmanifest versi + guard (chapter Dependency Management)
Data berubahanalisis lama tak bisa diulangdata terkunci + checksum
Path absolutgagal di komputer/folder lainmfilename + fullfile
Hasil tertimpariwayat hilang diam-diamfolder hasil/ + simpan hasil bersama parameternya

Seed Tetap dan Uji Ulang #

Pipeline reproducible menyatukan data terkunci dan komponen acak dengan seed eksplisit:

matlab
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);
end

Mekanisme 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):

matlab
    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:

matlab
function k = checksumManual(data)
%CHECKSUMMANUAL Checksum sederhana untuk data integer.
    k = mod(sum(uint8(sprintf('%d;', data))), 10000);
end

Simpan 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:

matlab
    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):

text
== 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 = 0

Alur 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.