使用遗传算法计算神经网络的超参数

news2024/11/24 16:30:33

遗传算法是基于种群的思想,将问题的解通过编码的方式转化为种群中的个体,并让这些个体不断地通过选择、交叉和变异算子模拟生物的进化过程然后利用“优胜劣汰”法则选择种群中适应性较强的个体构成子种群,然后让子种群重复类似的进化过程,直到找到问题的最优解或者到达一定的进化(运算)时间。

个体(染色体):自然界中一个个体(染色体)代表一个生物,在GA算法中,个体(染色体)代表了具体问题的一个解。

基因:在GA算法中,基因代表了具体问题解的一个决策变量。

种群:多个个体即组成一个种群。GA算法中,一个问题的多组解即构成了问题的解的种群。

Step 1. 种群初始化。首先随机生成一些个体。然后通过编码的方式,编码为一个向量表示。这里是为了方便后面的种群的交叉变异。将个体(可能解)编码后的二进制串叫做染色体染色体(或者有人叫DNA)就是个体(可能解)的二进制编码表示

Step 2. 评估种群。利用启发式算法对种群中的个体(矩形件的排入顺序)生成排样图并依此计算个体的适应函数值(利用率),然后保存当前种群中的最优个体作为搜索到的最优解。

Step 3. 选择操作。根据种群中个体的适应度的大小,通过轮盘赌或者期望值方法,将适应度高的个体从当前种群中选择出来。

Step 4. 交叉操作。将上一步骤选择的个体,用一定的概率阀值Pc控制是否利用单点交叉、多点交叉或者其他交叉方式生成新的交叉个体。

Step 5. 变异操作。用一定的概率阀值Pm控制是否对个体的部分基因执行单点变异或多点变异。

Step 6. 终止判断。若满足终止条件,则终止算法,否则返回Step 2。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D

DNA_SIZE = 4
POP_SIZE = 100
CROSSOVER_RATE = 0.8
MUTATION_RATE = 0.005
N_GENERATIONS = 10
X_BOUND = [-3, 3]
Y_BOUND = [-3, 3]


def F(x, y):
    return 3 * (1 - x) ** 2 * np.exp(-(x ** 2) - (y + 1) ** 2) - 10 * (x / 5 - x ** 3 - y ** 5) * np.exp(
        -x ** 2 - y ** 2) - 1 / 3 ** np.exp(-(x + 1) ** 2 - y ** 2)


def plot_3d(ax):
    X = np.linspace(*X_BOUND, 100)
    Y = np.linspace(*Y_BOUND, 100)
    X, Y = np.meshgrid(X, Y)
    Z = F(X, Y)
    ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm)
    ax.set_zlim(-10, 10)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    plt.pause(3)
    plt.show()


def get_fitness(pop):
    x, y = translateDNA(pop)
    pred = F(x, y)
    return (pred - np.min(
        pred)) + 1e-3  # 减去最小的适应度是为了防止适应度出现负数,通过这一步fitness的范围为[0, np.max(pred)-np.min(pred)],最后在加上一个很小的数防止出现为0的适应度


def translateDNA(pop):  # pop表示种群矩阵,一行表示一个二进制编码表示的DNA,矩阵的行数为种群数目
    x_pop = pop[:, 1::2]  # 奇数列表示X
    y_pop = pop[:, ::2]  # 偶数列表示y

    # pop:(POP_SIZE,DNA_SIZE)*(DNA_SIZE,1) --> (POP_SIZE,1)
    x = x_pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2 ** DNA_SIZE - 1) * (X_BOUND[1] - X_BOUND[0]) + X_BOUND[0]
    y = y_pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2 ** DNA_SIZE - 1) * (Y_BOUND[1] - Y_BOUND[0]) + Y_BOUND[0]
    return x, y


