2018년 10월 20일 토요일

RNN 연습

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

def load_weather(file_path, seq_length):
    weather = np.loadtxt(file_path, delimiter=' ', skiprows=1)
    weather = (weather[:,1:])
    weather = weather.transpose()
    weather = weather.reshape(-1, 1)

    xx, yy = [], []
    for i in range(len(weather)-seq_length):
        xx.append(weather[i:i+seq_length])
        yy.append(weather[i+seq_length])
    return np.float32(xx), np.float32(yy)

# 날씨 데이타# http://www.weather.go.kr/weather/climate/past_table.jspdef rnn_weather():
    batch_size = 1    seq_length = 7    n_classes = 1    hidden_size = 5    output_dim = 1
    xx, yy           = load_weather("Data/weather.txt", seq_length)
    xx_test, yy_test = load_weather("Data/weather_test.txt", seq_length)

    x = tf.placeholder(tf.float32, shape=[None, 7, 1])

    cells = tf.nn.rnn_cell.BasicRNNCell(num_units=hidden_size, activation=tf.tanh)
    output, state_ = tf.nn.dynamic_rnn(cells, x, dtype=tf.float32)

    z = tf.contrib.layers.fully_connected(inputs=output[:, -1],
                                          num_outputs=1,
                                          activation_fn=None)
    loss = tf.reduce_mean((z-yy)**2)

    optimizer = tf.train.AdamOptimizer(0.01)
    train = optimizer.minimize(loss)

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())

        for i in range(5000):
            sess.run(train, {x:xx})
            print(sess.run(loss , {x:xx}))

        p = sess.run(z, {x:xx_test[30:100]})

        plt.plot(p, 'r')
        plt.plot(yy_test[30:100], 'g')
        plt.show()

rnn_weather()

2018년 10월 17일 수요일

RNN simple

import tensorflow as tf
import numpy as np

def rnn_1():
    vocab = np.array(['e', 'n', 'o', 'r', 's', 't'])

    x = [[0., 0., 0., 0., 0., 1.], # t
         [1., 0., 0., 0., 0., 0.], # e
         [0., 1., 0., 0., 0., 0.], # n
         [0., 0., 0., 0., 1., 0.], # s
         [0., 0., 1., 0., 0., 0.]] # o

    y = [[1, 0, 0, 0, 0, 0], # e
         [0, 1, 0, 0, 0, 0], # n
         [0, 0, 0, 0, 1, 0], # s
         [0, 0, 1, 0, 0, 0], # o
         [0, 0, 0, 1, 0, 0]] # r

    w = tf.Variable(tf.random_uniform([6,6]))
    b = tf.Variable(tf.random_uniform([6]))

    # (5,6) = (5,6) @ (6, 6)
    z = tf.matmul(x, w) + b
    h = tf.nn.softmax(z)
    loss = tf.nn.softmax_cross_entropy_with_logits_v2(logits=z, labels=y)

    optimizer = tf.train.GradientDescentOptimizer(0.1)
    train = optimizer.minimize(loss=loss)

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        for i in range(1000):
            sess.run(train)
            print(sess.run(loss))

        print(sess.run(h))
        print(np.argmax(sess.run(h), axis=1 ))
        print(vocab[np.argmax(sess.run(h), axis=1)])
rnn_1()



def rnn_2_2():
    vocab = np.array(['e', 'n', 'o', 'r', 's', 't'])

    # tenso
    x = [[0., 0., 0., 0., 0, 1.],
         [1., 0., 0., 0., 0, 0.],
         [0., 1., 0., 0., 0, 0.],
         [0., 0., 0., 0., 1, 0.],
         [0., 0., 1., 0., 0, 0.]]
    # ensor
    y = [[1., 0., 0., 0., 0., 0.], # 클래스 6개. Dense 형태
         [0., 1., 0., 0., 0., 0.],
         [0., 0., 0., 0., 1., 0.],
         [0., 0., 1., 0., 0., 0.],
         [0., 0., 0., 1., 0., 0.]]

    hidden_size = 2  # 전개량

    x = np.float32([x]) # dynamic_rnn은 3차원 데이터를 입력으로 요구 함. x: 2차원 -> 3차원

    # RNN layer
    cells = tf.nn.rnn_cell.BasicRNNCell(num_units=hidden_size)
    outputs, _states = tf.nn.dynamic_rnn(cells, x, dtype=tf.float32)

    print(outputs.shape)

    # Softmax layer
    w = tf.Variable(tf.random_uniform([hidden_size, 6]))
    b = tf.Variable(tf.random_uniform([6]))

    # y(5, 6) = x(5, hidden_size) @ w(hidden_size, 6) # w에서 x와 만나는 것은 피처의 개수. 뒤는 class의 개수
    z = tf.matmul(outputs[0], w) + b
    h = tf.nn.softmax(z)

    loss_i = tf.nn.softmax_cross_entropy_with_logits_v2(logits=z, labels=y)
    loss = tf.reduce_mean(loss_i)

    optimizer = tf.train.GradientDescentOptimizer(0.1)
    train = optimizer.minimize(loss)

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())

    for i in range(1000):
        sess.run(train)
        pred = sess.run(z)
        pred_arg = np.argmax(pred, axis=1)
        print(i, sess.run(loss), pred_arg, ''.join(vocab[pred_arg])) #
    print('-' * 50)
    sess.close()


# one-hot encoding 유지한 상태에서 길이가 같은 여러 단어의 다음 글자 prediction
# 개인적으로 y(target, true value)도 one-hot encoding 유지한 것이 더 직관적이고 좋다.
# 아래 나오는 sparse_softmax_cross_entropy_with_logits와 sequence_loss는 과도하게 복잡하고, 최종 결과도 one-hot encoding된 결과이기 때문에, 불필요한 혼란 제거를 위해서는 그냥 y도 one-hot encoding 유지하는게 좋지 않을까.
# 강사님은 왜 굳이 sparse 형태를 사용하려 하는 것일까...

import tensorflow as tf
import numpy as np
from sklearn import preprocessing

def make_onehot(words):
    data = list(''.join(words))
    lb = preprocessing.LabelBinarizer().fit(data)

    xx, yy = [], []
    for text in words:
        onehot = lb.transform(list(text))
        xx.append(onehot[:-1])
        yy.append([onehot[i] for i in range(1,6)])

    return np.float32(xx), np.int32(yy), lb.classes_

