220914

AIVILLAIN·2022년 9월 14일
0

오공완

목록 보기
7/25

딥러닝은 AI나 머신러닝과 동의어가 아님

인공지능은 역사가 깊고 광범위한 분야로 일반적으로 인지 과정을 자동화하기 위한 모든 방법 (사고의 자동화)

머신러닝은 훈련 데이터를 사용하여 자동으로 프로그램(모델)을 개발하는 AI의 특정 하위 분야
데이터를 프로그램으로 바꾸는 과정을 학습이라고 부름

딥러닝은 머신러닝의 여러 종류 중 하나
기하학적 변환 함수들이 번갈아가며 연속적으로 길게 연결된 모델
이 연산들은 층이란 모듈을 구성
전형적인 딥러닝 모델은 층을 쌓아 올린 것
더 일반적으로 층의 그래프
층은 훈련하는 동안 학습되는 가중치라는 파라미터를 가짐
이 가중치에 모델의 지식이 저장됨
학습 과정은 좋은 가중치 값을 찾는 것

딥러닝이 특별한 이유

컴퓨터에서 매우 어렵다고 인식된 다양한 종류의 문제에서 큰 성과를 거둠
특히 이미지, 비디오, 사운드 등에서 유용한 정보를 추출하는 기계 인지 분야
충분한 훈련 데이터가 주어지면 사람이 인식하는 거의 모든 것을 데이터에서 추출할 수 있음
딥러닝이 지각 문제를 해결함

딥러닝이 많은 IT 기업에 엄청난 비즈니스 가치를 제공하고 있음
사람 수준의 음석 인식과 이미지 분류, 스마트 비서, 크게 향상된 기계 번역 등

딥러닝에서 가장 놀라운 점은 단순함
경사 하강법으로 충분히 큰 모수 모델을 충분히 많은 샘플에서 훈련하는 것이 필요한 전부

딥러닝에서 모든 것은 벡터
모델 입력과 타깃이 먼저 벡터로 바뀌어야 함
초기 입력 벡터 공간과 타깃 벡터 공간으로 바꾸는 것
딥러닝 모델의 각 층은 데이터에 간단한 기하학적 변환을 수행하여 통과시킴
모델은 층을 연결하여 복잡한 기하학적 변환을 구성
잘게 쪼개어 보면 단순한 변환의 연결
복잡한 변환이입력 공간을 타깃 공간으로 한 번에 하나의 포인트씩 매핑
변환을 결정하는 파라미터는 층의 가중치
모델이 얼마나 잘 작동하는지를 기반으로 반복적으로 업데이트됨
기하학적 변환의 핵심 특징은 미분 가능해야 한다는 점
(경사 하강법으로 파라미터를 학습하기 위해 필수)
입력에서 출력으로 바뀌는 기하학적 변환이 부드럽고 연속적이어야 함

데이터가 가진 의미를 벡터와 기하학적 공간으로 변환한 후 한 공간에서 다른 공간으로 매핑하는 복잡한 기하학적 변환을 점진적으로 학습
원본 데이터에 있는 모든 형태의 관계를 찾기 위해 충분히 큰 고차원 공간이 필요한 전부

벡터 공간은 컴퓨터 입장에서 계산하기 효율적
지능을 표현하기 위해서는 그래프 같은 다른 데이터 구조가 더 좋음
신경망은 초기에 그래프를 사용하여 의미를 인코딩하려는 아이디어에서 시작됨
층 기반 표현 학습, 계층적 표현 학습, 심층 미분 모델, 기하학적 변환 연결

핵심 기술

  • 처음에는 역전파 개발 이후 20년이 걸렸으나 2012년 이후 많은 연구자가 딥러닝에 참여하면서 갈수록 빨라짐
  • 지각과 관련된 많은 양의 데이터를 사용할 수 있음
    충분히 많은 데이터에서 충분히 큰 모델을 훈련
  • 고성능 병렬 컴퓨터 하드웨어를 값싸게 사용할 수 있음
  • 컴퓨팅 파워를 활용할 수 있는 다양한 소프트웨어 스택이 마련됨

모든 비즈니스에 웹 사이트가 필요하듯 모든 제품이 사용자가 생성한 데이터를 잘 이해할 필요가 있음

