input: Write a python function to create and run a grid search for a neural network model using keras and sklearn.
  assert type(create_and_run_grid_search(X_train, y_train)) == dict
  assert 'optimizer' in create_and_run_grid_search(X_train, y_train)
  assert 'batch_size' in create_and_run_grid_search(X_train, y_train)
  assert 'epochs' in create_and_run_grid_search(X_train, y_train)
output: from keras.models import Sequential
  from keras.layers import Dense
  from keras.optimizers import Adam, RMSprop
  from keras.wrappers.scikit_learn import KerasClassifier
  from sklearn.model_selection import GridSearchCV
  
  def create_and_run_grid_search(X_train, y_train):
      def create_model(optimizer='adam'):
          model = Sequential()
          model.add(Dense(12, input_dim=X_train.shape[1], activation='relu'))
          model.add(Dense(8, activation='relu'))
          model.add(Dense(1, activation='sigmoid'))
          model.compile(loss='binary_crossentropy', optimizer=optimizer, metrics=['accuracy'])
          return model
  
      model = KerasClassifier(build_fn=create_model, verbose=0)
      param_grid = {
          'batch_size': [10, 20, 40],
          'epochs': [10, 50, 100],
          'optimizer': ['adam', 'rmsprop']
      }
      grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1, cv=3)
      grid_result = grid.fit(X_train, y_train)
      
      return grid_result.best_params_