def rnn_words(words):
    hidden_size = 5

    x, y, vocab = make_onehot(words)
    batch_size, seq_length, n_classes = x.shape

    cells = tf.nn.rnn_cell.BasicRNNCell(num_units=hidden_size)
    outputs, states_ = tf.nn.dynamic_rnn(cells, x, dtype=tf.float32)

    z = tf.contrib.layers.fully_connected(inputs=outputs,
                                          num_outputs=n_classes,
                                          activation_fn=None)
    h = tf.nn.softmax(z)
    loss = tf.nn.softmax_cross_entropy_with_logits_v2(logits=z, labels=y)

    optimizer = tf.train.AdamOptimizer(0.1)
    train = optimizer.minimize(loss)

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        for i in range(100):
            sess.run(train)
            print(sess.run(loss))

        result = vocab[np.argmax(sess.run(z), axis=2)]
        print([''.join(x) for x in result])
rnn_words(['tensor', 'houses', 'yellow'])


# 가변길이 단어들 RNN 처리. y에 대해 one-hot encoding 유지.
import tensorflow as tf
import numpy as np
from sklearn import preprocessing

def make_onehot(words):
    same_length_words = []
    m = max([len(w) for w in words])
    for w in words:
       w += ' '*(m-len(w))
       same_length_words.append(w)

    data = list(''.join(words))
    lb = preprocessing.LabelBinarizer().fit(data)
    print(lb.classes_)

    xx, yy = [], []
    for w in same_length_words:
        onehot = lb.transform(list(w))
        print("onehot", onehot.shape)
        # (10 = 최대 단어 길이 seq_length, 12개 알파벳 n_classes)
        xx.append(onehot[:-1])
        yy.append(onehot[1:])

    return np.float32(xx), np.int32(yy), lb.classes_

def rnn_multi_words_different_length(words):
    word_length = [len(w) for w in words]

    x, y, vocab = make_onehot(words)
    print("x.shape", x.shape, "y.shape", y.shape, "\n", vocab)
    # (4, 10, 12) (4, 10, 12)
    # ['a' 'c' 'e' 'f' 'h' 'l' 'n' 'o' 'r' 's' 't' 'w']

    hidden_size = 8
    batch_size, seq_length, n_classes = x.shape

    cells = tf.nn.rnn_cell.BasicRNNCell(num_units=hidden_size)
    outputs, state_ = tf.nn.dynamic_rnn(cells, x, dtype=tf.float32,
                                        sequence_length=word_length)

    z = tf.contrib.layers.fully_connected(inputs=outputs,
                                          num_outputs=n_classes,
                                          activation_fn=None)
    print("z.shape", z.shape)
    loss = tf.nn.softmax_cross_entropy_with_logits_v2(logits=z, labels=y)

    optimizer = tf.train.AdamOptimizer(0.1)
    train = optimizer.minimize(loss=loss)

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        for i in range(1000):
          sess.run(train)
          print(sess.run(loss))

        result = ([''.join(x) for x in vocab[np.argmax(sess.run(z) , axis=2)]])
        for w, l in zip(result, word_length):
            print("result ", w[:l-1])


rnn_multi_words_different_length (['sea', 'what', 'corw', 'tensorflow'])



# one-hot label 제거
def rnn_2_3():
    vocab = np.array(['e', 'n', 'o', 'r', 's', 't'])

    # tenso
    x = [[0., 0., 0., 0., 0, 1.],
         [1., 0., 0., 0., 0, 0.],
         [0., 1., 0., 0., 0, 0.],
         [0., 0., 0., 0., 1, 0.],
         [0., 0., 1., 0., 0, 0.]]
    # ensor
    y = [0, 1, 4, 2, 3] # Sparse 형태

    hidden_size = 5  # 전개량

    x = np.float32([x])

    # RNN layer
    cells = tf.nn.rnn_cell.BasicRNNCell(num_units=hidden_size)
    outputs, _states = tf.nn.dynamic_rnn(cells, x, dtype=tf.float32)

    print(outputs.shape)

    # Softmax layer. Fully Connected Layer
    w = tf.Variable(tf.random_uniform([hidden_size, 6]))
    b = tf.Variable(tf.random_uniform([6]))
    z = tf.matmul(outputs[0], w) + b
    h = tf.nn.softmax(z)
    # y(5, 6) = x(5, hidden_size) @ w(hidden_size, 6) # w에서 x와 만나는 것은 피처의 개수. 뒤는 class의 개수

    loss_i = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=z, labels=y)
    loss = tf.reduce_mean(loss_i)

    optimizer = tf.train.GradientDescentOptimizer(0.1)
    train = optimizer.minimize(loss)

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())

    for i in range(1000):
        sess.run(train)
        pred = sess.run(z)
        pred_arg = np.argmax(pred, axis=1)
        print(i, sess.run(loss), pred_arg, ''.join(vocab[pred_arg])) #
    print('-' * 50)
    sess.close()


# Day_03_07_rnn_5_different.py
import numpy as np
import tensorflow as tf
from sklearn import preprocessing


def make_onehot_different(text_array):
    data = list(''.join(text_array))
    lb = preprocessing.LabelBinarizer().fit(data)

    max_len = max([len(t) for t in text_array])

    xx, yy = [], []
    for text in text_array:
        if len(text) < max_len:
            text += '*' * (max_len - len(text))

        onehot = lb.transform(list(text))

        x = onehot[:-1]
        x = np.float32(x)

        y = onehot[1:]
        y = np.argmax(y, axis=1)

        xx.append(x)
        yy.append(list(y))

    return np.float32(xx), tf.constant(yy), lb.classes_


def rnn_5_different(text_array, iteration=100):
    x, y, vocab = make_onehot_different(text_array)

    batch_size, seq_length, n_classes = x.shape
    hidden_size = 2

    seq_len_array = [len(t) for t in text_array]

    cells = tf.nn.rnn_cell.BasicRNNCell(num_units=hidden_size)
    outputs, _states = tf.nn.dynamic_rnn(cells, x, dtype=tf.float32,
                                         sequence_length=seq_len_array)

    # xavier 초기화 사용
    z = tf.contrib.layers.fully_connected(inputs=outputs,
                                          num_outputs=n_classes,
                                          activation_fn=None)

    w = tf.ones([batch_size, seq_length])
    loss = tf.contrib.seq2seq.sequence_loss(logits=z, targets=y, weights=w)

    optimizer = tf.train.AdamOptimizer(0.1)
    train = optimizer.minimize(loss)

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())

    for i in range(iteration):
        sess.run(train)

        pred = sess.run(z)
        pred_arg = np.argmax(pred, axis=2)

        if i % 10 == 0:
            print(i, end=' ')
            for arg, length in zip(pred_arg, seq_len_array):
                valid = vocab[arg]
                print(''.join(valid[:length - 1]), end=' ')
            print()
    print('-' * 50)
    print('ans :', text_array)

    sess.close()


