基于CNN的狗叫,猫叫语音分类

基于CNN的狗叫,猫叫语音分类

基于CNN的狗叫,猫叫语音分类

最近开始北漂的实习生活,第一家实习单位还是挺不错的。说句题外话,北京的生活没有想象中的那么恐怖,没有想象中的那么累,反而挺有人情味的。

公司里的主要业务是做“声纹识别”的,现在项目组好像主要分为传统的机器学习以及深度学习两个模块在做。刚接触到是一个唤醒的智能AI产品,为了尽快的熟悉这一模块的知识,所以找了个练手的项目。

这个分类很简单,就是单纯的让模型去识别是狗叫声还是猫叫声,只要使用python现成的库将音频的特征提取出来,然后使用卷积网络进行训练就可以了。这里比较头痛的是数据的获取,没有找到合适的,只能是写个脚本现爬(我真牛逼,哈哈)!!

import urllib

from bs4 import BeautifulSoup

def download(url, save_path):

urllib.urlretrieve(url, save_path)

dog_links = [

"http://sc.chinaz.com/tag_yinxiao/GouJiao.html",

"http://sc.chinaz.com/tag_yinxiao/GouJiao_2.html",

"http://sc.chinaz.com/tag_yinxiao/GouJiao_3.html",

"http://sc.chinaz.com/tag_yinxiao/GouJiao_4.html"

]

cat_links = [

"http://sc.chinaz.com/tag_yinxiao/MaoJiao.html",

"http://sc.chinaz.com/tag_yinxiao/MaoJiao_2.html",

"http://sc.chinaz.com/tag_yinxiao/MaoJiao_3.html",

]

count = 10

for link, type in cat_links:

response = urllib.urlopen(link)

content = response.read().decode('utf-8')

# print(content)

soup = BeautifulSoup(content)

divs = soup.findAll("div", class_="music_block")

for div in divs:

a = div.find_all("a")[1]["href"]

content = urllib.urlopen(a).read().decode('utf-8')

audio = BeautifulSoup(content).findAll("div", class_="dian")[1].find("a")["href"]

count += 1

download(audio, "./data/cat/cat"+str(count)+".wav")

大概下下有100多个素材吧,考虑到素材不是很多的原因。所以我们需要将比较长的音频切分成小段的,这样数据量就会增加(这一步是很重要的,数据量直接影响最后的结果)

然后就是提取切分数据集,提取特征(mfcc),最后使用卷积网络来训练。这里并不是对音频的源文件进行卷积,而是在mfcc特征上进行提取之后进行的,好像音频里面有很多特征,比图像里多很多,这里还需要以后进一步学习,不过好在python库都为我们写好了。直接上代码:

from pydub import AudioSegment

import os

import numpy as np

import scipy.io.wavfile as wav

from python_speech_features import mfcc

import pickle

import random

AUDIO_LEN = 400

MFCC_LEN = 13

def create_data():

item_len = 2000

base_path = "./all/"

for file in os.listdir(base_path):

real_path = base_path + file

audio = AudioSegment.from_file(real_path)

audio_len = len(audio)

steps = audio_len // item_len

for step in range(max(1, steps)):

item_audio = audio[step * item_len: (step + 1) * item_len]

save_audio = item_audio + AudioSegment.silent(item_len - len(item_audio))

save_audio.export("./data/" + str(step) + file, format="wav")

# create_data()

# exit()

def split_train_test():

base_dir = "./data/"

dogs = []

cats = []

for file in os.listdir(base_dir):

real_file = base_dir + file

if "cat" in file:

cats.append(real_file)

else:

dogs.append(real_file)

test = dogs[:10] + cats[:10]

train = dogs[10:] + cats[10:]

random.shuffle(train)

random.shuffle(test)

pickle.dump(train, open("./train", "wb"))

pickle.dump(test, open("./test", "wb"))

train_data = pickle.load(open("train", "rb"))

test_data = pickle.load(open("test", "rb"))

def get_train_or_test(type, batch_size = 30):

x = []

y = []

data = train_data if type == "train" else test_data

if type == "test":

batch_size = 10

all_dogs = [item for item in data if "dog" in item]

all_cats = [item for item in data if "cat" in item]

