text: # set to use CPU
  import os
  os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
  
  # 1. 분류 CNN 패키지 임포트 
  from sklearn import model_selection, metrics
  from sklearn.preprocessing import MinMaxScaler
  import numpy as np
  import matplotlib.pyplot as plt
  import os
  
  from keras import backend as K
  from keras.utils import np_utils
  from keras.models import Model
  from keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense, Dropout
  
  from keraspp import skeras
  from keraspp import sfile
  
  # 2. 분류 CNN 모델링
  class CNN(Model):
      def __init__(self, nb_classes): #, in_shape=None):
          super(CNN,self).__init__() # added 2021-10-01
          self.nb_classes = nb_classes
          #self.in_shape = in_shape
          
          self.conv2D_A = Conv2D(32, kernel_size=(3, 3), activation='relu')
          self.conv2D_B = Conv2D(64, (3, 3), activation='relu')
          self.maxPooling2D_A = MaxPooling2D(pool_size=(2, 2))
          self.dropout_A = Dropout(0.25)
          self.flatten = Flatten()
          
          self.dense_A = Dense(128, activation='relu')
          self.dropout_B = Dropout(0.5)
          self.dense_B = Dense(nb_classes, activation='softmax', name='preds')
          
      def call(self, x):
          nb_classes = self.nb_classes
          # in_shape = self.in_shape
  
          #x = Input(in_shape)
  
          h = self.conv2D_A(x)
          h = self.conv2D_B(h)
          h = self.maxPooling2D_A(h)
          h = self.dropout_A(h)
          h = self.flatten(h)
  
          h = self.dense_A(h)
          h = self.dropout_B(h)
  
          y = self.dense_B(h)
          
          return y
  
  # 3. 분류 CNN을 위한 데이터 준비
  class DataSet:
      def __init__(self, X, y, nb_classes, scaling=True, 
                   test_size=0.2, random_state=0):
          """
          X is originally vector. Hence, it will be transformed
          to 2D images with a channel (i.e, 3D).
          """
          self.X = X
          self.add_channels()
  
          X = self.X
          # the data, shuffled and split between train and test sets
          X_train, X_test, y_train, y_test = model_selection.train_test_split(
              X, y, test_size=0.2, random_state=random_state)
  
          print(X_train.shape, y_train.shape)
  
          X_train = X_train.astype('float32')
          X_test = X_test.astype('float32')
  
          if scaling:
              # scaling to have (0, 1) for each feature (each pixel)
              scaler = MinMaxScaler()
              n = X_train.shape[0]
              X_train = scaler.fit_transform(
                  X_train.reshape(n, -1)).reshape(X_train.shape)
              n = X_test.shape[0]
              X_test = scaler.transform(
                  X_test.reshape(n, -1)).reshape(X_test.shape)
              self.scaler = scaler
  
          print('X_train shape:', X_train.shape)
          print(X_train.shape[0], 'train samples')
          print(X_test.shape[0], 'test samples')
  
          # convert class vectors to binary class matrices
          Y_train = np_utils.to_categorical(y_train, nb_classes)
          Y_test = np_utils.to_categorical(y_test, nb_classes)
  
          self.X_train, self.X_test = X_train, X_test
          self.Y_train, self.Y_test = Y_train, Y_test
          self.y_train, self.y_test = y_train, y_test
          # self.input_shape = input_shape
  
      def add_channels(self):
          X = self.X
  
          if len(X.shape) == 3:
              N, img_rows, img_cols = X.shape
  
              if K.image_dim_ordering() == 'th':
                  X = X.reshape(X.shape[0], 1, img_rows, img_cols)
                  input_shape = (1, img_rows, img_cols)
              else:
                  X = X.reshape(X.shape[0], img_rows, img_cols, 1)
                  input_shape = (img_rows, img_cols, 1)
          else:
              input_shape = X.shape[1:]  # channel is already included.
  
          self.X = X
          self.input_shape = input_shape    
      
  # 4. 분류 CNN의 학습 및 성능 평가를 위한 머신 클래스
  class Machine():
      def __init__(self, X, y, nb_classes=2, fig=True):
          self.nb_classes = nb_classes
          self.set_data(X, y)
          self.set_model()
          self.fig = fig
  
      def set_data(self, X, y):
          nb_classes = self.nb_classes
          self.data = DataSet(X, y, nb_classes)
          print('data.input_shape', self.data.input_shape)
  
      def set_model(self):
          nb_classes = self.nb_classes
          data = self.data
          self.model = CNN(nb_classes=nb_classes)
          self.model.compile(loss='categorical_crossentropy',
                        optimizer='adadelta', metrics=['accuracy'])        
  
      def fit(self, epochs=10, batch_size=128, verbose=1):
          data = self.data
          model = self.model
  
          history = model.fit(data.X_train, data.Y_train, 
                              batch_size=batch_size, epochs=epochs,
                              verbose=verbose, 
                              validation_data=(data.X_test, data.Y_test))
          return history
  
      def run(self, epochs=100, batch_size=128, verbose=1):
          data = self.data
          model = self.model
          fig = self.fig
  
          history = self.fit(epochs=epochs,
                             batch_size=batch_size, verbose=verbose)
  
          score = model.evaluate(data.X_test, data.Y_test, verbose=0)
  
          print('Confusion matrix')
          Y_test_pred = model.predict(data.X_test, verbose=0)
          y_test_pred = np.argmax(Y_test_pred, axis=1)
          print(metrics.confusion_matrix(data.y_test, y_test_pred))
  
          print('Test score:', score[0])
          print('Test accuracy:', score[1])
  
          # Save results
          suffix = sfile.unique_filename('datatime')
          foldname = 'output_' + suffix
          os.makedirs(foldname)
          skeras.save_history_history(
              'history_history.npy', history.history, fold=foldname)
          model.save_weights(os.path.join(foldname, 'dl_model.h5'))
          print('Output results are saved in', foldname)
  
          if fig:
              plt.figure(figsize=(12, 4))
              plt.subplot(1, 2, 1)
              skeras.plot_acc(history)
              plt.subplot(1, 2, 2)
              skeras.plot_loss(history)
              plt.show()
  
          self.history = history
  
          return foldname
  
  # 5. 분류 CNN의 학습 및 성능 평가 수행
  from keras import datasets
  import keras
  assert keras.backend.image_data_format() == 'channels_last'
  
  # from keraspp import aicnn
  class MyMachine(Machine):
      def __init__(self):
          (X, y), (x_test, y_test) = datasets.cifar10.load_data()
          super(MyMachine,self).__init__(X, y, nb_classes=10)
  
  def main():
      m = MyMachine()
      m.run(epochs=2)
  
  if __name__ == '__main__':
      main()