rnn_5_different(['tensor', 'sea', 'white'])


 
# Day_03_08_rnn_final.py
import numpy as np
import tensorflow as tf
from sklearn import preprocessing


def make_onehot_sentence(sentence, seq_length):
    data = list(sentence)
    lb = preprocessing.LabelBinarizer().fit(data)
    print(lb.classes_)

    onehot = lb.transform(data)

    x = np.float32(onehot[:-1])
    y = np.argmax(onehot[1:], axis=1)

    # print(len(sentence))
    # for i in range(len(sentence) - seq_length):
    #     print(i, i + seq_length, sentence[i:i+seq_length])

    idx = [(i, i + seq_length) for i in range(len(sentence) - seq_length)]

    xx = [x[s:e] for s, e in idx]
    yy = [y[s:e] for s, e in idx]

    print(*yy[:5], sep='\n')

    return np.float32(xx), tf.constant(np.int32(yy)), lb.classes_


def rnn_final(sentence, iteration=100):
    x, y, vocab = make_onehot_sentence(sentence, 20)

    batch_size, seq_length, n_classes = x.shape
    hidden_size = 7

    cells = [tf.nn.rnn_cell.BasicRNNCell(num_units=hidden_size) for _ in range(2)]
    multi = tf.nn.rnn_cell.MultiRNNCell(cells)
    outputs, _states = tf.nn.dynamic_rnn(multi, x, dtype=tf.float32)

    # xavier 초기화 사용
    z = tf.contrib.layers.fully_connected(inputs=outputs,
                                          num_outputs=n_classes,
                                          activation_fn=None)

    w = tf.ones([batch_size, seq_length])
    loss = tf.contrib.seq2seq.sequence_loss(logits=z, targets=y, weights=w)

    optimizer = tf.train.AdamOptimizer(0.1)
    train = optimizer.minimize(loss)

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())

    for i in range(iteration):
        sess.run(train)
        print(i, sess.run(loss))
    print('-' * 50)

    pred = sess.run(z)
    print(pred.shape)       # (151, 20, 25)

    pred_arg = np.argmax(pred, axis=2)
    print(pred_arg.shape)   # (151, 20)

    total = '*' + ''.join(vocab[pred_arg[0]])

    for arg in pred_arg[1:]:
        curr = ''.join(vocab[arg])
        # print(curr)

        total += curr[-1]

    print('[{}]'.format(total))
    print('[{}]'.format(sentence))
    sess.close()


sentence = ("if you want to build a ship, "
            "don't drum up people to collect wood and " 
            "don't assign them tasks and work, " 
            "but rather teach them to long for the endless immensity of the sea.")

rnn_final(sentence, 1000)

# if you want to build a ship
# ---------------
# 0 : if you want
# 1 : f you want
# 2 :  you want t
# 3 : you want to
#
# 0 : if you want
# 1 : t to build



# Day_03_10_stock.py
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from sklearn import preprocessing, model_selection

np.set_printoptions(linewidth=1000)


def minmax_scale(data):
    mx = np.max(data, axis=0)
    mn = np.min(data, axis=0)

    return (data - mn) / (mx - mn + 1e-7)


def rnn_stock_1():
    stock = np.loadtxt('Data/stock_daily.csv',
                       delimiter=',', dtype=np.float32)
    stock = stock[::-1]
    # stock = minmax_scale(stock)
    # stock = preprocessing.minmax_scale(stock)
    scaler = preprocessing.MinMaxScaler().fit(stock)
    stock = scaler.transform(stock)
    print(stock[:3])
    print(stock.shape, stock.dtype)     # (732, 5) float32

    x = stock
    y = stock[:, -1:]

    print(y.shape)      # (732, 1)

    seq_length = 7
    n_features = 5      # n_classes
    output_dim = 1
    hidden_size = 10

    x_data, y_data = [], []
    for i in range(len(y) - seq_length):
        x_data.append(x[i:i+seq_length])    # 0~6, 1~7
        y_data.append(y[i+seq_length])      # 7  , 8

        # print(x_data[-1], '->', y_data[-1])

    x_data = np.float32(x_data)
    y_data = np.float32(y_data)

    print("SHAPE:", x_data.shape, y_data.shape)
    cells = tf.nn.rnn_cell.BasicRNNCell(num_units=hidden_size, activation=tf.tanh)
    outputs, _states = tf.nn.dynamic_rnn(cells, x_data, dtype=tf.float32)

    print(outputs.shape, outputs[:, -1].shape)
    z = tf.contrib.layers.fully_connected(inputs=outputs[:, -1],
                                          num_outputs=output_dim,
                                          activation_fn=None)

    loss = tf.reduce_mean((z - y_data) ** 2)

    optimizer = tf.train.AdamOptimizer(0.1)
    train = optimizer.minimize(loss)

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())

    for i in range(100):
        sess.run(train)
        print(i, sess.run(loss))


