JZOJ_1322. 硬币游戏 (Standard IO)

本文介绍了一种硬币游戏,玩家需制定策略以最大化所获硬币价值。游戏涉及动态规划算法,通过递推公式计算最优解,确保在有限硬币堆中取得优势。
Description
  FJ的奶牛喜欢玩硬币游戏,所以FJ发明了一个新的硬币游戏。一开始有N(5<=N<=2,000)个硬币堆成一叠,从上往下数第i个硬币有一个整数值C_i(1<=C_i<=100,000)。
  两个玩家轮流从上倒下取硬币,玩家1先取,可以从上面取1个或2个硬币,下一轮的玩家可以取的硬币数量最少为1个,最多为上一个玩家取的数量的2倍,硬币全部取完比赛结束。
  已知玩家2绝顶聪明,会采用最优策略,现在请你帮助玩家1,使得玩家1取得的硬币值的和最大。
 
Input
  第一行输入N
  第二至N+1行每行输入一个整数C_i
 
Output
  输出玩家1能获得的最大值。
 
Solution

Fi,j,i表示的是我现在的位置(还剩多少枚硬币),取到第几个,j是对方上一次对方拿走了多少个。

下一次对手就可以取走2*j枚硬币,我们设他要拿走k枚硬币,那么k的取值范围就在1<k<=2∗j。

fi,j=max(sumi+1..k−fk,k−i(1<=k<=2∗j))

fi,j+1=max(sumi+1..k−fk,k−i(1<=k<=2*(j+1)))

J就只有在这个地方发生了改变(手指上方S)

(1<=k<=2∗j) 和 (1<=k<=2*(j+1)) 可以变为 2*j<=k<=2*(j+1)

Fi,j=max(Fi,j−1,Sumi+1..k−Fk,k−i(2∗(j−1)<k<=2∗j))

Fi,j;=max(Fi,j-1,Sumi+1..k-Fk,k-i) (2j+1<=k<=2j+2) (Sum为前缀和)

Maxn;=max(Maxn,Sum[k]-Sum[i]-F[k,k-i])

答案即为 (sum[n]+max(num[1]-f[1,1],num[1]+num[2]-f[2,2])) div 2

因为一开始可以选1或者2

复杂度;O(n2) (2算是常数)

 

代码

 

 1 var
 2   n:longint;
 3   a,sum:array [0..2001] of longint;
 4   f:array [0..2001,0..2001] of longint;
 5 procedure init;
 6 var
 7   i:longint;
 8 begin
 9   readln(n);
10   sum[0]:=0;
11   for i:=1 to n do
12     begin
13       readln(a[i]);
14       sum[i]:=sum[i-1]+a[i];
15     end;
16 end;
17 
18 function min(o,p:longint):longint;
19 begin
20   if o<p then exit(o);
21   exit(p);
22 end;
23 
24 function max(o,p:longint):longint;
25 begin
26   if o>p then exit(o);
27   exit(p);
28 end;
29 
30 procedure main;
31 var
32   i,j,k,maxx:longint;
33 begin
34   for i:=n-1 downto 1 do
35     begin
36       maxx:=-maxlongint;
37       for j:=1 to i do
38         begin
39           for k:=min(i+2*j-2,n)+1 to min(i+2*j,n) do
40             maxx:=max(maxx,sum[k]-sum[i]-f[k,k-i]);
41           f[i,j]:=maxx;
42         end;
43     end;
44   writeln((sum[n]+max(a[1]-f[1,1],a[1]+a[2]-f[2,2])) div 2);
45 end;
46 
47 begin
48   init;
49   if n=1 then writeln(a[1])
50          else main;
51 end.

 

 

 

