Gần đây tôi đã cố gắng tìm hiểu Apache Spark như một sự thay thế cho Scikit Learn, tuy nhiên dường như với tôi ngay cả trong những trường hợp đơn giản, Scikit cũng hội tụ với một mô hình chính xác nhanh hơn Spark. Ví dụ tôi tạo ra 1000 điểm dữ liệu cho một hàm tuyến tính rất đơn giản (z = x + y) với kịch bản sau đây:Apache Spark có kém chính xác hơn 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))
sau đó tôi chạy kịch bản Scikit sau:
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))
Và sau đó kịch bản Spark này: (với spark-gửi, không có đối số khác)
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()
Kỳ lạ thay, mặc dù lỗi do tia lửa là một thứ tự tầm quan trọng lớn hơn do Scikit (0.185 và 0.045 tương ứng) mặc dù hai mô hình có thiết lập gần như giống nhau (theo như tôi có thể biết) Tôi hiểu rằng điều này đang sử dụng SGD với rất ít lần lặp lại và kết quả có thể khác nhau nhưng tôi không nghĩ rằng nó sẽ ở bất cứ nơi nào gần một sự khác biệt lớn như vậy hoặc một lỗi lớn như vậy, đặc biệt là với dữ liệu đặc biệt đơn giản.
Có điều gì tôi hiểu nhầm trong Spark? Nó có được cấu hình đúng không? Chắc chắn tôi sẽ nhận được một lỗi nhỏ hơn thế?
Tôi đề nghị bạn cung cấp giới hạn lỗi bằng cách lặp lại thí nghiệm nhiều lần với các hạt giống ngẫu nhiên khác nhau và kiểm tra xem bạn có nhận được kết quả tương tự hay không, 1000 điểm dữ liệu và 100 lần lặp lại không nhiều lắm, ngoài ra, sklearn và mllib sử dụng cùng một tốc độ học tập cho SGD, bạn sử dụng invscaling cho sklearn. giống nhau? –