def crossover_and_mutation(pop, CROSSOVER_RATE=0.8):
    new_pop = []
    for father in pop:  # 遍历种群中的每一个个体,将该个体作为父亲
        child = father  # 孩子先得到父亲的全部基因(这里我把一串二进制串的那些0,1称为基因)
        if np.random.rand() < CROSSOVER_RATE:  # 产生子代时不是必然发生交叉,而是以一定的概率发生交叉
            mother = pop[np.random.randint(POP_SIZE)]  # 再种群中选择另一个个体,并将该个体作为母亲
            cross_points = np.random.randint(low=0, high=DNA_SIZE * 2)  # 随机产生交叉的点
            child[cross_points:] = mother[cross_points:]  # 孩子得到位于交叉点后的母亲的基因
        mutation(child)  # 每个后代有一定的机率发生变异
        new_pop.append(child)

    return new_pop


def mutation(child, MUTATION_RATE=0.003):
    if np.random.rand() < MUTATION_RATE:  # 以MUTATION_RATE的概率进行变异
        mutate_point = np.random.randint(0, DNA_SIZE * 2)  # 随机产生一个实数,代表要变异基因的位置
        child[mutate_point] = child[mutate_point] ^ 1  # 将变异点的二进制为反转


def select(pop, fitness):  # nature selection wrt pop's fitness
    idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True,
                           p=(fitness) / (fitness.sum()))
    return pop[idx]


def print_info(pop):
    fitness = get_fitness(pop)
    max_fitness_index = np.argmax(fitness)
    print("max_fitness:", fitness[max_fitness_index])
    x, y = translateDNA(pop)
    print("最优的基因型:", pop[max_fitness_index])
    print("(x, y):", (x[max_fitness_index], y[max_fitness_index]))


if __name__ == "__main__":
    fig = plt.figure()
    ax = Axes3D(fig)
    plt.ion()  # 将画图模式改为交互模式,程序遇到plt.show不会暂停,而是继续执行
    plot_3d(ax)

    pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE * 2))  # matrix (POP_SIZE, DNA_SIZE)
    for _ in range(N_GENERATIONS):  # 迭代N代
        x, y = translateDNA(pop)
        if 'sca' in locals():
            sca.remove()
        sca = ax.scatter(x, y, F(x, y), c='black', marker='o');
        plt.show();
        plt.pause(0.1)
        pop = np.array(crossover_and_mutation(pop, CROSSOVER_RATE))
        # F_values = F(translateDNA(pop)[0], translateDNA(pop)[1])#x, y --> Z matrix
        fitness = get_fitness(pop)
        pop = select(pop, fitness)  # 选择生成新的种群

    print_info(pop)
    plt.ioff()
    plot_3d(ax)

 上面的代码来自:遗传算法详解 附python代码实现_重学CS的博客-CSDN博客_python遗传算法 

用遗传算法来判断神经网络中的参数

网络结构

import torch
from sklearn import datasets
import torch.nn.functional as Fun
from torch import nn

# 2. 定义BP神经网络
class Net(torch.nn.Module):
    def __init__(self, num,n_hidden,n_feature=4, n_output=3):
        super(Net, self).__init__()
        self.n_feature=n_feature
        self.n_hidden=int(n_hidden) ##隐藏层神经元的个数
        self.num=int(num)   ###中间隐藏层的层数
        self.input=torch.nn.Linear(n_feature,n_hidden)
        self.hidden = self.make_layer(torch.nn.Linear,self.num)   # 定义隐藏层网络
        self.out = torch.nn.Linear(n_hidden, n_output) # 定义输出层网络
        self.data,self.label=self.precess_data()
    def make_layer(self, block, num_of_layer):
        layers = []
        for _ in range(num_of_layer):
            layers.append(block(self.n_hidden,self.n_hidden))
        return nn.Sequential(*layers)
    def forward(self, x):
        x = Fun.relu(self.input(x))# 隐藏层的激活函数,采用relu,也可以采用sigmod,tanh
        x=Fun.relu(self.hidden(x))
        x = self.out(x)                   # 输出层不用激活函数
        return x
    def precess_data(self):
        # 1. 数据准备
        dataset = datasets.load_iris()
        data = torch.FloatTensor(dataset['data'])
        label = torch.LongTensor(dataset['target'])
        return data,label
    def train(self):
        # 3. 定义优化器损失函数
        self.net = Net(num=self.num,n_hidden=self.n_hidden,n_feature=4, n_output=3)    #n_feature:输入的特征维度,n_hiddenb:神经元个数,n_output:输出的类别个数
        optimizer = torch.optim.SGD(self.net.parameters(), lr=0.02) # 优化器选用随机梯度下降方式
        loss_func = torch.nn.CrossEntropyLoss() # 对于多分类一般采用的交叉熵损失函数,
        # 4. 训练数据
        for t in range(500):
            out = self.net(self.data)                 # 输入data,输出out
            loss = loss_func(out, self.label)     # 输出与label对比
            optimizer.zero_grad()   # 梯度清零
            loss.backward()         # 前馈操作
            optimizer.step()  # 使用梯度优化器
