2014-10-08 10 views
8

Ho appena iniziato con ML e Apache Spark, quindi ho provato la regressione lineare basata sugli esempi Spark. Non riesco a generare un modello corretto per tutti i dati tranne il campione nell'esempio e l'intercetta è sempre 0.0, indipendentemente dai dati di input.L'intercettazione del modello di regressione lineare Spark MLLib è sempre 0.0?

ho preparato un data-set di semplice allenamento in base alla funzione:

y = (2 * x1) + (3 * x2) + 4

cioè mi aspetterei l'intercetta di essere 4 e i pesi devono essere (2, 3).

Se corro il LinearRegressionWithSGD.train (...) sui dati grezzi, il modello è:

Model intercept: 0.0, weights: [NaN,NaN] 

E le previsioni sono tutte NaN:

Features: [1.0,1.0], Predicted: NaN, Actual: 9.0 
Features: [1.0,2.0], Predicted: NaN, Actual: 12.0 

ecc

Se scala prima i dati, ottengo:

Model intercept: 0.0, weights: [17.407863391511754,2.463212481736855] 

Features: [1.0,1.0], Predicted: 19.871075873248607, Actual: 9.0 
Features: [1.0,2.0], Predicted: 22.334288354985464, Actual: 12.0 
Features: [1.0,3.0], Predicted: 24.797500836722318, Actual: 15.0 

ecc

O sto facendo qualcosa di sbagliato, o non capisco quale dovrebbe essere l'output di questo modello, quindi qualcuno può suggerire dove potrei sbagliare qui?

Il mio codice è qui sotto:

// Load and parse the dummy data (y, x1, x2) for y = (2*x1) + (3*x2) + 4 
    // i.e. intercept should be 4, weights (2, 3)? 
    val data = sc.textFile("data/dummydata.txt") 

    // LabeledPoint is (label, [features]) 
    val parsedData = data.map { line => 
    val parts = line.split(',') 
    val label = parts(0).toDouble 
    val features = Array(parts(1), parts(2)) map (_.toDouble) 
    LabeledPoint(label, Vectors.dense(features)) 
    } 

    // Scale the features 
    val scaler = new StandardScaler(withMean = true, withStd = true) 
        .fit(parsedData.map(x => x.features)) 
    val scaledData = parsedData 
        .map(x => 
        LabeledPoint(x.label, 
        scaler.transform(Vectors.dense(x.features.toArray)))) 

    // Building the model: SGD = stochastic gradient descent 
    val numIterations = 1000 
    val step = 0.2 
    val model = LinearRegressionWithSGD.train(scaledData, numIterations, step) 

    println(s">>>> Model intercept: ${model.intercept}, weights: ${model.weights}")` 

    // Evaluate model on training examples 
    val valuesAndPreds = scaledData.map { point => 
    val prediction = model.predict(point.features) 
    (point.label, point.features, prediction) 
    } 
    // Print out features, actual and predicted values... 
    valuesAndPreds.take(10).foreach({case (v, f, p) => 
     println(s"Features: ${f}, Predicted: ${p}, Actual: ${v}")}) 
+0

Per PySpark, se qualcuno si chiede, questo sarebbe 'model = LinearRegressionWithSGD.train (res, intercettare = True)' –

risposta

8

Il metodo train si sta utilizzando è una scorciatoia che è impostato l'intercetta a zero e non cerca di trovare uno. Se si utilizza la classe sottostante è possibile ottenere un intercetta diversa da zero:

val model = new LinearRegressionWithSGD(step, numIterations, 1.0). 
    setIntercept(true). 
    run(scaledData) 

dovrebbe darvi un'intercettazione ora.

+0

Grazie per avermi segnalato al costruttore, Noah. Non sembra accettare alcun argomento (in Spark 1.1) ma va bene, poiché il modello sta producendo risultati piuttosto buoni con le impostazioni predefinite predefinite ora. Saluti! –

+1

@ChrisWebster sembra che il costruttore sia contrassegnato come privato, non è sicuro del perché. Stavo testando la scintilla in modo che funzionasse perfettamente. Ad ogni modo, un semplice aggiramento è quello di aggiungere una colonna di solo 1 da usare come intercettazione, poiché è quello che il codice di regressione lineare sta facendo comunque dietro le quinte. – Noah

10

@Noah: Grazie - il tuo consiglio mi ha spinto a guardarlo di nuovo, e ho trovato some example code here che ti permette di generare l'intercettazione e anche di impostare altri parametri, come il numero di iterazioni, tramite l'ottimizzatore.

Ecco il mio codice di generazione del modello rivisto, che sembra funzionare bene sul mio dati fittizi:

// Building the model: SGD = stochastic gradient descent: 
    // Need to setIntercept = true, and seems only to work with scaled data 
    val numIterations = 600 
    val stepSize = 0.1 
    val algorithm = new LinearRegressionWithSGD() 
    algorithm.setIntercept(true) 
    algorithm.optimizer 
    .setNumIterations(numIterations) 
    .setStepSize(stepSize) 

    val model = algorithm.run(scaledData) 

sembra ancora aver bisogno di dati scalati, piuttosto che i dati grezzi, come input, ma va bene per il mio scopi qui.

Problemi correlati