이런 미래가 도래하면 아주 쉽게 딥러닝을 사용하도록 도와주고 기초적인 코딩 기술을 가진 사람이라면 누구나 다룰 수 있는 도구가 필요할 것

일반적인 머신 러닝 작업 흐름

머신 러닝 작업 흐름에서 정말 어려운 부분은 종종 모델을 설계하고 훈련하기 전, 혹은 훈련 후 제품 출시까지 있는 것들

예측 대상, 활용 데이터, 성공 지표를 결정하기 위해 문제 영역을 이해하는 것이 성공적인 머신 러닝 어플리케이션을 위한 필수 조건

  • 문제 정의
    어떤 데이터를 사용할 수 있고 예측 대상은?
    데이터가 충분한가?
    데이터셋에 레이블링하기 위해 필요한 시간?
  • 목표 달성을 측정하기 위해 신뢰할 수 있는 방법
    간단한 작업이라면 예측 정확도가 될 수 있지만 많은 경우 문제 영역에 특화된 정교한 지표 필요
  • 모델을 평가하기 위해 사용할 검증 과정 준비
    훈련 세트, 검증 세트, 테스트 세트를 정의
    검증 세트와 테스트 세트의 레이블은 훈련 데이터에 노출되면 안됨
  • 데이터를 벡터화하고 신경망에 잘 맞는 형태로 전처리 (정규화 등)
  • 상식 수준의 기본 모델보다 나은 첫 번째 모델 만듬
    머신 러닝이 주어진 문제를 해결할 수 있는지 확인
  • 하이퍼파라미터를 튜닝, 규제를 추가하여 모델 구조를 점진적으로 개선
    검증 데이터의 성능만 사용하여 조정
    모델이 과대적합된 후 규제를 추가하거나 모델의 크기를 줄임
  • 하이퍼파라미터 튜닝을 하면 검증 세트에 과대적합될 수 있음

주요 네트워크 구조

완전 연결 네트워크, 합성곱 네트워크, 순환 네트워크
각 네트워크 종류는 특정 입력 형식을 의미
네트워크 구조는 데이터의 구조에 대한 가정을 담고 있음
좋은 모델을 탐색하기 위한 가설 공간
데이터 구조와 네트워크 구조의 가정 사이가 잘 맞는지에 따라 주어진 구조가 해당 문제에 잘 작동할지가 크게 좌우

다양한 네트워크 종류는 더 큰 다중 네트워크를 만들기 위해 연결될 수 있음

  • 벡터 데이터 : 완전 연결 네트워크(Dense 층)
  • 이미지 데이터 : 2D ConvNet
  • 사운드 데이터 : 1D ConvNet 혹은 RNN
  • 텍스트 데이터 : 1D ConvNet이나 RNN
  • 시계열 데이터 : RNN이나 1D ConvNet
  • 다른 종류의 시퀀스 데이터 : RNN이나 1D ConvNet
    데이터 순서에 중요한 의미가 있다면 RNN이 더 좋음
  • 비디오 데이터 : 3D ConvNet이나 특성 추출을 담당하는 프레임별 2D ConvNet과 그 뒤를 이어 시퀀스를 처리하는 RNN 혹은 1D ConvNet의 조합
  • 볼륨을 가진 데이터 : 3D ConvNet

완전 연결 네트워크
벡터 데이터를 처리하는 Dense 층을 쌓은 것
입력 특성에 특별한 가정을 두지 않음
한 Dense 층의 모든 유닛이 다른 층의 모든 유닛과 연결되어 있기 때문에 완전 연결이라고 부름
층은 모든 입력 특성 간의 관계를 매핑
2D 합성곱은 이와 다르게 국부적인 관계만 바라봄
범주형 데이터에 많이 사용됨
분류나 회귀 출력을 위해 다른 네트워크의 최종 단계에도 많이 사용됨
이진 분류를 수행하려면 마지막 Dense 층이 하나의 유닛, 시그모이드 활성화 함수를 사용
손실은 binary_crossentropy, 타깃은 0 또는 1

단일 레이블 다중 분류를 수행하려면 마지막 Dense 층이 클래스 개수만큼 유닛을 가져야 하고 softmax 활성화 함수를 사용
타깃을 원-핫 인코딩한다면 categorical_crossentropy
타깃이 정수 숫자라면 sparse_categorical_crossentropy

