【学习笔记】深度学习入门:基于Python的理论与实现-神经网络的学习

news2024/11/22 15:00:37

CONTENTS

    • 四、神经网络的学习
      • 4.1 从数据中学习
      • 4.2 Loss function
      • 4.3 数值微分
      • 4.4 梯度
      • 4.5 学习算法的实现

四、神经网络的学习

4.1 从数据中学习

神经网络的特征就是可以从数据中学习。所谓“从数据中学习”,是指可以由数据自动决定权重参数的值。利用特征量和机器学习的方法中,特征量仍是由人工设计的,而在神经网络中,连图像中包含的重要特征量也都是由机器来学习的。

机器学习中,一般将数据分为训练数据测试数据两部分来进行学习和实验等。首先,使用训练数据进行学习,寻找最优的参数;然后,使用测试数据评价训练得到的模型的实际能力。为什么需要将数据分为训练数据和测试数据呢?因为我们追求的是模型的泛化能力。为了正确评价模型的泛化能力,就必须划分训练数据和测试数据。另外,训练数据也可以称为监督数据

泛化能力是指处理未被观察过的数据(不包含在训练数据中的数据)的能力。获得泛化能力是机器学习的最终目标。只对某个数据集过度拟合的状态称为过拟合 o v e r   f i t t i n g over\ fitting over fitting)。避免过拟合也是机器学习的一个重要课题。

4.2 Loss function

神经网络的学习通过某个指标表示现在的状态。然后,以这个指标为基准,寻找最优权重参数。神经网络的学习中所用的指标称为损失函数 l o s s   f u n c t i o n loss\ function loss function)。这个损失函数可以使用任意函数,但一般用均方误差交叉熵误差等。

均方误差如下式所示,其中, y k y_k yk表示神经网络的输出, t k t_k tk表示监督数据, k k k表示数据的维数,均方误差会计算神经网络的输出和正确解监督数据的各个元素之差的平方,再求总和:

在这里插入图片描述

使用Python实现代码如下:

def mean_squared_error(y, t):
	return 0.5 * np.sum((y - t) ** 2)

举个例子计算一下:

# 设2为正确解
t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]

# 例1:2的概率最高的情况(0.6)
y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
mean_squared_error(np.array(y), np.array(t))  # 0.097500000000000031

# 例2:7的概率最高的情况(0.6)
y = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
mean_squared_error(np.array(y), np.array(t))  # 0.59750000000000003

交叉熵误差如下式所示,其中, y k y_k yk表示神经网络的输出, t k t_k tk表示正确解标签,且 t k t_k tk中只有正确解标签的索引为 1 1 1,其他均为 0 0 0 o n e − h o t one-hot onehot表示):

在这里插入图片描述

该式实际上只计算对应正确解标签的输出的自然对数。比如,假设正确解标签的索引是 “ 2 ” “2” 2,与之对应的神经网络的输出是 0.6 0.6 0.6,则交叉熵误差是 − l o g   0.6 = 0.51 -log\ 0.6=0.51 log 0.6=0.51;若 “ 2 ” “2” 2对应的输出是 0.1 0.1 0.1,则交叉熵误差为 − l o g   0.1 = 2.30 -log\ 0.1=2.30 log 0.1=2.30。也就是说,交叉熵误差的值是由正确解标签所对应的输出结果决定的。

使用Python实现代码如下:

def cross_entropy_error(y, t):
	delta = 1e-7
	return -np.sum(t * np.log(y + delta))

函数内部在计算np.log时,加上了一个微小值delta。这是因为,当出现np.log(0)时,结果会变为负无穷大的,这样一来就会导致后续计算无法进行。

举个例子计算一下:

t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
cross_entropy_error(np.array(y), np.array(t))  # 0.51082545709933802

y = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
cross_entropy_error(np.array(y), np.array(t))  # 2.3025840929945458

使用训练数据进行学习,严格来说,就是针对训练数据计算损失函数的值,找出使该值尽可能小的参数。计算损失函数时必须将所有的训练数据作为对象。计算损失函数时必须将所有的训练数据作为对象,如果要求所有训练数据的损失函数的总和,以交叉熵误差为例,可以写成下面的式子:

