深度学习---神经网络基础

深度学习概述

机器学习是实现人工智能的一种途径,深度学习是机器学习的一个子集,深度学习是实现机器学习的一种方法。与机器学习算法的主要区别如下图所示:

传统机器学习算术依赖人工设计特征,并进行特征提取,而深度学习方法不需要人工,而是依赖算法自动提取特征。深度学习模仿人类大脑的运行方式,从经验中学习获取知识。这也是深度学习被看做黑盒子,可解释性差的原因。

随着计算机软硬件的飞速发展,现阶段通过深度学习来模拟人脑来解释数据,包括图像,文本,音频等内容。目前深度学习的主要应用领域有:

  1. 语音识别
  2. 机器翻译
  3. 自动驾驶

当然在其他领域也能见到深度学习的身影,比如风控,安防,智能零售,医疗领域,推荐系统等。

神经网络概述

神经网络就是模拟人神经元的工作机理,并构造仿生的神经元来解决实际问题。一个简单的神经网络,包括输入层、隐藏层、输出层,其中隐藏层可以有很多层,每一层也可以包含数量众多的的神经元。以下流程就像,来源不同树突(树突都会有不同的权重)的信息进行的加权计算,输入到细胞中做加和,再通过激活函数输出细胞值。

神经网络中信息只向一个方向移动,即从输入节点向前移动,通过隐藏节点,再向输出节点移动。其中的基本部分是:

  1. 输入层: 即输入 x 的那一层
  2. 输出层: 即输出 y 的那一层
  3. 隐藏层: 输入层和输出层之间都是隐藏层

同一层的神经元之间没有连接。 第 N 层的每个神经元和第 N-1层 的所有神经元相连(这就是full connected的含义), 第N-1层神经元的输出就是第N层神经元的输入。每个连接都有一个权值。

激活函数 

激活函数用于对每层的输出数据进行变换,进而为整个网络结构结构注入了非线性因素。此时神经网络就可以拟合各种曲线。如果不使用激活函数,整个网络虽然看起来复杂,其本质还相当于一种线性模型,如下公式所示:

  • 没有引入非线性因素的网络等价于使用一个线性模型来拟合
  • 通过给网络输出增加激活函数,实现引入非线性因素,使得网络模型可以逼近任意函数, 提升网络对复杂问题的拟合能力。
  • 激活函数主要用来向神经网络中加入非线性因素,以解决线性模型表达能力不足的问题,它对神经网络有着极其重要的作用。网络参数在更新时,使用的反向传播算法(BP),要求激活函数必须可微。

sigmoid 激活函数

  • 从 sigmoid 函数图像可以得到,sigmoid 函数可以将任意的输入映射到 (0, 1) 之间,当输入的值大致在 <-6 或者 >6 时,意味着输入任何值得到的激活值都是差不多的,这样会丢失部分的信息。比如:输入 100 和输出 10000 经过 sigmoid 的激活值几乎都是等于 1 的,但是输入的数据之间相差 100 倍的信息就丢失了。
  • 对于 sigmoid 函数而言,输入值在 [-6, 6] 之间输出值才会有明显差异,输入值在 [-3, 3] 之间才会有比较好的效果。
  • 通过上述导数图像,发现导数数值范围是 (0, 0.25),当输入 <-6 或者 >6 时,sigmoid 激活函数图像的导数接近为 0,此时网络参数将更新极其缓慢,或者无法更新。
  • 一般来说, sigmoid 网络在 5 层之内就会产生梯度消失现象。而且,该激活函数并不是以 0 为中心的,所以在实践中这种激活函数使用的很少。sigmoid函数一般只用于二分类的输出层。

tanh 激活函数

  • 由上面的函数图像可以看到,Tanh 函数将输入映射到 (-1, 1) 之间,图像以 0 为中心,在 0 点对称,当输入 大概<-3 或者 >3 时将被映射为 -1 或者 1。其导数值范围 (0, 1),当输入的值大概 <-3 或者 > 3 时,其导数近似 0。
  • 与 Sigmoid 相比,它是以 0 为中心的,使得其收敛速度要比 Sigmoid 快,减少迭代次数。然而,从图中可以看出,Tanh 两侧的导数也为 0,同样会造成梯度消失。
  • 若使用时可在隐藏层使用tanh函数,在输出层使用sigmoid函数。