다중 레이블 다중 분류를 수행하려면 마지막 Dense층이 클래스 개수만큼 유닛을 가져야 하고 시그모이드 활성화 함수를 사용
손실로는 binary_crossentropy, 타깃은 k-핫 인코딩
(scikit-learn의 MultiLabelBinarizer)

연속된 값을 가진 벡터에 대해 회귀를 수행하려면 마지막 Dense 층이 예측하려는 값의 개수만큼 유닛을 가져야 하고 활성화 함수는 사용하지 않음
회귀에는 여러 가지 손실을 사용할 수 있고 가장 널리 사용되는 것은 MSE와 MAE

컨브넷
합성곱 층은 입력 텐서의 여러 위치(패치)에 동일한 기하학적 변환을 적용하여 공간 방향의 지역 패턴을 찾음
이동 불변성을 가진 표현을 만들어 합성곱 층을 데이터 효율적으로 만들고 모듈화
1D, 2D, 3D 등 어느 차원의 공간에도 적용 가능
Conv1D 층을 사용하여 시퀀스(특히 텍스트, 시계열 데이터는 이동 불변 가정을 따르지 않는 경우가 많음)를 처리하고 Conv2D 층을 사용하여 이미지를 처리하고 Conv3D 층을 사용하여 볼륨 데이터를 처리

컨브넷 또는 합성곱 네트워크는 합성곱과 최대 풀링 층이 쌓여 구성됨
풀링 층은 공간 방향으로 데이터를 다운샘플링
특성 맵의 수가 증가함에 따라 적절한 크기로 특성 맵 크기를 유지하여 후속 합성곱 층이 입력에서 더 큰 부분을 볼 수 있게 함
ConvNet은 Flatten 연산이나 전역 풀링 층으로 끝나는 경우가 많음
이 층은 공간 특성 맵을 벡터로 변환
그 뒤에 분류, 회귀를 위한 Dense 층이 이어짐

일반적인 합성곱이 동일하지만 더 빠르고 효율적을로 표현하는 깊이별 분할 합성곱으로 바뀔 것
새로운 네트워크를 처음부터 구축할 때는 깊이별 분할 합성곱을 고려해야 함

SeparableConv2D층은 Conv2D 대신 그대로 바꿀 수 있으며 더 가볍고 빠른 네트워크를 만들고 더 높은 성능을 냄

RNN
순환 신경망은 한 번에 하나의 타임스텝씩 입력 시퀀스를 처리하고 이 과정 동안 상태를 유지
시간 축을 따라 이동 불변성이 없는 패턴을 가진 시퀀스라면 1D 컨브넷 대신 사용하는 것이 바람직

케라스에는 3개의 RNN 층이 있음
SimpleRNN, GRU, LSTM
대부분 실전 어플리케이션에는 GRU나 LSTM을 사용
LSTM이 더 강력하지만 비용이 많이 듬
GRU는 좀 더 간단하고 값싼 LSTM의 대체물로 생각할 수 있음
여러 개의 RNN 층을 겹겹이 쌓으려면 마지막 층 이전 모든 층은 전체 시퀀스를 출력해야 함
추가적인 RNN 층을 쌓지 않는다면 전체 시퀀스 정보가 담긴 마지막 출력만 반환하는 것이 일반적

딥러닝의 가능성

