def is_correct(src):
    left = 0; right = 0
    # 반대괄호가 먼저나온다면 잘못된 괄호문자열
    if src[0] == ')':
        return False
    else:
        # 왼쪽일경우
        left = left + 1
        for i in src:
            # 오른쪽괄호가 왼쪽보다 많아지는순간이 있는경우 잘못된괄호문자열
            if left < right:
                return False
            elif i == '(':
                left = left + 1
            elif i == ')':
                right = right + 1
        # 이상없을시 올바른 괄호문자열
        return True


def correction(src):
    # 1. 입력이 빈 문자열
    if len(src) == 0:
        return ''
    # index 설정
    idx = 0; left = 0; right = 0
    for i in range(len(src)):
        # 균형잡힌 문자열 체크
        if src[i] is '(':
            left = left + 1
        elif src[i] is ')':
            right = right + 1
        # 균형잡힌만큼 index 를 저장
        if left == right:
            idx = i + 1
            break
    # 2. u와 v로 분리
    u = src[0:idx]; v = src[idx:]

    # 3. u가 올바른 문자열이면 v에 대해 recursive
    if is_correct(u):
        # 3-1 수행한 결과 문자열을 u에 이어붙인후 반환
        return u + correction(v)
    # 4. u 가 올바르지 않다면
    else:
        # 4-1 ~ 4-3 빈문자열에 ( 추가후 v계산후에 )붙여넣기
        tmp = '(' + correction(v) + ')'
        # 4-4 나머지 문자열 뒤집기
        for i in range(1, len(u) - 1):
            if u[i] is '(':
                tmp = tmp + ')'
            else:
                tmp = tmp + '('

        return tmp


def solution(p):
    return correction(p)

'Coding Test' 카테고리의 다른 글

2020 카카오 1차 코딩 테스트 문제 1번  (0) 2019.11.07
src = input()
dst = src