ReLU 激活函数 

  • 从上述函数图像可知,ReLU 激活函数将小于 0 的值映射为 0,而大于 0 的值则保持不变,它更加重视正信号,而忽略负信号,这种激活函数运算更为简单,能够提高模型的训练效率。
  • 但是,如果网络的参数采用随机初始化时,很多参数可能为负数,这就使得输入的正值会被舍去,而输入的负值则会保留,这可能在大部分的情况下并不是想要的结果。

ReLU 的导数图像如下:

  • ReLU是目前最常用的激活函数。 从图中可以看到,当x<0时,ReLU导数为0,而当x>0时,则不存在饱和问题。所以ReLU 能够在x>0时保持梯度不衰减,从而缓解梯度消失问题。然而随着训练的推进,部分输入会落入小于0区域,导致对应权重无法更新。这种现象被称为“神经元死亡”。
  • 与sigmoid相比,RELU的优势是:
  • 采用sigmoid函数,计算量大(指数运算),反向传播求误差梯度时,求导涉及除法,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多。 sigmoid函数反向传播时,很容易就会出现梯度消失的情况,从而无法完成深层网络的训练。 Relu会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生。

SoftMax 

softmax用于多分类过程中,它是二分类函数sigmoid在多分类上的推广,目的是将多分类的结果以概率的形式展现出来。计算方法如下图所示:

Softmax 直白来说就是将网络输出的 logits 通过 softmax 函数,就映射成为(0,1)的值,而这些值的累和为1(满足概率的性质),那么将它理解成概率,选取概率最大(也就是值对应最大的)节点,作为预测目标类别。 

其他激活函数

总结

对于隐藏层:

  1. 优先选择RELU激活函数
  2. 如果ReLu效果不好,那么尝试其他激活,如Leaky ReLu等。
  3. 如果使用了Relu, 需要注意一下Dead Relu问题, 避免出现大的梯度从而导致过多的神经元死亡。
  4. 不要使用sigmoid激活函数,可以尝试使用tanh激活函数

对于输出层

  1. 二分类问题选择sigmoid激活函数
  2. 多分类问题选择softmax激活函数
  3. 回归问题选择identity激活函数

传播算法

前向传播

前向传播指的是数据输入的神经网络中,逐层向前传输,一直到运算到输出层为止。

在网络的训练过程中经过前向传播后得到的最终结果跟训练样本的真实值总是存在一定误差,这个误差便是损失函数。想要减小这个误差,就用损失函数 ERROR,从后往前,依次求各个参数的偏导,这就是反向传播(Back Propagation)。利用反向传播算法对神经网络进行训练,该方法与梯度下降算法相结合,对网络中所有权重计算损失函数的梯度,并利用梯度值来更新权值以最小化损失函数。

链式法则

反向传播算法是利用链式法则进行梯度求解及权重更新的。对于复杂的复合函数,将其拆分为一系列的加减乘除或指数,对数,三角函数等初等函数,通过链式法则完成复合函数的求导。这里以一个神经网络中常见的复合函数的例子来说明这个过程,复合函数 𝑓(𝑥) 为:

其参数为权重 w、b。需要求关于 w 和 b 的偏导,然后应用梯度下降公式就可以更新参数。将复合函数分解为一系列的初等函数导数相乘的形式:

整个复合函数 𝑓(𝑥; 𝑤, 𝑏) 关于参数 𝑤 和 𝑏 的导数可以通过 𝑓(𝑥; 𝑤, 𝑏) 与参数 𝑤 和 𝑏 之间路径上所有的导数连乘来得到,即:

以w为例,当 𝑥 = 1, 𝑤 = 0, 𝑏 = 0 时,可以得到:

反向传播算法

BP(Back Propagation)算法也叫做误差反向传播算法,它用于求解模型的参数梯度,从而使用梯度下降法来更新网络参数。它的基本工作流程如下:

  • 通过正向传播得到误差,所谓正向传播指的是数据从输入到输出层,经过层层计算得到预测值,并利用损失函数得到预测值和真实值之前的误差。
  • 通过反向传播把误差传递给模型的参数,从而对网络参数进行适当的调整,缩小预测值和真实值之间的误差。
  • 反向传播算法是利用链式法则进行梯度求解,然后进行参数更新。对于复杂的复合函数,将其拆分为一系列的加减乘除或指数,对数,三角函数等初等函数,通过链式法则完成复合函数的求导。

