Frage Verwenden von Klassifizierungsdaten in der logistischen Regression


Ich werde die Max Bounty darauf setzen, während ich mich anstrengen muss, diese Konzepte zu lernen! Ich versuche einige Rankingdaten in einer logistischen Regression zu verwenden. Ich möchte maschinelles Lernen verwenden, um einen einfachen Klassifizierer zu machen, ob eine Webseite "gut" ist oder nicht. Es ist nur eine Lernübung, also erwarte ich keine großartigen Ergebnisse. Ich hoffe nur, dass ich den "Prozess" und die Codierungstechniken lernen kann.

Ich habe meine Daten wie folgt in eine .csv-Datei geschrieben:

URL WebsiteText AlexaRank GooglePageRank

In meiner Test CSV haben wir:

URL WebsiteText AlexaRank GooglePageRank Label

Label ist eine binäre Klassifizierung, die "gut" mit 1 oder "schlecht" mit 0 angibt.

Ich habe derzeit meine LR läuft nur mit der Website Text; auf dem ich eine TF-IDF laufe.

Ich habe zwei Fragen, mit denen ich Hilfe brauche. Ich werde ein Maximum auf diese Frage geben und sie mit der besten Antwort belohnen, da dies etwas ist, was ich gerne hätte, damit ich und andere lernen können.

  • Wie kann ich meine Rankingdaten für AlexaRank normalisieren? Ich habe eine Reihe von 10.000 Webseiten, für die ich den Alexa-Rang von allen habe; sie sind jedoch nicht geordnet 1-10,000. Sie sind in der Rangliste gesamtes Internet, so während http://www.google.com kann eingestuft werden #1, http://www.notasite.com kann eingestuft werden #83904803289480. Wie mache ich Normalisieren Sie dies in Scikit lernen, um das bestmögliche zu erreichen ergibt sich aus meinen Daten?
  • Ich leite meine logistische Regression auf diese Weise; Ich bin mir fast sicher, dass ich das falsch gemacht habe. Ich versuche, die TF-IDF auf dem Website-Text zu machen, füge dann die zwei anderen relevanten Spalten hinzu und passe die Logistische Regression an. Ich würde es begrüßen, wenn jemand schnell bestätigen könnte, dass ich die drei Spalten, die ich in meinem LR verwenden möchte, richtig einnehme. Jede Rückmeldung darüber, wie ich mich verbessern kann, würde auch hier geschätzt werden.

    loadData = lambda f: np.genfromtxt(open(f,'r'), delimiter=' ')
    
    print "loading data.."
    traindata = list(np.array(p.read_table('train.tsv'))[:,2])#Reading WebsiteText column for TF-IDF.
    testdata = list(np.array(p.read_table('test.tsv'))[:,2])
    y = np.array(p.read_table('train.tsv'))[:,-1] #reading label
    
    tfv = TfidfVectorizer(min_df=3,  max_features=None, strip_accents='unicode', analyzer='word',
    
    token_pattern=r'\w{1,}', ngram_range=(1, 2), use_idf=1, smooth_idf=1,sublinear_tf=1)
    
    rd = lm.LogisticRegression(penalty='l2', dual=True, tol=0.0001, C=1, fit_intercept=True,    intercept_scaling=1.0, class_weight=None, random_state=None)
    
    X_all = traindata + testdata
    lentrain = len(traindata)
    
    print "fitting pipeline"
    tfv.fit(X_all)
    print "transforming data"
    X_all = tfv.transform(X_all)
    X = X_all[:lentrain]
    X_test = X_all[lentrain:]
    
    print "20 Fold CV Score: ", np.mean(cross_validation.cross_val_score(rd, X, y, cv=20, scoring='roc_auc'))
    
    #Add Two Integer Columns
    AlexaAndGoogleTrainData = list(np.array(p.read_table('train.tsv'))[2:,3])#Not sure if I am doing this correctly. Expecting it to contain AlexaRank and GooglePageRank columns.
    AlexaAndGoogleTestData = list(np.array(p.read_table('test.tsv'))[2:,3])
    AllAlexaAndGoogleInfo = AlexaAndGoogleTestData + AlexaAndGoogleTrainData
    
    #Add two columns to X.
    X = np.append(X, AllAlexaAndGoogleInfo, 1) #Think I have done this incorrectly.
    
    print "training on full data"
    rd.fit(X,y)
    pred = rd.predict_proba(X_test)[:,1]
    testfile = p.read_csv('test.tsv', sep="\t", na_values=['?'], index_col=1)
    pred_df = p.DataFrame(pred, index=testfile.index, columns=['label'])
    pred_df.to_csv('benchmark.csv')
        print "submission file created.."`
    

Vielen Dank für das Feedback - bitte schreiben Sie, wenn Sie weitere Informationen benötigen!


5
2018-03-01 17:25


Ursprung


Antworten:


Ich vermute sklearn.preprocessing.StandardScaler wäre das erste, was du ausprobieren willst. StandardScaler verwandelt all Ihre Funktionen in Mean-0-Std-1-Funktionen.

  • Dies beseitigt definitiv Ihr erstes Problem. AlexaRank wird garantiert um 0 herum verteilt und begrenzt. (Ja, sogar massiv AlexaRank Werte wie 83904803289480 werden in kleine Gleitkommazahlen umgewandelt). Natürlich werden die Ergebnisse nicht ganzzahlig sein 1 und 10000 aber sie werden die gleiche Reihenfolge wie die ursprünglichen Ränge beibehalten. Und in diesem Fall hilft es, das zweite Problem wie folgt zu lösen, indem man den Rang begrenzt und normalisiert.
  • Um zu verstehen, warum die Normalisierung bei LR helfen würde, lassen Sie uns die Logit-Formulierung von LR erneut betrachten. enter image description here
    In Ihrem Fall sind X1, X2, X3 drei TF-IDF-Funktionen und X4, X5 sind Alexa / Google rangbezogene Funktionen. Die lineare Form der Gleichung legt nahe, dass die Koeffizienten die Änderung des Logits von y mit darstellen eine Einheit Änderung in einer Variablen. Denken Sie darüber nach, was passiert, wenn Ihr X4 auf einen massiven Rangwert festgelegt wird 83904803289480. In diesem Fall die Alexa-Rank-Variable dominiert Ihre LR-Passform und eine kleine Veränderung des TF-IDF-Werts haben fast keine Auswirkung auf die LR-Passform. Nun könnte man meinen, dass der Koeffizient in der Lage sein sollte, sich an kleine / große Werte anzupassen, um Unterschiede zwischen diesen Merkmalen zu berücksichtigen. Nicht in diesem Fall. Es ist nicht nur die Größe der Variablen wichtig, sondern auch ihre Angebot. Alexa Rank hat definitiv eine große Bandbreite und sollte in diesem Fall definitiv deine LR-Passform dominieren. Daher denke ich, dass die Normalisierung aller Variablen mit StandardScaler zur Anpassung des Bereichs die Anpassung verbessert.

Hier ist, wie Sie skalieren können X Matrix.

sc = proprocessing.StandardScaler().fit(X)
X = sc.transform(X)

Vergessen Sie nicht, denselben Scaler zu verwenden, um ihn zu transformieren X_test.

X_test = sc.transform(X_test)

Jetzt können Sie die Anpassungsprozedur usw. verwenden

rd.fit(X, y)
re.predict_proba(X_test)

Weitere Informationen zur sklearn-Vorverarbeitung finden Sie hier: http://scikit-learn.org/stable/modules/preprocessing.html

Bearbeiten: Der Parsing- und Spaltenverschmelzungs-Teil kann leicht unter Verwendung von Pandas durchgeführt werden, d. H. Es besteht keine Notwendigkeit, die Matrizen in eine Liste umzuwandeln und sie dann anzufügen. Darüber hinaus können Pandas-Datenrahmen direkt mit ihren Spaltennamen indiziert werden.

AlexaAndGoogleTrainData = p.read_table('train.tsv', header=0)[["AlexaRank", "GooglePageRank"]]
AlexaAndGoogleTestData = p.read_table('test.tsv', header=0)[["AlexaRank", "GooglePageRank"]]
AllAlexaAndGoogleInfo = AlexaAndGoogleTestData.append(AlexaAndGoogleTrainData)

Beachten Sie, dass wir vorbeigehen header=0 Argument zu read_table, um originale Header-Namen aus der tsv-Datei zu pflegen. Beachten Sie auch, wie wir den gesamten Satz von Spalten indizieren können. Endlich können Sie Stapel diese neue Matrix mit X verwenden numpy.hstack.

X = np.hstack((X, AllAlexaAndGoogleInfo))

hstack horizontal kombiniert zwei mehrdimensionale arrayähnliche Strukturen, vorausgesetzt, ihre Längen sind gleich.


5
2018-03-01 17:53



In Bezug auf die Normalisierung der numerischen Ränge entweder scikit StandardScaler oder eine logarithmische Transformation (oder beides) sollte gut genug funktionieren.

Für den Aufbau einer funktionierenden Pipeline finde ich, dass mein geistiger Zustand von der Verwendung des Pandas - Pakets und des sklearn.pipeline Dienstprogramme. Hier ist ein einfaches Skript, das tun sollte, was Sie brauchen.

Zuerst ein paar brauchbare Klassen, die ich immer brauche. Es wäre schön, so etwas zu haben sklearn.pipeline oder sklearn.utilities.

from sklearn import base
class Columns(base.TransformerMixin, base.BaseEstimator):
    def __init__(self, columns):
        super(Columns, self).__init__()
        self.columns_ = columns
    def fit(self, *args, **kwargs):
        return self
    def transform(self, X, *args, **kwargs):
        return X[self.columns_]

class Text(base.TransformerMixin, base.BaseEstimator):
    def fit(self, *args, **kwargs):
        return self
    def transform(self, X, *args, **kwargs):
        return (X.apply("\t".join, axis=1, raw=False))

Jetzt richte die Pipeline ein. Ich habe das benutzt SGDClassifier Da die logistische Regression für hochdimensionale Daten wie die Textklassifizierung tendenziell effizienter ist, finde ich normalerweise, dass Scharnierverluste normalerweise bessere Ergebnisse liefern als logistische Regression.

from sklearn import linear_model as lin
from sklearn import  metrics
from sklearn.feature_extraction import text as txt
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.preprocessing import StandardScaler
from sklearn import preprocessing as prep
import numpy as np
from pandas.io import parsers
import pandas as pd

pipe = Pipeline([
    ('feat', FeatureUnion([
        ('txt', Pipeline([
            ('txtcols', Columns(["WebsiteText"])),
            ('totxt', Text()),
            ('vect', txt.TfidfVectorizer()),
            ])),
        ('num', Pipeline([
            ('numcols', Columns(["AlexaRank", "GooglePageRank"])),
            ('scale', prep.StandardScaler()),
            ])),
        ])),
    ('clf', lin.SGDClassifier(loss="log")),
    ])

Als nächstes trainiere das Modell:

train=parsers.read_csv("train.csv")
pipe.fit(train, train.Label)

Abschließend Auswertung der Testdaten:

test=parsers.read_csv("test.csv")
tstlbl=np.array(test.Label)

print pipe.score(test, tstlbl)

pred = pipe.predict(test)
print metrics.confusion_matrix(tstlbl, pred)
print metrics.classification_report(tstlbl, pred)
print metrics.f1_score(tstlbl, pred)

prob = pipe.decision_function(test)
print metrics.roc_auc_score(tstlbl, prob)
print metrics.average_precision_score(tstlbl, prob)

Sie werden wahrscheinlich nicht sehr gute Ergebnisse erzielen, wenn Sie die Standardeinstellungen verwenden. aber es sollte Ihnen eine Arbeitsgrundlage geben, von der aus gearbeitet werden kann. Ich kann einige Parametereinstellungen vorschlagen, die normalerweise für mich funktionieren, wenn Sie möchten.


2
2018-03-18 02:00