# 5. 得出结果
    def test(self):
        self.train()
        out = self.net(self.data) #out是一个计算矩阵,可以用Fun.softmax(out)转化为概率矩阵
        prediction = torch.max(out, 1)[1] # 返回index  0返回原值
        pred_y = prediction.data.numpy()
        target_y = self.label.data.numpy()
# 6.衡量准确率
        accuracy = float((pred_y == target_y).astype(int).sum()) / float(target_y.size)
        # print("莺尾花预测准确率",accuracy)
        return accuracy

这里我们需要调节的参数是神经网络隐藏层个数,和隐藏层神经元个数。

因为这里两个变量都是整数,所以不可以用上文例子中的编码和解码方法。这里我们使用的是将一个二进制转换为十进制进行解码。

def translateDNA(pop):  # pop表示种群矩阵,一行表示一个二进制编码表示的DNA,矩阵的行数为种群数目
    x_pop = pop[:, :2]
    y_pop = pop[:, 2:]

    # 解码  将一个个体解码为一个解
    x=np.sum(np.power(2, np.arange(x_pop.shape[-1] - 1, -1, -1)) * x_pop, axis=1).reshape((-1, 1))
    y = np.sum(np.power(2, np.arange(y_pop.shape[-1] - 1, -1, -1)) * y_pop, axis=1).reshape((-1, 1))
    return x, y

完整代码

import torch
from sklearn import datasets
import torch.nn.functional as Fun
from torch import nn
import numpy as np
from matplotlib import pyplot as plt

DNA_SIZE = 4
POP_SIZE = 20
CROSSOVER_RATE = 0.8
MUTATION_RATE = 0.005
N_GENERATIONS = 5
num = [0, 4]  ##2**2
n_hidden = [0, 50]  ##2**6

# 2. 定义BP神经网络
class Net(torch.nn.Module):
    def __init__(self, num,n_hidden,n_feature=4, n_output=3):
        super(Net, self).__init__()
        self.n_feature=n_feature
        self.n_hidden=int(n_hidden) ##隐藏层神经元的个数
        self.num=int(num)   ###中间隐藏层的层数
        self.input=torch.nn.Linear(n_feature,n_hidden)
        self.hidden = self.make_layer(torch.nn.Linear,self.num)   # 定义隐藏层网络
        self.out = torch.nn.Linear(n_hidden, n_output) # 定义输出层网络
        self.data,self.label=self.precess_data()
    def make_layer(self, block, num_of_layer):
        layers = []
        for _ in range(num_of_layer):
            layers.append(block(self.n_hidden,self.n_hidden))
        return nn.Sequential(*layers)
    def forward(self, x):
        x = Fun.relu(self.input(x))# 隐藏层的激活函数,采用relu,也可以采用sigmod,tanh
        x=Fun.relu(self.hidden(x))
        x = self.out(x)                   # 输出层不用激活函数
        return x
    def precess_data(self):
        # 1. 数据准备
        dataset = datasets.load_iris()
        data = torch.FloatTensor(dataset['data'])
        label = torch.LongTensor(dataset['target'])
        return data,label
    def train(self):
        # 3. 定义优化器损失函数
        self.net = Net(num=self.num,n_hidden=self.n_hidden,n_feature=4, n_output=3)    #n_feature:输入的特征维度,n_hiddenb:神经元个数,n_output:输出的类别个数
        optimizer = torch.optim.SGD(self.net.parameters(), lr=0.02) # 优化器选用随机梯度下降方式
        loss_func = torch.nn.CrossEntropyLoss() # 对于多分类一般采用的交叉熵损失函数,
        # 4. 训练数据
        for t in range(500):
            out = self.net(self.data)                 # 输入data,输出out
            loss = loss_func(out, self.label)     # 输出与label对比
            optimizer.zero_grad()   # 梯度清零
            loss.backward()         # 前馈操作
            optimizer.step()  # 使用梯度优化器
