当你刷着短视频里各种“AI作画”“AI预测”的神奇效果时,是不是也会好奇:这些AI技术到底是怎么实现的?作为一个完全没有编程和AI基础的小白,能不能自己动手做出一个能用的AI小项目?

很多人对人工智能的印象停留在“高深莫测”“需要多年专业积累”,其实随着开源社区和深度学习框架的发展,现在零基础学习者也能快速上手完成有意思的AI实践。本文就带着大家从零基础出发,完成两个非常有代表性的AI实战项目:第一个是用图像风格迁移打造属于自己的“艺术滤镜生成器”,把普通照片变成梵高、莫奈风格的名画;第二个是基于历史数据做时间序列预测,用LSTM模型预测超市未来的商品销量(这个方法稍加改动就能用来预测股价趋势)。

两个项目都特意选择了对零基础最友好的实现路径,不需要你从零搭建复杂模型,只需要理解核心逻辑、调整少量参数就能跑通整个流程,做完就能立刻获得可视化的成果,帮你快速建立对人工智能实践的信心,接下来我们就正式开始吧。

一、AI实践入门为什么要选这两个项目?

对于零基础的同学来说,入门AI最大的障碍不是学不会数学公式,而是很难坚持:很多教程一上来先讲三个月的数学和编程基础,还没等到做项目就已经放弃了。而好的入门项目应该满足三个特点:**第一,成果可视化,做完就能立刻看到效果,获得正向反馈;第二,不需要从零造轮子,依托成熟框架和开源代码就能完成;第三,覆盖AI领域两大核心场景——计算机视觉(处理图像数据)和序列预测(处理时序数据),帮你建立对AI应用的整体认知。

我们选的两个项目刚好完美符合这三个要求,我们先从第一个更直观的图像风格迁移项目开始。

实践项目一:图像风格迁移——打造你的专属艺术滤镜生成器

1.1 项目背景:从“滤镜”到AI风格迁移,普通人也能玩艺术

你一定用过手机修图软件里的艺术滤镜:一键把照片变成油画、水彩风格,这些效果背后绝大多数用的就是“图像风格迁移”技术。在2015年之前,要实现这样的效果需要非常复杂的图形学算法,效果也很生硬;直到2015年神经风格迁移算法(Neural Style Transfer)提出之后,AI才真正实现了能把任意一张照片转化成顶级艺术大师的绘画风格,而且效果远远超过传统算法。

简单来说,这个项目你只需要准备两张图:一张是你自己拍的内容图(比如你的旅行照片、人像照片),一张是你喜欢的风格图(比如梵高的《星月夜》、莫奈的《日出·印象》),AI模型会自动把内容图的内容保留,同时把风格图的艺术风格“迁移”到内容图上,最终生成一张带有梵高/莫奈风格的全新图片,相当于你用AI亲手画了一幅属于自己的“名画”。

为什么这个项目绝对适合零基础入门?

我见过很多AI入门教程第一个项目就练MNIST手写数字识别,练完除了知道准确率98%之外,根本没有任何成就感,很多人做到一半就放弃了。而风格迁移项目完全不一样:

效果直观可见:你做完就能立刻得到一张属于自己的艺术图,可以直接保存下来当壁纸或者发朋友圈,成就感拉满;

不需要从零搭建模型:PyTorch、TensorFlow这些主流深度学习框架官方都提供了完整的预训练模型和教程代码,你只需要把自己的图片替换进去,调两个参数就能运行,不需要你自己写模型结构代码;

改动空间大:你可以尝试不同的内容图、不同艺术家的风格图,调整不同的参数得到不一样的效果,完全可以做成一个属于自己的滤镜工具。

1.2 核心概念讲解:零基础也能看懂的风格迁移原理

很多零基础同学一看到“神经网络”“深度学习”就头大,其实我们不需要看懂所有数学公式,只需要理解核心逻辑就能做项目,这里我用最通俗的话把原理讲清楚。

神经风格迁移的核心思路其实非常简单,它用到了一个非常关键的工具:预训练的图像分类卷积神经网络。什么意思呢?就是科学家已经提前用几百万张图片训练好了一个能识别图片内容的神经网络,这个网络在识别图片的时候,会自动把图片的“内容信息”和“风格信息”分开存在不同的网络层里:

靠近输入的底层网络会提取图片的基础内容信息(比如哪里是边、哪里是块,图片整体的轮廓结构);

靠近输出的高层网络会提取图片的抽象内容信息(比如这张图里是猫还是狗,是山还是海);

而不同网络层特征的相关性,就藏着图片的风格信息(比如梵高画的笔触是粗犷的条状,莫奈的笔触是细碎的点,这些纹理特点就是风格)。

所以风格迁移的步骤其实就是三步:

把我们的内容图输入预训练网络,提取出它的内容特征(也就是保留照片原本的内容结构:这里有个人,那里有棵树,这个结构我们不变);

把我们的风格图输入预训练网络,提取出它的风格特征(也就是梵高画的笔触、色彩搭配这些风格特点);

我们从一张随机噪声图开始,不断迭代修改这张图,让它的内容特征越来越接近我们输入的内容图,风格特征越来越接近我们输入的风格图,迭代几十次之后,就能得到我们想要的结果了。

这里给大家补充两个核心参数,后面做项目的时候我们会用到,你只要理解它们的作用就行:

内容权重(Content Weight):控制生成图和原图内容的相似程度,权重越高,生成图越贴近原图的内容结构,不容易变形;

风格权重(Style Weight):控制生成图的风格强度,权重越高,生成图的风格效果越明显,当然如果太高也会把原图的内容冲没,一般来说风格权重是内容权重的1000倍左右效果最好。

1.3 完整实践步骤:零基础一步步跟着做就能出成果

接下来我们一步步带大家完成项目,我们这里用PyTorch框架来实现,因为PyTorch现在是学术界和入门最常用的框架,代码更简洁好懂。如果你还没有安装Python和PyTorch,别担心,你也可以直接用Google Colab或者阿里云的免费GPU Notebook来运行,不需要自己在本地装环境。

步骤1:环境准备

第一步先把我们需要的工具包都装好,打开你的终端或者Notebook,输入以下命令:

安装pytorch和torchvision(如果用GPU版本可以去pytorch官网找对应命令)

pip install torch torchvision pip install pillow matplotlib # 用来处理图片和显示结果

装好之后,我们就可以导入需要的包了:

import torch import torch.nn as nn import torch.optim as optim from torchvision.models import vgg19 from torchvision.transforms import transforms from PIL import Image import matplotlib.pyplot as plt

这里我们用到的VGG19就是前面说的预训练好的图像分类网络,PyTorch已经帮我们下载好了预训练参数,不需要我们自己训练。

步骤2:加载预处理我们的内容图和风格图

接下来我们需要把你准备好的内容图和风格图加载进来,做一点简单的预处理,神经网络只能处理固定大小的张量,所以我们要把图片调整到统一的大小,转换成PyTorch能处理的格式。

这里我给大家建议:内容图就用你自己的手机照片就行,分辨率不用太大,太大了跑起来慢,500*800左右就刚好;风格图去网上搜“梵高星月夜”“莫奈日出”就能找到高清图,保存下来就行。

定义图片预处理规则:把图片转成张量,归一化