在这里插入图片描述

假设数据有 N N N个, t n k t_{nk} tnk表示第 n n n个数据的第 k k k个元素的值( y n k y_{nk} ynk是神经网络的输出, t n k t_{nk} tnk是监督数据)。

由于MNIST数据集的训练数据有 60000 60000 60000个,如果以全部数据为对象求损失函数的和,则计算过程需要花费较长的时间。因此,我们从全部数据中选出一部分,作为全部数据的“近似”。神经网络的学习也是从训练数据中选出一批数据(称为 m i n i − b a t c h mini-batch minibatch,小
批量),然后对每个 m i n i − b a t c h mini-batch minibatch进行学习。

假设要从这个训练数据中随机抽取10笔数据,可以使用如下代码,使用np.random.choice()可以从指定的数字中随机选择想要的数字。比如,np.random.choice(60000, 10)会从 0 0 0 59999 59999 59999之间随机选择 10 10 10个数字:

train_size = x_train.shape[0]
batch_size = 10
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]

改良交叉熵误差代码,实现一个可以同时处理单个数据和批量数据(数据作为 b a t c h batch batch集中输入)两种情况的函数:

def cross_entropy_error(y, t):
	if y.ndim == 1:
		t = t.reshape(1, t.size)
		y = y.reshape(1, y.size)
	batch_size = y.shape[0]
	return -np.sum(t * np.log(y + 1e-7)) / batch_size

当监督数据是标签形式(非 o n e − h o t one-hot onehot表示,而是像 “ 2 ” , “ 7 ” “2”,“7” 2,7这样的标签)时,交叉熵误差可通过如下代码实现:

def cross_entropy_error(y, t):
	if y.ndim == 1:
		t = t.reshape(1, t.size)
		y = y.reshape(1, y.size)
	batch_size = y.shape[0]
	return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size

# 假设batch_size = 5, t = [2, 7, 0, 9, 4]
# 则y[np.arange(batch_size), t] = [y[0, 2], y[1, 7], y[2, 0], y[3, 9], y[4, 4]]

4.3 数值微分

导数就是表示某个瞬间的变化量,它可以定义成下面的式子:

在这里插入图片描述

但是该式子计算时存在误差,因为真的导数是对应函数在 x x x处的斜率(称为切线),但上述实现中计算的导数对应的是 ( x + h ) (x+h) (x+h) x x x之间的斜率(如下图所示)。为了减小这个误差,我们可以计算函数 f f f ( x + h ) (x+h) (x+h) ( x − h ) (x-h) (xh)之间的差分。因为这种计算方法以 x x x为中心,计算它左右两边的差分,所以也称为中心差分(而 ( x + h ) (x+h) (x+h) x x x之间的差分称为前向差分)。

在这里插入图片描述

使用Python实现代码如下:

def numerical_diff(f, x):
	h = 1e-4 # 0.0001
	return (f(x + h) - f(x - h)) / (2 * h)

现在假设我们有一个一元二次函数: y = 0.01 x 2 + 0.1 x y=0.01x^2+0.1x y=0.01x2+0.1x,使用Python实现该式如下:

def function_1(x):
	return 0.01 * x ** 2 + 0.1 * x

我们来计算一下这个函数在 x = 5 x=5 x=5 和 x = 10 和x=10 x=10处的导数:

numerical_diff(function_1, 5)  # 0.1999999999990898
numerical_diff(function_1, 10)  # 0.2999999999986347

接下来我们来看另一个函数: f ( x 0 , x 1 ) = x 0 2 + x 1 2 f(x_0,x_1)=x_0^2+x_1^2 f(x0,x1)=x02+x12,和上例不同的是,这里有两个变量,使用Python实现该式如下:

def function_2(x):
	return x[0] ** 2 + x[1] ** 2
	# 或者return np.sum(x ** 2)

