Однострунная кодировка требует бит больше, чем преобразование значений в переменные индикатора. Обычно процесс ML требует, чтобы вы несколько раз применяли это кодирование для проверки или тестирования наборов данных и применяли модель, которую вы создаете, к наблюдаемым в режиме реального времени данным. Вы должны сохранить отображение (преобразование), которое использовалось для построения модели. Хорошее решение будет использовать DictVectorizer
или LabelEncoder
(за ним следует get_dummies
. Вот функция, которую вы можете использовать:
def oneHotEncode2(df, le_dict = {}):
if not le_dict:
columnsToEncode = list(df.select_dtypes(include=['category','object']))
train = True;
else:
columnsToEncode = le_dict.keys()
train = False;
for feature in columnsToEncode:
if train:
le_dict[feature] = LabelEncoder()
try:
if train:
df[feature] = le_dict[feature].fit_transform(df[feature])
else:
df[feature] = le_dict[feature].transform(df[feature])
df = pd.concat([df,
pd.get_dummies(df[feature]).rename(columns=lambda x: feature + '_' + str(x))], axis=1)
df = df.drop(feature, axis=1)
except:
print('Error encoding '+feature)
#df[feature] = df[feature].convert_objects(convert_numeric='force')
df[feature] = df[feature].apply(pd.to_numeric, errors='coerce')
return (df, le_dict)
Это работает в кадре данных pandas и для каждого столбца созданный ими, и возвращает обратное отображение. Таким образом, вы бы назвали это следующим образом:
train_data, le_dict = oneHotEncode2(train_data)
Затем в тестовых данных вызов выполняется путем передачи словаря, возвращенного из обучения:
test_data, _ = oneHotEncode2(test_data, le_dict)
Эквивалентный метод заключается в использовании DictVectorizer
. Связанная с ним публикация в том же разделе содержится в моем блоге. Я упоминаю ее здесь, поскольку она дает некоторые аргументы в пользу этого подхода, просто используя get_dummies post (раскрытие: это мой собственный блог).
Я попробовал 3 компилятора: MS Visual Studio 2012, gcc481 и Intel icl 13.1. Все они предупреждают, когда вы указываете. Я обнаружил, что gcc и MS автоматически генерируют код инициализации для tmp1, даже когда они предупреждают об отсутствии инициализации. Компилятор MS генерирует нежелательный доступ к памяти: movaps xmm0,xmmword ptr [rsp]
. Gcc генерирует более эффективный xorps xmm0,xmm0
. Поэтому в случае gcc добавление tmp1=_mm_setzero_ps()
устраняет предупреждение и создает точно такой же код, как и без него. В случае MS добавление tmp1=_mm_setzero_ps()
делает код короче и, вероятно, быстрее. Только компилятор Intel достаточно умен, чтобы избежать ненужной инициализации. Ниже приведено возможное обходное решение для компиляторов MS и gcc:
__m128 tmp1 = _mm_loadh_pi(_mm_load_ps (src), (__m64*)(src + 4));
Генерация кода:
movaps xmm0,xmmword ptr [rcx]
movhps xmm0,qword ptr [rcx+10h]
Он выглядит короче, но его следует сравнивать, чтобы убедиться, что он быстрее.
09/12/2013: тестовый код для различных идей подавления предупреждений:
#include <xmmintrin.h>
#include <stdint.h>
#include <stdio.h>
//---------------------------------------------------------------------------
// original code from http://download.intel.com/design/PentiumIII/sml/24504301.pdf
__m128 func1 (float *src)
{
__m128 tmp1;
tmp1 = _mm_loadh_pi(_mm_loadl_pi(tmp1, (__m64*)(src)), (__m64*)(src+ 4));
return tmp1;
}
//---------------------------------------------------------------------------
// original code plus tmp1 initialization
__m128 func2 (float *src)
{
__m128 tmp1 = _mm_loadh_pi(_mm_loadl_pi (_mm_setzero_ps (), (__m64*)(src)), (__m64*)(src + 4));
return tmp1;
}
//---------------------------------------------------------------------------
// use redundant load to eliminate warning
__m128 func3 (float *src)
{
__m128 tmp1 = _mm_loadh_pi(_mm_load_ps (src), (__m64*)(src + 4));
return tmp1;
}
//---------------------------------------------------------------------------
static void dump (void *data)
{
float *f16 = data;
int index;
for (index = 0; index < 4; index++)
printf ("%g ", f16 [index]);
printf ("\n");
}
//---------------------------------------------------------------------------
int main (void)
{
float f [8] = {1, 2, 3, 4, 5, 6, 7, 8};
__m128 tmp;
tmp = func1 (f);
dump (&tmp);
tmp = func2 (f);
dump (&tmp);
tmp = func3 (f);
dump (&tmp);
return 0;
}
команды сборки:
gcc -O3 -Wall -Wfatal-errors sample.c -osample.exe
objdump -Mintel --disassemble sample.exe > disasm.txt
cl -Ox -Zi -W4 sample.c
dumpbin -disasm -symbols sample.exe > disasm.txt
icl -Ox -Zi sample.c
dumpbin -disasm -symbols sample.exe > disasm.txt
Это то, что _mm_undefined_ps
для (но это только на самом деле помогает коду с компилятором Intel. Другие компиляторы обычно относятся к нему аналогично _mm_setzero_ps
).
И кроме того, вы хотите загрузить movsd
два поплавка, которые нуль расширяют и ломают ложную зависимость от старого значения регистра, а не movlps
, который сливается. (Если вы не строите жесткий старый 32-разрядный процессор с SSE1, но не SSE2, как и PIII, ваш код изначально был написан для.)
Чтобы перейти к double *
и использовать _mm_load_sd
. Вы не разыгрываете это самостоятельно, только через _mm_load_sd
, поэтому я думаю, , это все еще 100-процентное строгое сглаживание. Тем не менее, это работает на современных компиляторах! Если это оказывается небезопасным, _mm_loadl_epi64
(movq
) принимает аргумент __m128i const*
(странно, потому что он загружает только младшие 64 бит, но это тип may_alias, который вы можете определенно использовать безопасно для чтения любого другого типа, например char*
.)
static inline
__m128 stride_gather(float *src) {
__m128 tmp1 = _mm_castpd_ps(_mm_load_sd((const double*)src)); // movsd
tmp1 = _mm_loadh_pi(tmp1, (const __m64*)(src+4)); // movhps
return tmp1;
}
gcc7 и позже использовать movq
вместо movsd
, что странно, но я думаю, что все в порядке. В худшем случае дополнительный цикл задержки задержки байпаса в качестве входа в movhps
для некоторых старых процессоров, но не пропускная способность.
Другие 3 основных компилятора (clang / ICC / MSVC) все компилируют этот к ожидаемому movsd
/ movhps
без ложной зависимости от старого значения xmm0. ( source + asm output в проводнике компилятора Godbolt .)