패스트캠퍼스 - 딥러닝을 활용한 자연어생성

패캠 강의 듣고 영한/한영 번역기 만들어 본 후기

개발결과





내가 영한/한영 번역기 개발했다!!!

물론 강의 그대로 따라함 ㅎㅎ

수강후기1(말이쁘게하자)

 수업을 통해서 정말로 흥미로운 경험을 쌓을  있었습니다. 

Seq2Seq나 기계번역과 같은 개념들뿐만 아니라,

실제로 적용해보면서 자연어생성에 대해 어떻게 학습하는지에 대한 감을 잡을  있었어요.

특히 Transformer에 대한 깊은 내용도 다루어서 이론과 실습을 연결짓는데  도움이 되었어요.

수강후기2(찐)

영문으로  데이터가 하도 많아서 구x, 파x고 번역기 쓰고 있는데 이게 웬걸 사용량 제한이 있네...

어디 오픈소스 없나 하고 구글링 한참해보는데 있을리가 없고...(물론 내가 못찾았을 가능성도 크지만)

자연어처리 ()기현 강사님의 '딥러닝을 활용한 자연어생성' 강의가 있네 근데 기계번역 다루네 개꿀!

바로 결제하고 강의를 집중해서 들으면서 실습을 충실히 진행하였습니다. 

물론 이번에 얻은 RTX 4090 테스트 해보고 싶었기에 약간의 파라미터 조정은 있었지만 결과는 대만족!!

 번역  잘한다 ㅎㅎ 

앞으로의 목표1(말이쁘게하자)

앞으로의 목표는  수업에서 얻은 지식을 기반으로 실무에서 

능숙한 자연어처리 엔지니어가 되는 것이에요.

새로운 기술과 도전에 대비하면서도 동시에 기술 발전에 기여하고 싶어졌어요 ㅎㅎ

앞으로의 목표2(찐)

이제 영어 말고도 일본어 중국어 아시아어 등등 데이터 AI-Hub에 공개해뒀던데

이것도 되려나? 되면 무엇을 번역해볼까 ㅎㅎ

Python 생산성 향상을 위한 지름길

지름길, 커맨드 라인, 그리고 패키지

for문에서 번호를 생성하거든 enumerate 함수를 사용하는 것이 더 좋다.

# 안좋은 예시
beat_list = ['John', 'Paul', 'George', 'Ringo']
for i in range(len(beat_list)):
    print(i, '. ', beat_list[i])

# 좋은 예시
beat_list = ['John', 'Paul', 'George', 'Ringo']
for i, name in enumerate(beat_list, 1):
    print(i, '. ', name)

다중 대입 / 튜플 대입을 사용한다.

# 다중 대입
a = b = c = d = e = 0

# 튜플 대입
a, b = 1, 0

def fibo(n):
    a, b = 1, 0

    while a <= n:
        print(a, end= ' ')
        a, b = a + b, a

# 고급 튜플 대입
a, *b = 2, 4, 6, 8  # a = 2, b = [4, 6, 8]

리스트와 문자열 ‘곱하기’를 사용한다.

my_list = [0] * 1000

trip_list = [1, 2, 3] * 100
len(trip_list)  # 300

divider_str = '_' * 40

루프와 else 키워드를 사용한다.

# 루프와 else는 try-except 문법으로 사용될 수 있다.
# 루프와 함께 사용한 else는 루프가 break 문을 만나서 일찍 빠져나오지 않았을 때 실행된다.
def find_divisor(n, max):
    for i in range(2, max + 1):
        if n % i == 0:
            print(i, '은/는', n, '의 약수이다.')
            break
    else:
        print('약수를 찾지 못했습니다.')

불리언과 ‘not’의 이점을 활용한다.

# 안좋은 예시
if len(my_str) == 0:
    break

# 좋은 예시
if not my_str:
    break

연결된 비교 연산자를 사용한다.

a, b, c = 5, 10, 15
if 0 < a <= c > b > 1:
    print('모든 비교 연산은 True')

함수 테이블(딕셔너리)로 switch 문을 모방한다.

menu_dict = {'load':load_fn, 'save':save_fn, 'exit':exit_fn, 'update':update_fn}
(menu_dict[selector])()  # 함수 호출

is 연산자는 정확하게 사용한다.