通过一个例子来简单理解下 BP 算法进行网络参数更新的过程:

为了能够把计算过程描述的更详细一些,上图中一个矩形代表一个神经元,每个神经元中分别是值和激活值的计算结果和其对应的公式,最终计算出真实值和预测值之间的误差 0.2984. 其中:

  1. 由下向上看,最下层绿色的两个圆代表两个输入值
  2. 右侧的8个数字,最下面4个表示 w1、w2、w3、w4 的参数初始值,最上面的4个数字表示 w5、w6、w7、w8 的参数初始值
  3. b1 值为 0.35,b2 值为 0.60
  4. 预测结果分别为: 0.7514、0.7729

参数初始化

在构建网络之后,网络中的参数是需要初始化的。需要初始化的参数主要有权重和偏置,偏置一般初始化为 0 即可,而对权重的初始化则会更加重要。

  • 均匀分布初始化,权重参数初始化从区间均匀随机取值。即在(-1/√d,1/√d)均匀分布中生成当前神经元的权重,其中d为每个神经元的输入数量。
  • 正态分布初始化,随机初始化从均值为0,标准差是1的高斯分布中取样,使用一些很小的值对参数W进行初始化.
  • 全0初始化,将神经网络中的所有权重参数初始化为 0.
  • 全1初始化,将神经网络中的所有权重参数初始化为 1.
  • 固定值初始化,将神经网络中的所有权重参数初始化为某个固定值.
  • kaiming 初始化,也叫做 HE 初始化。HE 初始化分为正态分布的 HE 初始化、均匀分布的 HE 初始化.
  • xavier 初始化,也叫做Glorot初始化,该方法的基本思想是各层的激活值和梯度的方差在传播过程中保持一致。它有两种,一种是正态分布的 xavier 初始化、一种是均匀分布的 xavier 初始化.

优化方法

传统的梯度下降优化算法中,可能会碰到以下情况:碰到平缓区域,梯度值较小,参数优化变慢碰到 “鞍点” ,梯度为0,参数无法优化碰到局部最小值,对于这些问题,出现了一些对梯度下降算法的优化方法,例如:Momentum、AdaGrad、RMSprop、Adam等。

指数加权平均

β 的值越大,则绘制出的折线越加平缓;β 值一般默认都是 0.9。

Momentum

AdaGrad

RMSProp

Adam

Momentum 使用指数加权平均计算当前的梯度值、AdaGrad、RMSProp 使用自适应的学习率,Adam 结合了 Momentum、RMSProp 的优点,使用:移动加权平均的梯度和移动加权平均的学习率。使得能够自适应学习率的同时,也能够使用 Momentum 的优点。

总结

对普通梯度下降算法的优化方法,主要有 Momentum、AdaGrad、RMSProp、Adam 等优化方法,其中 Momentum 使用指数加权平均参考了历史梯度,使得梯度值的变化更加平缓。AdaGrad 则是针对学习率进行了自适应优化,由于其实现可能会导致学习率下降过快,RMSProp 对 AdaGrad 的学习率自适应计算方法进行了优化,Adam 则是综合了 Momentum 和 RMSProp 的优点,在很多场景下,Adam 的表示都很不错。

正则化

在训深层练神经网络时,由于模型参数较多,在数据量不足的情况下,很容易过拟合。Dropout 就是在神经网络中一种缓解过拟合的方法。

缓解过拟合的方式就是降低模型的复杂度,而 Dropout 就是通过减少神经元之间的连接,把稠密的神经网络神经元连接,变成稀疏的神经元连接,从而达到降低网络复杂度的目的。

dropout 层的使用,其作用用于控制网络复杂度,达到正则化的目的,类似于 L2 正则化对线性回归的作用。

批量归一化

在神经网络的搭建过程中,Batch Normalization(批量归一化)是经常使用一个网络层,其主要的作用是控制数据的分布,加快网络的收敛。