因为该式有两个变量,因此有必要区分对哪个变量求导数,有多个变量的函数的导数称为偏导数。用数学式表示的话,可以写成 ∂ f ∂ x 0 , ∂ f ∂ x 1 \frac {\partial f}{\partial x_0},\frac {\partial f}{\partial x_1} x0f,x1f。偏导数需要将多个变量中的某一个变量定为目标变量,并将其他变量固定为某个值(即常数)。

例如求 x 0 = 3 , x 1 = 4 x_0=3,x_1=4 x0=3,x1=4时,关于 x 0 x_0 x0的偏导数 ∂ f ∂ x 0 \frac {\partial f}{\partial x_0} x0f

def function_tmp1(x0):
	return x0 * x0 + 4.0 ** 2.0

numerical_diff(function_tmp1, 3.0)  # 6.00000000000378

4.4 梯度

( ∂ f ∂ x 0 , ∂ f ∂ x 1 ) (\frac {\partial f}{\partial x_0},\frac {\partial f}{\partial x_1}) (x0f,x1f)这样的由全部变量的偏导数汇总而成的向量称为梯度 g r a d i e n t gradient gradient),梯度指示的方向是各点处的函数值减小最多的方向。梯度可以像下面这样来实现:

def numerical_gradient(f, x):
    h = 1e-4  # 0.0001
    grad = np.zeros_like(x)  # 会生成一个形状和x相同,所有元素都为0的数组
    
    it = np.nditer(x, flags = ['multi_index'], op_flags = ['readwrite'])
    while not it.finished:
        idx = it.multi_index
        tmp_val = x[idx]
        x[idx] = float(tmp_val) + h
        fxh1 = f(x)  # f(x + h)
        
        x[idx] = float(tmp_val) - h
        fxh2 = f(x)  # f(x - h)
        grad[idx] = (fxh1 - fxh2) / (2 * h)
        
        x[idx] = tmp_val  # 还原值
        it.iternext()
    return grad

神经网络必须在学习时找到最优参数(权重和偏置)。这里所说的最优参数是指损失函数取最小值时的参数,通过巧妙地使用梯度来寻找函数最小值(或者尽可能小的值)的方法就是梯度法。由于梯度表示的是各点处的函数值减小最多的方向,无法保证梯度所指的方向就是函数的最小值或者真正应该前进的方向。虽然梯度的方向并不一定指向最小值,但沿着它的方向能够最大限度地减小函数的值。

现在,我们尝试用数学式来表示梯度法,如下式所示:

在这里插入图片描述

式中的 η \eta η表示更新量,在神经网络的学习中,称为学习率( l e a r n i n g   r a t e learning\ rate learning rate)。学习率决定在一次学习中,应该学习多少,以及在多大程度上更新参数。

学习率需要事先确定为某个值,比如 0.01 0.01 0.01 0.001 0.001 0.001。一般而言,这个值过大或过小,都无法抵达一个“好的位置”。在神经网络的学习中,一般会一边改变学习率的值,一边确认学习是否正确进行了。

使用Python实现梯度下降法如下,其中参数 f f f是要进行最优化的函数, i n i t _ x init\_x init_x是初始值, l r lr lr是学习率 l e a r n i n g   r a t e learning\ rate learning rate s t e p _ n u m step\_num step_num是梯度法的重复次数:

def gradient_descent(f, init_x, lr=0.01, step_num=100):
	x = init_x
	for i in range(step_num):
		grad = numerical_gradient(f, x)
		x -= lr * grad
	return x

实验结果表明,学习率过大的话,会发散成一个很大的值;反过来,学习率过小的话,基本上没怎么更新就结束了。也就是说,设定合适的学习率是一个很重要的问题。

神经网络中的梯度是指损失函数关于权重参数的梯度:

在这里插入图片描述

我们以一个简单的神经网络为例,来实现求梯度的代码。为此,我们要实现一个名为simpleNet的类:

class simpleNet:
	def __init__(self):
		self.W = np.random.randn(2, 3)  # 用高斯分布进行初始化

	def predict(self, x):
		return np.dot(x, self.W)

	def loss(self, x, t):
		z = self.predict(x)
		y = softmax(z)
		loss = cross_entropy_error(y, t)
		return loss

试着用一下simpleNet

