Diffusers
Safetensors
File size: 12,803 Bytes
278bf35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
import torch
import numpy as np


def analyze_single_tensor(tensor, name="tensor"):
    """详细分析单个tensor的各种属性"""
    print(f"\n{'=' * 60}")
    print(f"分析: {name}")
    print(f"{'=' * 60}")

    # 基本属性
    print(f"形状: {tensor.shape}")
    print(f"数据类型: {tensor.dtype}")
    print(f"设备: {tensor.device}")
    print(f"总元素数: {tensor.numel()}")
    print(f"存储大小: {tensor.element_size() * tensor.numel() / 1024:.2f} KB")
    print(f"是否需要梯度: {tensor.requires_grad}")

    # 检查是否为视图或连续
    print(f"是否连续: {tensor.is_contiguous()}")
    if hasattr(tensor, 'storage_offset'):
        print(f"存储偏移: {tensor.storage_offset()}")

    # NaN和Inf分析
    nan_mask = torch.isnan(tensor)
    inf_mask = torch.isinf(tensor)
    nan_count = nan_mask.sum().item()
    inf_count = inf_mask.sum().item()
    total_count = tensor.numel()

    print(f"NaN数量: {nan_count}/{total_count} ({nan_count / total_count * 100:.2f}%)")
    print(f"Inf数量: {inf_count}/{total_count} ({inf_count / total_count * 100:.2f}%)")

    # 有效值分析
    valid_mask = ~nan_mask & ~inf_mask
    valid_count = valid_mask.sum().item()

    if valid_count > 0:
        valid_values = tensor[valid_mask]
        print(f"有效值数量: {valid_count}/{total_count} ({valid_count / total_count * 100:.2f}%)")
        print(f"有效值范围: [{valid_values.min().item():.10f}, {valid_values.max().item():.10f}]")
        print(f"有效值均值: {valid_values.mean().item():.10f}")
        print(f"有效值标准差: {valid_values.std().item():.10f}")
        print(f"有效值中位数: {valid_values.median().item():.10f}")

        # 分位数分析 - 修复类型问题
        if valid_count >= 5:
            # 确保使用浮点类型计算分位数
            if not valid_values.is_floating_point():
                valid_values_float = valid_values.float()
                print(f"⚠️ 转换为浮点类型计算分位数: {valid_values.dtype} -> {valid_values_float.dtype}")
            else:
                valid_values_float = valid_values

            # 确保分位数张量在正确设备上
            quantile_tensor = torch.tensor([0.1, 0.25, 0.5, 0.75, 0.9],
                                           device=valid_values_float.device,
                                           dtype=valid_values_float.dtype)

            try:
                quantiles = torch.quantile(valid_values_float, quantile_tensor)
                print(f"有效值分位数:")
                print(f"  10%: {quantiles[0].item():.10f}")
                print(f"  25%: {quantiles[1].item():.10f}")
                print(f"  50%: {quantiles[2].item():.10f}")
                print(f"  75%: {quantiles[3].item():.10f}")
                print(f"  90%: {quantiles[4].item():.10f}")
            except Exception as e:
                print(f"❌ 分位数计算失败: {e}")
    else:
        print("⚠️ 没有有效值!")

    # NaN分布分析
    if nan_count > 0:
        print("\nNaN分布分析:")
        # 检查每个维度的NaN分布
        if tensor.dim() > 0:
            for dim in range(tensor.dim()):
                nan_along_dim = nan_mask.sum(dim=dim)
                if nan_along_dim.dim() > 0:
                    unique_counts = torch.unique(nan_along_dim)
                    print(f"  维度{dim}: {unique_counts.tolist()}")

        # 找出NaN的位置模式
        nan_indices = torch.nonzero(nan_mask)
        if len(nan_indices) > 0:
            print(f"前5个NaN位置:")
            for i in range(min(5, len(nan_indices))):
                print(f"  位置 {nan_indices[i].tolist()}")

    # Inf分布分析
    if inf_count > 0:
        print("\nInf分布分析:")
        inf_indices = torch.nonzero(inf_mask)
        if len(inf_indices) > 0:
            print(f"前5个Inf位置:")
            for i in range(min(5, len(inf_indices))):
                idx = inf_indices[i]
                value = tensor[tuple(idx)]
                print(f"  位置 {idx.tolist()}: {value.item()}")

    # 零值分析
    zero_mask = tensor == 0
    zero_count = zero_mask.sum().item()
    print(f"零值数量: {zero_count}/{total_count} ({zero_count / total_count * 100:.2f}%)")

    # 极端值分析
    if valid_count > 0:
        abs_values = torch.abs(valid_values)
        large_values = abs_values > 1e6
        large_count = large_values.sum().item()
        small_values = abs_values < 1e-6
        small_count = small_values.sum().item()

        print(f"绝对值>1e6的数量: {large_count}/{valid_count} ({large_count / valid_count * 100:.2f}%)")
        print(f"绝对值<1e-6的数量: {small_count}/{valid_count} ({small_count / valid_count * 100:.2f}%)")

    # 内存布局分析
    print(f"\n内存布局:")
    print(f"步长: {tensor.stride()}")
    print(f"数据指针: {tensor.data_ptr()}")

    return {
        'shape': tensor.shape,
        'dtype': tensor.dtype,
        'device': tensor.device,
        'nan_count': nan_count,
        'inf_count': inf_count,
        'valid_count': valid_count,
        'zero_count': zero_count,
    }