def rnn_stock_2():
    stock = np.loadtxt('Data/stock_daily.csv',
                       delimiter=',', dtype=np.float32)
    stock = stock[::-1]
    # stock = minmax_scale(stock)
    # stock = preprocessing.minmax_scale(stock)
    scaler = preprocessing.MinMaxScaler().fit(stock)
    stock = scaler.transform(stock)
    print(stock[:3])
    print(stock.shape, stock.dtype)  # (732, 5) float32

    x = stock
    y = stock[:, -1:]

    print(y.shape)  # (732, 1)

    seq_length = 7
    n_features = 5  # n_classes
    output_dim = 1
    hidden_size = 10

    x_data, y_data = [], []
    for i in range(len(y) - seq_length):
        x_data.append(x[i:i + seq_length])  # 0~6, 1~7
        y_data.append(y[i + seq_length])  # 7  , 8

        # print(x_data[-1], '->', y_data[-1])

    x_data = np.float32(x_data)
    y_data = np.float32(y_data)

    # 75:25
    data = model_selection.train_test_split(x_data, y_data, shuffle=False)
    x_train, x_test, y_train, y_test = data

    x_holder = tf.placeholder(tf.float32, [None, seq_length, n_features])

    cells = tf.nn.rnn_cell.BasicRNNCell(num_units=hidden_size, activation=tf.tanh)
    outputs, _states = tf.nn.dynamic_rnn(cells, x_holder, dtype=tf.float32)

    z = tf.contrib.layers.fully_connected(inputs=outputs[:, -1],
                                          num_outputs=output_dim,
                                          activation_fn=None)

    loss = tf.reduce_mean((z - y_train) ** 2)

    optimizer = tf.train.AdamOptimizer(0.1)
    train = optimizer.minimize(loss)

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())

    for i in range(100):
        sess.run(train, {x_holder: x_train})
        print(i, sess.run(loss, {x_holder: x_train}))

    pred = sess.run(z, {x_holder: x_test})

    plt.plot(y_test, 'r')
    plt.plot(pred, 'g')
    plt.show()


# rnn_stock_1()
rnn_stock_1()


print('\n\n\n\n\n\n\n')

2018년 10월 15일 월요일

numpy

import numpy as np

def python_basie():
    a = np.array([[1, 2, 3], [3, 4, 5]])
    print(a[1])

    a, b = 3, 5
    c = 3, 5 # packing

    print(a, b, c)

    d, e = c # unpacking
    print(d, e)

    def f(a, b, c):
        print(a, b, c)

    f(1,2, 3)        # positional
    f(a=3, b=2, c=1) # keyword


# [] : List  : 중간중간 쉼표가 있음.
# [] : numpy.ndarray : 중간중간 쉼표가 없음.
# slicing. List와 ndarray 둘다 동작
def slicing():
    a = range(10)
    print(a)

    a = list(a)
    print(a)

    print(a[0])
    print(a[0:3]) # range()와 동일
    print(a[-1])
    print(a[3:])

    print(a[0:int(len(a) / 2)])
    print(a[int(len(a) / 2):])

    print(a[0:5])
    print(a[5:])

    print(a[:5])
    print(a[5:])
    print(a[:])    # 전체

    print(a[::2])  # 짝수 번째
    print(a[1::2]) # 홀수 번째

    print(a[-1::-1])
    print(a[::-1])

def np_basic():
    a = np.arange(6)
    print(a)
    print(a.shape, a.dtype, a.size, a.ndim)

    b = np.reshape(a, [2,3])
    print(b)

    b = a.reshape([2,3]) # OK
    print(b)

    b = a.reshape((2,3)) # OK
    print(b)

    b = a.reshape(2,3) # OK  python에서 튜플의 ()의 괄호는 생략 가능
    print(b)

    # broadcast 연산
    print(a+1)
    print(a*2)
    print(a/2)
    print(a>2)
    print(a ** 2)
    print(a[a>2]) # a> 2 항목만 뽑아 줌
    print(np.sin(a)) # universal function

    print(b+1)
    print(b*2)
    print(b/2)
    print(b>2)
    print(b ** 2)
    print(b[b>2]) # a> 2 항목만 뽑아 줌
    print(np.sin(b)) # universal function

    print(a+a) # vector operation
    print(b+b)


    a1 = np.arange(3)
    a2 = np.arange(6)
    a3 = np.arange(3).reshape(1,3)
    a4 = np.arange(3).reshape(3,1)
    a5 = np.arange(6).reshape(2,3)

    print("-"*50)
    print("a2", a2)
    print("a3", a3)
    print("a4", a4)
    print("a5", a5)
    print("-"*50)

    # scaler + vector ok : broadcast
    # shape이 다른 vector끼리는 NG !
    # 같은 shape 끼리는 연산 가능 OK ! : vector op
    # 1개 짜리 vector는 scale로 간주함. : broadcast

    # a1+a2 # ng : shape이 다르면 error
    print(a1+a3) # ok  : vector op
    print(a1+a4) # ok  : broadcast + broadcast
    print(a1+a5) # ok  : broadcast + vector op

    #print(a2+a3)
    #print(a2+a4)
    #print(a2+a5)
    #
    print(a3+a4)
    # print(a3+a5)
    #
    #print(a4+a5)

    c = np.arange(12)

    #아래 3가지는 모두 동일
    print(c.reshape(3,4).shape)
    print(c.reshape(-1,4).shape)
    print(c.reshape(3,-1).shape)

    d = c.reshape(3,4)

    # 아래 2가지는 모두 동일
    print(d.reshape(12))
    print(d.reshape(-1))

    np.random.seed(1)
    e = np.random.randint(100, size=12).reshape(3,4)
    print(e)

    print(np.max(e))
    print("axis=0", np.max(e, axis=0)) # 수직
    print("axis=1", np.max(e, axis=1)) # 수평

    print(np.argmax(e))
    print("axis=0", np.argmax(e, axis=0)) # 수직에서 가장 큰 위치 알려 줌
    print("axis=1", np.argmax(e, axis=1)) # 수평에서 가장 큰 위치 알려 줌
 
 
import numpy as np

import tensorflow as tf



a = np.arange(10)

print(a)



# 여러 항목을 한번에 꺼내는 방법

print(a[3], a[9])

# 는 아래와 동일하다. numpy는 "Index 배열" 지원 함.

print(a[[3, 9]]) # []를 하나더 해줘야 한다. 배열 행/열 index와 충돌 피하기 위해.



print("-"*50)



b = np.arange(12).reshape(3,4)

print(b)



print(b[0])

print(b[[0, -1]]) # 2개의 행데이터를 뽑아서 결합하는 방법. Index 배열 사용



print(b[::-1]) # 행 순서 뒤집기

print(b[-1, -1]) # 마지막 데이터.

# "Fancy index"이라 부름. 대괄호 안에 ,를 사용하는 문법. 차원마다 ,가 늘어남.

# 정수, slicing,

print(b[::-1, ::-1]) # 행과 열을 모두 뒤집기.



print(b.T) # transpose



# 문제 : 2차원 배열을 전치 형태로 출력하세요 (반복문, fancy index 사용)

for i in range(b.shape[-1]):

  print(b[:, i])



# 행을 가져오는 것도 사실은 열 인덱싱을 생략한 것.

