string sebagai fitur di pohon keputusan / hutan acak

64

Saya melakukan beberapa masalah pada aplikasi pohon keputusan / hutan acak. Saya mencoba menyesuaikan masalah yang memiliki angka dan juga string (seperti nama negara) sebagai fitur. Sekarang perpustakaan, scikit-learn hanya mengambil angka sebagai parameter, tapi saya ingin menyuntikkan string dan mereka membawa banyak pengetahuan.

Bagaimana saya menangani skenario seperti itu?

Saya dapat mengubah string menjadi angka dengan beberapa mekanisme seperti hashing in Python. Tetapi saya ingin mengetahui praktik terbaik tentang bagaimana string ditangani dalam masalah pohon keputusan.

user3001408
sumber
Dalam kasus sckitlearn saya telah melihat bahwa kita perlu menyandikan variabel kategori, jika tidak metode fit akan membuat kesalahan dengan mengatakan ValueError: tidak dapat mengonversi string menjadi float
Kar

Jawaban:

56

Di sebagian besar sistem pembelajaran mesin yang mapan, variabel kategori ditangani secara alami. Misalnya dalam R Anda akan menggunakan faktor, di WEKA Anda akan menggunakan variabel nominal. Ini tidak terjadi di scikit-belajar. Pohon keputusan yang diimplementasikan dalam scikit-learn hanya menggunakan fitur numerik dan fitur ini selalu ditafsirkan sebagai variabel numerik kontinu .

Dengan demikian, hanya mengganti string dengan kode hash harus dihindari, karena dianggap sebagai fitur numerik berkelanjutan setiap pengkodean yang akan Anda gunakan akan menginduksi urutan yang sama sekali tidak ada dalam data Anda.

Salah satu contoh adalah untuk kode ['merah', 'hijau', 'biru'] dengan [1,2,3], akan menghasilkan hal-hal aneh seperti 'merah' lebih rendah dari 'biru', dan jika Anda rata-rata 'merah' dan 'biru' Anda akan mendapatkan 'hijau'. Contoh lain yang lebih halus mungkin terjadi ketika Anda memberi kode ['rendah', 'sedang', 'tinggi'] dengan [1,2,3]. Dalam kasus yang terakhir mungkin terjadi memiliki urutan yang masuk akal, namun, beberapa inkonsistensi halus mungkin terjadi ketika 'sedang' di tidak di tengah 'rendah' ​​dan 'tinggi'.

Akhirnya, jawaban atas pertanyaan Anda terletak pada pengodean fitur kategorikal menjadi beberapa fitur biner . Misalnya, Anda dapat memberi kode ['merah', 'hijau', 'biru'] dengan 3 kolom, satu untuk setiap kategori, memiliki 1 ketika kategori cocok dan 0 sebaliknya. Ini disebut one-hot-encoding , binary encoding, one-of-k-encoding atau apa pun. Anda dapat memeriksa dokumentasi di sini untuk pengkodean fitur kategorikal dan ekstraksi fitur - hashing dan dicts . Tentunya one-hot-encoding akan memperluas kebutuhan ruang Anda dan kadang-kadang juga mengganggu kinerja.

rapaio
sumber
2
Ini adalah implementasi scikit yang tidak menangani variabel kategorikal dengan benar. Pengodean ulang seperti yang disarankan jawaban ini mungkin adalah yang terbaik yang dapat Anda lakukan. Pengguna yang lebih serius mungkin mencari paket alternatif.
SmallChess
3
Satu dapat menggunakan sklearn.preprocessing.LabelBinarizer untuk satu-hot-encoding dari variabel kategori.
GuSuku
@ Rapaio Saya pikir pengkodean biner tidak sama dengan satu pengkodean panas. Pengodean biner adalah ketika Anda merepresentasikan 8 kategori dengan 3 kolom, atau antara 9 hingga 16 kategori dengan 4 kolom dan seterusnya. Apakah aku salah?
Alok Nayak
paket python patsy akan berurusan dengan satu-hot encoding dari variabel kategori. patsy.readthedocs.io/en/latest/quickstart.html
zhespelt
5
Jangan gunakan LabelBinarizer, gunakan sklearn.preprocessing.OneHotEncoder . Jika Anda menggunakan panda untuk mengimpor dan melakukan pra-proses data Anda, Anda juga dapat melakukannya secara langsung menggunakan pandas.get_dummies . Menyebalkan bahwa scikit-learning tidak mendukung variabel kategori.
Ricardo Cruz
11