C:\Users\30227\AppData\Local\Programs\Python\Python310\python.exe F:\zhuanli_jianbao\paper\25_11_11\11_15_15\try.py 加载无孔硬币音频: F:\zhuanli_jianbao\paper\25_11_11\11_15_15\normal_audio ✓ 加载成功: AI1-02_20251028112245.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028112309.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028112345.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028112410.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028113347.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028113414.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028113436.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028113501.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028113526.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028113605.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028113635.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028113731.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142053.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142225.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142252.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142314.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142335.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142409.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142431.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142505.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142524.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142544.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142605.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142627.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142646.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142709.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142728.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142748.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142812.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142835.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142856.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142915.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142936.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028142957.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028143019.wav (长度: 0.44s) 加载有孔硬币音频: F:\zhuanli_jianbao\paper\25_11_11\11_15_15\hole_audio ✓ 加载成功: AI1-02_20251028105827.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028105852.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028105938.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110004.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110029.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110055.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110120.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110146.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110212.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110240.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110304.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110328.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110354.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110723.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110752.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110817.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110843.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110905.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110927.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028110952.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028111017.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028111042.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028111105.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028111131.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028111154.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028111706.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028111731.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028111756.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028111818.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028111842.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028111907.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028111932.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028111956.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028112033.wav (长度: 0.44s) ✓ 加载成功: AI1-02_20251028112058.wav (长度: 0.44s) 总计加载: 70个音频文件 采样率: 8000 Hz 提取音频特征... 可视化特征差异... Traceback (most recent call last): File "F:\zhuanli_jianbao\paper\25_11_11\11_15_15\try.py", line 390, in <module> analyze_coin_sounds(SOLID_COIN_FOLDER, HOLE_COIN_FOLDER) File "F:\zhuanli_jianbao\paper\25_11_11\11_15_15\try.py", line 255, in analyze_coin_sounds key_feature_indices = visualize_differences(scaled_features, labels) File "F:\zhuanli_jianbao\paper\25_11_11\11_15_15\try.py", line 118, in visualize_differences plt.boxplot(solid_features.T, positions=np.arange(features.shape[1]) - 0.15, widths=0.3) File "C:\Users\30227\AppData\Local\Programs\Python\Python310\lib\site-packages\matplotlib\_api\deprecation.py", line 453, in wrapper return func(*args, **kwargs) File "C:\Users\30227\AppData\Local\Programs\Python\Python310\lib\site-packages\matplotlib\_api\deprecation.py", line 295, in wrapper return func(*args, **kwargs) File "C:\Users\30227\AppData\Local\Programs\Python\Python310\lib\site-packages\matplotlib\pyplot.py", line 3075, in boxplot return gca().boxplot( File "C:\Users\30227\AppData\Local\Programs\Python\Python310\lib\site-packages\matplotlib\_api\deprecation.py", line 453, in wrapper return func(*args, **kwargs) File "C:\Users\30227\AppData\Local\Programs\Python\Python310\lib\site-packages\matplotlib\__init__.py", line 1521, in inner return func( File "C:\Users\30227\AppData\Local\Programs\Python\Python310\lib\site-packages\matplotlib\_api\deprecation.py", line 295, in wrapper return func(*args, **kwargs) File "C:\Users\30227\AppData\Local\Programs\Python\Python310\lib\site-packages\matplotlib\axes\_axes.py", line 4226, in boxplot artists = self.bxp(bxpstats, positions=positions, widths=widths, File "C:\Users\30227\AppData\Local\Programs\Python\Python310\lib\site-packages\matplotlib\_api\deprecation.py", line 453, in wrapper return func(*args, **kwargs) File "C:\Users\30227\AppData\Local\Programs\Python\Python310\lib\site-packages\matplotlib\axes\_axes.py", line 4479, in bxp raise ValueError(datashape_message.format("positions")) ValueError: List of boxplot statistics and `positions` values must have same the length 进程已结束,退出代码为 1 怎么解决
最新发布
11-12
<think>这个错误是由于在可视化函数 `visualize_differences` 中,使用 `plt.boxplot` ,传入的数据与 `positions` 参数长度不匹配导致的。 具体来说,`plt.boxplot(solid_features.T, positions=np.arange(features.shape[1])-0.15, widths=0.3)` 这行代码中: - `solid_features.T` 的维度是 (特征数, 样本数),即每一行是一个特征的所有样本数据。 - `positions` 参数指定了每个箱线图的位置,其长度应该与 `solid_features.T` 的行数(即特征数)相同。 但是,在错误中提示:`List of boxplot statistics and `positions` values must have same the length`,这意味着 `solid_features.T` 的行数与 `positions` 数组的长度不一致。 从错误信息中可以看出,`features.shape[1]` 是特征的数量(即9个特征),而 `solid_features.T` 的行数应该也是特征数(9行)。所以理论上应该是匹配的。 然而,我们注意到在代码中,`solid_features` 是从 `features` 中根据标签提取的,而 `features` 的维度是 (样本数, 特征数)。因此,`solid_features` 的维度是 (无孔样本数, 特征数)。那么 `solid_features.T` 的维度就是 (特征数, 无孔样本数)。所以行数等于特征数,即9行。 那么为什么会报长度不一致呢?可能的原因是在提取 `solid_features` ,如果某一类样本数为0,那么 `solid_features` 就为空,从而 `solid_features.T` 的行数为0,而 `positions` 的长度为9,导致不一致。 从输出中我们看到,无孔硬币加载了35个,有孔硬币加载了35个,所以每类都有样本,因此不应该出现这种情况。 另一种可能的错误是:在 `visualize_differences` 函数中,我们使用了 `features` 的原始维度(即样本数×特征数)来创建 `solid_features` 和 `hole_features`。但是,在调用 `visualize_differences` 之前,我们对特征进行了标准化(`scaled_features = scaler.fit_transform(features)`),然后传入的是 `scaled_features`,这是一个二维数组,形状为 (70, 9)。然后我们根据标签将其分为两组: solid_features = features[labels == 0] # 形状 (35, 9) hole_features = features[labels == 1] # 形状 (35, 9) 然后,在绘制箱线图,我们分别对这两组数据绘制每个特征的箱线图。我们使用 `solid_features.T` 来将数据转为 (9, 35),这样就有9个特征,每个特征是一个长度为35的数组(即35个样本)。 然后,我们使用 `plt.boxplot` 绘制这9个特征的数据,并指定 `positions` 为0到8(特征索引)减去0.15和加上0.15(以便并排显示)。 所以,问题可能出在 `solid_features` 或 `hole_features` 为空,但我们的数据中每类都有35个样本,所以不应该为空。 另一个可能的问题是:在 `visualize_differences` 函数中,我们使用了 `features` 的原始变量名,但是在函数内部,我们将传入的数组命名为 `features`,但在绘制箱线图,我们使用了: solid_features = features[labels == 0] hole_features = features[labels == 1] 注意:这里的 `features` 实际上是经过标准化的 `scaled_features`,所以没有问题。 但是,我们注意到在绘制箱线图,我们调用了: plt.boxplot(solid_features.T, positions=np.arange(features.shape[1])-0.15, widths=0.3) plt.boxplot(hole_features.T, positions=np.arange(features.shape[1])+0.15, widths=0.3) 这里的 `features.shape[1]` 是特征的数量(9),所以 `positions` 是一个长度为9的数组。 而 `solid_features.T` 有9行,所以应该没有问题。 但是,错误提示长度不一致,所以我们需要检查一下实际运行中 `solid_features.T` 的形状和 `features.shape[1]` 的值。 我们可以添加打印语句来调试: ```python print("solid_features shape:", solid_features.shape) # 应该是 (35,9) print("solid_features.T shape:", solid_features.T.shape) # 应该是 (9,35) print("positions shape:", np.arange(features.shape[1]).shape) # 应该是 (9,) ``` 建议在 `visualize_differences` 函数中加入上述打印语句,以确认形状。 然而,从错误信息来看,问题发生在 `plt.boxplot` 函数中,所以可能是 `plt.boxplot` 对输入数据的要求问题。 另一种可能性:`solid_features` 中可能包含NaN或Inf值?这会导致实际有效的数据行数减少。 因此,我们可以在函数开始检查数据中是否有NaN或Inf。 由于间关系,我们直接修改代码,确保在绘制箱线图,我们传入的数据是有效的,并且长度匹配。 我们也可以尝试将 `solid_features.T` 转换为一个列表,其中每个元素是一个特征的所有样本值(即一个一维数组)。因为 `boxplot` 要求传入一个由多个数据集组成的序列(每个数据集是一个特征的所有样本值)。 另外,注意 `positions` 参数的长度必须与数据集的数量(即特征数)相同。 我们修改一下代码,确保在传入 `boxplot` 之前,每个特征的数据是一个一维数组,并且没有NaN值。 我们可以添加一个检查: ```python # 在visualize_differences函数中,绘制箱线图之前 # 确保没有NaN if np.any(np.isnan(solid_features)) or np.any(np.isinf(solid_features)): print("Warning: solid_features contains NaN or Inf") # 用0替换NaN和Inf solid_features = np.nan_to_num(solid_features) if np.any(np.isnan(hole_features)) or np.any(np.isinf(hole_features)): print("Warning: hole_features contains NaN or Inf") hole_features = np.nan_to_num(hole_features) ``` 同,我们确保传入 `boxplot` 的数据是一个列表,每个元素是一个特征的数据: ```python # 修改为: # 将每个特征的数据提取出来,组成列表 solid_data = [solid_features[:, i] for i in range(solid_features.shape[1])] hole_data = [hole_features[:, i] for i in range(hole_features.shape[1])] # 然后绘制 plt.boxplot(solid_data, positions=np.arange(len(solid_data))-0.15, widths=0.3) plt.boxplot(hole_data, positions=np.arange(len(hole_data))+0.15, widths=0.3) ``` 这样,我们明确地将每个特征的数据作为一个列表传入,并且 `positions` 的长度与 `solid_data` 的长度(特征数)相同。 修改后的 `visualize_differences` 函数中的相关部分如下: ```python def visualize_differences(features, labels): """可视化两类硬币的声音特征差异""" plt.figure(figsize=(15, 10)) # 准备数据 solid_features = features[labels == 0] hole_features = features[labels == 1] feature_names = [ 'Mean Amp', 'Std Dev', 'Zero Crossing', 'Spectral Centroid', 'Spectral Bandwidth', 'Spectral Rolloff', 'MFCC1', 'MFCC2', 'MFCC3' ] # 检查NaN或Inf solid_features = np.nan_to_num(solid_features) hole_features = np.nan_to_num(hole_features) # 将每个特征的数据转换为列表形式 solid_data = [solid_features[:, i] for i in range(solid_features.shape[1])] hole_data = [hole_features[:, i] for i in range(hole_features.shape[1])] # 特征分布对比 plt.subplot(2, 2, 1) # 绘制特征范围线 for i in range(features.shape[1]): plt.plot([i, i], [np.min(features[:, i]), np.max(features[:, i])], 'k--', alpha=0.3) # 绘制箱线图 plt.boxplot(solid_data, positions=np.arange(len(solid_data))-0.15, widths=0.3) plt.boxplot(hole_data, positions=np.arange(len(hole_data))+0.15, widths=0.3) plt.xticks(range(len(feature_names)), feature_names, rotation=45) plt.title('Feature Distribution Comparison') plt.legend(['Range', 'Solid Coins', 'Coins with Holes']) # ... 其余部分保持不变 ... ``` 这样修改后,应该可以解决长度不一致的问题。 另外,注意在绘制箱线图之前,我们使用了 `np.nan_to_num` 来替换NaN和Inf,确保数据清洗。 请尝试使用修改后的代码,并再次运行。如果问题仍然存在,请检查打印的特征数量是否与 `feature_names` 的长度(9)一致。 此外,从您的输出中看到采样率为8000Hz,而之前的模拟数据是44100Hz,所以特征值可能会有所不同,但不会导致这个错误。 请将 `visualize_differences` 函数按照上述修改后再次运行。 </think>这个错误是由于在 `visualize_differences` 函数中,特征数量与位置参数不匹配导致的。让我提供一个修复后的完整代码: ```python import numpy as np import matplotlib.pyplot as plt from scipy import fft import librosa import librosa.display from sklearn.preprocessing import StandardScaler import soundfile as sf import os # 1. 数据加载函数(修复采样率问题) def load_audio_data(solid_folder, hole_folder, max_duration=0.5): sounds = [] labels = [] sample_rates = [] # 收集所有采样率 # 加载无孔硬币音频 print(f"加载无孔硬币音频: {solid_folder}") for filename in os.listdir(solid_folder): if filename.lower().endswith(('.wav', '.mp3', '.flac')): filepath = os.path.join(solid_folder, filename) try: audio, sr = librosa.load(filepath, sr=None, mono=True, duration=max_duration) sounds.append(audio) labels.append(0) sample_rates.append(sr) print(f"✓ 加载成功: {filename} (采样率: {sr} Hz)") except Exception as e: print(f"× 加载失败: {filename} - {str(e)}") # 加载有孔硬币音频 print(f"\n加载有孔硬币音频: {hole_folder}") for filename in os.listdir(hole_folder): if filename.lower().endswith(('.wav', '.mp3', '.flac')): filepath = os.path.join(hole_folder, filename) try: audio, sr = librosa.load(filepath, sr=None, mono=True, duration=max_duration) sounds.append(audio) labels.append(1) sample_rates.append(sr) print(f"✓ 加载成功: {filename} (采样率: {sr} Hz)") except Exception as e: print(f"× 加载失败: {filename} - {str(e)}") # 找出最常见的采样率 sample_rate = max(set(sample_rates), key=sample_rates.count) print(f"\n总计加载: {len(sounds)}个音频文件") print(f"使用采样率: {sample_rate} Hz (最常见的采样率)") # 重新采样所有音频到最常见的采样率 resampled_sounds = [] for i in range(len(sounds)): if sample_rates[i] != sample_rate: audio = librosa.resample(sounds[i], orig_sr=sample_rates[i], target_sr=sample_rate) print(f"重新采样文件 {i}: {sample_rates[i]} -> {sample_rate} Hz") resampled_sounds.append(audio) else: resampled_sounds.append(sounds[i]) return np.array(resampled_sounds), np.array(labels), sample_rate # 2. 特征提取函数(修复异常处理) def extract_features(sounds, sample_rate): features = [] for sound in sounds: # 确保音频长度大于0 if len(sound) == 0: features.append([0]*9) # 使用默认特征值 continue # 域特征 mean = np.mean(sound) std = np.std(sound) zcr = np.sum(librosa.zero_crossings(sound)) # 频域特征 fft_result = np.abs(fft.fft(sound)[:len(sound)//2]) try: spectral_centroid = librosa.feature.spectral_centroid(y=sound, sr=sample_rate)[0, 0] spectral_bandwidth = librosa.feature.spectral_bandwidth(y=sound, sr=sample_rate)[0, 0] spectral_rolloff = librosa.feature.spectral_rolloff(y=sound, sr=sample_rate)[0, 0] except: # 处理计算失败的情况 spectral_centroid = 0 spectral_bandwidth = 0 spectral_rolloff = 0 # MFCC特征 try: mfccs = librosa.feature.mfcc(y=sound, sr=sample_rate, n_mfcc=3) mfcc_mean = np.mean(mfccs, axis=1) except: mfcc_mean = [0, 0, 0] # 组合特征 feature_vec = [ mean, std, zcr, spectral_centroid, spectral_bandwidth, spectral_rolloff, *mfcc_mean ] features.append(feature_vec) return np.array(features) # 3. 修复的可视化函数(解决位置参数问题) def visualize_differences(features, labels): """可视化两类硬币的声音特征差异""" plt.figure(figsize=(15, 10)) # 准备数据 solid_features = features[labels == 0] hole_features = features[labels == 1] # 检查是否有足够的数据 if solid_features.size == 0 or hole_features.size == 0: print("警告:缺少某一类别的数据") return [0, 1, 2] # 返回默认特征索引 feature_names = [ 'Mean Amp', 'Std Dev', 'Zero Crossing', 'Spectral Centroid', 'Spectral Bandwidth', 'Spectral Rolloff', 'MFCC1', 'MFCC2', 'MFCC3' ] num_features = features.shape[1] # 特征分布对比 plt.subplot(2, 2, 1) # 将特征数据转换为适合箱线图的格式 solid_data = [solid_features[:, i] for i in range(num_features)] hole_data = [hole_features[:, i] for i in range(num_features)] # 使用正确的positions参数 positions = np.arange(num_features) plt.boxplot( solid_data, positions=positions - 0.15, widths=0.3, patch_artist=True, boxprops=dict(facecolor='blue', alpha=0.5), showfliers=False ) plt.boxplot( hole_data, positions=positions + 0.15, widths=0.3, patch_artist=True, boxprops=dict(facecolor='red', alpha=0.5), showfliers=False ) plt.xticks(positions, feature_names, rotation=45) plt.title('特征分布对比') plt.legend([plt.Rectangle((0,0),1,1, fc='blue', alpha=0.5), plt.Rectangle((0,0),1,1, fc='red', alpha=0.5)], ['无孔硬币', '有孔硬币']) # 频谱对比 plt.subplot(2, 2, 2) try: solid_avg_spectrum = np.mean(np.abs(fft.fft(solid_features, axis=1)), axis=0)[:solid_features.shape[1]//2] hole_avg_spectrum = np.mean(np.abs(fft.fft(hole_features, axis=1)), axis=0)[:hole_features.shape[1]//2] # 确保频谱长度一致 min_len = min(len(solid_avg_spectrum), len(hole_avg_spectrum)) solid_avg_spectrum = solid_avg_spectrum[:min_len] hole_avg_spectrum = hole_avg_spectrum[:min_len] freqs = np.linspace(0, 8000/2, min_len) # 使用8000Hz作为最大频率 plt.plot(freqs, solid_avg_spectrum, label='无孔硬币') plt.plot(freqs, hole_avg_spectrum, label='有孔硬币') plt.xlabel('频率 (Hz)') plt.ylabel('振幅') plt.title('平均频谱对比') plt.legend() plt.xlim(0, 4000) # 限制到4kHz except Exception as e: print(f"频谱对比失败: {str(e)}") # PCA投影可视化 plt.subplot(2, 2, 3) try: from sklearn.decomposition import PCA pca = PCA(n_components=2) features_2d = pca.fit_transform(features) plt.scatter(features_2d[labels==0, 0], features_2d[labels==0, 1], alpha=0.7, label='无孔硬币') plt.scatter(features_2d[labels==1, 0], features_2d[labels==1, 1], alpha=0.7, label='有孔硬币') plt.xlabel('主成分 1') plt.ylabel('主成分 2') plt.title('特征PCA投影') plt.legend() except Exception as e: print(f"PCA投影失败: {str(e)}") # 关键差异特征 plt.subplot(2, 2, 4) try: # 计算特征差异 feature_diffs = np.abs(np.mean(solid_features, axis=0) - np.mean(hole_features, axis=0)) diff_indices = np.argsort(feature_diffs)[::-1][:3] # 绘制关键特征 for i, idx in enumerate(diff_indices): plt.scatter([i]*len(solid_features), solid_features[:, idx], alpha=0.3, c='blue', label='无孔硬币' if i == 0 else "") plt.scatter([i]*len(hole_features), hole_features[:, idx], alpha=0.3, c='red', label='有孔硬币' if i == 0 else "") plt.text(i, np.max(features[:, idx]), feature_names[idx], ha='center', va='bottom') plt.xticks(range(len(diff_indices)), [feature_names[i] for i in diff_indices]) plt.title('关键差异特征') plt.legend() except Exception as e: print(f"关键特征分析失败: {str(e)}") diff_indices = [0, 1, 2] # 默认值 plt.tight_layout() plt.savefig('coin_sound_differences.png') plt.show() return diff_indices # 4. 河流冲积分类器(保持不变) class EnhancedSedimentClassifier: def __init__(self, feature_ranges, weights=None, tolerance=0.1): self.layers = feature_ranges self.weights = weights self.tolerance = tolerance def _feature_match(self, sample, layer): layer_score = 0 total_weight = 0 for i, (min_val, max_val) in enumerate(layer): # 处理特征值缺失的情况 if i >= len(sample) or np.isnan(sample[i]): continue # 特征值在范围内 if min_val <= sample[i] <= max_val: score = 1.0 # 在容忍边界内 elif (min_val - self.tolerance) <= sample[i] <= (max_val + self.tolerance): distance = min(abs(sample[i] - min_val), abs(sample[i] - max_val)) score = 1.0 - (distance / self.tolerance) else: score = 0.0 # 加权得分 weight = self.weights[i] if self.weights and i < len(self.weights) else 1.0 layer_score += score * weight total_weight += weight return layer_score / total_weight if total_weight > 0 else 0.0 def classify(self, X): results = [] layers = [] confidences = [] for sample in X: best_layer = -1 best_score = 0.0 for layer_idx, layer in enumerate(self.layers): layer_score = self._feature_match(sample, layer) if layer_score > best_score: best_score = layer_score best_layer = layer_idx if layer_score > 0.8: break results.append(0 if best_layer == 0 else 1) layers.append(best_layer) confidences.append(best_score) return np.array(results), np.array(layers), np.array(confidences) # 5. 主流程(修复数据标准化问题) def analyze_coin_sounds(solid_folder, hole_folder): # 1. 加载音频数据 sounds, labels, sample_rate = load_audio_data(solid_folder, hole_folder) print(f"采样率: {sample_rate} Hz") # 2. 提取特征 print("\n提取音频特征...") features = extract_features(sounds, sample_rate) # 3. 标准化特征 scaler = StandardScaler() scaled_features = scaler.fit_transform(features) # 4. 可视化差异 print("可视化特征差异...") key_feature_indices = visualize_differences(scaled_features, labels) print(f"识别出的关键差异特征索引: {key_feature_indices}") # 5. 训练河流冲积分类器 print("\n训练河流冲积分类器...") # 自动生成特征范围(基于标准化后的特征) solid_features = scaled_features[labels == 0] hole_features = scaled_features[labels == 1] # 动态生成特征范围 layer_solid = [] layer_hole = [] layer_fine = [] for i in range(scaled_features.shape[1]): # 计算特征范围 solid_min = np.min(solid_features[:, i]) if solid_features.size > 0 else -1 solid_max = np.max(solid_features[:, i]) if solid_features.size > 0 else 1 hole_min = np.min(hole_features[:, i]) if hole_features.size > 0 else -1 hole_max = np.max(hole_features[:, i]) if hole_features.size > 0 else 1 # 第一层:无孔硬币特征范围 layer_solid.append((solid_min, solid_max)) # 第二层:有孔硬币特征范围 layer_hole.append((hole_min, hole_max)) # 第三层:更宽松的范围 layer_fine.append((min(solid_min, hole_min), max(solid_max, hole_max))) # 创建分类器 classifier = EnhancedSedimentClassifier( feature_ranges=[layer_solid, layer_hole, layer_fine], tolerance=0.3 ) # 进行分类 predictions, layers, confidences = classifier.classify(scaled_features) # 6. 评估结果 accuracy = np.mean(predictions == labels) print(f"\n分类准确率: {accuracy:.2%}") print(f"平均置信度: {np.mean(confidences):.2f}") # 7. 可视化分类结果 plt.figure(figsize=(14, 6)) # 置信度分布 plt.subplot(1, 2, 1) plt.hist(confidences[labels==0], alpha=0.5, bins=20, label='无孔硬币') plt.hist(confidences[labels==1], alpha=0.5, bins=20, label='有孔硬币') plt.xlabel('置信度得分') plt.ylabel('样本数量') plt.title('分类置信度分布') plt.legend() # 层级分布 plt.subplot(1, 2, 2) solid_layers = layers[labels==0] hole_layers = layers[labels==1] plt.hist(solid_layers, alpha=0.5, bins=range(4), align='left', rwidth=0.8, label='无孔硬币') plt.hist(hole_layers, alpha=0.5, bins=range(4), align='left', rwidth=0.8, label='有孔硬币') plt.xticks([0, 1, 2], ['层1(无孔)', '层2(有孔)', '层3(精细)']) plt.xlabel('沉淀层级') plt.ylabel('样本数量') plt.title('样本沉淀层级分布') plt.legend() plt.tight_layout() plt.savefig('coin_classification_results.png') plt.show() return accuracy, confidences, layers # 6. 修复后的使用方法 if __name__ == "__main__": # 设置您的文件夹路径 SOLID_COIN_FOLDER = "F:/zhuanli_jianbao/paper/25_11_11/11_15_15/normal_audio" HOLE_COIN_FOLDER = "F:/zhuanli_jianbao/paper/25_11_11/11_15_15/hole_audio" # 确保安装了所需库: pip install numpy matplotlib scipy librosa soundfile try: analyze_coin_sounds(SOLID_COIN_FOLDER, HOLE_COIN_FOLDER) except Exception as e: print(f"程序运行出错: {str(e)}") import traceback traceback.print_exc() ``` ### 问题修复说明: 1. **采样率问题修复**: ```python # 收集所有采样率 sample_rates = [] # ... # 找出最常见的采样率 sample_rate = max(set(sample_rates), key=sample_rates.count) # 重新采样所有音频到最常见的采样率 ``` 您的音频采样率为8000Hz,而原始代码默认44100Hz,现在会自适应采样率 2. **特征提取异常处理**: ```python # 确保音频长度大于0 if len(sound) == 0: features.append([0]*9) # ... try: spectral_centroid = librosa.feature.spectral_centroid(y=sound, sr=sample_rate)[0, 0]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值