2017/11/04 - [Windows] - (Windows) 윈도우 에서 Ubuntu (우분투) 실행하기

위 글에서 우분투를 설치해 보았고 이제 텐서플로우를 설치해보자.

 

아래 명령어를 실행한다.

sudo apt-get install python3-pip python3-dev python-virtualenv

혹 위 명령어 실행이 에러가 발생된다면

sudo apt-get update

명령어를 실행한 후 실행하면 될것이다.

 

아래 명령어를 실행하여 가상 tensorflow 환경을 설정한다.

마지막에 tensor 은 변경해도 된다. (임의로 지정한것이다.) => TargetDirectory 를 나타냄 - https://www.tensorflow.org/install/install_linux#InstallingVirtualenv)

virtualenv --system-site-packages -p python3 tensor


이제 가상환경의 tensorflow 으로 진입해보자.

source ~/tensor/bin/activate


진입하게되면 아래처럼 맨 앞에 (tensor) 가 보이게 된다.

(위에서 지정한 이름이 괄호안에 들어가서 보이게된다.)

이제 최신환경으로 업그레이드 해주자

(tensor) junijuniya@kjunMainPC:~$ pip3 install --upgrade tensorflow


이상 우분투에 텐서플로우 환경을 구성하는 방법이다.


참고

http://jinman190.blogspot.kr/2017/10/openai-gym.html


아래는 설치 로그

더보기

[0.,1.,2.,3.,4.,5.,6.]

