Techniki uczenia maszynowego do szacowania wieku użytkowników na podstawie ulubionych stron na Facebooku


25

Mam bazę danych z mojej aplikacji na Facebooku i staram się używać uczenia maszynowego do szacowania wieku użytkowników na podstawie tego, co lubią na Facebooku.

Istnieją trzy kluczowe cechy mojej bazy danych:

  • rozkład wieku w moim zestawie szkoleniowym (łącznie 12 tys. użytkowników) jest przekrzywiony w stosunku do młodszych użytkowników (tj. mam 1157 użytkowników w wieku 27 lat i 23 użytkowników w wieku 65 lat);

  • wiele witryn ma nie więcej niż 5 polubień (odfiltrowałem strony FB z mniej niż 5 polubieniami).

  • jest o wiele więcej funkcji niż próbek.

Moje pytania brzmią zatem: jaką strategię zaproponowałbyś w celu przygotowania danych do dalszej analizy? Czy powinienem wykonać redukcję wymiarów? Którą metodę ML najlepiej zastosować w tym przypadku?

Używam głównie Pythona, więc wskazówki dotyczące Pythona byłyby bardzo mile widziane.


1
Kiedy mówisz „dużo więcej funkcji niż próbek”, zakładam, że masz na myśli, że unikalna liczba lubianych witryn to >> liczba użytkowników. Czy dotyczy to również domeny głównej witryn? tzn. czy są to adresy URL youtube.com lub cnn.com w witrynach, czy też są już powiązane z domeną? Skłaniam się ku redukcji wymiarów poprzez zwijanie adresów URL do katalogów głównych domen, a nie konkretnych stron, jeśli to możliwe.
cwharland

Dziękuję za odpowiedź. Liczba funkcji (unikalne polubione strony) wynosi 32 tys., A liczba próbek (użytkowników) wynosi 12 tys. Są to strony na Facebooku, więc nie ma potrzeby ograniczania adresów URL. Użytkownik może polubić facebook.com/cnn lub nie. Jednak podoba mi się pomysł oszacowania wieku użytkowników na podstawie udostępnionych linków :)
Wojciech Walczak

Ahhh, źle odczytałem opis polubionych witryn. Dziękuję za wyjaśnienie.
cwharland

Odpowiedzi:


16

Jedną rzeczą na początek byłoby k-NN. Chodzi o to, że masz macierz użytkowników / przedmiotów, a dla niektórych użytkowników masz zgłoszony wiek. Wiek osoby w matrycy przedmiotów użytkownika może być dobrze określony przez coś w rodzaju średniego lub średniego wieku kilku najbliższych sąsiadów w obszarze przedmiotów.

Tak więc każdy użytkownik wyrażony jest jako wektor w przestrzeni przedmiotów, znajdź najbliższych sąsiadów i przypisz temu wektorowi podsumowującą statystykę wieku najbliższych sąsiadów. Możesz wybrać k dla odcięcia odległości lub bardziej realistycznie, iteracyjnie przypisując wiek do przytrzymania pociągu i wybierając k, który minimalizuje błąd w tym przydziale.

Jeśli problemem jest wymiarowość, możesz z łatwością przeprowadzić redukcję w tym układzie przez rozkład pojedynczej wartości, wybierając wektory m, które wychwytują największą wariancję w grupie.

We wszystkich przypadkach, ponieważ każda funkcja jest binarna, wydaje się, że podobieństwo kosinusowe byłoby metryką odległości.

Muszę trochę więcej pomyśleć o innych podejściach (regresja, rf itp.), Biorąc pod uwagę wąskie skupienie twojej przestrzeni funkcji (wszystkie warianty tej samej akcji, polubienie). Myślę, że podejście użytkownika / przedmiotu może być najlepsze.

Jedna uwaga, jeśli wieki dla twojego pociągu są zgłaszane przez siebie, być może będziesz musiał poprawić niektóre z nich. Ludzie na Facebooku zwykle zgłaszają wiek w dekadzie, w której się urodzili. Wykreśl histogram dat urodzenia (pochodzących z wieków) i sprawdź, czy masz skoki w dekadach, takich jak lata 70., 80., 90.


Cześć, twoja odpowiedź jest dość podobna do mojej faktycznej strategii. Użyłem sklearn.neighbors.KNeighborsRegressorz metryką cosinus na przestrzeni zredukowanej SVD (po zastosowaniu SVD średni błąd oszacowania spadł z ~ 6 lat do ~ 4). Użytkownicy w mojej bazie danych mają 18–65 lat (starsi użytkownicy zostali odfiltrowani), więc istnieje 48 możliwych klas. Zastanawiam się, czy nie jest to zbyt wiele klas dla kNN i czy powinienem traktować to jako regresję czy problem klasyfikacji (myślę, że obie mają zastosowanie).
Wojciech Walczak

Mogę powiedzieć, anegdotycznie, że używam przypadkowych lasów dla każdej klasy, aby dopasować kilka klas indywidualnie, a następnie połączyć wyniki każdego z tych modeli na różne sposoby. W takim przypadku możesz nawet pomyśleć o przypisaniu wcześniejszych prawdopodobieństw do wieku każdego użytkownika za pomocą kNN, a następnie przejrzeć każdy model oparty na klasach, użyć tych wyników, aby zaktualizować wcześniejsze prawdopodobieństwa dla każdej klasy i wybrać najbardziej prawdopodobną klasę z tych potomnych. Brzmi to trochę skomplikowanie, ale w najgorszym przypadku miałbyś dokładność kNN.
cwharland

7

Niedawno zrobiłem podobny projekt w Pythonie (przewidywanie opinii przy użyciu danych podobnych do FB) i miałem dobre wyniki w następującym podstawowym procesie:

  1. Wczytaj zestaw szkoleniowy (n = N), wykonując iterację rozdzielaną przecinkami, jak rekordy linia po linii, i użyj licznika, aby zidentyfikować najpopularniejsze strony
  2. Dla każdej z K najpopularniejszych stron (użyłem około 5000, ale możesz bawić się różnymi wartościami), użyj pandas.DataFrame.isin, aby sprawdzić, czy każda osoba w zestawie szkoleniowym lubi każdą stronę, a następnie utwórz ramkę danych N x K. wyników (nazywam to xdata_train)
  3. Utwórz serię (nazywam to ydata_train) zawierającą wszystkie zmienne wynikowe (w moim przypadku opinie, w twoim wieku) z takim samym indeksem jak xdata_train
  4. Skonfiguruj losowy klasyfikator lasu za pomocą scikit-learn, aby przewidywać ydata_train na podstawie xdata_train
  5. Skorzystaj z testów krzyżowej scikit-learn, aby dostosować parametry i poprawić dokładność (poprawianie liczby popularnych stron, liczby drzew, minimalnego rozmiaru liści itp.)
  6. Wypisuj losowy klasyfikator lasu i listę najpopularniejszych stron z piklami (lub zachowaj w pamięci, jeśli robisz wszystko naraz)
  7. Załaduj resztę danych, załaduj listę popularnych stron (w razie potrzeby) i powtórz krok 2, aby wygenerować xdata_new
  8. Załaduj losowy klasyfikator lasu (jeśli to konieczne) i użyj go do przewidywania wartości danych xdata_new
  9. Prześlij prognozowane wyniki do nowego pliku CSV lub innego wybranego formatu wyjściowego

W twoim przypadku musisz wymienić klasyfikator na regressor (więc patrz tutaj: http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestRegressor.html ), ale w przeciwnym razie ten sam proces powinien działać bez większych problemów.

