pengantar
Jika saya memahami Anda dengan benar, Anda perlu mengidentifikasi pengguna yang Anda tidak memiliki Pengidentifikasi Unik, jadi Anda ingin mengetahui siapa mereka dengan mencocokkan Data Acak. Anda tidak dapat menyimpan identitas pengguna dengan andal karena:
- Cookie Dapat dihapus
- Alamat IP Dapat berubah
- Browser Dapat Berubah
- Tembolok Peramban dapat dihapus
Java Applet atau Com Object akan menjadi solusi mudah menggunakan hash informasi perangkat keras, tetapi saat ini orang-orang sangat memperhatikan keamanan sehingga akan sulit untuk membuat orang memasang program-program semacam ini pada sistem mereka. Ini membuat Anda terjebak dengan menggunakan Cookie dan alat-alat serupa lainnya.
Cookie dan alat serupa lainnya
Anda mungkin mempertimbangkan untuk membangun Profil Data, kemudian menggunakan tes Probabilitas untuk mengidentifikasi Pengguna yang Kemungkinan . Profil yang berguna untuk ini dapat dihasilkan oleh beberapa kombinasi berikut ini:
- Alamat IP
- Alamat IP asli
- Alamat IP Proksi (pengguna sering menggunakan proxy yang sama berulang kali)
- Kue
- Bug Web (kurang dapat diandalkan karena bug diperbaiki, tetapi masih bermanfaat)
- Bug PDF
- Bug Flash
- Bug Jawa
- Browser
- Klik Pelacakan (banyak pengguna mengunjungi seri halaman yang sama pada setiap kunjungan)
- Browser Sidik Jari - Plugin yang Dipasang (orang-orang sering memiliki beragam, set plugin yang agak unik)
- Gambar dalam cache (orang terkadang menghapus cookie mereka tetapi meninggalkan gambar dalam cache)
- Menggunakan Blobs
- URL (riwayat browser atau cookie dapat berisi id pengguna unik di URL, seperti https://stackoverflow.com/users/1226894 atau http://www.facebook.com/barackobama?fref=ts )
- System Fonts Detection (ini adalah tanda kunci kunci yang sedikit diketahui tetapi seringkali unik)
- HTML5 & Javascript
- HTML5 LocalStorage
- API Geolokasi HTML5 dan Geocoding Terbalik
- Arsitektur, Bahasa OS, Waktu Sistem, Resolusi Layar, dll.
- API Informasi Jaringan
- API Status Baterai
Item yang saya daftarkan, tentu saja, hanya beberapa cara yang memungkinkan pengguna dapat diidentifikasi secara unik. Masih banyak lagi.
Dengan kumpulan elemen Data Acak ini untuk membuat Profil Data, untuk apa selanjutnya?
Langkah selanjutnya adalah mengembangkan beberapa Logika Fuzzy , atau, lebih baik lagi, Jaringan Syaraf Tiruan (yang menggunakan logika fuzzy). Dalam kedua kasus tersebut, idenya adalah untuk melatih sistem Anda, dan kemudian menggabungkan pelatihannya dengan Bayesian Inference untuk meningkatkan akurasi hasil Anda.
The NeuralMesh perpustakaan untuk PHP memungkinkan Anda untuk menghasilkan Artificial Neural Networks. Untuk menerapkan Bayesian Inference, periksa tautan berikut:
Pada titik ini, Anda mungkin berpikir:
Mengapa begitu banyak Matematika dan Logika untuk tugas yang tampaknya sederhana?
Pada dasarnya, karena itu bukan tugas yang mudah . Apa yang Anda coba capai sebenarnya adalah Probabilitas Murni . Misalnya, diberikan pengguna yang dikenal berikut:
User1 = A + B + C + D + G + K
User2 = C + D + I + J + K + F
Ketika Anda menerima data berikut:
B + C + E + G + F + K
Pertanyaan yang pada dasarnya Anda tanyakan adalah:
Berapa probabilitas bahwa data yang diterima (B + C + E + G + F + K) sebenarnya adalah User1 atau User2? Dan yang mana dari dua pertandingan yang paling mungkin?
Agar dapat menjawab pertanyaan ini secara efektif, Anda perlu memahami Format Frekuensi vs Probabilitas dan mengapa Kemungkinan Gabungan menjadi pendekatan yang lebih baik. Rinciannya terlalu banyak untuk masuk ke sini (itulah sebabnya saya memberi Anda tautan), tetapi contoh yang baik adalah Aplikasi Wisaya Diagnosis Medis , yang menggunakan kombinasi gejala untuk mengidentifikasi kemungkinan penyakit.
Pikirkan sejenak serangkaian titik data yang terdiri dari Profil Data Anda (B + C + E + G + F + K dalam contoh di atas) sebagai Gejala , dan Pengguna Tidak Dikenal sebagai Penyakit . Dengan mengidentifikasi penyakit, Anda dapat lebih lanjut mengidentifikasi pengobatan yang sesuai (memperlakukan pengguna ini sebagai User1).
Jelas, suatu Penyakit yang telah kami identifikasi lebih dari 1 Gejala lebih mudah untuk diidentifikasi. Faktanya, semakin banyak gejala yang dapat kita identifikasi, diagnosis kita semakin mudah dan akurat.
Apakah ada alternatif lain?
Tentu saja. Sebagai ukuran alternatif, Anda dapat membuat algoritme penilaian sederhana Anda sendiri, dan mendasarkannya pada pencocokan tepat. Ini tidak seefisien probabilitas, tetapi mungkin lebih mudah untuk Anda terapkan.
Sebagai contoh, perhatikan grafik skor sederhana ini:
+ ------------------------- + -------- + ------------ +
| Properti | Berat | Pentingnya |
+ ------------------------- + -------- + ------------ +
| Alamat IP asli | 60 | 5 |
| Alamat IP proxy yang digunakan | 40 | 4 |
| Cookie HTTP | 80 | 8 |
| Cookie Sesi | 80 | 6 |
| Cookies Pihak Ketiga | 60 | 4 |
| Cookie Flash | 90 | 7 |
| Bug PDF | 20 | 1 |
| Bug Flash | 20 | 1 |
| Bug Jawa | 20 | 1 |
| Halaman yang Sering | 40 | 1 |
| Browser Cetak Jari | 35 | 2 |
| Plugin Terpasang | 25 | 1 |
| Gambar dalam Cached | 40 | 3 |
| URL | 60 | 4 |
| Deteksi Font Sistem | 70 | 4 |
| Penyimpanan Lokal | 90 | 8 |
| Geolokasi | 70 | 6 |
| AOLTR | 70 | 4 |
| API Informasi Jaringan | 40 | 3 |
| API Status Baterai | 20 | 1 |
+ ------------------------- + -------- + ------------ +
Untuk setiap informasi yang dapat Anda kumpulkan berdasarkan permintaan yang diberikan, berikan skor terkait, kemudian gunakan Pentingnya untuk menyelesaikan konflik ketika skor sama.
Bukti dari konsep
Untuk bukti konsep yang sederhana, silakan lihat di Perceptron . Perceptron adalah Model RNA yang umumnya digunakan dalam aplikasi pengenalan pola. Bahkan ada Kelas PHP lama yang mengimplementasikannya dengan sempurna, tetapi Anda mungkin perlu memodifikasinya untuk tujuan Anda.
Meskipun menjadi alat yang hebat, Perceptron masih dapat mengembalikan beberapa hasil (kemungkinan pertandingan), jadi menggunakan perbandingan Skor dan Perbedaan masih berguna untuk mengidentifikasi yang terbaik dari pertandingan tersebut.
Asumsi
- Simpan semua informasi yang mungkin tentang setiap pengguna (IP, cookie, dll.)
- Jika hasilnya adalah pencocokan tepat, tambah skor dengan 1
- Jika hasilnya tidak sama persis, kurangi skor sebesar 1
Harapan
- Buat label RNA
- Hasilkan pengguna acak yang meniru basis data
- Hasilkan satu pengguna Tidak Dikenal
- Hasilkan RNA dan Nilai pengguna yang tidak dikenal
- Sistem akan menggabungkan informasi RNA dan mengajarkan Perceptron
- Setelah melatih Perceptron, sistem akan memiliki seperangkat bobot
- Anda sekarang dapat menguji pola pengguna Tidak Dikenal dan Perceptron akan menghasilkan set hasil.
- Simpan semua kecocokan positif
- Sortir pertandingan terlebih dahulu dengan Skor, lalu oleh Perbedaan (seperti dijelaskan di atas)
- Keluarkan dua kecocokan terdekat, atau, jika tidak ada kecocokan yang ditemukan, hasilkan hasil kosong
Kode untuk Bukti Konsep
$features = array(
'Real IP address' => .5,
'Used proxy IP address' => .4,
'HTTP Cookies' => .9,
'Session Cookies' => .6,
'3rd Party Cookies' => .6,
'Flash Cookies' => .7,
'PDF Bug' => .2,
'Flash Bug' => .2,
'Java Bug' => .2,
'Frequent Pages' => .3,
'Browsers Finger Print' => .3,
'Installed Plugins' => .2,
'URL' => .5,
'Cached PNG' => .4,
'System Fonts Detection' => .6,
'Localstorage' => .8,
'Geolocation' => .6,
'AOLTR' => .4,
'Network Information API' => .3,
'Battery Status API' => .2
);
// Get RNA Lables
$labels = array();
$n = 1;
foreach ($features as $k => $v) {
$labels[$k] = "x" . $n;
$n ++;
}
// Create Users
$users = array();
for($i = 0, $name = "A"; $i < 5; $i ++, $name ++) {
$users[] = new Profile($name, $features);
}
// Generate Unknown User
$unknown = new Profile("Unknown", $features);
// Generate Unknown RNA
$unknownRNA = array(
0 => array("o" => 1),
1 => array("o" => - 1)
);
// Create RNA Values
foreach ($unknown->data as $item => $point) {
$unknownRNA[0][$labels[$item]] = $point;
$unknownRNA[1][$labels[$item]] = (- 1 * $point);
}
// Start Perception Class
$perceptron = new Perceptron();
// Train Results
$trainResult = $perceptron->train($unknownRNA, 1, 1);
// Find matches
foreach ($users as $name => &$profile) {
// Use shorter labels
$data = array_combine($labels, $profile->data);
if ($perceptron->testCase($data, $trainResult) == true) {
$score = $diff = 0;
// Determing the score and diffrennce
foreach ($unknown->data as $item => $found) {
if ($unknown->data[$item] === $profile->data[$item]) {
if ($profile->data[$item] > 0) {
$score += $features[$item];
} else {
$diff += $features[$item];
}
}
}
// Ser score and diff
$profile->setScore($score, $diff);
$matchs[] = $profile;
}
}
// Sort bases on score and Output
if (count($matchs) > 1) {
usort($matchs, function ($a, $b) {
// If score is the same use diffrence
if ($a->score == $b->score) {
// Lower the diffrence the better
return $a->diff == $b->diff ? 0 : ($a->diff > $b->diff ? 1 : - 1);
}
// The higher the score the better
return $a->score > $b->score ? - 1 : 1;
});
echo "<br />Possible Match ", implode(",", array_slice(array_map(function ($v) {
return sprintf(" %s (%0.4f|%0.4f) ", $v->name, $v->score,$v->diff);
}, $matchs), 0, 2));
} else {
echo "<br />No match Found ";
}
Keluaran:
Possible Match D (0.7416|0.16853),C (0.5393|0.2809)
Print_r dari "D":
echo "<pre>";
print_r($matchs[0]);
Profile Object(
[name] => D
[data] => Array (
[Real IP address] => -1
[Used proxy IP address] => -1
[HTTP Cookies] => 1
[Session Cookies] => 1
[3rd Party Cookies] => 1
[Flash Cookies] => 1
[PDF Bug] => 1
[Flash Bug] => 1
[Java Bug] => -1
[Frequent Pages] => 1
[Browsers Finger Print] => -1
[Installed Plugins] => 1
[URL] => -1
[Cached PNG] => 1
[System Fonts Detection] => 1
[Localstorage] => -1
[Geolocation] => -1
[AOLTR] => 1
[Network Information API] => -1
[Battery Status API] => -1
)
[score] => 0.74157303370787
[diff] => 0.1685393258427
[base] => 8.9
)
Jika Debug = true Anda akan dapat melihat Input (Sensor & Diinginkan), Bobot Awal, Output (Sensor, Jumlah, Jaringan), Kesalahan, Koreksi dan Bobot Akhir .
+----+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+----+---------+---------+---------+---------+---------+---------+---------+---------+---------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------+
| o | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15 | x16 | x17 | x18 | x19 | x20 | Bias | Yin | Y | deltaW1 | deltaW2 | deltaW3 | deltaW4 | deltaW5 | deltaW6 | deltaW7 | deltaW8 | deltaW9 | deltaW10 | deltaW11 | deltaW12 | deltaW13 | deltaW14 | deltaW15 | deltaW16 | deltaW17 | deltaW18 | deltaW19 | deltaW20 | W1 | W2 | W3 | W4 | W5 | W6 | W7 | W8 | W9 | W10 | W11 | W12 | W13 | W14 | W15 | W16 | W17 | W18 | W19 | W20 | deltaBias |
+----+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+----+---------+---------+---------+---------+---------+---------+---------+---------+---------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------+
| 1 | 1 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 0 | -1 | 0 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | 1 | 1 | 0 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 |
| -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | -1 | -1 | 1 | -19 | -1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 |
| -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- |
| 1 | 1 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 19 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 |
| -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | -1 | -1 | 1 | -19 | -1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 |
| -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- |
+----+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+----+---------+---------+---------+---------+---------+---------+---------+---------+---------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------+
x1 hingga x20 mewakili fitur yang dikonversi oleh kode.
// Get RNA Labels
$labels = array();
$n = 1;
foreach ( $features as $k => $v ) {
$labels[$k] = "x" . $n;
$n ++;
}
Ini demo online
Kelas yang digunakan:
class Profile {
public $name, $data = array(), $score, $diff, $base;
function __construct($name, array $importance) {
$values = array(-1, 1); // Perception values
$this->name = $name;
foreach ($importance as $item => $point) {
// Generate Random true/false for real Items
$this->data[$item] = $values[mt_rand(0, 1)];
}
$this->base = array_sum($importance);
}
public function setScore($score, $diff) {
$this->score = $score / $this->base;
$this->diff = $diff / $this->base;
}
}
Kelas Perceptron yang Dimodifikasi
class Perceptron {
private $w = array();
private $dw = array();
public $debug = false;
private function initialize($colums) {
// Initialize perceptron vars
for($i = 1; $i <= $colums; $i ++) {
// weighting vars
$this->w[$i] = 0;
$this->dw[$i] = 0;
}
}
function train($input, $alpha, $teta) {
$colums = count($input[0]) - 1;
$weightCache = array_fill(1, $colums, 0);
$checkpoints = array();
$keepTrainning = true;
// Initialize RNA vars
$this->initialize(count($input[0]) - 1);
$just_started = true;
$totalRun = 0;
$yin = 0;
// Trains RNA until it gets stable
while ($keepTrainning == true) {
// Sweeps each row of the input subject
foreach ($input as $row_counter => $row_data) {
// Finds out the number of columns the input has
$n_columns = count($row_data) - 1;
// Calculates Yin
$yin = 0;
for($i = 1; $i <= $n_columns; $i ++) {
$yin += $row_data["x" . $i] * $weightCache[$i];
}
// Calculates Real Output
$Y = ($yin <= 1) ? - 1 : 1;
// Sweeps columns ...
$checkpoints[$row_counter] = 0;
for($i = 1; $i <= $n_columns; $i ++) {
/** DELTAS **/
// Is it the first row?
if ($just_started == true) {
$this->dw[$i] = $weightCache[$i];
$just_started = false;
// Found desired output?
} elseif ($Y == $row_data["o"]) {
$this->dw[$i] = 0;
// Calculates Delta Ws
} else {
$this->dw[$i] = $row_data["x" . $i] * $row_data["o"];
}
/** WEIGHTS **/
// Calculate Weights
$this->w[$i] = $this->dw[$i] + $weightCache[$i];
$weightCache[$i] = $this->w[$i];
/** CHECK-POINT **/
$checkpoints[$row_counter] += $this->w[$i];
} // END - for
foreach ($this->w as $index => $w_item) {
$debug_w["W" . $index] = $w_item;
$debug_dw["deltaW" . $index] = $this->dw[$index];
}
// Special for script debugging
$debug_vars[] = array_merge($row_data, array(
"Bias" => 1,
"Yin" => $yin,
"Y" => $Y
), $debug_dw, $debug_w, array(
"deltaBias" => 1
));
} // END - foreach
// Special for script debugging
$empty_data_row = array();
for($i = 1; $i <= $n_columns; $i ++) {
$empty_data_row["x" . $i] = "--";
$empty_data_row["W" . $i] = "--";
$empty_data_row["deltaW" . $i] = "--";
}
$debug_vars[] = array_merge($empty_data_row, array(
"o" => "--",
"Bias" => "--",
"Yin" => "--",
"Y" => "--",
"deltaBias" => "--"
));
// Counts training times
$totalRun ++;
// Now checks if the RNA is stable already
$referer_value = end($checkpoints);
// if all rows match the desired output ...
$sum = array_sum($checkpoints);
$n_rows = count($checkpoints);
if ($totalRun > 1 && ($sum / $n_rows) == $referer_value) {
$keepTrainning = false;
}
} // END - while
// Prepares the final result
$result = array();
for($i = 1; $i <= $n_columns; $i ++) {
$result["w" . $i] = $this->w[$i];
}
$this->debug($this->print_html_table($debug_vars));
return $result;
} // END - train
function testCase($input, $results) {
// Sweeps input columns
$result = 0;
$i = 1;
foreach ($input as $column_value) {
// Calculates teste Y
$result += $results["w" . $i] * $column_value;
$i ++;
}
// Checks in each class the test fits
return ($result > 0) ? true : false;
} // END - test_class
// Returns the html code of a html table base on a hash array
function print_html_table($array) {
$html = "";
$inner_html = "";
$table_header_composed = false;
$table_header = array();
// Builds table contents
foreach ($array as $array_item) {
$inner_html .= "<tr>\n";
foreach ( $array_item as $array_col_label => $array_col ) {
$inner_html .= "<td>\n";
$inner_html .= $array_col;
$inner_html .= "</td>\n";
if ($table_header_composed == false) {
$table_header[] = $array_col_label;
}
}
$table_header_composed = true;
$inner_html .= "</tr>\n";
}
// Builds full table
$html = "<table border=1>\n";
$html .= "<tr>\n";
foreach ($table_header as $table_header_item) {
$html .= "<td>\n";
$html .= "<b>" . $table_header_item . "</b>";
$html .= "</td>\n";
}
$html .= "</tr>\n";
$html .= $inner_html . "</table>";
return $html;
} // END - print_html_table
// Debug function
function debug($message) {
if ($this->debug == true) {
echo "<b>DEBUG:</b> $message";
}
} // END - debug
} // END - class
Kesimpulan
Mengidentifikasi pengguna tanpa Pengenal Unik bukanlah tugas yang mudah atau sederhana. itu tergantung pada pengumpulan jumlah Data Acak yang cukup yang dapat Anda kumpulkan dari pengguna dengan berbagai metode.
Bahkan jika Anda memilih untuk tidak menggunakan Jaringan Syaraf Tiruan, saya sarankan setidaknya menggunakan Matriks Probabilitas Sederhana dengan prioritas dan kemungkinan - dan saya berharap kode dan contoh yang diberikan di atas memberi Anda cukup untuk melanjutkan.