简体   繁体   中英

Keras model for two-dimensional input

I'm trying to adapt a keras tutorial on housing prices to evaluate board game positions. The problem is that the board game positions are two-dimensional, and that makes keras complain.

Here's some code based on the tutorial that processes some dummy data generated from a linear equation.

import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasRegressor
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import KFold

# fix random seed for reproducibility
seed = 1
np.random.seed(seed)

# Generate dataset with linear outputs.
sample_count = 1000
column_count = 5
X = np.random.uniform(size=sample_count * column_count)
X.shape = (sample_count, column_count)
Y = 2*X[:, 0] + X[:, 1] + X[:, 2] + 11*X[:, 3] + 3*X[:, 4]


# define base model
def baseline_model():
    # create model
    model = Sequential()
    model.add(Dense(column_count * 2,
                    input_dim=column_count,
                    kernel_initializer='normal',
                    activation='relu'))
    model.add(Dense(1, kernel_initializer='normal'))
    # Compile model
    model.compile(loss='mean_squared_error', optimizer='adam')
    return model


# evaluate model with standardized dataset
estimator = KerasRegressor(build_fn=baseline_model, epochs=100, batch_size=5, verbose=0)

kfold = KFold(n_splits=10, random_state=seed)
results = cross_val_score(estimator, X, Y, cv=kfold)
print("Results: %.2f (%.2f) MSE" % (results.mean(), results.std()))

estimator.fit(X, Y)

test_samples = np.identity(column_count)
predictions = estimator.predict(test_samples)
print(predictions)

That works fine, but not when I try something equivalent with two-dimensional data. Here's the two-dimensional code:

import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasRegressor
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import KFold

# fix random seed for reproducibility
seed = 1
np.random.seed(seed)

# Generate dataset with linear outputs.
sample_count = 1000
row_count = 2
column_count = 3
X = np.random.uniform(size=sample_count * row_count * column_count)
X = X.reshape(sample_count, row_count, column_count)
Y = 2*X[:, 0, 0] + X[:, 0, 1] + 2*X[:, 0, 2] + 11*X[:, 1, 0] + 3*X[:, 1, 1]
Y = Y.reshape(sample_count, 1)


# define base model
def baseline_model():
    # create model
    model = Sequential()
    model.add(Dense(row_count * column_count * 2,
                    input_shape=(row_count, column_count),
                    kernel_initializer='normal',
                    activation='relu'))
    model.add(Dense(1, kernel_initializer='normal'))
    # Compile model
    model.compile(loss='mean_squared_error', optimizer='adam')
    return model


# evaluate model with standardized dataset
estimator = KerasRegressor(build_fn=baseline_model, epochs=100, batch_size=5, verbose=0)

kfold = KFold(n_splits=10, random_state=seed)
results = cross_val_score(estimator, X, Y, cv=kfold)
print("Results: %.2f (%.2f) MSE" % (results.mean(), results.std()))

estimator.fit(X, Y)

test_samples = np.zeros((row_count*column_count, row_count, column_count))
for sample_num, (row_num, column_num) in enumerate((row_num, column_num)
                                                   for row_num in range(row_count)
                                                   for column_num in range(column_count)):
    test_samples[sample_num, row_num, column_num] = 1
predictions = estimator.predict(test_samples)
print(predictions)

When I run that code, I get this error:

