2013-02-22 17 views
12

Tôi đang cố gắng sử dụng bộ dữ liệu đánh giá xe từ kho lưu trữ UCI và tôi tự hỏi liệu có một cách thuận tiện để binarize các biến phân loại trong sklearn hay không. Một cách tiếp cận sẽ là sử dụng DictVectorizer của LabelBinarizer nhưng ở đây tôi nhận được k các tính năng khác nhau trong khi bạn nên có chỉ k-1 để tránh collinearization. Tôi đoán tôi có thể viết chức năng của riêng tôi và thả một cột nhưng sổ sách kế toán này là tẻ nhạt, có cách nào dễ dàng để thực hiện các phép biến đổi đó và nhận được kết quả là ma trận thưa thớt không?Làm thế nào để mã hóa một biến phân loại trong sklearn?

+0

Có lý do cụ thể nào khiến bạn thích tính năng k-1 trên k không? Có tính năng k làm cho việc giải thích các hệ số (nói theo mô hình tuyến tính) dễ dàng hơn nhiều và có thể thúc đẩy các tính năng thưa thớt. –

+1

Tôi đã cố gắng để tìm sự liên quan của hệ số và chạy vào các vấn đề collinearity http://en.wikipedia.org/wiki/Multicollinearity – tonicebrian

+0

Tôi đoán tôi không đủ vào bên thống kê của sự vật để xem lý do tại sao điều này sẽ là một vấn đề . Tôi sẽ tưởng tượng tính năng mã hóa k để cung cấp kết quả có ý nghĩa hơn nhiều về mặt tính năng liên quan so với bất kỳ phương pháp mã hóa nào khác. –

Trả lời

15

DictVectorizer là cách được khuyến nghị để tạo mã hóa một biến nóng của các biến phân loại; bạn có thể sử dụng đối số sparse để tạo một ma trận CSR thưa thớt thay vì một mảng dày đặc dày đặc. Tôi thường không quan tâm đến đa cộng tuyến và tôi đã không nhận thấy một vấn đề với các phương pháp mà tôi có xu hướng sử dụng (ví dụ: LinearSVC, SGDClassifier, phương pháp dựa trên cây). Nó không phải là một vấn đề để vá các DictVectorizer để thả một cột cho mỗi tính năng phân loại - bạn đơn giản cần phải loại bỏ một thuật ngữ từ DictVectorizer.vocabulary vào cuối phương pháp fit. Quay lại đầu trang Cung cấp Phản hồi GIẢI PHÁP (Yêu cầu Kéo luôn được chào đón!)

+5

Có lý do cụ thể nào mà bạn đề nghị DictVectorizer trên lớp OneHotEncoder không? – Dexter

+5

DictVectorizer là tổng quát hơn - Đầu vào OneHotEncoder bị giới hạn ở các cột số nguyên đại diện cho các loại. DictVectorizer cũng đề cập đến các giá trị phân loại văn bản. Mặt khác, nếu tất cả các bạn có danh mục số nguyên ở vị trí đầu tiên, OneHotEncoder có vẻ như là sự lựa chọn đơn giản nhất. –

+1

Nhưng để sử dụng DictVectorizer, tôi cần chuyển đổi mảng thành danh sách từ điển với mỗi từ điển trong danh sách tương ứng với một hàng trong mảng. Điều này có vẻ như một hack. Tại sao tôi không thể chuyển một mảng vào DictVectorizer? – Ben

16

Các phương pháp cơ bản là

import numpy as np 
import pandas as pd, os 
from sklearn.feature_extraction import DictVectorizer 

def one_hot_dataframe(data, cols, replace=False): 
    vec = DictVectorizer() 
    mkdict = lambda row: dict((col, row[col]) for col in cols) 
    vecData = pd.DataFrame(vec.fit_transform(data[cols].apply(mkdict, axis=1)).toarray()) 
    vecData.columns = vec.get_feature_names() 
    vecData.index = data.index 
    if replace is True: 
     data = data.drop(cols, axis=1) 
     data = data.join(vecData) 
    return (data, vecData, vec) 

data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 
     'year': [2000, 2001, 2002, 2001, 2002], 
     'pop': [1.5, 1.7, 3.6, 2.4, 2.9]} 

df = pd.DataFrame(data) 

df2, _, _ = one_hot_dataframe(df, ['state'], replace=True) 
print df2 

Dưới đây là cách thực hiện ở định dạng thưa thớt

import numpy as np 
import pandas as pd, os 
import scipy.sparse as sps 
import itertools 

def one_hot_column(df, cols, vocabs): 
    mats = []; df2 = df.drop(cols,axis=1) 
    mats.append(sps.lil_matrix(np.array(df2))) 
    for i,col in enumerate(cols): 
     mat = sps.lil_matrix((len(df), len(vocabs[i]))) 
     for j,val in enumerate(np.array(df[col])): 
      mat[j,vocabs[i][val]] = 1. 
     mats.append(mat) 

    res = sps.hstack(mats) 
    return res 

data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 
     'year': ['2000', '2001', '2002', '2001', '2002'], 
     'pop': [1.5, 1.7, 3.6, 2.4, 2.9]} 

df = pd.DataFrame(data) 
print df 

vocabs = [] 
vals = ['Ohio','Nevada'] 
vocabs.append(dict(itertools.izip(vals,range(len(vals))))) 
vals = ['2000','2001','2002'] 
vocabs.append(dict(itertools.izip(vals,range(len(vals))))) 

print vocabs 

print one_hot_column(df, ['state','year'], vocabs).todense() 
+2

Làm thế nào để bạn xử lý các giá trị vô hình trong dữ liệu mới với cách tiếp cận này? – marbel

31

nếu dữ liệu của bạn là một DataFrame gấu trúc, sau đó bạn có thể đơn giản gọi get_dummies. Giả sử rằng khung dữ liệu của bạn là df và bạn muốn có một biến nhị phân cho mỗi cấp độ 'khóa' biến. Bạn chỉ cần gọi:

pd.get_dummies(df['key']) 

và sau đó xóa một trong các biến giả, để tránh vấn đề đa colinearity. Tôi hy vọng điều này sẽ giúp ...

+5

Cá nhân tôi thích get_dummies của gấu trúc hơn với OneHotEncoder hoặc DictVectorizer từ sklearn. Việc sử dụng get_dummies trong Pandas thường dẫn đến thủ tục hợp lý hơn và ít mã hơn. Pandas là nhiều hơn về phân tích dữ liệu và tiền xử lý và sklearn là nhiều hơn về các quá trình 'học tập' nặng nề, theo như tôi đang quan tâm. – luanjunyi

+19

Hạn chế đối với get_dummies là nó sẽ không nhất thiết tạo ra các cột giả trên một tập dữ liệu điểm (để lại cho bạn một tấn phức tạp khi cố gắng ghi điểm một mô hình) – Chris

+1

Một cách để làm điều này trước hết là đào tạo concat và kiểm tra DataFrame, sau đó áp dụng get_dummies và cuối cùng là đào tạo và thử nghiệm DataFrame riêng biệt. Bằng cách này, dữ liệu thử nghiệm và đào tạo sẽ có mã hóa một lần nhất quán. – weidongxu

Các vấn đề liên quan