s1 = 'a b c d e f'
s2 = 'a b c' + ' d e f'
s1 == s2  # True
s1 is s2  # False

단일 행 for 루프를 사용한다.

# for 변수 in 나열식_데이터: 블록문
for i in range(10): print(i, end=' ')

여러 문장을 하나의 행으로 줄인다.

for i in range(5): n = i * 2; m = 5; print(n+m, end=' ')

a = 1; b = 2; c = a + b; print(c)

# 참_표현식 if 조건문 else 거짓_표현식
cell = 'X' if turn % 2 else '0'

큰 번호 안에 언더스코어(_)를 넣는다.

# 안좋은 예시
CEO_salary = 1500000

# 좋은 예시
CEO_salary = 1_500_000

doc string을 작성하고 사용한다.

# doc string은 함수나 클래스 모두에서 등장할 수 있다.

def quad(a, b, c):
    '''Quadratic Formula function.

    This function applies the Quadratic Formula
    to determine the roots of x in a quadratic
    equation of the form ax^2 + bx + c = 0.
    '''
    determin = (b * b - 4 * a * c) ** .5
    x1 = (-b + determin) / (2 * a)
    x2 = (-b - determin) / (2 * a)
    return x1, x2

help(quad)

# 커멘트 라인에서 실행 (queens.py 모듈의 도움말 확인)
# python -m pydoc queens

제너레이터

# 제너레이터 = 이터레이터를 만드는 가장 쉬운 방법
def make_evens_gen():
    for n in range(2, 11, 2):
        yield n

my_gen = make_evens_gen()
next(my_gen)  # 2
next(my_gen)  # 4
next(my_gen)  # 6

my_gen = make_evens_gen()
list(my_gen)  # [2, 4, 6, 8, 10]

PyTorch 신경망의 기본 구성요소

Neural Network basic

Matrix Multiplication

import torch
import torch.nn as nn

x = torch.FloatTensor([[1, 2],
                       [3, 4],
                       [5, 6]])
y = torch.FloatTensor([[1, 2],
                       [1, 2]])

x.size(), y.size()      # torch.Size([3, 2]), torch.Size([2, 2])

z = torch.matmul(x, y)
z.size()                # torch.Size([3, 2])


x = torch.FloatTensor([[[1, 2],
                        [3, 4],
                        [5, 6]],
                       [[7, 8],
                        [9, 10],
                        [11, 12]],
                       [[13, 14],
                        [15, 16], 
                        [17, 18]]])
y = torch.FloatTensor([[[1, 2, 2],
                        [1, 2, 2]],
                       [[1, 3, 3],
                        [1, 3, 3]],
                       [[1, 4, 4],
                        [1, 4, 4]]])

x.size(), y.size()      # torch.Size([3, 3, 2]) torch.Size([3, 2, 3])

z = torch.bmm(x, y)     # batch matrix multiplication
z.size()                # torch.Size([3, 3, 3])

How to use GPU

# Convert CUDA tensor - cuda()
x = torch.cuda.FloatTensor(2, 2)
x           # tensor([[0., 0.],
            #         [0., 0.]], device='cuda:0')

x = torch.FloatTensor(2, 2)

d = torch.device('cuda:0')

x = x.cuda(device=d)
x           # tensor([[0., 0.],
            #         [0., 0.]], device='cuda:0')

x.device    # device(type='cuda', index=0)


# Convert CUDA tensor - to()
d = torch.device('cpu')
x = x.to(device=d)          # x = x.cpu()
x           # tensor([[0., 0.],
            #         [0., 0.]])


# Move model from CPU to GPU
linear = nn.linear(2, 2)

linear = linear.cuda()

linear = linear.cpu()

d = torch.device('cuda:0')
linear = linear.to(d)

p = next(linear.parameters())
p.device                    # device(type='cuda', index=0)

list(linear.parameters())   # iteration

PyTorch 유용한 함수들

Pytorch로 시작하는 딥러닝 입문 (2/2)

Useful Methods

import torch

# expand - 주어진 tensor를 복사후 concate
x = torch.FloatTensor([[[1, 2]],
                       [[3, 4]]])
x.size()               # torch.Size([2, 1, 2])

y = x.expand(*[2, 3, 2])
y.size()               # torch.size([2, 3, 2])

