Понимание утечки данных и получение идеального результата с использованием тестовых данных - PullRequest
0 голосов
/ 31 мая 2018

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

Давайте загрузим тестовые данные.

Обратите внимание, что у нас нет тренировочных данных, только тестовые данные.Более того, мы даже не будем использовать какие-либо функции тестовых объектов.Все, что нам нужно для решения этой задачи - это файл с индексами для пар, которые нам нужно сравнить.Давайте загрузим данные с тестовыми индексами.

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)

Я хочу понять идею этого.Как мы используем утечку только из данных испытаний.

1 Ответ

0 голосов
/ 23 февраля 2019

В статье есть подсказка.Количество положительных пар должно быть 1000 * N * (N-1) / 2, а количество всех пар - 1000 * N (1000N-1) / 2.Конечно, количество всех пар намного, намного больше, если набор тестов был выбран случайным образом.

Как упоминает автор, после того, как вы оцените свое постоянное предсказание 1 с на тестовом наборе, вы можете сказать, чтовыборка не была сделана наугад.Точность, которую вы получите, составляет 50%.Если бы выборка была выполнена правильно, это значение должно было бы быть намного ниже.

Таким образом, они строят матрицу инцидентности и вычисляют точечное произведение (меру сходства) между представлениями наших идентификаторов.Затем они повторно используют информацию о точности, полученной при постоянных предсказаниях (при 50%), чтобы получить соответствующий порог (f> 14).Он будет больше 14, потому что это составляет примерно половину нашего тестового набора, который, в свою очередь, соответствует 50% точности.

"магическое" значение не должно было быть больше 14. Оно могло бы быть равно 14. Вы могли бы скорректировать это значение после некоторого изучения таблицы лидеров (пока вы захватываете половинутестовый набор).

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