TensorFlow手写数字识别代码运行报错:numpy.AxisError问题求助
解决numpy.AxisError问题:MNIST手写数字识别输入格式错误
这是之前MNIST神经网络相关提问的跟进内容,基于TensorFlow预编写了MNIST数据集的神经网络,调整后包含main.py和screen.py两个文件:
main.py代码
import tensorflow as tf import matplotlib.pyplot as plt import numpy as np mnist=tf.keras.datasets.mnist (x_train, y_train), (x_test, y_test) = mnist.load_data() x_train=tf.keras.utils.normalize(x_train, axis=1) x_test=tf.keras.utils.normalize(x_test, axis=1) model=tf.keras.models.Sequential() model.add(tf.keras.layers.Flatten()) model.add(tf.keras.layers.Dense(128, activation=tf.nn.relu)) model.add(tf.keras.layers.Dense(128, activation=tf.nn.relu)) model.add(tf.keras.layers.Dense(10, activation=tf.nn.softmax)) model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model.fit(x_train, y_train, epochs=3) val_loss, val_acc = model.evaluate(x_test, y_test) print(val_loss, val_acc) model.save("num_reader.model") new_model=tf.keras.models.load_model('num_reader.model') predictions=new_model.predict([x_test]) print(predictions)
screen.py代码
import tensorflow as tf import pygame import sys import numpy as np from main import * import main as nn class Screen: def __init__(self): pygame.init() #self.screen=pygame.display.set_mode((28,28),pygame.FULLSCREEN) self.screen=pygame.display.set_mode((280,280)) self.array=[] self.setArr() self.bg_color=(250, 250,250) self.ok=False self.full=[] self.done=False print(new_model) self.result=0 def runGame(self): self.screen.fill(self.bg_color) while True: pygame.display.flip() self._check_events() self.draw() if self.full != []: break def _check_events(self): for event in pygame.event.get(): if event.type==pygame.QUIT: sys.exit() if event.type==pygame.KEYDOWN: if event.key==pygame.K_ESCAPE: sys.exit() if event.key==pygame.K_d: self.done=True self.decode() print(len(self.full)) if event.key==pygame.K_c: self.done=False self.setArr() self.screen.fill(self.bg_color) if event.type==pygame.MOUSEBUTTONDOWN: #print("mouseDown") self.ok=True elif event.type==pygame.MOUSEBUTTONUP: self.ok=False def setArr(self): self.shortArr=[] for y in range(28): self.shortArr.append(0) for x in range(28): self.array.append(self.shortArr) def draw(self): if self.ok==True: x,y=pygame.mouse.get_pos() x=round(x/10)*10 y=round(y/10)*10 #print(x,y) #print(self.array[int(x)//10][int(y)//10]) self.array[int(x)//10][int(y)//10]=1 pygame.draw.rect(self.screen, (0,0,0), pygame.Rect(x, y, 10, 10)) #print("draw") def decode(self): self.full=[] for x in range(28): for y in range(28): self.full.append(self.array[x][y]) if __name__ == '__main__': Sc=Screen() Sc.runGame() result = nn.new_model.predict(tf.keras.utils.normalize(np.array(Sc.full), axis=1)) print(result)
运行代码时出现以下错误:
Traceback (most recent call last): File "C:\Users\user\Documents\Jake\machine learning\MNIST dataset SOLVED\screen.py", line 81, in <module> result = nn.new_model.predict(tf.keras.utils.normalize(np.array(Sc.full), axis=1)) File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\site-packages\keras\utils\np_utils.py", line 89, in normalize l2 = np.atleast_1d(np.linalg.norm(x, order, axis)) File "<__array_function__ internals>", line 180, in norm File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\site-packages\numpy\linalg\linalg.py", line 2547, in norm return sqrt(add.reduce(s, axis=axis, keepdims=keepdims)) numpy.AxisError: axis 1 is out of bounds for array of dimension 1
问题原因与解决方案
问题根源
- 维度不匹配:
Sc.full是一维数组(长度784),但tf.keras.utils.normalize指定axis=1时,要求输入至少为二维数组。训练时的x_train是(60000,28,28)的三维数组,归一化时axis=1针对每个样本的行维度操作,一维输入无法满足该要求,因此报错。 - 模型输入格式不符:模型接受的输入是批量样本,每个样本为28x28的二维数组,当前传入的是一维784元素数组,且缺少批量维度(即使单样本也需添加维度变为(1,28,28))。
- 数组初始化bug:
setArr方法中所有行引用了同一个shortArr列表,导致修改某一行元素时所有行对应位置都会同步变化。
修改步骤
1. 修正输入格式(修改screen.py主函数部分)
if __name__ == '__main__': Sc=Screen() Sc.runGame() # 将一维数组转为28x28的二维图像格式 input_img = np.array(Sc.full).reshape(28, 28) # 添加批量维度,转为(1,28,28),匹配模型输入要求 input_img = np.expand_dims(input_img, axis=0) # 归一化,axis=1与训练时逻辑一致 normalized_input = tf.keras.utils.normalize(input_img, axis=1) # 执行预测 result = nn.new_model.predict(normalized_input) # 输出预测的数字 print("预测结果:", np.argmax(result))
2. 修正数组初始化bug(修改setArr方法)
def setArr(self): self.array=[] for x in range(28): # 每次循环创建新列表,避免所有行引用同一对象 self.shortArr=[] for y in range(28): self.shortArr.append(0) self.array.append(self.shortArr)
说明
reshape(28,28):将一维的784元素数组还原为MNIST标准的28x28图像尺寸。expand_dims(input_img, axis=0):为单样本添加批量维度,模型默认接受批量输入(形状为(batch_size, 28, 28))。- 修正后的
setArr方法:每次循环创建新列表,保证每行独立,避免绘图时所有行同步变化的问题。
内容的提问来源于stack exchange,提问作者jake is the coolest
相关产品推荐
相关产品推荐

