Я прочитал статью об утечке данных.В хакатоне есть два набора данных: данные обучения, на которых участники обучают свой алгоритм, и набор тестов, на которых измеряется производительность.Утечка данных помогает получить идеальный результат в тестовых данных, не просматривая данные поезда, используя утечку.Я прочитал статью, но мне не хватает того, как эксплуатируется утечка.Шаги, как показано в статье, следующие:
Давайте загрузим тестовые данные.
Обратите внимание, что у нас нет тренировочных данных, только тестовые данные.Более того, мы даже не будем использовать какие-либо функции тестовых объектов.Все, что нам нужно для решения этой задачи - это файл с индексами для пар, которые нам нужно сравнить.Давайте загрузим данные с тестовыми индексами.
test = pd.read_csv('../test_pairs.csv')
test.head(10)
pairId FirstId SecondId
0 0 1427 8053
1 1 17044 7681
2 2 19237 20966
3 3 8005 20765
4 4 16837 599
5 5 3657 12504
6 6 2836 7582
7 7 6136 6111
8 8 23295 9817
9 9 6621 7672
test.shape[0]
368550
Например, мы можем думать, что существует тестовый набор данных изображений, и каждому изображению присваивается уникальный идентификатор от 0 до N − 1 (N -количество изображений).В приведенном выше кадре данных FirstId и SecondId указывают на эти Id и определяют пары, которые мы должны сравнить: например, принадлежат ли оба изображения в паре одному и тому же классу или нет.Так, например, для первой строки: если изображения с Id = 1427 и Id = 8053 принадлежат одному и тому же классу, мы должны прогнозировать 1 и 0 в противном случае.Но в нашем случае нас не очень заботят изображения и то, как именно мы сравниваем изображения (при условии, что компаратор является двоичным).
print(test['FirstId'].nunique())
print(test['SecondId'].nunique())
26325
26310
Таким образом, количество пар, которые нам даны для классификации, равноочень очень маленький по сравнению с общим количеством пар.Чтобы использовать утечку, мы должны предположить (или доказать), что общее количество положительных пар мало по сравнению с общим количеством пар.Например: подумайте о наборе данных изображений с 1000 классов, N изображений на класс.Тогда, если задача состояла в том, чтобы определить, принадлежит ли пара изображений к одному и тому же классу, у нас было бы 1000 * N * (N − 1) / 2 положительных пар, тогда как общее количество пар было 1000 * N (1000N − 1) /2.
Другой пример: в конкурсе Quora задача состояла в том, чтобы классифицировать, являются ли пары предложений дубликатами друг друга или нет.Конечно, общее количество пар вопросов очень велико, а количество дубликатов (положительных пар) намного меньше.
Наконец, давайте получим долю пар класса 1. Нам просто нужно представить константуПрогноз "все единицы" и проверить возвращаемую точность.Создайте фрейм данных со столбцами pairId и Prediction, заполните его и экспортируйте в файл .csv.Затем отправьте
test['Prediction'] = np.ones(test.shape[0])
sub=pd.DataFrame(test[['pairId','Prediction']])
sub.to_csv('sub.csv',index=False)
All ones have accuracy score is 0.500000.
Итак, мы предположили, что общее количество пар намного больше, чем количество положительных пар, но это не относится к тестовому набору.Это означает, что тестовый набор строится не путем выборки случайных пар, а с использованием специального алгоритма выборки.Пары класса 1 с избыточной выборкой.Теперь подумайте, как мы можем использовать этот факт?Что здесь за утечка?Если вы получите его сейчас, вы можете попытаться получить окончательный ответ самостоятельно, иначе вы можете следовать приведенным ниже инструкциям.
Создание магической функции
В этом разделе мы создадим магическую функцию, что решит проблему почти идеально.Инструкции приведут вас к правильному решению, но, пожалуйста, попробуйте объяснить цель шагов, которые мы делаем для себя, - это очень важно.
Матрица заболеваемости
Во-первых, нам нужнопостроить матрицу заболеваемости.Вы можете думать о парах (FirstId, SecondId) как о ребрах в неориентированном графе.Матрица инцидентности - это матрица размера (maxId + 1, maxId + 1), где каждой строке (столбцу) i соответствует i-й Id.В этой матрице мы помещаем значение 1 в позицию [i, j], если и только если пара (i, j) или (j, i) присутствует в данном наборе pais (FirstId, SecondId).Все остальные элементы в матрице инцидентности являются нулями.Импортироватьмуравей!Матрицы инцидентности, как правило, очень очень редки (небольшое количество ненулевых значений).В то же время матрицы заболеваемости обычно огромны с точки зрения общего количества элементов, и их невозможно хранить в памяти в плотном формате.Но из-за их разреженности матрицы инцидентности могут быть легко представлены как разреженные матрицы.Если вы не знакомы с разреженными матрицами, см. Ссылки на wiki и scipy.sparse.Пожалуйста, используйте любой из scipy.sparseconstructors для построения матрицы инцидентности.Например, вы можете использовать этот конструктор: scipy.sparse.coo_matrix ((data, (i, j))).Мы настоятельно рекомендуем научиться использовать разные типы scipy.sparseconstuctors и матрицы, но если вы чувствуете, что не хотите их использовать, вы всегда можете построить эту матрицу с помощью простого цикла for.Сначала вам нужно будет создать матрицу, используя scipy.sparse.coo_matrix ((M, N), [dtype]) с соответствующей формой (M, N), а затем перебрать пары (FirstId, SecondId) и заполнить соответствующие элементы в матрице.с единицами.
Обратите внимание, что матрица должна быть симметричной и состоять только из нулей и единиц.Это способ проверить себя.
import networkx as nx
import numpy as np
import pandas as pd
import scipy.sparse
import matplotlib.pyplot as plt
test = pd.read_csv('../test_pairs.csv')
x = test[['FirstId','SecondId']].rename(columns={'FirstId':'col1', 'SecondId':'col2'})
y = test[['SecondId','FirstId']].rename(columns={'SecondId':'col1', 'FirstId':'col2'})
comb = pd.concat([x,y],ignore_index=True).drop_duplicates(keep='first')
comb.head()
col1 col2
0 1427 8053
1 17044 7681
2 19237 20966
3 8005 20765
4 16837 599
data = np.ones(comb.col1.shape, dtype=int)
inc_mat = scipy.sparse.coo_matrix((data,(comb.col1,comb.col2)), shape=(comb.col1.max() + 1, comb.col1.max() + 1))
rows_FirstId = inc_mat[test.FirstId.values,:]
rows_SecondId = inc_mat[test.SecondId.values,:]
f = rows_FirstId.multiply(rows_SecondId)
f = np.asarray(f.sum(axis=1))
f.shape
(368550, 1)
f = f.sum(axis=1)
f = np.squeeze(np.asarray(f))
print (f.shape)
Теперь создайте магическую функцию
Почему мы создали матрицу инцидентности?Мы можем думать о строках в этом матиксе как о представлении объектов.i-я строка является представлением для объекта с Id = i.Затем, чтобы измерить сходство между двумя объектами, мы можем измерить сходство между их представлениями.И мы увидим, что такие представления очень хороши.
Теперь выберите строки из матрицы инцидентности, которые соответствуют test.FirstId's и test.SecondId's.
Так что не забудьте преобразовать
pd.series
to
np.array
Эти строки обычно должны работать очень быстро
rows_FirstId = inc_mat[test.FirstId.values,:]
rows_SecondId = inc_mat[test.SecondId.values,:]
Наша магическая особенность - это скалярное произведение между представлениями пары объектов.Точечное произведение можно рассматривать как меру сходства - для наших неотрицательных представлений точечное произведение близко к 0, когда представления различны, и огромно, когда представления похожи.Теперь вычислите скалярное произведение между соответствующими строками в матрицах row_FirstId и row_SecondId.
От магической функции к двоичным предсказаниям
Но как нам преобразовать эту функцию в двоичные предсказания?У нас нет набора поездов для изучения модели, но у нас есть часть информации о наборе тестов: базовый показатель точности, который вы получили при отправке константы.И у нас также есть очень сильные соображения относительно процесса генерации данных, поэтому, вероятно, у нас все будет хорошо, даже без обучающего набора.Мы можем попытаться выбрать порог и установить для прогнозов значение 1, если значение функции f выше порогового значения, и 0 в противном случае.Какой порог вы бы выбрали?Как нам найти правильный порог?Давайте сначала рассмотрим эту функцию: напечатать частоты (или счетчики) каждого значения в функции f.
Например, используйте функцию
np.unique
, проверьте наличие флагов Функция для подсчета частоты каждого элемента
from scipy.stats import itemfreq
itemfreq(f)
array([[ 14, 183279],
[ 15, 852],
[ 19, 546],
[ 20, 183799],
[ 21, 6],
[ 28, 54],
[ 35, 14]])
Вы видитекак эта функция объединяет пары?Может быть, вы можете угадать хороший порог, посмотрев на значения?На самом деле, в других ситуациях это может быть не так очевидно, но в целом, чтобы выбрать порог, вам нужно только запомнить оценку вашего базового представления и использовать эту информацию.Выберите порог ниже:
pred = f > 14 # SET THRESHOLD HERE
pred
array([ True, False, True, ..., False, False, False], dtype=bool)
submission = test.loc[:,['pairId']]
submission['Prediction'] = pred.astype(int)
submission.to_csv('submission.csv', index=False)
Я хочу понять идею этого.Как мы используем утечку только из данных испытаний.