def compare_tensors(tensor1, tensor2, name="tensor"):
    """比较两个tensor的详细差异"""
    print(f"\n{'=' * 60}")
    print(f"比较: {name}")
    print(f"{'=' * 60}")

    # 基本属性比较
    print(f"形状: {tensor1.shape} vs {tensor2.shape}")
    print(f"数据类型: {tensor1.dtype} vs {tensor2.dtype}")
    print(f"设备: {tensor1.device} vs {tensor2.device}")

    # 检查形状是否匹配
    if tensor1.shape != tensor2.shape:
        print("❌ 形状不匹配!")
        return False

    # 数值比较
    diff = torch.abs(tensor1 - tensor2)
    max_diff = torch.max(diff).item()
    mean_diff = torch.mean(diff).item()

    print(f"最大绝对差异: {max_diff:.10f}")
    print(f"平均绝对差异: {mean_diff:.10f}")

    # 检查是否完全相同
    if torch.equal(tensor1, tensor2):
        print("✅ 两个tensor完全相同")
        return True
    else:
        print("❌ tensor存在差异")

        # 检查差异的分布
        zero_diff_mask = diff == 0
        zero_count = zero_diff_mask.sum().item()
        total_count = tensor1.numel()
        print(f"相同元素比例: {zero_count}/{total_count} ({zero_count / total_count * 100:.2f}%)")

        # 找出差异最大的位置
        if max_diff > 0:
            max_diff_idx = torch.argmax(diff)
            max_diff_idx_tuple = np.unravel_index(max_diff_idx.cpu().numpy(), tensor1.shape)
            print(f"最大差异位置: {max_diff_idx_tuple}")
            print(
                f"该位置值: {tensor1.flatten()[max_diff_idx].item():.10f} vs {tensor2.flatten()[max_diff_idx].item():.10f}")

        # 检查NaN和Inf
        nan_mask1 = torch.isnan(tensor1)
        nan_mask2 = torch.isnan(tensor2)
        inf_mask1 = torch.isinf(tensor1)
        inf_mask2 = torch.isinf(tensor2)

        print(f"tensor1 NaN数量: {nan_mask1.sum().item()}")
        print(f"tensor2 NaN数量: {nan_mask2.sum().item()}")
        print(f"tensor1 Inf数量: {inf_mask1.sum().item()}")
        print(f"tensor2 Inf数量: {inf_mask2.sum().item()}")

        # 检查NaN位置是否一致
        if nan_mask1.any() or nan_mask2.any():
            nan_positions_match = torch.equal(nan_mask1, nan_mask2)
            print(f"NaN位置是否一致: {nan_positions_match}")
            if not nan_positions_match:
                # 找出不一致的NaN位置
                nan_mismatch = (nan_mask1 != nan_mask2)
                mismatch_count = nan_mismatch.sum().item()
                print(f"NaN位置不一致数量: {mismatch_count}")

        return False


def detailed_nan_analysis(tensor, name="tensor"):
    """详细分析tensor中的NaN分布"""
    print(f"\n--- {name} NaN分析 ---")

    nan_mask = torch.isnan(tensor)
    nan_count = nan_mask.sum().item()
    total_count = tensor.numel()

    if nan_count == 0:
        print("✅ 没有NaN值")
        return

    print(f"NaN数量: {nan_count}/{total_count} ({nan_count / total_count * 100:.2f}%)")

    # 分析NaN的分布模式
    if tensor.dim() > 0:
        # 检查每个维度的NaN分布
        print("各维度的NaN分布:")
        for dim in range(tensor.dim()):
            nan_along_dim = nan_mask.sum(dim=dim)
            if nan_along_dim.dim() > 0:
                unique_counts = torch.unique(nan_along_dim)
                print(f"  维度{dim}: {unique_counts.tolist()}")

    # 检查有效值的统计
    valid_values = tensor[~nan_mask]
    if len(valid_values) > 0:
        print(f"有效值范围: [{valid_values.min().item():.6f}, {valid_values.max().item():.6f}]")
        print(f"有效值均值: {valid_values.mean().item():.6f}")
        print(f"有效值标准差: {valid_values.std().item():.6f}")