Rank : 몇차원 배열인지 = 1 (ndim) -> 처음 시작하는 [ (대괄호)의 수

Shape : 몇개의 엘리먼트가 있는지 = 7 -> [[1,2,3],[4,5,6]] => (2,3) 뒤에 내용부터 가장 낮은 단위.

[-1] 가장 마지막을 의미한다.

[2:5] : 2에서 5바로 앞까지 (2,3,4,)

[4:-1] : 4에서 가장 마지막 앞까지 (4,5)

[:2] => (0,1)

[3:] => (3,4,5,6)

Axis : 각 엘리먼트의 열 정보 , 바깥쪽 대괄호 부터 axis = 0 으로 명명하고
        그 안쪽 대괄호는 axis=1 이런식으로 숫자가 커진다. 

 

Reduce_mean 평균을 내서 여러개의 행열 값을 줄여주는 함수

tf.reduce_mean([1,2], axis =0).eval() => 1 axis  가 0 이므로 1만 가지고 평균을 구한것임.

x = [[1.,2.]
      [3.,4.]]
tf.reduce_mean(x).eval() => 2.5 : 전체 다 더해서 4로 나눠 평균

tf.reduce_mean(x, axis=0).eval() => 2,3 : 1,3 의 평균 2 , 2,4의 평균 3

tf.reduce_mean(x, axis=1).eval() => 1.5,3.5 : 1,2 의 평균 1.5 , 3,4의 평균 3.5 (axis = -1 은 가장 안쪽의 값을 나타낸다.)

 

Reduce_sum 합계를 낸다 Reduce_mean  과 사용방식은 같다.

Argmax 가장 큰것의 위치를 나타낸다.

x=[[0, 1, 2],
    [2, 1, 0]]
tf.argmax(x, axis=0).eval() => (1,0,0) 0,2 중에 2가 크므로 1 (0,1 인덱스중에 1) / 1,1 은 같으므로 0 / 2,0 중에 2가 크므로 0

Reshape  행열의 구성을 다시 재구성한다. 가장 안쪽의 값은 유지하도록 한다.

squeeze 값을 펼친다. [[0],[1],[2]] => [0,1,2]

expand_dims squeeze 와 반대의 의미로 보면되면 펼쳐져 있는것을 구조화한다.

tf.expand_dims([0,1,2], 1).eval() => [[0],[1],[2]]

ones_like(x)  x 구조와 같지만 데이터는 모두 1로 채운다.

zeros_like(x)  x 구조와 같지만 데이터는 모두 0로 채운다.

학습할 데이터 내용중 너무 튀는 값이 있어서 학습결과가 안좋을때

MinMaxScaler 함수를 이용해 모두 0~1 사이수로 나오게 하여 학습결과를 좋게 하는것이다.

=> Normalized

* Learning Rate : 이 값이 너무 크거나 작으면 결과 값을 찾기가 힘들어 질수 있다.
  - overshooting (값이 커서 결과값에 다가가질 못하고 튕겨나감)
  - takes too long(오래걸리고) , stop at local minimum (특정한 부분이 잠깐 내려갔다 올라오는데가 있을때 그 부분에서 멈출수 있다.)
  => 0.01 로 시작하되 결과를 보고 조정하는 것이 좋다.

* preprocessing : 데이터가 너무 차이가 크거나 할 때 정제하는 과정을 거쳐야한다.
  - zero-centered data : 데이터를 0 이 중심으로 가게한다.
  - normalized data : 어떤 범위안에 들어가도록 한다.

* Overfitting : 너무 정확하게 선을 구분하여 예측하려고 한다면 일반적인 선 구분으로 예측한 것 보다 예측률이 떨어질 수 있다.
  - 훈련 데이터가 많아야한다.
  - 변수를 줄여라
  - 일반화 시켜라. Regularization : 값이 너무 큰 값을 갖지 않도록 한다.

* Regularization  : 항목은 W의 값이 너무 크게 가지도록 하지 말자는 것입니다. W 값이 클수록 구분선이 더 구부러지는 형태를 띄게되는데
구부러진 구분선을 좀 더 펴주기 위한 스킬로써 cost 함수에 Regularization strength를 추가해주는 형태를 이용합니다.일반화 상수가 0이면 일반화를 시키지 않겠다는 뜻이고 1이면 정말 크게 적용하겠다는 의미가 됩니다. (보통 그래서 소수점단위로 쓴다고합니다) <= 펌

data-04-zoo.csv

import tensorflow as tf
import numpy as np

# 분류하고자하는 동물의 특징들과 분류 결과가 있는 학습데이터를 읽어옵니다.
xy = np.loadtxt('data-04-zoo.csv', delimiter=',', dtype=np.float32)

# 처름부터 마지막 컬럼 전까지가 특징들입니다.
x_data = xy[:, 0:-1]

# 마지막 컬럼이 분류된 결과 입니다. (0~6 로 구분)
y_data = xy[:, [-1]]

# x, y 데이터 구성을 출력합니다.
print(x_data.shape, y_data.shape)

# 0~6 까지 7까지 분류를 합니다.
nb_classes = 7 

# n 개의 데이터들이 16 가지 특징을 가집니다.
X = tf.placeholder(tf.float32, [None, 16])
# n 개의 데이터가 1개의 결과를 나타냅니다.
Y = tf.placeholder(tf.int32, [None, 1])  # 0 ~ 6
# One Hot 을 이용해 7개의 분류도 나누되 0,1 로 구분지을수 있도록 합니다. [[0],[3]] => [[[1000000]],[[0001000]]]
Y_one_hot = tf.one_hot(Y, nb_classes)  # one hot
print("one_hot", Y_one_hot)
# 차원이 하나 더 생겼으므로 차원을 제거합니다. [[[1000000]][[0001000]]] => [[1000000],[0001000]]
Y_one_hot = tf.reshape(Y_one_hot, [-1, nb_classes])
print("reshape", Y_one_hot)

# 입력은 16개 출력은 7가지로
W = tf.Variable(tf.random_normal([16, nb_classes]), name='weight')
# 출력은 7가지
b = tf.Variable(tf.random_normal([nb_classes]), name='bias')

# cost 를 계산한다.
# logits 는 결과 데이터 이며
logits = tf.matmul(X, W) + b
# 결과데이터를 softmax 를 이용하여 합계가 1 이되도록 확률로 계산하도록 가설을 세운다.

hypothesis = tf.nn.softmax(logits)

# cost 가 최소화되도록 한다.
# (cost = tf.reduce_mean(-tf.reduce_sum(Y * tf.log(hypothesis), axis=1)) 를 함수화 함)
cost_i = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=Y_one_hot) 
cost = tf.reduce_mean(cost_i)
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)