Ponadto powinieneś zdawać sobie sprawę z najbardziej niesamowitej funkcji losowych lasów w Pythonie: natychmiastowa równoległość! Ci z nas, którzy zaczęli robić to w R, a następnie przeprowadzili się, są zawsze zaskoczeni, zwłaszcza gdy pracujesz na maszynie z kilkadziesiąt rdzeni (patrz tutaj: http://blog.yhathq.com/posts/comparing- random-woods-in-python-and-r.html ).

Na koniec zauważ, że byłaby to idealna aplikacja do analizy sieci, jeśli masz dane dotyczące znajomych, a także samych osób. Jeśli możesz przeanalizować wiek znajomych użytkownika, wiek użytkownika prawie na pewno będzie w ciągu roku lub dwóch mediany wśród jego znajomych, szczególnie jeśli użytkownicy są wystarczająco młodzi, aby zbudować sieci znajomych, będąc jeszcze w szkoła (ponieważ większość to koledzy z klasy). Ta prognoza prawdopodobnie przebije wszystkie modele. --- To jest podręcznikowy przykład problemu, w którym właściwe dane> właściwy model za każdym razem.

Powodzenia!


2
Ciekawym aspektem korzystania z 5000 najlepszych witryn jest fakt, że mogą nie być dobrzy w segmentacji użytkowników ze względu na wiek. Najważniejsze strony pod względem budowy to te, które odwiedzają wszyscy. Dlatego nie są zbyt dobrzy w segmentowaniu użytkowników, ponieważ wszystkie możliwe klasyfikacje (grupy wiekowe) zaangażowały się w te witryny. Jest to podobne pojęcie do części idf tf-idf. idf pomaga odfiltrować szum „każdy ma tę funkcję”. W jaki sposób najczęściej odwiedzane witryny plasują się jako cechy na twoich wykresach o zmiennym znaczeniu wraz z RF?
cwharland

1
Słuszna uwaga. Łatwym rozwiązaniem byłoby rozwarstwienie zbioru danych szkoleniowych do przedziałów J wieku (np. 13-16, 17-20, 21-24 itd.) I wybranie górnych (K / J) stron dla każdej grupy. Zapewni to znaczną reprezentację dla każdej grupy. Grupy z pewnością będą się nakładać, więc jeśli byłbyś naprawdę wybredny, możesz wziąć najlepsze (K / J) unikalne strony dla każdej grupy, ale myślę, że to może być przesada.
Therriault

5

Inną sugestią jest przetestowanie regresji logistycznej . Jako dodatkowy bonus, wagi (współczynniki) modelu dadzą Ci wyobrażenie, które witryny są pozbawione znaczenia dla wieku.

Sklearn oferuje sklearn.linear_model.LogisticRegression pakiet zaprojektowany również do obsługi rzadkich danych.

Jak wspomniano w komentarzach, w niniejszej sprawie, przy większej liczbie zmiennych wejściowych niż w próbkach, należy uregulować model (w przypadku sklearn.linear_model.LogisticRegression użyj penalty='l1'argumentu).


1
Myślę, że z LR musiałbyś stworzyć wiele modeli przedziałów wiekowych. Jak porównałby dwa modele dla różnych przedziałów wiekowych, które przewidują ten sam problem po włączeniu dla użytkownika?
cwharland

1
Zauważ, że LR kończy się niepowodzeniem, gdy jest więcej zmiennych niż obserwacji, i działa słabo, jeśli założenia modelu nie są spełnione. Aby go użyć, redukcja wymiarów musi być pierwszym krokiem.
Christopher Louden,

1
@cwharland nie powinieneś uważać zmiennej odpowiedzi za kategoryczną, ponieważ jest ona z natury ciągła i dyskrecjonalna na podstawie definicji problemu. Uznanie go za kategoryczny oznaczałoby powiedzenie algorytmowi, że przewidywanie wieku 16, kiedy rzeczywiście ma 17 lat, jest tak samo poważnym błędem, jak przewidywanie 30, kiedy rzeczywiście ma 17 lat. Rozważenie go w sposób ciągły gwarantuje, że małe błędy (16 vs 17) będą uważane za małe i duże ( 30 vs 17) są uważane za duże. W tym przypadku stosuje się regresję logistyczną do przewidywania wartości ciągłej, a nie do szacowania prawdopodobieństw późniejszych.
damienfrancois

@ChristopherLouden Masz rację, że waniliowa wersja regresji logistycznej nie jest odpowiednia dla przypadku „dużego p małego n”. Powinienem wspomnieć, że w tym przypadku ważne jest uregulowanie. Aktualizuję swoją odpowiedź. Ale LR z regulacją L1 jest rodzajem wyboru funkcji, więc uważam, że nie ma potrzeby wstępnego kroku FS.
damienfrancois

@damienfrancois: Zdecydowanie się zgadzam. Jestem trochę zaniepokojony, że w tym przypadku LR zbyt surowo będzie karać wartości pośrednie. Wydaje się, że nie ma motywacji do odwzorowania na sigmoidalną krzywą, biorąc pod uwagę, że nie jesteś szczególnie zainteresowany ekstremalnymi wartościami wieku. Być może jednak źle interpretuję użycie.
cwharland

4

Niektóre badania D. Nguyena i in. spróbuj przewidzieć wiek użytkownika Twittera na podstawie jego tweetów. Może uznasz je za przydatne. Używają regresji logistycznej i liniowej.


3

Oprócz bardziej wyrafinowanych metod można wypróbować formułę Bayesa

P (I | p1 ... pn) = P (p1 ... pn | I) P (I) / sum_i (P (p1 ... pn | i) P (i))

P (I | p1 ... pn) to prawdopodobieństwo, że użytkownik należy do grupy wiekowej I, jeśli lubił p1, .., pn

P (i) to prawdopodobieństwo, że użytkownik należy do grupy wiekowej i

P (p1 .. pn | i) to prawdopodobieństwo, że użytkownik polubił p1, .., pn, jeśli należy do grupy wiekowej i.

  • Masz już oszacowania dla P (i) z twoich danych: jest to tylko odsetek użytkowników w grupie wiekowej I.
  • Aby oszacować P (p1 ... pn | i), dla każdej grupy wiekowej szacuję prawdopodobieństwo (częstotliwość) p_ij, aby polubić stronę j. Aby p_ij było niezerowe dla wszystkich j, możesz mieszać częstotliwość dla całej populacji z niewielką wagą.

  • Następnie log P (p1 ... pn | i) = suma (log p_ij, i = p1, .., pn), suma na wszystkich stronach, które nowy użytkownik lubi. Ta formuła byłaby w przybliżeniu prawdziwa, zakładając, że użytkownik lubi strony w swojej grupie wiekowej niezależnie.

  • Teoretycznie powinieneś również dodać log (1-p_ij) do wszystkich tych, których nie lubił, ale w praktyce powinieneś odkryć, że suma log (1-p_ij) będzie nieistotnie mała, więc nie będziesz też potrzebować dużo pamięci.

Jeśli Ty lub ktoś inny spróbowałeś tego, skomentuj wynik.


2

To bardzo interesujący problem.

Napotkałem podobny, analizując zdjęcia przesyłane przez użytkowników do sieci społecznościowej. Zastosowałem następujące podejście:

  • Zamiast kojarzyć dane z grupami wiekowymi (15 lat, 27 lat, ...), stworzyłem różne grupy wiekowe: poniżej 18 lat, od 18 do 30 lat i powyżej 30 lat (wynika to ze specyficznego problemu, jakim byliśmy twarzą, ale możesz wybrać dowolne interwały). Ten podział bardzo pomaga rozwiązać problem.
  • Następnie utworzyłem hierarchiczne grupowanie (dzielące lub agregujące). Następnie wybieram te gałęzie, w których miałem użytkowników o znanym wieku (lub wieku grupowym), a następnie dla tej gałęzi przedłużyłem ten sam wiek do tej grupy.

Podejście to jest częściowo nadzorowane, dlatego polecam je, jeśli masz tylko niektóre dane.

Zauważ, że w sieci społecznościowej ludzie zwykle kłamią na temat wieku (tylko dla zabawy, a czasem dlatego, że chcą się zamaskować w sieci społecznościowej).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.