# 5. 得出结果
    def test(self):
        self.train()
        out = self.net(self.data) #out是一个计算矩阵,可以用Fun.softmax(out)转化为概率矩阵
        prediction = torch.max(out, 1)[1] # 返回index  0返回原值
        pred_y = prediction.data.numpy()
        target_y = self.label.data.numpy()
# 6.衡量准确率
        accuracy = float((pred_y == target_y).astype(int).sum()) / float(target_y.size)
        # print("莺尾花预测准确率",accuracy)
        return accuracy

def F(num, n_hidden):
    accuracy=[]
    for i in range(len(num)):
        model=Net(int(num[i]),int(n_hidden[i]))
        score=model.test()
        accuracy.append(score)
    return accuracy

def get_fitness(pop):
    x, y = translateDNA(pop)
    pred = F(x, y)
    # 减去最小的适应度是为了防止适应度出现负数,通过这一步fitness的范围为[0, np.max(pred)-np.min(pred)],最后在加上一个很小的数防止出现为0的适应度
    return (pred - np.min(pred)) + 1e-3,pred

def translateDNA(pop):  # pop表示种群矩阵,一行表示一个二进制编码表示的DNA,矩阵的行数为种群数目
    x_pop = pop[:, :2]
    y_pop = pop[:, 2:]

    # 解码  将一个个体解码为一个解
    x=np.sum(np.power(2, np.arange(x_pop.shape[-1] - 1, -1, -1)) * x_pop, axis=1).reshape((-1, 1))
    y = np.sum(np.power(2, np.arange(y_pop.shape[-1] - 1, -1, -1)) * y_pop, axis=1).reshape((-1, 1))
    return x, y

def crossover_and_mutation(pop, CROSSOVER_RATE=0.8):
    new_pop = []
    for father in pop:  # 遍历种群中的每一个个体,将该个体作为父亲
        child = father  # 孩子先得到父亲的全部基因(这里我把一串二进制串的那些0,1称为基因)
        if np.random.rand() < CROSSOVER_RATE:  # 产生子代时不是必然发生交叉,而是以一定的概率发生交叉
            mother = pop[np.random.randint(POP_SIZE)]  # 再种群中选择另一个个体,并将该个体作为母亲
            cross_points = np.random.randint(low=0, high=DNA_SIZE * 2)  # 随机产生交叉的点
            child[cross_points:] = mother[cross_points:]  # 孩子得到位于交叉点后的母亲的基因
        mutation(child)  # 每个后代有一定的机率发生变异
        new_pop.append(child)
    return new_pop

def mutation(child, MUTATION_RATE=0.003):
    if np.random.rand() < MUTATION_RATE:  # 以MUTATION_RATE的概率进行变异
        mutate_point = np.random.randint(0, DNA_SIZE * 2)  # 随机产生一个实数,代表要变异基因的位置
        child[mutate_point] = child[mutate_point] ^ 1  # 将变异点的二进制为反转

def select(pop, fitness):  # nature selection wrt pop's fitness
    idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True,
                           p=(fitness) / (fitness.sum()))
    return pop[idx]

def print_info(pop):
    fitness,pred = get_fitness(pop)
    max_fitness_index = np.argmax(fitness)
    print("max_fitness:", fitness[max_fitness_index])
    x, y = translateDNA(pop)
    print("最优的基因型:", pop[max_fitness_index])
    print("(x, y):", (x[max_fitness_index], y[max_fitness_index]))
    return (x[max_fitness_index], y[max_fitness_index]),fitness[max_fitness_index],pred[max_fitness_index]