y = torch.cat([x, x, x], dim=1)
y.size()               # torch.size([2, 3, 2])


# randperm - 랜덤 함수, index_select와 활용
rt = torch.randperm(10)
rt.size()                # torch.Size([10])
print(rt)                # tensor([1, 9, 6, 4, 0, 7, 3, 5, 2, 8])
 

# argmax - 최대값을 가지고 있는 index를 반환
x = torch.randperm(3**3).reshape(3, 3, -1)
y = x.argmax(dim = -1)

y.size()                    # torch.Size([3, 3])


# topk - topk와 해당 index를 반환 
values, indices = torch.topk(x, k = 1, dim = -1)
values.size()               # torch.Size([3, 3, 1])

values.squeeze(-1).size()   # torch.Size([3, 3])

x.argmax(dim = -1) == indices.squeeze(-1)   # True

values, indices = torch.topk(x, k = 2, dim = -1)
values.size()               # torch.Size([3, 3, 2])


# 정렬하기1 - topk로 정렬
target_dim = -1
values, indices = torch.topk(x, k = x.size(target_dim), largest = True)

# 정렬하기2 - sort로 정렬
values, indices = torch.sort(x, dim = -1, descending = True)


# masked_fill - mask 처리한 곳(True) 채우기
x = torch.FloatTensor([i for i in range(3**2)]).reshape(3, -1)
x.size()                    # torch.Size([3, 3])

mask = x > 4
print(mask)                 # tensor([[False, False, False],
                            #         [False, False,  True],
                            #         [ True,  True,  True]])

y = x.masked_fill(mask, value = -1)
print(y)                    # tensor([[ 0.,  1.,  2.],
                            #         [ 3.,  4., -1.],
                            #         [-1., -1., -1.]])


# Ones and Zeros
torch.ones(2, 3)
torch.zeros(2, 3)

# (기존 Tensor와 연산하기 위해선 아래 방법이 더 유용함)
x = torch.FloatTensor([[1, 2, 3],
                       [4, 5, 6]])
x.size()                    # torch.Size([2, 3])

torch.ones_like(x)          # torch.ones(2, 3)
torch.zeros_like(x)         # torch.zeros(2, 3)

PyTorch 기본

Pytorch로 시작하는 딥러닝 입문 (1/2)

텐서 조작하기

import torch
import numpy as np

# 1차원 텐서, 벡터
t = torch.FloatTensor([0., 1., 2., 3., 4., 5., 6.])

t.dim()   # 1 (rank, 차원)
t.size()  # torch.Size([7]) (shape)


# 2차원 텐서, 행렬
t = torch.FloatTensor([[1., 2., 3.],
                       [4., 5., 6.],
                       [7., 8., 9.],
                       [10., 11., 12.]
                      ])

t.dim()   # 2 (rank, 차원)
t.size()  # torch.Size([4, 3]) (shape)
t[:, 1]   # tensor([2., 5., 8., 11.[) (모든 행, 인덱스가 1인 열)


# 브로드캐스팅
m1 = torch.FloatTensor([[1, 2]])
m2 = torch.FloatTensor([3])       # [3] -> [3, 3]
print(m1 + m2)                    # tensor([[4., 5.]])


# 행렬 곱셈
a = torch.FloatTensor([[1, 2],
                       [3, 4]])
b = torch.FloatTensor([[1, 2],
                       [1, 2]])
c = torch.matmul(a, b)
c                       # tensor([[ 3.,  6.], [ 7., 14.]])

# 차원 변경 뷰(View)
t = np.array([[[0, 1, 2],
               [3, 4, 5]],
              [[6, 7, 8],
               [9, 10, 11]]])
ft = torch.FloatTensor(t)

ft.shape                    # torch.Size([2, 2, 3])
ft.view([-1, 3]).shape      # torch.Size([4, 3])
ft.view([3, -1]).shape      # torch.Size([3, 4])
ft.view([-1, 1, 3]).shape   # torch.Size([4, 1, 3]) 


# 1인 차원 제거 스퀴즈(Squeeze)
ft = torch.FloatTensor([[0], [1], [2]])

ft.shape              # torch.Size([3, 1])
ft.squeeze().shape    # torch.Size([3])


# 1인 차원 추가 언스퀴즈(unsqueeze) - 특정 인덱스에 차원 추가
ft = torch.FloatTensor([[1, 2], [3, 4]])