층을 서로 연결하여 어떤 것끼리라도 매핑할 수 있음
적절한 훈련 데이터와 수용할 만한 복잡도가 있는 연속된 기하학적 변환을 통한 매핑이어야 함
기초적인 분류와 회귀 작업은 머신 러닝의 기본

  • 벡터 데이터를 벡터 데이터로 매핑
    • 예측 의학
      환자의 의료 기록으로 미래 건강 예측
    • 행동 타겟팅
      어떤 사용자를 웹 사이트에 오래 머무르게 하는 웹 사이트 속성 탐색
    • 품질 제어
      제조된 상품에서 얻은 데이터를 바탕으로 제품 불량률 예측
  • 이미지 데이터를 벡터 데이터로 매핑
    • 의료 진단 보조
      의료 영상 슬라이드를 사용하여 암 진단 예측
    • 자율 주행 자동차
      자동차 카메라에서 촬영한 비디오 프레임 데이터를 바탕으로 휠 각도 조정
    • 보드게임 AI
      바둑과 체스 게임에서 상대편 말의 움직임을 예측
    • 식단 도우미
      음식 사진을 보고 칼로리 계산
    • 나이 예측
      인물 사진을 보고 나이를 예측
  • 시계열 데이터를 벡터 데이터로 매핑
    • 날씨 예측
      지역별 날씨의 시계열 데이터를 사용하여 특정 지역의 다음 주 날씨 예측
    • 뇌-컴퓨터 인터페이스
      뇌자도 시계열 데이터를 사용하여 컴퓨터 명령 실행
    • 행동 타겟팅
      사용자가 웹 사이트에서 발생시킨 시계열 데이터를 사용하여 제품 구매 확률을 예측
  • 텍스트를 텍스트로 매핑
    • 스마트 답장
      이메일을 보고 가능한 한 줄 답변을 만듬
    • 질문 응답
      질문에 대한 답변을 만듬
    • 요약
      긴 글을 짧게 요약
  • 이미지를 텍스트로 매핑
    • 캡셔닝
      이미지를 보고 이미지의 컨텐츠를 설명하는 짧은 캡션을 만듬
  • 텍스트를 이미지로 매핑
    • 조건부 이미지 생성
      짧은 텍스트 설명에 부합하는 이미지를 생성
    • 로고 생성/선택
      회사의 이름이나 설명에서 회사의 로고를 만듬
  • 이미지를 이미지로 매핑
    • 초고해상도 변환
      작은 크기의 이미지를 고해상도 버전으로 변환
    • 공간 깊이 감지
      실내 이미지를 보고 공간 지도를 만듬
  • 이미지와 텍스트를 텍스트로 매핑
    • 비주얼 QA
      이미지와 이미지 내용에 관한 자연어 질문을 보고 자연어 답변을 만듬
  • 비디오와 텍스트를 텍스트로 매핑
    • 비디오 QA
      짧은 비디오 내용에 관한 자연어 질문을 보고 자연어 답변을 만듬

딥러닝의 한계

제품 관리자가 작성한 소프트웨어 기능 정의서와 개발 팀이 이 요구 사항에 맞추어 개발한 소스 코드로 이루어진 데이터를 수십만 개, 수백만 개 모을 수 있으나 제품 설명서를 보고 소스 코드를 생성하는 딥러닝 모델은 훈련할 수 없음
일반적으로 프로그래밍처럼 논증이 필요하거나 장기 계획을 세워 과학적 방법을 적용하거나 알고리즘을 사용하여 데이터를 조작하는 일은 주입하는 데이터의 양에 상관없이 딥러닝 모델로 달성할 수 없는 영역

한 벡터 공간을 다른 벡터 공간으로 매핑하기 위해 단순하고 연속된 기하학적 변환을 연결한 것이기 때문
한 매니폴드 X에서 다른 매니폴드 Y로 매핑하는 것이 할 수 있는 전부

X에서 Y로 학습 가능한 변환이 있다고 가정
딥러닝 모델은 일종의 프로그램으로 생각할 수 있음
반대로 대부분의 프로그램은 딥러닝 모델로 표현할 수 없음
이런 기하학적 변환은 너무 복잡하거나 학습에 필요한 적절한 데이터가 없기 때문

층을 추가하고 더 많은 훈련 데이터를 사용하여 현재 딥러닝 기술을 증대하는 것은 이 이슈를 표면적으로 조금 완화시킬 뿐
딥러닝 모델이 표현할 수 있는 한계가 있고 대부분의 학습 대상 프로그램은 데이터 매니폴드에 대한 연속된 기하학적 변환으로 나타낼 수 없는 근본적인 문제를 해결할 수는 없음

머신러닝 모델의 의인화 위험

현대 AI에서 오는 실제 위험은 딥러닝 모델이 하는 일을 잘 이해하지 못하고 그 능력을 과대평가 하는 데서 옴
사진을 설명하는 캡션 생성 모델이 성공적으로 훈련될 대 모델이 그림의 내용을 이해하고 캡션을 만들었다고 생각
이런 오해 때문에 훈련 데이터에 있는 이미지와 조금만 달라져도 모델이 완전히 엉뚱한 캡션을 만드는 것을 보고 놀라게 됨
특히 모델이 잘못 분류하도록 고안된 적대적인 샘플을 딥러닝 네트워크에 주입할 때 이런 문제가 두드러짐

