강의 복습 내용

  • numpy의 사용법과 함수들
  • 행렬과 벡터의 연산방법
  • 역행렬과 같은 행렬 관련 연산법

얻은 지식

  • numpy
    • numpy로 배열선언
    • numpy관련 함수
    • 행렬 계산 함수
  • 벡터
    • 노름(norm)
    • L1,L2 노름
  • 행렬
  • 선형회귀분석하기

numpy

  • 넘파이
  • numerical python의 약자
    • 선형대수 계산식 파이썬 라이브러리
  • 단순한 행렬 표현은 가능하지만 계산하는데 처리속도등의 문제가 있다.
    • 이를 해결해줌
  • 고성능 과학 계산용 패키지

특징

  • 일반적 list에 비해 빠르고, 메모리 효율적
  • 반복문 없이 데이터 배열 처리지원
  • 선형대수와 관련된 다양한 기능을 제공
  • c,c++,포트란 등의 언어와 통합 가능

설치

conda insall numpy # conda를 이용해 설치

ndarray

  • numpy의 array
  • np.array로 배열 선언 타입은ndarray로 나타난다.
import numpy as np # 일반적으로 np로 호출

#한가지 데이터 type만 넣을 수 있음
  # list와 차이가 있다.
  # dynamic typing not supported
  # c의 array 
test_array = np.array([1,2,4,5],float) 
#np.array 함수를 통해 배열 생성

  • numpy의 array와 python의 list의 차이
    • numpy는 메모리에 연속적으로 차례대로 들어간다.
    • list는 메모리의 위치가 연속적이지 않다.
  • np.array().shape dimension구성을 반환
  • np.array().dtype type을 반환

  • rank에 따라 불리는 이름이 있다.
    • 참고
    • scala, vector, matrix,3-tensor(3rd order tensor)
  • np.ndim(nparray) number of dimension

  • np.array().nbytes 바이트 계산

hadling shape

  • shape가 변경되는 경우가 생김
  • np.array().reshape(변경할모양) shape를 변경, element의 개숫는 동일
    • -1은 알아서 채우라는 표시
  • np.array().flatten() 다차원을 1차원 array로 변환

  • indexing
    • np.array()[0,0]표기법을 제공, matirx에서는 row,column을 의미함

slicing

  • list와 달리 행과 열부분을 나눠서 slicing이 가능함
  • 부분집합 추출할때 유용
    • [row,column]으로 표현됨
    • 1:3이면 마지막은 포함 안됨
    • start:end:step으로 표현
a=np.array([1,2,3,4],[5,6,7,8]],int)

# 전체 row, 2번째 column이상 자르기
a[:,2:]
# 1번 row만, 1부터 3까지의 column만 자르기
a[1,1:3]
# 1번 row부터 3번 row까지만
a[1:3] # column부분은 생략해서