transform = transforms.Compose([ transforms.Resize((500, 600)), # 把图片调整到500行600列,你可以根据自己图片比例改 transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ])

def load_image(path): img = Image.open(path).convert('RGB') # 打开图片转成RGB三通道 img = transform(img).unsqueeze(0) # 加一个批次维度 return img

替换成你自己的图片路径

content_img = load_image('my_photo.jpg') style_img = load_image('van_gogh.jpg')

这里的归一化参数是VGG网络默认的参数,直接用就行,不需要改,为什么要归一化?因为预训练模型训练的时候就是用这个参数归一化的,我们输入的图片也要做一样的处理才能得到正确的特征。

步骤3:定义提取内容特征和风格特征的方法

接下来我们从VGG19网络里把我们需要的内容特征和风格特征取出来,我们不需要VGG的分类层,只需要它前面的卷积层来提取特征:

选择提取内容特征和风格特征的层,这个是官方常用的选择,效果最好

content_layers = ['conv4_2'] # 用第四层的卷积特征来做内容特征 style_layers = ['conv1_1', 'conv2_1', 'conv3_1', 'conv4_1', 'conv5_1'] # 每一层都提取风格特征

class VGGFeatureExtractor(nn.Module): def init(self): super(VGGFeatureExtractor, self).init() vgg = vgg19(pretrained=True).features # 只取VGG的卷积部分 self.layers = { '0': 'conv1_1', '1': 'conv1_2', '2': 'pool1', '3': 'conv2_1', '4': 'conv2_2', '5': 'pool2', '6': 'conv3_1', '7': 'conv3_2', '8': 'conv3_3', '9': 'conv3_4', '10': 'pool3', '11': 'conv4_1', '12': 'conv4_2', '13': 'conv4_3', '14': 'conv4_4', '15': 'pool4', '16': 'conv5_1', '17': 'conv5_2', '18': 'conv5_3', '19': 'conv5_4', '20': 'pool5' } self.vgg = vgg.eval() # 把模型改成评估模式,不需要训练 for param in self.vgg.parameters(): param.requires_grad = False # 预训练模型我们不需要改它的参数,所以关闭梯度

这里我们把VGG的参数都冻住了,因为我们不需要训练VGG,我们只需要用它提特征,需要训练调整的是我们最终生成的那张图,这个一定要注意哦。

步骤4:定义内容损失和风格损失

接下来我们要定义损失函数,损失函数就是告诉AI“你现在生成的图离目标差多少”,AI会根据损失来调整生成图:

首先是内容损失:我们生成图的内容特征要和我们输入的内容图的内容特征越接近越好,所以用均方误差就行:

def content_loss(gen_content, target_content): return torch.mean((gen_content - target_content) ** 2)

然后是风格损失,风格损失我们要用格拉姆矩阵(Gram Matrix)来计算,很多同学听不懂格拉姆矩阵,你只要知道它就是用来计算不同特征通道之间的相关性,这个相关性就代表了风格,所以我们计算生成图格拉姆矩阵和风格图格拉姆矩阵的均方误差就是风格损失:

def gram_matrix(features): batch_size, channels, height, width = features.size() features = features.view(channels, height * width) # 把特征展开 gram = torch.mm(features, features.t()) # 矩阵相乘得到格拉姆矩阵 return gram

def style_loss(gen_style, target_style): gen_gram = gram_matrix(gen_style) target_gram = gram_matrix(target_style) return torch.mean((gen_gram - target_gram) ** 2)

步骤5:开始迭代优化生成图片

一切准备就绪,我们现在可以开始生成了。我们先初始化生成图,一开始我们直接用内容图初始化,比随机噪声收敛更快,效果更好:

初始化特征提取器

extractor = VGGFeatureExtractor()

提取内容图和风格图的目标特征

content_target, _ = extractor(content_img) _, style_target = extractor(style_img)

初始化生成图,用内容图初始化,并且开启梯度,我们要优化生成图

gen_img = content_img.clone().requires_grad_(True)

定义优化器,我们只优化生成图这个变量,用Adam优化器就行

optimizer = optim.Adam([gen_img], lr=0.01)

设置权重,这个是常用的参数,你可以自己调

content_weight = 1 style_weight = 1000

迭代次数,一般300次就够了,次数越多效果越精细,当然也越慢

epochs = 300

开始迭代

for epoch in range(epochs): optimizer.zero_grad() # 提取当前生成图的特征 gen_content, gen_style = extractor(gen_img) # 计算内容损失 c_loss = content_loss(gen_content[content_layers[0]], content_target[content_layers[0]]) # 计算总风格损失,每一层的风格损失加起来 s_loss = 0 for layer in style_layers: s_loss += style_loss(gen_style[layer], style_target[layer]) # 总损失等于加权之后的和 total_loss = content_weight * c_loss + style_weight * s_loss # 反向传播更新生成图 total_loss.backward() optimizer.step() # 每10轮打印一次损失 if (epoch + 1) % 50 == 0: print(f"Epoch {epoch+1}/{epochs}, Total Loss: {total_loss.item():.4f}, Content Loss: {c_loss.item():.4f}, Style Loss: {s_loss.item():.4f}")

接下来你只需要等它跑完就行,如果用GPU的话300次只需要一两分钟,就算用CPU也只需要十几分钟,很快就能出结果。

跑完之后我们把生成的图片还原,显示出来:

把生成图的归一化还原,转成图片格式

untransform = transforms.Compose([ transforms.Normalize(mean=[-0.485/0.229, -0.456/0.224, -0.406/0.225], std=[1/0.229, 1/0.224, 1/0.225]), transforms.ToPILImage() ])

gen_img_final = gen_img.squeeze(0).cpu() gen_pil = untransform(gen_img_final)

显示图片

plt.imshow(gen_pil) plt.axis('off') plt.show()

保存图片

gen_pil.save('generated_art.jpg')

到这里你就得到了一张属于你自己的AI艺术画了!是不是非常简单?

1.4 结果展示与效果分析

我自己试了一张旅行拍的西湖照片,分别用梵高《星月夜》和莫奈《睡莲》做风格迁移,给大家说下不同参数出来的效果:

当风格权重设置为1000的时候:《星月夜》的效果非常明显,原本照片里的山峦都变成了梵高标志性的螺旋状笔触,湖水的波纹也变成了粗犷的条纹,同时照片里的雷峰塔轮廓完全保留了,整体既有照片的内容结构,又有梵高的星空风格,效果非常惊艳;

当我把风格权重调到5000的时候:风格效果更强了,但是雷峰塔的轮廓开始有点模糊,细节有点丢失,如果你想要更强烈的风格效果可以调高,想要保留更多原图细节就调低;

用莫奈《睡莲》做风格迁移的时候,出来的效果是莫奈标志性的细碎笔触,整体色彩变得非常柔和,像一幅印象派油画,完全看不出是原本的照片了。

很多零基础同学会问:这个出来的效果会不会很糊?其实只要你输入的原图清晰,迭代次数够300次,出来的效果是非常清晰的,完全可以用来做壁纸或者打印出来。

1.5 给零基础学习者的注意提示

第一次做这个项目肯定会遇到各种各样的小问题,我把大家最容易遇到的问题整理出来,提前避开坑:

环境问题:如果你的电脑没有NVIDIA显卡,跑CPU会比较慢,建议直接用免费的Google Colab或者国内的ModelArts、Kaggle Notbook,都提供免费的GPU,一两分钟就能跑完;

图片路径问题:很多同学运行的时候报“找不到图片”,大部分都是路径写错了,你要把图片和代码放在同一个文件夹,或者写绝对路径;

参数调整技巧:不要上来就改一大堆参数,默认参数(内容权重1,风格权重1000,迭代300次)已经能得到很好的效果了,跑完一遍之后再慢慢调参数试不同效果;

不要纠结原理细节:很多零基础同学卡在这里,非要搞懂格拉姆矩阵的数学原理才往下走,其实完全没必要,你先把项目跑通,得到成果,有成就感了再回头深入研究原理,进步会快很多;

拓展玩法:你可以尝试把自己的照片换成动漫图、书法作品,风格图换成国画、浮世绘,甚至用你自己画的草稿当风格图,能得到很多意想不到的效果。

实践项目二:时间序列预测——基于LSTM的销量/股价趋势预测

做完第一个好玩的视觉项目,我们再来看第二个非常实用的AI项目:时间序列预测。不管你是做零售运营做销售,还是炒股买基金,都会遇到一个问题:怎么根据过去的历史数据,预测未来的趋势?这个就是时间序列预测要解决的问题。

这个项目我们以超市商品销量预测为例,用LSTM神经网络来做,整个流程做完之后,你只需要把数据换成你自己的股价数据,就能用来预测股价趋势,方法是完全一样的。

2.1 项目背景:为什么要学时间序列预测?

时间序列就是按照时间顺序排列的一组数据,比如每天的销量、每天的股价、每个小时的气温,这些都是时间序列数据。预测未来的趋势是时间序列最常见的应用,在商业里,超市提前预测未来一周的商品销量,就能合理备货,避免卖不出去积压库存,也避免不够卖缺货亏钱;在金融领域,投资者通过预测股价走势来制定交易策略,所以这个项目的实用价值非常高。

为什么这个项目适合零基础入门?

很多零基础同学觉得预测是一件非常难的事情,其实这个项目对零基础非常友好:

数据获取非常简单:我们用的数据是Kaggle上公开的超市销售数据集,免费下载,而且已经整理好了,你甚至用Excel就能做数据清洗;

模型非常成熟:LSTM做时间序列预测已经是非常成熟的方法,PyTorch也有现成的LSTM层可以直接调用,不需要你自己实现LSTM的复杂结构;

能理解AI处理序列数据的核心逻辑:做完这个项目你就能明白什么是序列数据,怎么用滑动窗口把原始数据变成AI能训练的样本,这个逻辑是通用的,以后你做其他序列任务也能用。

2.2 核心概念讲解:零基础也能看懂的LSTM时间序列预测

我们还是不讲复杂的数学公式,只讲核心逻辑,让你能懂原理能做项目。

什么是时间序列预测的问题?

我们举个简单的例子:我们有过去100天,每天的某款矿泉水的销量,我们想要预测未来7天的销量是多少。一般我们的做法是:用过去N天的销量作为输入,来预测第N+1天的销量,比如我们用过去30天的销量预测第31天的销量,然后用2-31天的销量预测第32天的,以此类推,这样就能得到我们想要的未来一周的预测结果了,这个方法叫做滑动窗口法,是时间序列预测最常用的样本构造方法。

为什么要用LSTM,不用传统的线性回归?

传统的时间序列预测方法比如ARIMA,只能处理比较简单的趋势,对于有复杂波动、多因素影响的数据,预测效果不好。而LSTM是一种专门用来处理序列数据的循环神经网络,它最大的特点就是能记住序列里长期的信息,比如它能记住一个月前的促销活动对现在销量的影响,这是传统方法做不到的,所以对于复杂的销量、股价数据,LSTM的预测效果比传统方法好很多。

简单说一下LSTM的核心逻辑,你不用懂细节,只要知道它和普通神经网络的区别就行:普通神经网络一次处理一个样本,样本之间是独立的;而LSTM处理序列的时候,会保留之前处理过的数据的“记忆”,用这个记忆来帮助预测接下来的结果,所以非常适合时间序列这种前后有关联的数据。

2.3 完整实践步骤:从数据下载到模型训练一步步走

我们还是一步步来,零基础跟着做就能跑通。

步骤1:数据下载与预处理

首先我们去Kaggle下载公开的超市销售数据集,地址是:https://www.kaggle.com/datasets/coderpillr/supermarket-sales-dataset ,这个数据集整理了一家超市多个门店,不同商品分类1年多的每日销量数据,免费下载,大小只有几M,非常适合练手。

下载下来之后是一个csv文件,我们先把数据读进来,做一点简单的预处理,我们先选其中一个商品分类的销量来做预测,你如果要预测所有商品,分开做就行:

我们需要的包先装好:

pip install pandas numpy matplotlib scikit-learn torch

然后导入包,读数据:

import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.preprocessing import MinMaxScaler import torch import torch.nn as nn import torch.optim as optim

读数据,改成你自己的文件路径

df = pd.read_csv('supermarket_sales.csv')

把日期转成时间格式,按日期排序

df['date'] = pd.to_datetime(df['date']) df = df.sort_values('date')

我们选“饮料”这个分类的每日总销量来做预测,你可以换成其他分类

data = df[df['category'] == 'Beverages'].groupby('date')['daily_sales'].sum().values

把数据变成二维数组,方便归一化

data = data.reshape(-1, 1) print(f"我们一共拿到了{len(data)}天的饮料销量数据")

接下来我们要做归一化,因为神经网络对归一化之后的数据训练效果更好,LSTM也不例外:

把销量归一化到0-1之间

scaler = MinMaxScaler(feature_range=(0, 1)) scaled_data = scaler.fit_transform(data)

接下来我们用滑动窗口构造训练样本,我们设置用过去30天的销量预测未来1天的销量:

def create_sequences(data, seq_length): X = [] y = [] for i in range(len(data) - seq_length): X.append(data[i:i+seq_length]) y.append(data[i+seq_length]) return np.array(X), np.array(y)

seq_length = 30 # 用过去30天预测下一天 X, y = create_sequences(scaled_data, seq_length)

然后我们把数据分成训练集和测试集,一般我们用前80%的数据做训练,后20%做测试,测试集用来验证我们模型的预测效果对不对:

train_size = int(0.8 * len(X)) X_train, X_test = X[:train_size], X[train_size:] y_train, y_test = y[:train_size], y[train_size:]

转成PyTorch的张量,调整形状:LSTM的输入形状是(批次大小, 序列长度, 特征数),这里特征数是1,只有销量

X_train = torch.tensor(X_train, dtype=torch.float32) y_train = torch.tensor(y_train, dtype=torch.float32) X_test = torch.tensor(X_test, dtype=torch.float32) y_test = torch.tensor(y_test, dtype=torch.float32)

print(f"训练集样本数:{len(X_train)}, 测试集样本数:{len(X_test)}")

步骤2:定义LSTM预测模型

接下来我们定义我们的LSTM模型,结构非常简单,就是一层LSTM层加一个全连接输出层,PyTorch已经把LSTM实现好了,我们直接用就行:

class LSTMTimeSeries(nn.Module): def init(self, input_size=1, hidden_size=50, num_layers=1, output_size=1): super(LSTMTimeSeries, self).init() self.hidden_size = hidden_size self.num_layers = num_layers # LSTM层,输入特征是1,隐藏层神经元是50个,1层 self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True) # 全连接层,把LSTM的输出转成我们要预测的销量值 self.fc = nn.Linear(hidden_size, output_size)

这个模型非常简单,只有不到20行代码,你不需要改任何东西,直接用就行,参数都是适合小数据集的默认参数,效果很好。

步骤3:训练模型

接下来我们就可以开始训练模型了,我们用均方误差作为损失函数,用Adam优化器来更新参数:

选择设备,有GPU用GPU,没有用CPU

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') model = LSTMTimeSeries().to(device) X_train = X_train.to(device) y_train = y_train.to(device) X_test = X_test.to(device) y_test = y_test.to(device)

criterion = nn.MSELoss() # 回归问题用均方误差损失 optimizer = optim.Adam(model.parameters(), lr=0.001) epochs = 100 # 训练100轮,对于小数据集足够了 train_losses = [] test_losses = []

开始训练

model.train() for epoch in range(epochs): optimizer.zero_grad() # 前向传播得到预测值 outputs = model(X_train) loss = criterion(outputs, y_train) # 反向传播更新参数 loss.backward() optimizer.step() # 记录损失 train_losses.append(loss.item()) # 计算测试集损失 model.eval() with torch.no_grad(): test_outputs = model(X_test) test_loss = criterion(test_outputs, y_test) test_losses.append(test_loss.item()) model.train() if (epoch + 1) % 10 == 0: print(f"Epoch {epoch+1}/{epochs}, Train Loss: {loss.item():.6f}, Test Loss: {test_loss.item():.6f}")

训练过程会输出每一轮的训练损失和测试损失,一般训练100轮之后损失就稳定了,不会再下降了,如果你的损失还在降,可以多训练几十轮。

步骤4:预测未来7天的销量

训练完模型之后,我们就可以做预测了,我们先把测试集的预测结果做出来,看看和真实值拟合得怎么样,然后再预测未来7天的销量:

把所有数据的预测结果都做出来

model.eval() with torch.no_grad(): all_predictions = model(torch.tensor(X, dtype=torch.float32).to(device)).cpu().numpy()

把预测结果还原成原来的销量范围(因为我们之前做了归一化)

all_predictions = scaler.inverse_transform(all_predictions)

真实值也还原

y_true = scaler.inverse_transform(y)

接下来我们预测未来7天,怎么预测呢?我们用最后30天的真实数据预测第1天的,然后把预测出来的第1天加到序列末尾,去掉最早的一天,再预测第2天,以此类推,就能预测出7天的:

拿到最后30天的数据

last_seq = scaled_data[-seq_length:] future_predictions = [] model.eval() with torch.no_grad(): for _ in range(7): seq_tensor = torch.tensor(last_seq, dtype=torch.float32).unsqueeze(0).to(device) pred = model(seq_tensor) pred_np = pred.cpu().numpy()[0] future_predictions.append(pred_np[0]) # 把预测结果加进去,去掉最早的一个 last_seq = np.vstack([last_seq[1:], pred_np])

还原预测结果

future_predictions = scaler.inverse_transform(np.array(future_predictions).reshape(-1, 1))

到这里我们就拿到了未来7天的销量预测结果了!接下来我们来画图看看效果。

2.4 结果分析:拟合效果怎么样?

我们把真实销量、训练集预测、测试集预测还有未来7天预测都画出来看看效果:

plt.figure(figsize=(15, 6))

画出真实销量

plt.plot(df['date'][seq_length:], data[seq_length:], label='真实销量', color='blue')

画出预测销量

plt.plot(df['date'][seq_length:train_size+seq_length], all_predictions[:train_size], label='训练集预测', color='green') plt.plot(df['date'][train_size+seq_length:], all_predictions[train_size:], label='测试集预测', color='red')

画出未来7天预测

future_dates = pd.date_range(df['date'].iloc[-1] + pd.Timedelta(days=1), periods=7) plt.plot(future_dates, future_predictions, label='未来7天预测', color='orange', linestyle='--') plt.legend() plt.xlabel('日期') plt.ylabel('销量') plt.title('饮料销量LSTM预测结果') plt.show()

我们来分析我跑出来的结果:

训练集拟合效果:训练集的预测曲线几乎和真实曲线重合,说明模型很好地学习到了历史数据的规律;

测试集拟合效果:测试集的预测曲线整体趋势和真实曲线一致,峰值和谷值的位置也基本对得上,整体误差在10%以内,对于一个简单的单变量LSTM模型来说,这个效果已经非常好了,完全可以用来做备货参考;

未来预测结果:未来7天的预测曲线延续了之前的趋势,如果之前一周销量是上升的,预测也会延续上升趋势,如果之前是下降的,也会延续下降趋势,当然因为我们只用了历史销量一个变量,没有加入促销、节假日这些因素,如果加上这些信息,预测精度会更高。

如果我们把这里的销量数据换成每天的股价收盘价,流程完全一样,就能得到股价未来一周的预测趋势,当然要说明的是:股价受太多因素影响,就算模型拟合得好,也不代表未来一定准,这个大家一定要注意,不要拿来直接做交易哦。

2.5 给零基础学习者的学习提示

这个项目也给大家整理几个常见的坑和提升技巧:

滑动窗口长度选择:我们这里选了30天,你也可以试7天、14天,一般序列长度不要太长也不要太短,太长了LSTM也记不住那么多信息,太短了信息不够,对于日销量日股价数据,30天左右效果最好;

过拟合问题:如果你发现训练损失很低,测试损失很高,就是过拟合了,你可以把LSTM的隐藏层神经元数从50改成30,或者加入dropout,就能缓解过拟合;

数据量问题:我们这个项目用了三百多天的数据,足够训练一个简单的LSTM模型了,如果你的数据更少,可以试试Facebook的Prophet模型,Prophet对于小数据量的时间序列预测效果更好,而且代码更简单,非常适合零基础;

提升精度的方法:我们这里只用了历史销量一个特征,如果你想要更高精度,可以加入日期相关特征(比如是不是周末、是不是节假日)、促销信息,把这些作为额外特征输入LSTM,预测精度会提升很多;

不要迷信模型:时间序列预测本质上是用历史规律预测未来,如果未来没有发生大的变化,预测就准,如果有黑天鹅事件(比如疫情、突然的政策变化),再好的模型也预测不准,商业应用一定要结合业务经验调整。

三、零基础AI入门的一点感悟

两个项目做完,我相信你对AI实践已经有了基本的认知,其实零基础入门AI,最关键的不是先学完所有理论再做项目,而是先跑通一个完整的项目,获得成就感,然后再慢慢补理论和基础,很多人走错了路,学了半年数学还没写过一行代码,最后肯定坚持不下去。

我们这两个项目,一个覆盖了计算机视觉(图像处理),一个覆盖了序列预测(时序数据),都是现在AI应用最广泛的领域,你做完这两个项目,就已经超过了80%嘴上说要学AI但是从来不动手的人了。接下来你可以试试拓展这两个项目,比如把风格迁移做成一个web小工具,上传图片就能生成,给你的朋友用;或者把你的时间序列预测换成你感兴趣的股票,试试看预测效果,这样你的进步会非常快。

最后给零基础同学一个建议:AI没有你想的那么难,现在开源社区有这么多成熟的代码和预训练模型,你不需要从零开始,只要会改参数、会换数据,就能做出属于自己的AI项目,从一个个小项目开始,积累下来,你很快就能成为能独立做项目的AI实践者了。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