for i in range(b.shape[0]):

  print(b[i, :])





def show_matmul(s1, s2):

    a = tf.constant(s1, shape=s1)

    b = tf.constant(s2, shape=s2)



    result = tf.matmul(a, b).shape

    print(" {} @ {} = {} ".format(s1, s2, result))



show_matmul([2,3], [3,2]) # 데이터가 아니라 shape을 넘긴 것임.

show_matmul([3,4], [4,2])





show_matmul([7, 2, 3], [7, 3, 2]) # tensorflow의 행렬 2차원까지밖에 없음. 
# 앞의 7은 7번 2차원행렬 연산을 할거란 의미. 2, 3과 3, 2는 매칭되어야 함.


show_matmul([2, 7, 3], [2, 3, 2])



# np squeeze : 의미 없는 차원을 없애 줌. 1차원만 없앨 수 있음. 2차원은 못 없앰.

x = np.array([[[[[0], [1], [2]], [[3], [4], [5]]]]])

print(x)

print(x.shape)



print(x.squeeze(axis=0).shape)

print(x.squeeze(axis=1).shape)

print(x.squeeze(axis=4).shape)

print(x.squeeze().shape) # 모두 한꺼번에 제거



np.random.seed(123)

t = np.random.random_integers(0, 100, 24).reshape(2, 3, 4) # 0~100에서 24개 생성

print("\n")

print(t)

print("\n")

print(np.argmax(t, axis=0), end='\n\n') # 0차원 2개 끼리 비교

print(np.argmax(t, axis=1), end='\n\n') # 1차원 3개 끼리 비교

print(np.argmax(t, axis=2), end='\n\n') # 2차원 4개 끼리 비교 

gradient descent

Single Variable
import matplotlib.pyplot as plt

x = [1, 2, 3]
y = [1, 2, 3]

# y = x  : True function# h(x) = wx : Hyperthesisdef cost(x, y, w):
   sum = 0   for a, b in zip(x, y):
       sum += (w*a - b)**2   return sum/len(x)

def show_cost():
    print(cost(x, y, 0))
    print(cost(x, y, 1))
    print(cost(x, y, 2))

    c = []
    for w in range(-10, 11):
      c.append(cost(x, y, w))

    print(c)
    plt.plot(range(-10, 11), c)
    plt.show()

    # 미분 : 기울기. 순간 변화량    #        x축으로 1만큼 움직일 때, y축으로 움직인 거리    #  y = x  1 = 1, 2 = 2, 3 = 3    #  y = 2x 2 = 1, 4 = 2, 6 = 3

def gradient_descent(x, y, w):
   gd = 0   for a, b in zip(x, y):
       gd += (w*a - b)*a # MSE cost w에 대해 미분시 x, 여기서는 a를 한번 더 곱해 주는 식이 된다.   return gd/len(x)

def update_gradient_descent(init=3, learning_rate=0.2, epoch=20):
   x = [1, 2, 3]
   y = [1, 2, 3]

   w = init
   for i in range(epoch):
       c = cost(x, y, w)
       g = gradient_descent(x, y, w)
       w -= learning_rate * g
       print(i, c)
   return w

w = update_gradient_descent()
print (5*w)
print (7*w)

# 문제 w 1.0으로 만드는 방법. Hyper parameter# 1. step을 올린다.# 2. learning late# 3. 초기값
# x 5 6일 대의 결과를 예측


Multi Variables
x1, x2, x3는 각각 피처. w1, w2, w3는 각각의 비중.
y는 실측

def loss(x1, x2, x3, y, w1, w2, w3):
    c = 0    for x_1, x_2, x_3, y_1 in zip(x1, x2, x3, y):
        c += (x_1*w1 + x_2*w2 + x_3*w3 - y_1) ** 2    
    return c / len(y)

def update_gradient_decent_one(x, y, w):
    d = 0    for x_1, y_1 in zip(x, y):
        d += (x_1*w - y_1)*x_1
    return d

def update_gradient_decent(x1, x2, x3, y, w1, w2, w3):
    w1 = w1 - 0.2 * update_gradient_decent_one(x1, y, w1)
    w2 = w2 - 0.2 * update_gradient_decent_one(x2, y, w2)
    w3 = w2 - 0.2 * update_gradient_decent_one(x3, y, w3)
    return w1, w2, w3

x1 = [1, 4, 5, 8] # 공부 시간
x2 = [3, 4, 7, 9] # 출석 일 수
x3 = [4, 6, 1, 3] # 학습 열정
y = [3, 5, 4, 7] # 성적

w1 = 3
w2 = 4
w3 = 5

for i in range(50):
    w1, w2, w3 = update_gradient_decent(x1, x2, x3, y, w1, w2, w3)
    print(loss(x1, x2, x3, y, w1, w2, w3))

2018년 9월 13일 목요일

TLS1.2 tests

up.mykings.pw:8888/update.txt

www.yahoo.co.jr
[기대] 메인 화면에 주황색 경고 메시지 없어야 함.

https://www.ssllabs.com/ssltest/viewMyClient.html#1532670339319&frame_loaded
[기대]
Your user agent has good protocol support.
Your user agent supports TLS 1.2, which is recommended protocol version at the moment.




2018년 8월 24일 금요일

bayes

Yi.t
t에 하나라도 생산되면 1
아니면 0

제약 조건 추가
Pi.t <= M(큰수) * yi.t


https://stats.stackexchange.com/questions/188319/bayes-theorem-with-multiple-conditions



https://www.analyticsvidhya.com/blog/2016/06/bayesian-statistics-beginners-simple-english/

2018년 7월 1일 일요일

Python matplot

import matplotlib.pyplot as plt

a = 3b = 2c = 1
year = [x for x in range(-100, 100)]
pop  = [x*(a)+b for x in range(-100, 100)]
#pop  = [x*x*x*x*(a)+x*x*b+x*c + d for x in range(-100, 100)]
plt.plot(year,pop)
plt.show()

2018년 6월 29일 금요일

Python RE 2

import re
import statistics
import collections

data = []
f = open("localhost_access_log.2016-04-01.txt", "r" )
for l in f:
    match = re.search("^[\d:.]+", l )
    ip = match.group()

    match = re.search('\[([\w/:]+)', l)
    date = match.group(1)

    match = re.search(' /[\w.-]*', l)
    doc = match.group().strip()

    match = re.search('[\d-]+$', l)
    byte = match.group()
    if (byte == '-'):
        byte = 0    byte = int(byte)
    data.append([ip, date, doc, byte])