# 가능한 step수들을 탐색
for step in range(1, len(src)//2+1):
    # 비교하기전에 넣어둘 list 선언
    tmp = ''
    # step 만큼 이동하며 문자열 압축이가능한지확인
    i = 0
    while i < len(src):
        # 압축이 가능할 경우
        if src[i:i+step] == src[i+step:i+2*step]:
            compress = 2
            # 다음스텝으로
            i = i + step
            # compress 가능한 문자열 체크
            for j in range(i, len(src), step):
                if src[j:j+step] == src[j+step:j+2*step]:
                    # 있다면 숫자를 추가한뒤에 다음스텝으로
                    compress = compress + 1
                    i = i + step
                else:
                    # 없다면 중지
                    break
            # 문자열 연산을통해 문자열 생성
            tmp = tmp + str(compress) + src[j:j+step]
            # 다음스텝으로
            i = i + step
        # 압축이 불가할경우
        else:
            # step 만큼 list에 넣고 다음 step으로 이동
            tmp = tmp + src[i:i+step]
            i = i + step

    # 압축이완료될경우 기존의 압축과 압축률비교a
    if len(tmp) < len(dst):
        # 압축률이 좋을경우 대체
        dst = tmp

print(dst)

'Coding Test' 카테고리의 다른 글

2020 카카오 1차 코딩 테스트 문제 2번  (0) 2019.11.08

1 x 1 convolution

 

논문을 읽다가 1 x 1 convolution 이란걸 보게되었습니다.

 

1 x 1 convolution이 뭘까? 궁금해서 찾아본것을 바탕으로 정리해보겠습니다.

 

Neural Network연산을 할때 feature map들의 채널을 줄이는 연산을 많이 진행합니다.

 

다음과 같은 연산을 보겠습니다.

 

5 x 5 filter convolution 연산

 

[그림. 1] 5 x 5 convolution 연산 

 

연산량은 28 x 28 x 32 x 5 x 5 x 192 = 120,422,400 약 1.2억 번의 연산이 필요합니다.

 

 

여기서 1 x 1 convolution을 사용하여 channel을 줄인뒤, 5 x 5 filter convolution을 적용해 보겠습니다.

 

1 x 1 convolution을 이용한 5 x 5 convolution 연산

 

[그림. 2] 1 x 1 convolution을 이용한 5 x 5 convolution 연산

 

우선 첫번째로 채널을 줄이는 연산량은 28 x 28 x 16 x 1 x 1 x 192 = 2,408,448 약 240만 번의 연산이 필요하며,

 

다시 32 채널로 늘릴때는 28 x 28 x 32 x 5 x 5 x 16 =  10,035,200 약 1000만번의 연산이 필요합니다.

 

따라서, 총 약 1240만번의 연산이 필요하게 됩니다.

 

같은 5 x 5 filter를 적용한 연산임에도 불구하고 연산량은

 

1.2억번(12000만번) 과 1240만번의 연산으로 10배가까이 차이나는것을 확인할 수 있습니다.

 

그럼, 과연 실제로도 그정도 연산속도 차이가 있을까요? 

 

Tensorflow를 통해 실험해 보겠습니다.

 

1. MNIST 불러오기

 

from tensorflow import keras

(train_images, train_labels), (test_images, test_labels) = keras.datasets.mnist.load_data()

train_images = train_images.reshape((60000, 28, 28, 1))
test_images = test_images.reshape((10000, 28, 28, 1))

train_images, test_images = train_images / 255.0, test_images / 255.0

 

우선 mnist를 불러온뒤에 convolution을 사용하기위해 이미지를 reshape를 통해 모양을 바꾸고 정규화하겠습니다.

 

2. 모델 정의하기

 

모델을 5 x 5 convolution만 사용한 모델과 1 x 1 convolution을 활용한 모델 2개를 정의하겠습니다.

 

model = keras.models.Sequential([
    keras.layers.Conv2D(192, (3, 3), activation='relu', padding='SAME', input_shape=(28, 28, 1)),
    keras.layers.Conv2D(1024, (5, 5), activation='relu', padding='SAME'),
    keras.layers.Flatten(),
    keras.layers.Dense(10, activation='softmax')
])

model2 = keras.models.Sequential([
    keras.layers.Conv2D(192, (3, 3), activation='relu', padding='SAME', input_shape=(28, 28, 1)),
    keras.layers.Conv2D(16, (1,1), activation='relu', padding='SAME'),
    keras.layers.Conv2D(1024, (5, 5), activation='relu', padding='SAME'),
    keras.layers.Flatten(),
    keras.layers.Dense(10, activation='softmax')
])

 

실험에서는 좀더 차이를 확실하게 보기위해 32채널이아닌 1024채널을 사용하겠습니다.

 

3. summury( ) 함수를 통해 정보 확인

 

 

model.summary()

model2.summary()

 

[그림. 3] summary( ) 함수 비교

각 모델의 parameter의 수를 보면 약 3배정도의 parameter의 차이를 보입니다.

 

4. 모델 훈련하기

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model2.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(train_images, train_labels, epochs=5)

model2.fit(train_images, train_labels, epochs=5)

 

각 모델의 optimizer와 loss를 정의하고, 실제로 훈련을 진행합니다.

 

[그림. 4] model의 학습

 

[그림.5] model2의 학습

실제로 실험을 해본 결과는 10배나 5배 빠른 정도로 차이가있지는 않았고, 30% ~ 40% 정도의 차이를 보입니다.

 

gpu환경과 cpu환경의 차이가 있나 궁금해서 cpu환경에서 한번더 실험을 진행했습니다.

 

[그림. 6] cpu환경에서의 두 모델 속도차이

 

하지만, cpu환경에서 실험을 해본결과는 약 5배정도의 속도차이를 보입니다.

 

accuracy에서는 큰차이가 없는걸로 보아, 성능에는 큰 차이가 없는걸로 확인됩니다.

 

5. inference 속도 차이

model.evaluate(test_images, test_labels)

model2.evaluate(test_images, test_labels)

 

inference의 속도도 한번 비교해보겠습니다. 각 모델을 3번씩 inference를 진행해보겠습니다.

 

[그림. 7] model의 inference

 

[그림. 8] model2의 inference

inference에서는 간극이 더 줄어 20% ~ 30%의 성능차이를 보였습니다.

 

따라서, 이론적으로 계산했던 10배이상의 차이는 보이지 않으며 20~30%정도의 속도 상승을 보이는것을

 

확인할 수 있었습니다.

 

하지만, GPU환경이 아닌 CPU환경에서는 좀더 이론에 가까운 5배정도의 차이를 보이는것을 확인할 수 있었습니다. 

 

'Deep Learning' 카테고리의 다른 글

Single Layer Perceptron (SLP)  (0) 2019.11.05

tf.data.Dataset

tensorflow에서 지원하는 Dataset를 관리하는 모듈입니다.

 

Training시에 data를 쉽게 처리하기위해 제공되는 모듈로서 MNIST를 활용하여 실습해보겠습니다.

1. MNIST 불러오기

 import tensorflow as tf

mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()

 

우선 tf.keras.datasets.mnist를 통해 mnist를 불러오겠습니다.

2. from_tensor_slices 사용하기

 ds_train = tf.data.Dataset.from_tensor_slices(
    (x_train, y_train)
).shuffle(10000).batch(10)

 

불러온 데이터를 tf.data.Datset의 method인 from_tensor_slices( )를 통해 tensor를 생성합니다.

 

 

[참조] https://www.tensorflow.org/guide/data#consuming_numpy_arrays

 

Tensorflow.org에 따르면 큰 크기의 feature일 경우 tf.constant( )의 사용으로 여러번 array가 복사되어,

 

메모리의 낭비가 발생한다고하니 주의가 필요합니다.

 

shuffle( )은 입력된 buffer_size만큼 data를 채우고 무작위로 sampling하여 새로운 data로 바꿉니다.

 

완벽한 셔플링을 위해서는 데이터 세트의 전체 크기보다 크거나 같은 버퍼 크기가 필요합니다.

 

만약 작은 데이터수보다 작은 buffer_size를 사용할경우,

 

처음에 설정된 buffer_size만큼의 data안에서 임의의 셔플링이 발생합니다.

 

batch( )를 통해 원하는 batch size를 결정하게 됩니다.

3. batch 불러오기

images = []; labels = []
for image, label in ds_train:
    images = image; labels = label
    break

images, labels = images.numpy(), labels.numpy()

 

tensorflow 2.0 에서는 for 문을 통해 batch_dataset에 접근할 수 있습니다.

 

또한, tensorflow 2.0 에서는 eager모드가 기본으로 적용돼 있습니다.

 

따라서, tensorflow를 numpy로 변경하기위해서 session을 불러오는 작업이 numpy( )로 간단히 대체되었습니다.

4. batch 출력

def batch_out(data):
    for image, label in data:
        return image.numpy(), label.numpy()

 

우선 간단히 batch 1개를 return하는 함수를 작성하여 batch를 불러오도록 하겠습니다.

 

images, labels = batch_out(ds_train)
fig1 = plt.figure(num='first batch')
for i in range(10):
    subplot = fig1.add_subplot(2, 5, i + 1)
    subplot.axis('off')
    subplot.imshow(images[i], cmap='gray')

images, labels = batch_out(ds_train)
fig2 = plt.figure(num='second batch')
for i in range(10):
    subplot = fig2.add_subplot(2, 5, i + 1)
    subplot.axis('off')
    subplot.imshow(images[i], cmap='gray')

plt.show()

 

batch를 불러온후 각 batch를 출력해보았습니다.

 

 

 

각 batch가 다르게나오는것을 확인할 수 있습니다.

Perceptron ⓝ 지각, 자각

신경 생리학자인 Warren MacCulloch 와 논리학자 Walter Pitts가 함께 제안한 'McCulloch-Pitts 뉴런'

[그림. 1] 신경세포와 Perceptron

perceptron은 우리 몸에있는 신경망 세포를 본따 컴퓨터로 옮겨 표현한것 입니다.

 

Single Layer Perceptron

1개층의 Perceptron을 이용한 것을 Single Layer Perceptron (SLP) 라고 합니다.

 

[그림. 2] Single Layer Perceptron

 

x1w1 + x2w2 + w0 = output 으로 표현 되며, w0은 bias라고 불리웁니다.

 

Single Layer Perceptron은 분류를 위한 문제를 해결하기위한 새로운 방법으로 사용되어졌지만,

 

한가지문제점이 존재합니다. 다음 그림을 보겠습니다.

 

 

[그림. 3] AND문제 OR문제와 XOR문제

 

그래프에서 표현된 빨간점이 0 파란점이 1입니다. 

 

AND와 OR는 단순히 직선하나로 간단히 분류가 되어지며, SLP를 사용해 쉽게 분류가 가능합니다.

 

하지만, XOR같은 경우는 단순히 직선 1개를 가지고는 분류할수 없게되는 문제를 가지고 있습니다.

 

이를 해결하기 위한 방법으로 새롭게 Multiple Layer Perceptron이 등장하게 됩니다.

'Deep Learning' 카테고리의 다른 글

1 x 1 convolution  (0) 2019.11.07

딥러닝을 좋아하는 학생입니다!

한번 시작해보겠습니다!

+ Recent posts