BAB V. Kesimpulan Dan Saran
5.2. Saran
Untuk meningkatkan unjuk kerja dari sistem pendeteksi wajah, dapat dilakukan dengan memberikan pelatihan lebih lanjut dengan tambahan data training yang lebih banyak dan lebih bervariasi.
Pada kasus pendeteksian wajah di dalam citra berwarna, akurasi dapat ditingkatkan dengan mengkombinasikan sistem ini dengan sistem pendeteksi warna kulit. Kecepatan deteksi juga dapat ditingkatkan dengan bantuan pendeteksi warna kulit, karena dengan demikian deteksi dengan jaringan syaraf tiruan hanya perlu dilakukan pada area yang mengandung warna kulit.
Teknologi deteksi wajah adalah salah satu bidang penelitian yang masih terus berkembang. Hasil dari deteksi wajah ini dapat dimanfaatkan lebih lanjut untuk membangun sistem pengenalan wajah (face recognition).
Mellon University, USA.
Fausett, L., 1994, Fundamentals of Neural Networks: Architectures, Algorithms, and Applications, Prentice-Hall Inc., USA.
Gibb, J., 1996, Back Propagation Family Album, ftp://ftp.mpce.mq.edu.au/comp/ techreports/960005.gibb.ps, Macquarie University, Australia.
Gonzalez, R.C., Woods, R.E., 1992, Digital Image Processing, Addison-Wesley Publishing Company, USA.
Graham, D. B., Allinson, N. M., 1998, “ Characterizing Virtual Eigensignatures for General Purpose Face Recognition” , (in) Face Recognition: From Theory to Applications, NATO ASI Series F, Computer and Systems Sciences, Vol. 163. H. Wechsler, P. J. Phillips, V. Bruce, F. Fogelman-Soulie and T. S. Huang (eds), pp 446-456.
Haykin, S., 1994, Neural Networks: A Comprehensive Foundation, Macmillan College Publishing Company, USA.
Hjelmas, E., Low, B.K., 2001, “ Face Detection: A Survey” , Computer Vision and Image Understanding. 83, pp. 236-274.
LeCun, Y., Bottou, L., Orr, G.B., Muller, K.R., 1998, “ Efficient BackProp” , Neural Networks: tricks of the trade, Springer.
Lew, M. S., Huijsmans, N., 1996, “ Information Theory and Face Detection” , Proc. of International Conference on Pattern Recognition 1996.
Osuna, E., Freund, R., Girosi, F., 1997, “ Training Support Vector Machines: An Application to Face Detection” , Proc. IEEE Conf. Computer Vision and Pattern Recognition 1997.
Press, W.H., 1992, Numerical Recipes In C: The Art Of Scientific Computing, Cambridge University Press, USA.
Riedmiller, M., 1994, “ Advanced Supervised Learning in Multi-Layer Perceptrons – From Backpropagation to Adaptive Learning Algorithms” , Int. Journal of Computer Standards and Interfaces (16) 1994.
Representations by Error Propagation” , Parallel Distributed Processing, chapter 8, MIT Press, Cambridge, MA.
Sarle, W.S., ed., 2002, Neural Network FAQ, URL: ftp://ftp.sas.com/pub/neural/ FAQ.html
Schiffmann, W., Joost, M., Werner, R., 1993, “ Comparison of Optimized Backpropagation Algorithms” , Proc. of the European Symposium on Artificial Neural Networks (ESANN) ’93, Brussels.
Schneiderman, H., 2000, “ A Statistical Approach to 3D Object Detection Applied to Faces and Cars” , CMU-RI-TR-00-06, Robotics Institute Carnegie Mellon University.
Schneiderman, H., Kanade, T., 2000, “ A Statistical Approach to 3D Object Detection Applied to Faces and Cars” , Proc. IEEE Conf. Computer Vision and Pattern Recognition vol. 1.
Sung, K.K., 1996, “ Learning and Example Selection for Object and Pattern Detection” , AITR 1572, Massachusetts Institute of Technology AI Lab. Sung, K.K., Poggio, T., 1994, “ Example-Based Learning for View-Based Human
Face Detection” , Technical Report AI Memo 1521, Massachusetts Institute of Technology AI Lab.
Turk, M., Pentland, A., 1991, “ Eigenfaces for Recognition” , J. Cognitive Neuroscience, vol. 3, no.1.
Yang, M.H., Kriegman, D., Ahuja, N., 2002, “ Detecting Faces in Images: A Survey” , IEEE Trans. Pattern Analysis and Machine Intelligence, vol. 24, no. 1.
int NN1dClass::StartTrainingQuickprop() {
/************************************************************
USE QUICKPROP ALGORITHM (reference: Fahlman, 1988) Variable name convention: w => weight, b => bias
***********************************************************/ double Ep; // Error
double mju; // learning rate
double mgf; // maximum growth factor (denoted mju in some literature) double * xi; // pointer to input training data
double t, dfa_y, ynet, del_o, dfa_h, sigma_x; double del_h; int i,j,k; mju = Form1->editLearnRate->Text.ToDouble(); mgf = Form1->editMGF->Text.ToDouble(); nMAX_EPOCH = Form1->editMaxEpoch->Text.ToInt(); errorGoal = Form1->editErrorGoal->Text.ToDouble(); dTargetValueFace = Form1->editTargetValueFace->Text.ToDouble(); max_wrongClass = Form1->edit_max_wrongClass->Text.ToIntDef(0); epoch = 0; TDateTime t1, t2; AnsiString s; s = Form1->edit_Ntrd->Text; Ntrd = s.ToIntDef(0); if (Ntrd<0) Ntrd=0; t1 = Now(); if (Ntrd==0) {ShowMessage("Ntrd = 0!"); return(0);} if (!InitWeight()) return(0); if (!InitTrainingInputDataSet()) return(0); Form1->Memo5->Clear();
// dE_dw_wlayer1 --> dE/dw utk layer 1, ... dst double * dE_dw_wlayer1 = new double[nwh]; double * dE_dw_blayer1 = new double[nbh]; double * dE_dw_wlayer2 = new double[nwo]; double dE_dw_blayer2;
// dE_dw_wlayer1_prev --> previous dE/dw utk layer 1, ... dst double * dE_dw_wlayer1_prev = new double[nwh];
double * dE_dw_blayer1_prev = new double[nbh]; double * dE_dw_wlayer2_prev = new double[nwo]; double dE_dw_blayer2_prev;
// dwo, dwh, dbo, dbh --> weight changes
// old_dwo, old_dwh, old_dbo, old_dbh --> previous weight changes double dbo, old_dbo;
double * dwo = new double[nwo]; double * old_dwo = new double[nwo]; double * dwh = new double[nwh]; double * old_dwh = new double[nwh]; double * dbh = new double[nbh]; double * old_dbh = new double[nbh]; wrt1("=====> Start training (quickprop) ...");
wrt1(AnsiString("# of weights: ") + numofWeights + "; class: " + className); // dump additional information
s = Format("Info: Ntrd:%d; MAX_EPOCH:%d; Error goal:%8.2e; VLR:%d; batch_update:%d.", ARRAYOFCONST((Ntrd, nMAX_EPOCH, errorGoal, VLR, batch_update)));
while (1) { Ep = CalcError();
if ((epoch % SHOW_STEP_EVERY)==0) { Application->ProcessMessages(); // write in log.
wrt1(Format(" %5d , %15g, %15g, %6d", ARRAYOFCONST((epoch, mju, Ep, wrongClass)))); }
if (epoch==nMAX_EPOCH) { wrt1("Max epoch reached!"); break;
}
if (Ep < errorGoal) {
wrt1("Error goal reached!"); break;
}
if (wrongClass <= max_wrongClass) { wrt1("Maximum wrong class reached!"); break; } if (blStoppedByUser) { wrt1("Aborted by user!"); break; } if (blPausedByUser) {
ShowMessage("Training paused. Press OK to continue."); blPausedByUser = false;
}
// Reset semua delta Error for (j=0; j<nwh; j++) { dE_dw_wlayer1[j] = 0; } zeros1d(dE_dw_blayer1, nwo); zeros1d(dE_dw_wlayer2, nwo); dE_dw_blayer2 = 0;
// batch update method if (batch_update==1) { // hitung update bobot for (i=0; i<Ntrd; i++) { xi = aTRD[i].trd_in; t = aTRD[i].trd_out; ynet = yout(xi);
// hitung update bobot utk output layer dfa_y = dfa(ynet);
del_o = dfa_y*(t-ynet); for (j=0; j<nwo; j++) {
dE_dw_wlayer2[j] += (del_o * hout[j]); }
dE_dw_blayer2 = dE_dw_blayer2 + (del_o);
// hitung delta Error utk update bobot utk hidden layer // hidden layer 4x4, masing2 menerima 25 input for (j=0; j<nwo1; j++) {
dfa_h = dfa(hout[j]); //% derivative of sigmoid function // hanya ada 1 output
sigma_x = (del_o * wo[j]); del_h = dfa_h*sigma_x;
dE_dw_wlayer1[st+21] += (del_h*xi[st+21]); dE_dw_wlayer1[st+22] += (del_h*xi[st+22]); dE_dw_wlayer1[st+23] += (del_h*xi[st+23]); dE_dw_wlayer1[st+24] += (del_h*xi[st+24]); dE_dw_wlayer1[st+40] += (del_h*xi[st+40]); dE_dw_wlayer1[st+41] += (del_h*xi[st+41]); dE_dw_wlayer1[st+42] += (del_h*xi[st+42]); dE_dw_wlayer1[st+43] += (del_h*xi[st+43]); dE_dw_wlayer1[st+44] += (del_h*xi[st+44]); dE_dw_wlayer1[st+60] += (del_h*xi[st+60]); dE_dw_wlayer1[st+61] += (del_h*xi[st+61]); dE_dw_wlayer1[st+62] += (del_h*xi[st+62]); dE_dw_wlayer1[st+63] += (del_h*xi[st+63]); dE_dw_wlayer1[st+64] += (del_h*xi[st+64]); dE_dw_wlayer1[st+80] += (del_h*xi[st+80]); dE_dw_wlayer1[st+81] += (del_h*xi[st+81]); dE_dw_wlayer1[st+82] += (del_h*xi[st+82]); dE_dw_wlayer1[st+83] += (del_h*xi[st+83]); dE_dw_wlayer1[st+84] += (del_h*xi[st+84]); dE_dw_blayer1[j] = dE_dw_blayer1[j] + (del_h); }
// hidden layer 5x5, masing2 menerima 16 input int n;
for (j=0; j<nwo2; j++) {
dfa_h = dfa(hout[nwo1+j]); //% derivative of sigmoid function // hanya ada 1 output
sigma_x = (del_o * wo[nwo1+j]); del_h = dfa_h*sigma_x; int st = start_25[j]; n = st + 0; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 1; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 2; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 3; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 20; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 21; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 22; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 23; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 40; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 41; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 42; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 43; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 60; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 61; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 62; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); n = st + 63; dE_dw_wlayer1[nwh1+n] += (del_h*xi[n]); dE_dw_blayer1[nwo1+j] += (del_h); } }
// update bobot & bias if (epoch==0) {
// reset nilai old_dwh, old_dbh, old_dwo, old_dbo for (int jj=0; jj<nwh; jj++)
old_dwh[jj] = 0.0;
zeros1d(old_dbh, nwo); zeros1d(old_dwo, nwo);
// update bobot & bias output layer
// mgf --> maximum growth factor (mju in some literature (Fahlman)) // in this program mju is the learning rate.
// update bobot output layer for (j=0; j<nwo; j++) {
#define dE dE_dw_wlayer2[j] #define dE_prev dE_dw_wlayer2_prev[j] #define deltaw dwo[j]
#define deltaw_prev old_dwo[j] if (deltaw_prev > 0) { deltaw = 0;
if (dE > 0) { deltaw = mju * dE; }
if (dE > (mgf/(1+mgf)) * dE_prev ) { deltaw = deltaw + (mgf * deltaw_prev); }
else {
deltaw = deltaw + ((dE * deltaw_prev) / (dE_prev - dE)); } } else if (deltaw_prev < 0) { deltaw = 0; if (dE < 0) { deltaw = mju * dE; }
if (dE < (mgf/(1+mgf)) * dE_prev ) { deltaw = deltaw + (mgf * deltaw_prev); }
else {
deltaw = deltaw + ((dE * deltaw_prev) / (dE_prev - dE));
} } else {
deltaw = mju * dE; }
wo[j] = wo[j] + dwo[j]; }
// update bias output layer #define dE dE_dw_blayer2 #define dE_prev dE_dw_blayer2_prev #define deltaw dbo
#define deltaw_prev old_dbo if (deltaw_prev > 0) { deltaw = 0; if (dE > 0) { deltaw = mju * dE; }
if (dE > (mgf/(1+mgf)) * dE_prev ) { deltaw = deltaw + (mgf * deltaw_prev); }
else {
}
if (dE < (mgf/(1+mgf)) * dE_prev ) { deltaw = deltaw + (mgf * deltaw_prev); }
else {
deltaw = deltaw + ((dE * deltaw_prev) / (dE_prev - dE));
} } else {
deltaw = mju * dE; }
bo = bo + dbo;
// update bobot & bias hidden layer // update bobot hidden layer #define dE dE_dw_wlayer1[k] #define dE_prev dE_dw_wlayer1_prev[k] #define deltaw dwh[k]
#define deltaw_prev old_dwh[k] for (k=0; k<nwh; k++) { if (deltaw_prev > 0) { deltaw = 0; if (dE > 0) { deltaw = mju * dE; }
if (dE > (mgf/(1+mgf)) * dE_prev ) { deltaw = deltaw + (mgf * deltaw_prev); }
else {
deltaw = deltaw + ((dE * deltaw_prev) / (dE_prev - dE)); } } else if (deltaw_prev < 0) { deltaw = 0; if (dE < 0) { deltaw = mju * dE; }
if (dE < (mgf/(1+mgf)) * dE_prev ) { deltaw = deltaw + (mgf * deltaw_prev); }
else {
deltaw = deltaw + ((dE * deltaw_prev) / (dE_prev - dE));
} } else {
deltaw = mju * dE; }
wh[k] = wh[k] + dwh[k]; }
// update bias hidden layer #define dE dE_dw_blayer1[k] #define dE_prev dE_dw_blayer1_prev[k] #define deltaw dbh[k]
if (dE > (mgf/(1+mgf)) * dE_prev ) { deltaw = deltaw + (mgf * deltaw_prev); }
else {
deltaw = deltaw + ((dE * deltaw_prev) / (dE_prev - dE)); } } else if (deltaw_prev < 0) { deltaw = 0; if (dE < 0) { deltaw = mju * dE; }
if (dE < (mgf/(1+mgf)) * dE_prev ) { deltaw = deltaw + (mgf * deltaw_prev); }
else {
deltaw = deltaw + ((dE * deltaw_prev) / (dE_prev - dE));
} } else {
deltaw = mju * dE; }
bh[k] = bh[k] + dbh[k]; }
} // if (batch_update==1)
// simpan delta bobot terakhir, utk dipakai pada epoch berikutnya for (int j=0; j<nwh; j++) {
old_dwh[j] = dwh[j]; }
for (int k=0; k<nwo; k++) { old_dwo[k] = dwo[k]; old_dbh[k] = dbh[k]; }
old_dbo = dbo;
// simpan semua delta Error terakhir, utk dipakai pada epoch berikutnya for (int j=0; j<nwh; j++) {
dE_dw_wlayer1_prev[j] = dE_dw_wlayer1[j]; }
for (int i=0; i<nwo; i++) {
dE_dw_blayer1_prev[i] = dE_dw_blayer1[i]; dE_dw_wlayer2_prev[i] = dE_dw_wlayer2[i]; }
dE_dw_blayer2_prev = dE_dw_blayer2; epoch = epoch+1; // go to next epoch... }
// iterasi training selesai wrt1("Finished.");
s = Format("Final state: Epoch/LR/Ep/wrongClass = %d / %g / %g / %d", ARRAYOFCONST((epoch, mju, Ep,wrongClass)));
wrt1(s); wrtNNWComments(s); t2 = Now();
s = "Started: " + t1.DateTimeString(); wrt1(s); wrtNNWComments(s);
wrongClass=0; AnsiString dflag;
wrt3("--- Final output using training dataset as input:"); wrt3("(Pattern # starts from 0)");
wrt3("Pattern # Target Output |Target-Output|"); for (int i=0; i<Ntrd; i++) {
y = yout(aTRD[i].trd_in);
diff = fabs(aTRD[i].trd_out-y); // selisih target dg actual output if (diff>=0.9) { dflag = "*****"; wrongClass++; } else dflag = " "; if (Form1->rgDumpOutput->ItemIndex==1) { if (diff>=1)
wrt3(Format("%4d %10g %20g %10.4f %s", ARRAYOFCONST((i, aTRD[i].trd_out, y, diff, dflag))));
}
if (Form1->rgDumpOutput->ItemIndex==2) {
wrt3(Format("%4d %10g %20g %10.4f %s", ARRAYOFCONST((i, aTRD[i].trd_out, y, diff, dflag))));
}
// hitung jumlah data training utk face dan non face if (aTRD[i].trd_out > 0) nDataFace++;
}
nDataNonFace = Ntrd - nDataFace;
s = Format("Training data: %6d (face: %6d; non-face:%6d).", ARRAYOFCONST((Ntrd, nDataFace, nDataNonFace))); wrt1(s); wrtNNWComments(s); s = Format("wrongClass: %4d", ARRAYOFCONST((wrongClass))); wrt3(s); wrtNNWComments(s); Screen->Cursor = crDefault; wrt1(""); delete [] dwo; delete [] old_dwo; delete [] dwh; delete [] old_dwh; delete [] dbh; delete [] old_dbh; delete [] aTRD; delete [] dE_dw_wlayer1; delete [] dE_dw_blayer1; delete [] dE_dw_wlayer2; delete [] dE_dw_wlayer1_prev; delete [] dE_dw_blayer1_prev; delete [] dE_dw_wlayer2_prev; return(1); }