详解TensorFlow2实现前向传播

目录
  • 概述
  • 会用到的函数
    • 张量最小值
    • 张量最大值
    • 数据集分批
    • 迭代
    • 截断正态分布
    • relu 激活函数
    • one_hot
    • assign_sub
  • 准备工作
    • train 函数
  • run 函数
  • 完整代码

概述

前向传播 (Forward propagation) 是将上一层输出作为下一层的输入, 并计算下一层的输出, 一直到运算到输出层为止.

会用到的函数

张量最小值

```reduce_min``函数可以帮助我们计算一个张量各个维度上元素的最小值.

格式:

tf.math.reduce_min(
    input_tensor, axis=None, keepdims=False, name=None
)

参数:

  • input_tensor: 传入的张量
  • axis: 维度, 默认计算所有维度
  • keepdims: 如果为真保留维度, 默认为 False
  • name: 数据名称

张量最大值

```reduce_max``函数可以帮助我们计算一个张量各个维度上元素的最大值.

格式:

tf.math.reduce_max(
    input_tensor, axis=None, keepdims=False, name=None
)

参数:

  • input_tensor: 传入的张量
  • axis: 维度, 默认计算所有维度
  • keepdims: 如果为真保留维度, 默认为 False
  • name: 数据名称

数据集分批

from_tensor_slices可以帮助我们切分传入 Tensor 的第一个维度. 得到的每个切片都是一个样本数据.

格式:

@staticmethod
from_tensor_slices(
    tensors
)

迭代

我们可以调用iter函数来生成迭代器.

格式:

iter(object[, sentinel])

参数:
-object: 支持迭代的集合对象

  • sentinel: 如果传递了第二个参数, 则参数 object 必须是一个可调用的对象 (如, 函数). 此时, iter 创建了一个迭代器对象, 每次调用这个迭代器对象的__next__()方法时, 都会调用 object

例子:

list = [1, 2, 3]
i = iter(list)
print(next(i))
print(next(i))
print(next(i))

输出结果:

1
2
3

截断正态分布

truncated_normal可以帮助我们生成一个截断的正态分布. 生成的正态分布值会在两倍的标准差的范围之内.

格式:

tf.random.truncated_normal(
    shape, mean=0.0, stddev=1.0, dtype=tf.dtypes.float32, seed=None, name=None
)

参数:

  • shape: 张量的形状
  • mean: 正态分布的均值, 默认 0.0
  • stddev: 正态分布的标准差, 默认为 1.0
  • dtype: 数据类型, 默认为 float32
  • seed: 随机数种子
  • name: 数据名称

relu 激活函数

激活函数有 sigmoid, maxout, relu 等等函数. 通过激活函数我们可以使得各个层之间达成非线性关系.

激活函数可以帮助我们提高模型健壮性, 提高非线性表达能力, 缓解梯度消失问题.

one_hot

tf.one_hot函数是讲 input 准换为 one_hot 类型数据输出. 相当于将多个数值联合放在一起作为多个相同类型的向量.

格式:

tf.one_hot(
    indices, depth, on_value=None, off_value=None, axis=None, dtype=None, name=None
)

参数:

  • indices: 索引的张量
  • depth: 指定独热编码维度的标量
  • on_value: 索引 indices[j] = i 位置处填充的标量,默认为 1
  • off_value: 索引 indices[j] != i 所有位置处填充的标量, 默认为 0
  • axis: 填充的轴, 默认为 -1 (最里面的新轴)
  • dtype: 输出张量的数据格式
  • name:数据名称

assign_sub

assign_sub可以帮助我们实现张量自减.

格式:

tf.compat.v1.assign_sub(
    ref, value, use_locking=None, name=None
)

参数:

  • ref: 多重张量
  • value: 张量
  • use_locking: 锁
  • name: 数据名称

准备工作

import tensorflow as tf

# 定义超参数
batch_size = 256  # 一次训练的样本数目
learning_rate = 0.001  # 学习率
iteration_num = 20  # 迭代次数