神经网络的学习其实在学习数据的分布,随着网络的深度增加、网络复杂度增加,一般流经网络的数据都是一个 mini batch,每个 mini batch 之间的数据分布变化非常剧烈,这就使得网络参数频繁的进行大的调整以适应流经网络的不同分布的数据,给模型训练带来非常大的不稳定性,使得模型难以收敛。

如果对每一个 mini batch 的数据进行标准化之后,数据分布就变得稳定,参数的梯度变化也变得稳定,有助于加快模型的收敛。

批量归一化层,该层的作用主要是用来控制每层数据的流动时的均值和方差,防止训练过程出现剧烈的波动,模型难以收敛,或者收敛较慢。批量归一化层在计算机视觉领域使用较多。

案例-价格分类

import torch
import torch.nn as nn
import torch.nn.functional as F
import pandas as pd
from sklearn.model_selection import train_test_split
from torch.utils.data import TensorDataset
from torch.utils.data import DataLoader
import torch.optim as optim
import numpy as np
import time
from sklearn.preprocessing import StandardScaler# 构建数据集
def create_dataset():data = pd.read_csv('data/手机价格预测.csv')# 特征值和目标值x, y = data.iloc[:, :-1], data.iloc[:, -1]x = x.astype(np.float32)y = y.astype(np.int64)# 数据集划分x_train, x_valid, y_train, y_valid = \train_test_split(x, y, train_size=0.8, random_state=88, stratify=y)# 数据标准化transfer = StandardScaler()x_train = transfer.fit_transform(x_train)x_valid = transfer.transform(x_valid)# 构建数据集train_dataset = TensorDataset(torch.from_numpy(x_train), torch.tensor(y_train.values))valid_dataset = TensorDataset(torch.from_numpy(x_valid), torch.tensor(y_valid.values))return train_dataset, valid_dataset, x_train.shape[1], len(np.unique(y))train_dataset, valid_dataset, input_dim, class_num = create_dataset()# 构建网络模型
class PhonePriceModel(nn.Module):def __init__(self, input_dim, output_dim):super(PhonePriceModel, self).__init__()self.linear1 = nn.Linear(input_dim, 128)self.linear2 = nn.Linear(128, 256)self.linear3 = nn.Linear(256, 512)self.linear4 = nn.Linear(512, 128)self.linear5 = nn.Linear(128, output_dim)def _activation(self, x):return torch.sigmoid(x)def forward(self, x):x = self._activation(self.linear1(x))x = self._activation(self.linear2(x))x = self._activation(self.linear3(x))x = self._activation(self.linear4(x))output = self.linear5(x)return output# 编写训练函数
def train():# 固定随机数种子torch.manual_seed(0)# 初始化模型model = PhonePriceModel(input_dim, class_num)# 损失函数criterion = nn.CrossEntropyLoss()# 优化方法optimizer = optim.Adam(model.parameters(), lr=1e-4)# 训练轮数num_epoch = 50for epoch_idx in range(num_epoch):# 初始化数据加载器dataloader = DataLoader(train_dataset, shuffle=True, batch_size=8)# 训练时间start = time.time()# 计算损失total_loss = 0.0total_num = 1# 准确率correct = 0for x, y in dataloader:output = model(x)# 计算损失loss = criterion(output, y)# 梯度清零optimizer.zero_grad()# 反向传播loss.backward()# 参数更新optimizer.step()total_num += len(y)total_loss += loss.item() * len(y)print('epoch: %4s loss: %.2f, time: %.2fs' %(epoch_idx + 1, total_loss / total_num, time.time() - start))# 模型保存torch.save(model.state_dict(), 'model/phone-price-model.bin')def test():# 加载模型model = PhonePriceModel(input_dim, class_num)model.load_state_dict(torch.load('model/phone-price-model.bin'))# 构建加载器dataloader = DataLoader(valid_dataset, batch_size=8, shuffle=False)# 评估测试集correct = 0for x, y in dataloader:output = model(x)y_pred = torch.argmax(output, dim=1)correct += (y_pred == y).sum()print('Acc: %.5f' % (correct.item() / len(valid_dataset)))if __name__ == '__main__':train()test()

