博主介绍:
    ✌我是阿龙
,一名专注于Java技术领域的程序员,全网拥有10W+粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台的优质作者。通过长期分享和实战指导,我致力于帮助更多学生完成毕业项目和技术提升。

技术范围:
    我熟悉的技术领域涵盖SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等方面的设计与开发。如果你有任何技术难题,我都乐意与你分享解决方案。

 主要内容:
     我的服务内容包括:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文撰写与辅导、论文降重、长期答辩答疑辅导。我还提供腾讯会议一对一的专业讲解和模拟答辩演练,帮助你全面掌握答辩技巧与代码逻辑。

🍅获取源码请在文末联系我🍅

温馨提示:文末有 CSDN 平台官方提供的阿龙联系方式的名片!

温馨提示:文末有 CSDN 平台官方提供的阿龙联系方式的名片!

目录:

一、详细操作演示视频       在文章的尾声,您会发现一张电子名片👤,欢迎通过名片上的联系方式与我取得联系,以获取更多关于项目演示的详尽视频内容。视频将帮助您全面理解项目的关键点和操作流程。期待与您的进一步交流!        承诺所有开发的项目,全程售后陪伴!!!

2  相关工具及介绍

2.1  Python语言

2.2  hive简介

2.5  Spark

2.4 数据采集

2.5  环境部署

2.6  环境部署

系统实现界面展示:

LSTM模型训练代码介绍:

2.7 测试概述

2.8软件测试原则

2.9测试用例

论文部分参考:​编辑

为什么选择我(我可以给你的定制项目推荐核心功能,一对一推荐)实现定制!!!

一、详细操作演示视频
       在文章的尾声,您会发现一张电子名片👤,欢迎通过名片上的联系方式与我取得联系,以获取更多关于项目演示的详尽视频内容。视频将帮助您全面理解项目的关键点和操作流程。期待与您的进一步交流!
        承诺所有开发的项目,全程售后陪伴!!!

相关工具及介绍

2.1  Python语言

Python是由荷兰数学和计算机研究学会的吉多·范罗苏姆于20世纪90年代设计的一款高级语言。Python优雅的语法和动态类型,以及解释型语言的本质,使它成为许多领域脚本编写和快速开发应用的首选语言。Python相比与其他高级语言,开发代码量较小,代码风格简洁优雅,拥有丰富的第三方库。Python的代码风格导致其可读性好,便于维护人员阅读维护,程序更加健壮。Python能够轻松地调用其他语言编写的模块,因此也被成为“胶水语言”。

2.2  hive简介

Hive是一个数据仓库工具,当把特定结构地数据文件存入Hive对应的HDFS目录时,Hive能将其映射成表,并提供类 SQL 查询功能。底层会将sql语句转成MapReduce程序,大大方便程序开发,其中执行引擎可以更换,执行效率大大提高,Hive主要用于解决海量结构化日志的数据统计。

在本课题中,配置Hive为主要数据仓库,有以下几点原因

(1) Hive的操作接口采用类SQL语法,提供快速开发能力。

(2)相对于传统的关系型数据库,Hive更擅长于数据分析。

(3) Hive支持用户自定义函数,用户可根据自己的需求来实现自己的函数。

(4) Hive基于HDFS进行存储,扩展性高,可靠性高。

(5) Hive底层计算引擎可更换。

由于Hive默认底层引擎位MapReduce,MapReduce在遇到迭代式任务时,会将任务落盘至HDFS再进行运算,对于大批量数据处理来说,这很影响效率,所以我们会将引擎改成Tez。

2.3  hadoop技术

Hadoop 是 Apache 软件基金会下的一个开源分布式计算平台,它以分布式文件系统HDFS和MapReduce算法为核心。Hadoop提供了一个可靠的共享存储与分析系统[2]。用户可以在不了解分布式底层细节的情况下,开发分布式程序,充分利用集群的威力进行高速运算和存储。

Hadoop拥有以下4大优势:

(1) 高容错性:Hadoop底层维护多个数据副本,所以即使Hadoop某个计算元素或存储出现故障,也不会导致数据的丢失。

(2) 高扩展性:在集群间分配任务数据,可方便扩展数以千计的节点。

(3) 高效性:在MapReduce的思想下,Hadoop是并行工作的,大大加快了任务的处理速度。

Hadoop实现了一个分布式文件系统( Distributed File System),其中一个组件是HDFS(Hadoop Distributed File System)。HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上;而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。HDFS放宽了(relax)POSIX的要求,可以以流的形式访问(streaming access)文件系统中的数据。

在本课题中,由于其中的Mapreduce框架其设计初衷并不是为了满足循环迭代式数据流处理,因此在多并行运行的数据可复用场景中存在诸多计算效率等问题,Hadoop框架主要用于数据存储。

2.5  Spark

是一种DAG(有向无环图)的,基于内存的快速、通用、可扩展的大数据分析计算引擎。Spark 是分布式数据快速分析项目。它的核心技术是弹性分布式数据集(Resilient Distributed Datasets),简称RDD,提供了比 MapReduce 丰富的模型,可以快速在内存中对数据集进行多次迭代,不像MapReduce需要落盘数据才能进行迭代式运算,可支持复杂的数据挖掘算法和图形计算算法[4]。Spark的运行模式包括Local、Standalone、Yarn及Mesos几种。其中Local模式仅用于本地开发,Mesos模式国内几乎不用。在公司中因为大数据服务基本搭载Yarn集群调度,因此Spark On Yarn模式会用的比较多。

Spark是一个基于内存的,用于大规模数据处理的统一分析引擎,其运算速度可以达到Mapreduce的10-100倍。具有如下特点:内存计算。Spark优先将数据加载到内存中,数据可以被快速处理,并可启用缓存。shuffle过程优化。和Mapreduce的shuffle过程中间文件频繁落盘不同,Spark对Shuffle机制进行了优化,降低中间文件的数量并保证内存优先。RDD计算模型。Spark具有高效的DAG调度算法,同时将RDD计算结果存储在内存中,避免重复计算。

2.4 数据采集

考虑到更方便后续对数据的处理和分析,在采集视频数据后,选择了将爬取到的数据存入CSV文件中。CSV提供了一种轻量级、便捷的方式来批量写入数据且CSV文件较小,便于在网络间传输和分享,这对于分布式计算框架如Hadoop非常有利。而且CSV以纯文本形式存储表格数据,每行代表一条记录,各字段由逗号(或其他分隔符)分隔。这种结构化数据格式可以被各种编程语言和工具解析,包括Hadoop生态中的MapReduce程序。

2.5  环境部署

本文的软件开发环境及运行环境如下。操作系统:Linux;JDK:1.8.0_241 版本;Hadoop:hadoop-3.3.5版本;虚拟机:VMware-16.0;数据库工具:mysql-5.7.29版本、SQLyog-13.2.0版本;框架:Flask;可视化工具:Echarts。

为了实现基于大数据技术的视频数据分析与研究,需要搭建Hadoop集群,它可提供海量数据的分布式存储、分布式计算和分布式管理功能[9]。首先创建三台Linux系统的虚拟机,修改三台虚拟机的IP(192.168.144.131、192.168.144.132、192.168.144.133)并添加免密登录和安装JDK与Hadoop,修改Hadoop配置文件(hadoop-env.sh、core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml),在终端运行hadoop namenode -format命令进行格式化格式化HDFS,最后启动Hadoop(start-all.sh),能在浏览器中http://192.168.144.131:9870查看是否HDFS正常运行,访问成功如图4.1所示。

2.6  环境部署

本文的软件开发环境及运行环境如下。操作系统:Linux;JDK:1.8.0_241 版本;Hadoop:hadoop-3.3.5版本;虚拟机:VMware-16.0;数据库工具:mysql-5.7.29版本、SQLyog-13.2.0版本;框架:Flask;可视化工具:Echarts。