# 读取mnist数据集
(x, y), _ = tf.keras.datasets.mnist.load_data()  # 读取训练集的特征值和目标值
print(x[:5])  # 调试输出前5个图
print(y[:5])  # 调试输出前5个目标值数字
print(x.shape)  # (60000, 28, 28) 单通道
print(y.shape)  # (60000,)

# 转换成常量tensor
x = tf.convert_to_tensor(x, dtype=tf.float32) / 255  # 转换为0~1的形式
y = tf.convert_to_tensor(y, dtype=tf.int32)  # 转换为整数形式

# 调试输出范围
print(tf.reduce_min(x), tf.reduce_max(x))  # 0~1
print(tf.reduce_min(y), tf.reduce_max(y))  # 0~9

# 分割数据集
train_db = tf.data.Dataset.from_tensor_slices((x, y)).batch(batch_size)  # 256为一个batch
train_iter = iter(train_db)  # 生成迭代对象

# 定义权重和bias [256, 784] => [256, 256] => [256, 128] => [128, 10]
w1 = tf.Variable(tf.random.truncated_normal([784, 256], stddev=0.1))  # 标准差为0.1的截断正态分布
b1 = tf.Variable(tf.zeros([256]))  # 初始化为0

w2 = tf.Variable(tf.random.truncated_normal([256, 128], stddev=0.1))  # 标准差为0.1的截断正态分布
b2 = tf.Variable(tf.zeros([128]))  # 初始化为0

w3 = tf.Variable(tf.random.truncated_normal([128, 10], stddev=0.1))  # 标准差为0.1的截断正态分布
b3 = tf.Variable(tf.zeros([10]))  # 初始化为0

输出结果:

[[[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
...
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]]

[[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
...
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]]

[[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
...
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]]

[[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
...
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]]

[[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
...
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]]]
[5 0 4 1 9]
(60000, 28, 28)
(60000,)
tf.Tensor(0.0, shape=(), dtype=float32) tf.Tensor(1.0, shape=(), dtype=float32)
tf.Tensor(0, shape=(), dtype=int32) tf.Tensor(9, shape=(), dtype=int32)

train 函数

def train(epoch):  # 训练
    for step, (x, y) in enumerate(train_db):  # 每一批样本遍历
        # 把x平铺 [256, 28, 28] => [256, 784]
        x = tf.reshape(x, [-1, 784])

        with tf.GradientTape() as tape:  # 自动求解
            # 第一个隐层 [256, 784] => [256, 256]
            # [256, 784]@[784, 256] + [256] => [256, 256] + [256] => [256, 256] + [256, 256] (广播机制)
            h1 = x @ w1 + tf.broadcast_to(b1, [x.shape[0], 256])
            h1 = tf.nn.relu(h1)  # relu激活

            # 第二个隐层 [256, 256] => [256, 128]
            h2 = h1 @ w2 + b2
            h2 = tf.nn.relu(h2)  # relu激活

            # 输出层 [256, 128] => [128, 10]
            out = h2 @ w3 + b3

            # 计算损失MSE(Mean Square Error)
            y_onehot = tf.one_hot(y, depth=10)  # 转换成one_hot编码
            loss = tf.square(y_onehot - out)  # 计算总误差
            loss = tf.reduce_mean(loss)  # 计算平均误差MSE

        # 计算梯度
        grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3])

        # 更新权重
        w1.assign_sub(learning_rate * grads[0])  # 自减梯度*学习率
        b1.assign_sub(learning_rate * grads[1])  # 自减梯度*学习率
        w2.assign_sub(learning_rate * grads[2])  # 自减梯度*学习率
        b2.assign_sub(learning_rate * grads[3])  # 自减梯度*学习率
        w3.assign_sub(learning_rate * grads[4])  # 自减梯度*学习率
        b3.assign_sub(learning_rate * grads[5])  # 自减梯度*学习率

        if step % 100 == 0:  # 每运行100个批次, 输出一次
            print("epoch:", epoch, "step:", step, "loss:", float(loss))

run 函数

def run():
    for i in range(iteration_num):  # 迭代20次
        train(i)

完整代码

import tensorflow as tf

# 定义超参数
batch_size = 256  # 一次训练的样本数目
learning_rate = 0.001  # 学习率
iteration_num = 20  # 迭代次数