if __name__ == "__main__":

    pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE * 2))  # matrix (POP_SIZE, DNA_SIZE)
    point=[]
    score=[]
    accuracy=[]
    for i in range(N_GENERATIONS):  # 迭代N代
        print('第{}代'.format(i))
        pop = np.array(crossover_and_mutation(pop, CROSSOVER_RATE))
        # F_values = F(translateDNA(pop)[0], translateDNA(pop)[1])#x, y --> Z matrix
        fitness,_= get_fitness(pop)
        pop = select(pop, fitness)  # 选择生成新的种群
        (x,y),output,acc=print_info(pop)
        point.append((x,y))
        score.append(output)
        accuracy.append(acc)

    for i in point:
        print(i)
    ##绘制准确率随迭代次数的变换曲线
    plt.plot(accuracy)
    plt.show()

 

上面的曲面是准确率随迭代次数的关系,可以看到在第一代和第二代的结果是比较好的。至于为什么迭代的越多,准确率下降的问题还需要研究。 

参考文献:

遗传算法详解 附python代码实现_重学CS的博客-CSDN博客_python遗传算法 

python遗传算法解简单整数规划与原理探究_m0_51810505的博客-CSDN博客_遗传算法整数规划 

搭建简单的神经网络——使用pytorch实现鸢尾花的分类_yuekangwei的博客-CSDN博客_pytorch 鸢尾花

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

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

相关文章

nginx配置websocket支持wss

和前端联调完项目之后&#xff0c;将项目部署到了开发环境上面。结果这时候发现ws连接报错了&#xff0c;怎么回事&#xff0c;明明和前端在本地都联调好了的&#xff01; 观察报错发现&#xff0c;提示我们需要使用wss连接&#xff0c;而我和前端在对接联调时使用的是ws连接。…

mysql 学习---窗口函数

文章目录Mysql 8.0新特性窗口函数常见窗口函数Mysql 8.0新特性 窗口函数 理解&#xff1a; 窗口函数的作用类似于在查询中对数据进行分组&#xff0c;类似于聚合函数&#xff0c;但不同的是把聚合函数是分组的记录合成一条&#xff0c;也就是一组一条数据&#xff0c;窗口函数…

缓存击穿、缓存穿透、缓存雪崩

初学者总是喜欢自己吓自己&#xff0c;在听到缓存击穿、缓存穿透、缓存雪崩等问题后&#xff0c;就觉得这根本不是自己这个级别所能接触的知识点&#xff0c;甚至不敢下定决心去了解。 然而&#xff0c;缓存击穿、缓存穿透、缓存雪崩等概念只是听着高大上罢了&#xff0c;实则并…

RabbitMq应用

1.RabbitMQ介绍 1.1现存问题 服务调用&#xff1a;两个服务调用时&#xff0c;我们可以通过传统的HTTP方式&#xff0c;让服务A直接去调用服务B的接口&#xff0c;但是这种方式是同步的方式&#xff0c;虽然可以采用SpringBoot提供的Async注解实现异步调用&#xff0c;但是这…

Spring之AOP

谈起AOP就不得不说起代理&#xff0c;Java 源代码经过编译生成字节码&#xff0c;然后再由 JVM 经过类加载&#xff0c;连接&#xff0c;初始化成 Java 类型&#xff0c;可以看到字节码是关键&#xff0c;静态和动态的区别就在于字节码生成的时机 静态代理&#xff1a;由程序员…

BLE MESH中的Secure Network beacon包

作用&#xff1a;节点使用安全网络信标来识别子网及其安全状态。可以用来更新Key和Iv Index。 数据包结构&#xff1a; 数据包格式&#xff1a; 大小含义 Beacon Type 1安全网络信标&#xff08;0x01&#xff09; Flags1包含密钥刷新标志和IV更新标志 Network ID8包含网络ID的值…

代码随想录算法训练营第四天 | 24. 两两交换链表中的节点 19.删除链表的倒数第N个节点 面试题 02.07. 链表相交 142.环形链表II

今天是链表章节最后一天&#xff0c;加油&#x1f4aa; 24. 两两交换链表中的节点 题目&#xff1a;给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节…

html练习11:案例仿制