网络模型调优:

  1. 对输入数据进行标准化
  2. 调整优化方法
  3. 调整学习率
  4. 增加批量归一化层
  5. 增加网络层数、神经元个数
  6. 增加训练轮数
  7. 等等...

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/166413.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构----算法--五大基本算法(这里没有写分支限界法)和银行家算法

数据结构----算法–五大基本算法&#xff08;这里没有写分支限界法&#xff09;和银行家算法 一.贪心算法 1.什么是贪心算法 在有多个选择的时候不考虑长远的情况&#xff0c;只考虑眼前的这一步&#xff0c;在眼前这一步选择当前的最好的方案 二.分治法 1.分治的概念 分…

公有云厂商---服务对照表

各厂商特点&#xff1a; Compute: Network: Storage: Database: Migration Tool: Identify: WAF: 来源&#xff1a;https://comparecloud.in/

【网络安全 --- xss-labs靶场通关(1-10关)】详细的xss-labs靶场通关思路及技巧讲解,让你对xss漏洞的理解更深刻

靶场安装&#xff1a; 靶场安装请参考以下博客&#xff0c;既详细有提供工具&#xff1a; 【网络安全 --- xss-labs靶场】xss-labs靶场安装详细教程&#xff0c;让你巩固对xss漏洞的理解及绕过技巧和方法&#xff08;提供资源&#xff09;-CSDN博客【网络安全 --- xss-labs通…

嵌入式硬件中常见的100种硬件选型方式

1请列举您知道的电阻、电容、电感品牌&#xff08;最好包括国内、国外品牌&#xff09;。 电阻&#xff1a; 美国&#xff1a;AVX、VISHAY 威世 日本&#xff1a;KOA 兴亚、Kyocera 京瓷、muRata 村田、Panasonic 松下、ROHM 罗姆、susumu、TDK 台湾&#xff1a;LIZ 丽智、PHY…

服务器数据恢复-RAID5中磁盘被踢导致阵列崩溃的服务器数据恢复案例

服务器数据恢复环境&#xff1a; 一台3U的某品牌机架式服务器&#xff0c;Windows server操作系统&#xff0c;100块SAS硬盘组建RAID5阵列。 服务器故障&#xff1a; 服务器有一块硬盘盘的指示灯亮黄灯&#xff0c;这块盘被raid卡踢出后&#xff0c;raid阵列崩溃。 服务器数据…

JavaEE初阶学习:Servlet

1.Servlet 是什么 Servlet 是一种 Java 程序&#xff0c;用于在 Web 服务器上处理客户端请求和响应。Servlet 可以接收来自客户端&#xff08;浏览器、移动应用等&#xff09;的 HTTP 请求&#xff0c;并生成 HTML 页面或其他格式的数据&#xff0c;然后将响应发送回客户端。S…

解决CondaHTTPError HTTP 000 CONNECTION FAILED for url解决方法

解决CondaHTTPError: HTTP 000 CONNECTION FAILED for url解决方法 问题&#xff1a;使用conda install命令安装包提示CondaHTTPError: HTTP 000 CONNECTION FAILED for url 分析&#xff1a;网络连接问题&#xff0c;大概率是网速不行或者源没有换 解决方案&#xff1a;修改国…

C++多态、虚函数、纯虚函数、抽象类

多态的概念 通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会产生出不同的状态。 举个简单的例子&#xff1a;抢红包&#xff0c;我们每个人都只需要点击一下红包&#xff0c;就会抢到金额。有些人能…

5G学习笔记之5G频谱

参考&#xff1a;《5G NR通信标准》1. 5G频谱 1G和2G移动业务的频段主要在800MHz~900MHz&#xff0c;存在少数在更高或者更低频段&#xff1b;3G和4G的频段主要在450MHz ~ 6GHz&#xff1b;5G主要是410MHz ~ 6GHz&#xff0c;以及24GHz ~ 52GHz。 5G频谱跨度较大&#xff0c;可…

开源贡献难吗?

本文整理自字节跳动 Flink SQL 技术负责人李本超在 CommunityOverCode Asia 2023 上的 Keynote 演讲&#xff0c;李本超根据自己在开源社区的贡献经历&#xff0c;基于他在贡献开源社区过程中的一些小故事和思考&#xff0c;如何克服困难&#xff0c;在开源社区取得突破&#x…

