기계 학습 - 선형 모델(보스턴 주택 가격 예측)

기계 학습 - 선형 모델(보스턴 주택 가격 예측)

인공지능, 머신러닝, 딥러닝의 관계

여기에 이미지 설명 삽입

  • 인공지능(AI)은 인간의 지능을 시뮬레이션, 확장 및 확장하기 위한 이론, 방법, 기술 및 응용 시스템을 개발하는 기술 과학이며, 이 정의는 목표를 제시할 뿐 방법을 제한하지 않습니다.
  • 기계 학습(Machine Learning, ML)은 현재 인공 지능을 달성하는 보다 효과적인 방법입니다.
  • DL(Deep Learning)은 가장 널리 사용되는 기계 학습 알고리즘으로 대부분의 기존 기계 학습 알고리즘을 대체합니다.

기계 학습

기계 학습은 컴퓨터를 사용하여 인간의 학습 행동을 시뮬레이션하거나 구현하여 새로운 지식이나 기술을 습득하고 기존 지식 구조를 재구성하여 지속적으로 성능을 향상시키는 특수 연구입니다.

기계 학습의 구현은 유도 및 추론과 유사한 훈련 및 예측의 두 단계로 나눌 수 있습니다.

  • 귀납: 특정 예에서 일반 법칙을 추상화합니다. 즉, 특정 수의 샘플(알려진 입력 x 및 출력 y)에서 출력 y와 입력 x 간의 관계를 학습합니다.
  • 추론: 특정 사례에 대한 일반 법률에서 결과를 도출합니다. 학습에서 얻은 y와 x의 관계를 기반으로 새로운 x에서 y를 계산합니다.

모델에서 계산한 출력이 실제 장면의 출력과 일치하면 모델이 유효합니다. 모델이 효과적이기 위한 기본 조건은 알려진 샘플에 적합 할 수 있어야 합니다 .

손실함수(Loss) : 모델의 예측값과 실제값의 차이를 측정하는 평가함수

여기에 이미지 설명 삽입

모델의 세 가지 핵심 요소 결정: 모델 가정 , 평가 함수최적화 알고리즘

손실을 최소화하는 것이 모델의 최적화 목표이며 손실을 최소화하는 방법을 최적화 알고리즘이라고 합니다.

기계 학습 작업의 프레임 워크, 학습의 본질은 매개 변수 추정 및 알려지지 않은 목적 함수 fff 훈련 샘플DDD를 기초로, 가설 세트HHH , 학습 알고리즘AA를A는 함수gg를g 이면ggg는 훈련 샘플 DD에 가장D , 함수ggg 는 목적 함수ff에프 .
여기에 이미지 설명 삽입

딥 러닝

현재 대부분의 머신 러닝 작업은 특히 음성, 컴퓨터 비전 및 자연어 처리 분야에서 딥 러닝 모델을 사용하여 해결할 수 있으며 딥 러닝 모델의 효과는 기존 머신 러닝 알고리즘에 비해 크게 향상되었습니다.

머신 러닝과 딥 러닝은 모델 가정, 평가 함수, 최적화 알고리즘이라는 이론적 구조가 일치하며 근본적인 차이점은 가정의 복잡성에 있습니다.

인공 신경망은 다중 신경망 계층(convolutional layer, fully connected layer, LSTM 등)을 포함하며 각 계층에는 많은 뉴런이 포함 됩니다 .

딥 러닝 모델은 입력에서 출력으로의 매핑 함수로 간주할 수 있으며 충분히 깊은 신경망은 이론적으로 어떤 복잡한 함수에도 적합할 수 있습니다. 신경망은 샘플 데이터의 내부 법칙과 표현 수준을 학습하는 데 매우 적합하며 텍스트, 이미지 및 음성 작업에 잘 적용할 수 있습니다.

딥러닝은 인공지능 구현의 기반으로 알려져 있다 .

여기에 이미지 설명 삽입

  • 뉴런

    신경망의 각 노드는 뉴런이라고 하며 가중치 합과 활성화 함수 의 두 부분으로 구성됩니다.

    • 가중 합: 모든 출력의 가중 합
    • 비선형 변환(활성화 함수): 가중 합의 결과가 비선형 함수로 변환되어 뉴런 계산이 비선형 기능을 가질 수 있습니다.
  • 다층 연결

    많은 수의 뉴런이 서로 다른 레이어에 배열되어 함께 연결된 다층 구조를 형성하며 이를 신경망이라고 합니다.

  • 앞으로 계산

    네트워크의 앞에서부터 순서대로 입력에서 출력을 계산하는 프로세스입니다.

  • 계산 그래프

    신경망의 계산 논리를 그래픽으로 표시합니다.

    신경망의 연산 그래프를 수식으로 표현하는 것도 가능하다.
    Y = f 3 ( f 2 ( f 1 ( w 1 ⋅ x 1 + w 2 ⋅ x 2 + . . + b ) . . ) . . . ) Y = f3(f2(f1(w_1 x_1 + w_2 · x_2+ ... + b)...)...)와이=에프 3 ( 에프 2 ( 에프 1 ( 1엑스1+2엑스2+...+) ... ) ... )

신경망은 본질적으로 많은 매개변수가 있는 큰 공식입니다.

