├── .gitignore ├── README.md ├── example └── example.ipynb ├── presentation ├── Презентация-less-memes.pdf └── Презентация.pdf ├── setup.py ├── voice2vec ├── __init__.py ├── data │ ├── __init__.py │ ├── spectograms.py │ └── voices_data.py └── neural │ ├── __init__.py │ └── model.py └── web ├── app.py └── templates └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .ipynb_checkpoints/ 3 | */__pycache__/ 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SpeechLock 2 | ## Преобразование голоса ввектор 3 | [![Code Climate](https://codeclimate.com/github/xenx/speech/badges/gpa.svg)](https://codeclimate.com/github/xenx/speech) 4 | [![Code Health](https://landscape.io/github/xenx/speech/master/landscape.svg?style=flat)](https://landscape.io/github/xenx/speech/master) 5 | [![GoTo](https://img.shields.io/badge/GoTo-project-4bb89b.svg)](https://github.com/goto-ru) 6 | [![MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) 7 | 8 | 9 | Cases: 10 | 11 | 1. Персонализация голосовых интерфейсов. 12 | 2. Разбивание аудио дорожки и поиск голосов на ней + кластерезация этих голосов. 13 | 3. Вытаскивание признаков из голоса. 14 | 15 | Исследование: 16 | 17 | 1. Возможность построения карты голосов 18 | 2. Попроверять разные теории на голосах + Cases[3] 19 | -------------------------------------------------------------------------------- /example/example.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Данные. Загрузка.\n", 8 | "\n", 9 | "Данные скачать можно [тут](https://drive.google.com/file/d/0BzeJJkS7RDPHa3pIdzUySnpORWs/view?usp=sharing)" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": { 16 | "collapsed": false 17 | }, 18 | "outputs": [], 19 | "source": [ 20 | "from data_utils.data import Users" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 2, 26 | "metadata": { 27 | "collapsed": false 28 | }, 29 | "outputs": [], 30 | "source": [ 31 | "# Загрузим данные\n", 32 | "data = Users()" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "Возьмём Train выборку" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 3, 45 | "metadata": { 46 | "collapsed": false 47 | }, 48 | "outputs": [], 49 | "source": [ 50 | "train = data.get_train()" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "Посмотрим на звук" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": 4, 63 | "metadata": { 64 | "collapsed": true 65 | }, 66 | "outputs": [], 67 | "source": [ 68 | "import matplotlib.pyplot as plt\n", 69 | "%matplotlib inline" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": 5, 75 | "metadata": { 76 | "collapsed": false 77 | }, 78 | "outputs": [ 79 | { 80 | "data": { 81 | "text/plain": [ 82 | "" 83 | ] 84 | }, 85 | "execution_count": 5, 86 | "metadata": {}, 87 | "output_type": "execute_result" 88 | }, 89 | { 90 | "data": { 91 | "image/png": "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\nG2ywwQavEf4fhK/hQeFAoOQAAAAASUVORK5CYII=\n", 92 | "text/plain": [ 93 | "" 94 | ] 95 | }, 96 | "metadata": {}, 97 | "output_type": "display_data" 98 | } 99 | ], 100 | "source": [ 101 | "plt.imshow(train[0][1].T)" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "Загрузим модель обучения" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 6, 114 | "metadata": { 115 | "collapsed": true 116 | }, 117 | "outputs": [], 118 | "source": [ 119 | "from neural.model import NeuralNetwork" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": 7, 125 | "metadata": { 126 | "collapsed": true 127 | }, 128 | "outputs": [], 129 | "source": [ 130 | "# Загрузим модель\n", 131 | "network = NeuralNetwork()" 132 | ] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "metadata": { 137 | "collapsed": true 138 | }, 139 | "source": [ 140 | "Обучим нашу модель" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 8, 146 | "metadata": { 147 | "collapsed": false 148 | }, 149 | "outputs": [ 150 | { 151 | "data": { 152 | "text/plain": [ 153 | "[array(0.0)]" 154 | ] 155 | }, 156 | "execution_count": 8, 157 | "metadata": {}, 158 | "output_type": "execute_result" 159 | } 160 | ], 161 | "source": [ 162 | "network.train(train)" 163 | ] 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "metadata": {}, 168 | "source": [ 169 | "Для каждого слова предскажем его вектор" 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": 9, 175 | "metadata": { 176 | "collapsed": false 177 | }, 178 | "outputs": [], 179 | "source": [ 180 | "vectors = []\n", 181 | "\n", 182 | "for user in data.base.keys():\n", 183 | " for word in data.base[user].keys():\n", 184 | " voice = data[user][word]\n", 185 | " a = voice.copy()\n", 186 | " a.resize(100,20)\n", 187 | " vectors.append(network.predict([[a]])[0][0])" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "Попробуем отобразить все вектора" 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "execution_count": 10, 200 | "metadata": { 201 | "collapsed": false 202 | }, 203 | "outputs": [], 204 | "source": [ 205 | "x = []\n", 206 | "y = []\n", 207 | "\n", 208 | "for a in train:\n", 209 | " x.append(a[0])\n", 210 | " y.append(a[1])" 211 | ] 212 | }, 213 | { 214 | "cell_type": "code", 215 | "execution_count": null, 216 | "metadata": { 217 | "collapsed": true 218 | }, 219 | "outputs": [], 220 | "source": [] 221 | } 222 | ], 223 | "metadata": { 224 | "kernelspec": { 225 | "display_name": "Python 3", 226 | "language": "python", 227 | "name": "python3" 228 | }, 229 | "language_info": { 230 | "codemirror_mode": { 231 | "name": "ipython", 232 | "version": 3 233 | }, 234 | "file_extension": ".py", 235 | "mimetype": "text/x-python", 236 | "name": "python", 237 | "nbconvert_exporter": "python", 238 | "pygments_lexer": "ipython3", 239 | "version": "3.5.2" 240 | } 241 | }, 242 | "nbformat": 4, 243 | "nbformat_minor": 0 244 | } 245 | -------------------------------------------------------------------------------- /presentation/Презентация-less-memes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voice2vec/SpeechLock/5e7b8f98232390babee6b5bb0ec448bb341aa577/presentation/Презентация-less-memes.pdf -------------------------------------------------------------------------------- /presentation/Презентация.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voice2vec/SpeechLock/5e7b8f98232390babee6b5bb0ec448bb341aa577/presentation/Презентация.pdf -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | setup( 4 | name='voice2vec', 5 | version='0.0.1', 6 | description='Voice to vector. Voice similarity', 7 | license='MIT', 8 | url='https://github.com/xenx/speech', 9 | 10 | install_requires=['flask', 'numpy', 'librosa', 'theano', 'lasagne', 'dill'], 11 | 12 | package=find_packages(exclude=['web']), 13 | ) 14 | -------------------------------------------------------------------------------- /voice2vec/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voice2vec/SpeechLock/5e7b8f98232390babee6b5bb0ec448bb341aa577/voice2vec/__init__.py -------------------------------------------------------------------------------- /voice2vec/data/__init__.py: -------------------------------------------------------------------------------- 1 | from .spectograms import get_spectrogram 2 | from .voices_data import VoicesData 3 | -------------------------------------------------------------------------------- /voice2vec/data/spectograms.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from librosa import load, logamplitude 3 | from librosa.feature import melspectrogram 4 | 5 | 6 | def get_spectrogram(path): 7 | """Строим спектограмму из wav файла""" 8 | y, sr = load(path) 9 | S = melspectrogram(y, sr=sr, n_mels=100) 10 | log_S = logamplitude(S, ref_power=np.max) 11 | return log_S 12 | -------------------------------------------------------------------------------- /voice2vec/data/voices_data.py: -------------------------------------------------------------------------------- 1 | import dill 2 | import numpy as np 3 | from numpy.random import choice 4 | 5 | from voice2vec.data.spectograms import get_spectrogram 6 | 7 | 8 | class VoicesData: 9 | def __init__(self, path='users.dl'): 10 | # Путь до dill модели 11 | self.path = path 12 | # Defaultdict информации 13 | self.base = dill.load(open(self.path, 'rb')) 14 | 15 | def __getitem__(self, item): 16 | return self.base[item] 17 | 18 | def save(self): 19 | """Поскольку это не стандартная DB, тут нужна функция сохранения""" 20 | dill.dump(self.base, open(self.path, 'wb')) 21 | 22 | def get_train(self, shape=(100, 20)): 23 | """Делаем из данных train выборку""" 24 | train = [] 25 | for key in self.base.keys(): 26 | if len(self.base[key]) >= 2: 27 | for _ in range(0, len(self.base[key]), 2): 28 | values = choice(list(self.base[key]), 2) 29 | 30 | a = np.asarray(self.base[key][values[0]]) 31 | b = np.asarray(self.base[key][values[1]]) 32 | 33 | other = choice(list(self.base), 1)[0] 34 | c = np.asarray(self.base[other][choice(list(self.base[other]), 1)[0]]) 35 | 36 | other_value = c.copy() 37 | value_first = a.copy() 38 | value_second = b.copy() 39 | 40 | other_value.resize(shape) 41 | value_first.resize(shape) 42 | value_second.resize(shape) 43 | 44 | train.append((value_first, other_value, value_second)) 45 | 46 | return train 47 | 48 | def add_wav(self, user, word): 49 | """Сохраняем спектограму для пользователя""" 50 | self.base[user][word] = get_spectrogram('/tmp/voice2vec-data-add_wav-tempfile.wav') 51 | 52 | def get_train_for_user(self, user, shape=(100, 20)): 53 | """Трейн данные для одного пользователя""" 54 | train = [] 55 | if len(self.base[user]) >= 2: 56 | for _ in range(0, len(self.base[user]), 2): 57 | values = choice(list(self.base[user]), 2) 58 | 59 | a = np.asarray(self.base[user][values[0]]) 60 | b = np.asarray(self.base[user][values[1]]) 61 | 62 | other = choice(list(self.base), 1) 63 | c = np.asarray(self.base[other][choice(list(self.base[other]), 1)[0]]) 64 | 65 | value_first = a.copy() 66 | value_second = b.copy() 67 | other_value = c.copy() 68 | 69 | other_value.resize(shape) 70 | value_first.resize(shape) 71 | value_second.resize(shape) 72 | 73 | train.append((value_first, other_value, value_second)) 74 | else: 75 | raise ValueError 76 | -------------------------------------------------------------------------------- /voice2vec/neural/__init__.py: -------------------------------------------------------------------------------- 1 | from .model import NeuralNetwork, Speech2VecLayer, BaseNeuralNetwork 2 | -------------------------------------------------------------------------------- /voice2vec/neural/model.py: -------------------------------------------------------------------------------- 1 | import theano 2 | import theano.tensor as T 3 | 4 | from lasagne.layers import InputLayer, DenseLayer, ReshapeLayer, Conv1DLayer, MaxPool1DLayer, GlobalPoolLayer, \ 5 | get_output, get_all_params, get_all_param_values, set_all_param_values 6 | 7 | from lasagne.nonlinearities import very_leaky_rectify, tanh 8 | 9 | from lasagne.updates import adagrad 10 | 11 | from lasagne.layers import Layer 12 | 13 | 14 | class Speech2VecLayer(Layer): 15 | def __init__(self, incoming, sound_shape, num_units, **kwargs): 16 | """ 17 | :param incoming: the layer feeding into this layer, or the expected input shape. 18 | :param sound_shape: shape of freq x time 19 | :param num_units: output vector dimension 20 | """ 21 | 22 | super().__init__(incoming, **kwargs) 23 | 24 | input_reshape = ReshapeLayer(incoming, (-1,) + sound_shape) # Сворачиваем все записи друг за другом 25 | convolution = Conv1DLayer(input_reshape, num_filters=100, filter_size=5, nonlinearity=very_leaky_rectify) 26 | pooling = MaxPool1DLayer(convolution, 2) 27 | global_pooling = GlobalPoolLayer(pooling) 28 | dense = DenseLayer(global_pooling, num_units=300) 29 | output_dense = DenseLayer(dense, num_units=num_units, nonlinearity=tanh, name='output') 30 | all_vectors_output = ReshapeLayer(output_dense, (-1, 3, num_units)) 31 | 32 | self.layers = (input_reshape, convolution, pooling, global_pooling, dense, output_dense, all_vectors_output) 33 | 34 | self.get_output_for = all_vectors_output.get_output_for 35 | self.get_output_shape_for = all_vectors_output.get_output_shape_for 36 | self.get_params = all_vectors_output.get_params 37 | 38 | 39 | class BaseNeuralNetwork: 40 | def __init__(self, sound_shape, num_units, main_layer_class, loss_func, updates_func): 41 | # входной тензор (кол-во батчей, кол-во записей, время, частота) 42 | input_X = T.tensor4("X") 43 | 44 | # сеть 45 | input_layer = InputLayer(shape=(None, 3) + sound_shape, input_var=input_X.swapaxes(2, 3)) 46 | all_output = main_layer_class(input_layer, sound_shape, num_units) # for loss 47 | vector_output = ReshapeLayer(all_output, (-1, 1, num_units)) # for use 48 | 49 | # предсказание нейронки 50 | all_predicted = get_output(all_output) # for loss 51 | vector_predicted = get_output(vector_output) # for use 52 | 53 | # функция ошибки 54 | loss = loss_func(all_predicted) 55 | 56 | # посчитать обновлённые веса с шагом по градиенту 57 | trainable_weights = get_all_params(all_output, trainable=True) 58 | updates_sgd = updates_func(loss, trainable_weights) 59 | 60 | # функция, которая обучает сеть на 1 шаг и возвращащет значение функции потерь 61 | self.fit = theano.function([input_X], loss, updates=updates_sgd) 62 | 63 | # функция, которая возвращает вектор голоса 64 | self.predict = theano.function([input_X], vector_predicted) 65 | 66 | self.all_output = all_output 67 | self.vector_output = vector_output 68 | self.all_predicted = all_predicted 69 | self.vector_predicted = vector_predicted 70 | 71 | def get_params(self, **tags): 72 | return get_all_params(self.all_output, **tags) 73 | 74 | def get_params_values(self, **tags): 75 | return get_all_param_values(self.all_output, **tags) 76 | 77 | def set_params_values(self, values, **tags): 78 | set_all_param_values(self.all_output, values, **tags) 79 | 80 | 81 | class NeuralNetwork(BaseNeuralNetwork): 82 | def __init__(self, num_units=2): 83 | """ 84 | :param num_units: output vector dimension 85 | """ 86 | 87 | def loss_func(all_predicted): 88 | def distance_sq(x1, x2): 89 | return T.sum(T.sqr(x1 - x2)) 90 | 91 | d1 = distance_sq(all_predicted[:, 0], all_predicted[:, 1]) 92 | d2 = distance_sq(all_predicted[:, 0], all_predicted[:, 2]) 93 | alpha = 1e-2 94 | 95 | return T.maximum(d1 + alpha, 0) - T.maximum(d2 + alpha, 0) 96 | 97 | super().__init__( 98 | sound_shape=(20, 100), 99 | num_units=num_units, 100 | main_layer_class=Speech2VecLayer, 101 | loss_func=loss_func, 102 | updates_func=lambda loss, weights: adagrad(loss, weights, learning_rate=0.001) 103 | ) 104 | -------------------------------------------------------------------------------- /web/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | 3 | from voice2vec.neural import NeuralNetwork 4 | from voice2vec.data import VoicesData 5 | 6 | # Загрузим модель 7 | our_network = NeuralNetwork() 8 | 9 | # Загрузим данные 10 | data = VoicesData() 11 | 12 | # Обучимся 13 | our_network.fit(data.get_train()) 14 | 15 | vectors_x = [] 16 | vectors_y = [] 17 | names = [] 18 | labels = [] 19 | for user in data.base.keys(): 20 | names.append(user) 21 | x, y = [], [] 22 | label = [] 23 | for word in data.base[user].keys(): 24 | label.append(word) 25 | voice = data[user][word] 26 | a = voice.copy() 27 | a.resize(100, 20) 28 | 29 | predicted = our_network.predict([[a]])[0][0] 30 | 31 | x.append(predicted[0]) 32 | y.append(predicted[1]) 33 | 34 | labels.append(label) 35 | 36 | vectors_x.append(x) 37 | vectors_y.append(y) 38 | 39 | new_data = '[' 40 | 41 | for i in range(len(names)): 42 | new_data += 'l' + str(i) +',' 43 | 44 | new_data += ']' 45 | 46 | app = Flask(__name__) 47 | 48 | 49 | @app.route("/") 50 | def main(): 51 | return render_template('index.html', vectors_x=vectors_x, 52 | vectors_y=vectors_y, names=names, labels=labels, 53 | data=new_data) 54 | 55 | 56 | if __name__ == "__main__": 57 | app.run() 58 | -------------------------------------------------------------------------------- /web/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 34 | --------------------------------------------------------------------------------