Why You Should Always Use Feature Embeddings With Structured Datasets - 리뷰

2021. 2. 28. 10:08관심있는 주제/Dimension Reduction

정형 데이터에서 뉴럴 네트워크를 훈련시킬 때, 피처 임베딩은 중요한 것 중에 하나다. 

이 기술은 NLP이외에는 좀 처럼 가르쳐 주지 않는다. 결과적으로 구조화 된 데이터 세트에서는 거의 완전히 무시됩니다.

그러나 이 단계를 스킵하는 것은 모델 정확성을 떨어트립니다. 

이로 인해 XGBoost와 같은 그래디언트 강화 방법이 구조화 된 데이터 세트 문제에 대해 항상 우월하다는 잘못된 이해가 생겼습니다.

 

향상된 신경망을 임베딩하는 것은 종종 그래디언트 부스트 방법을 능가 할뿐만 아니라 이러한 임베딩이 추출 될 때 두 모델링 방법 모두 주요 개선 사항을 볼 수 있습니다. 이 기사는 다음 질문에 답할 것입니다.

 

  • What are feature embeddings?
  • How are they used with structured data?
  • If they are so powerful, why are they not more common?
  • How are embeddings implemented?
  • How do I use these embeddings to enhance other models?

신경망은 희소한 범주형 피처에 어려움이 있습니다.

임베딩은 모델 성능을 증가하기위해서 이러한 피처들을 감소하기 위한 방법이다.

구조화된 데이터셋에 대해 이야기하기전에, 임베딩이 일반적으로 사용되는 방식을 이해하는 데 도움이됩니다.

NLP에서는 일반적으로 수천 단어의 사전을 처리합니다. 이러한 사전은 모델에 원-핫 인코딩되어 수학적으로 가능한 모든 단어에 대해 별도의 열을 갖는 것과 동일합니다. (모델에 단어가 입력되면 해당 열에는 1이 표시되고 다른 모든 열에는 0이 표시됩니다.) 이것은 엄청나게 희박한 데이터 세트로 이어집니다. 해결책은 임베딩을 만드는 것입니다.

 

임베딩은 기본적으로 훈련 텍스트를 기반으로 유사한 의미를 가진 단어를 그룹화하고 해당 위치를 반환합니다. 예를 들어 '재미'는 '유머', '춤'또는 '머신 러닝'과 같은 단어와 유사한 임베딩 값을 가질 수 있습니다.

실제로 신경망은 이러한 대표적인 기능에서 훨씬 더 잘 수행됩니다

 

Embeddings with Structured Data

구조화된 데이터셋에서는 종종 희소한 범주형 피처를 포함하고 있다. 

위에 테이블에서 볼 때, zip_code 나, store_id가 그 예다. 

그 피처들은 엄청나게 많은 cardinality를 가지고 있다. 이것이 유의미하다면 반드시 필요하지만, 그냥 일반적인 방법을 사용해야 한다면, 오히려 버리는게 모델에 더 좋을 것이다.

이러한 경우에 임베딩을 사용하면 어떨까?

 

문제는 이제 우리가 둘 이상의 피처들을 다루고 있다는 것입니다.

이 경우 두 개의 범주형 피처들(우편 번호 및 매장 ID)과 매출 합계와 같은 유의미한 피처가 있습니다.


Why Embeddings Are Ignored

대부분의 큰 회사에서는 대부분 이 기술을 사용하고 있습니다. 문제는 이러한 대기업 이외의 데이터 과학자 대부분이 이러한 방식으로 임베딩을 사용하는 것에 대해 들어 본 적이 없다는 것입니다. 왜 그런 겁니까?

이러한 방법은 구현하기가 너무 어렵다고 말하지는 않지만 일반적인 온라인 과정이나 전문 분야의 복잡성 수준보다 높습니다.

대부분의 기계 학습 실무자는 임베딩을 다른 비범 주적 기능과 병합하는 방법을 결코 배우지 않습니다.

결과적으로 우편 번호 및 상점 ID와 같은 기능은 종종 모델에서 단순히 삭제됩니다. 그러나 이것들은 중요한 기능입니다!

일부 기능 값은 평균 인코딩(mean encoding)과 같은 기술을 통해 처리할 수 있지만 이러한 개선 사항은 종종 미미합니다. 그래디언트 부스트 방법이 이러한 범주 형 기능을 더 잘 처리 할 수 ​​있기 때문에 이것은 신경망을 완전히 건너 뛰는 경향으로 이어졌습니다. 그러나 위에서 언급했듯이 임베딩은 다음 섹션에서 볼 수 있듯이 두 모델을 모두 개선 할 수 있습니다.

 


How to Implement Embeddings