net = simpleNet()
x = np.array([0.6, 0.9])
p = net.predict(x)
print(p)  # [1.05414809, 0.63071653, 1.1328074]
np.argmax(p)  # 2,最大值的索引
t = np.array([0, 0, 1])  # 正确解标签
net.loss(x, t)  # 0.92806853663411326

接下来求梯度:

def f(W):
	return net.loss(x, t)
dW = numerical_gradient(f, net.W)

Python中如果定义的是简单的函数,可以使用 l a m b d a lambda lambda表示法。使用 l a m b d a lambda lambda的情况下,上述代码可以如下实现:

f = lambda w: net.loss(x, t)
dW = numerical_gradient(f, net.W)

4.5 学习算法的实现

我们先来确认一下神经网络的学习步骤,顺便复习一下这些内容:

  • (1) m i n i − b a t c h mini-batch minibatch:从训练数据中随机选出一部分数据;
  • (2)计算梯度:为了减小 m i n i − b a t c h mini-batch minibatch的损失函数的值,需要求出各个权重参数的梯度;
  • (3)更新参数:将权重参数沿梯度方向进行微小更新;
  • (4)重复:重复以上三个步骤。

神经网络的学习按照上面 4 4 4个步骤进行。这个方法通过梯度下降法更新参数,不过因为这里使用的数据是随机选择的 m i n i − b a t c h mini-batch minibatch数据,所以又称为随机梯度下降法

下面,我们来实现手写数字识别的 2 2 2层神经网络(隐藏层为 1 1 1层)。我们将这个 2 2 2层神经网络实现为一个名为TwoLayerNet的类,实现过程如下所示:

class TwoLayerNet:
    def __init__(self, input_size, hidden_size, output_size, weight_init_std = 0.01):
        # 初始化权重
        self.params = {}
        self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['b1'] = np.zeros(hidden_size)
        self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
        self.params['b2'] = np.zeros(output_size)
        
    def predict(self, x):
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']
        
        a1 = np.dot(x, W1) + b1
        z1 = sigmoid(a1)
        a2 = np.dot(z1, W2) + b2
        y = softmax(a2)
        
        return y
    
    def loss(self, x, t):
        y = self.predict(x)
        return cross_entropy_error(y, t)
    
    def accuracy(self, x, t):
        y = self.predict(x)
        y = np.argmax(y, axis = 1)
        t = np.argmax(t, axis = 1)
        accuracy = np.sum(y == t) / float(x.shape[0])
        return accuracy
    
    def numerical_gradient(self, x, t):
        loss_W = lambda W: self.loss(x, t)
        
        grads = {}
        grads['W1'] = numerical_gradient(loss_W, self.params['W1'])
        grads['b1'] = numerical_gradient(loss_W, self.params['b1'])
        grads['W2'] = numerical_gradient(loss_W, self.params['W2'])
        grads['b2'] = numerical_gradient(loss_W, self.params['b2'])
        
        return grads

接下来,我们就以TwoLayerNet类为对象,使用MNIST数据集进行学习:

import sys
sys.path.append('D:\VS Code Project\Deep Learning')
import numpy as np
import matplotlib.pylab as plt
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet

# 读入数据
(x_train, t_train), (x_test, t_test) = load_mnist(normalize = True, one_hot_label = True)

network = TwoLayerNet(input_size = 784, hidden_size = 50, output_size = 10)

# 超参数
iters_num = 10000  # 适当设定循环的次数
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1  # 学习率

train_loss_list = []
train_acc_list = []
test_acc_list = []

iter_per_epoch = max(train_size / batch_size, 1)

for i in range(iters_num):
    # 获取mini-batch
    batch_mask = np.random.choice(train_size, batch_size)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]
    
    # 计算梯度
    grad = network.numerical_gradient(x_batch, t_batch)
    # grad = network.gradient(x_batch, t_batch)  # 误差反向传播法高速计算梯度
    
    # 更新参数
    for key in ('W1', 'b1', 'W2', 'b2'):
        network.params[key] -= learning_rate * grad[key]
    
    # 记录学习过程
    loss = network.loss(x_batch, t_batch)
    train_loss_list.append(loss)
    
    if i % iter_per_epoch == 0:
        train_acc = network.accuracy(x_train, t_train)
        test_acc = network.accuracy(x_test, t_test)
        train_acc_list.append(train_acc)
        test_acc_list.append(test_acc)
        print("train acc, test acc | " + str(train_acc) + ", " + str(test_acc))
        