# 读取mnist数据集
(x, y), _ = tf.keras.datasets.mnist.load_data()  # 读取训练集的特征值和目标值
print(x[:5])  # 调试输出前5个图
print(y[:5])  # 调试输出前5个目标值数字
print(x.shape)  # (60000, 28, 28) 单通道
print(y.shape)  # (60000,)

# 转换成常量tensor
x = tf.convert_to_tensor(x, dtype=tf.float32) / 255  # 转换为0~1的形式
y = tf.convert_to_tensor(y, dtype=tf.int32)  # 转换为整数形式

# 调试输出范围
print(tf.reduce_min(x), tf.reduce_max(x))  # 0~1
print(tf.reduce_min(y), tf.reduce_max(y))  # 0~9

# 分割数据集
train_db = tf.data.Dataset.from_tensor_slices((x, y)).batch(batch_size)  # 256为一个batch
train_iter = iter(train_db)  # 生成迭代对象

# 定义权重和bias [256, 784] => [256, 256] => [256, 128] => [128, 10]
w1 = tf.Variable(tf.random.truncated_normal([784, 256], stddev=0.1))  # 标准差为0.1的截断正态分布
b1 = tf.Variable(tf.zeros([256]))  # 初始化为0

w2 = tf.Variable(tf.random.truncated_normal([256, 128], stddev=0.1))  # 标准差为0.1的截断正态分布
b2 = tf.Variable(tf.zeros([128]))  # 初始化为0

w3 = tf.Variable(tf.random.truncated_normal([128, 10], stddev=0.1))  # 标准差为0.1的截断正态分布
b3 = tf.Variable(tf.zeros([10]))  # 初始化为0

def train(epoch):  # 训练
    for step, (x, y) in enumerate(train_db):  # 每一批样本遍历
        # 把x平铺 [256, 28, 28] => [256, 784]
        x = tf.reshape(x, [-1, 784])

        with tf.GradientTape() as tape:  # 自动求解
            # 第一个隐层 [256, 784] => [256, 256]
            # [256, 784]@[784, 256] + [256] => [256, 256] + [256] => [256, 256] + [256, 256] (广播机制)
            h1 = x @ w1 + tf.broadcast_to(b1, [x.shape[0], 256])
            h1 = tf.nn.relu(h1)  # relu激活

            # 第二个隐层 [256, 256] => [256, 128]
            h2 = h1 @ w2 + b2
            h2 = tf.nn.relu(h2)  # relu激活

            # 输出层 [256, 128] => [128, 10]
            out = h2 @ w3 + b3

            # 计算损失MSE(Mean Square Error)
            y_onehot = tf.one_hot(y, depth=10)  # 转换成one_hot编码
            loss = tf.square(y_onehot - out)  # 计算总误差
            loss = tf.reduce_mean(loss)  # 计算平均误差MSE

        # 计算梯度
        grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3])

        # 更新权重
        w1.assign_sub(learning_rate * grads[0])  # 自减梯度*学习率
        b1.assign_sub(learning_rate * grads[1])  # 自减梯度*学习率
        w2.assign_sub(learning_rate * grads[2])  # 自减梯度*学习率
        b2.assign_sub(learning_rate * grads[3])  # 自减梯度*学习率
        w3.assign_sub(learning_rate * grads[4])  # 自减梯度*学习率
        b3.assign_sub(learning_rate * grads[5])  # 自减梯度*学习率

        if step % 100 == 0:  # 每运行100个批次, 输出一次
            print("epoch:", epoch, "step:", step, "loss:", float(loss))

def run():
    for i in range(iteration_num):  # 迭代20次
        train(i)

if __name__ == "__main__":
    run()

输出结果:

epoch: 0 step: 0 loss: 0.5439826250076294
epoch: 0 step: 100 loss: 0.2263326346874237
epoch: 0 step: 200 loss: 0.19458135962486267
epoch: 1 step: 0 loss: 0.1788959801197052
epoch: 1 step: 100 loss: 0.15782299637794495
epoch: 1 step: 200 loss: 0.1580992043018341
epoch: 2 step: 0 loss: 0.15085121989250183
epoch: 2 step: 100 loss: 0.1432340145111084
epoch: 2 step: 200 loss: 0.14373672008514404
epoch: 3 step: 0 loss: 0.13810500502586365
epoch: 3 step: 100 loss: 0.13337770104408264
epoch: 3 step: 200 loss: 0.1334681361913681
epoch: 4 step: 0 loss: 0.12887853384017944
epoch: 4 step: 100 loss: 0.12551936507225037
epoch: 4 step: 200 loss: 0.125375896692276
epoch: 5 step: 0 loss: 0.12160968780517578
epoch: 5 step: 100 loss: 0.1190723180770874
epoch: 5 step: 200 loss: 0.11880680173635483
epoch: 6 step: 0 loss: 0.11563797295093536
epoch: 6 step: 100 loss: 0.11367204040288925
epoch: 6 step: 200 loss: 0.11331651359796524
epoch: 7 step: 0 loss: 0.11063456535339355
epoch: 7 step: 100 loss: 0.10906648635864258
epoch: 7 step: 200 loss: 0.10866570472717285
epoch: 8 step: 0 loss: 0.10636782646179199
epoch: 8 step: 100 loss: 0.10510052740573883
epoch: 8 step: 200 loss: 0.10468046367168427
epoch: 9 step: 0 loss: 0.10268573462963104
epoch: 9 step: 100 loss: 0.10163718461990356
epoch: 9 step: 200 loss: 0.10121693462133408
epoch: 10 step: 0 loss: 0.09949333965778351
epoch: 10 step: 100 loss: 0.09859145432710648
epoch: 10 step: 200 loss: 0.09819269925355911
epoch: 11 step: 0 loss: 0.0966767817735672
epoch: 11 step: 100 loss: 0.09586615860462189
epoch: 11 step: 200 loss: 0.09550992399454117
epoch: 12 step: 0 loss: 0.09417577087879181
epoch: 12 step: 100 loss: 0.09341947734355927
epoch: 12 step: 200 loss: 0.09310202300548553
epoch: 13 step: 0 loss: 0.09193204343318939
epoch: 13 step: 100 loss: 0.09122277796268463
epoch: 13 step: 200 loss: 0.09092779457569122
epoch: 14 step: 0 loss: 0.0899026170372963
epoch: 14 step: 100 loss: 0.08923697471618652
epoch: 14 step: 200 loss: 0.08895798027515411
epoch: 15 step: 0 loss: 0.08804921805858612
epoch: 15 step: 100 loss: 0.08742769062519073
epoch: 15 step: 200 loss: 0.0871589332818985
epoch: 16 step: 0 loss: 0.08635203540325165
epoch: 16 step: 100 loss: 0.0857706069946289
epoch: 16 step: 200 loss: 0.0855005756020546
epoch: 17 step: 0 loss: 0.08479145169258118
epoch: 17 step: 100 loss: 0.08423925191164017
epoch: 17 step: 200 loss: 0.08396687358617783
epoch: 18 step: 0 loss: 0.08334997296333313
epoch: 18 step: 100 loss: 0.08281457424163818
epoch: 18 step: 200 loss: 0.08254452794790268
epoch: 19 step: 0 loss: 0.08201286941766739
epoch: 19 step: 100 loss: 0.08149122446775436
epoch: 19 step: 200 loss: 0.08122102916240692