ft.shape              # torch.size([2, 2])
ft.unsqueeze(2)       # ft.reshape(2, 2, -1) / torch.size([2, 2, 1])


# 타입 캐스팅
lt = torch.LongTensor([1, 2, 3, 4])   # long 타입
lt.float()                            # float 타입 tensor([1., 2., 3., 4.])

bt = torch.ByteTensor([True, False, False, True])
bt          # tensor([1, 0, 0, 1], dtype=torch.unit8)
bt.long()   # tensor([1, 0, 0, 1])


# 연결하기(concatenate)
x = torch.FloatTensor([[1, 2], [3, 4]])
y = torch.FloatTensor([[5, 6], [7, 8]])

torch.cat([x, y], dim=0)
# tensor([[1., 2.],
#         [3., 4.],
#         [5., 6.],
#         [7., 8.]])

torch.cat([x, y], dim=1)
# tensor([[1., 2., 5., 6.],
#         [3., 4., 7., 8.]])

x = torch.FloatTensor([1, 4])
y = torch.FloatTensor([2, 5])
z = torch.FloatTensor([3, 6])


# 연결하기(stack) - unsqueeze(차원추가) 후에 연결

torch.stack([x, y, z])
# tensor([[1., 4.],
#         [2., 5.], 
#         [3., 6.]])

torch.stack([x, y, z], dim=1)
# tensor([[1., 2., 3.],
#         [4., 5., 6.]])

# (큰 행렬을 자르고 붙일때 유용하게 사용하는 방법)
result = []
for i in range(5):
    x = torch.FloatTensor(2, 2)
    result += x

result = torch.stack(result)
result.size()           #torch.Size([5, 2, 2])


# 0 or 1로 채워진 텐서
x = torch.FloatTensor([[0, 1, 2], [2, 1, 0]])

torch.ones_like(x)
# tensor([[1., 1., 1.],
#         [1., 1., 1.]])

torch.zeros_like(x)
# tensor([[0., 0., 0.],
#         [0., 0., 0.]])


# 덮어쓰기 연산
x = torch.FloatTensor([[1, 2], [3, 4]])

x.mul(2.)
x         # tensor([[1., 2.], [3., 4.]])

x.mul_(2.)
x         # tensor([[2., 4.], [6., 8.]])


# 인덱스로 조회하기(index_select)
x = torch.FloatTensor([[[1, 1],
                        [2, 2]],
                       [[3, 3],
                        [4, 4]],
                       [[5, 5],
                        [6, 6]]])

indice = torch.LongTensor([2, 1])
x.size()                # torch.Size([3, 2, 2])

y = x.index_select(dim=0, index=indice)
y.size()                # torch.Size([2, 2, 2])

print(y)                # tensor([[[5., 5.],
                        #          [6., 6.]]
                        #
                        #         [[3., 3.],
                        #          [4., 4.]]])

Python 리스트 기능

리스트 기능 정리

얕은 복사 vs 깊은 복사

a_list = [1, 2, 0, 4, 5] 
b_list = a_list     # 별칭 생성
c_list = a_list[:]  # 얕은 복사

a_list[2] = 3

print(b_list)       # [1, 2, 3, 4, 5]
print(c_list)       # [1, 2, 0, 4, 5]


import copy

a_list = [1, 2, [5, 10]]

b_list = a_list[:]  # 얕은 복사

b_list[0] = 0
b_list[1] = 0
b_list[2][0] = 0
b_list[2][1] = 0

print(a_list)       # [1, 2, [0, 0]]

c_list = copy.deepcopy(a_list)  # 깊은 복사

c_list[0] = 0
c_list[1] = 0
c_list[2][0] = 0
c_list[2][1] = 0

print(a_list)       # [1, 2, [5, 10]]

리스트 함수

len(리스트)
max(리스트)
min(리스트)
reversed(리스트)    # 역순으로 정렬된 이터레이터 반환
sorted(리스트)      # 정렬된 리스트 생성
sum(리스트)         # 모든 항목을 더한 값 반환, 숫자만 가능

리스트 메서드

리스트.append()
리스트.clear()          # 모든 항목 제거
리스트.extend(리스트)     # [1,2,3].extend([4,5]) => [1,2,3,4,5]
리스트.insert(인덱스, )
리스트.revome()       # 값의 첫 인스턴스 제거