creation function

  • 생성 함수
  • np.arange() range와 같은 효과로 배열을 생성
    • arange(시작,끝,step)으로 생성
  • np.zeros(모양) - 0으로 가득한 ndarray생성
    • np.zeros(shape,dtype,order)
  • np.ones(모양) - 1로 가득한 ndarray생성
    • np.ones(shpae,dtype,order)
  • np.empty(모양) - shape만 주어지고 비어있는 ndarray생성
    • memory initialization이 되지 않음
    • 값을 출력하면 누군가 쓴 값이 보여준다 (엿보기)
    • np.empty(shapte,type)
  • np.something_like(이름)
    • 기존 ndarray의 shape만큼 1,0,empty array를 반환
    • np.ones_like(기존ndarray명) - arrya와 같은 모양으로 1채우기
    • np.zeros_like(기존ndarray명) - arrya와 같은 모양으로 0채우기
    • np.empty_like(기존ndarray명) - arrya와 같은 모양으로 empty한거채우기
  • identity
    • 단위행렬을 생성함
    • np.identity(row길이,dtype)
  • eye
    • 대각선이 1인 행렬(단위행렬과 유사하지만 다름)
    • np.eye(3) 단위행렬과 같은 결과를 보인다.
    • np.eye(row,column,k값 대각선이 시작되는 index)
  • diag
    • 대각 행렬의 값을 추출
    • np.diag(matrix,[k 시작되는 index])
  • random sampling
    • 데이터 분포에 따라 sampling으로 array를 생성
    • (모수,모수,데이터크기)로 들어간다.
    • np.random.uniform(0,1,10).reshap(2,5) - 균등분포
      • 0부터1까지 균등하게 뽑는다.
    • np.random.normal(0,1,10).reshap(2,5 - 정규분포
    • 그외 여러가지 있다.

operation functions

  • array내의 계산
  • axis
    • operation function을 실행할때 기준이 되는 축
    • 2차원일때는 (axix=0,axis=1)과 같이 기준을 추가해줄수있다.
    • 0이면 row기준으로 더하기, 1이면 모든 column기준으로 더하기
  • sum
    • array의 모든 요소를 더하기
    • sum(axis=1)로 axis를 지정할 수 있다.
  • concatenate
    • array를 합치는 함수
    • np.vstack((array,array)) - row붙이기
    • np.hstack((array,array)) - column붙이기
    • concatenate
      • np.concatenate((a,b),axis)로 합친다.

array operation

  • array간의 계산
  • array간의 shape이 같을때 일어나는 연산
    • element-wise operations라고 한다.
    • 같은 위치끼리 연산되는것
    • +,-,*가 가근
  • dot product
    • 행렬 기본연산으로 dot함수 사용
    • a.dot(b) 또는 a @ b로도 표현 가능
  • transpose
    • transpose()또는 T attribute사용
    • a.T를쓰면 행과 열의 위치가 변경된다.
[1,2,3],[4,5,6]
->
[1,4],[2,5],[3,6]
  • broadcasting
    • shape이 다른 배열간 연산 지원
    • 낮은부분이 알아서 퍼져서 계산이 된다.
    • 따로 함수가 있는게 아니라 알아서 채워주는것
    • 예) vector + scalar - scalar가 vector모양으로 알아서 채워서 더해진다.
      • matrix + scalar - 위와 같음 각 요소를 scalar가 더해진다.
      • matrix + vector - 남은자리를 matrix처럼 늘어난다.
        • 대신 vector는 matrix와 열이 같아야한다.

          numpy performance

    • timeit
    • % timeit을 앞에 된다.

comparisons

  • array 는 대소비교도 가능하다
  • all은 모든 배열의 요소가 조건이 참인지
  • any은 배열중 하나라도 조건이 참인지
a = np.array(5)
a<2 # 각각의 array요소마다 진행한다.
# [True,True,False,False,False

np.any(a<2)
# True
np.all(a<2)
# False
  • 같은 크기면 요소간의대소비교 결과를 boolean type으로 반환한다.
  • logical
    • 둘다 boolean type일때
    • np.logical_and(a,b) - 두 배열을 and 연산
    • np.logical_or(a,b)- 두 배열을 or연산
    • np.logical_not(a)- not을 반환
  • np.where
    • 많이 사용됨
    • where(조건,true일때,false일때)-조건에따라 배열을 만든다.
    • where(조건)-조건에 맞는 배열을 반환
  • isnan
    • not a number인지
  • isfinite
    • 유한한지
    • 발산하지 않는지
a=np.arange(10)

np.where(a>4,3,2)
#[2,2,2,2,3,3,3,3,3,3]
np.where(a>4)
#[5,6,7,8,9]

np.isnan(a)#not a number 메모리 값이 존재하지 않을때

np.isfinite(a)#한정되지 않을때 발산하지 않을때
  • argmax,argmin
    • 최대값, 최소값의 index를 반환
    • np.argmax(a)
    • np.argmin(a)
    • np.argsort() 오름차순으로 index값을 반환한다.
a= np.array([1,2,4,5,8,78,23,3])

np.argsort()
#[0,1,7,2,3,4,6,5]

np.argsort()[::-1]#반대
np.argmax(a)
#5

#axis도 적용 가능

boolean, fancy index

  • boolean index
    • 특정 조건에 따른 값을 배열 형태로 추출
    • comparison operation함수들도 사용 가능하다.
    • a[조건]
    • 조건에는 같은 shape여야 한다.
a = np.arange(10)
a[a>3] # 조건이 true인 index의 요소만 추출
#[4,5,6,7,8,9]

  • fancy index
    • index value를 이용해 값 추출
      • 범위를 벗어나면 에러
    • matrix형태도 가능
    • take함수를 사용