# 绘制图形
markers = {'train': 'o', 'test': 's'}
x = np.arange(len(train_acc_list))
plt.plot(x, train_acc_list, label = 'train acc')
plt.plot(x, test_acc_list, label = 'test acc', linestyle = '--')
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.ylim(0, 1.0)
plt.legend(loc = 'lower right')
plt.show()

神经网络学习的最初目标是掌握泛化能力,因此,要评价神经网络的泛化能力,就必须使用不包含在训练数据中的数据。上述的代码在进行学习的过程中,会定期地对训练数据和测试数据记录识别精度。这里,每经过一个 e p o c h epoch epoch,我们都会记录下训练数据和测试数据的识别精度。 e p o c h epoch epoch是一个单位。一个 e p o c h epoch epoch表示学习中所有训练数据均被使用过一次时的更新次数。比如,对于 10000 10000 10000笔训练数据,用大小为 100 100 100笔数据的 m i n i − b a t c h mini-batch minibatch进行学习时,重复随机梯度下降法 100 100 100次,就相当于所有的训练数据就都被“看过”了。

绘图结果如下图所示:

在这里插入图片描述

如上图所示,随着 e p o c h epoch epoch的前进(学习的进行),我们发现使用训练数据和测试数据评价的识别精度都提高了,并且,这两个识别精度基本上没有差异(两条线基本重叠在一起)。因此,可以说这次的学习中没有发生过拟合的现象。

下一节:【学习笔记】深度学习入门:基于Python的理论与实现-误差反向传播法。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HBase 开发:使用Java操作HBase 第1关:创建表

为了完成本关任务,你需要掌握:1.如何使用Java连接HBase数据库,2.如何使用Java代码在HBase中创建表。 如何使用Java连接HBase数据库 Java连接HBase需要两个类: HBaseConfigurationConnectionFactoryHBaseConfiguration 要连接HBase…

SPARKSQL3.0-Spark兼容多版本Hive源码分析

一、前言 阅读本节需要先掌握Catalog基础知识 Spark对Hive的所有操作都是通过获取Hive元数据[metastore]帮助spark构建表信息从而调用HDFS-API对原始数据的操作,可以说Spark兼容多版本Hive就是在兼容Hive的Metastore 二、源码分析 在catalog一节中我们知道spark…

二.maven常用功能点

maven常用功能点一:分模块开发设计二:聚合三:继承1.依赖的继承2.可继承的内容3.聚合与继承的区分四:属性1.自定义属性2.内置属性3.Setting属性4.java系统属性5.环境变量属性五:java配置文件引用pom属性六:多…

基于PHP+MySQL大学生心理健康管理系统的设计与实现

随着时代的发展,大学生的数量与日预增但是相对的也出现了很多心理问题,大学生自杀等心理问题引起的问题屡见不鲜如何能过更好的培养大学生正确的心理健康问题是现在很多大学多面临的一个重要的问题。本系统主要是对共享自行车的信息进行管理。该系统的基本功能包括用户登录,用户…

云小课|云小课带你玩转可视化分析ELB日志

阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说)、深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云。更多精彩内容请单击此处。 云日志服务支持可视化查看日志,当ELB日志接入云日志服务后&a…

[附源码]计算机毕业设计springboot青栞系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

野火FPGA进阶(3):SDRAM读写控制器的设计与验证

文章目录第50讲:SDRAM读写控制器的设计与验证理论部分设计与实现1. sdram_ctrlsdram_initsdram_a_refsdram_writesdram_readsdram_arbitsdram_ctrl2. sdram_topfifo_ctrlsdram_top3. uart_sdramuart_rxuart_txfifo_readuart_sdram第50讲:SDRAM读写控制器…