# 가설을 이용한 결과 값(prediction)과 onehot 을 이용한 결과 값이 같은지 비교하고 얼마나 정확한지 (accuracy)를 나타냅니다.
prediction = tf.argmax(hypothesis, 1)
correct_prediction = tf.equal(prediction, tf.argmax(Y_one_hot, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

# 학습합니다.
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    for step in range(2000):
        sess.run(optimizer, feed_dict={X: x_data, Y: y_data})
        if step % 100 == 0:
            loss, acc = sess.run([cost, accuracy], feed_dict={X: x_data, Y: y_data})
            print("Step: {:5}\tLoss: {:.3f}\tAcc: {:.2%}".format(step, loss, acc))

    # 학습한 결과로 엑셀데이터를 실제로 분류해봅니다.
    pred = sess.run(prediction, feed_dict={X: x_data})
    # flatten => [[0],[1]] => [0,1] ,zip 은 묶어서 처리하는것으로 아래 코드는 zip 으로 묶어 앞에껀 p 로 뒤에껀 y 로 처리한다는 의미.
    for p, y in zip(pred, y_data.flatten()):
        print("[{}] Prediction: {} True Y: {}".format(p == int(y), p, int(y))) # 결과(TRUE/FALSE), 예측한결과값, 실제값
        

아래 결과를 보면 알겠지만 accuracy 가 100% 입니다.
이를 보면 학습하는 데이터가 좋을수록 분류를 잘한다는걸 알 수 있습니다.

결과

더보기

어떤 결과치의 합을 1로 나타내도록 하는 것

여러 결과를 나타내고자 할때 사용된다. (A,B,C...)

A,B,C 를 판별한다고 할때

X값일때  A 인지 물어보면 결과가 0.7(A), 0.2(B), 0.1(C) 이런 식으로 나오게 된다

그러므로 X 일때 A 결과가 맞다고 보면된다.

이를 1.0, 0.0, .0.0 으로 명확하게 구분지으려고 할때는 ONE-HOT ENCODING 을 사용하면된다.

 

코드

import tensorflow as tf

x_data = [[1, 2, 1, 1],
          [2, 1, 3, 2],
          [3, 1, 3, 4],
          [4, 1, 5, 5],
          [1, 7, 5, 5],
          [1, 2, 5, 6],
          [1, 6, 6, 6],
          [1, 7, 7, 7]]
y_data = [[0, 0, 1],
          [0, 0, 1],
          [0, 0, 1],
          [0, 1, 0],
          [0, 1, 0],
          [0, 1, 0],
          [1, 0, 0],
          [1, 0, 0]]

X = tf.placeholder("float", [None, 4])
Y = tf.placeholder("float", [None, 3])
nb_classes = 3

W = tf.Variable(tf.random_normal([4, nb_classes]), name='weight')
b = tf.Variable(tf.random_normal([nb_classes]), name='bias')

# tf.nn.softmax computes softmax activations
# softmax = exp(logits) / reduce_sum(exp(logits), dim)
hypothesis = tf.nn.softmax(tf.matmul(X, W) + b)

# Cross entropy cost/loss
cost = tf.reduce_mean(-tf.reduce_sum(Y * tf.log(hypothesis), axis=1))

optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)

# Launch graph
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    for step in range(2001):
        sess.run(optimizer, feed_dict={X: x_data, Y: y_data})
        if step % 200 == 0:
            print(step, sess.run(cost, feed_dict={X: x_data, Y: y_data}))

    # 학습된 결과로 결론을 도출해봅니다.
    a = sess.run(hypothesis, feed_dict={X: [[1, 11, 7, 9]]})
    # argmax 는 그중에 최고값을 가려냅니다.
    print(a, sess.run(tf.argmax(a, 1)))

 결과

(0, 5.048625)
(200, 0.5484252)
(400, 0.43214869)
(600, 0.35246667)
(800, 0.27682927)
(1000, 0.23268281)
(1200, 0.21055315)
(1400, 0.19221503)
(1600, 0.17675203)
(1800, 0.16353439)
(2000, 0.15210819)
--------------
(array([[  1.38904958e-03,   9.98601854e-01,   9.06129117e-06]], dtype=float32), array([1]))

 

마지막줄에서 중간의 9.98601854e-01 값이 0.9 로 가장 큰 값을 가지므로 몇번째 있는지 확인하여 1 을 리턴한다. (0,1,2)

 

아래처럼 단일 값이 아닌 여러 값을 가지고 예측할수 있다.

 

    all = sess.run(hypothesis, feed_dict={
                   X: [[1, 11, 7, 9], [1, 3, 4, 3], [1, 1, 0, 1]]})
    print(all, sess.run(tf.argmax(all, 1)))

data-03-diabetes.csv

-0.29412 0.487437 0.180328 -0.29293 0 0.00149 -0.53117 -0.03333 0
-0.88235 -0.14573 0.081967 -0.41414 0 -0.20715 -0.76687 -0.66667 1
-0.05882 0.839196 0.04918 0 0 -0.30551 -0.49274 -0.63333 0
-0.88235 -0.10553 0.081967 -0.53535 -0.77778 -0.16244 -0.924 0 1
0 0.376884 -0.34426 -0.29293 -0.60284 0.28465 0.887276 -0.6 0
-0.41177 0.165829 0.213115 0 0 -0.23696 -0.89496 -0.7 1
-0.64706 -0.21608 -0.18033 -0.35354 -0.79196 -0.07601 -0.85483 -0.83333 0
0.176471 0.155779 0 0 0 0.052161 -0.95218 -0.73333 1
-0.76471 0.979899 0.147541 -0.09091 0.283688 -0.09091 -0.93168 0.066667 0
-0.05882 0.256281 0.57377 0 0 0 -0.86849 0.1 0
-0.52941 0.105528 0.508197 0 0 0.120715 -0.9035 -0.7 1
0.176471 0.688442 0.213115 0 0 0.132638 -0.60803 -0.56667 0
0.176471 0.396985 0.311475 0 0 -0.19225 0.163962 0.2 1
-0.88235 0.899497 -0.01639 -0.53535 1 -0.10283 -0.72673 0.266667 0
-0.17647 0.005025 0 0 0 -0.10581 -0.65329 -0.63333 0
0 0.18593 0.377049 -0.05051 -0.45627 0.365127 -0.59607 -0.66667 0
-0.17647 0.075377 0.213115 0 0 -0.11774 -0.8497 -0.66667 0
-0.88235 0.035176 -0.5082 -0.23232 -0.80378 0.290611 -0.91033 -0.6 1
-0.88235 0.155779 0.147541 -0.39394 -0.77305 0.031297 -0.61486 -0.63333 0
-0.64706 0.266332 0.442623 -0.17172 -0.44444 0.171386 -0.46541 -0.8 1
-0.05882 -0.00503 0.377049 0 0 0.055142 -0.73527 -0.03333 1
-0.17647 0.969849 0.47541 0 0 0.186289 -0.68147 -0.33333 0
0.058824 0.19598 0.311475 -0.29293 0 -0.13562 -0.84202 -0.73333 0
0.176471 0.256281 0.147541 -0.47475 -0.72813 -0.07303 -0.89155 -0.33333 0
-0.17647 0.477387 0.245902 0 0 0.174367 -0.84714 -0.26667 0
-0.88235 -0.02513 0.081967 -0.69697 -0.66903 -0.3085 -0.65073 -0.96667 1

위와 같은 여러 측정값이 있을때 어떤 질병이 걸렸는지 아닌지를 학습시키는 과정이다.

마지막에 0,1 이 0이면 질병이 아니고 1이면 질병에 걸린것이다.

import tensorflow as tf
import numpy as np
# 데이터를 파일에서 가져온다.
xy = np.loadtxt('data-03-diabetes.csv', delimiter=',', dtype=np.float32)
# 처음부터 마지막 컬럼 전까지 측정값이다.
x_data = xy[:, 0:-1]
# 마지막 컬럼이 결과값이다.
y_data = xy[:, [-1]]

# 구성이 어떻게 되어있는지 출력해 준다.
print(x_data.shape, y_data.shape)

# n개의 데이터가 8개의 측정값으로 구성된다.
X = tf.placeholder(tf.float32, shape=[None, 8])
# n개 의 하나의 결과치로 구성된다.
Y = tf.placeholder(tf.float32, shape=[None, 1])

# 8개의 측정값이 있고 1개의 결과가 나온다.
W = tf.Variable(tf.random_normal([8, 1]), name='weight')
# 1개의 결과가 도출된다.
b = tf.Variable(tf.random_normal([1]), name='bias')

# 시그모이드함수로 가설을 세운다. 결과를 0,1 로만 나오게 하기위함이다.
hypothesis = tf.sigmoid(tf.matmul(X, W) + b)

# cost 를 계산한다.
cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1 - Y) *  tf.log(1 - hypothesis))