sample_dogs = random.sample(all_dogs, int(batch_size / 2))

sample_cats = random.sample(all_cats, batch_size - int(batch_size / 2))

sample = sample_dogs + sample_cats

random.shuffle(sample)

for item in sample:

try:

fs, audio = wav.read(item)

processed_audio = mfcc(audio, samplerate=fs)

x_hold = np.zeros(shape=(AUDIO_LEN, MFCC_LEN))

x_hold[:len(processed_audio), :] = processed_audio

x.append(x_hold)

if type == "train":

reverse = []

for data in x_hold:

list(data).reverse()

reverse.append(data)

x.append(reverse)

y.append([1, 0] if "cat" in item else [0, 1])

y.append([1, 0] if "cat" in item else [0, 1])

except:

print("error")

pass

x = np.array(x) / 100

x = np.array(x)

y = np.array(y)

return x, y

这一块主要是训练前的预操作,包括对数据切分,划分训练集,测试集,还有提取特征。

import tensorflow as tf

import update_audio

AUDIO_LEN = update_audio.AUDIO_LEN

MFCC_LEN = update_audio.MFCC_LEN

x = tf.placeholder(shape=(None, AUDIO_LEN, MFCC_LEN), dtype=tf.float32)

x_change = tf.expand_dims(x, -1)

y = tf.placeholder(shape=(None, 2), dtype=tf.int32)

def create_model():

print("input shape", x_change.shape)

filter1 = tf.Variable(tf.random_normal([10, 3, 1, 64]))

bias1 = tf.Variable(tf.random_normal([64]))

conv_1 = tf.nn.conv2d(x_change, filter1, strides=[1, 1, 1, 1], padding="SAME") + bias1

print("conv_1 shape", conv_1.shape)

relu1 = tf.nn.relu(conv_1)

dropout1 = tf.nn.dropout(relu1, 0.5)

max_pool1 = tf.nn.max_pool(dropout1, [1, 2, 2, 1], [1, 2, 2, 1], 'SAME')

print("max pool shape", max_pool1.shape)

flatten = tf.layers.flatten(max_pool1)

print("flatten shape", flatten.shape)

net_work = tf.layers.dense(flatten, units=128, activation=tf.nn.relu)

logit = tf.layers.dense(net_work, units=2, activation=tf.nn.softmax)

print("logit shape", logit.shape)

return logit

logit = create_model()

def build_loss():

loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=logit))

return loss

loss = build_loss()

def create_opt():

opt = tf.train.GradientDescentOptimizer(0.0001).minimize(loss)

return opt

opt = create_opt()

correct_prediction = tf.equal(tf.argmax(logit,1), tf.argmax(y,1))

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

saver = tf.train.Saver()

with tf.Session() as sess:

sess.run(tf.global_variables_initializer())

saver.restore(sess, "./model/model.model")

feed_test_x, feed_test_y = update_audio.get_train_or_test("test")

feed_test = {x: feed_test_x, y: feed_test_y}

for index in range(10000):

feed_x, feed_y = update_audio.get_train_or_test("train")

feed = {x: feed_x, y: feed_y}

get_loss, _ = sess.run([loss, opt], feed_dict=feed)

if index % 100 == 0:

get_acc = sess.run(accuracy, feed_dict=feed_test)

print(get_loss, get_acc)

saver.save(sess, "./model/model.model")

模型的主题模块,主要使用卷积网络对特征进行卷积,这里的特征并不是特别复杂,数据量也不是特别大,所以使用一层卷积就可以了,最后输出分类结果。

我最后得到的结果是损失0.31 准确率将近0.8(20个里面错3 - 4 个),如果后续需要改进的话可以继续对数据特征进行一些提取,或者扩大训练量,效果应该还会有提升!

相关发现

正在阅读:DNF数据芯片怎么刷 DNF数据芯片哪里爆的多DNF数据芯片怎么刷 DNF数据芯片哪里爆的多
什么软件可以设计格子
bst365app

什么软件可以设计格子

🌼 07-27 🌻 8561
全新乐斗赛季来临!符文大乱斗、狂野激斗、双人竞技场升级回归~
夕阳下草原上吃草的牛群
365是正规平台吗

夕阳下草原上吃草的牛群

🌼 08-15 🌻 2879