原来飞桨还可以这么玩!当人工智能邂逅蓝桥杯算法题,会擦出怎样的火花?
本文以蓝桥杯的Fibonacci数列、大等于n的最小完全平方数为例,用飞桨解决问题。先阐述神经网络原理,从简单神经元到多层网络,再说明其工作机制。接着分别对两道题生成数据、构建模型、优化器和损失函数,经训练和验证,模型能近似拟合结果,展示了用机器学习解决算法题的思路。

当人工智能邂逅蓝桥杯算法题,会擦出怎样的火花?
假如人工智能也玩起了蓝桥杯算法题... ...
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
目前,蓝桥杯上几乎所有算法题都是每个输入都有唯一确定的输出,对于一些输入输出是线性关系的题目,利用机器学习可以做一个对应的拟合,从而根据拟合出来的模型得到最终结果。
本文会以蓝桥杯的2道算法题(Fibonacci数列、大等于n的最小完全平方数)为例,尝试使用飞桨解决上面这两道算法题。
一、实现原理
虽然都说神经网络是个大黑盒,但是,其实这个黑盒并不是那么黑。
一个神经元就相当于一个函数,最简单的神经网络只有一个神经元神经网络是由许许多多的神经元搭建起来的,也就是说一个能拟合任意函数的函数拟合器其实是由许许多多的函数搭建起来的是不是有点像傅里叶级数?(傅里叶发现任何周期函数都可以用正弦函数和余弦函数构成的无穷级数来表示)
1.从最简单的神经网路开始
在学习机器学习的过程中,大家对神经网络应该都有一个基本概念:神经网络就像一个函数拟合器,它可以拟合任意函数。
举个例子,输入一个数,输出它的相反数,那么这个函数就是正比例函数,且它的比例系数为-1,我们试着构造一个刚刚描述的神经网络:
In [ ]def NeuralNetwork(inputs, weight): # 定义神经网络 prediction = inputs * weight # 将数据与权重相乘 return predictioninputs = 2 # 输入数据,可随意更换weight = -1 # 权重pred = NeuralNetwork(inputs, weight) # 前向传播,即获得预测结果print(pred)登录后复制
-2登录后复制
刚刚我们完成的就是前向传播的过程,也就是一个预测的过程 。
预测其实就是神经网络对输入数据进行“思考”后得到的结果,更复杂的例子有:基于昨天的天气预测今天的天气
2.神经网络工作原理概述
上面的那个神经网络将输入乘以权重,将输入数据“缩放”一定的比例。神经网络的交互其实很简单:
目前为止,所有的神经网络都是这样工作的,它使用权重中的知识解释输入数据中的信息。
看到这里,你心中也许会有疑惑,为什么可以把权重当作知识?
另一种理解神经网络权重值的方法,是将权重作为网络的输入和预测之间敏感度的度量:
3.使用多个输入进行预测
在实际场景中,如果能给神经网络提供的信息越多,那么神经网络应该能做出更准确的预测。
事实上,一个网络也可以同时接受多个输入数据点。就像下面这个例子:
weights = [0.012, 0.3, 0.25] #温度、湿度、风速的权重inputs = [26, 0.75, 1.2] #温度、湿度、风速数据def PredSum(inputs, weights): assert(len(inputs) == len(weights)) output = 0 for item in range(len(inputs)): output += inputs[item] * weights[item] #将输入分别乘以其对应的权重 return outputdef NeuralNetwork(inputs, weights): pred = PredSum(inputs, weights) return predpred = NeuralNetwork(inputs, weights)print(pred) #一段时间后发生某事的概率,如下雨的概率登录后复制
0.837登录后复制登录后复制
这种新的神经网络可以同时接受多个输入并作出预测。这使得网络能够结合多种形式的信息,做出更明智的决定。但是它使用权重的基本机制并没有改变。
这里带来的新特性是,因为有多个输入,所以要把他们各自的预测结果合在一起。因此,将每个输入乘以其各自的权重,然后对所有局部预测结果进行求和,这称为输入的加权和。
不过,像上面这样的代码虽然一次就可以处理多个输入,但是还是显得太麻烦了,因此,我们需要用到新工具:Numpy
对于创建向量和执行常见函数(如点积运算)来说,它的代码效率很高,下面是利用Numpy实现相同功能的代码:
In [ ]import numpy as npweights = np.array([0.012, 0.3, 0.25])inputs = np.array([26, 0.75, 1.2])def NeuralNetwork(inputs, weights): pred = inputs.dot(weights) return predpred = NeuralNetwork(inputs, weights)print(pred)登录后复制
0.837登录后复制登录后复制
4.只用一个输入做出多个输出
多输出可能是比多输入更简单的拓展。如果是3个输出,则预测过程与三个单一权重的独立神经网络是一样的。需要注意的是,这3个预测结果完全独立。
假设我们在一场球赛上,想通过某个球队的胜负记录预测球员的心情(是高兴还是悲伤)、下一场比赛的结果以及队员的受伤比例,来看看这个例子怎么做:
In [ ]import numpy as npweights = np.array([0.3, 0.2, 0.9])inputs = 0.65def NeuralNetwork(inputs, weights): pred = inputs * weights return predpred = NeuralNetwork(inputs, weights)# print(pred)print("受伤比例预测:{}".format(pred[0]))print("比赛胜负预测:{}".format(pred[1]))print("悲伤程度预测:{}".format(pred[2]))登录后复制 受伤比例预测:0.195比赛胜负预测:0.13悲伤程度预测:0.5850000000000001登录后复制
5.基于多个输入得到多个输出
基于给定的多个输入,神经网络预测得到多个输出。
假设我们在一场球赛上,想通过某个球队的胜负记录、粉丝数和球员数量来预测球员的心情(是高兴还是悲伤)、下一场比赛的结果以及队员的受伤比例,来看看这个例子怎么做:
In [ ]import numpy as np#从左到右分别是:[是否受伤, 是否胜利, 是否难过]weights = np.array([[0.02, 0.01, 0.05], #胜负记录 [0.001, 0.025, 0.04], #粉丝数量 [0.013, 0.03, 0.001]]) #球员数量inputs = np.array([0.65, 12.0, 8.0]) #分别是该球队的胜负记录、粉丝数量、球员数量def NeuralNetwork(inputs, weights): pred = inputs.dot(weights) return predpred = NeuralNetwork(inputs, weights)# print(pred)print("受伤比例预测:{}".format(pred[0]))print("比赛胜负预测:{}".format(pred[1]))print("悲伤程度预测:{}".format(pred[2]))登录后复制 受伤比例预测:0.129比赛胜负预测:0.5465悲伤程度预测:0.5205登录后复制
分析一下上面这个例子,这个神经网络对输入数据执行了3次独立的加权和操作,产生了3个预测结果。其实就是简单的矩阵运算,横行乘竖列再相加。
6.用预测结果进一步预测
神经网络是可以堆叠的!可以将一个网络的输出提供给另一个网路作为输入。这相当于两个连续的向量矩阵乘法。
这样做的原因是:在处理复杂问题时,对于单一权重矩阵来说过于复杂(即参数的数量不够)。
还是上面的例子:在一场球赛上,想通过某个球队的胜负记录、粉丝数和球员数量来预测球员的心情(是高兴还是悲伤)、下一场比赛的结果以及队员的受伤比例:
In [ ]import numpy as np#从左到右分别是:[是否受伤, 是否胜利, 是否难过]InputHiddent = np.array([[0.2, 0.01, 0.05], #隐藏层第一个单元 [0.01, 0.025, 0.04], #隐藏层第二个单元 [0.13, 0.03, 0.001]]) #隐藏层第三个单元#从左到右分别是:隐藏层第一个单元到第三个单元的权重HiddentPrediction = np.array([[0.02, 0.1, 0.5], #胜负记录 [0.01, 0.25, 0.04], #粉丝数量 [0.013, 0.3, 0.01]]) #球员数量weights = [InputHiddent, HiddentPrediction] #存放权重值,[输入到隐藏层的权重, 隐藏层到输出的权重]inputs = np.array([0.65, 12.0, 8.0]) #分别是该球队的胜负记录、粉丝数量、球员数量def NeuralNetwork(inputs, weights): hid = inputs.dot(weights[0]) #计算隐藏层的输出 pred = hid.dot(weights[1]) #将上一层(隐藏层)的输出带入下一层的输入 return predpred = NeuralNetwork(inputs, weights)# print(pred)print("受伤比例预测:{}".format(pred[0]))print("比赛胜负预测:{}".format(pred[1]))print("悲伤程度预测:{}".format(pred[2]))登录后复制 受伤比例预测:0.0380315比赛胜负预测:0.421775悲伤程度预测:0.672065登录后复制
二、拟合斐波那契数列
Fibonacci数列是蓝桥杯试题入门训练的题目,算是一道入门的题目,我们尝试让神经网络试试看,看看能不能解决这道题
1.问题描述
斐波那契数列的递推公式为:Fn=Fn−1+Fn−2,其中F1=F2=1。
当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。
输入格式
输入包含一个整数n。
输出格式
输出一行,包含一个整数,表示Fn除以10007的余数。
2.生成数据
数据几乎是所有模型的关键,它决定着模型的天花板。
这里我们用到的是numpy里生成随机数的函数:
numpy.random.randint(low, high=None, size=None, dtype='l')登录后复制
函数的作用是,返回一个随机整型数,范围从低(包括)到高(不包括),即[low,high)。如果没有写参数high的值,则返回[0,low)的值。
参数如下:
low: int
生成的数值最低要大于等于low。 (hign = None时,生成的数值要在[0,low)区间内)
high: int (可选)
如果使用这个值,则生成的数值在[low, high)区间。
size: int or tuple of ints(可选)
输出随机数的尺寸,比如size = (m * n* k)则输出同规模即m * n* k个随机数。默认是None的,仅仅返回满足要求的单一随机数。
dtype: dtype(可选)
想要输出的格式。如int64、int等等
输出:
out: int or ndarray of ints返回一个随机数或随机数数组
输入数据
In [48]# 生成输入数据import numpynum_inputs=1num_examples=10features = numpy.random.randint(1, 10, (num_examples, num_inputs)) # 生成含有10个1~10的元素的二维列表登录后复制 In [ ]
print(features[:,0])登录后复制
数据对应的标签
In [1]def Fibonacci(n): # 求斐波契那数列的函数,输入n,输出第n项对应的值 F = [1, 1] if n <= 2: for item in range(n): F.append(F[item] + F[item + 1]) return F[n - 1]%10007 else: for item in range(n - 2): result = (F[0] + F[1]) % 10007 # 计算出下一项后直接取余数,不影响结果 F[0], F[1] = F[1], result return result # 直接输出余数,不需要再除10007登录后复制 In [3]
# 输出斐波那契数列的前9项for item in range(1, 10): print(Fibonacci(item), end=" ")登录后复制
1 1 2 3 5 8 13 21 34登录后复制 In [49]
# 生成输入对应的标签labels = []for item in features[:,0].tolist(): labels.append(Fibonacci(item))labels = numpy.expand_dims(labels, axis=-1) #注意:需要在最后增加一个维度登录后复制 In [ ]
print(labels[:,0])登录后复制
将数组转换成张量
In [50]# 将数据转换成tensorimport paddlefeatures = features.astype('float32')labels = labels.astype('float32')train_datas = paddle.to_tensor(features)y_true = paddle.to_tensor(labels)登录后复制登录后复制 3.构建线性回归模型
飞桨框架2.0中,组网相关的API都在paddle.nn目录下,你可以通过 Sequential 或 SubClass 的方式构建具体的模型。
这里我们使用最简单的线性变换层组网:
class paddle.nn.Linear(in_features, out_features, weight_attr=None, bias_attr=None, name=None)登录后复制登录后复制
参数:
in_features (int) – 线性变换层输入单元的数目。out_features (int) – 线性变换层输出单元的数目。weight_attr (ParamAttr, 可选) – 指定权重参数的属性。默认值为None,表示使用默认的权重参数属性,将权重参数初始化为0。具体用法请参见 ParamAttr 。bias_attr (ParamAttr|bool, 可选) – 指定偏置参数的属性。 bias_attr 为bool类型且设置为False时,表示不会为该层添加偏置。 bias_attr 如果设置为True或者None,则表示使用默认的偏置参数属性,将偏置参数初始化为0。具体用法请参见 ParamAttr 。默认值为None。name (str,可选) – 具体用法请参见 Name ,一般无需设置,默认值为None。In [59]import paddleclass Regressor(paddle.nn.Layer): def __init__(self): super(Regressor, self).__init__() self.fc1 = paddle.nn.Linear(1, 2) # 输入数据的维度是1,所以in_features必须为1 self.fc2 = paddle.nn.Linear(2, 2) # 上一层的输出维度是2,所以in_features必须为2 self.fc3 = paddle.nn.Linear(2, 1) # 根据题目,输出斐波那契数列数列第n项的值,因此输出维度为1 def forward(self, inputs): inputs = self.fc1(inputs) hiddent = self.fc2(inputs) pred = self.fc3(hiddent) return predmodel = Regressor()登录后复制
4.构建优化器和损失函数
最优化问题是计算数学中最为重要的研究方向之一。在深度学习领域,优化算法同样是关键环节之一。即使完全相同的数据集与模型架构,不同的优化算法也很可能导致不同的训练结果,甚至有的模型出现不收敛现象。
训练的过程包含以下几点:
数据集加载网络搭建优化器设置学习率调整(可选)度下降是目前神经网络中使用最为广泛的优化算法之一。为弥补基本梯度下降的种种缺陷,研究者们提出了一系列的变种算法,从最初的SGD逐步演变到Adam、RMSprop等。
这里我们使用的是Adam算法:
In [60]# 定义Adam优化器lr = paddle.optimizer.lr.CosineAnnealingDecay(learning_rate=0.5, T_max=50)optimizer = paddle.optimizer.Adam(learning_rate=lr, parameters=model.parameters(), weight_decay=paddle.regularizer.L2Decay(0.0001))mse_loss = paddle.nn.MSELoss() # 计算预测值和目标值的均方差误差登录后复制
5.模型训练
模型训练主要有下面几个步骤:
前向传播计算误差反向传播更新参数梯度清零In [65]for i in range(1000): # 训练100轮 y_predict = model(train_datas) # 前向传播得到预测结果 loss = mse_loss(y_predict, y_true) # 计算预测结果与期望值的差距 loss.backward() # 根据损失进行反向传播 optimizer.step() # 更新参数 optimizer.clear_grad() # 梯度清零print(loss.numpy())登录后复制
[3.0985627]登录后复制
6.模型验证
斐波那契数列的前9项:
In [66]infer_features = numpy.random.randint(1, 10, (1, 1)).astype('float32') # 随机生成一个数据infer_features = paddle.to_tensor(infer_features)fetch_list = model(infer_features) # 前向传播登录后复制 In [68]print(infer_features)print(fetch_list)登录后复制登录后复制
Tensor(shape=[1, 1], dtype=float32, place=CUDAPlace(0), stop_gradient=True, [[6.]])Tensor(shape=[1, 1], dtype=float32, place=CUDAPlace(0), stop_gradient=False, [[9.02307510]])登录后复制
斐波那契数列的第6项是8,模型的预测输出是9.02,取整就是9,虽然不是很准确,但是结果接近。
三、大等于n的最小完全平方数
大等于n的最小完全平方数是蓝桥杯试题算法训练里的练习题,难度比斐波那契数列要难一些,我们用飞桨来解这一题,过程跟上一题类似。
1.问题描述
输出大等于n的最小的完全平方数。
若一个数能表示成某个自然数的平方的形式,则称这个数为完全平方数
Tips:注意数据范围
输入格式
一个整数n
输出格式
大等于n的最小的完全平方数
样例输入71711登录后复制 样例输出
71824登录后复制
2.生成数据
数据生成的方法跟上一题类似,关于numpy.random模块还有很多用法,可以尝试使用该模块生成更多的数据。
In [144]# 生成输入数据import numpynum_inputs=1num_examples=10features = numpy.random.randint(1, 10, (num_examples, num_inputs))登录后复制 In [5]
import mathdef PerfectSquare(n): # 求最小完全平方数的方法 result = 0 if n >= 0: result = n ** 0.5 result = math.ceil(result) result = result ** 2 return result登录后复制 In [6]
# 输出1~10的最小完全平方数for item in range(1, 10): print(PerfectSquare(item), end=" ")登录后复制
1 4 4 4 9 9 9 9 9登录后复制 In [145]
# 生成输入对应的标签labels = []for item in features[:,0].tolist(): labels.append(PerfectSquare(item))labels = numpy.expand_dims(labels, axis=-1) #注意:需要在最后增加一个维度登录后复制 In [146]
# 将数据转换成tensorimport paddlefeatures = features.astype('float32')labels = labels.astype('float32')train_datas = paddle.to_tensor(features)y_true = paddle.to_tensor(labels)登录后复制登录后复制 3.构建线性回归模型
飞桨框架2.0中,组网相关的API都在paddle.nn目录下,你可以通过 Sequential 或 SubClass 的方式构建具体的模型。
这里我们使用最简单的线性变换层组网:
class paddle.nn.Linear(in_features, out_features, weight_attr=None, bias_attr=None, name=None)登录后复制登录后复制
参数:
in_features (int) – 线性变换层输入单元的数目。out_features (int) – 线性变换层输出单元的数目。weight_attr (ParamAttr, 可选) – 指定权重参数的属性。默认值为None,表示使用默认的权重参数属性,将权重参数初始化为0。具体用法请参见 ParamAttr 。bias_attr (ParamAttr|bool, 可选) – 指定偏置参数的属性。 bias_attr 为bool类型且设置为False时,表示不会为该层添加偏置。 bias_attr 如果设置为True或者None,则表示使用默认的偏置参数属性,将偏置参数初始化为0。具体用法请参见 ParamAttr 。默认值为None。name (str,可选) – 具体用法请参见 Name ,一般无需设置,默认值为None。In [147]import paddlemodel = paddle.nn.Linear(in_features=1, out_features=1) # 使用最简单的线性变换层登录后复制
4.构建优化器和损失函数
最优化问题是计算数学中最为重要的研究方向之一。在深度学习领域,优化算法同样是关键环节之一。即使完全相同的数据集与模型架构,不同的优化算法也很可能导致不同的训练结果,甚至有的模型出现不收敛现象。
训练的过程包含以下几点:
数据集加载网络搭建优化器设置学习率调整(可选)度下降是目前神经网络中使用最为广泛的优化算法之一。为弥补基本梯度下降的种种缺陷,研究者们提出了一系列的变种算法,从最初的SGD逐步演变到Adam、RMSprop等。
这里我们使用的是Adam算法:
In [148]# 定义Momentum优化器lr = paddle.optimizer.lr.CosineAnnealingDecay(learning_rate=0.25, T_max=100)optimizer = paddle.optimizer.Adam(learning_rate=lr, parameters=model.parameters(), weight_decay=paddle.regularizer.L2Decay(0.0002))mse_loss = paddle.nn.MSELoss() # 计算预测值和目标值的均方差误差登录后复制
5.模型训练
模型训练主要有下面几个步骤:
前向传播计算误差反向传播更新参数梯度清零In [149]for i in range(100): y_predict = model(train_datas) loss = mse_loss(y_predict, y_true) loss.backward() optimizer.step() optimizer.clear_grad()print(loss.numpy())登录后复制
[0.77032995]登录后复制
6.模型验证
In [155]infer_features = numpy.random.randint(1, 10, (1, 1)).astype('float32')infer_features = paddle.to_tensor(infer_features)fetch_list = model(infer_features)登录后复制 In [156]print(infer_features)print(fetch_list)登录后复制登录后复制
Tensor(shape=[1, 1], dtype=float32, place=CUDAPlace(0), stop_gradient=True, [[6.]])Tensor(shape=[1, 1], dtype=float32, place=CUDAPlace(0), stop_gradient=False, [[8.56781006]])登录后复制
6的最小完全平方数是9,模型的输出是8.56,比较接近9,但是还有点差距,不过总的来说,是可以近似拟合的。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
说一下WorkBuddy 的 Plan 模式
如何切换到 Plan 模式 想体验这种更可控的方式?操作很简单。在 WorkBuddy 主界面的右下角,你会看到一个“安全模式切换”的下拉菜单,从中选择“Plan”选项即可完成切换。 核心使用流程 光说概念可能有点抽象,咱们直接看个例子。假设你手头有个任务:“把桌面上‘项目报告’文件夹里所有Exce
滴滴出行开放打车 Skill,“龙虾”叫车全程不需要切换 App
滴滴出行全网首发语音打车Skill,一句话智能叫车全攻略 近日,滴滴出行正式上线了一项创新的语音交互功能:全面开放打车Skill。这意味着,用户只需通过语音指令,即可完成从叫车到行程追踪的全流程,真正实现“动口不动手”的便捷出行体验。 整个操作过程,包括目的地搜索、车型比价、下单确认、查看订单状态等
阿里千问 AI 眼镜接入蚂蚁 GPASS:语音解锁共享单车、停车缴费
当AI眼镜学会“跑腿”:语音解锁单车,无感支付停车费 近来,智能穿戴领域的一个新动向值得关注:阿里旗下的千问AI眼镜,正式接入了蚂蚁集团的GPASS平台。这可不是一次简单的功能叠加,它意味着,诸如共享单车骑行、停车缴费这一系列高频的“AI办事”功能,开始从手机屏幕转移到了你的眼前。 简单说,借助GP
Workbuddy注册额外积分
角色定位与核心任务目标 明确了基本定位后,我们直接切入核心:作为一名专业的文章优化师,我的核心职责在于,将那些带有明显AI生成特征的文本,深度重塑为拥有个人特色与行业洞见的优质内容。 换句话说,这项任务的关键在于实施一次“精准的换血手术”。你必须严格保证原文所有的事实依据、核心观点、逻辑框架,以及每
我把 Anthropic 的 Harness 工程思想做成了一个 Skill
用AI写代码,难在哪儿? 用AI生成代码本身并不难,真正的挑战在于让它稳定地交付一个真正可用的东西。这篇文章,我们就来聊聊Anthropic工程团队是如何破解这个难题的,以及我如何将这套方法论落地成了一个可以复用的实战工具。 用 AI 写代码有多难?不是写不出来难,是让它稳定交付可用的东西很难。这篇
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
相关攻略
2015-03-10 11:25
2015-03-10 11:05
2021-08-04 13:30
2015-03-10 11:22
2015-03-10 12:39
2022-05-16 18:57
2025-05-23 13:43
2025-05-23 14:01
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