Anda perlu menyandikan string Anda sebagai fitur numerik yang dapat digunakan sci-kit untuk algoritme ML. Fungsionalitas ini ditangani dalam modul preprocessing (misalnya, lihat sklearn.preprocessing.LabelEncoder untuk contoh).

Kyle.
sumber
4
rapaio menjelaskan dalam jawabannya mengapa ini akan mendapatkan hasil yang salah
Keith
7

Anda biasanya harus meng-enkode variabel kategori satu-panas untuk model scikit-learning, termasuk hutan acak. Acak hutan sering akan berfungsi baik tanpa penyandian satu panas tetapi biasanya berkinerja lebih baik jika Anda melakukan penyandian satu panas. Pengodean satu-panas dan variabel "dummying" memiliki arti yang sama dalam konteks ini. Scikit-learn memiliki sklearn.preprocessing.OneHotEncoder dan Pandas memiliki pandas.get_dummies untuk mencapai ini.

Namun, ada alternatifnya. Artikel "Beyond One-Hot" di KDnuggets sangat membantu menjelaskan mengapa Anda perlu menyandikan variabel kategori dan alternatif untuk penyandian sekali panas.

Ada implementasi alternatif dari hutan acak yang tidak memerlukan pengkodean satu panas seperti R atau H2O. Implementasi dalam R mahal secara komputasi dan tidak akan berfungsi jika fitur Anda memiliki banyak kategori . H2O akan bekerja dengan sejumlah besar kategori. Continuum telah membuat H2O tersedia dalam Anaconda Python.

Ada upaya berkelanjutan untuk membuat scikit-belajar menangani fitur-fitur kategorikal secara langsung .

Artikel ini memiliki penjelasan tentang algoritma yang digunakan dalam H2O. Ini referensi makalah akademik Algoritma Pohon Keputusan Paralel Streaming dan versi yang lebih panjang dari kertas yang sama.

denson
sumber
5

Pembaruan 2018!

Anda dapat membuat ruang embedding (vektor padat) untuk variabel kategori Anda. Banyak dari Anda yang akrab dengan word2vec dan fastext, yang menanamkan kata-kata dalam ruang vektor padat yang bermakna. Gagasan yang sama di sini-- variabel kategorikal Anda akan dipetakan ke vektor dengan beberapa makna.

Dari makalah Guo / Berkhahn :

Penyisipan entitas tidak hanya mengurangi penggunaan memori dan mempercepat jaringan saraf dibandingkan dengan pengkodean satu-panas, tetapi lebih penting lagi dengan memetakan nilai-nilai serupa yang berdekatan satu sama lain dalam ruang penyisipan, ia mengungkapkan sifat intrinsik dari variabel kategori. Kami menerapkannya dengan sukses dalam kompetisi Kaggle baru-baru ini dan mampu mencapai posisi ketiga dengan fitur yang relatif sederhana.

Para penulis menemukan bahwa mewakili variabel kategori dengan cara ini meningkatkan efektivitas semua algoritma pembelajaran mesin yang diuji, termasuk hutan acak.

Contoh terbaik mungkin aplikasi teknik Pinterest untuk mengelompokkan Pin terkait:

masukkan deskripsi gambar di sini

Orang-orang di fastai telah menerapkan embeddings kategoris dan membuat posting blog yang sangat bagus dengan notebook demo pendamping .

Detail dan Penjelasan Tambahan