리스트.count()        # 인스턴스 개수 반환
리스트.index()        # 값의 인덱스 반환
리스트.pop([인덱스])     # 인덱스의 값 반환 및 제거, default index = -1

리스트.sort([reverse=False])  # reverse=True 하면 정렬한 뒤에 뒤집음
리스트.reverse()        # 현재 순서를 뒤집음

후위표기법(RPN)

연산자를 피연산자 뒤에 위치시키는 언어

# 방법 1
the_stack = []

def push(v):
    the_stack.append(v)

def pop():
    return the_stack.pop()

def main():
    s = input('Enter RPN string: ')
    a_list = s.split()
    for item in a_list:
        if item in '+-*/':
            op2 = pop()
            op1 = pop()
            if item == '+':
                push(op1 + op2)
            elif item == '-':
                push(op1 - op2)
            elif item == '*':
                push(op1 * op2)
            else:
                push(op1 / op2)
        else:
            push(float(item))
    print(pop())


# 방법 2
the_stack = []

def main():
    s = input('Enter RPN string: ')
    a_list = s.split()
    for item in a_list:
        if item in '+-*/':
            op2 = the_stack.pop()
            op1 = the_stack.pop()
            if item == '+':
                the_stack.append(op1 + op2)
            elif item == '-':
                the_stack.append(op1 - op2)
            elif item == '*':
                the_stack.append(op1 * op2)
            else:
                the_stack.append(op1 / op2)
        else:
            the_stack.append(float(item))
    print(the_stack.pop())


# 방법 3
the_stack = []

def main():
    s = input('Enter RPN string: ')
    a_list = s.split()
    for item in a_list:
        if item in '+-*/':
            op2 = the_stack.pop()
            op1 = the_stack.pop()
            the_stack.append(eval(str(op1) + item + str(op2)))
        else:
            the_stack.append(float(item))
    print(the_stack.pop())

Lambda & reduce 함수

import functools

# functools.reduce(fuction, list)
# lambda arguments: return_value

t5 = functools.reduce(lambda x, y: x + y, [1,2,3,4,5])
print(t5)   # 15

List Comprehension

b_list = [i * i for i in a_list]

conditional_list = [i * i for i in a_list if i > 0]

mult_list = [i * j for i in range(3) for j in range(3)]

Python 문자열 기능

문자열 기본 함수 및 메서드 정리

문자열 => 숫자 변환

n = int('10001')
n2 = int('10001', 2)    # 이진수 변환
n8 = int('775', 8)      # 8진수 변환
n16 = int('1E', 16)     # 16진수 변환

문자열 함수

input(프롬프트에 출력할 문자열)     # 문자열 입력을 위한 프롬프트 사용자
len(문자열)
max(문자열)
min(문자열)
reversed(문자열)                # 역순 문자열을 가진 이터레이터 변환
sorted(문자열)                  # 정렬된 문자열을 지닌 리스트 변환

대・소문자 변환 메서드

문자열.lower()
문자열.upper()
문자열.title()      # 'foo foo'.title() =>'Foo Foo'
문자열.swapcase()   # 대소문자를 서로 변경

검색-교체 메서드

문자열.startswith(부분문자열)
문자열.endswith(부분문자열)
문자열.count(부분문자열)
문자열.find(부분문자열)
문자열.index(부분문자열)        # find와 같지만, 예외 발생
문자열.rfind(부분문자열)        # find와 같지만, 오른쪽부터 검색
문자열.replace(기존, 신규 [, 제한횟수])

# 예시
while romstr.startswith('M'):
    amt += 1000             # 합계를 위해 1,000을 더한다
    romstr = romstr[1:]     # 첫번째 문자를 제거

앞뒤 문자 제거 or 맞춤 메서드

문자열.strip(default=' ')
문자열.lstrip()
문자열.rstrip()
문자열.ljust(길이 [, 채우기_문자])      # 왼쪽 자리 맞춤
문자열.rjust(길이 [, 채우기_문자])      # 오른쪽 자리 맞춤
문자열.center(길이 [, 채우기_문자])     # 텍스트를 가운데에 위치
숫자_문자열.zill(길이)                # 숫자 0 codnrl

Pagination


© 2023. All rights reserved.

Powered by Hydejack