f.close()

print("1.전체 로그 출력")
for i in data:
    print("접속ip: {}\n접속일: {}\n요청문서: {}\n바이트크기: {}".format(i[0], i[1], i[2], i[3]))
    print("-"*30)

print("\n2. ip별 접속회수")
ip_list = [n[0] for n in data]
cip = collections.Counter(ip_list)
for i in cip:
   print(i, cip[i],"회")

print("\n3. 문서별 방문회수")
doc_list = [n[2] for n in data]
cdoc = collections.Counter(doc_list)
for i in cdoc:
   print(i, cdoc[i],"회")

print("\n4. 전체전송 바이트 사이즈, 평균 전송 바이트 사이즈, 전송 바이트 사이즈 표준 편차")
byte_list = [n[3] for n in data]
s = sum(byte_list)
m = statistics.mean(byte_list)
d = statistics.stdev(byte_list)
print("전체 전송 바이트 크기: {}\n평균 전송바이트 사이즈: {}\n전송 바이트 사이트 표준편차: {}".format(s,m,d))

print("\n5. 가장 많이 방문한 ip와 방문 회수")
m = cip.most_common(1)
m = m[0]
print(m[0], m[1], "회" )







import re
import collections
from statistics import mean, stdev
fp = open('localhost_access_log.2016-04-01.txt')
data = []
for rd in fp:
    match = re.search('([\d.:]+) \S+ \S+ \[([\w:/]+) \S+\] "\S+ (\S+) \S+" \d+ (\S+)', rd )
    d={}
    d['ip']= match.group(1)
    d['dt']= match.group(2)
    d['view']= match.group(3)
    bsize =  match.group(4)
    bsize = 0 if bsize=='-' else int(bsize)
    d['bsize']= bsize
    data.append( d )

# # 1. 전체 로그 출력# for dt in data:#     print("접속ip:", dt['ip'])#     print("접속일:", dt['dt'])#     print("요청문서:", dt['view'])#     print("바이트크기:", dt['bsize'])#     print("="*10)#2.ipList = [ n['ip'] for n in data]
ipCount = collections.Counter(ipList)
for ip,cnt in ipCount.items():
    print("ip:",ip,"접속횟수:",cnt)

#3.# viewList = [ n['view'] for n in data]# viewCount = collections.Counter(viewList)# for view,cnt in viewCount.items():#     print("페이지:",view,"접속횟수:",cnt)
#4.
print( "전체전송사이즈:", sum([n['bsize'] for n in data] ) )
print( "평균전송사이즈:", mean([n['bsize'] for n in data] ) )
print( "표준편차:", stdev([n['bsize'] for n in data] ) )

#5.mip,cnt  =  ipCount.most_common(1)[0]
print("가장많이 방문ip:", mip, "방문횟수:", cnt )

# print( data )
    # print("ip:", match.group(1) )    # print("dt:",match.group(2) )    # print("view:", match.group(3) )    # print("bsize:", match.group(4) )    # print("="*20)

2018년 6월 28일 목요일

Python PyQt5

PyQt5
pyqt5-tools


from PyQt5.QtWidgets import *
import sys # commandline args
def buttonClicked():
    print("clicked")

app = QApplication(sys.argv)  # Queue 메모리에서 이벤트를 가져 오기 위한 loop
dlg = QDialog()
dlg.setWindowTitle("Hi")
dlg.setGeometry(100, 100, 500, 300)
dlg.show()

layout = QVBoxLayout()
button = QPushButton("클릭")
button.clicked.connect(buttonClicked)
edit   = QLineEdit()

layout.addWidget(button)
layout.addWidget(edit)

dlg.setLayout(layout)

app.exec() # 무한 루프. Queue 메모리 체크print("end...")




from PyQt5.QtWidgets import *
import sys # commandline argsclass MyWindow:
    def __init__(self):
        self.dlg = QDialog()
        self.dlg.setWindowTitle("Hi")
        self.dlg.setGeometry(100, 100, 500, 300)
        self.dlg.show()

        self.layout = QVBoxLayout()
        self.button = QPushButton("클릭")
        self.button.clicked.connect(self.buttonClicked)
        self.edit   = QLineEdit()

        self.layout.addWidget(self.button)
        self.layout.addWidget(self.edit)
        
        self.dlg.setLayout(self.layout)

    def buttonClicked(self):
        print("clicked")

def main():
    app = QApplication(sys.argv)  # Queue 메모리에서 이벤트를 가져 오기 위한 loop    my = MyWindow()
    app.exec() # 무한 루프. Queue 메모리 체크    print("end...")

if __name__ == '__main__':
    main()




from PyQt5.QtWidgets import *
from PyQt5.uic import loadUi # XML UI 정보를 로딩해서 객체를 생성해 줌.import sys

class MyWin:
    def __init__(self):
        self.dlg = loadUi("a.ui")
        self.dlg.show()

        self.dlg.pushButton.clicked.connect(self.buttonClicked)
        self.dlg.radioButton.toggled.connect(lambda : print("toggled"))


    def buttonClicked(self):
        print("clicked")
        # print(self.dlg.lineEdit.setText("dadsd")) # designer에 있는 속성에서 set과 속성 첫글자를 대문자로 바꿔주면 설정 함수이다.(대개)        print(self.dlg.lineEdit.text()) # designeer의 속성 이름에 ()를 붙여주면 값이 넘어 온다.
app = QApplication(sys.argv)
a = MyWin()
app.exec()





from PyQt5.QtWidgets import *
from PyQt5.uic import loadUi # XML UI 정보를 로딩해서 객체를 생성해 줌.import sys

class MyWin:
    def __init__(self):
        self.dlg = loadUi("b.ui")
        self.dlg.show()

        self.dlg.pushButton.clicked.connect(self.buttonClicked)

    def buttonClicked(self):
        print("clicked")
        print(self.dlg.spinBox.value(), self.dlg.spinBox_2.value())
        s = self.dlg.spinBox.value()+self.dlg.spinBox_2.value();
        print(s)
        self.dlg.lineEdit.setText(str(s))

app = QApplication(sys.argv)
a = MyWin()
app.exec()




from PyQt5.QtWidgets import *
from PyQt5.uic import loadUi # XML UI 정보를 로딩해서 객체를 생성해 줌.import sys