为了实现基于大数据技术的视频数据分析与研究,需要搭建Hadoop集群,它可提供海量数据的分布式存储、分布式计算和分布式管理功能[9]。首先创建三台Linux系统的虚拟机,修改三台虚拟机的IP(192.168.144.131、192.168.144.132、192.168.144.133)并添加免密登录和安装JDK与Hadoop,修改Hadoop配置文件(hadoop-env.sh、core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml),在终端运行hadoop namenode -format命令进行格式化格式化HDFS,最后启动Hadoop(start-all.sh),能在浏览器中http://192.168.144.131:9870查看是否HDFS正常运行,访问成功如图4.1所示。

系统实现界面展示:

LSTM模型训练代码介绍:
 


#获取当前文件路径的根目录
parent_directory = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
dbtype, host, port, user, passwd, dbName, charset,hasHadoop = config_read(os.path.join(parent_directory,"config.ini"))
#MySQL连接配置
mysql_config = {
    'host': host,
    'user':user,
    'password': passwd,
    'database': dbName,
    'port':port
}

#获取预测可视化图表接口
def productdataforecast_forecastimgs(request):
    if request.method in ["POST", "GET"]:
        msg = {'code': normal_code, 'message': 'success'}
        # 指定目录
        directory = os.path.join(parent_directory, "templates", "upload", "productdataforecast")
        # 获取目录下的所有文件和文件夹名称
        all_items = os.listdir(directory)
        # 过滤出文件(排除文件夹)
        files = [f'upload/productdataforecast/{item}' for item in all_items if os.path.isfile(os.path.join(directory, item))]
        msg["data"] = files
        fontlist=[]
        for font in fm.fontManager.ttflist:
            fontlist.append(font.name)
        msg["message"]=fontlist
        return JsonResponse(msg, encoder=CustomJsonEncoder)

# 定义函数创建时间序列数据集
def create_dataset(data, time_step=1):
    X, Y = [], []
    for i in range(len(data) - time_step - 1):
        a = data[i:(i + time_step), :]
        X.append(a)
        Y.append(data[i + time_step, :])
    return np.array(X), np.array(Y)

