Уменьшение размерности в Python (определение порога дисперсии)

После полудня. У меня проблемы с моим сценарием. В частности, я хотел бы сохранить сингулярные значения и соответствующие им собственные векторы, когда сумма подмножества собственных значений больше, чем 0,9 * сумма всех собственных значений. До сих пор мне удавалось использовать цикл for и функцию добавления, которая создает список кортежей, представляющих сингулярные значения и собственные векторы. Однако, когда я пытаюсь вложить оператор if в цикл for, чтобы выполнить условие, я его нарушаю. вот мой код.

o = np.genfromtxt (r"C:\Users\Python\Desktop\PCADUMMYDATADUMP.csv", delimiter=",")
o_m=np.matrix(o)

#We define the covariance matrix of our data accordingly  This is the mean centered data approx
#of the covariance matrix.  
def covariance_matrix(x):
    #create the mean centered data matrix.  this is the data matrix minus the matrix augmented from the vector that represents the column average
    m_c_d=x-np.repeat(np.mean(x, axis=0,), len(x), axis=0)
    #we compute the matrix operations here
    m_c_c=np.multiply(1/((len(m_c_d)-1)),np.transpose(m_c_d)*m_c_d)
    return m_c_c



#Define the correlation matrix for our mean adjsuted data matrix
def correlation_matrix(x):
    C_M = covariance_matrix(x)
    #matrix operation is diagonal(covariance_matrix)^-1/2*(covaraince_matrix)*diagonal(covariance_matrix)^-1/2
    c_m=fractional_matrix_power(np.diag(np.diag(C_M)),-1/2)*C_M*fractional_matrix_power(np.diag(np.diag(C_M)),-1/2)
    return c_m


def s_v_d(x):
    C_M=covariance_matrix(x)
    #create arrays that hold the left singular vectors(u), the right singular vectors(v), and the singular values (s)
    u,s,v=np.linalg.svd(C_M)
    #not sure if we should keep this here but this is how we can grab the eigenvalues which are the sqares of the singular values
    eigenvalues=np.square(s)

    singular_array=[]
    for i in range(0,len(s)-1):
        if np.sum(singular_array,axis=1) < (.9*np.sum(s)):
            singular_pairs=[s[i],v[:,i]]
            singular_array.append(singular_pairs)
        else:
            break

    return np.sum(s,axis=0)

в частности, рассмотрите цикл for и if после single[array]. Спасибо!


person user7351362    schedule 10.03.2017    source источник


Ответы (1)


Я думаю, что ваш singular_array с его «смешанными» скалярными/векторными элементами немного больше, чем может выдержать np.sum. Я не уверен на 100%, но разве дисперсии не квадраты сингулярных значений? Другими словами, разве вы не должны использовать свое eigenvalues для принятия решения?

Во всяком случае, вот нециклический подход:

part_sums = np.cumsum(eigenvalues)
cutoff = np.searchsorted(part_sums, 0.9 * part_sums[-1])
singular_array = list(zip(s[:cutoff], v[:, :cutoff]))

Измените eigenvalues на s, если считаете, что это более уместно.

Как это работает:

cumsum вычисляет текущую сумму по eigenvalues. Таким образом, его последний элемент является общей суммой, и нам нужно только найти место, где part_sums пересекает 90% этой суммы. Это то, что searchsorted делает для нас.

Когда у нас есть отсечка, все, что остается, — это применить ее к сингулярным значениям и векторам и сформировать пары, используя zip.

person Paul Panzer    schedule 11.03.2017
comment
Спасибо за ответ! - person user7351362; 11.03.2017
comment
@ user7351362 Не за что. Дайте мне знать, работает ли это. - person Paul Panzer; 11.03.2017
comment
Спасибо за ответ! Гах-это? Это своего рода разочарование. Спасибо за предоставление альтернативного метода (отлично работает, мне нужно узнать, как работают функции zip и search. И да, вы правы в том, что квадраты значений singualr являются собственными значениями! Я действительно думал, что передал квадраты значений в s_v_d, но я тупица, ха-ха * хотел отредактировать свой первый ответ как этот, но пропустил пять минут окончания, ха-ха - person user7351362; 11.03.2017
comment
Я немного не уверен в функции сортировки поиска - не могли бы вы объяснить ее и почему вы ее использовали, если у вас есть секунда? - person user7351362; 11.03.2017
comment
@user7351362 user7351362 cumsum в строке перед создает вектор с e0, e0 + e1, e0 + e1 + e2, ... и т. д. Поскольку дисперсии ei положительны, это последовательность, отсортированная вверх. Мы хотим знать, где он пересекает 90% общего числа. Это то, что делает searchsorted. Он принимает второй аргумент, в который мы поместили 90%, и проверяет, по какому индексу он будет соответствовать первому аргументу, чтобы объединенная последовательность все еще была отсортирована. Таким образом, это говорит нам, при каком k e0+e1+....+ek пересекает 90% e0+e1+...+en. - person Paul Panzer; 11.03.2017
comment
о, это довольно мощно. мне определенно нужно добавить его в свой набор инструментов. собираюсь попытаться отследить еще немного документации. Большое спасибо. в качестве последней вещи, не могли бы вы объяснить значимость -1 в аргументе отсортированного поиска? - person user7351362; 11.03.2017
comment
@ user7351362 он просто выбирает последний элемент part_sums, который представляет собой общую сумму e0+e1+...+en - person Paul Panzer; 11.03.2017