Recentemente ho cercato di conoscere Apache Spark come sostituto di Scikit Learn, tuttavia mi sembra che anche in casi semplici, Scikit converge in un modello accurato molto più veloce di Spark. Per esempio ho generato 1000 punti di dati per una semplice funzione lineare (z = x + y) con il seguente script:Apache Spark è meno preciso di Scikit Learn?
from random import random
def func(in_vals):
'''result = x (+y+z+w....)'''
result = 0
for v in in_vals:
result += v
return result
if __name__ == "__main__":
entry_count = 1000
dim_count = 2
in_vals = [0]*dim_count
with open("data_yequalsx.csv", "w") as out_file:
for entry in range(entry_count):
for i in range(dim_count):
in_vals[i] = random()
out_val = func(in_vals)
out_file.write(','.join([str(x) for x in in_vals]))
out_file.write(",%s\n" % str(out_val))
Ho poi eseguito il seguente script Scikit:
import sklearn
from sklearn import linear_model
import numpy as np
data = []
target = []
with open("data_yequalsx.csv") as inFile:
for row in inFile:
vals = row.split(",")
data.append([float(x) for x in vals[:-1]])
target.append(float(vals[-1]))
test_samples= len(data)/10
train_data = [0]*(len(data) - test_samples)
train_target = [0]*(len(data) - test_samples)
test_data = [0]*(test_samples)
test_target = [0]*(test_samples)
train_index = 0
test_index = 0
for j in range(len(data)):
if j >= test_samples:
train_data[train_index] = data[j]
train_target[train_index] = target[j]
train_index += 1
else:
test_data[test_index] = data[j]
test_target[test_index] = target[j]
test_index += 1
model = linear_model.SGDRegressor(n_iter=100, learning_rate="invscaling", eta0=0.0001, power_t=0.5, penalty="l2", alpha=0.0001, loss="squared_loss")
model.fit(train_data, train_target)
print(model.coef_)
print(model.intercept_)
result = model.predict(test_data)
mse = np.mean((result - test_target) ** 2)
print("Mean Squared Error = %s" % str(mse))
Poi questo script Spark: (con accensione a presentare, senza altri argomenti)
from pyspark.mllib.regression import LinearRegressionWithSGD, LabeledPoint
from pyspark import SparkContext
sc = SparkContext (appName="mllib_simple_accuracy")
raw_data = sc.textFile ("data_yequalsx.csv", minPartitions=10) #MinPartitions doesnt guarantee that you get that many partitions, just that you wont have fewer than that many partitions
data = raw_data.map(lambda line: [float(x) for x in line.split (",")]).map(lambda entry: LabeledPoint (entry[-1], entry[:-1])).zipWithIndex()
test_samples= data.count()/10
training_data = data.filter(lambda (entry, index): index >= test_samples).map(lambda (lp,index): lp)
test_data = data.filter(lambda (entry, index): index < test_samples).map(lambda (lp,index): lp)
model = LinearRegressionWithSGD.train(training_data, step=0.01, iterations=100, regType="l2", regParam=0.0001, intercept=True)
print(model._coeff)
print(model._intercept)
mse = (test_data.map(lambda lp: (lp.label - model.predict(lp.features))**2).reduce(lambda x,y: x+y))/test_samples;
print("Mean Squared Error: %s" % str(mse))
sc.stop()
Stranamente, però, l'errore data dalla candela è un ordine di grandezza maggiore di quella data dalla Scikit (rispettivamente 0.185 e 0.045) nonostante i due modelli abbiano un setup quasi identico (per quanto posso dire) Capisco che questo stia usando SGD con pochissime iterazioni e quindi i risultati potrebbero essere diversi ma non avrei pensato che sarebbe dovunque vicino una differenza così grande o un errore così grande, soprattutto dati i dati eccezionalmente semplici.
C'è qualcosa che sto fraintendendo in Spark? Non è configurato correttamente? Sicuramente dovrei avere un errore più piccolo di quello?
ti suggerisco di fornire limiti di errore ripetendo l'esperimento più volte con semi casuali diversi e controlla se ottieni lo stesso risultato: 1000 punti dati e 100 iterazioni non sono molti.Inoltre, sklearn e mllib usano lo stesso programma di apprendimento per SGD? tu usi l'invalaling per sklearn ma mllib usa lo stesso? –