# MindSpore报错: ValueError: For 'MatMul', the input dimensions must be equal, but got 'x1\_col': 817920 and 'x2\_row': 272640.

**1. 系统环境**

硬件环境\(Ascend/GPU/CPU\): Ascend/GPU/CPU

MindSpore版本: 不限

执行模式（动态图）: 不限模式

Python版本: 3.7.5

操作系统平台: Ubuntu 16.04

**2. 报错信息**

2.1报错信息

```
[ERROR] ANALYZER(8534,ffffb5cca780,python):2022-11-30-10:59:18.593.719 [mindspore/ccsrc/pipeline/jit/static_analysis/async_eval_result.cc:66] HandleException] Exception happened, check the information as below.
The function call stack (See file '/home/ma-user/work/rank_0/om/analyze_fail.dat' for more details):
# 0 In file /home/ma-user/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/nn/wrap/cell_wrapper.py(373)
loss = self.network(*inputs)
^
# 1 In file /home/ma-user/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/nn/wrap/cell_wrapper.py(111)
out = self._backbone(data)
^
# 2 In file /home/ma-user/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/nn/layer/basic.py(323)
if len(x_shape) != 2:
# 3 In file /home/ma-user/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/nn/layer/basic.py(326)
if self.has_bias:
# 4 In file /home/ma-user/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/nn/layer/basic.py(325)
x = self.matmul(x, self.weight)
^
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
/tmp/ipykernel_8534/2891349598.py in
1 model = ms.train.Model(net, loss, opt, metrics={'acc', 'loss'})
----> 2 model.train(25, ds_train, callbacks=[LossMonitor(per_print_times=ds_train.get_dataset_size())], dataset_sink_mode=False)
3 metrics = model.eval(ds_test)
4 print(metrics)
~/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/train/model.py in train(self, epoch, train_dataset, callbacks, dataset_sink_mode, sink_size)
904 callbacks=callbacks,
905 dataset_sink_mode=dataset_sink_mode,
--> 906 sink_size=sink_size)
907
908 def build(self, train_dataset=None, valid_dataset=None, sink_size=-1, epoch=1, jit_config=None):
~/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/train/model.py in wrapper(self, *args, **kwargs)
85 raise e
86 else:
---> 87 func(self, *args, **kwargs)
88 return wrapper
89
~/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/train/model.py in _train(self, epoch, train_dataset, callbacks, dataset_sink_mode, sink_size)
540 self._check_reuse_dataset(train_dataset)
541 if not dataset_sink_mode:
--> 542 self._train_process(epoch, train_dataset, list_callback, cb_params)
543 elif context.get_context("device_target") == "CPU":
544 logger.info("The CPU cannot support dataset sink mode currently."
~/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/train/model.py in _train_process(self, epoch, train_dataset, list_callback, cb_params)
792 cb_params.train_dataset_element = next_element
793 list_callback.step_begin(run_context)
--> 794 outputs = self._train_network(*next_element)
795 cb_params.net_outputs = outputs
796 if self._loss_scale_manager and self._loss_scale_manager.get_drop_overflow_update():
~/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/nn/cell.py in __call__(self, *args, **kwargs)
584 logger.warning(f"For 'Cell', it's not support hook function in graph mode. If you want to use hook "
585 f"function, please use context.set_context to set pynative mode.")
--> 586 out = self.compile_and_run(*args)
587 return out
588
~/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/nn/cell.py in compile_and_run(self, *inputs)
962 """
963 self._auto_parallel_compile_and_run = True
--> 964 self.compile(*inputs)
965
966 new_inputs = []
~/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/nn/cell.py in compile(self, *inputs)
935 """
936 if self._dynamic_shape_inputs is None or self._dynamic_shape_inputs[0] is None:
--> 937 _cell_graph_executor.compile(self, *inputs, phase=self.phase, auto_parallel_mode=self._auto_parallel_mode)
938 else:
939 self._check_compile_dynamic_shape(*inputs)
~/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/common/api.py in compile(self, obj, phase, do_convert, auto_parallel_mode, *args)
1004 enable_ge = context.get_context("enable_ge")
1005 self._graph_executor.set_weights_values(obj.parameters_dict())
-> 1006 result = self._graph_executor.compile(obj, args_list, phase, self._use_vm_mode())
1007 obj.compile_cache.add(phase)
1008 if not result:
~/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/ops/primitive.py in __check__(self, *args)
465 for track in tracks:
466 fn = getattr(self, 'check_' + track)
--> 467 fn(*(x[track] for x in args))
468
469
~/anaconda3/envs/MindSpore/lib/python3.7/site-packages/mindspore/ops/operations/math_ops.py in check_shape(self, x1, x2)
1387 if np.all(np.array(x1) != -1) and np.all(np.array(x2) != -1):
1388 if x1_col != x2_row:
-> 1389 raise ValueError(f"For '{cls_name}', the input dimensions must be equal, but got 'x1_col': {x1_col} "
1390 f"and 'x2_row': {x2_row}. And 'x' shape {x1}(transpose_a={self.transpose_a}), "
1391 f"'y' shape {x2}(transpose_b={self.transpose_b}).")
ValueError: For 'MatMul', the input dimensions must be equal, but got 'x1_col': 817920 and 'x2_row': 272640. And 'x' shape [32, 817920](transpose_a=False), 'y' shape [3, 272640](transpose_b=True).
```

