Ich habe kürzlich versucht, Apache Spark als Ersatz für Scikit Learn kennenzulernen, aber es scheint mir, dass Scikit selbst in einfachen Fällen viel schneller zu einem akkuraten Modell konvergiert als Spark. Zum Beispiel erzeugte I 1000 Datenpunkte für eine sehr einfache lineare Funktion (z = x + y) mit dem folgende Skript:Ist Apache Spark weniger genau als 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))
ich folgendes Scikit Skript dann lief:
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))
Und dann dieser Funke Skript: (mit Funken einreichen, keine weiteren Argumente)
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()
Merkwürdig zwar, wird der Fehler durch Funken gegeben ist eine Größenordnung größer als gegeben, dass durch Scikit (0.185 bzw. 0.045) trotz der beiden Modelle, die eine nahezu identische Konfiguration haben (soweit ich das beurteilen kann) Ich verstehe, dass dies SGD mit sehr wenigen Iterationen verwendet und so die Ergebnisse abweichen können, aber ich hätte das nicht gedacht es wäre irgendwo in der Nähe eines so großen Unterschieds oder eines so großen Fehlers, besonders angesichts der außergewöhnlich einfachen Daten.
Gibt es etwas, das ich in Spark falsch verstehe? Ist es nicht richtig konfiguriert? Sicherlich sollte ich einen kleineren Fehler bekommen als das?
Ich schlage vor, Sie Fehlergrenzen schaffen, durch das Experiment zu wiederholen mehrere Male mit verschiedenen zufälligen Seeds und prüfen, ob Sie das gleiche Ergebnis erhalten, 1000 Datenpunkte und 100 Iterationen ist nicht viel Außerdem verwenden Sklearn und MLLIB den gleichen Lerntarif für SGD Sie verwenden Invescaling für Sklearn aber ist MLLIB verwenden das Gleiche? –