보스턴 주택 가격 예측

Python 언어 및 Numpy 라이브러리를 사용하여 신경망 모델 구축

데이터 세트 소개

보스턴 지역의 주택 가격은 많은 요인에 의해 영향을 받는데, 데이터 세트는 주택 가격에 영향을 미칠 수 있는 13가지 요인과 이러한 유형의 주택 평균 가격을 계산하여 13가지 요인을 기반으로 주택 가격을 예측하는 모델을 구축할 것으로 예상됩니다.

여기에 이미지 설명 삽입

예측 문제는 예측 출력의 유형이 연속적인 실제 값인지 이산 레이블인지에 따라 회귀 작업분류 작업 으로 나눌 수 있습니다 .

모델 가정 → \rightarrow 선형 회귀 모델

주택 가격과 다양한 영향 요인 간의 선형 관계를
y = ∑ j = 1 M xjwj + by=\sum_{j=1}^{M}x_jw_j+b로 설명할 수 있다고 가정합니다.와이=j = 1엑스jj+b 모델의 솔루션 프로세스는 알려진 샘플 데이터를 통해 각 wj wj를
맞추는 것입니다.wjbb _b ,wj wjwjbb _b는 각각 선형 모델의 가중치와 편향을 나타냅니다.

1차원의 경우 wj wjwjbb _b 는 직선의 기울기와 절편입니다.

평가 함수 → \rightarrow 평균 제곱 오차

선형회귀모델은 예측된 주택가격과 실제 주택가격의 차이를 측정하기 위해 손실함수(Loss)로 평균제곱오차(Mean Squared Error, MSE)를 사용한다.
MSE = 1N ∑ i = 1N ( Y i ^ − Y i ) 2 MSE = \frac{1}{N}\sum_{i=1}^{N}(\hat{Y_i} - Y_i)^2MSE=N1나는 = 1(와이^-와이)2
각 학습 샘플에 대한 모델의 예측 오차를 합산하고 누적하여 전체 샘플의 정확도를 측정합니다.

손실 함수의 설계는 합리성(물리적 의미)뿐만 아니라 해결의 용이성(해결하기 쉬움)도 고려해야 합니다.

선형 회귀 모델 네트워크 구조

신경망의 표준 구조에서 각 뉴런은 가중치 합과 비선형 변환으로 구성되며, 여러 개의 뉴런이 레이어로 배열되고 연결되어 신경망을 형성합니다.

선형 회귀 모델은 가중치 합만 있고 비선형 변환이 없는 뉴런이며 네트워크를 형성할 필요가 없습니다.

여기에 이미지 설명 삽입

보스턴 주택 가격 예측 작업 구현

다양한 시나리오의 딥러닝 모델은 어느 정도 융통성이 있으며 기본적으로 5단계로 구성됩니다.

  • 데이터 처리

    모델을 읽을 수 있도록 데이터를 읽고 전처리 작업(데이터 확인, 서식 지정 등)을 완료합니다.

  • 모델 디자인

    모델의 가설 공간과 동일한 네트워크 구조 설계

  • 훈련 구성

    모델에서 사용하는 솔루션 탐색 알고리즘 및 옵티마이저를 설정하고 컴퓨팅 리소스를 지정합니다.

  • 교육 과정

    교육 프로세스는 루프에서 호출되며 각 라운드에는 순방향 계산 , 손실 함수(최적화 대상) 역전파의 세 단계가 포함됩니다.

  • 모델 저장

    학습된 모델을 저장하고 모델이 예측할 때 호출

서로 다른 모델을 구축할 때 모델의 세 가지 요소(모델 가정, 평가 함수, 최적화 알고리즘)만 다르고 다른 단계는 기본적으로 동일합니다.

1. 데이터 처리

데이터 처리에는 데이터 가져오기 , 데이터 차원 변환 , 데이터 세트 분할 , 데이터 정규화 처리load_data 함수 캡슐화의 다섯 가지 기본 부분이 포함됩니다 .

데이터가 전처리된 후 모델에서 호출할 수 있습니다.

데이터 가져오기

import numpy as np
import json
# 读取训练数据
datafile = "./work/housing.data"
data = np.fromfile(datafile,sep=" ")

치수 변환

읽은 원본 데이터는 1차원이고 모든 데이터는 서로 연결되어 있으며 차원은 13 xx 를 포함하여 행당 하나의 데이터 샘플(14개 값)이 있는 2차원 행렬을 형성하도록 변환되어야 합니다.x (집값에 영향을 미치는 특성) 및yyy (집 유형의 평균 가격)

feature_names = [
    "CRIM",  "ZN",  "INDUS", "CHAS", "NOX", "RM", "AGE", "DIS", "RAD",
    "TAX", "PTRATIO", "B", "LSTAT", "MEDV"
]