Net neural digunakan untuk membuat embeddings yaitu menetapkan vektor untuk setiap nilai kategorikal. Setelah Anda memiliki vektor, Anda dapat menggunakannya dalam model apa pun yang menerima nilai numerik. Setiap komponen vektor menjadi variabel input. Misalnya, jika Anda menggunakan vektor 3-D untuk menyematkan daftar warna kategori Anda, Anda mungkin mendapatkan sesuatu seperti: red = (0, 1.5, -2.3), biru = (1, 1, 0) dll. Anda akan menggunakan tiga variabel input di hutan acak Anda sesuai dengan tiga komponen Untuk benda merah, c1 = 0, c2 = 1.5, dan c3 = -2.3. Untuk benda biru, c1 = 1, c2 = 1, dan c3 = 0.

Anda sebenarnya tidak perlu menggunakan jaringan saraf untuk membuat embeddings (walaupun saya tidak merekomendasikan menghindar dari teknik ini). Anda bebas membuat embeddings sendiri dengan tangan atau cara lain, bila memungkinkan. Beberapa contoh:

  1. Peta warna ke vektor RGB.
  2. Peta lokasi ke vektor lat / long.
  3. Dalam model politik AS, petakan kota ke beberapa komponen vektor yang mewakili perataan kiri / kanan, beban pajak, dll.
Pete
sumber
OK keren tapi kecuali saya melewatkan sesuatu ini untuk jaring mulai selesai. Bagaimana cara kita membuat embedding dan kemudian memasukkan embedding itu ke dalam Forrest? Saya kira Anda harus melatih seluruh jaring dengan semua fitur dan kemudian mengambil beberapa lapisan pertama dan menggunakannya sebagai fitur input Anda ke Forrest Anda. Tidak jelas bagaimana ini akan dilakukan.
Keith
@Keith jaring saraf digunakan untuk membuat embeddings yaitu menetapkan vektor untuk setiap nilai kategorikal. Setelah Anda memiliki vektor, Anda dapat menggunakannya dalam model apa pun yang menerima nilai numerik. Setiap komponen vektor menjadi variabel input. Misalnya, jika Anda menggunakan vektor 3-D untuk menyematkan daftar warna kategori Anda, Anda mungkin mendapatkan sesuatu seperti: red = (0, 1.5, -2.3), blue = (1, 1, 0)dll. Anda akan menggunakan tiga variabel input di hutan acak Anda yang sesuai dengan tiga komponen. Untuk benda merah, c1 = 0, c2 = 1.5, dan c3 = -2.3. Untuk benda berwarna biru, c1 = 1, c2 = 1, dan c3 = 0.
Pete
Saya benar-benar mendapatkan konsep itu karena sangat sederhana. Maksud saya bagaimana hal ini dilakukan dalam implementasi? Demo notebook fast.ai yang Anda tautkan memiliki sedikit dengan RandomForestRegressor di akhir tetapi saya tidak benar-benar melihat bagaimana ini menambahkan dalam embeddings.
Keith
Saya pikir ini mungkin contoh yang baik dari kode di Keras github.com/entron/entity-embedding-rossmann
Keith
3

Anda bisa menggunakan variabel dummy dalam skenario seperti itu. Dengan panda, panda.get_dummiesAnda dapat membuat variabel dummy untuk string yang ingin Anda tempatkan di Pohon Keputusan atau Hutan Acak.

Contoh:

import pandas as pd
d = {'one' : pd.Series([1., 2., 3.,4.], index=['a', 'b', 'c','d']),'two' :pd.Series(['Paul', 'John', 'Micheal','George'], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)

df_with_dummies= pd.get_dummies(df,columns=["two"],drop_first=False)
df_with_dummies
ozn
sumber
2

Ubah menjadi angka, misalnya untuk setiap negara unik dengan menggunakan nomor unik (seperti 1,2,3 dan ...)

Anda juga tidak perlu menggunakan One-Hot Encoding (alias variabel dummy) ketika bekerja dengan hutan acak, karena pohon tidak bekerja seperti algoritma lain (seperti regresi linier / logistik) dan mereka tidak bekerja dengan jarak jauh (mereka bekerja dengan menemukan pemisahan yang baik untuk fitur Anda) jadi TIDAK PERLU untuk One-Hot Encoding

Arash Jamshidi
sumber
1
Ini sebenarnya tergantung pada algoritma tertentu yang melatih pohon. Secara khusus, scikit TIDAK mendukung variabel kategori.
chuse