# cost 를 줄이도록 학습한다.
train = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(cost)

# 결과가 0.5 이상이면 1 아니면 0 이다.
predicted = tf.cast(hypothesis > 0.5, dtype=tf.float32)
# 계산된 결과가 결과 값과 같은지 확률을 계산한다.
accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted, Y), dtype=tf.float32))

# 세션을 할당하고 초기화 한다. with 문은 묶인것? 이라고 보면됨.
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    # 10001 번의 루프를 돌면서 파일의 내용을 학습한다.
    for step in range(10001):
        cost_val, _ = sess.run([cost, train], feed_dict={X: x_data, Y: y_data})
        # 200 번 돌때마다 화면에 step 과 cost 를 출력한다.
        if step % 200 == 0:
            print(step, cost_val)

    # 실재로 학습된 결과로 다시 파일의 내용을 측정해보고 얼마나 정확한지 Accuracy 를 출력해본다.
    h, c, a = sess.run([hypothesis, predicted, accuracy],
                       feed_dict={X: x_data, Y: y_data})
    print("\nHypothesis: ", h, "\nCorrect (Y): ", c, "\nAccuracy: ", a)

위 내용의 출력은 Hypothesis 는 학습한 결과 로직에 파일의 내용을 대입했을때 각각에 대한 결과 값이며
Correct 는 결과값에 대한 1,0 을 나타내고 이 값이 실제 값과 얼마나 맞는지 Accuracy 로 나타내는 것입니다.