딥러닝 모델은 입력을 전혀 이해하지 못함
적어도 사람이 느끼는 것은 아님
우리가 이미지, 소리, 언어를 이해하는 것은 인간의 지각 경험을 통해형성된 것
레이블된 많은 양의 훈련 샘플을 모델에 주입하여 데이터를 사람의 개념에 매핑하는 기하학적 변환을 학습
이 매핑은 사람의 경험에서 학습하여 마음속에 내재된 진짜 모델을 단순하게 흉내낸 것 (거울 속에 비친 흐릿한 이미지와 비슷)

머신러닝 기술자는 항상 이를 기억해야 함
신경망이 수행하는 작업을 이해한다고 믿는 함정에 빠지면 안됨
적어도 사람이 느끼는 방식으로 이해하지 못함
훈련 입력을 훈련 타깃에 일대일로 매핑하는 방식
훈련 데이터에 없는 데이터를 주입하면 엉뚱한 결과를 낼 것

지역 일반화 vs 궁극 일반화

딥러닝 모델이 수행하는 입력-출력 사이의 간단한 기하학적 변환과 사람이 생각하고 배우는 방식 사이에는 근본적인 차이가 있음
사람이 명시적인 훈련 샘플을 사용하는 대신 몸에 배인 경험에서 학습한다는 것만이 아님
학습 과정이 다른 것 이외에도 근본적인 표현 차이가 있음

사람은 심층 네트워크 또는 곤충들처럼 자극과 반응을 즉각 매핑하는 것 이상을 수행
현재 상황과 자기 자신, 다른 사람에 대한 복잡하고 추상적인 모델 구성
이 모델을 사용하여 미래 가능성을 예측하고 장기 계획을 세움
사람은 경험하지 못한 어떤 것을 표현하기 위해 알고 있는 개념을 합침
가상의 일을 다루는 이런 능력은 추상, 추론을 통해 우리 마음속에 있는 모델의 공간을 직접 경험할 수 있는 것 이상으로 확장 (궁금 일반화)
데이터가 조금만 있거나 새로운 데이터가 전혀 없어도 이전에 경험한 적 없는 새로운 상황에 적응하는 능력

심층 신경망이 하는 것과 극명하게 대립
심층 네트워크의 일반화를 지역 일반화라고 칭함
심층 네트워크가 수행하는 입력-출력 매핑은 새로운 데이터가 훈련할 때 보았던 것과 조금만 달라도 납득할만한 결과를 내지 못함

현재 모델은 과거 데이터와 비슷한 환경에만 적용되는 지역 일반화만 수행할 수 있음

numpy 실습코드

Numerical Python

파이썬에서 선형대수 기반의 프로그램을 쉽게 만들 수 있도록 지원하는 대표적인 패키지
루프를 사용하지 않고 대량 데이터의 배열 연산을 가능하게 하므로 빠른 배열 연산 속도를 보장
C/C++과 같은 저수준 언어 기반의 호환 API 제공
기존 C/C++ 기반의 타 프로그램과 데이터를 주고받거나 API를 호출해 쉽게 통합할 수 있는 기능 제공

numpy ndarray 개요

넘파이 모듈 임포트

as np를 통해 약어로 모듈을 표현

넘파이의 기반 데이터 타입은 ndarray
ndarray를 이용해 넘파이에서 다차원 배열을 쉽게 생성하고 다양한 연산을 수행할 수 있음

넘파이 array() 함수는 파이썬의 리스트와 같은 다양한 인자를 입력으로 ndarray로 변환하는 기능 수행
생성된 ndarray 배열의 shape 변수는 ndarray의 크기, 즉 행과 열 수를 튜플 형태로 가지고 있음
ndarray.ndim은 배열의 차원을 리턴

ndarray의 데이터 타입

숫자, 문자열, bool 값 등 모두 가능
숫자의 경우 int(8, 16, 32bit), unsigned int(8, 16, 32bit), float(16, 32, 64, 128bit), complex 타입
ndarray 내의 데이터 타입은 그 연산의 특성상 같은 데이터 타입만 가능
한 개의 ndarray 객체에 int와 float가 함께 있을 수 없음
dtype 속성으로 데이터 타입 확인 가능
다른 데이터 유형이 섞여 있는 리스트를 ndarray로 변경하면 데이터 크기가 더 큰 데이터 타입으로 형 변환을 일괄 적용
데이터값의 타입 변경 시에는 astype() 메서드 사용

