Giới thiệu
Nếu tôi hiểu bạn chính xác, bạn cần xác định người dùng mà bạn không có Mã định danh duy nhất, vì vậy bạn muốn tìm ra họ là ai bằng cách khớp Dữ liệu ngẫu nhiên. Bạn không thể lưu trữ danh tính người dùng một cách đáng tin cậy vì:
- Cookies có thể bị xóa
- Địa chỉ IP có thể thay đổi
- Trình duyệt có thể thay đổi
- Cache của trình duyệt có thể bị xóa
Java Applet hoặc Com Object sẽ là một giải pháp dễ dàng khi sử dụng hàm băm thông tin phần cứng, nhưng ngày nay mọi người nhận thức được bảo mật đến mức khó có thể khiến mọi người cài đặt các loại chương trình này trên hệ thống của họ. Điều này khiến bạn bị mắc kẹt với việc sử dụng Cookies và các công cụ tương tự khác.
Cookies và các công cụ tương tự khác
Bạn có thể xem xét việc xây dựng Hồ sơ dữ liệu, sau đó sử dụng các kiểm tra Xác suất để xác định Người dùng có thể xảy ra . Một hồ sơ hữu ích cho việc này có thể được tạo bởi một số kết hợp sau:
- Địa chỉ IP
- Địa chỉ IP thật
- Địa chỉ IP proxy (người dùng thường sử dụng cùng một proxy nhiều lần)
- Bánh quy
- Lỗi web (ít đáng tin cậy hơn vì lỗi đã được sửa nhưng vẫn hữu ích)
- Lỗi PDF
- Lỗi flash
- Lỗi Java
- Trình duyệt
- Nhấp theo dõi (nhiều người dùng truy cập cùng một loạt trang trên mỗi lần truy cập)
- Trình duyệt Finger Print - Plugin được cài đặt (mọi người thường có các bộ plugin khác nhau, hơi độc đáo)
- Hình ảnh được lưu trong bộ nhớ cache (đôi khi mọi người xóa cookie của họ nhưng để lại hình ảnh được lưu trong bộ nhớ cache)
- Sử dụng Blobs
- (Các) URL (lịch sử trình duyệt hoặc cookie có thể chứa id người dùng duy nhất trong các URL, chẳng hạn như https://stackoverflow.com/users/1226894 hoặc http://www.facebook.com/barackobama?fref=ts )
- Phát hiện phông chữ hệ thống (đây là một chữ ký khóa ít được biết đến nhưng thường là duy nhất)
- HTML5 & Javascript
- HTML5 LocalStorage
- API định vị địa lý HTML5 và mã hóa địa lý đảo ngược
- Kiến trúc, Ngôn ngữ hệ điều hành, Thời gian hệ thống, Độ phân giải màn hình, v.v.
- API thông tin mạng
- API trạng thái pin
Tất nhiên, các mục tôi liệt kê chỉ là một vài cách có thể được xác định duy nhất người dùng. Chúng còn nhiều nữa.
Với tập hợp các yếu tố Dữ liệu ngẫu nhiên này để xây dựng Hồ sơ dữ liệu từ đó, tiếp theo là gì?
Bước tiếp theo là phát triển một số Logic mờ , hay tốt hơn là Mạng nơ ron nhân tạo (sử dụng logic mờ). Trong cả hai trường hợp, ý tưởng là đào tạo hệ thống của bạn, và sau đó kết hợp đào tạo của nó với Bayesian Inference để tăng độ chính xác của kết quả của bạn.
Các NeuralMesh thư viện cho PHP cho phép bạn tạo Artificial Neural Networks. Để thực hiện suy luận Bayes, hãy kiểm tra các liên kết sau:
Tại thời điểm này, bạn có thể nghĩ:
Tại sao rất nhiều toán học và logic cho một nhiệm vụ có vẻ đơn giản?
Về cơ bản, bởi vì nó không phải là một nhiệm vụ đơn giản . Trên thực tế, những gì bạn đang cố gắng đạt được là Xác suất thuần túy . Ví dụ: được cung cấp cho những người dùng đã biết sau:
User1 = A + B + C + D + G + K
User2 = C + D + I + J + K + F
Khi bạn nhận được dữ liệu sau:
B + C + E + G + F + K
Câu hỏi mà bạn chủ yếu hỏi là:
Xác suất mà dữ liệu nhận được (B + C + E + G + F + K) thực sự là User1 hoặc User2 là bao nhiêu? Và trận đấu nào trong hai trận đấu đó có khả năng xảy ra nhất ?
Để trả lời hiệu quả câu hỏi này, bạn cần hiểu Định dạng Tần suất và Xác suất và tại sao Xác suất chung có thể là một cách tiếp cận tốt hơn. Các chi tiết có quá nhiều để vào đây (đó là lý do tại sao tôi cung cấp cho bạn các liên kết), nhưng một ví dụ điển hình là Ứng dụng Thuật sĩ Chẩn đoán Y khoa , sử dụng kết hợp các triệu chứng để xác định các bệnh có thể.
Hãy suy nghĩ một chút về chuỗi các điểm dữ liệu bao gồm Hồ sơ dữ liệu của bạn (B + C + E + G + F + K trong ví dụ trên) dưới dạng Triệu chứng và Người dùng không xác định là Bệnh . Bằng cách xác định bệnh, bạn có thể xác định thêm một phương pháp điều trị thích hợp (coi người dùng này là Người dùng1).
Rõ ràng, một bệnh mà chúng tôi đã xác định được nhiều hơn 1 Triệu chứng dễ xác định hơn. Trên thực tế, càng có nhiều triệu chứng chúng ta có thể xác định, chẩn đoán của chúng ta càng dễ dàng và chính xác hơn.
Còn lựa chọn nào nữa ko?
Tất nhiên. Là một biện pháp thay thế, bạn có thể tạo thuật toán chấm điểm đơn giản của riêng mình và dựa trên các kết quả khớp chính xác. Điều này không hiệu quả như xác suất, nhưng có thể đơn giản hơn để bạn thực hiện.
Ví dụ, xem xét biểu đồ điểm đơn giản này:
+ ------------------------- + -------- + ------------ +
| Tài sản | Cân nặng | Tầm quan trọng |
+ ------------------------- + -------- + ------------ +
| Địa chỉ IP thật | 60 | 5 |
| Địa chỉ IP proxy được sử dụng | 40 | 4 |
| Bánh quy HTTP | 80 | 8 |
| Cookies phiên | 80 | 6 |
| Bánh quy bên thứ 3 | 60 | 4 |
| Flash Cookies | 90 | 7 |
| Lỗi PDF | 20 | 1 |
| Lỗi flash | 20 | 1 |
| Lỗi Java | 20 | 1 |
| Trang thường xuyên | 40 | 1 |
| Trình duyệt Finger Print | 35 | 2 |
| Plugin đã cài đặt | 25 | 1 |
| Hình ảnh lưu trữ | 40 | 3 |
| URL | 60 | 4 |
| Phát hiện phông chữ hệ thống | 70 | 4 |
| Lưu trữ cục bộ | 90 | 8 |
| Định vị địa lý | 70 | 6 |
| AOLTR | 70 | 4 |
| API thông tin mạng | 40 | 3 |
| API trạng thái pin | 20 | 1 |
+ ------------------------- + -------- + ------------ +
Đối với mỗi mẩu thông tin mà bạn có thể thu thập theo một yêu cầu nhất định, hãy trao điểm số liên quan, sau đó sử dụng Tầm quan trọng để giải quyết xung đột khi điểm số giống nhau.
Bằng chứng của khái niệm
Đối với một bằng chứng đơn giản về khái niệm, xin vui lòng xem Perceptron . Perceptron là một Mô hình RNA thường được sử dụng trong các ứng dụng nhận dạng mẫu. Thậm chí còn có một lớp PHP cũ thực hiện nó một cách hoàn hảo, nhưng bạn có thể sẽ cần phải sửa đổi nó cho mục đích của mình.
Mặc dù là một công cụ tuyệt vời, Perceptron vẫn có thể trả về nhiều kết quả (có thể có kết quả trùng khớp), do đó, sử dụng so sánh Điểm và Sự khác biệt vẫn hữu ích để xác định điểm tốt nhất của những trận đấu đó.
Giả định
- Lưu trữ tất cả thông tin có thể có về mỗi người dùng (IP, cookie, v.v.)
- Trường hợp kết quả là một trận đấu chính xác, tăng 1 điểm
- Trong trường hợp kết quả không khớp chính xác, hãy giảm 1 điểm
Sự mong đợi
- Tạo nhãn RNA
- Tạo người dùng ngẫu nhiên mô phỏng cơ sở dữ liệu
- Tạo một người dùng không xác định
- Tạo giá trị và giá trị RNA của người dùng không xác định
- Hệ thống sẽ hợp nhất thông tin RNA và dạy Perceptron
- Sau khi đào tạo Perceptron, hệ thống sẽ có một bộ trọng số
- Bây giờ bạn có thể kiểm tra mẫu Người dùng không xác định và Perceptron sẽ tạo ra một tập kết quả.
- Lưu trữ tất cả các trận đấu tích cực
- Sắp xếp các trận đấu trước theo Điểm, sau đó theo Chênh lệch (như được mô tả ở trên)
- Xuất ra hai kết quả khớp gần nhất hoặc, nếu không tìm thấy kết quả khớp nào, xuất kết quả trống
Mã chứng minh khái niệm
$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 ";
}
Đầu ra:
Possible Match D (0.7416|0.16853),C (0.5393|0.2809)
In_r của "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
)
Nếu Debug = true, bạn sẽ có thể thấy Đầu vào (Cảm biến & Mong muốn), Trọng lượng ban đầu, Đầu ra (Cảm biến, Tổng, Mạng), Lỗi, Hiệu chỉnh và Trọng lượng cuối cùng .
+----+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+----+---------+---------+---------+---------+---------+---------+---------+---------+---------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------+
| 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 đến x20 đại diện cho các tính năng được chuyển đổi bởi mã.
// Get RNA Labels
$labels = array();
$n = 1;
foreach ( $features as $k => $v ) {
$labels[$k] = "x" . $n;
$n ++;
}
Đây là một bản demo trực tuyến
Lớp được sử dụng:
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;
}
}
Lớp Perceptron đã sửa đổi
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
Phần kết luận
Xác định người dùng không có Mã định danh duy nhất không phải là một nhiệm vụ đơn giản hoặc đơn giản. nó phụ thuộc vào việc thu thập đủ lượng Dữ liệu ngẫu nhiên mà bạn có thể thu thập từ người dùng bằng nhiều phương pháp khác nhau.
Ngay cả khi bạn chọn không sử dụng Mạng thần kinh nhân tạo, tôi khuyên bạn ít nhất nên sử dụng Ma trận xác suất đơn giản với các ưu tiên và khả năng - và tôi hy vọng mã và các ví dụ được cung cấp ở trên cung cấp cho bạn đủ để tiếp tục.