def productdataforecast_forecast(request):
    if request.method in ["POST", "GET"]:
        msg = {'code': normal_code, "msg": mes.normal_code}
        #1.获取数据集
        connection = pymysql.connect(**mysql_config)
        query = "SELECT date, productname,shopnames,price,salesvolume,xse FROM productdata ORDER BY date ASC"
        #2.处理缺失值
        data = pd.read_sql(query, connection).dropna()
        # 转换日期格式为datetime
        date_format = data['date'].iloc[0]
        if isinstance(date_format, (datetime.date, datetime.datetime)):
            date_format=''
        elif "年" in date_format and "月" in date_format and "日" in date_format:
            date_format='%Y年%m月%d日'
        elif "年" in date_format and "月" in date_format:
            date_format='%Y年%m月'
        elif "年" in date_format:
            date_format='%Y年'
        else:
            date_format=''
        if date_format=="" or date_format==None:
            data['date'] = pd.to_datetime(data['date'])
        else:
            data['date'] = pd.to_datetime(data['date'], format=date_format)
        data.set_index('date', inplace=True)
        productname_encoder = LabelEncoder()
        data['productname'] = productname_encoder.fit_transform(data['productname'])
        shopnames_encoder = LabelEncoder()
        data['shopnames'] = shopnames_encoder.fit_transform(data['shopnames'])
        #只选择需要的列
        data = data[[
            'productname',
            'shopnames',
            'price',
            'salesvolume',
            'xse',
        ]]
        # 归一化处理(为了LSTM的训练)
        scaler = MinMaxScaler(feature_range=(0, 1))
        scaled_data = scaler.fit_transform(data)

         #设置时间步长
        time_step = int(len(data)/10)# 使用过去30的数据
        if time_step>30:
            time_step=30
        if time_step<=0:
            time_step=1
        X, y = create_dataset(scaled_data, time_step)
        #划分训练集和测试集
        train_size = int(len(X) * 0.8)  # 80%的数据用于训练
        X_train, X_test = X[:train_size], X[train_size:]
        y_train, y_test = y[:train_size], y[train_size:]
        # 查看训练数据集的形状
        print(f'X_train shape: {X_train.shape}, y_train shape: {y_train.shape}')
        # 创建 LSTM 模型
        model = Sequential()
        model.add(LSTM(50, return_sequences=True, input_shape=(X_train.shape[1], X_train.shape[2])))
        model.add(Dropout(0.2))  # 防止过拟合
        model.add(LSTM(50, return_sequences=False))
        model.add(Dropout(0.2))
        model.add(Dense(len(data.columns), activation='relu'))  # 输出层,预测
        #编译模型
        model.compile(optimizer='adam', loss='mean_squared_error')
        #训练模型
        model.fit(X_train, y_train, epochs=100, batch_size=32, verbose=1)
        #进行预测
        train_predict = model.predict(X_train)
        test_predict = model.predict(X_test)
        #将预测结果反归一化
        train_predict = scaler.inverse_transform(train_predict)
        test_predict = scaler.inverse_transform(test_predict)
        #绘制预测结果
        plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体 SimHei
        plt.rcParams['axes.unicode_minus'] = False  # 解决负号 '-' 显示为方块的问题
        plt.figure(figsize=(12, 6),dpi=80)
        plt.plot(data.index[:len(train_predict)], train_predict[:, 1 -1], label='训练productname预测',
                 color='blue')
        plt.plot(data.index[len(train_predict) + time_step + 1:], test_predict[:, 1 -1],
                 label='测试productname预测', color='red')
        plt.plot(data.index, data['productname'], label='实际productname', color='green')
        plt.title('productname预测')
        plt.xlabel('Date')
        plt.ylabel('productname')
        plt.legend()
        directory =os.path.join(parent_directory,"templates","upload","productdataforecast","productname_prediction.png")
        os.makedirs(os.path.dirname(directory), exist_ok=True)
        plt.savefig(directory)
        plt.clf()
        plt.close()
        plt.figure(figsize=(12, 6),dpi=80)
        plt.plot(data.index[:len(train_predict)], train_predict[:, 2 -1], label='训练shopnames预测',
                 color='blue')
        plt.plot(data.index[len(train_predict) + time_step + 1:], test_predict[:, 2 -1],
                 label='测试shopnames预测', color='red')
        plt.plot(data.index, data['shopnames'], label='实际shopnames', color='green')
        plt.title('shopnames预测')
        plt.xlabel('Date')
        plt.ylabel('shopnames')
        plt.legend()
        directory =os.path.join(parent_directory,"templates","upload","productdataforecast","shopnames_prediction.png")
        os.makedirs(os.path.dirname(directory), exist_ok=True)
        plt.savefig(directory)
        plt.clf()
        plt.close()
        plt.figure(figsize=(12, 6),dpi=80)
        plt.plot(data.index[:len(train_predict)], train_predict[:, 3 -1], label='训练price预测',
                 color='blue')
        plt.plot(data.index[len(train_predict) + time_step + 1:], test_predict[:, 3 -1],
                 label='测试price预测', color='red')
        plt.plot(data.index, data['price'], label='实际price', color='green')
        plt.title('price预测')
        plt.xlabel('Date')
        plt.ylabel('price')
        plt.legend()
        directory =os.path.join(parent_directory,"templates","upload","productdataforecast","price_prediction.png")
        os.makedirs(os.path.dirname(directory), exist_ok=True)
        plt.savefig(directory)
        plt.clf()
        plt.close()
        plt.figure(figsize=(12, 6),dpi=80)
        plt.plot(data.index[:len(train_predict)], train_predict[:, 4 -1], label='训练salesvolume预测',
                 color='blue')
        plt.plot(data.index[len(train_predict) + time_step + 1:], test_predict[:, 4 -1],
                 label='测试salesvolume预测', color='red')
        plt.plot(data.index, data['salesvolume'], label='实际salesvolume', color='green')
        plt.title('salesvolume预测')
        plt.xlabel('Date')
        plt.ylabel('salesvolume')
        plt.legend()
        directory =os.path.join(parent_directory,"templates","upload","productdataforecast","salesvolume_prediction.png")
        os.makedirs(os.path.dirname(directory), exist_ok=True)
        plt.savefig(directory)
        plt.clf()
        plt.close()
        plt.figure(figsize=(12, 6),dpi=80)
        plt.plot(data.index[:len(train_predict)], train_predict[:, 5 -1], label='训练xse预测',
                 color='blue')
        plt.plot(data.index[len(train_predict) + time_step + 1:], test_predict[:, 5 -1],
                 label='测试xse预测', color='red')
        plt.plot(data.index, data['xse'], label='实际xse', color='green')
        plt.title('xse预测')
        plt.xlabel('Date')
        plt.ylabel('xse')
        plt.legend()
        directory =os.path.join(parent_directory,"templates","upload","productdataforecast","xse_prediction.png")
        os.makedirs(os.path.dirname(directory), exist_ok=True)
        plt.savefig(directory)
        plt.clf()
        plt.close()
        #准备未来7的输入数据
        last_data_days = scaled_data[-time_step:] #取最后time_step的数据
        future_predictions = []

        for _ in range(7):  # 预测未来7
          last_data_days = last_data_days.reshape((1, time_step, len(data.columns)))  # 重塑数据
          prediction = model.predict(last_data_days)
          future_predictions.append(prediction[0])
          last_data_days = np.append(last_data_days[:, 1:, :], [prediction], axis=1)  # 更新输入数据

        #转换为原始数据
        future_predictions = scaler.inverse_transform(future_predictions)
        #获取当前日期
        last_date = data.index[-1]  # 数据集中最后一个日期
        future_dates = [last_date + datetime.timedelta(days=i) for i in range(1, 7+1)]  # 生成未来7日的日期
        df = pd.DataFrame(columns=[
            'date',
            'productname',
            'shopnames',
            'price',
            'salesvolume',
            'xse',
        ])
        df['date'] = future_dates
        df['productname'] = future_predictions[:, 1 -1]
        df['shopnames'] = future_predictions[:, 2 -1]
        df['price'] = future_predictions[:, 3 -1]
        df['salesvolume'] = future_predictions[:, 4 -1]
        df['xse'] = future_predictions[:, 5 -1]
        df['productname']=df['productname'].astype(int)
        df['productname'] = productname_encoder.inverse_transform(df['productname'])
        df['shopnames']=df['shopnames'].astype(int)
        df['shopnames'] = shopnames_encoder.inverse_transform(df['shopnames'])
        df['price'] = df['price'].astype(float)
        df['price']=np.round(df['price'], 2)
        df['salesvolume']=df['salesvolume'].astype(int)
        df['xse'] = df['xse'].astype(float)
        df['xse']=np.round(df['xse'], 2)
        #9.创建数据库连接,将DataFrame 插入数据库
        connection_string = f"mysql+pymysql://{mysql_config['user']}:{mysql_config['password']}@{mysql_config['host']}:{mysql_config['port']}/{mysql_config['database']}"
        engine = create_engine(connection_string)