def compare_value_ranges(tensor1, tensor2, name="tensor"):
    """比较两个tensor的数值范围"""
    print(f"\n--- {name} 数值范围比较 ---")

    # 排除NaN后的统计
    tensor1_valid = tensor1[~torch.isnan(tensor1)]
    tensor2_valid = tensor2[~torch.isnan(tensor2)]

    if len(tensor1_valid) > 0 and len(tensor2_valid) > 0:
        print(f"tensor1范围: [{tensor1_valid.min().item():.10f}, {tensor1_valid.max().item():.10f}]")
        print(f"tensor2范围: [{tensor2_valid.min().item():.10f}, {tensor2_valid.max().item():.10f}]")
        print(f"tensor1均值: {tensor1_valid.mean().item():.10f}")
        print(f"tensor2均值: {tensor2_valid.mean().item():.10f}")
    else:
        print("⚠️ 无法计算有效值的统计(可能全是NaN)")


# 加载tensor
print("加载tensor文件...")
latent1 = torch.load('latents1-5.pth')  # 有病
latent2 = torch.load('latents1-2.pth')  # 没病
sampled_points1 = torch.load('sampled_points1-5.pth')
sampled_points2 = torch.load('sampled_points1-2.pth')
tensor1 = torch.load('tensor1-5.pth')
tensor2 = torch.load('tensor1-2.pth')

# =========================================
before_scheduler_latents = torch.load("before_scheduler_latents1-8.pth")
prepare_latents = torch.load("prepare_latents1-8.pth")
scheduler_latents = torch.load("scheduler_latents1-8.pth")
noise = torch.load("noise_pred1-8.pth")

before_scheduler_latents2 = torch.load("before_scheduler_latents1-9.pth")
prepare_latents2 = torch.load("prepare_latents1-9.pth")
scheduler_latents2 = torch.load("scheduler_latents1-9.pth")
noise2 = torch.load("noise_pred1-9.pth")
# 1-7 和 1-8 都是最后sdf为正数的failure case,但是他们结果完全相同。

print("✅ 所有tensor加载完成")

# 首先单独分析每个tensor
print("\n" + "=" * 80)
print("单独分析每个tensor")
print("=" * 80)

print('Flash Attention',torch.backends.cuda.sdp_kernel)

# analyze_single_tensor(latent1, "latent1 (有病)")
# analyze_single_tensor(latent2, "latent2 (没病)")
# analyze_single_tensor(sampled_points1, "sampled_points1")
# analyze_single_tensor(sampled_points2, "sampled_points2")
# analyze_single_tensor(tensor1, "tensor1 (有病)")
# analyze_single_tensor(tensor2, "tensor2 (没病)")
analyze_single_tensor(before_scheduler_latents, "before_scheduler")
analyze_single_tensor(prepare_latents, "prepare")
analyze_single_tensor(scheduler_latents, "scheduler")
analyze_single_tensor(noise, "noise")

compare_tensors(before_scheduler_latents, before_scheduler_latents2, "(COMPARE)before_scheduler")
compare_tensors(prepare_latents, prepare_latents2, "(COMPARE)prepare_latents")
compare_tensors(scheduler_latents, scheduler_latents2, "(COMPARE)scheduler")
compare_tensors(noise, noise2, "(COMPARE)noise")


# # 然后进行比较分析
# print("\n" + "=" * 80)
# print("比较分析")
# print("=" * 80)
#
# # 比较latents
# compare_tensors(latent1, latent2, "latents")
# detailed_nan_analysis(latent1, "latent1 (有病)")
# detailed_nan_analysis(latent2, "latent2 (没病)")
# compare_value_ranges(latent1, latent2, "latents")
#
# # 比较sampled_points
# compare_tensors(sampled_points1, sampled_points2, "sampled_points")
# detailed_nan_analysis(sampled_points1, "sampled_points1")
# detailed_nan_analysis(sampled_points2, "sampled_points2")
# compare_value_ranges(sampled_points1, sampled_points2, "sampled_points")
#
# # 比较输出tensor
# compare_tensors(tensor1, tensor2, "output tensor")
# detailed_nan_analysis(tensor1, "tensor1 (有病)")
# detailed_nan_analysis(tensor2, "tensor2 (没病)")
# compare_value_ranges(tensor1, tensor2, "output tensor")