[附源码]JAVA毕业设计工程车辆动力电池管理系统(系统+LW)

[附源码]JAVA毕业设计工程车辆动力电池管理系统(系统LW) 目运行 环境项配置: Jdk1.8 Tomcat8.5 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 …

怎么在Windows下使用Makefile文件

前言:如果熟悉在Linux开发的话,肯定知道Makefile文件的用处,它给我们带来很多的便利。在Linux系统下并不会像Windows那么多开发工具,在Windows下,只要在开发工具上点击一个按钮,就能将工程的所有源码进行编…

365天深度学习训练营-第P2周:彩色图片识别

目录 一、前言 二、我的环境 三、代码实现 1、数据下载以及可视化 2、CNN模型 3、训练结果可视化 4、随机图像预测 四、模型优化 1、CNN模型 2、VGG-16模型 3、Alexnet模型 4、Resnet模型 一、前言 >- **🍨 本文为[🔗365天深度学习训练营]…

2022年钒电池行业研究报告

第一章 行业概况 钒电池(Vanadium Redox Battery,缩写为VRB),全称为全钒氧化还原液流电池,是一种活性物质呈循环流动液态的氧化还原电池。钒电池可以作为大容量储能电站的电池,其工作原理如下:…

Unity 2021 请求 Android 12 读取本地文件权限

目标 工具: Unity 2021.2.14c1f1Android 12 系统手机 目标:实现Unity打出来的Apk包能请求读写android手机本地文件权限 原理 在Android系统中,操作手机中不安全的数据时,需要配置相应的权限,只有经过用户许可才能…

[附源码]JAVA毕业设计个人信息管理系统(系统+LW)

[附源码]JAVA毕业设计个人信息管理系统(系统LW) 目运行 环境项配置: Jdk1.8 Tomcat8.5 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术…

深度学习-第三章概率与信息论

前言 概率论学科定义概率与信息论在人工智能领域的应用 3.1,为什么要使用概率论3.2,随机变量3.3,概率分布 3.3.1,离散型变量和概率质量函数3.3.2,连续型变量和概率密度分布函数 3.4,边缘概率3.5&#xff0c…

量子计算新突破!来源于150年前的思想实验

澳大利亚新南威尔士大学的研究表明,使用现代版本的“麦克斯韦妖”,可将量子比特重置为“0”态的错误减少了20倍。 Andrea Morello教授解释了麦克斯韦妖思想实验如何与他的团队通过仅选择冷电子进行量子计算的成就相类比。(图片来源&#xff1…

Go-Windows环境的快速搭建

下载 Downloads - The Go Programming Language 或者直接到指定版本下载可以根据个人喜好,下载zip或者执行版 下载后文件夹 查看版本 必须查看版本,通过go version命令进行查看最新版本1.19.3版本 配置的GoPath 已经自动配置进去 需要重新进入一个新的…

HBuilder X 导入git项目以及拉取和推送

1. 首先在 HB中 > 工具 > 插件安装 > Git插件 2. 安装好 Git 插件之后还要安装一个 tortoisegit (小乌龟) tortoisegit : 这里根据电脑下载对应的位数,需要转换成中文的可以下载中文包: 安装 tortoisegit : 1. 双击刚刚下载的msi文件进入安装 2. 连续两次next之后…

[附源码]计算机毕业设计JAVA校园环境保护监督系统

[附源码]计算机毕业设计JAVA校园环境保护监督系统 项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM my…

虚拟机NAL模式连接linux系统

windows虚拟机连外网,相当于设置双网卡,虚拟机编辑网关如下: 在window系统查看设置vmnet8 在linux系统配置ip静态网址 cd /etc/sysconfig/network-scripts/ vim ifcfg-ens33在linux上重启网卡。 在window上添加路由,先查询路由&a…

C语言经典题目之字符串逆序

目录 一、字符串逆序(基础题) 1.一个经典的错误,标准的零分 2.采用gets函数来修补漏洞 ​编辑 3.非要使用scanf怎么办? 4.使用指针来实现逆序函数 5.将函数修改为,只要传入两个地址,就能逆序这两个地址…