2.2脚本代码

```
import numpy as np
import mindspore as ms
from mindspore import nn
from mindspore import context
from mindspore import dataset
from mindspore.train.callback import LossMonitor

#当前实验选择算力为Ascend，如果在本地体验，参数device_target设置为"CPU”
context.set_context(mode=context.PYNATIVE_MODE, device_target="CPU")

#要筛选的分辨率条件
targetWidth=426
targetHeight=640
targetChannal=3

#读取animal文件夹下所有文件的名字
rootDir='animal'
fileNameList=['cat','elephant','sheep']
label_map = {
'cat': 0,
'elephant': 1,
'sheep': 2
}
X,Y=[],[]
for fileName in fileNameList:
    for imgName in range(100):
        img=np.random.randn(targetWidth, targetHeight, targetChannal)
        if(len(img.shape)==3):
            width,height,channal=img.shape
        if width==targetWidth and height==targetHeight and channal==targetChannal:#符合筛选条件的样本留下放到X，其标签放到Y
            X.append(img.flatten())
            Y.append(label_map[fileName])#类别
#print(X,Y)

#划分训练集和测试集合
sampleNum=len(X)
train_idx = np.random.choice(sampleNum, int(sampleNum*0.8), replace=False)#取80%的样本作为训练集
test_idx = np.array(list(set(range(sampleNum)) - set(train_idx)))#剩下的样本作为测试集
X_train=[X[i].astype(np.float32) for i in range(len(X)) if i in train_idx]
Y_train=[Y[i] for i in range(len(Y)) if i in train_idx]
X_test=[X[i].astype(np.float32) for i in range(len(X)) if i in test_idx]
Y_test=[Y[i] for i in range(len(Y)) if i in test_idx]
XY_train = list(zip(X_train, Y_train))
ds_train = dataset.GeneratorDataset(XY_train, ['x', 'y'])
# ds_train.set_dataset_size(sampleNum)
ds_train = ds_train.shuffle(buffer_size=sampleNum).batch(32, drop_remainder=True)
XY_test = list(zip(X_test, Y_test))
ds_test = dataset.GeneratorDataset(XY_test, ['x', 'y'])
ds_test = ds_test.batch(30)#具体作用
#print(XY_test)
for e in X_train:
    print(e.shape)
net = nn.Dense(targetWidth*targetHeight, 3)
loss = nn.loss.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
opt = nn.optim.Momentum(net.trainable_params(), learning_rate=0.05, momentum=0.9)
model = ms.train.Model(net, loss, opt, metrics={'acc', 'loss'})
model.train(25, ds_train, callbacks=[LossMonitor(per_print_times=ds_train.get_dataset_size())], dataset_sink_mode=False)
metrics = model.eval(ds_test)
print(metrics)
```

**3. 根因分析**

根据报错信息的最后一行，可以定位到时是算子MatMul计算出错、

```
ValueError: For 'MatMul', the input dimensions must be equal, but got 'x1_col': 817920 and 'x2_row': 272640. And 'x' shape [32, 817920] (transpose_a=False), 'y' shape [3, 272640] (transpose_b=True).
```

而网络只有一层Dense和loss函数组成，因此只可能在Dense里调用了MatMul函数，Dense的任务就是在初始化时创建一个weight矩阵，矩阵的shape由初始化时传入的in\_channels 和 out\_channels决定，

```
class Dense(Cell):
    def __init__(self,
                 in_channels,
                 out_channels,
                 weight_init='normal',
                 bias_init='zeros',
                 has_bias=True,
                 activation=None):
        """Initialize Dense."""
        ...
        self.weight = Parameter(initializer(weight_init, [out_channels, in_channels]), name="weight")
        ...

    def construct(self, x):
        ...
        x = self.matmul(x, self.weight)
        ...
```

在本例中weight矩阵的shape为3 × 272640

```
nn.Dense(targetWidth*targetHeight, 3)
```

根据矩阵乘法的知识  x1\_col和x2\_row必须相等，而在本例中，x1\_col == 817920 and x2\_row == 272640，不满足矩阵乘法要求，从而导致报错。根据Dense中matmul调用的位置关系，x1对应输入图片数据，x2对应self.weight，weight矩阵的shape为3 × 272640\(weight转置后相乘，因为transpose\_b=True\)，因此应该检查输入图片的shape为何为817920。

接下来检查输入数据集的构建方式，通过Image.open\(imgDir\)打开图片，在根据targetWidth、targetHeight和targetChannal筛选样本，筛选后的样本shape为\[targetWidth, targetHeight, targetChannal\]，最后将数据flatten后加入到链表X中。此时发现，数据构建时其实用到了三个维度，width,height和channal，而Dense中的创建权重矩阵只用了两个维度width和height，因此自然不能完成矩阵乘法的运算。

**4. 解决方案**

创建权重矩阵时加上channal维度，

```
net = nn.Dense(targetWidth*targetHeight*targetChannal, 3)
```

