Хорошо, я нашел ответ сам: в основном это делается простым изменением import keras
на import tensorflow.keras as keras
. Tf.keras позволяет передавать набор проверки также как тензор:
X, Y = datasetLoader('PATH-TO-DATASET', 264)
X_val, Y_val = datasetLoader('PATH-TO-VALIDATION-DATASET', 264)
# ... define and compile the model like above
parallel_model.fit(
epochs= epochs,
steps_per_epoch= STEPS_PER_EPOCH,
shuffle= False,
validation_data= (X_val, Y_val),
validation_steps= STEPS_PER_VALIDATION_EPOCH
)
Если ваша программа выглядит так ...
int main(int, char **) {
double x[5000][500],y[5000][500],z[5000][500];
// ...
return 0;
}
... значит, вы переполняете стек. Самый быстрый способ исправить это - добавить слово static .
int main(int, char **) {
static double x[5000][500],y[5000][500],z[5000][500];
// ...
return 0;
}
Второй самый быстрый способ исправить это - переместить объявление из функции:
double x[5000][500],y[5000][500],z[5000][500];
int main(int, char **) {
// ...
return 0;
}
Третий самый быстрый способ исправить это - для выделения памяти в куче:
int main(int, char **) {
double **x = new double*[5000];
double **y = new double*[5000];
double **z = new double*[5000];
for (size_t i = 0; i < 5000; i++) {
x[i] = new double[500];
y[i] = new double[500];
z[i] = new double[500];
}
// ...
for (size_t i = 5000; i > 0; ) {
delete[] z[--i];
delete[] y[i];
delete[] x[i];
}
delete[] z;
delete[] y;
delete[] x;
return 0;
}
Четвертый самый быстрый способ - выделить память в куче с помощью std :: vector. В вашем файле меньше строк, но больше строк в модуле компиляции, и вы должны либо придумать значимое имя для производных векторных типов, либо поместить их в анонимное пространство имен, чтобы они не загрязняли глобальное пространство имен:
#include <vector>
using std::vector
namespace {
struct Y : public vector<double> { Y() : vector<double>(500) {} };
struct XY : public vector<Y> { XY() : vector<Y>(5000) {} } ;
}
int main(int, char **) {
XY x, y, z;
// ...
return 0;
}
Пятый самый быстрый способ - разместить их в куче, но использовать шаблоны, чтобы размеры не были настолько удалены от объектов:
include <vector>
using namespace std;
namespace {
template <size_t N>
struct Y : public vector<double> { Y() : vector<double>(N) {} };
template <size_t N1, size_t N2>
struct XY : public vector< Y<N2> > { XY() : vector< Y<N2> > (N1) {} } ;
}
int main(int, char **) {
XY<5000,500> x, y, z;
XY<500,50> mini_x, mini_y, mini_z;
// ...
return 0;
}
Самый эффективный способ - выделить двумерные массивы как одномерные, а затем использовать арифметику индексов.
Все вышеизложенное предполагает, что у вас есть какая-то причина, хорошая или плохая, для желания создать свой собственный механизм многомерного массива. Если у вас нет причин и вы планируете снова использовать многомерные массивы, настоятельно рекомендуем установить библиотеку:
Способ "хорошо играть с STL" - это используйте Boost Multidimensional Массив .
Быстрый способ - использовать Blitz ++ .
Ваше объявление должно появиться на верхнем уровне, вне какой-либо процедуры или метода.
Безусловно самый простой способ диагностировать segfault в коде C или C ++ - это используйте valgrind . Если один из ваших массивов неисправен, valgrind точно определит, где и как. Если ошибка в другом месте, он также сообщит вам об этом.
valgrind можно использовать с любым двоичным файлом x86, но он предоставит дополнительную информацию, если вы скомпилируете с помощью gcc -g
.
Эти массивы находятся в стеке. Стеки довольно ограничены по размеру. Вы наверняка столкнетесь с ...
. Вы можете попробовать и использовать Boost.Multi_array
typedef boost::multi_array<double, 2> Double2d;
Double2d x(boost::extents[5000][500]);
Double2d y(boost::extents[5000][500]);
Double2d z(boost::extents[5000][500]);
Фактически большой фрагмент памяти будет выделен в куче и автоматически освобожден при необходимости.
По-моему, у вас есть переполнение стека, честно говоря, Спольски!
Попробуйте скомпилировать свою программу с параметром gcc -fstack-check. Если ваши массивы слишком велики для размещения в стеке, вы получите исключение StorageError.
Я думаю, что это хорошая ставка, поскольку 5000 * 500 * 3 удвоений (по 8 байтов каждый) составляют около 60 мегабайт - ни одна платформа не имеет для этого достаточного стека. Вам нужно будет разместить свои большие массивы в куче.
Другим решением предыдущих было бы выполнение
ulimit -s stack_area
для расширения максимального стека.
Одно замечание насчет постоянного использования вектора: насколько я понимаю, если вы отойдете от конца массива, он просто выделит более крупный массив и скопирует все, что может создать незаметные и трудно обнаруживаемые ошибки, когда вы действительно привязаны к работе с массивом фиксированного размера. По крайней мере, с реальным массивом вы столкнетесь с ошибкой, если дойдете до конца, что упростит обнаружение ошибки.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
typedef double (*array5k_t)[5000];
array5k_t array5k = calloc(5000, sizeof(double)*5000);
// should generate segfault error
array5k[5000][5001] = 10;
return 0;
}