684 lines
25 KiB
PHP
684 lines
25 KiB
PHP
<?php
|
|
namespace App\Http\Controllers;
|
|
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use App\Models\DataUji;
|
|
use App\Models\Prediksi;
|
|
use App\Models\DataLatih;
|
|
use Maatwebsite\Excel\Facades\Excel;
|
|
use App\Models\HasilPengujian;
|
|
|
|
class UjiController extends Controller
|
|
{
|
|
public function index()
|
|
{
|
|
$dataLatih = DataLatih::all();
|
|
$dataUji = session('data_uji', []);
|
|
$jumlahDataLatih = $dataLatih->count();
|
|
$riwayatTerakhir = HasilPengujian::latest('created_at')->whereNotNull('status_prediksi')->get();
|
|
if (session()->has('hasil_uji')) {
|
|
$hasil = session('hasil_uji');
|
|
}
|
|
if ($jumlahDataLatih <= 0) {
|
|
return "Tidak ada data latih, silahkan input terlebih dahulu";
|
|
}
|
|
|
|
// Tidak ada data uji karena belum diproses
|
|
$jumlahDataUji = 0;
|
|
$persentase_uji = 0;
|
|
$persentase_latih = 100;
|
|
$dataUji = [];
|
|
|
|
// Tetap hitung atribut numerik sebagai persiapan visualisasi
|
|
$atribut_numerik = $this->hitungAtributNumerik($dataLatih);
|
|
|
|
// Untuk kategori tetap hitung juga
|
|
$fitur_kategorik = ['faktor1', 'faktor2'];
|
|
$kelas = ['Naik', 'Turun'];
|
|
|
|
$atribut_kategorik = [];
|
|
foreach ($fitur_kategorik as $fitur) {
|
|
$kategori_unik = $dataLatih->pluck($fitur)->unique()->values()->all();
|
|
$atribut_kategorik[$fitur] = [
|
|
'kategori' => $kategori_unik,
|
|
'status' => []
|
|
];
|
|
|
|
foreach ($kelas as $label) {
|
|
$group = $dataLatih->where('hipotesis', $label);
|
|
$total_group = $group->count();
|
|
|
|
$prob_kategori = [];
|
|
foreach ($kategori_unik as $kategori) {
|
|
$jumlah_kategori = $group->where($fitur, $kategori)->count();
|
|
$prob = ($jumlah_kategori + 1) / ($total_group + count($kategori_unik));
|
|
$prob_kategori[] = $prob;
|
|
}
|
|
$atribut_kategorik[$fitur]['status'][strtolower($label)] = $prob_kategori;
|
|
}
|
|
}
|
|
|
|
// Tidak ada hasil uji karena belum dilakukan
|
|
$hasil = [];
|
|
$akurasi = 0;
|
|
$precision = 0;
|
|
$recall = 0;
|
|
$tp = $fp = $tn = $fn = 0;
|
|
|
|
// Probabilitas kelas (sebagai info statistik)
|
|
$jumlah_naik = $dataLatih->where('hipotesis', 'Naik')->count();
|
|
$jumlah_turun = $dataLatih->where('hipotesis', 'Turun')->count();
|
|
$total_data = $jumlah_naik + $jumlah_turun;
|
|
|
|
$prob_naik = $total_data > 0 ? round(($jumlah_naik / $total_data) * 100, 2) : 0;
|
|
$prob_turun = $total_data > 0 ? round(($jumlah_turun / $total_data) * 100, 2) : 0;
|
|
|
|
// Data kategorik seperti di index()
|
|
$fitur_kategorik = ['faktor1', 'faktor2'];
|
|
$kelas = ['Naik', 'Turun'];
|
|
$atribut_kategorik = [];
|
|
// Cek apakah ada data hasil uji di session
|
|
if (session()->has('hasil_uji')) {
|
|
$hasil = session('hasil_uji');
|
|
$akurasi = session('akurasi_uji');
|
|
$precision = session('precision_uji');
|
|
$recall = session('recall_uji');
|
|
$tp = session('tp_uji');
|
|
$fp = session('fp_uji');
|
|
$tn = session('tn_uji');
|
|
$fn = session('fn_uji');
|
|
$persentase_uji = session('persentase_uji');
|
|
$persentase_latih = session('persentase_latih');
|
|
$jumlahDataUji = session('jumlah_data_uji');
|
|
$jumlahDataLatih = session('jumlah_data_latih');
|
|
$prob_turun = session('prob_turun', 0);
|
|
$prob_naik = session('prob_naik', 0);
|
|
$jumlah_turun = session('jumlah_turun', 0);
|
|
$jumlah_naik = session('jumlah_naik', 0);
|
|
$total_data = $jumlah_naik + $jumlah_turun;
|
|
} else {
|
|
// Default data kosong kalau belum ada pengujian
|
|
$hasil = [];
|
|
$akurasi = 0;
|
|
$precision = 0;
|
|
$recall = 0;
|
|
$tp = $fp = $tn = $fn = 0;
|
|
$persentase_uji = 0;
|
|
$persentase_latih = 100;
|
|
$jumlahDataUji = 0;
|
|
$jumlah_naik = $dataLatih->where('hipotesis', 'Naik')->count();
|
|
$jumlah_turun = $dataLatih->where('hipotesis', 'Turun')->count();
|
|
$total_data = $jumlah_naik + $jumlah_turun;
|
|
|
|
// Controller
|
|
$prob_naik = $total_data > 0 ? ($jumlah_naik / $total_data) : 0;
|
|
$prob_turun = $total_data > 0 ? ($jumlah_turun / $total_data) : 0;
|
|
}
|
|
|
|
foreach ($fitur_kategorik as $fitur) {
|
|
$kategori_unik = $dataLatih->pluck($fitur)->unique()->values()->all();
|
|
$atribut_kategorik[$fitur] = [
|
|
'kategori' => $kategori_unik,
|
|
'status' => []
|
|
];
|
|
|
|
foreach ($kelas as $label) {
|
|
$group = $dataLatih->where('hipotesis', $label);
|
|
$total_group = $group->count();
|
|
|
|
$prob_kategori = [];
|
|
foreach ($kategori_unik as $kategori) {
|
|
$jumlah_kategori = $group->where($fitur, $kategori)->count();
|
|
$prob = ($jumlah_kategori + 1) / ($total_group + count($kategori_unik));
|
|
$prob_kategori[] = $prob;
|
|
}
|
|
$atribut_kategorik[$fitur]['status'][strtolower($label)] = $prob_kategori;
|
|
}
|
|
}
|
|
|
|
return view('admin.uji-data', [
|
|
'jumlah_data_latih' => $dataLatih->count(),
|
|
'persentase_latih' => $persentase_latih,
|
|
'persentase_uji' => $persentase_uji,
|
|
'jumlah_data_uji' => $jumlahDataUji,
|
|
'prob_turun' => $prob_turun,
|
|
'prob_naik' => $prob_naik,
|
|
'jumlah_turun' => $jumlah_turun,
|
|
'jumlah_naik' => $jumlah_naik,
|
|
'atribut_numerik' => $this->hitungAtributNumerik($dataLatih),
|
|
'atribut_kategorik' => $atribut_kategorik,
|
|
'dataUji' => $dataUji,
|
|
'data_uji' => $hasil,
|
|
'akurasi' => round($akurasi, 2),
|
|
'precision' => round($precision, 2),
|
|
'recall' => round($recall, 2),
|
|
'tp' => $tp,
|
|
'fp' => $fp,
|
|
'tn' => $tn,
|
|
'fn' => $fn,
|
|
'data_kasus' => $this->hitungAtributNumerik($dataLatih)['kasus_2023'] ?? [],
|
|
'jumlah_data' => $dataLatih->count(),
|
|
'total_data' => $total_data,
|
|
'riwayat_pengujian' => $riwayatTerakhir,
|
|
'from_excel' => false
|
|
|
|
]);
|
|
}
|
|
public function proses(Request $request)
|
|
{
|
|
$dataLatih = DataLatih::inRandomOrder()->get();
|
|
$persentase = (int) $request->input('persentase');
|
|
$total = $dataLatih->count();
|
|
|
|
if ($total === 0) {
|
|
return back()->with('error', 'Data kosong');
|
|
}
|
|
|
|
// Hitung jumlah data latih dan uji sesuai persentase
|
|
$jumlahDataLatih = max(round($total * ($persentase / 100)), 1);
|
|
$jumlahDataUji = $total - $jumlahDataLatih;
|
|
|
|
$dataLatihUpdate = $dataLatih->slice(0, $jumlahDataLatih);
|
|
$dataUji = $dataLatih->slice($jumlahDataLatih);
|
|
|
|
// Hitung probabilitas kelas dari dataLatihUpdate
|
|
$probabilitasKelas = $this->hitungProbabilitasKelas($dataLatihUpdate);
|
|
|
|
if (empty($probabilitasKelas)) {
|
|
return back()->with('error', 'Gagal hitung probabilitas kelas!');
|
|
}
|
|
|
|
// Hitung jumlah hipotesis Naik dan Turun di data latih (opsional, bisa untuk info)
|
|
$jumlah_naik = $dataLatihUpdate->where('hipotesis', 'Naik')->count();
|
|
$jumlah_turun = $dataLatihUpdate->where('hipotesis', 'Turun')->count();
|
|
$total_data = $jumlah_naik + $jumlah_turun;
|
|
|
|
$hasil = [];
|
|
$benar = 0;
|
|
$tp = $fp = $tn = $fn = 0;
|
|
$hasilSudahAda = HasilPengujian::count() > 0;
|
|
|
|
foreach ($dataUji as $data) {
|
|
$hipotesisAsli = ucfirst(strtolower($data->hipotesis));
|
|
$prediksi = $this->naiveBayes($data, $dataLatihUpdate);
|
|
|
|
$prediksiTahun = ((int)$data->data_tahun <= 2024) ? 2025 : ((int)$data->data_tahun + 1);
|
|
|
|
$status = $prediksi === $hipotesisAsli ? '✅ Benar' : '❌ Salah';
|
|
|
|
$hasil[] = [
|
|
'id' => $data->id,
|
|
'kabupaten' => $data->kecamatan,
|
|
'data_tahun' => $data->data_tahun,
|
|
'phbs' => $data->phbs,
|
|
'imunisasi' => $data->imunisasi,
|
|
'merokok' => $data->merokok,
|
|
'kasus_2023' => $data->kasus_2023,
|
|
'latitude' => $data->latitude,
|
|
'longitude' => $data->longitude,
|
|
'prediksi_tahun' => $prediksiTahun,
|
|
'hipotesis_asli' => $hipotesisAsli,
|
|
'prediksi' => $prediksi,
|
|
'status' => $status,
|
|
];
|
|
|
|
// Simpan hasil pengujian ke database jika belum ada data
|
|
if (!$hasilSudahAda) {
|
|
HasilPengujian::create([
|
|
'kecamatan' => $data->kecamatan,
|
|
'data_tahun' => $data->data_tahun,
|
|
'phbs' => $data->phbs,
|
|
'imunisasi' => $data->imunisasi,
|
|
'merokok' => $data->merokok,
|
|
'jumlah_kasus' => $data->kasus_2023 ?? 0,
|
|
'latitude' => $data->latitude,
|
|
'longitude' => $data->longitude,
|
|
'prediksi_tahun' => $prediksiTahun,
|
|
'status_asli' => $hipotesisAsli,
|
|
'status_prediksi' => $prediksi,
|
|
]);
|
|
}
|
|
|
|
// Hitung TP, FP, TN, FN untuk evaluasi
|
|
if ($hipotesisAsli === 'Naik' && $prediksi === 'Naik') $tp++;
|
|
if ($hipotesisAsli === 'Naik' && $prediksi === 'Turun') $fn++;
|
|
if ($hipotesisAsli === 'Turun' && $prediksi === 'Naik') $fp++;
|
|
if ($hipotesisAsli === 'Turun' && $prediksi === 'Turun') $tn++;
|
|
|
|
if ($hipotesisAsli === $prediksi) $benar++;
|
|
}
|
|
|
|
$akurasi = $benar / $jumlahDataUji * 100;
|
|
$precision = $tp + $fp > 0 ? ($tp / ($tp + $fp)) * 100 : 0;
|
|
$recall = $tp + $fn > 0 ? ($tp / ($tp + $fn)) * 100 : 0;
|
|
|
|
|
|
session([
|
|
'hasil_uji' => $hasil,
|
|
'akurasi_uji' => round($akurasi, 2),
|
|
'precision_uji' => round($precision, 2),
|
|
'recall_uji' => round($recall, 2),
|
|
'tp_uji' => $tp,
|
|
'fp_uji' => $fp,
|
|
'tn_uji' => $tn,
|
|
'fn_uji' => $fn,
|
|
'persentase_uji' => 100 - $persentase,
|
|
'persentase_latih' => $persentase,
|
|
'jumlah_data_uji' => $dataUji->count(),
|
|
'jumlah_data_latih' => $dataLatihUpdate->count(),
|
|
'prob_turun' => $probabilitasKelas['Turun'],
|
|
'prob_naik' => $probabilitasKelas['Naik'],
|
|
'jumlah_turun' => $jumlah_turun,
|
|
'jumlah_naik' => $jumlah_naik,
|
|
'total_data' => $total_data,
|
|
'id_data_latih' => $dataLatihUpdate->pluck('id')->toArray(),
|
|
'id_data_uji' => $dataUji->pluck('id')->toArray(),
|
|
]);
|
|
|
|
return view('admin.uji-data', [
|
|
'hasil' => $hasil,
|
|
'benar' => $benar,
|
|
'total' => $jumlahDataUji,
|
|
'totalDataLatih' => $jumlahDataLatih,
|
|
'akurasi' => round($akurasi, 2),
|
|
'precision' => round($precision, 2),
|
|
'recall' => round($recall, 2),
|
|
'tp' => $tp,
|
|
'fp' => $fp,
|
|
'tn' => $tn,
|
|
'fn' => $fn,
|
|
'persentase' => $persentase,
|
|
'atribut_numerik' => $this->hitungAtributNumerik($dataLatih),
|
|
'jumlah_data' => $jumlahDataLatih,
|
|
'data_uji' => $hasil,
|
|
'jumlah_data_latih' => $dataLatihUpdate->count(),
|
|
'jumlah_data_uji' => $dataUji->count(),
|
|
'persentase_latih' => $persentase,
|
|
'persentase_uji' => 100 - $persentase,
|
|
'probabilitasKelas' => $probabilitasKelas,
|
|
'prob_naik' => $probabilitasKelas['Naik'],
|
|
'prob_turun' => $probabilitasKelas['Turun'],
|
|
'jumlah_naik' => $jumlah_naik,
|
|
'jumlah_turun' => $jumlah_turun,
|
|
'total_data' => $total_data,
|
|
'from_excel' => false
|
|
]);
|
|
}
|
|
|
|
public function naiveBayes($uji, $dataLatih)
|
|
{
|
|
$labels = ['Naik', 'Turun'];
|
|
$fitur = ['phbs', 'imunisasi', 'merokok', 'kasus_2023'];
|
|
$hasilLogProb = [];
|
|
|
|
foreach ($labels as $label) {
|
|
$group = $dataLatih->where('hipotesis', $label);
|
|
$totalGroup = $group->count();
|
|
|
|
if ($totalGroup == 0) {
|
|
$hasilLogProb[$label] = -INF;
|
|
continue;
|
|
}
|
|
|
|
$prior = $totalGroup / $dataLatih->count();
|
|
$logProb = log($prior);
|
|
|
|
foreach ($fitur as $f) {
|
|
$mean = $group->avg($f);
|
|
$variance = $group->reduce(function ($carry, $item) use ($f, $mean) {
|
|
return $carry + pow($item[$f] - $mean, 2);
|
|
}, 0) / $totalGroup;
|
|
|
|
$variance = max($variance, 1e-6); // Hindari division by zero
|
|
|
|
$prob = (1 / sqrt(2 * M_PI * $variance)) * exp(-pow($uji[$f] - $mean, 2) / (2 * $variance));
|
|
$logProb += log($prob);
|
|
}
|
|
|
|
$hasilLogProb[$label] = $logProb;
|
|
}
|
|
|
|
// Ambil label dengan logProb terbesar
|
|
return array_keys($hasilLogProb, max($hasilLogProb))[0];
|
|
}
|
|
private function hitungAtributNumerik($dataLatih)
|
|
{
|
|
$atribut_numerik = [];
|
|
$fitur_numerik = ['phbs', 'imunisasi', 'merokok', 'kasus_2023'];
|
|
$kelas = ['Naik', 'Turun'];
|
|
|
|
// Mapping label nama atribut
|
|
$nama_atribut_baru = [
|
|
'phbs' => 'Perilaku Hidup Bersih dan Sehat',
|
|
'imunisasi' => 'Imunisasi',
|
|
'merokok' => 'Kebiasaan Merokok',
|
|
'kasus_2023' => 'Data Kasus',
|
|
];
|
|
|
|
foreach ($fitur_numerik as $fitur) {
|
|
$atribut_numerik[$fitur] = [
|
|
'label' => $nama_atribut_baru[$fitur] ?? ucfirst($fitur),
|
|
'mean' => [],
|
|
'std' => [],
|
|
'avg_prob' => [],
|
|
];
|
|
foreach ($kelas as $label) {
|
|
$group = $dataLatih->where('hipotesis', $label);
|
|
$mean = $group->avg($fitur) ?? 0;
|
|
$variansi = $group->reduce(function ($carry, $item) use ($fitur, $mean) {
|
|
return $carry + pow($item[$fitur] - $mean, 2);
|
|
}, 0) / max($group->count() - 1, 1);
|
|
$std = sqrt($variansi);
|
|
|
|
$atribut_numerik[$fitur]['mean'][strtolower($label)] = $mean;
|
|
$atribut_numerik[$fitur]['std'][strtolower($label)] = $std;
|
|
|
|
$prob = (1 / sqrt(2 * M_PI * $variansi)) * exp(-pow($mean - $mean, 2) / (2 * $variansi));
|
|
$atribut_numerik[$fitur]['avg_prob'][strtolower($label)] = round($prob, 6);
|
|
}
|
|
}
|
|
return $atribut_numerik;
|
|
}
|
|
|
|
public function reset()
|
|
{
|
|
// Hapus hasil pengujian dari session
|
|
session()->forget([
|
|
'hasil_uji',
|
|
'akurasi_uji',
|
|
'precision_uji',
|
|
'recall_uji',
|
|
'tp_uji',
|
|
'fp_uji',
|
|
'tn_uji',
|
|
'fn_uji',
|
|
'persentase_uji',
|
|
'persentase_latih',
|
|
'jumlah_data_uji',
|
|
'jumlah_data_latih',
|
|
'id_data_latih',
|
|
'id_data_uji'
|
|
]);
|
|
|
|
// Hapus data hasil pengujian dari database jika perlu
|
|
HasilPengujian::truncate(); // ini akan menghapus semua data dari tabel hasil_pengujian
|
|
DataUji::truncate();
|
|
session()->flash('enable_radio', true);
|
|
return redirect()->route('admin.uji-data')->with('success', 'Hasil pengujian telah direset.');
|
|
}
|
|
public function upload(Request $request)
|
|
{
|
|
$request->validate([
|
|
'file_excel' => 'required|file|mimes:xls,xlsx',
|
|
]);
|
|
|
|
$data = \Excel::toArray([], $request->file('file_excel'));
|
|
|
|
if (empty($data[0]) || count($data[0]) < 2) {
|
|
return back()->withErrors(['file_excel' => 'File Excel kosong atau tidak sesuai format.']);
|
|
}
|
|
|
|
// Ambil statistik dari data latih
|
|
$jumlah_naik = DataLatih::where('hipotesis', 'Naik')->count();
|
|
$jumlah_turun = DataLatih::where('hipotesis', 'Turun')->count();
|
|
$jumlah_data_latih = $jumlah_naik + $jumlah_turun;
|
|
|
|
if ($jumlah_data_latih == 0) {
|
|
return back()->withErrors(['file_excel' => 'Data latih tidak tersedia atau kosong.']);
|
|
}
|
|
|
|
$dataBaru = [];
|
|
$jumlah_data_uji_total = DataUji::count(); // Jumlah data uji, misal 15
|
|
$total_datatest = $jumlah_data_latih + $jumlah_data_uji_total; // 17 + 15 = 32
|
|
|
|
$persentase_latih = $total_datatest > 0 ? round(($jumlah_data_latih / $total_datatest) * 100) : 0; // % data latih dari total
|
|
$persentase_uji = $total_datatest > 0 ? round(($jumlah_data_uji_total / $total_datatest) * 100) : 0; // % data uji dari total
|
|
|
|
$prob_naik = $jumlah_data_latih > 0 ? round($jumlah_naik / $jumlah_data_latih, 4) : 0; // probabilitas naik dari data latih
|
|
$prob_turun = $jumlah_data_latih > 0 ? round($jumlah_turun / $jumlah_data_latih, 4) : 0; // probabilitas turun dari data latih
|
|
|
|
$fitur_list = ['phbs', 'imunisasi', 'merokok', 'kasus_2023'];
|
|
$atribut_numerik = [];
|
|
$fitur_labels = [
|
|
'phbs' => 'Perilaku Hidup Bersih dan Sehat',
|
|
'imunisasi' => 'Imunisasi',
|
|
'merokok' => 'Merokok',
|
|
'kasus_2023' => 'Jumlah Kasus',
|
|
];
|
|
foreach ($fitur_list as $fitur) {
|
|
$data_naik = DataLatih::where('hipotesis', 'Naik')->pluck($fitur)->filter()->values();
|
|
$data_turun = DataLatih::where('hipotesis', 'Turun')->pluck($fitur)->filter()->values();
|
|
|
|
$mean_naik = $data_naik->avg();
|
|
$mean_turun = $data_turun->avg();
|
|
|
|
$std_naik = sqrt($data_naik->map(fn($x) => pow($x - $mean_naik, 2))->avg() ?: 0) ?: 1e-6;
|
|
$std_turun = sqrt($data_turun->map(fn($x) => pow($x - $mean_turun, 2))->avg() ?: 0) ?: 1e-6;
|
|
|
|
$atribut_numerik[$fitur] = [
|
|
'label' => $fitur_labels[$fitur] ?? 'Tidak ada label',
|
|
'mean' => ['naik' => $mean_naik, 'turun' => $mean_turun],
|
|
'std' => ['naik' => $std_naik, 'turun' => $std_turun],
|
|
];
|
|
}
|
|
$tp = $tn = $fp = $fn = 0;
|
|
|
|
foreach ($data[0] as $index => $row) {
|
|
if ($index == 0 || strtolower(trim($row[1] ?? '')) === 'kecamatan') continue;
|
|
|
|
$kecamatan = trim($row[1] ?? '');
|
|
$jumlah_penduduk = intval($row[2] ?? 0);
|
|
$data_tahun = intval($row[3] ?? 0); // jika perlu tahun
|
|
$phbs = floatval(str_replace(',', '.', $row[4] ?? 0));
|
|
$imunisasi_pcv_1 = floatval(str_replace(',', '.', $row[5] ?? 0)); // jika kamu gunakan
|
|
$imunisasi_pcv_2 = floatval(str_replace(',', '.', $row[6] ?? 0)); // jika kamu gunakan
|
|
$imunisasi = floatval(str_replace(',', '.', $row[7] ?? 0));
|
|
$merokok = floatval(str_replace(',', '.', $row[8] ?? 0));
|
|
$jumlah_kasus = intval($row[9] ?? 0);
|
|
$latitude = floatval(str_replace(',', '.', $row[10] ?? 0));
|
|
$longitude = floatval(str_replace(',', '.', $row[11] ?? 0));
|
|
$status = trim($row[12] ?? '');
|
|
|
|
|
|
if (!$kecamatan || $phbs === null || $imunisasi === null || $merokok === null) {
|
|
continue;
|
|
}
|
|
|
|
$rasio = ($phbs + $imunisasi - $merokok) / ($jumlah_kasus ?: 1);
|
|
$status_asli = $rasio > 1 ? 'Naik' : 'Turun';
|
|
|
|
$log_naik = log($prob_naik ?: 1e-10);
|
|
$log_turun = log($prob_turun ?: 1e-10);
|
|
|
|
$fitur_values = [
|
|
'phbs' => $phbs,
|
|
'imunisasi' => $imunisasi,
|
|
'merokok' => $merokok,
|
|
'kasus_2023' => $jumlah_kasus,
|
|
];
|
|
|
|
foreach ($fitur_values as $fitur => $value) {
|
|
$mean_naik = $atribut_numerik[$fitur]['mean']['naik'];
|
|
$mean_turun = $atribut_numerik[$fitur]['mean']['turun'];
|
|
$std_naik = $atribut_numerik[$fitur]['std']['naik'];
|
|
$std_turun = $atribut_numerik[$fitur]['std']['turun'];
|
|
|
|
$gauss_naik = (1 / ($std_naik * sqrt(2 * M_PI))) * exp(-pow($value - $mean_naik, 2) / (2 * pow($std_naik, 2)));
|
|
$gauss_turun = (1 / ($std_turun * sqrt(2 * M_PI))) * exp(-pow($value - $mean_turun, 2) / (2 * pow($std_turun, 2)));
|
|
|
|
$log_naik += log($gauss_naik ?: 1e-10);
|
|
$log_turun += log($gauss_turun ?: 1e-10);
|
|
}
|
|
|
|
$prediksi = $log_naik > $log_turun ? 'Naik' : 'Turun';
|
|
|
|
if ($status_asli == 'Naik' && $prediksi == 'Naik') $tp++;
|
|
elseif ($status_asli == 'Turun' && $prediksi == 'Turun') $tn++;
|
|
elseif ($status_asli == 'Turun' && $prediksi == 'Naik') $fp++;
|
|
elseif ($status_asli == 'Naik' && $prediksi == 'Turun') $fn++;
|
|
|
|
$dataUji = new DataUji();
|
|
$dataUji->kecamatan = $kecamatan;
|
|
$dataUji->jumlah_penduduk = $jumlah_penduduk;
|
|
$dataUji->data_tahun = $data_tahun;
|
|
$dataUji->phbs = $phbs;
|
|
$dataUji->imunisasi_pcv_1 = $imunisasi_pcv_1;
|
|
$dataUji->imunisasi_pcv_2 = $imunisasi_pcv_2;
|
|
$dataUji->rata_rata_imunisasi = $imunisasi;
|
|
$dataUji->perilaku_merokok = $merokok;
|
|
$dataUji->data_kasus = $jumlah_kasus;
|
|
$dataUji->latitude = $latitude;
|
|
$dataUji->longitude = $longitude;
|
|
$dataUji->status_prediksi = $prediksi;
|
|
$dataUji->save();
|
|
|
|
// Cek apakah data uji untuk kecamatan ini sudah ada
|
|
$dataUjiExist = DataUji::where('kecamatan', $kecamatan)->first();
|
|
|
|
if (!$dataUjiExist) {
|
|
// Jika belum ada, simpan data baru
|
|
$dataUji = new DataUji();
|
|
$dataUji->kecamatan = $kecamatan;
|
|
$dataUji->jumlah_penduduk = $jumlah_penduduk;
|
|
$dataUji->data_tahun = $data_tahun;
|
|
$dataUji->phbs = $phbs;
|
|
$dataUji->imunisasi_pcv_1 = $imunisasi_pcv_1;
|
|
$dataUji->imunisasi_pcv_2 = $imunisasi_pcv_2;
|
|
$dataUji->rata_rata_imunisasi = $imunisasi;
|
|
$dataUji->perilaku_merokok = $merokok;
|
|
$dataUji->data_kasus = $jumlah_kasus;
|
|
$dataUji->latitude = $latitude;
|
|
$dataUji->longitude = $longitude;
|
|
$dataUji->status_prediksi = $prediksi;
|
|
$dataUji->save();
|
|
}
|
|
|
|
$dataBaru[] = [
|
|
'id' => $dataUji->id,
|
|
'kabupaten' => $dataUji->kecamatan,
|
|
'jumlah_penduduk' => $dataUji->jumlah_penduduk,
|
|
'data_tahun' => $data_tahun,
|
|
'phbs' => $dataUji->phbs,
|
|
'pcv1' => $dataUji->imunisasi_pcv_1 ?? '-',
|
|
'pcv2' => $dataUji->imunisasi_pcv_2 ?? '-',
|
|
'imunisasi' => $dataUji->rata_rata_imunisasi,
|
|
'merokok' => $dataUji->perilaku_merokok,
|
|
'kasus_2023' => $dataUji->data_kasus,
|
|
'latitude' => $dataUji->latitude ?? '-',
|
|
'longitude' => $dataUji->longitude ?? '-',
|
|
'hipotesis_asli' => $status_asli,
|
|
'prediksi' => $dataUji->status_prediksi,
|
|
];
|
|
|
|
}
|
|
|
|
$jumlah_data_uji_baru = count($dataBaru);
|
|
$total = $tp + $tn + $fp + $fn;
|
|
$akurasi = $total > 0 ? (($tp + $tn) / $total) * 100 : 0;
|
|
$precision = ($tp + $fp) > 0 ? ($tp / ($tp + $fp)) * 100 : 0;
|
|
$recall = ($tp + $fn) > 0 ? ($tp / ($tp + $fn)) * 100 : 0;
|
|
|
|
session([
|
|
'hasil_uji' => $dataBaru,
|
|
'akurasi_uji' => round($akurasi, 2),
|
|
'precision_uji' => round($precision, 2),
|
|
'recall_uji' => round($recall, 2),
|
|
'tp_uji' => $tp,
|
|
'fp_uji' => $fp,
|
|
'tn_uji' => $tn,
|
|
'fn_uji' => $fn,
|
|
'persentase_uji' => $persentase_uji,
|
|
'persentase_latih' => $persentase_latih,
|
|
'jumlah_data_uji' => $jumlah_data_uji_total + $jumlah_data_uji_baru,
|
|
'jumlah_data_latih' => $jumlah_data_latih,
|
|
'prob_turun' => $prob_turun,
|
|
'prob_naik' => $prob_naik,
|
|
'jumlah_turun' => $jumlah_turun,
|
|
'jumlah_naik' => $jumlah_naik,
|
|
'total_data' => $total_datatest + $jumlah_data_uji_baru,
|
|
'id_data_latih' => DataLatih::pluck('id')->toArray(),
|
|
'id_data_uji' => DataUji::pluck('id')->toArray(),
|
|
|
|
]);
|
|
session()->flash('success', 'Data testing berhasil diupload dan diuji.');
|
|
$fileHash = md5_file($request->file('file_excel')->getRealPath());
|
|
|
|
if (session('last_upload_hash') === $fileHash) {
|
|
return back()->with('message', 'File sudah diuji sebelumnya. Silakan upload file lain.');
|
|
}
|
|
|
|
session(['last_upload_hash' => $fileHash]);
|
|
|
|
return view('admin.uji-data', [
|
|
'data_uji' => $dataBaru,
|
|
'persentase_latih' => $persentase_latih,
|
|
'persentase_uji' => $persentase_uji,
|
|
'jumlah_data_latih' => $jumlah_data_latih,
|
|
'jumlah_data_uji' => $jumlah_data_uji_total + $jumlah_data_uji_baru,
|
|
'jumlah_naik' => $jumlah_naik,
|
|
'jumlah_turun' => $jumlah_turun,
|
|
'prob_naik' => $prob_naik,
|
|
'prob_turun' => $prob_turun,
|
|
'atribut_numerik' => $atribut_numerik,
|
|
'akurasi' => $akurasi,
|
|
'precision' => $precision,
|
|
'recall' => $recall,
|
|
'tp' => $tp,
|
|
'tn' => $tn,
|
|
'fp' => $fp,
|
|
'fn' => $fn,
|
|
'total_data' => $total_datatest + $jumlah_data_uji_baru,
|
|
'from_excel' => true,
|
|
]);
|
|
}
|
|
|
|
private function hitungConfusionMatrix($dataUji)
|
|
{
|
|
$tp = $fp = $tn = $fn = 0;
|
|
|
|
foreach ($dataUji as $data) {
|
|
$actual = $data['hipotesis_asli'];
|
|
$pred = $data['prediksi'];
|
|
|
|
if ($actual === 'Naik' && $pred === 'Naik') $tp++;
|
|
elseif ($actual === 'Naik' && $pred === 'Turun') $fn++;
|
|
elseif ($actual === 'Turun' && $pred === 'Naik') $fp++;
|
|
elseif ($actual === 'Turun' && $pred === 'Turun') $tn++;
|
|
}
|
|
|
|
return compact('tp', 'fp', 'tn', 'fn');
|
|
}
|
|
// Fungsi untuk hitung probabilitas kelas dari data latih
|
|
public function hitungProbabilitasKelas($dataLatih)
|
|
{
|
|
$jumlah_naik = 0;
|
|
$jumlah_turun = 0;
|
|
|
|
foreach ($dataLatih as $item) {
|
|
if (!isset($item->hipotesis)) {
|
|
continue; // skip kalau property hipotesis tidak ada
|
|
}
|
|
$hip = strtolower($item->hipotesis);
|
|
if ($hip === 'naik') {
|
|
$jumlah_naik++;
|
|
} elseif ($hip === 'turun') {
|
|
$jumlah_turun++;
|
|
}
|
|
}
|
|
|
|
$total_data = count($dataLatih);
|
|
|
|
$jumlah_kelas = 2;
|
|
|
|
$prob_naik = ($jumlah_naik + 1) / ($total_data + $jumlah_kelas);
|
|
$prob_turun = ($jumlah_turun + 1) / ($total_data + $jumlah_kelas);
|
|
return [
|
|
'Naik' => $prob_naik,
|
|
'Turun' => $prob_turun,
|
|
'jumlah_naik' => $jumlah_naik,
|
|
'jumlah_turun' => $jumlah_turun,
|
|
'total_data' => $total_data
|
|
];
|
|
}
|
|
} |