ndarray 편리하게 생성

특정 크기와 차원을 가진 ndarray를 연속값이나 0 또는 1로 초기화해 쉽게 생성해야 할 필요가 있는 경우
arange(), zeros(), ones()를 이용
np.arange(start, stop, step)
np.zeros(ones)(shape, dtype) (dtype default는 float64)

ndarray의 차원과 크기를 변경하는 reshape()

ndarray를 특정 차원 및 크기로 변경
지정된 사이즈로 변경이 불가능하면 오류를 발생
인자로 -1을 적용하는 경우가 많음
-1을 인자로 사용하면 원래 ndarray와 호환되는 새로운 shape로 반환

ndarray의 데이터 세트 선택 (Indexing)

  • 특정 데이터만 추출
    원하는 위치의 인덱스 값 지정을 통해 해당 위치 데이터 반환
  • 슬라이싱
    연속된 인덱스 상의 ndarray를 추출
  • 팬시 인덱싱
    일정한 인덱싱 집합을 리스트 또는 ndarray 형태로 지정하여 해당 위치에 있는 데이터의 ndarray 반환
  • boolean 인덱싱
    특정 조건에 해당하는지 여부인 True/False 값 인덱싱 집합을 기반으로 반환

단일 값 추출

ndarray 객체에 해당하는 위치의 인덱스 값을 []안에 입력
-1 인덱스는 맨 뒤의 데이터 값 의미
단일 인덱스를 이용해 ndarray 내의 데이터 값도 간단히 수정 가능
다차원 ndarray에서 단일 값 추출 시 ,(콤마)로 분리된 row, column 위치의 인덱스를 통해 접근
축 기반 연산에서 axis가 생략되면 axis 0을 의미

슬라이싱

: 기호를 이용해 연속한 데이터를 슬라이싱해서 추출할 수 있음
단일 값 추출을 제외한 나머지 인덱싱으로 추출된 데이터세트는 모두 ndarray 타입
시작 인덱스:종료 인덱스 - 1 위치에 있는 데이터의 ndarray를 반환
시작, 종료 인덱스는 생략 가능
시작 인덱스를 종료하면 맨 처음 인덱스인 0으로 간주
종료 인덱스를 생략하면 맨 마지막 인덱스로 간주

팬시 인덱싱

리스트나 ndarray로 인덱스 집합을 지정하면 해당 위치의 인덱스에 해당하는 ndarray 반환

불린 인덱싱

조건 필터링과 검색을 동시에 할 수 있음

행렬의 정렬

np.sort()와 ndarray.sort(), 정렬된 행렬의 인덱스를 반환하는 argsort()

넘파이의 행렬 정렬은 np.sort()와 같이 넘파이에서 sort()를 호출하는 방식과 행렬 자체에서 sort()를 호출하는 방식이 있음
np.sort()의 경우 원 행렬은 그대로 유지한 채 정렬된 행렬을 반환하며 ndarray.sort()는 원 행렬 자체를 정렬한 형태로 변환

기본 오름차순으로 행렬 내 원소 정렬, 내림차순으로 정렬하기 위해서는 [::-1] 적용

행렬이 2차원 이상일 경우 axis 축 값 설정을 통해 로우 방향, 컬럼 방향으로 정렬 수행 가능

원본 행렬이 정렬되었을 때 기존 원본 행렬의 원소에 대한 인덱스를 필요로 할 때 np.argsort()를 이용
np.argsort()는 정렬 행렬의 원본 행렬 인덱스를 ndarray 형으로 반환
numpy의 ndarray는 RDBMS의 TABLE 칼럼이나 DataFrame 칼럼과 같은 메타 데이터를 가질 수 없음
따라서 실제 값과 그 값이 뜻하는 메타 데이터를 별도의 ndarray로 각각 가져야만 함

선형대수 연산

행렬 내적(행렬 곱)

두 행렬 A와 B의 내적은 np.dot()을 이용해 계산이 가능
왼쪽 행렬의 열 개수와 오른쪽 행렬의 행 개수가 동일해야 내적 연산 가능

전치 행렬

원 행렬에서 행과 열의 위치를 교환환 원소로 구성한 행렬

profile
소신있는 오픈마인드

0개의 댓글