Spark--经典SQL50题

目录 连接数据库准备工作 1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数 2、查询"01"课程比"02"课程成绩低的学生的信息及课程分数 3、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩 4、查询平均成绩…

在Kubernetes(k8s)上部署整个SpringCloud微服务应用

视频教程地址&#xff1a;https://www.bilibili.com/video/BV1Xh4y1q7aW/ 文章目录 项目准备打成使用Docker打成镜像准备Docker仓库打包项目为Docker镜像 部署应用到k8s创建nfs挂载目录创建一些基本资源创建命名空间创建拉取镜像的secret创建java运行环境的profile 部署mysql创…

Unity中Shader的XRay透视效果

文章目录 前言一、模拟菲涅尔效果1、获取 V 向量2、获取 N 向量3、点积输出效果4、模拟出菲涅尔效果(中间暗&#xff0c;周围亮) 二、实现 &#xff38;Ray 效果1、使用半透明排序、修改混合模式、加点颜色2、增加分层效果&#xff08;使用 frac 函数&#xff0c;只取小数部分&…

【深入探究Java集合框架】从List到Map的完整指南

文章目录 &#x1f31f; Java集合框架&#x1f34a; Collection&#x1f389; List&#x1f389; Set&#x1f389; Map &#x1f34a; 集合的选择&#x1f389; 1. 有序并允许重复元素的集合 List&#x1f389; 2. 无序并且不允许重复元素的集合 Set&#x1f389; 3. 维护映射…

【计网 EMail】计算机网络 EMail协议详解:中科大郑烇老师笔记 (五)

目录 0 引言1 电子邮件EMail1.1 组成1.2 SMTP协议1.3 案例&#xff1a;Alice给Bob发送报文1.4 SMTP总结1.5 邮件报文格式1.6 POP3协议和IMAP协议 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;计算机四大基础专栏&#x1f4dc; 其他章节&#xf…

辅助驾驶功能开发-功能规范篇(16)-2-领航辅助系统NAP-安全接管策略

书接上回 2.3.6安全接管策略 为保障辅助驾驶车辆的安全性,在辅助驾驶系统运行过程中,对出现的影响系统稳定性的异常情况,制定对应的安全接管策略。 异常情况可能包括:系统传感器、控制器、执行器、电源、通讯、备份系统等的故障或失效,驾驶员异常行为(如不响应车辆的接管…

毅速丨3D打印结合拓扑优化 让轻量化制造更容易

制造轻量化对于提高能源利用效率、提高产品性能和减少环境影响&#xff0c;推动制造业的绿色化、高质量发展具有重要的促进作用。 轻量化设计对许多领域都有着重要影响&#xff0c;尤其是那些需要降低能源消耗、提高运输效率或减少对环境影响的领域。如航空航天&#xff0c;轻量…

【论文阅读笔记】 Curated Pacific Northwest AI-ready Seismic Dataset

Curated Pacific Northwest AI-ready Seismic Dataset 太平洋西北部人工智能地震数据集 摘要 描述了一个AI就绪地震数据集包括各种地震事件参数 仪器元数据 地震波行描述地震目录和事件属性&#xff08;事件震级类型&#xff0c;信道类型&#xff0c;波形极性&#xff0c;信…

网络协议--ICMP:Internet控制报文协议

6.1 引言 ICMP经常被认为是IP层的一个组成部分。它传递差错报文以及其他需要注意的信息。ICMP报文通常被IP层或更高层协议&#xff08;TCP或UDP&#xff09;使用。一些ICMP报文把差错报文返回给用户进程。 ICMP报文是在IP数据报内部被传输的&#xff0c;如图6-1所示。 ICMP…

【Overload游戏引擎细节分析】Lambert材质Shader分析

一、经典光照模型&#xff1a;Phong模型 现实世界的光照是极其复杂的&#xff0c;而且会受到诸多因素的影响&#xff0c;这是以目前我们所拥有的处理能力无法模拟的。经典光照模型冯氏光照模型(Phong Lighting Model)通过单独计算光源成分得到综合光照效果&#xff0c;然后添加…