class MyWin:
    def __init__(self):
        self.dlg = loadUi("d.ui")
        self.dlg.show()

        self.dlg.pushButton.clicked.connect(self.buttonClicked)
        self.init_widget()

    def init_widget(self):
        self.dlg.listWidget.addItems(['LG1', 'LG2', 'LG3', 'LG4'])
        self.dlg.listWidget.clicked.connect(self.buttonClicked)
        self.dlg.actionMenu2.triggered.connect(self.buttonClicked_menu2)

    def buttonClicked_menu2(self):
        print("buttonClicked_menu2")
        self.pop = loadUi("a.ui")
        #self.pop.show()# show는 modalless. exec는 모달로 구동 함.        self.pop.exec()
        print("hello") # exec로 실행한 경우, dlg가 닫혀야 이 라인이 실행된다.
    def buttonClicked(self):
        print("clicked")
        # print(self.dlg.spinBox.value(), self.dlg.spinBox_2.value())        # s = self.dlg.spinBox.value()+self.dlg.spinBox_2.value();        print(self.dlg.listWidget.currentItem().text())
        self.dlg.lineEdit.setText(self.dlg.listWidget.currentItem().text())

app = QApplication(sys.argv)
a = MyWin()
app.exec()





Python RE

반복 메타 문자 * + ? {} 는 그 앞글자가 몇번 나오는지 설정
match = re.search('ap*le', s1) # p가 0회 이상 반복 되는 것을 찾아 달라. OK : apple, appple, ale.match = re.search('ap+le', s1) # p가 1회 이상 반복 되는 것을 찾아 달라. OK : aple, apple, appple. NG : alematch = re.search("ap?le", s1) # p가 0 또는 1회. OK : ale, aple. NG : apple
match = re.search('ap{2}le', s1) # p가 2번만 반복된 것만 찾는다. OK :apple  NG : aple, appplematch = re.search('ap{2, 5}le', s1) # p가 2번, 또는 3번, 또는 4번 또는 5번 반복된 것만 찾는다. OK :apple, appple, apppple  NG : aple
매칭 메타 문자 . []
match = re.search('ki.i', s1) # .은 개행을 제외한 모든 문자를 허용. OK : kiwi ki3i kixi ki#i ki?i "ki i"   NG : ki\nimatch = re.search('^app', s1)  # ^은 문자열이 주어진 패턴으로 시작하면 매칭 됨. s1이 app로 시작한다면 찾음. NG : ^kiwimatch = re.search("nna$", s1) # $는 문자열이 주어진 패턴으로 끝나는지 확인. s1이 nna로 끝나면 찾음.
match = re.search('[abcxz]pple', s1) # []문자의 집합 중 한문자가 대신할 수 있다. OK : apple, bpple, cpple     NG : dpplematch = re.search('ki[vwx]i', s1) # []문자의 집합 중 한문자가 대신할 수 있다. OK : kiwi kiwwwwi kivwvwvwi    NG kiwwaxximatch = re.search('ki[a-z]i', s1) # []문자 범위   OK : kixi    NG : kiXimatch = re.search('ki[a-z]+i') # OK : kidaljdlkajdklajdlkalkji  NG : kikjklj2i kiWdsdai
match = re.search('서울[시은가]', s2) # OK 서울시 서울은 서울가 NG 서울이match = re.search('서울[가-힣]', s2)  # 모든 한글글자 1개  OK : 서울이 서울락 서울흘  NG: 서울2 서울s
match = re.search('ki[a-zA-Z0-9]+i') # OK : kiai kiZi ki0i    NG: ki#i ki?i
match = re.search('melon|banana') # melon 또는 banana면 됨.match = re.search('melon|ba+na') #
escape \d
match = re.search('ki\di') # ki[0-9]i와 같음. OK : ki0i ki1i ki2imatch = re.search('ki[\da-z]i') # ki[0-9a-z]i와 같음.match = re.search('ki[\da-z. ]') # OK: ki0. 찾아줌
Search는 첫번째 것만 찾아 줌. 매칭 되는 것 다 찾고자 하면 findAll을 써야 함. 그 결과는 list 객체.
match = re.search('app[a-z]+') # app, applicationsList = re.findall('app[a-z]+', s1)

[] 안의 ^은 not 의 의미 임. []밖과 다름.
\D는 [^0-9] 숫자가 아님을 의미

match = re.search('ki\Di')  # OK : ki#a  NG ki5i
\s 화이트 스페이스 (탭, 개행, 스페이스)
match = re.search('ki\si')  # OK : ki i, ki    i
\S 화이트 스페이스가 아닌 것
match = re.search('ki\Si')  # OK : kiwi ki#i ki9i
\w 숫자, 영어 대소문자, _
match = re.search('ki\wi') # ki_i kiwi kiWi ki9i
\W 숫자, 영어, 대소문자, _ 가 아닌 글자.

s3에서 숫자3개-소문자3개
match = re.search('\d{3}-[a-z]{3}', s3)

() 그룹
match = re.search('(\d{3})-([a-z]{3})', s3)
print(match.groups(), match.groups(1), match.groups(2) ,sep='\n')

print(match.group())


# []밖과 안에서 의미가 다른 문자들이 있다.# .는 []밖에서는 줄바꿈을 제외한 모든 문자. []안에서는 그냥 .이다. escape 안해 도 됨.# ^는 []밖에서는 시작점. []안에서 첫자리에 쓰이면 가령 [^OOO] 이면 OOO의 negation이다.
# group은 1번이 첫번째 그룹 괄호를 의미 함.
# ASCII에서 \b는 벨소리임. 그런데 정규식에서도 \b는 공백 escape 의미로 씀.# 때문에 ASCII 코드가 아니라, 정규식 \b 공백으로 하기 위해서는 매칭 앞에 r을 붙여줘야 한다.import re
s1 = "apple kiwi banana appple ale application"s2 = "서울시 은평구"s3 = "123-abc def-ghi jkl-23 566-Abc"s4 = '<a href="test.html"> <img src="my.jpg"> </a> <div> aaa</div>'s5 = 'abc$ 192.168.12.240 --  22^352 [01/Apr/2016:12:39:00 +0900] "GET /bg-middle.png HTTP/1.1" 200 1918's6 =  "aaa bbb.ccc.dd@aa.co.kr 123ffg my_test@my.co.kr"s8 = "sdsadPYTHON like"s9 = "abc\ng"s10 = '''python testprogram hello ppp aaaphone my'''s11 = 'abc#def ghi-jkl'
match = re.search('\d+.\d+.\d+.\d+', s5)
print(match.group())
s = re.sub('app\w+', 'like', s1) # 앞 패턴의 문자들을 뒤 문자열로 바꿔 줌print(s)