feature_num = len(feature_names)
data = data.reshape([data.shape[0] // feature_num,feature_num])

데이터 세트 파티션

데이터 세트는 훈련 세트와 테스트 세트로 나뉘며 훈련 세트는 모델의 매개변수를 결정하는 데 사용되고 테스트 세트는 모델의 효과를 평가하는 데 사용됩니다 .

# 将80%的数据用作训练集,20%用作测试集
ratio = 0.8
offset = int(data.shape[0]*ratio)
training_data = data[:offset]

데이터 정규화

각 기능 의 값이 0과 1 사이에서 조정되도록 각 기능을 정규화하면 두 가지 이점이 있습니다.

  • 모델 학습이 더 효율적입니다.

  • 기능 이전의 가중치는 예측 결과에 대한 변수의 기여도를 나타낼 수 있습니다.

    각각의 고유값 자체는 정규화 후 동일한 범위를 갖기 때문에

maximums,minimums = training_data.max(axis=0),training_data.min(axis=0)
# 对数据进行归一化处理
for i in range(feature_num):
	data[:,i] = (data[:,i] - minimums[i]) / (maximums[i] - minimums[i])

입력 기능의 정규화는 통합 학습 단계 크기를 미래에 더 적절하게 만들기 위한 것이기도 합니다.

특성 입력이 정규화되면 다른 매개변수에 의한 손실 출력은 비교적 규칙적인 곡선이 되고 학습 속도는 균일한 값으로 설정할 수 있습니다.

특성 입력이 정규화되지 않은 경우 서로 다른 특성에 해당하는 매개변수에 필요한 단계 크기가 일치하지 않습니다. 큰 규모의 매개변수에는 더 큰 단계 크기가 필요하고 작은 크기의 매개변수에는 작은 단계 크기가 필요하므로 통일된 설정이 불가능합니다. 학습 속도.

여기에 이미지 설명 삽입

정규화되지 않은 기능은 다양한 기능 차원에 대해 서로 다른 이상적인 단계 크기를 생성합니다.

load_data 함수로 캡슐화

다음 단계에서 모델을 호출할 수 있도록 위의 데이터 처리 작업을 캡슐화하여 load_data 함수를 형성합니다.

def load_data():
    # 从文件导入数据
    datafile = "./data/housing.data"
    data = np.fromfile(datafile,sep=" ")
    # 每条原始数据包含14项,其中前面13项是影响因素,第14项是相应的房屋价格平均数
    feature_names = [
    "CRIM",  "ZN",  "INDUS", "CHAS", "NOX", "RM", "AGE", "DIS", "RAD",
    "TAX", "PTRATIO", "B", "LSTAT", "MEDV"]

	feature_num = len(feature_names)
    # 将原始数据进行Reshape,变成[N,14]这样的形状
	data = data.reshape([data.shape[0] // feature_num,feature_num])
    # 将原始数据集拆分成训练集和测试集
    # 使用80%的数据做训练,20%的数据做测试
    # 测试集和训练集必须没有交集
    ratio = 0.8
    offset = int(data.shape[0] * ratio)
    # 计算训练集的最大值,最小值
    maximums,minimums = training_data.max(axis=0),training_data.min(axis=0)
    # 对数据进行归一化处理
    for i in range(feature_num):
        data[:,i] = (data[;,i] - minimums[i]) / (maximums[i] - minimums[i])
    # 训练集和测试集的划分
    training_data = data[:offset]
    test_data = data[offset:]
   	return training_data,test_data

2. 모델 설계

모델 설계는 모델의 순방향 계산 프로세스를 실현하는 네트워크 구조 설계라고도 하는 딥 러닝 모델의 핵심 요소 중 하나입니다.

입력 기능 xxx 에는 13개의 벡터,yy가y는 1개의 벡터를 가지며 매개변수 가중치의 모양은13 × 1 13\times113×1

완전한 선형 회귀 공식은 또한 오프셋 bb를 초기화해야 합니다.b , 선형 회귀 모델의 전체 출력은
z = t + bz=t+b 입니다.=+b
특징과 매개변수로부터 출력 값을 계산하는 과정을 순방향 계산이라고 합니다.

기능 및 매개 변수에서 예측 값을 출력하는 계산 프로세스를 완료하는 전달 기능을 구현합니다.

class Network():
    def __init__(self,num_of_weights):
        # 随机产生w的初始值
        # 为了保持程序每次运行结果的一致性,设置固定的随机数种子
        np.random.seed(0)
        self.w = np.random.randn(num_of_weights,1)
        self.b = 0
        
    def forward(self,x):
        # x -> (1,13) , w-> (13,1)
        z = np.dot(x,self.w) + self.b
        return z

3. 교육 구성

모델 설계가 완료된 후 훈련 구성을 통해 모델의 최적값을 찾는 것 , 즉 손실함수를 통해 모델의 품질을 측정하는 것이 필요하다 .

모델별로 xx 계산x 의 영향요인에 해당하는 주택가격은zzz , 실제 데이터의 집값은yyy , 예측 값 zz를 측정하기 위한 일종의 지표가 필요합니다.z 및 참값yy사이의 간격 y .

회귀 문제의 경우 가장 일반적으로 사용되는 측정 방법은 평균 제곱 오차를 지표로 사용하여 모델의 품질을 평가하는 것입니다.
손실 = ( y − z ) 2 손실 = (yz)^2손실 _=( y-)2
손실 손실손실 일반적으로 손실 함수라고 하며 모델의 품질을 측정하는 지표입니다.

평균 제곱 오차는 회귀 문제에서 손실 함수로 자주 사용되며, 분류 문제에서는 교차 엔트로피(Cross-Entropy)가 손실 함수로 자주 사용됩니다.

손실함수의 계산은 각 샘플의 손실함수 값을 고려해야 하기 때문에 단일 샘플의 손실함수를 합산하여 전체 샘플 수로 나누어야 함 NNN
손실 = 1 N ∑ i = 1 N ( yi − zi ) 2 손실 = \frac{1}{N}\sum_{i=1}^{N}(y_i-z_i)^2손실 _=N1나는 = 1( y-)2
Network 클래스에 손실 함수 추가

class Network():
    def __init__(self,num_of_weights):
        # 随机产生w的初始值
        # 为了保持程序每次运行结果的一致性,设置固定的随机数种子
        np.random.seed(0)
        self.w = np.random.randn(num_of_weights,1)
        self.b = 0
        
    def forward(self,x):
        # x -> (1,13) , w-> (13,1)
        z = np.dot(x,self.w) + self.b
        return z
    def loss(self,z,y):
        error = z-y
        loss = np.mean(error * error)
        return loss

4. 교육과정

위 과정은 신경망을 구성하는 과정을 설명한 것으로, 신경망을 통해 예측값과 손실함수의 계산이 완료된다.

모델의 훈련 과정, 매개변수 ww 완성wbbb 의 솔루션입니다 .

학습 과정의 목표는 정의된 손실 함수를 가능한 한 작게 만드는 것, 즉 파라메트릭 솔루션 ww 를 찾는 것입니다.wbbb , 손실 함수가 최소값을 얻도록 합니다.

여기에 이미지 설명 삽입

특정 지점에서 곡선의 기울기가 해당 지점에서 함수 곡선의 미분 값과 같기 때문입니다. 곡선의 극점에서의 기울기는 0, 즉 극점에서 함수의 도함수는 0입니다. 손실 함수가 ww 의 최소값을 얻도록 하십시오.wbbb는 다음 연립방정식의 해가 되어야 합니다.

∂ L ∂ w = 0 \frac{\partial{L}}{\partial{w}} = 0=0

∂ L ∂ b = 0 \frac{\partial{L}}{\partial{b}} = 0=0

샘플 데이터 ( x , y ) (x,y) 가져오기( 엑스 ,y ) w 및 bw 및 b를얻기 위해 위의 방정식으로w b 의 값 이지만 이 접근 방식은 선형 회귀와 같은 간단한 작업에만 유효합니다. 모델이 비선형 변환을 포함하거나 손실 함수가 평균 제곱 오차의 단순한 형태가 아닌 경우 위 공식을 통해 해결하기 어렵습니다.

보다 보편적인 수치해법: 경사하강법

1. 경사하강법(GD)

순방향으로는 풀기 쉽지만 역방향으로는 풀기 어려운 일방향함수(one-way functions)라는 함수가 많으며, 암호학에서 널리 사용됩니다.

콤비네이션 자물쇠의 특징은 키가 맞는지(알려진 xxx,求yyy 는 쉽지만) 암호 잠금 시스템을 획득하더라도 크랙할 수 없는 올바른 비밀 키는 무엇입니까(알려진yyy ,xxx 는 어렵다).

신경망 모델의 손실함수는 일방향 함수로 역으로 풀기가 쉽지 않다.

Gradient descent 방법, 손실 함수의 최소값을 해결하는 실현 아이디어: 현재 매개변수 값에서 가장 낮은 지점에 도달할 때까지 내리막 방향으로 단계적으로.

훈련의 핵심은 ( w , b ) (w,b) 의 집합을 찾는 것입니다.( ,b ) , 따라서 손실 함수LLL은 최소값을 취합니다.

손실 함수 범주 선택: 절대값 오차평균 제곱 오차 의 비교

  • 절대값 오류의 손실 함수, 미분 불가능
  • 평균 제곱 오차의 손실 함수를 미분할 수 있습니다.

평균 제곱 오차에는 두 가지 이점이 있습니다.

  • 곡선의 가장 낮은 점은 미분 가능합니다.
  • 가장 낮은 지점에 가까울수록 곡선의 기울기가 점차 느려지므로 현재 기울기를 통해 가장 낮은 지점에 근접한 정도를 판단하는 데 도움이 됩니다.

매개변수 업데이트 프로세스에서 따라야 할 원칙:

  • 손실 감소 보장
  • 가능한 한 빠른 하락세

그래디언트의 반대 방향은 함수 값이 가장 빠르게 감소하는 방향입니다.

기울기 계산

기울기 계산을 더 간결하게 하기 위해(유도 과정에서 계수 2가 생성됨) 계수 1 2 \frac{1}{2} 가 도입되었습니다.21, 定义损失函数
L = 1 2 N ∑ i = 1 N ( yi - zi ) 2 L = \frac{1}{2N}\sum_{i=1}^{N}(y_i - z_i)^2=2N_ _1나는 = 1( y-)2
경중zi z_iii예측값 zi = ∑ j = 0 12 xij ⋅ wj + b z_i = \sum_{j=0}^{12}x_i^j w_j + b
=j = 012엑스jj+b
최소한정
구배 = ( ∂ L ∂ w 0 , ∂ L ∂ w 1 , . . . , ∂ L ∂ w 12 , ∂ L ∂ b ) 구배 = (\frac{\partial{L}}{\partial{ w_0}},\frac{\partial{L}}{\partial{w_1}},...,\frac{\partial{L}}{\partial{w_{12}}},\frac{\partial {L}}{\부분{b}})그라데이션 _ _ _ _ _ _ _=(0,1,... ,12,) LL을
계산하기 위해 에서 wwwbbb 의 偏导数
∂ L ∂ wj = 1 N ∑ i = 1 N ( zi − yi ) ∂ zi ∂ wj = 1 N ∑ i = 1 N ( zi − yi ) xij \frac{\partial{L}}{\ 부분{w_j}} = \frac{1}{N}\sum_{i=1}^N(z_i-y_i)\frac{\부분{z_i}}{\부분{w_j}}= \frac{1} {N}\sum_{i=1}{N}(z_i-y_i)x_i^jj=N1나는 = 1( -와이)j.=N1나는 = 1 ( -와이) 엑스j

∂ L ∂ b = 1N ∑ i = 1N ( zi − yi ) ∂ zi ∂ b = 1N ∑ i = 1N ( zi − yi ) \frac{\partial{L}}{\partial{b}} = \frac{1}{N}\sum_{i=1}^N(z_i - y_i)\frac{\partial{z_i}}{\partial{b}} = \frac{1}{N}\sum_ {i=1}^{N}(z_i-y_i)=N1나는 = 1( -와이).=N1나는 = 1( -와이)

Numpy의 브로드캐스트 메커니즘으로 인해 계산 프로세스가 더 간결해졌습니다.

다른 관점에서 총 기울기를 고려하십시오.

각 샘플은 기울기에 대한 기여도를 가지며 전체 기울기는 기울기에 대한 샘플 기여도의 평균값입니다
. = 1 N ( zi − yi ) xij \frac{\partial{L}}{\partial{w_j}} = \frac{1}{N}\sum_{i=1}^N(z_i-y_i)\frac {\ 부분{z_i}}{\부분{w_j}}= \frac{1}{N}\sum_{i=1}{N}(z_i-y_i)x_i^jj=N1나는 = 1( -와이)j.=N1나는 = 1 ( -와이) 엑스j
Network 클래스의 그래디언트 기능을 높입니다.

class Network():
    def __init__(self,num_of_weights):
        # 随机产生w的初始值
        # 为了保持程序每次运行结果的一致性,设置固定的随机数种子
        np.random.seed(0)
        self.w = np.random.randn(num_of_weights,1)
        self.b = 0
        
    def forward(self,x):
        # x -> (1,13) , w-> (13,1)
        z = np.dot(x,self.w) + self.b
        return z
    def loss(self,z,y):
        error = z-y
        loss = np.mean(error * error)
        return loss
    def gradient(self,x,y):
        z = self.forward(x)
        gradient_w = (z-y)*x
        gradient_w = np.mean(gradient_w,axis=0)
        gradient_w = gradient_w[:,np.newaxis]
        
        gradient_b = (z-y)
        gradient_b = np.mean(gradient_b)
        return gradient_w,gradient_b

손실 함수가 더 작은 지점을 결정하고 그래디언트 방법을 업데이트하고 그래디언트의 반대 방향으로 작은 단계를 이동합니다.

net.w[5] = net.w[5] - eta *gradient_w5
  • 빼기, 매개 변수는 그라디언트의 반대 방향으로 이동해야 합니다.
  • eta: 그래디언트의 반대 방향, 즉 각 이동의 단계 크기를 따라 각 매개 변수 값의 크기를 제어하며 학습 속도라고 합니다.

Train 함수 캡슐화

학습 및 업데이트 함수에서 순환 계산 프로세스를 캡슐화합니다.

구현 논리: 출력 순방향 계산, 출력 및 실제 값을 기반으로 Loss 계산, Loss 및 입력을 기반으로 기울기 계산, 기울기에 따라 매개변수 값 업데이트

class Network():
    def __init__(self,num_of_weights):
        # 随机产生w的初始值
        # 为了保持程序每次运行结果的一致性,设置固定的随机数种子
        np.random.seed(0)
        self.w = np.random.randn(num_of_weights,1)
        self.b = 0
        
    def forward(self,x):
        # x -> (1,13) , w-> (13,1)
        z = np.dot(x,self.w) + self.b
        return z
    def loss(self,z,y):
        error = z-y
        loss = np.mean(error * error)
        return loss
    def gradient(self,x,y):
        z = self.forward(x)
        gradient_w = (z-y)*x
        gradient_w = np.mean(gradient_w,axis=0)
        gradient_w = gradient_w[:,np.newaxis]
        
        gradient_b = (z-y)
        gradient_b = np.mean(gradient_b)
        return gradient_w,gradient_b
   def update(self,gradient_w,gradient_b,eta=0.01):
    	self.w = self.w - eta*gradient_w
        self.b = self.b - eta*gradient_b
   def train(self,x,y,iterations=100,eta = 0.01):
    	losses = []
        for i in range(iterations):
            z = self.forward(x)
            L = self.loss(z,y)
            gradient_w, gradient_b = self.gradient(x,y)
            self.update(gradient_w,gradient_b,eta)
            losses.append(L)
            if (i+1)%10 == 0:
                print("iter {},loss {}".format(i,L))
        return losses
    
# 获取数据
train_data ,test_data = load_data()
x = train_data[:,:-1]
y = train_data[:,-1:]
# 创建网络
net = Network(13)
num_iterations = 1000
# 启动训练
losses = net.train(x,y,iterations=num_iterations,eta=0.01)

# 画出损失函数的变化趋势
plot_x = np.arange(num_iterations)
plot_y = np.array(losses)
plt.plot(plot_x,plot_y)
plt.show()
2. 확률적 경사하강법

경사하강법에서 각각의 손실함수와 기울기 계산은 데이터 집합의 데이터 전체량을 기준으로 하지만 실제 문제에서는 데이터 집합이 매우 큰 경우가 많다. , 효율성이 매우 낮습니다. 매개변수는 그래디언트의 반대 방향을 따라 한 번에 조금씩만 업데이트되므로 방향이 정확할 필요는 없습니다. 합리적인 해결책은 매번 전체 데이터 집합에서 데이터의 작은 부분을 무작위로 추출하여 전체를 나타내고 이 부분의 데이터를 기반으로 기울기와 손실을 계산하여 매개 변수를 업데이트하는 것입니다.이 방법을 Stochastic Gradient Descent라고합니다. (확률적 경사하강법, SGD)

핵심 아이디어

  • 미니배치: 각 반복에서 추출된 데이터 배치를 미니배치라고 합니다.
  • 배치 크기: 각 미니 배치에 포함된 샘플 수를 배치 크기라고 합니다.
  • Epoch 프로그램이 반복될 때 미니배치에 따라 샘플을 점차적으로 추출 전체 데이터 세트를 순회하면 한 라운드의 훈련이 완료되며, 이를 Epoch(라운드)라고도 합니다. num_epochs 및 batch_size는 매개변수로 전달됩니다.

train_data를 batch_size의 여러 미니 배치로 나눕니다.

batch_size = 10
n = train_data.shape[0]
np.random.shuffle(train_data)
mini_batches = [train_data[k:k+batch_size] for k in range(0,n,batch_size)]

SGD에서는 전체를 나타내기 위해 샘플의 일부를 임의로 선택합니다. 임의 샘플링의 효과를 달성하기 위해 먼저 train_data의 샘플 순서를 임의로 중단한 다음 미니 배치를 추출합니다.

실험 결과 모델은 마지막 데이터에 더 깊은 인상을 받았습니다.교육 데이터를 가져온 후 모델 교육이 끝날수록 모델 매개 변수에 대한 마지막 데이터 배치의 영향이 커집니다.이를 방지하기 위해 모델 메모리가 훈련 효과에 영향을 미치지 않도록 하려면 샘플 작동 순서를 재정렬해야 합니다.

학습 과정에서 무작위로 선택된 각각의 미니배치 데이터가 모델 학습을 위해 모델에 입력됩니다. 학습 과정의 핵심은 2계층 루프입니다.

  • 루프의 첫 번째 레이어는 에포크라고 하는 샘플 세트가 훈련되는 횟수를 나타냅니다.

    for epoch_id in range(num_epochs):
        pass
    
  • 루프의 두 번째 계층은 각 순회 중에 샘플 세트가 분할되고 모든 훈련이 수행되어야 하는 반복(iter(반복))이라는 여러 배치를 나타냅니다.

    for iter_id,mini_batch in emumerate(mini_batches):
        pass
    

    내부 루프는 전형적인 4단계 교육 프로세스입니다.

    1. 앞으로 계산
    2. 손실을 계산하다
    3. 기울기 계산
    4. 매개변수 업데이트
def train(self,training_data,num_epochs,batch_size=10,eta=0.01):
    n= len(training_data)
    losses = []
    for epoch_id in range(num_epochs):
        # 在每轮迭代开始之前,将训练数据的顺序进行随机打乱
        # 然后再按照每次取出batch_size条数据的方式取出
        np.random.shuffle(training_data)
        # 将训练数据进行拆分,每个mini_batch包含batch_size条数据
        mini_batches = [training_data[k:k+batch_size] for k in range(0,n,batch_size)]
        for iter_id,mini_batch in enumerate(mini_batches):
            x = mini_batch[:,:-1]
            y = mini_batch[:,-1:]
            a = self.forward(x)
            loss = self.loss(a,y)
            gradient_w, gradient_b = self.gradient(x,y)
            self.update(gradient_w,gradient_b,eta)
            losses.append(loss)
            print("Epoch {:3d} / iter {:3d},loss = {:.4f}".format(epoch_id,iter_id,loss))
      return losses

Stochastic Gradient Descent는 학습 프로세스의 속도를 높이지만 매개변수만 업데이트하고 매번 적은 수의 샘플을 기반으로 손실을 계산하기 때문에 손실 감소 곡선이 진동하게 됩니다.

신경망으로 모델을 구축하기 위한 세 가지 핵심 사항

  • 네트워크 구축 및 매개변수 ww 초기화wbbb ,예측 및 손실 함수 계산 방법 정의
  • 초기점을 무작위로 선택하고 기울기 계산 방법 및 매개변수 업데이트 방법을 설정합니다.
  • 데이터 셋의 데이터를 batch_size의 크기에 따라 여러 개의 미니배치로 나누고 모델에 넣어 기울기를 계산하고 매개변수를 업데이트하며 손실 함수가 거의 떨어지지 않을 때까지 계속 반복합니다.

전체 코드

https://download.csdn.net/download/first_bug/87733907

import numpy as np
from matplotlib import pyplot as plt

def load_data():
    datafile = "./housing.data"
    data = np.fromfile(datafile,sep=" ")

    feature_names = [ 'CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE','DIS', 
                 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV' ]
    feature_num = len(feature_names)
    data = data.reshape([data.shape[0] // feature_num, feature_num])


    ratio = 0.8
    offset = int(data.shape[0] * ratio)
    training_data = data[:offset]
    maximums, minimums = training_data.max(axis=0), training_data.min(axis=0)

    # 对数据进行归一化处理,使用训练集的极值
    for i in range(feature_num):
        data[:, i] = (data[:, i] - minimums[i]) / (maximums[i] - minimums[i])

    # 训练集和测试集的划分
    training_data = data[:offset]
    test_data = data[offset:]
    return training_data,test_data

class Network():
    def __init__(self,num_of_weights):
        # 随机产生w的初始值
        # 为了保持程序每次运行结果的一致性,设置固定的随机数种子
        np.random.seed(0)
        self.w = np.random.randn(num_of_weights,1)
        self.b = 0
        
    def forward(self,x):
        # x -> (1,13) , w-> (13,1)
        z = np.dot(x,self.w) + self.b
        return z
    
    def loss(self,z,y):
        error = z-y
        loss = np.mean(error * error)
        return loss
    
    def gradient(self,x,y):
        z = self.forward(x)
        gradient_w = (z-y)*x
        gradient_w = np.mean(gradient_w,axis=0)
        gradient_w = gradient_w[:,np.newaxis]
        
        gradient_b = (z-y)
        gradient_b = np.mean(gradient_b)
        return gradient_w,gradient_b
    
    def update(self,gradient_w,gradient_b,eta=0.01):
        self.w = self.w - eta*gradient_w
        self.b = self.b - eta*gradient_b

    def train_gd(self,x,y,iterations=100,eta = 0.01):
        losses = []
        for i in range(iterations):
            z = self.forward(x)
            L = self.loss(z,y)
            gradient_w, gradient_b = self.gradient(x,y)
            self.update(gradient_w,gradient_b,eta)
            losses.append(L)
            if (i+1)%10 == 0:
                print("iter {},loss {}".format(i,L))
        return losses
    
    def train_sgd(self,training_data,num_epochs,batch_size=10,eta=0.01):
        n= len(training_data)
        losses = []
        for epoch_id in range(num_epochs):
            # 在每轮迭代开始之前,将训练数据的顺序进行随机打乱
            # 然后再按照每次取出batch_size条数据的方式取出
            np.random.shuffle(training_data)
            # 将训练数据进行拆分,每个mini_batch包含batch_size条数据
            mini_batches = [training_data[k:k+batch_size] for k in range(0,n,batch_size)]
            for iter_id,mini_batch in enumerate(mini_batches):
                x = mini_batch[:,:-1]
                y = mini_batch[:,-1:]
                a = self.forward(x)
                loss = self.loss(a,y)
                gradient_w, gradient_b = self.gradient(x,y)
                self.update(gradient_w,gradient_b,eta)
                losses.append(loss)
                print("Epoch {:3d} / iter {:3d},loss = {:.4f}".format(epoch_id,iter_id,loss))
        return losses
    def valid(self,test_data):
        x = test_data[:,:-1]
        y = test_data[:,-1:]
        a = self.forward(x)
        loss = self.loss(a,y)
        return loss

def main():
    # 获取数据
    train_data ,test_data = load_data()
    x = train_data[:,:-1]
    y = train_data[:,-1:]
    # 创建网络
    net = Network(13)
    num_iterations = 1000
    # 启动训练
    losses = net.train_gd(x,y,iterations=num_iterations,eta=0.01)
    #losses = net.train_sgd(train_data,num_iterations,batch_size=10,eta=0.01)
    
    print("valid loss: {:.4f}".format(net.valid(test_data)))

    # 画出损失函数的变化趋势
    plot_x = np.arange(len(losses))
    plot_y = np.array(losses)
    plt.plot(plot_x,plot_y)
    plt.show()

if __name__ == "__main__":
    main()

numpy 함수

np.fromfile

np.fromfile(file,dtype=float,count=-1,sep="",offset=0,like=None)

텍스트 또는 이진 파일의 데이터에서 배열을 구성하고, 알려진 데이터 유형이 있는 이진 데이터를 읽고, 간단한 형식의 텍스트 파일을 구문 분석하는 효율적인 방법입니다.

  • 파일

    열린 파일 객체 또는 파일 경로

  • dtype

    파일에 있는 항목의 크기와 바이트 순서를 결정하는 데 사용되는 이진 파일의 경우 배열의 데이터 유형을 반환합니다. 대부분의 내장 데이터 유형이 지원됩니다.

  • 개수: 정수

    읽을 항목 수, 전체 파일의 경우 -1

  • 9월: str

    파일이 텍스트 파일인 경우 항목 사이의 구분 기호를 지정하고 빈("") 구분 기호는 파일이 이진 파일로 간주됨을 의미합니다. 구분 기호의 공백(" ")은 0개 이상의 공백 문자와 일치합니다.

  • 오프셋: 정수

    파일의 현재 위치에서 바이트 단위 로 오프셋되며 기본값은 0이며 바이너리 파일에만 허용됩니다.

  • 좋아요: array_like

    Numpy 배열이 아닌 배열 참조 객체 생성 허용 as로 전달된 유사 배열이 __array_function__ 프로토콜을 지원하면 그에 의해 결과가 정의됩니다. 이 매개변수를 통해 전달된 개체 배열 개체.

ndarray.shape

행렬의 차원 정보(0번째 차원의 길이, 1번째 차원의 길이, ..., n번째 차원의 길이)를 반환합니다.

2개의 행과 3개의 열이 있는 행렬: (2,3)

ndarray.reshape

매트릭스의 차원 정보 수정, 매개 변수는 차원 정보입니다.

동일한 데이터를 가리키는 새로운 ndarray 객체를 반환합니다. 하나의 ndarray를 수정하면 데이터를 가리키는 다른 ndarray 객체도 수정됩니다.

numpy.dot

배열 연산은 요소 수준이며 배열을 곱한 결과는 각 해당 요소의 곱으로 구성된 배열입니다.

행렬의 경우 numpy는 행렬 곱셈을 위한 도트 함수를 제공합니다.

res = np.dot(a,b,out=None)

두 요소 a, b의 곱을 가져옵니다.

numpy 난수

난수 시드 설정

np.random.seed(n)

난수 생성

np.random.rand(d0,d1,d2,...,dn)

순종 세트 반환 0 1 0~10 1  균일하게 분포된 무작위 표본 값, 표본의 값 범위는[ 0 , 1 ) [0,1)[ 0 ,1 ) , 1 제외

np.random.randn(d0,d1,d2,...,dn)

표준정규분포를 따르는 임의의 표본 값의 집합을 반환하며 그 값은 기본적으로 − 1.96 ∼ + 1.96 -1.96 \thicksim + 1.96 사이입니다.- 1.96~+ 1.96 , 더 큰 값의 확률은 더 작습니다.

np.newaxis

np.newaxis의 기능은 새로운 차원을 추가하는 것이며, 위치가 다르면 생성된 사각형의 모양도 다릅니다.

np.newaxis가 배치된 위치에 해당 위치에 차원을 추가합니다.

  • x[:,np.newaxis], 뒤쪽에 배치하면 열에 차원이 추가됩니다.
  • x[np.newaxis,:], 앞에 배치, 행에 차원을 추가합니다.

일반적으로 1차원 데이터를 다른 행렬과 곱할 수 있는 행렬로 변환하는 데 사용됩니다.

np.random.shuffle

원래 배열에서 섞기 작업을 수행하고 요소를 재정렬하고 원래 순서를 섞습니다.

matplotlib 3D 플로팅

  1. 3차원 좌표축 객체 생성 Axes3D

    # 方法一,利用参数projection='3d'
    from matplotlib import pyplot as plt
    
    # 定义坐标轴
    fig = plt.figure()
    ax1 = plt.axes(projection="3d")
    
    # 方法二: 利用三维轴 ( 已废弃 )
    from matplotlib import pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    
    # 定义图像和三维格式坐标轴
    fig = plt.figure()
    ax2 = Axes3D(fig)
    
  2. 그림

    import numpy as np
    from matplotlib import pyplot as plt
    # 定义坐标轴
    fig = plt.figure()
    ax1 = plt.axes(projection="3d")
    
    # 设置xyz方向的变量
    z = np.linspace(0,13,1000) # 在[0-13]之间等距取1000个点
    x = 5*np.sin(z)
    y = 5*np.cos(z)
    
    #设置坐标轴
    ax1.set_xlabel('X')
    ax1.set_ylabel('Y')
    ax1.set_zlabel('Z')
    ax1.plot3D(x,y,z,'gray')#绘制空间曲线
    plt.show()#显示图像
    

    여기에 이미지 설명 삽입

    import numpy as np
    from matplotlib import pyplot as plt
    #定义新坐标轴
    fig=plt.figure()
    ax3=plt.axes(projection='3d')
     
    #定义三维数据
    xx=np.arange(-5,5,0.5)
    yy=np.arange(-5,5,0.5)
     
    #生成网格点坐标矩阵,对x和y数据执行网格化
    X,Y=np.meshgrid(xx,yy)
     
    #计算z轴数据
    Z=np.sin(X)+np.cos(Y)
     
    #绘图
    #函数plot_surface期望其输入结构为一个规则的二维网格
    ax3.plot_surface(X,Y,Z,cmap='rainbow') #cmap是颜色映射表
    plt.title("3D")
    plt.show()
    
    

    여기에 이미지 설명 삽입

여기에 이미지 설명 삽입

  • X, Y 데이터는 좌표점을 결정합니다.
  • Z축 데이터는 X 및 Y 좌표점에 해당하는 높이를 결정합니다.

참고

https://aistudio.baidu.com/aistudio/projectdetail/5687440

추천

출처blog.csdn.net/first_bug/article/details/130396954