到此这篇关于详解TensorFlow2实现前向传播的文章就介绍到这了,更多相关TensorFlow2前向传播内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • tensorflow基本操作小白快速构建线性回归和分类模型

    目录 tensorflow是非常强的工具,生态庞大 tensorflow提供了Keras的分支 Define tensor constants. Linear Regression 分类模型 本例使用MNIST手写数字 Model prediction: 7 Model prediction: 2 Model prediction: 1 Model prediction: 0 Model prediction: 4 TF 目前发布2.5 版本,之前阅读1.X官方文档,最近查看2.X的文档. te

  • pytorch实现线性回归

    pytorch实现线性回归代码练习实例,供大家参考,具体内容如下 欢迎大家指正,希望可以通过小的练习提升对于pytorch的掌握 # 随机初始化一个二维数据集,使用朋友torch训练一个回归模型 import numpy as np import random import matplotlib.pyplot as plt x = np.arange(20) y = np.array([5*x[i] + random.randint(1,20) for i in range(len(x))])

  • python深度总结线性回归

    目录 概述 例子 通俗解释 数学推导 误差 评估方法 梯度下降 批量梯度下降 随机梯度下降 小批量梯度下降法 案例一 概述 线性回归的定义是: 目标值预期是输入变量的线性组合. 线性模型形式简单, 易于建模, 但却蕴含着机器学习中一些重要的基本思想. 线性回归, 是利用数理统计中回归分析, 来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法, 运用十分广泛. 优点: 结果易于理解, 计算不复杂 缺点: 对非线性的数据拟合不好 例子 数据: 工资和年龄 (2 个特征) 目标: 预测银行

  • python实现线性回归算法

    本文用python实现线性回归算法,供大家参考,具体内容如下 # -*- coding: utf-8 -*- """ Created on Fri Oct 11 19:25:11 2019 """ from sklearn import datasets, linear_model # 引用 sklearn库,主要为了使用其中的线性回归模块 # 创建数据集,把数据写入到numpy数组 import numpy as np # 引用numpy库,主

  • 使用pytorch实现线性回归

    本文实例为大家分享了pytorch实现线性回归的具体代码,供大家参考,具体内容如下 线性回归都是包括以下几个步骤:定义模型.选择损失函数.选择优化函数. 训练数据.测试 import torch import matplotlib.pyplot as plt # 构建数据集 x_data= torch.Tensor([[1.0],[2.0],[3.0],[4.0],[5.0],[6.0]]) y_data= torch.Tensor([[2.0],[4.0],[6.0],[8.0],[10.0]

  • python机器学习之线性回归详解

    一.python机器学习–线性回归 线性回归是最简单的机器学习模型,其形式简单,易于实现,同时也是很多机器学习模型的基础. 对于一个给定的训练集数据,线性回归的目的就是找到一个与这些数据最吻合的线性函数. 二.OLS线性回归 2.1 Ordinary Least Squares 最小二乘法 一般情况下,线性回归假设模型为下,其中w为模型参数 线性回归模型通常使用MSE(均方误差)作为损失函数,假设有m个样本,均方损失函数为:(所有实例预测值与实际值误差平方的均值) 由于模型的训练目标为找到使得损

  • 回归预测分析python数据化运营线性回归总结

    目录 内容介绍 一般应用场景 线性回归的常用方法 线性回归实现 线性回归评估指标 线性回归效果可视化 数据预测 内容介绍 以 Python 使用 线性回归 简单举例应用介绍回归分析. 线性回归是利用线性的方法,模拟因变量与一个或多个自变量之间的关系: 对于模型而言,自变量是输入值,因变量是模型基于自变量的输出值,适用于x和y满足线性关系的数据类型的应用场景. 用于预测输入变量和输出变量之间的关系,特别是当输入变量的值发生变化时,输出变量的值也随之发生变化. 回归模型正是表示从输入变量到输出变量之

  • 详解TensorFlow2实现前向传播

    目录 概述 会用到的函数 张量最小值 张量最大值 数据集分批 迭代 截断正态分布 relu 激活函数 one_hot assign_sub 准备工作 train 函数 run 函数 完整代码 概述 前向传播 (Forward propagation) 是将上一层输出作为下一层的输入, 并计算下一层的输出, 一直到运算到输出层为止. 会用到的函数 张量最小值 ```reduce_min``函数可以帮助我们计算一个张量各个维度上元素的最小值. 格式: tf.math.reduce_min( inpu

  • 详解tensorflow2.x版本无法调用gpu的一种解决方法

    最近学校给了一个服务器账号用来训练神经网络使用,服务器本身配置是十路titan V,然后在上面装了tensorflow2.2,对应的python版本是3.6.2,装好之后用tf.test.is_gpu_available()查看是否能调用gpu,结果返回结果是false,具体如下: 这里tensorflow应该是检测出了gpu,但是因为某些库无法打开而导致tensorflow无法调用,返回了false,详细查看错误信息可以看到一行: 可以看到上面几个文件都顺利打开了,但是最后一个libcudnn

  • 详解TensorFlow2实现线性回归

    目录 概述 MSE 线性回归 公式 梯度下降 线性回归实现 计算 MSE 梯度下降 迭代训练 主函数 完整代码 概述 线性回归 (Linear Regression) 是利用回归分析来确定两种或两种以上变量间相互依赖的定量关系. 对线性回归还不是很了解的同学可以看一下这篇文章: python深度总结线性回归 MSE 均方误差 (Mean Square Error): 是用来描述连续误差的一种方法. 公式: y_predict: 我们预测的值y_real: 真实值 线性回归 公式 w: weigh

  • 详解Vue3.0 前的 TypeScript 最佳入门实践

    前言 我个人对更严格类型限制没有积极的看法,毕竟各类转类型的骚写法写习惯了. 然鹅最近的一个项目中,是 TypeScript + Vue ,毛计喇,学之...-真香! 注意此篇标题的"前",本文旨在讲Ts混入框架的使用,不讲Class API 1. 使用官方脚手架构建 npm install -g @vue/cli # OR yarn global add @vue/cli 新的 Vue CLI 工具允许开发者 使用 TypeScript 集成环境 创建新项目. 只需运行 vue cr

  • Json转化为Java对象的实例详解

    Json转化为Java对象的实例详解 问题:前后端数据交互时,经常会遇到Json串与Java对象转化的问题,有的Java对象中还包含了List对象等. 解决方案: 引入 json-lib包,Maven坐标如下: <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> &l

  • Spring事物的传播特性详解

    一.事务的传播性 研究的是多个事务存在时的处理策略 1)REQUIRED:如果存在一个事务,则支持当前事务,如果当前没有事务,就新建一个事务.这是最常见的选择. 2)SUPPORTS:如果存在一个事务,支持当前事务,如果当前没有事务,就以非事务方式执行. 3)MANDATORY:如果存在一个事务,支持当前事务,如果当前没有事务,就抛出异常. 4)REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起. 5)NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前

  • Spring 事务隔离与事务传播的详解与对比

    Spring 事务隔离与事务传播的详解与对比 Spring是SSH中的管理员,负责管理其它框架,协调各个部分的工作.今天一起学习一下Spring的事务管理.Spring的事务管理分为声明式跟编程式.声明式就是在Spring的配置文件中进行相关配置:编程式就是用注解的方式写到代码里. Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分. DataSource. Tr

  • PHP数字前补0的自带函数sprintf 和number_format的用法(详解)

    很多时候我们需要对数字进行格式化,比如位数不足前面加0补足.用PHP可以很轻易实现,因为PHP自带了相关功能的函数. <?php //生成4位数,不足前面补0 $var=sprintf("%04d", 2); echo $var;//结果为0002 echo date('Y_m_d', time()).'_'.sprintf('d', rand(0,99)); echo sprintf('%05s',444);//输出5为字符串,不足以0补充 ?> sprintf()函数

  • vue.js前后端数据交互之提交数据操作详解

    本文实例讲述了vue.js前后端数据交互之提交数据操作.分享给大家供大家参考,具体如下: 前端小白刚开始做页面的时候,我们的前端页面中经常会用到表单,所以学会提交表单也是一个基本技能,其实用ajax就能实现,但他的原始语法有点...额 ...复杂,所以这里给大家提供一种用vue-resource向后端提交数据. (1)第一步,先在template中写一个表单: <el-form :model="ruleForm" :rules="rules" ref=&quo

  • 详解.net core webapi 前后端开发分离后的配置和部署

    背景:现在越来越多的企业都采用了在开发上前后端分离,前后端开发上的分离有很多种,那么今天,我来分享一下项目中得的前后端分离. B/S Saas 项目:(这个项目可以理解成个人中心,当然不止这么点功能) 前端:node.js + vue 后端:.net core webapi 前端安装 node.js 跟创建vue项目这些不是这篇文章的重点,重点在于项目完成后的部署. .net corewebapi创建后,默认就创建了一个wwwroot的文件夹,这个文件夹是用来放置静态文件的,所以,我们可以理解成

随机推荐