my = ['love', 'like', "like", "love"]
cnt = -1def fn(x):
    global cnt
    cnt += 1    return my[cnt]+x.group()

s = re.sub('app\w+', fn, s1)
print(s)

# 함수의 정적 변수 사용하는 방법def fn(x):
    fn.cnt += 1    return my[fn.cnt]+x.group()
fn.cnt = -1  # 함수 선언 밑에 초기 값을 적어 준다.
s = re.sub('app\w+', fn, s1)
print(s)

# match = re.search('href=\"(\w+.?\w+?)\"', s4)match = re.search('\[([\w/:]+)', s5)
match = re.search('GET /(\S+)', s5)
match = re.search('\d+$', s5)
ml = re.findall('[\d^]+', s5)
ml = re.findall('\w+$', s5)
print(ml)

match = re.search("pY", s8, re.I) # Ignore casematch = re.search("abc.g", s9, re.DOTALL) # .이 개행까지 대신할 수 있게 함.match = re.search(r"^p\w+\s+\w+", s10, re.M) # ^는 전체 문자열의 시작을 의미하지만, re.M을 추가하면 각 라인별 시작으로 바꿔 줌.
com = re.compile("app\w+")  # 같은 패턴을 다른 스트링에 적용하고자 할 때는 미리 컴파일 해 둔 것을 사용하면, 속도가 더 빠름.match = com.search(s1)

s = re.split("[# -]", s11) # 주어진 문자들로 스트링을 잘라 냄.print(s)

if match:
  print(match.group())
else:
  print("not found")

fi = re.finditer('app\w+', s1) # match 객체 generator를 돌려 줌.fi = re.finditer('(\S+)@\S+', s6) # match 객체 generator를 돌려 줌.ml = re.findall('(\S+)@\S+', s6) # match 객체 generator를 돌려 줌. 첫번째 항목의 group list를 돌려 줌.
for i in fi:
    print(i.group(1))

# if match:#   print(match.group())# else:#   print("not match")
# try:#     반복 메타 문자 * + ? {} 는 그 앞글자가 몇번 나오는지 설정#     match = re.search('ap*le', s1) # p가 0회 이상 반복 되는 것을 찾아 달라. OK : apple, appple, ale.#     match = re.search('ap+le', s1) # p가 1회 이상 반복 되는 것을 찾아 달라. OK : aple, apple, appple. NG : ale#     match = re.search("ap?le", s1) # p가 0 또는 1회. OK : ale, aple. NG : apple##     match = re.search('ap{2}le', s1) # p가 2번만 반복된 것만 찾는다. OK :apple  NG : aple, appple#     match = re.search('ap{2, 5}le', s1) # p가 2번, 또는 3번, 또는 4번 또는 5번 반복된 것만 찾는다. OK :apple, appple, apppple  NG : aple##     매칭 메타 문자 . []#     match = re.search('ki.i', s1) # .은 개행을 제외한 모든 문자를 허용. OK : kiwi ki3i kixi ki#i ki?i "ki i"   NG : ki\ni#     match = re.search('^app', s1)  # ^은 문자열이 주어진 패턴으로 시작하면 매칭 됨. s1이 app로 시작한다면 찾음. NG : ^kiwi#     match = re.search("nna$", s1) # $는 문자열이 주어진 패턴으로 끝나는지 확인. s1이 nna로 끝나면 찾음.##     match = re.search('[abcxz]pple', s1) # []문자의 집합 중 한문자가 대신할 수 있다. OK : apple, bpple, cpple     NG : dpple#     match = re.search('ki[vwx]i', s1) # []문자의 집합 중 한문자가 대신할 수 있다. OK : kiwi kiwwwwi kivwvwvwi    NG kiwwaxxi#     match = re.search('ki[a-z]i', s1) # []문자 범위   OK : kixi    NG : kiXi#     match = re.search('ki[a-z]+i') # OK : kidaljdlkajdklajdlkalkji  NG : kikjklj2i kiWdsdai##     match = re.search('서울[시은가]', s2) # OK 서울시 서울은 서울가 NG 서울이#     match = re.search('서울[가-힣]', s2)  # 모든 한글글자 1개  OK : 서울이 서울락 서울흘  NG: 서울2 서울s##     match = re.search('ki[a-zA-Z0-9]+i') # OK : kiai kiZi ki0i    NG: ki#i ki?i##     match = re.search('melon|banana') # melon 또는 banana면 됨.#     match = re.search('melon|ba+na') ###     escape \d#     match = re.search('ki\di') # ki[0-9]i와 같음. OK : ki0i ki1i ki2i#     match = re.search('ki[\da-z]i') # ki[0-9a-z]i와 같음.#     match = re.search('ki[\da-z. ]') # OK: ki0. 찾아줌##     Search는 첫번째 것만 찾아 줌. 매칭 되는 것 다 찾고자 하면 findAll을 써야 함. 그 결과는 list 객체.#     match = re.search('app[a-z]+') # appa, application#     sList = re.findall('app[a-z]+', s1)##     [] 안의 ^은 not 의 의미 임. []밖과 다름.#     \D는 [^0-9] 숫자가 아님을 의미##     match = re.search('ki\Di')  # OK : ki#a  NG ki5i##     \s 화이트 스페이스 (탭, 개행, 스페이스)#     match = re.search('ki\si')  # OK : ki i, ki    i##     \S 화이트 스페이스가 아닌 것#     match = re.search('ki\Si')  # OK : kiwi ki#i ki9i##     \w 숫자, 영어 대소문자, _#     match = re.search('ki\wi') # ki_i kiwi kiWi ki9i##     \W 숫자, 영어, 대소문자, _ 가 아닌 글자.##     s3에서 숫자3개-소문자3개#     match = re.search('\d{3}-[a-z]{3}', s3)##     () 그룹#     match = re.search('(\d{3})-([a-z]{3})', s3)#     print(match.groups(), match.groups(1), match.groups(2) ,sep='\n')##     print(match.group())#     #print(sList)# except Exception as err:#     print("not found")