PyTorch 뒤에 있는 Python 마법.
24206 단어 machinelearningpythonpytorch
Pytork는 Python의 많은 기본 기능을 이용하여 우리에게 일치하고 깨끗한 API를 제공하였다.본문에서 나는 이러한 원생 특성을 상세하게 설명할 것이다.이런 것들을 배우면 왜 PyTorch에서 어떤 방식으로 일을 하는지 이해하고 제공하는 것을 더욱 잘 활용할 수 있습니다.
분층 마술법
레이어
are some of the basic constructs in PyTorch that we use to build our models. You import the layer and apply them to tensors.
```python
import torch
import torch.nn as nn
x = torch.rand(1, 784)
layer = nn.Linear(784, 10)
output = layer(x)
여기에서 우리는 장량x
의 층을 호출할 수 있기 때문에 그것은 틀림없이 함수일 것이다. 그렇지?nn.Linear()
함수를 반환하시겠습니까?검사 유형을 통해 그것을 검증합시다.>>> type(layer)
<class 'torch.nn.modules.linear.Linear'>
서프라이즈nn.Linear
는 사실상 하나의 클래스이고 층은 이 클래스의 대상이다."What! How could we call it then? Aren't only functions supposed to be callable?"
아니오, 호출 가능한 대상을 만들 수도 있습니다.Python은 클래스에서 만든 대상을 호출할 수 있도록 마술 함수를 사용하는 기본 방법을 제공합니다.
하나의 종류가 하나의 숫자를 배로 늘리는 간단한 예를 봅시다.
class Double(object):
def __call__(self, x):
return 2*x
여기서 우리는 클래스에 마술 방법__call__
을 추가하여 그 어떤 숫자도 배로 전달한다.이 클래스에서 대상을 만들고 호출할 수 있습니다.>>> d = Double()
>>> d(2)
4
또는 상술한 코드는 단행에 조합할 수 있다.>>> Double()(2)
4
파이썬의 모든 내용이 대상이기 때문이다.다음 숫자를 배로 늘리는 함수 예시를 참고하십시오.def double(x):
return 2*x
>>> double(2)
4
심지어 함수도 백그라운드에서 __call__
방법을 호출한다.>>> double.__call__(2)
4
앞으로 패스하는 마술 방법
모델 예제를 살펴보겠습니다. 이 모델은 10개의 출력을 얻기 위해 하나의 완전히 연결된 레이어를 MNIST 이미지에 적용합니다.
import torch.nn as nn
class Model(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 10)
def forward(self, x):
return self.fc1(x)
다음 코드를 숙지해야 합니다.우리는 이 모델이 일부 장량 x에서의 출력을 계산하고 있다.x = torch.rand(10, 784)
model = Model()
output = model(x)
우리는 어떤 장량에서 모델을 직접 호출하면 그 위에서 .forward()
함수를 실행할 수 있다는 것을 안다.이게 어떻게 된 일입니까?이것은 이전 예시의 원인과 같다.우리는 이 종류
nn.Module
를 계승했다.내부적으로는 nn.Module
마술 방법이 있는데 이 방법은 __call__()
호출된다.그래서 우리가 잠시 후에 .forward()
방법을 다시 쓸 때, 그것은 실행된다.# nn.Module
class Module(object):
def __call__(self, x):
# Simplified
# Actual implementation has validation and gradient tracking.
return self.forward(x)
따라서 우리는 직접 장량에서 이 모델을 호출할 수 있다.output = model(x)
# model.__call__(x)
# -> model.forward(x)
데이터 집중의 마술 방법
PyTorch에서는 일반적으로
.forward()
클래스로부터 계승된 사용자 정의 클래스를 만들어서 우리의 훈련과 테스트 데이터 집합을 준비합니다.왜 우리가 방법을 정의할 때 모호한 이름을 사용했는지 생각해 본 적이 있습니까? 예를 들어 Dataset
와__len__
?from torch.utils.data import Dataset
class Numbers(Dataset):
def __init__(self, x, y):
self.data = x
self.labels = y
def __len__(self):
return len(self.data)
def __getitem__(self, i):
return (self.data[i], self.labels[i])
>>> dataset = Numbers([1, 2, 3], [0, 1, 0])
>>> print(len(dataset))
3
>>> print(dataset[0])
(1, 0)
이 방법들은 파이썬의 내장 마술 방법이다.너는 우리가 __getitem__
함수를 어떻게 사용하여 목록과 원조 등 비교할 수 있는 데이터의 길이를 얻는지 안다.>>> x = [10, 20, 30]
>>> len(x)
3
Python은 사용자 정의 클래스len
를 정의하여 __len__
에서 작업할 수 있도록 합니다.예:class Data(object):
def __len__(self):
return 10
>>> d = Data()
>>> len(d)
10
이와 유사하게, 색인 표현을 사용하여 목록과 메타그룹 요소에 접근하는 방법을 알고 있습니다.>>> x = [10, 20, 30]
>>> x[0]
10
파이썬은 마술 방법으로 사용자 정의 클래스에 이런 기능을 제공할 수 있습니다.예:class Data(object):
def __init__(self):
self.x = [10, 20, 30]
def __getitem__(self, i):
return x[i]
>>> d = Data()
>>> d[0]
10
이러한 개념을 통해 이제 내장 데이터 세트(예: MNIST)를 쉽게 이해하고 사용할 수 있습니다.from torchvision.datasets import MNIST
>>> trainset = MNIST(root='mnist', download=True, train=True)
>>> print(len(trainset))
60000
>>> print(trainset[0])
(<PIL.Image.Image image mode=L size=28x28 at 0x7F06DC654128>, 0)
DataLoader의 마술 방법
NIST 디지털 트레이닝 데이터 세트를 위한 데이터 로더를 만듭니다.
from torchvision.datasets import MNIST
from torch.utils.data import DataLoader
import torchvision.transforms as transforms
trainset = MNIST(root='mnist',
download=True,
train=True,
transform=transforms.ToTensor())
trainloader = DataLoader(trainset, batch_size=32, shuffle=True)
이제 순환하지 않고 데이터 캐리어에서 첫 번째 데이터에 직접 접근해 보겠습니다.만약 우리가 색인을 통해 그것을 방문하려고 시도한다면, 이상이 발생할 것이다.>>> trainloader[0]
TypeError: 'DataLoader' object does not support indexing
너는 아마 이미 이렇게 하는 것에 익숙해졌을 것이다.images, labels = next(iter(trainloader))
너는 우리가 왜 기차 적재기를 len()
옆에 싸서 전화하는지 생각해 본 적이 있니?우리 이 수수께끼를 풀자.3개의 요소를 포함하는 목록을 고려합니다
__getitem__
.Python에서는 iter()
함수를 사용하여 next()
에서 교체기를 생성할 수 있습니다.x = [1, 2, 3]
y = iter(x)
교체기를 사용하는 이유는 교체기가 로드 지연을 허용하기 때문에 한 번에 메모리에 하나의 요소만 불러올 수 있기 때문이다.>>> next(x)
1
>>> next(x)
2
>>> next(x)
3
>>> next(x)
StopIteration:
우리는 모든 원소를 얻었다. 우리가 목록의 끝에 도착했을 때, 우리는 x
이상을 얻었다.이런 모델은 우리의 일반적인 기계 학습 작업 절차와 일치한다. 이런 작업 절차에서 우리는 한 번에 메모리에서 소량의 데이터를 얻고 앞뒤로 전달한다.그래서
x
PyTorch에도 이 모델이 포함되어 있다.Python의 클래스로 교체기를 만들기 위해서는 마술 방법
iter
과 StopIteration
을 정의해야 합니다class ExampleLoader(object):
def __init__(self, data):
self.data = iter(data)
def __iter__(self):
return self
def __next__(self):
return next(self.data)
>>> l = ExampleLoader([1, 2, 3])
>>> next(iter(l))
1
여기에서 DataLoader
함수는 같은 대상의 클래스로 되돌아오는 __iter__
마술 방법을 호출합니다.그리고 __next__
함수 호출 클래스의 iter()
마술 방법으로 데이터의 다음 요소를 되돌려줍니다.PyTorch에서 DataLoader의 구현은 다음과 같습니다.
class DataLoader(object):
def __iter__(self):
if self.num_workers == 0:
return _SingleProcessDataLoaderIter(self)
else:
return _MultiProcessingDataLoaderIter(self)
class _SingleProcessDataLoaderIter(_BaseDataLoaderIter):
def __next__(self):
# logic to return batch from whole data
...
따라서 그들은 교체기 생성 부분과 실제 데이터 불러오는 부분을 결합시킨다.__iter__
할 때, 우리가 사용하는 것이 단일한지 여러 개의 워커인지 검사합니다 >>> type(iter(trainloader))
torch.utils.data.dataloader._SingleProcessDataLoaderIter
next()
방법을 정의했다. 우리가 __next__
를 호출할 때, 이 방법은 집합iter()
의 실제 데이터를 되돌려준다images, labels = next(iter(trainloader))
# equivalent to:
images, labels = trainloader.__iter__().__next__()
따라서 우리는 한 차례의 이미지와 라벨을 얻을 수 있다.결론
따라서 우리는 PyTorch가 어떻게 그 API 디자인에서 로컬 Python 자체의 고급 개념을 참고하는지 보았다.나는 이 문장이 이러한 개념의 배후에 있는 신비한 베일을 벗기고 당신이 더 좋은PyTorch 사용자가 되는 데 도움이 되기를 바랍니다.
연결
만약 당신이 이 박문을 좋아한다면, 언제든지 저에게 연락 주십시오. 저는 매주 그곳에서 새로운 박문을 공유할 것입니다.
Reference
이 문제에 관하여(PyTorch 뒤에 있는 Python 마법.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/amitness/the-python-magic-behind-pytorch-159텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)