2.7 测试概述

系统测试就是对项目是否存在错误而运行程序的一种检测方式。系统测试对于一个软件来说极为重要,并且在开发过程中占有很大的比重。每一次功能的实现都伴随着很多次的测试。它是软件是否能用的检测环节,对于软件质量的评估有着重要影响。系统能否被验收成功是测试中最后一个至关重要的环节。

2.8软件测试原则

当进行软件测试时,有一些原则需要遵循,以确保测试的有效性和效率。

第一:测试应该尽早开始。在需求分析和系统设计阶段就应该进行测试准备,以便尽早发现系统的不足之处。这样可以降低修复成本,提高开发效率。测试人员应该在分析需求时就参与进来,确保需求具备可测试性和正确性。

第二:测试应该是全面的。测试应该覆盖软件的各个功能模块和不同的使用场景,以确保软件在各种情况下都能正常运行。测试还应该关注软件的性能、安全性和可用性等方面,以全面评估软件的质量。

随着软件开发的复杂性增加,手动测试已经无法满足需求。自动化测试可以提高测试的效率和准确性,减少人为错误。通过编写自动化测试脚本,可以快速执行大量的测试用例,并及时发现问题。软件的开发是一个迭代的过程,每个迭代都会引入新功能和修复旧问题。因此,测试也应该是一个持续的过程,与开发同步进行。持续集成和持续交付等技术可以帮助实现持续测试,确保软件在每个迭代中都能达到预期的质量标准。通过测试不仅仅是为了发现问题,更重要的是提供有价值的反馈给开发人员。测试人员应该及时向开发人员报告问题,并提供详细的复现步骤和环境信息,以便开发人员能够快速定位和解决问题。