a = np.array([2,4,6,8],float)
b = np.array([0,0,1,3,2,1],int)

# b는 무조건 int타입이어야 한다.
# b의 값들은 a의 index범위를 벗어나면 안된다.
a[b]
#[2,2,4,8,6,4]
a.take(b)#위와 같다
#[2,2,4,8,6,4]


numpy i/o

  • text를 읽고 저장하는게 가능
  • np.load(txt)
    • 파일 호출
  • a.astype(int)
    • 형변환
  • np.savetext(파일명, array명, delimiter=",")
    • text형식으로 저장
    • delimiter로 중간마다 넣을 단어를 정할수있다.
  • np.save(이름,arr="저장할 nparray")
    • 객체 형태인 .npy파일로 저장된다.

벡터

벡터란

  • 숫자를 원소로 가지는 리스트 또는 배열
  • 행백터
    • 세로로 된것
\[\begin{matrix} 1\\2\\3 \end{matrix}\]
  • 열백터
    • 가로로 된것
    • T가 표현된다.
\[\begin{matrix} 1&2&3 \end{matrix}\]
  • 공간에서 한 점을 나타낸다.
    • 원점을 기준으로 상대적 위치를 표현
    • 숫자를 곱하면 방향은 그대로면서 길이만 변합니다.
      • 스칼라 곱이라고 함
  • 같은 모양이면 덧셈,뺄셈이 가능
  • 같은 모양일때 곱하는 성분곱
    • 같은 위치의 값끼리 곱해서 나타낸 결과
  • 덧셈이 진행되는 방식
    • 두개의 벡터가 더해질때
    • a가 0을 상대적으로 가는 방향일때, b는 a의 위치를 기준으로 상대적 위치 이동을 표현하게 됩니다.

노름(norm)

  • 원점에서부터의 거리
  • L1-노름
    • 각 성분의 변화량의 절대값을 모두 더하기
  • L2-노름
    • 피타고라스 정리를 이용해 유클리드 거리를 계산하기
  • 노름의 종류에 따라 기하학적 성질이 달라진다.
    • 원이라는 것에서 두가지 노름이 계산하는결과가 다르다.
    • L1은 마름모 형태가 된다.
      • Robust학습, Lasso회귀에 사용
    • L2가 우리가 아는 원 형태로 계산한다.
      • Laplace근사, Ridge 회귀
    • 최적화, 학습방법, 정규화에 사용될 수 있다.
    • 목적에 따라 적절한 노름을 사용
  • 두 백터의 거리계산 방식
    • 백터의 뺄셈을 통해 거리를 계산한다.
  • 두 벡터의 각도 계산
    • 제2 코사인 법칙을 통해 계산이 가능하다.
    • L2 노름으로 계산이 가능
  • 내적
    • 두벡터들을 성분곱 하고, 더한값
    • inner product
    • np.inner(x,y)로 표현가능
  • 내적 해석
    • 정사영(orthogonal projection)된 벡터의 길이
    • X벡터를 Y벡터 기준으로 수직으로 내릴때 생기는 그림자를 의미한다.
    • 그림자의 길이는 코사인 법칙에 의해 \(\Vert x \Vert cos \theta\) 와 같다
    • 내적은 이 그림자의 길이를 \(\Vert y \Vert\) 만큼 조정한값
    • 두 벡터가 얼만큼 유사한가를 측정할때 사용한다.

행렬

행렬이란

  • matrix은 벡터를 원소로 가지는 2차원 배열
    • numpy는 행이 기본 단위
  • i는 행, j는 열
  • Tranpose matrix
    • 행과 열이 바뀐 행렬
    • 표현은 \(X^T = (x_{ji})\)
  • 행렬도 모양이 같으면 덧셈,뺄셈, 성분곱도 가능
  • 스칼라곱도 벡터와 차이없다.
  • 두데이터를 연결하는 연산자(operator)로 이해할 수 있따.
    • 행렬 곱을 통해 벡터를 다른 차원의 공간으로 보낸다.
    • 이때의 행렬을 연산자라고 한다.
    • 데이터에서 패턴을 추출, 데이터 압축할 수 있다.
    • linear transform이라고 한다.

행렬곱셈

  • 두행렬(x,y) 행렬곱셈은 a의 i행과 b의 j열의 내적을 성분으로 가지는 행렬
    • dot계산
    • numpy에서는 @로 표현한다.
  • 행렬 내적np.inner로 계산하면
    • 두 행렬의 각 행끼리의 내적을 성분으로 가지는 행렬을 계산한다.