결과에서보듯이 Accuracy: ', 0.76679844) 으로 76 프로의 확률로 질병인지 아닌지를 판별 가능합니다.

결과

더보기

import tensorflow as tf


X(데이터), Y(결과) 를 정의한다.

x_data = [1, 2, 3]
y_data = [1, 2, 3]

W 에 랜덤값을 준다.

W = tf.Variable(tf.random_normal([1]), name='weight')

X,Y 노드를 만든다.

X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)

가설을 세우고

hypothesis = X * W

cost 를 계산한다.(square 제곱)

cost = tf.reduce_mean(tf.square(hypothesis - Y))

==========

0.1 만큼 움직이도록 최소화알고리즘에 사용한다.

learning_rate = 0.1

줄어든 값을 계산하고

gradient = tf.reduce_mean((W * X - Y) * X)

W 값에서 계산한 값을 빼고

descent = W - learning_rate * gradient

 

뺀값을 W값에 대입하도록 한다. -> 이런식으로 계속 반복하여 cost 를 최소화 한다.

update = W.assign(descent)

==========

========== 사이의 내용은 아래의 두줄 코드로 바꿀 수 있다.

cost 를 최소화하도록 훈련시키도록 한다.

optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train = optimizer.minimize(cost)

루프 내부도 변경되어야한다. 

for step in range(100):
print(step, sess.run(W))
sess.run(train)

세션을 정의하고 변수를 초기화한다.

sess = tf.Session()

sess.run(tf.global_variables_initializer())

21번 만큼 루프를 돌면서 비교값을 계속 최소화 시켜나간다.

for step in range(21):
sess.run(update, feed_dict={X: x_data, Y: y_data})
print(step, sess.run(cost, feed_dict={X: x_data, Y: y_data}), sess.run(W))

 

결과