2.9测试用例

(1)用户登陆测试用例

表 6-1 用户登录用例表

项目/软件

编制时间

20xx/xx/xx

功能模块名

用户登陆模块

用例编号

xxxx

功能特性

用户身份验证

测试目的

验证是否输入合法的信息,允许合法登陆,阻止非法登陆

测试数据

用户名=1密码=a1身份= 非认证用户

操作步骤

操作描述

数 据

期望结果

实际结果

状态

1

输入用户名和密码

用户名= 1密码=1

显示进入后的页面。

同期望结果。

正常

2

输入用户名和密码

用户名= 1密码=aaa

显示警告信息“不存在该用户名或密码错误!”

同期望结果。

正常

3

输入用户名和密码

用户名= aaa密码=1

显示警告信息“不存在该用户名或密码错误”

同期望结果。

正常

4

输入用户名和密码

用户名=“” 密码=“”

显示警告信息“用户名密码不能为空!”

同期望结果。

正常

(2)用户注册测试用例

表 6-2  用户注册用例表

项目/软件

编制时间

20xx/xx/xx

功能模块名

用户注册模块

用例编号

xxxx

功能特性

用户注册

测试目的

验证私注册是否成功,注册数据是否合法

测试数据

用户名=aaa 密码=aaa电子邮件=dwa@qq.com 

操作步骤

操作描述

数 据

期望结果

实际结果

测试状态

1

输入注册数据

用户名= aaa密码=aaa 电子邮件=dwa@qq.com

提示:注册成功!转入用户主页

同期望结果。

正常

2

输入注册数据

用户名= aaa密码=aaa 电子邮件=dwa@qq.com

提示:用户名已注册

同期望结果。

正常

3

输入注册数据

用户名= aaa密码=”” 电子邮件=dwa@qq.com

提示:密码不能为空

同期望结果。

正常

4

输入注册数据

密码=aaa 电子邮件=dwa@qq.com

提示:用户名为空

同期望结果。

正常

论文部分参考:

为什么选择我(我可以给你的定制项目推荐核心功能,一对一推荐)实现定制!!!

     我是程序员阿龙,专注于软件开发,拥有丰富的编程能力和实战经验。在过去的几年里,我辅导了上千名学生,帮助他们顺利完成毕业项目,同时我的技术分享也吸引了超过50W+的粉丝。我是CSDN特邀作者、博客专家、新星计划导师,并在Java领域内获得了多项荣誉,如博客之星。我的作品也被掘金、华为云、阿里云、InfoQ等多个平台推荐,成为各大平台的优质作者。
已经为上百名同学获得优秀毕业生!
源码获取
文章下方名片联系我即可~
大家点赞、收藏、关注、评论啦 、查看👇🏻获取联系方式👇🏻
精彩专栏推荐订阅:在下方专栏

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