Переключение набора циклического кода для использования параллельного потока, по-видимому, приводит к игнорированию определенной части кода.
Я использую MOA и Weka с Java 11 для выполнения простой рекомендацииПример движка, использующий подсказки из исходного кода moa.tasks.EvaluateOnlineRecomender
, который использует внутреннюю настройку задачи MOA для проверки точности реализации смещенной регуляризованной пошаговой одновременной матричной факторизации (BRISMF), предоставленной MOA.Вместо того, чтобы использовать подготовленный класс MOA MovielensDataset
, я переключился на Instances
Weka для перспектив применения инструментов ML от Weka.
Время, необходимое для обработки около миллиона экземпляров (я использую Movielens 1Mнабор данных) было около 13-14 минут.В попытке увидеть улучшения, я хотел запустить его в параллельном потоке и стал подозрительным, когда задача завершилась примерно через 40 секунд.Я обнаружил, что BRISMFPredictor.predictRating
всегда производит 0 в теле параллельного потока.Вот код для любого случая:
Код для инициализации:
import com.github.javacliparser.FileOption;
import com.github.javacliparser.IntOption;
import moa.options.ClassOption;
import moa.recommender.predictor.BRISMFPredictor;
import moa.recommender.predictor.RatingPredictor;
import moa.recommender.rc.data.RecommenderData;
import weka.core.converters.CSVLoader;
...
private static ClassOption datasetOption;
private static ClassOption ratingPredictorOption;
private static IntOption sampleFrequencyOption;
private static FileOption defaultFileOption;
static {
ratingPredictorOption = new ClassOption("ratingPredictor",
's', "Rating Predictor to evaluate on.", RatingPredictor.class,
"moa.recommender.predictor.BRISMFPredictor");
sampleFrequencyOption = new IntOption("sampleFrequency",
'f', "How many instances between samples of the learning performance.", 100, 0, 2147483647);
defaultFileOption = new FileOption("file",
'f', "File to load.",
"C:\\Users\\shiva\\Documents\\Java-ML\\mlapp\\data\\ml-1m\\ratings.dat", "dat", false);
}
... и внутри main()
(причуды сCSVLoader
от Weka требовал, чтобы я заменял разделитель ::
по умолчанию на +
)
var csvLoader = new CSVLoader();
csvLoader.setSource(defaultFileOption.getFile());
csvLoader.setFieldSeparator("+");
var dataset = csvLoader.getDataSet();
System.out.println(dataset.toSummaryString());
var predictor = new BRISMFPredictor();
predictor.prepareForUse();
RecommenderData data = predictor.getData();
data.clear();
data.disableUpdates(false);
Теперь чередуем следующие фрагменты:
for (var instance : dataset) {
var user = (int) instance.value(0);
var item = (int) instance.value(1);
var rating = instance.value(2);
double predictedRating = predictor.predictRating(user, item);
System.out.printf("User %d | Movie %d | Actual Rating %d | Predicted Rating %f%n",
user, item, Math.round(rating), predictedRating);
}
(теперь это нубво всем одновременно):
dataset.parallelStream().forEach(instance -> {
var user = (int) instance.value(0);
var item = (int) instance.value(1);
var rating = instance.value(2);
double predictedRating = predictor.predictRating(user, item);
System.out.printf("User %d | Movie %d | Actual Rating %d | Predicted Rating %f%n",
user, item, Math.round(rating), predictedRating);
});
Теперь я решаю, что, черт возьми, эта операция не может быть выполнена параллельно, и я переключаю ее на использование stream()
.Даже в этом случае сегмент, по-видимому, полностью игнорируется, поскольку вывод снова равен 0.0 каждый раз
dataset.stream().forEach(instance -> {
var user = (int) instance.value(0);
var item = (int) instance.value(1);
var rating = instance.value(2);
double predictedRating = predictor.predictRating(user, item);
System.out.printf("User %d | Movie %d | Actual Rating %d | Predicted Rating %f%n",
user, item, Math.round(rating), predictedRating);
});
Я пытался удалить оператор печати из прогона, но безрезультатно.
Очевидно,Я получаю ожидаемые выходные строки, состоящие из фактического и прогнозируемого рейтинга в течение 13 минут в первом случае, но обнаруживаю, что прогнозируемый рейтинг равен 0,0 во втором случае с подозрительно низким временем выполнения.Есть что-то, что я пропускаю?
РЕДАКТИРОВАТЬ: использование dataset.forEach()
делает то же самое.Возможно, причуды лямбд?