역행렬

  • 행렬에 행렬곱셈을 통해 항등행렬(대각선으로 1)을 만드는 행렬
  • 행과 열의 숫자가 같아야 한다.
  • \(A^{-1 }\)이라 표현한다.
    • np.linalg.inv(x)로 계산할 수 있다.

유사역행렬(psudo-inverse)

  • 역행렬을 구하지 못할때 사용한다.
  • 무어-펜로스(moore-penrose)역행렬\(A^+\)을 이용한다.
    • np.linalg.pinv(x)로 계산할 수 있다.
    • n>=m으로 행이 큰경우 \(A^+ = (A^TA)^{-1}A^T, A^+ A=I\)가 성립
    • n<=m으로 열이 큰경우 \(A^+ = A^T(AA^T)^{-1}, AA^+=I\)만 성립
Y = np.array([[0,1],[1,-1],[-2,1]])
np.linalg.pinv(Y) @ Y # 항등행렬 비슷하게 계산이 된다.
# 행이 크기때문에 유사역행렬이 앞에서 계산해야한다.

응용1

  • 연립방정식 풀기
  • n<=m으로 식이 해의 개수보다 작거나 같아야 해를 구할 수 있다.
\[\begin{matrix} a_{11}x_1+a_{12}x_2+ \cdots +a_{1m}x_m = b_1 \\ a_{21}x_1+a_{22}x_2+ \cdots +a_{1m}x_m = b_1 \\ \vdots \\ a_{n1}x_1+a_{n2}x_2+ \cdots +a_{nm}x_m = b_n \\ \end{matrix}\]
  • 위의 공식은 Ax = b로 행렬식으로 표현이 된다.
  • \(x=A^+b\)가 돤다
  • n<=m이므로 \(x=A^T(AA^T)^{-1}b\)를 계산하면 된다.

응용2

  • n>=m 경우인 변수보다 식이 더 많은 경우
  • 선형회귀분석
  • np.linalg.pinv를 이용하여 선형 모델로 해석하는 선형회귀식을 찾을 수 있다.
  • 행이 많아서
  • 식은 \(X\beta = \hat y \approx y\)
    • 예측한 \(\hat y\) 와 \(y\)의 L2노름이 최소화할때 예측을 잘했다고 볼 수 있다.
    • \(\beta=(X^TX)^{-1}X^Ty\)로 \(\beta\)를 구하고 y에 근접한 \(\hat y\)를 구할 수 있다.
  • sklearnLinearRegression으로 구할 수 있다.
from sklean.linear_model import LinearRegression
model = LinearRegression
model.fit(X,y)#X는 식, y는 결과

#x_test는 [값1,값2,...값m]으로 X의 열만큼 있는 배열이다.
y_test = model.predict(x_test)#x_test란 값을 넣어서 y_test를 확인
#x_test가 X의 행의 값과 동일하게 넣으면 같은행의 y값이 나온다.


# 역행렬로 근사한 값 구하기
X_ = np.array([np.append(x,[1]) for x in X])# 각 행마다 1을 추가
beta = np.linalg.pinv(X_) @ y # Xb=y일때 b구하기
y_test2 = np.append(x_test,[1]) @ beta 
# 새로운 행인 [...x_test,1]를 append하고, beta를 행렬곱셈으로 예측값 확인
# y_test와 y_test2가 유사하다.



좀더 찾아보기

  • Robust
  • Lasso
  • Lablace
  • Ridge

피어세션 정리

  • numpy
  • isfinite? 언제쯤 사용할지
    • 수렴하지 않을때
      • 경사하강법때 사용할거 같다.
    • m1에서 numpy설치가 어렵다.
  • 굉장히 큰 매트릭스는?
    • list와 numpy의 차이가 무엇일까
  • rnn(자연어처리)
    • 자연어처리 바이블
    • 자연어 처리
  • 이번주할거
    • numpy함수를 실제 딥러닝 코드에서 어떻게 쓰는지 예시 코드 공부

의문사항

  • 선형회귀할때 다시 y_test를 구하려고 intercept항을 추가하는 이유?
    • 이미 model.predict로 구한거 아닌지?