이 프로세스에서 가장 어려운 부분은 TensorFlow 데이터 세트에 익숙해지는 것입니다. pandas 데이터 프레임만큼 직관적이지는 않지만 대규모 데이터 세트로 모델을 확장 할 계획이 있거나 더 복잡한 네트워크를 구축하려는 경우 배울 수있는 훌륭한 기술입니다.

 

이 예에서는 위의 가상 고객 판매 테이블을 사용합니다. 우리의 목표는 목표 달의 매출을 예측하는 것입니다.

단순함과 간결함을 위해 엔지니어링 단계를 건너 뛰고 사전 분할 판다스로 시작합니다.

더 큰 데이터 세트의 경우 데이터 프레임으로 시작하지 않을 가능성이 높지만 이는 다른 기사의 주제입니다.

여기서는 tensorflow로 진행된 예시입니다.

 

trainset = tf.data.Dataset.from_tensor_slices((
    dict(X_train),dict(y_train))).batch(32)
validationset = tf.data.Dataset.from_tensor_slices((
    dict(X_val),dict(y_val))).batch(32)

한 가지 주목할 점은 이러한 TensorFlow 데이터 세트와 이후의 변환은 pandas 데이터 프레임과 같은 방식으로 메모리에 저장되지 않는다는 것입니다.

기본적으로 데이터가 배치별로 전달되는 파이프 라인이므로 모델이 메모리에 맞지 않는 너무 큰 데이터 세트를 효율적으로 학습 할 수 있습니다. 이것이 우리가 실제 데이터가 아닌 데이터 프레임의 사전을 제공하는 이유입니다. 일반적으로 Keras API를 사용하는 것처럼 학습하는 대신 지금 배치 크기를 정의하고 있습니다.

 

zip code와 store id의 unique한 값을 생성시킵니다.

zip_codes = X_train['zip_code'].unique()
store_ids = X_train['store_id'].unique()

tensorflow feature columns를 사용하여 데이터 파이프라인를 정의한다. 

 

# numeric features being fed into the model:
feature_columns = []
feature_columns.append(
    tf.feature_column.numeric_column('gender')
feature_columns.append(
    tf.feature_column.numeric_column('age)
feature_columns.append(
    tf.feature_column.numeric_column('previous_sales')
                       
# categorical columns using the lists created above:
zip_col = tf.feature_column.categorical_column_with_vocabulary_list(
    'zip_code', zip_codes)
store_col = tf.feature_column.categorical_column_with_vocabulary_list(
    'store_id', store_ids)
                       
# create an embedding from the categorical column:
zip_emb = tf.feature_column.embedding_column(zip_col,dimension=6)
store_emb = tf.feature_column.embedding_column(store_col,dimension=4)
                       
# add the embeddings to the list of feature columns
tf.feature_columns.append(zip_emb)
tf.feature_columns.append(store_emb)
                       
# create the input layer for the model
feature_layer = tf.keras.layers.DenseFeatures(feature_columns)

임베딩 단계에서 차원 수를 지정해야했습니다. 이것은 범주 형 열을 줄이려는 기능의 수를 나타냅니다. 일반적으로 전체 카테고리 수의 4 번째 루트 (예 : 1000 개의 고유 우편 번호를 ~ 6 개의 임베딩 열로 줄임)로 피처를 줄이지 만 이는 모델에서 조정할 수있는 또 다른 매개 변수입니다.

 

model = tf.keras.models.Sequential()
model.add(feature_layer)
model.add(tf.keras.layers.Dense(units=512,activation=’relu’))
model.add(tf.keras.layers.Dropout(0.25))
# add any layers that you want here
Model.add(tf.keras.layers.Dense(units=1))
# compile and train the model
model.compile(loss='mse', optimizer='adam', metrics=['accuracy'])
model.fit(trainset, validation_data=valset, epochs=20, verbose=2)

훈련된 임베딩값을 사용할 수 있다.

zip_emb_weights = model.get_weights()[1]
store_emb_weights = model.get_weights()[0]

 

# create column names for the embeddings
zip_emb_cols = ['zip_emb1', 'zip_emb2', 'zip_emb3', …]
store_emb_cols = ['store_emb1', 'store_emb2', 'store_emb3', …]
# create a pandas data frame:
zip_emb_df = pd.DataFrame(columns=zip_emb_cols,
                          index=zip_codes,data=zip_emb_weights)
store_emb_df = pd.DataFrame(columns=store_emb_cols,
                            index=store_ids,data=store_emb_weights)
# finally, save the data frames to csv or other format
zip_emb_df.to_csv('zip_code_embeddings.csv')
store_emb_df.to_csv('store_id_embeddings.csv')

 

embedding 기술은 참 좋은 것 같다. 

근데 이것을 지금 pytorch에서 하고 싶은데, 모듈처럼 만들고 싶은게 현재 목표다! 

어떻게 해야할 지는 tensorflow를 참고해봐야겠다.

 

728x90