1.目标效果 2.布局效果 3.顶端部分制作效果 问题&#xff1a;img和p无法同时垂直居中显示&#xff0c;img会顶端对齐&#xff0c;p会底部对齐 解决方法&#xff1a;把img作为背景加入&#xff1b;用两个div分别做img和p的容器再进行格式调整 4.导航栏部分制作效果 要点&#…

保证项目如期上线,测试人能做些什么?

要保证项目按照正常进度发布&#xff0c;需要整个研发团队齐心协力。 有很多原因都可能会造成项目延期。 1、产品经理频繁修改需求 2、开发团队存在技术难题 3、测试团队测不完 今天我想跟大家聊一下&#xff0c;测试团队如何保证项目按期上线&#xff0c;以及在这个过程中可能…

词法分析程序

一、实验原理 1.1实验内容 通过本实验&#xff0c;应达到以下目标&#xff1a; 1.掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。 2.掌握词法分析的实现方法。 3.上机调试编出的词法分析程序。 1.2实验内容 词法分析是作为相对独立的阶段来完成的…

C# 事件

一 C#中的事件 大致上&#xff1a;事件-----回调函数&#xff1b; 二 用户界面中的事件 ① 按钮点击事件 ② 基本的写法 this.button1.Clicknew System.EventHandler(this.button1_Click); private void button1_Click(object sender,EventHandler e) {this.label1.TextDat…

C++智能指针weak_ptr

C智能指针weak_ptr 学习路线&#xff1a;C智能指针shared_ptr->C智能指针unique_ptr->C智能指针weak_ptr 简介&#xff1a;本文讲解常用的智能指针的用法和原理&#xff0c;包括shared_ptr,unique_ptr,weak_ptr。 概述 weak_ptr设计的目的是为配合 shared_ptr 而引入…

静电场方程与边界面上的衔接条件 工程电磁学 P6

我们现在已经知道两个公式 我们可以得到微分形式 对于体密度&#xff0c;面密度&#xff0c;线密度&#xff0c;点电荷的理解 很多同学会问空间中为什么要有面密度&#xff0c;线密度的存在呢&#xff1f; 其实这个是模型的需要&#xff0c;因为介质不一定是连续的&#xff0…

如何设计一个高性能的图 Schema

本文整理自青藤云安全工程师——文洲在青藤云技术团队内部分享&#xff0c;分享视频参考&#xff1a;https://www.bilibili.com/video/BV1r64y1R72i 图数据库的性能和 schema 的设计息息相关&#xff0c;但是 NebulaGraph 官方本身对图 schema 的设计其实没有一个定论&#xff…

Codeforces Round #837 (Div. 2) C. Hossam and Trainees

Problem - C - Codeforces 翻译&#xff1a; 胡萨姆有&#x1d45b;名学员。他给&#x1d456;-th的学员分配了一个号码&#x1d44e;&#x1d456;。 一双&#x1d456;-th和&#x1d457;-th(&#x1d456;≠&#x1d457;)学员被称为成功的如果有一个整数&#x1d465;(&…

基于springboot的企业员工工资管理系统(财务系统)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

Vue渲染器(二):挂载与更新

渲染器&#xff08;二&#xff09;&#xff1a;挂载与更新 前面介绍了渲染器的基本概念和整体框架&#xff0c;接下来就可以介绍渲染器的核心功能&#xff1a;挂载与更新。 1.挂载子节点和元素的属性&#xff1a; vnode.children的值为字符串类型时&#xff0c;会把它设置为…

019 | 在线电影娱乐网站系统设计含论文 | 大学生毕业设计 | 极致技术工厂

作为一个在线电影娱乐网站系统&#xff0c;它展示给浏览者的是各种电影信息&#xff0c;把这些信息能够按用户的需要友好的展示出来是很重要的&#xff0c;同时&#xff0c;能够实现对这些信息的有条不紊的管理也是不可以忽视的。对浏览者和会员的功能而言叫做前台实现&#xf…

[附源码]Node.js计算机毕业设计电子购物商城Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

[附源码]计算机毕业设计电商小程序Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis MavenVue等等组成&#xff0c;B/S模式…