English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Введение
Хотите получить основные характеристики данных с помощью случайного леса
1, Теория
Случайный лес - это высоко гибкий метод машинного обучения с широкими перспективами применения, от маркетинга до медицинского страхования. Его можно использовать для моделирования маркетинговых симуляций, статистики источников клиентов, сохранения и流失а. Также он может использоваться для прогнозирования риска заболеваний и восприимчивости пациентов к заболеваниям.
В зависимости от способа генерации индивидуальных обучающих обучателей, текущие методы интеграции могут быть大致 разделены на две большие категории: метод последовательного генерирования, при котором индивидуальные обучающие обучатели имеют сильную зависимость друг от друга и должны генерироваться последовательно, и метод параллельного генерирования, при котором индивидуальные обучающие обучатели не имеют сильной зависимости друг от друга и могут генерироваться одновременно;
代表 первого - Boosting, второго - Bagging и "Случайный лес" (Random
Forest)
Случайный лес, основываясь на методе Bagging, который использует решения деревьев в качестве базового обучающего обучателя, а также вводит случайный выбор признаков в процессе обучения решений деревьев (то есть вводит случайный выбор признаков).
Простыми словами, случайный лес - это интеграция решений деревьев, но есть два отличия:
(2) Различия в выборе признаков: n классификационных признаков каждого决策 дерева выбираются случайным образом из всех признаков (n - это параметр, который нам нужно selbst anpassen)
Random Forest, простыми словами, например, для прогнозирования зарплаты, это строительство нескольких деревьев решений job, age, house, а затем, основываясь на различных характеристиках прогнозируемого объема (teacher, 39, suburb) в соответствующих целях каждого дерева, определять вероятность возникновения прогнозируемого объема (например, P(zarплата<5000)=0,3).
Random Forest - это инструмент, который может выполнять регрессию и классификацию. Он обладает свойствами обработки больших данных и помогает в моделировании базовых данных, которые очень важны для оценки или переменных.
Описание параметров:
Самыми важными параметрами являются n_estimators и max_features.
n_estimators: это количество деревьев в лесу. Теоретически лучше всего. Но вместе с этим растет время вычислений. Но не всегда больше лучше, лучшая производительность достигается при разумном количестве деревьев.
max_features: выбирает подмножество набора характеристик и использует его для разбиения узлов. Чем меньше количество подмножеств, тем быстрее уменьшается дисперсия, но одновременно быстрее увеличивается среднеквадратичное отклонение. Согласно лучшему практическому опыту. Если это задача регрессии:
max_features=n_features, если это классификационная проблема, то max_features=sqrt(n_features).
Чтобы получить хорошие результаты, необходимо установить max_depth=None, а также min_sample_split=1.
Кроме того, не забывайте о cross_validated (кросс-валидации), а также помните, что в random forest bootstrap=True, но в extra-trees bootstrap=False.
2、Python-реализация Random Forest
2.1Demo1
Реализация основных функций Random Forest
#Random Forest from sklearn.tree import DecisionTreeRegressor from sklearn.ensemble import RandomForestRegressor import numpy as np from sklearn.datasets import load_iris iris=load_iris() #print iris#У iris 4 свойства: ширина чашечки, длина чашечки, ширина лепестка, длина лепестка; метка - вид цветов: setosa versicolour virginica print(iris['target'].shape) rf=RandomForestRegressor()#Здесь используются параметры по умолчанию rf.fit(iris.data[:150],iris.target[:150])#Тренировка модели #Случайно выбираются два образца с различающимися прогнозами instance=iris.data[[100,109]] print(instance) rf.predict(instance[[0]]) print('instance 0 prediction;',rf.predict(instance[[0]])) print('instance 1 prediction;',rf.predict(instance[[1]])) print(iris.target[100],iris.target[109])
运行结果
(150,)
[[ 6.3 3.3 6. 2.5]
[ 7.2 3.6 6.1 2.5]]
instance 0 prediction; [ 2.]
instance 1 prediction; [ 2.]
2 2
2.2 Demo2
3种方法的比较
#random forest test from sklearn.model_selection import cross_val_score from sklearn.datasets import make_blobs from sklearn.ensemble import RandomForestClassifier from sklearn.ensemble import ExtraTreesClassifier from sklearn.tree import DecisionTreeClassifier X, y = make_blobs(n_samples=10000, n_features=10, centers=100, random_state=0) clf = DecisionTreeClassifier(max_depth=None, min_samples_split=2, random_state=0) scores = cross_val_score(clf, X, y) print(scores.mean()) clf = RandomForestClassifier(n_estimators=10, max_depth=None, min_samples_split=2, random_state=0) scores = cross_val_score(clf, X, y) print(scores.mean()) clf = ExtraTreesClassifier(n_estimators=10, max_depth=None, min_samples_split=2, random_state=0) scores = cross_val_score(clf, X, y) print(scores.mean())
Результат выполнения:
0.979408793821
0.999607843137
0.999898989899
2.3 Demo3-реализация выбора признаков
#random forest 2 from sklearn.tree import DecisionTreeRegressor from sklearn.ensemble import RandomForestRegressor import numpy as np from sklearn.datasets import load_iris iris=load_iris() from sklearn.model_selection import cross_val_score, ShuffleSplit X = iris["data"] Y = iris["target"] names = iris["feature_names"] rf = RandomForestRegressor() scores = [] for i in range(X.shape[1]): score = cross_val_score(rf, X[:, i:i+1], Y, scoring="r2", cv=ShuffleSplit(len(X), 3, .3)) scores.append((round(np.mean(score), 3), names[i])) print(sorted(scores, reverse=True))
Результат выполнения:
[(0.89300000000000002, 'ширина лепестка (см)'), (0.82099999999999995, 'длина лепестка')
(cm)'), (0.13, 'длина sepala (см)'), (-0.79100000000000004, 'ширина sepala (см)')]
2.4 demo4-случайный лес
Хотелось бы использовать следующий код для создания случайного леса решений, но встретилась проблема, что программа постоянно работает, не отвечает, и её нужно отладить.
#random forest 4 #coding:utf-8 import csv from random import seed from random import randrange from math import sqrt def loadCSV(filename):#загрузка данных, построчно сохраняется в список dataSet = [] with open(filename, 'r') as file: csvReader = csv.reader(file) for line in csvReader: dataSet.append(line) return dataSet # кроме столбца метки, все другие столбцы преобразуются в тип float def column_to_float(dataSet): featLen = len(dataSet[0]) - 1 for data in dataSet: for column in range(featLen): data[column] = float(data[column].strip()) # случайным образом разделить данные на N частей, чтобы облегчить кросс-валидацию, одна часть является тестовым набором,其余 части являются обучающими наборами def spiltDataSet(dataSet, n_folds): fold_size = int(len(dataSet) / n_folds) dataSet_copy = list(dataSet) dataSet_spilt = [] for i in range(n_folds): fold = [] while len(fold) < fold_size: # здесь不能用if, if работает только в первый раз, while выполняет цикл, пока условие не будет выполнено index = randrange(len(dataSet_copy)) fold.append(dataSet_copy.pop(index)) # pop() функция используется для удаления одного элемента из списка (по умолчанию последний элемент) и возвращает значение этого элемента. dataSet_spilt.append(fold) return dataSet_spilt # создать подмножество данных def get_subsample(dataSet, ratio): subdataSet = [] lenSubdata = round(len(dataSet) * ratio)# возвращает浮-point number while len(subdataSet) < lenSubdata: index = randrange(len(dataSet) - 1) subdataSet.append(dataSet[index]) # вывести количество элементов в subdataSet return subdataSet # разделить данные def data_spilt(dataSet, index, value): left = [] right = [] for row in dataSet: if row[index] < value: left.append(row) else: right.append(row) return left, right # вычислить стоимость разреза def spilt_loss(left, right, class_values): loss = 0.0 for class_value in class_values: left_size = len(left) if left_size != 0: # предотвращение деления на ноль prop = [row[-1] for row in left].count(class_value) / float(left_size) loss += (prop * (1.0 - prop)) right_size = len(right) if right_size != 0: prop = [row[-1] for row in right].count(class_value) / float(right_size) loss += (prop * (1.0 - prop)) return loss # выберите случайных n характеристик, среди которых выберите наилучший для разреза def get_best_spilt(dataSet, n_features): features = [] class_values = list(set(row[-1] for row in dataSet)) b_index, b_value, b_loss, b_left, b_right = 999, 999, 999, None, None while len(features) < n_features: index = randrange(len(dataSet[0]) - 1) if index not in features: features.append(index) # print 'features:',features for index in features:# найти индекс колонки, наиболее подходящий для узла (наименьшая потеря) for row in dataSet: left, right = data_spilt(dataSet, index, row[index])# по нему ветви справа и слева loss = spilt_loss(left, right, class_values) if loss < b_loss: # Поиск минимальной стоимости разреза b_index, b_value, b_loss, b_left, b_right = index, row[index], loss, left, right # print b_loss # print type(b_index) return {'index': b_index, 'value': b_value, 'left': b_left, 'right': b_right} # Определение выходного тега def decide_label(data): output = [row[-1] for row in data] return max(set(output), key=output.count) # Подразделение поддеревьев, процесс непрерывного создания узлов def sub_spilt(root, n_features, max_depth, min_size, depth): left = root['left'] # print left right = root['right'] del (root['left']) del (root['right']) # print depth if not left or not right: root['left'] = root['right'] = decide_label(left + right) # print 'testing' return if depth > max_depth: root['left'] = decide_label(left) root['right'] = decide_label(right) return if len(left) < min_size: root['left'] = decide_label(left) else: root['left'] = get_best_spilt(left, n_features) # print 'testing_left' sub_spilt(root['left'], n_features, max_depth, min_size, depth + 1) if len(right) < min_size: root['right'] = decide_label(right) else: root['right'] = get_best_spilt(right, n_features) # вывести 'testing_right' sub_spilt(root['right'], n_features, max_depth, min_size, depth + 1) # построить décisionnel arbre def build_tree(dataSet, n_features, max_depth, min_size): root = get_best_spilt(dataSet, n_features) sub_spilt(root, n_features, max_depth, min_size, 1) return root # предсказать результаты тестового набора def predict(tree, row): predictions = [] if row[tree['index']] < tree['value']: if isinstance(tree['left'], dict): return predict(tree['left'], row) else: return tree['left'] else: if isinstance(tree['right'], dict): return predict(tree['right'], row) else: return tree['right'] # predictions=set(predictions) def bagging_predict(trees, row): predictions = [predict(tree, row) for tree in trees] return max(set(predictions), key=predictions.count) # создать случайный лес def random_forest(train, test, ratio, n_feature, max_depth, min_size, n_trees): trees = [] for i in range(n_trees): train = get_subsample(train, ratio)# изрезать данные для выбора подмножества tree = build_tree(train, n_features, max_depth, min_size) # вывести 'дерево %d: '%i,tree trees.append(tree) # predict_values = [predict(trees,row) for row in test] predict_values = [bagging_predict(trees, row) for row in test] return predict_values # Calculate accuracy def accuracy(predict_values, actual): correct = 0 for i in range(len(actual)): if actual[i] == predict_values[i]: correct += 1 return correct / float(len(actual)) if __name__ == '__main__': seed(1) dataSet = loadCSV(r'G:\0研究生\tianchiCompetition\训练小样本2.csv') column_to_float(dataSet) n_folds = 5 max_depth = 15 min_size = 1 ratio = 1.0 # n_features=sqrt(len(dataSet)-1) n_features = 15 n_trees = 10 folds = spiltDataSet(dataSet, n_folds)#Firstly, split the dataset scores = [] for fold in folds: train_set = folds[ :] # It is not simple to use train_set=folds, as this is a reference. So when the value of train_set changes, the value of folds will also change. Therefore, we need to use a copy form. (L[:]) can copy sequences, D.copy() can copy dictionaries, and list can generate copies list(L) train_set.remove(fold)# Selecting the training set # print len(folds) train_set = sum(train_set, []) # Combining multiple fold lists into a single train_set list # print len(train_set) test_set = [] for row in fold: row_copy = list(row) row_copy[-1] = None test_set.append(row_copy) # for row in test_set: # print row[-1] actual = [row[-1] for row in fold] predict_values = random_forest(train_set, test_set, ratio, n_features, max_depth, min_size, n_trees) accur = accuracy(predict_values, actual) scores.append(accur) print ('Trees is %d' % n_trees) print ('scores:%s' % scores) print ('mean score:%s' % (sum(scores) / float(len(scores))))
2.5 случайное лесное классификация sonic данных
# CART на данных набора Bank Note from random import seed from random import randrange from csv import reader # Load a CSV file def load_csv(filename): file = open(filename, "r") lines = reader(file) dataset = list(lines) return dataset # Convert string column to float def str_column_to_float(dataset, column): for row in dataset: row[column] = float(row[column].strip()) # Разделите набор данных на k частей def cross_validation_split(dataset, n_folds): dataset_split = list() dataset_copy = list(dataset) fold_size = int(len(dataset) / n_folds) for i in range(n_folds): fold = list() while len(fold) < fold_size: index = randrange(len(dataset_copy)) fold.append(dataset_copy.pop(index)) dataset_split.append(fold) return dataset_split # Рассчитать процент точности def accuracy_metric(actual, predicted): correct = 0 for i in range(len(actual)): if actual[i] == predicted[i]: correct += 1 return correct / float(len(actual)) * 100.0 # Оценка алгоритма с использованием разделения на кросс-валидационные подмножества def evaluate_algorithm(dataset, algorithm, n_folds, *args): folds = cross_validation_split(dataset, n_folds) scores = list() for fold in folds: train_set = list(folds) train_set.remove(fold) train_set = sum(train_set, []) test_set = list() for row in fold: row_copy = list(row) test_set.append(row_copy) row_copy[-1] = None predicted = algorithm(train_set, test_set, *args) actual = [row[-1] for row in fold] accuracy = accuracy_metric(actual, predicted) scores.append(accuracy) возврат scores # Разделите набор данных на основе атрибута и значения атрибута def test_split(index, value, dataset): left, right = list(), list() for row in dataset: if row[index] < value: left.append(row) else: right.append(row) return left, right # Рассчитать индекс Gini для разделенного набора данных def gini_index(groups, class_values): gini = 0.0 for class_value in class_values: for group in groups: size = len(group) if size == 0: continue proportion = [row[-1] for row in group].count(class_value) / float(size) gini += (proportion * (1.0 - proportion)) return gini # Выбрать наилучший разделительный пункт для набора данных def get_split(dataset): class_values = list(set(row[-1] for row in dataset)) b_index, b_value, b_score, b_groups = 999, 999, 999, None for index in range(len(dataset[0])-1): for row in dataset: groups = test_split(index, row[index], dataset) gini = gini_index(groups, class_values) if gini < b_score: b_index, b_value, b_score, b_groups = index, row[index], gini, groups print ({'index':b_index, 'value':b_value}) return {'index':b_index, 'value':b_value, 'groups':b_groups} # создать-terminal узел значения def to_terminal(group): outcomes = [row[-1] for row in group] return max(set(outcomes), key=outcomes.count) # Create child splits for a node or make terminal def split(node, max_depth, min_size, depth): left, right = node['groups'] del(node['groups']) # check for a no split if not left or not right: node['left'] = node['right'] = to_terminal(left + right) return # check for max depth if depth >= max_depth: node['left'], node['right'] = to_terminal(left), to_terminal(right) return # process left child if len(left) <= min_size: node['left'] = to_terminal(left) else: node['left'] = get_split(left) split(node['left'], max_depth, min_size, depth+1) # process right child if len(right) <= min_size: node['right'] = to_terminal(right) else: node['right'] = get_split(right) split(node['right'], max_depth, min_size, depth+1) # Построить решающее дерево def build_tree(train, max_depth, min_size): root = get_split(train) split(root, max_depth, min_size, 1) return root # Сделать предсказание с помощью決策ового дерева def predict(node, row): if row[node['index']] < node['value']: if isinstance(node['left'], dict): return predict(node['left'], row) else: return node['left'] else: if isinstance(node['right'], dict): return predict(node['right'], row) else: return node['right'] # алгоритм классификации и регрессии дерева def decision_tree(train, test, max_depth, min_size): tree = build_tree(train, max_depth, min_size) predictions = list() for row in test: prediction = predict(tree, row) predictions.append(prediction) return(predictions) # тест CART на данных набора Bank Note seed(1) # загружать и готовить данные filename = r'G:\0pythonstudy\决策树\sonar.all-data.csv' dataset = load_csv(filename) # convert string attributes to integers for i in range(len(dataset[0])-1): str_column_to_float(dataset, i) # evaluate algorithm n_folds = 5 max_depth = 5 min_size = 10 scores = evaluate_algorithm(dataset, decision_tree, n_folds, max_depth, min_size) print('Оценки: %s' % scores) print('Средняя точность: %.3f%%' % (sum(scores)/float(len(scores))))
Результат выполнения:
{'index': 38, 'value': 0.0894}
{'index': 36, 'value': 0.8459}
{'index': 50, 'value': 0.0024}
{'index': 15, 'value': 0.0906}
{'index': 16, 'value': 0.9819}
{'index': 10, 'value': 0.0785}
{'index': 16, 'value': 0.0886}
{'index': 38, 'value': 0.0621}
{'index': 5, 'value': 0.0226}
{'index': 8, 'value': 0.0368}
{'index': 11, 'value': 0.0754}
{'index': 0, 'value': 0.0239}
{'index': 8, 'value': 0.0368}
{'index': 29, 'value': 0.1671}
{'index': 46, 'value': 0.0237}
{'index': 38, 'value': 0.0621}
{'index': 14, 'value': 0.0668}
{'index': 4, 'value': 0.0167}
{'index': 37, 'value': 0.0836}
{'index': 12, 'value': 0.0616}
{'index': 7, 'value': 0.0333}
{'index': 33, 'value': 0.8741}
{'index': 16, 'value': 0.0886}
{'index': 8, 'value': 0.0368}
{'index': 33, 'value': 0.0798}
{'index': 44, 'value': 0.0298}
Scores: [48.78048780487805, 70.73170731707317, 58.536585365853654, 51.2195121951]
2195, 39.02439024390244]
Mean Accuracy: 53.659%
请按任意键继续. . .
知识点:
1. load CSV file
from csv import reader # Load a CSV file def load_csv(filename): file = open(filename, "r") lines = reader(file) dataset = list(lines) return dataset filename = r'G:\0pythonstudy\决策树\sonar.all-data.csv' dataset=load_csv(filename) print(dataset)
2. 把数据转化成float格式
# Convert string column to float def str_column_to_float(dataset, column): for row in dataset: row[column] = float(row[column].strip()) # print(row[column]) # convert string attributes to integers for i in range(len(dataset[0])-1): str_column_to_float(dataset, i)
3. 把最后一列的分类字符串转化成0、1整数
def str_column_to_int(dataset, column): class_values = [row[column] for row in dataset]# 生成一个class label的list # print(class_values) unique = set(class_values)# set 获得list的不同元素 print(unique) lookup = dict()# 定义一个字典 # print(enumerate(unique)) for i, value in enumerate(unique): lookup[value] = i # print(lookup) for row in dataset: row[column] = lookup[row[column]] print(lookup['M'])
4. Разделите набор данных на K частей
# Разделите набор данных на k частей def cross_validation_split(dataset, n_folds): dataset_split = list()# создать пустой список dataset_copy = list(dataset) print(len(dataset_copy)) print(len(dataset)) #print(dataset_copy) fold_size = int(len(dataset) / n_folds) for i in range(n_folds): fold = list() while len(fold) < fold_size: index = randrange(len(dataset_copy)) # print(index) fold.append(dataset_copy.pop(index))# использовать .pop() для удаления элементов (эквивалентно передаче), элементы k-х обучающих наборов различаются dataset_split.append(fold) return dataset_split n_folds=5 folds = cross_validation_split(dataset, n_folds)# элементы k-х обучающих наборов различаются
5. Рассчитать точность
# Рассчитать процент точности def accuracy_metric(actual, predicted): correct = 0 for i in range(len(actual)): if actual[i] == predicted[i]: correct += 1 return correct / float(len(actual)) * 100.0# это выражение правильности двоичной классификации
6. Двухклассовая классификация каждого столбца
# Разделите набор данных на основе атрибута и значения атрибута def test_split(index, value, dataset): left, right = list(), list()# Инициализировать два пустых списка for row in dataset: if row[index] < value: left.append(row) else: right.append(row) return left, right # Возвратить два списка, каждый из которых выполняет двучастную категоризацию指定ных строк (index) по значению.
7. Использовать коэффициент Gini для получения наилучшего разделительного пункта
# Рассчитать индекс Gini для разделенного набора данных def gini_index(groups, class_values): gini = 0.0 for class_value in class_values: for group in groups: size = len(group) if size == 0: continue proportion = [row[-1] for row in group].count(class_value) / float(size) gini += (proportion * (1.0 - proportion)) return gini # Выбрать наилучший разделительный пункт для набора данных def get_split(dataset): class_values = list(set(row[-1] for row in dataset)) b_index, b_value, b_score, b_groups = 999, 999, 999, None for index in range(len(dataset[0])-1): for row in dataset: groups = test_split(index, row[index], dataset) gini = gini_index(groups, class_values) if gini < b_score: b_index, b_value, b_score, b_groups = index, row[index], gini, groups # print(groups) print ({'index':b_index, 'value':b_value,'score':gini}) return {'index':b_index, 'value':b_value, 'groups':b_groups}
This code, when calculating the gini index, applies the definition directly and is not difficult to understand. Understanding the best split point may be more difficult, here it uses two levels of iteration, one is iteration over different columns, and the other is iteration over different rows. And, in each iteration, the gini coefficient is updated.
8、Decision Tree Generation
# Create child splits for a node or make terminal def split(node, max_depth, min_size, depth): left, right = node['groups'] del(node['groups']) # check for a no split if not left or not right: node['left'] = node['right'] = to_terminal(left + right) return # check for max depth if depth >= max_depth: node['left'], node['right'] = to_terminal(left), to_terminal(right) return # process left child if len(left) <= min_size: node['left'] = to_terminal(left) else: node['left'] = get_split(left) split(node['left'], max_depth, min_size, depth+1) # process right child if len(right) <= min_size: node['right'] = to_terminal(right) else: node['right'] = get_split(right) split(node['right'], max_depth, min_size, depth+1)
Здесь используется рекурсивное программирование, постоянно генерируются левые и правые ветви.
9. Построение решающего дерева
# Построить решающее дерево def build_tree(train, max_depth, min_size): root = get_split(train) split(root, max_depth, min_size, 1) return root tree=build_tree(train_set, max_depth, min_size) print(tree)
10. Предсказание тестового множества
# Построить решающее дерево def build_tree(train, max_depth, min_size): root = get_split(train)# Получить наилучший разделительный критерий, значение индекса и группы split(root, max_depth, min_size, 1) return root # tree=build_tree(train_set, max_depth, min_size) # print(tree) # Сделать предсказание с помощью決策ового дерева def predict(node, row): print(row[node['index']]) print(node['value']) if row[node['index']] < node['value']:# Используется тестовое множество для замены наилучшего разделительного критерия, при наличии отклонений в разделе, дальнейшее сравнение производится через поисковую операцию в левых и правых ветвях. if isinstance(node['left'], dict):# Если тип данных node['left'] является словарем, выполняется операция return predict(node['left'], row) else: return node['left'] else: if isinstance(node['right'], dict): return predict(node['right'], row) else: return node['right'] tree = build_tree(train_set, max_depth, min_size) predictions = list() for row in test_set: prediction = predict(tree, row) predictions.append(prediction)
11. Оценка決策樹
# Оценка алгоритма с использованием разделения на кросс-валидационные подмножества def evaluate_algorithm(dataset, algorithm, n_folds, *args): folds = cross_validation_split(dataset, n_folds) scores = list() for fold in folds: train_set = list(folds) train_set.remove(fold) train_set = sum(train_set, []) test_set = list() for row in fold: row_copy = list(row) test_set.append(row_copy) row_copy[-1] = None predicted = algorithm(train_set, test_set, *args) actual = [row[-1] for row in fold] accuracy = accuracy_metric(actual, predicted) scores.append(accuracy) возврат scores
Это все содержимое статьи, надеюсь, это поможет вам в изучении, также希望大家多多支持呐喊教程。
Объявление: содержимое статьи взято из Интернета, авторские права принадлежат соответствующему автору, контент предоставлен пользователями Интернета, сайт не имеет права собственности, не был отредактирован вручную, и не несет ответственности за соответствующие юридические вопросы. Если вы обнаружите спорное содержимое о нарушении авторских прав, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (во время отправки письма, пожалуйста, замените # на @) для сообщения о нарушении и предоставьте соответствующие доказательства. При подтверждении, сайт немедленно удаляет спорное содержимое.