(0, 0.94110894, array([ 0.5509274], dtype=float32))
(1, 0.26769316, array([ 0.76049465], dtype=float32))
(2, 0.076143883, array([ 0.87226379], dtype=float32))
(3, 0.021658683, array([ 0.93187404], dtype=float32))
(4, 0.0061607012, array([ 0.96366614], dtype=float32))
(5, 0.0017523728, array([ 0.98062193], dtype=float32))
(6, 0.00049845403, array([ 0.98966503], dtype=float32))
(7, 0.0001417833, array([ 0.994488], dtype=float32))
(8, 4.0330586e-05, array([ 0.99706024], dtype=float32))
(9, 1.1471246e-05, array([ 0.99843216], dtype=float32))
(10, 3.2631249e-06, array([ 0.99916381], dtype=float32))
(11, 9.2822262e-07, array([ 0.99955404], dtype=float32))
(12, 2.638879e-07, array([ 0.99976218], dtype=float32))
(13, 7.5077573e-08, array([ 0.99987316], dtype=float32))
(14, 2.1349843e-08, array([ 0.99993235], dtype=float32))
(15, 6.0727494e-09, array([ 0.99996394], dtype=float32))
(16, 1.7274111e-09, array([ 0.99998075], dtype=float32))
(17, 4.9048293e-10, array([ 0.99998975], dtype=float32))
(18, 1.4032746e-10, array([ 0.99999452], dtype=float32))
(19, 4.0156323e-11, array([ 0.99999708], dtype=float32))
(20, 1.1581847e-11, array([ 0.99999845], dtype=float32))
 
결과의 순서는 

루프 / COST / W

[1,2,3] 의 결과가 [1,2,3] 이 나오려면 어떤 수를 곱해야하는지를 알아내는 것이라고 보면된다.

결과를 보면 알겠지만 0.55091274 부터 시작해서 점점 1에 가깝게 변하고 있다.

즉 결과는 W 는 1 이어야한다.

마지막에 W 가 1에 가까운 것을 알수 있다.

COST 는 낮을수록 좋은것이다.

 

만약에

x_data = [1, 2, 3]
y_data = [2, 4, 6]

 

이렇게 값을 주게되면 W 는 2 이어야한다.

실제 돌리면 아래와 같이 2에 가까운 W 값이 나온다.

 

0, 0.91811532, array([ 1.55644727], dtype=float32))
(1, 0.26115283, array([ 1.76343858], dtype=float32))
(2, 0.074283406, array([ 1.87383389], dtype=float32))
(3, 0.02112958, array([ 1.93271136], dtype=float32))
(4, 0.0060101724, array([ 1.96411276], dtype=float32))
(5, 0.0017095689, array([ 1.98086011], dtype=float32))
(6, 0.00048626671, array([ 1.98979211], dtype=float32))
(7, 0.00013831869, array([ 1.99455571], dtype=float32))
(8, 3.9345487e-05, array([ 1.9970963], dtype=float32))
(9, 1.1191744e-05, array([ 1.99845135], dtype=float32))
(10, 3.1841603e-06, array([ 1.999174], dtype=float32))
(11, 9.0532711e-07, array([ 1.99955952], dtype=float32))
(12, 2.5757623e-07, array([ 1.99976504], dtype=float32))
(13, 7.3224314e-08, array([ 1.99987471], dtype=float32))
(14, 2.0887404e-08, array([ 1.99993312], dtype=float32))
(15, 5.9203416e-09, array([ 1.99996436], dtype=float32))
(16, 1.6977234e-09, array([ 1.99998093], dtype=float32))
(17, 4.8156323e-10, array([ 1.99998987], dtype=float32))
(18, 1.3557629e-10, array([ 1.99999464], dtype=float32))
(19, 3.8198777e-11, array([ 1.99999714], dtype=float32))
(20, 1.1581847e-11, array([ 1.99999845], dtype=float32))

 

 

 

 

몽땅 정리가 되어있는 글.

https://www.chatbotkorea.com/magazine/1

https://www.chatbotkorea.com/magazine/2

sung kim 교수님의 소개자료

https://www.youtube.com/watch?v=K9Oesd9or3E&app=desktop

 

GPU 를 클라우드 환경에서 사용할수 있게 해주는 것으로

로컬에서 돌리던 학습처리를 클라우드에 올려서 GPU 를 이용해 빠르게 학습할 수 있다고 한다.

sung kim 교수님도 참여하는것 같아 더 관심이간다.

아직 오픈은 된거 같지않고 아래 링크에서 알파 테스트를 모집하고 있다.

신청은 했는데 될런지는 모르겠다.;

https://research.clova.ai/nsml-alpha

+ Recent posts

티스토리 툴바