Traceback (most recent call last):
  File "/home/don/PycharmProjects/ml_tutorial/ml_tutorial/run_linear2.py", line 40, in <module>
    results = cross_val_score(estimator, X, Y, cv=kfold)
  File "/home/don/.local/share/virtualenvs/ml_tutorial-3a_885qf/lib/python3.6/site-packages/sklearn/model_selection/_validation.py", line 402, in cross_val_score
    error_score=error_score)
  File "/home/don/.local/share/virtualenvs/ml_tutorial-3a_885qf/lib/python3.6/site-packages/sklearn/model_selection/_validation.py", line 240, in cross_validate
    for train, test in cv.split(X, y, groups))
  File "/home/don/.local/share/virtualenvs/ml_tutorial-3a_885qf/lib/python3.6/site-packages/sklearn/externals/joblib/parallel.py", line 917, in __call__
    if self.dispatch_one_batch(iterator):
  File "/home/don/.local/share/virtualenvs/ml_tutorial-3a_885qf/lib/python3.6/site-packages/sklearn/externals/joblib/parallel.py", line 759, in dispatch_one_batch
    self._dispatch(tasks)
  File "/home/don/.local/share/virtualenvs/ml_tutorial-3a_885qf/lib/python3.6/site-packages/sklearn/externals/joblib/parallel.py", line 716, in _dispatch
    job = self._backend.apply_async(batch, callback=cb)
  File "/home/don/.local/share/virtualenvs/ml_tutorial-3a_885qf/lib/python3.6/site-packages/sklearn/externals/joblib/_parallel_backends.py", line 182, in apply_async
    result = ImmediateResult(func)
  File "/home/don/.local/share/virtualenvs/ml_tutorial-3a_885qf/lib/python3.6/site-packages/sklearn/externals/joblib/_parallel_backends.py", line 549, in __init__
    self.results = batch()
  File "/home/don/.local/share/virtualenvs/ml_tutorial-3a_885qf/lib/python3.6/site-packages/sklearn/externals/joblib/parallel.py", line 225, in __call__
    for func, args, kwargs in self.items]
  File "/home/don/.local/share/virtualenvs/ml_tutorial-3a_885qf/lib/python3.6/site-packages/sklearn/externals/joblib/parallel.py", line 225, in <listcomp>
    for func, args, kwargs in self.items]
  File "/home/don/.local/share/virtualenvs/ml_tutorial-3a_885qf/lib/python3.6/site-packages/sklearn/model_selection/_validation.py", line 528, in _fit_and_score
    estimator.fit(X_train, y_train, **fit_params)
  File "/home/don/.local/share/virtualenvs/ml_tutorial-3a_885qf/lib/python3.6/site-packages/keras/wrappers/scikit_learn.py", line 152, in fit
    history = self.model.fit(x, y, **fit_args)
  File "/home/don/.local/share/virtualenvs/ml_tutorial-3a_885qf/lib/python3.6/site-packages/keras/engine/training.py", line 952, in fit
    batch_size=batch_size)
  File "/home/don/.local/share/virtualenvs/ml_tutorial-3a_885qf/lib/python3.6/site-packages/keras/engine/training.py", line 789, in _standardize_user_data
    exception_prefix='target')
  File "/home/don/.local/share/virtualenvs/ml_tutorial-3a_885qf/lib/python3.6/site-packages/keras/engine/training_utils.py", line 128, in standardize_input_data
    'with shape ' + str(data_shape))
ValueError: Error when checking target: expected dense_2 to have 3 dimensions, but got array with shape (900, 1)

How can I persuade the model to accept two-dimensional inputs?

Based on a similar discussion in a GitHub issue , you can just add a Flatten() layer to reduce the input dimensions.

import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Flatten
from keras.wrappers.scikit_learn import KerasRegressor
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import KFold

# fix random seed for reproducibility
seed = 1
np.random.seed(seed)

# Generate dataset with linear outputs.
sample_count = 1000
row_count = 2
column_count = 3
X = np.random.uniform(size=sample_count * row_count * column_count)
X = X.reshape(sample_count, row_count, column_count)
Y = 2*X[:, 0, 0] + X[:, 0, 1] + 2*X[:, 0, 2] + 11*X[:, 1, 0] + 3*X[:, 1, 1]
Y = Y.reshape(sample_count, 1)


# define base model
def baseline_model():
    # create model
    model = Sequential()
    model.add(Dense(row_count * column_count * 2,
                    input_shape=(row_count, column_count),
                    kernel_initializer='normal',
                    activation='relu'))
    model.add(Flatten())
    model.add(Dense(1, kernel_initializer='normal'))
    # Compile model
    model.compile(loss='mean_squared_error', optimizer='adam')
    return model


# evaluate model with standardized dataset
estimator = KerasRegressor(build_fn=baseline_model, epochs=100, batch_size=5, verbose=0)

kfold = KFold(n_splits=10, random_state=seed)
results = cross_val_score(estimator, X, Y, cv=kfold)
print("Results: %.2f (%.2f) MSE" % (results.mean(), results.std()))

estimator.fit(X, Y)

test_samples = np.zeros((row_count*column_count, row_count, column_count))
for sample_num, (row_num, column_num) in enumerate((row_num, column_num)
                                                   for row_num in range(row_count)
                                                   for column_num in range(column_count)):
    test_samples[sample_num, row_num, column_num] = 1
predictions = estimator.predict(test_samples)
print(predictions)

I think I'll need to use other layers like Conv2D to actually take advantage of the two-dimensional relationships, but this gets me past the error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM